@probelabs/probe 0.6.0-rc199 → 0.6.0-rc200

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/cjs/index.cjs CHANGED
@@ -34621,6 +34621,323 @@ var init_zod = __esm({
34621
34621
  }
34622
34622
  });
34623
34623
 
34624
+ // src/tools/edit.js
34625
+ function isPathAllowed(filePath, allowedFolders) {
34626
+ if (!allowedFolders || allowedFolders.length === 0) {
34627
+ const resolvedPath3 = (0, import_path5.resolve)(filePath);
34628
+ const cwd = (0, import_path5.resolve)(process.cwd());
34629
+ return resolvedPath3 === cwd || resolvedPath3.startsWith(cwd + import_path5.sep);
34630
+ }
34631
+ const resolvedPath2 = (0, import_path5.resolve)(filePath);
34632
+ return allowedFolders.some((folder) => {
34633
+ const allowedPath = (0, import_path5.resolve)(folder);
34634
+ return resolvedPath2 === allowedPath || resolvedPath2.startsWith(allowedPath + import_path5.sep);
34635
+ });
34636
+ }
34637
+ function parseFileToolOptions(options = {}) {
34638
+ return {
34639
+ debug: options.debug || false,
34640
+ allowedFolders: options.allowedFolders || [],
34641
+ cwd: options.cwd
34642
+ };
34643
+ }
34644
+ var import_ai, import_fs4, import_path5, import_fs5, editTool, createTool, editSchema, createSchema, editDescription, createDescription, editToolDefinition, createToolDefinition;
34645
+ var init_edit = __esm({
34646
+ "src/tools/edit.js"() {
34647
+ "use strict";
34648
+ import_ai = require("ai");
34649
+ import_fs4 = require("fs");
34650
+ import_path5 = require("path");
34651
+ import_fs5 = require("fs");
34652
+ editTool = (options = {}) => {
34653
+ const { debug, allowedFolders, cwd } = parseFileToolOptions(options);
34654
+ return (0, import_ai.tool)({
34655
+ name: "edit",
34656
+ description: `Edit files using exact string replacement (Claude Code style).
34657
+
34658
+ This tool performs exact string replacements in files. It requires the old_string to match exactly what's in the file, including all whitespace and indentation.
34659
+
34660
+ Parameters:
34661
+ - file_path: Path to the file to edit (absolute or relative)
34662
+ - old_string: Exact text to find and replace (must be unique in the file unless replace_all is true)
34663
+ - new_string: Text to replace with
34664
+ - replace_all: (optional) Replace all occurrences instead of requiring uniqueness
34665
+
34666
+ Important:
34667
+ - The old_string must match EXACTLY including whitespace
34668
+ - If old_string appears multiple times and replace_all is false, the edit will fail
34669
+ - Use larger context around the string to ensure uniqueness when needed`,
34670
+ inputSchema: {
34671
+ type: "object",
34672
+ properties: {
34673
+ file_path: {
34674
+ type: "string",
34675
+ description: "Path to the file to edit"
34676
+ },
34677
+ old_string: {
34678
+ type: "string",
34679
+ description: "Exact text to find and replace"
34680
+ },
34681
+ new_string: {
34682
+ type: "string",
34683
+ description: "Text to replace with"
34684
+ },
34685
+ replace_all: {
34686
+ type: "boolean",
34687
+ description: "Replace all occurrences (default: false)",
34688
+ default: false
34689
+ }
34690
+ },
34691
+ required: ["file_path", "old_string", "new_string"]
34692
+ },
34693
+ execute: async ({ file_path, old_string, new_string, replace_all = false }) => {
34694
+ try {
34695
+ if (!file_path || typeof file_path !== "string" || file_path.trim() === "") {
34696
+ return `Error editing file: Invalid file_path - must be a non-empty string`;
34697
+ }
34698
+ if (old_string === void 0 || old_string === null || typeof old_string !== "string") {
34699
+ return `Error editing file: Invalid old_string - must be a string`;
34700
+ }
34701
+ if (new_string === void 0 || new_string === null || typeof new_string !== "string") {
34702
+ return `Error editing file: Invalid new_string - must be a string`;
34703
+ }
34704
+ const resolvedPath2 = (0, import_path5.isAbsolute)(file_path) ? file_path : (0, import_path5.resolve)(cwd || process.cwd(), file_path);
34705
+ if (debug) {
34706
+ console.error(`[Edit] Attempting to edit file: ${resolvedPath2}`);
34707
+ }
34708
+ if (!isPathAllowed(resolvedPath2, allowedFolders)) {
34709
+ return `Error editing file: Permission denied - ${file_path} is outside allowed directories`;
34710
+ }
34711
+ if (!(0, import_fs5.existsSync)(resolvedPath2)) {
34712
+ return `Error editing file: File not found - ${file_path}`;
34713
+ }
34714
+ const content = await import_fs4.promises.readFile(resolvedPath2, "utf-8");
34715
+ if (!content.includes(old_string)) {
34716
+ return `Error editing file: String not found - the specified old_string was not found in ${file_path}`;
34717
+ }
34718
+ const occurrences = content.split(old_string).length - 1;
34719
+ if (!replace_all && occurrences > 1) {
34720
+ return `Error editing file: Multiple occurrences found - the old_string appears ${occurrences} times. Use replace_all: true to replace all occurrences, or provide more context to make the string unique.`;
34721
+ }
34722
+ let newContent;
34723
+ if (replace_all) {
34724
+ newContent = content.replaceAll(old_string, new_string);
34725
+ } else {
34726
+ newContent = content.replace(old_string, new_string);
34727
+ }
34728
+ if (newContent === content) {
34729
+ return `Error editing file: No changes made - old_string and new_string might be the same`;
34730
+ }
34731
+ await import_fs4.promises.writeFile(resolvedPath2, newContent, "utf-8");
34732
+ const replacedCount = replace_all ? occurrences : 1;
34733
+ if (debug) {
34734
+ console.error(`[Edit] Successfully edited ${resolvedPath2}, replaced ${replacedCount} occurrence(s)`);
34735
+ }
34736
+ return `Successfully edited ${file_path} (${replacedCount} replacement${replacedCount !== 1 ? "s" : ""})`;
34737
+ } catch (error2) {
34738
+ console.error("[Edit] Error:", error2);
34739
+ return `Error editing file: ${error2.message}`;
34740
+ }
34741
+ }
34742
+ });
34743
+ };
34744
+ createTool = (options = {}) => {
34745
+ const { debug, allowedFolders, cwd } = parseFileToolOptions(options);
34746
+ return (0, import_ai.tool)({
34747
+ name: "create",
34748
+ description: `Create new files with specified content.
34749
+
34750
+ This tool creates new files in the filesystem. It will create parent directories if they don't exist.
34751
+
34752
+ Parameters:
34753
+ - file_path: Path where the file should be created (absolute or relative)
34754
+ - content: Content to write to the file
34755
+ - overwrite: (optional) Whether to overwrite if file exists (default: false)
34756
+
34757
+ Important:
34758
+ - By default, will fail if the file already exists
34759
+ - Set overwrite: true to replace existing files
34760
+ - Parent directories will be created automatically if needed`,
34761
+ inputSchema: {
34762
+ type: "object",
34763
+ properties: {
34764
+ file_path: {
34765
+ type: "string",
34766
+ description: "Path where the file should be created"
34767
+ },
34768
+ content: {
34769
+ type: "string",
34770
+ description: "Content to write to the file"
34771
+ },
34772
+ overwrite: {
34773
+ type: "boolean",
34774
+ description: "Overwrite if file exists (default: false)",
34775
+ default: false
34776
+ }
34777
+ },
34778
+ required: ["file_path", "content"]
34779
+ },
34780
+ execute: async ({ file_path, content, overwrite = false }) => {
34781
+ try {
34782
+ if (!file_path || typeof file_path !== "string" || file_path.trim() === "") {
34783
+ return `Error creating file: Invalid file_path - must be a non-empty string`;
34784
+ }
34785
+ if (content === void 0 || content === null || typeof content !== "string") {
34786
+ return `Error creating file: Invalid content - must be a string`;
34787
+ }
34788
+ const resolvedPath2 = (0, import_path5.isAbsolute)(file_path) ? file_path : (0, import_path5.resolve)(cwd || process.cwd(), file_path);
34789
+ if (debug) {
34790
+ console.error(`[Create] Attempting to create file: ${resolvedPath2}`);
34791
+ }
34792
+ if (!isPathAllowed(resolvedPath2, allowedFolders)) {
34793
+ return `Error creating file: Permission denied - ${file_path} is outside allowed directories`;
34794
+ }
34795
+ if ((0, import_fs5.existsSync)(resolvedPath2) && !overwrite) {
34796
+ return `Error creating file: File already exists - ${file_path}. Use overwrite: true to replace it.`;
34797
+ }
34798
+ const dir = (0, import_path5.dirname)(resolvedPath2);
34799
+ await import_fs4.promises.mkdir(dir, { recursive: true });
34800
+ await import_fs4.promises.writeFile(resolvedPath2, content, "utf-8");
34801
+ const action = (0, import_fs5.existsSync)(resolvedPath2) && overwrite ? "overwrote" : "created";
34802
+ const bytes = Buffer.byteLength(content, "utf-8");
34803
+ if (debug) {
34804
+ console.error(`[Create] Successfully ${action} ${resolvedPath2}`);
34805
+ }
34806
+ return `Successfully ${action} ${file_path} (${bytes} bytes)`;
34807
+ } catch (error2) {
34808
+ console.error("[Create] Error:", error2);
34809
+ return `Error creating file: ${error2.message}`;
34810
+ }
34811
+ }
34812
+ });
34813
+ };
34814
+ editSchema = {
34815
+ type: "object",
34816
+ properties: {
34817
+ file_path: {
34818
+ type: "string",
34819
+ description: "Path to the file to edit"
34820
+ },
34821
+ old_string: {
34822
+ type: "string",
34823
+ description: "Exact text to find and replace"
34824
+ },
34825
+ new_string: {
34826
+ type: "string",
34827
+ description: "Text to replace with"
34828
+ },
34829
+ replace_all: {
34830
+ type: "boolean",
34831
+ description: "Replace all occurrences (default: false)"
34832
+ }
34833
+ },
34834
+ required: ["file_path", "old_string", "new_string"]
34835
+ };
34836
+ createSchema = {
34837
+ type: "object",
34838
+ properties: {
34839
+ file_path: {
34840
+ type: "string",
34841
+ description: "Path where the file should be created"
34842
+ },
34843
+ content: {
34844
+ type: "string",
34845
+ description: "Content to write to the file"
34846
+ },
34847
+ overwrite: {
34848
+ type: "boolean",
34849
+ description: "Overwrite if file exists (default: false)"
34850
+ }
34851
+ },
34852
+ required: ["file_path", "content"]
34853
+ };
34854
+ editDescription = "Edit files using exact string replacement. Requires exact match including whitespace.";
34855
+ createDescription = "Create new files with specified content. Will create parent directories if needed.";
34856
+ editToolDefinition = `
34857
+ ## edit
34858
+ Description: ${editDescription}
34859
+
34860
+ When to use:
34861
+ - For precise, surgical edits to existing files
34862
+ - When you need to change specific lines or blocks of code
34863
+ - For renaming functions, variables, or updating configuration values
34864
+ - When the exact text to replace is known and unique (or use replace_all for multiple occurrences)
34865
+
34866
+ When NOT to use:
34867
+ - For creating new files (use 'create' tool instead)
34868
+ - When you cannot determine the exact text to replace
34869
+ - When changes span multiple locations that would be better handled together
34870
+
34871
+ Parameters:
34872
+ - file_path: (required) Path to the file to edit
34873
+ - old_string: (required) Exact text to find and replace (must match including whitespace, newlines, and indentation)
34874
+ - new_string: (required) Text to replace with
34875
+ - replace_all: (optional, default: false) Replace all occurrences if the string appears multiple times
34876
+
34877
+ Important notes:
34878
+ - The old_string MUST match EXACTLY, including all whitespace, indentation, and line breaks
34879
+ - If old_string appears multiple times and replace_all is false, the tool will fail
34880
+ - Always verify the exact formatting of the text you want to replace
34881
+
34882
+ Examples:
34883
+ <edit>
34884
+ <file_path>src/main.js</file_path>
34885
+ <old_string>function oldName() {
34886
+ return 42;
34887
+ }</old_string>
34888
+ <new_string>function newName() {
34889
+ return 42;
34890
+ }</new_string>
34891
+ </edit>
34892
+
34893
+ <edit>
34894
+ <file_path>config.json</file_path>
34895
+ <old_string>"debug": false</old_string>
34896
+ <new_string>"debug": true</new_string>
34897
+ <replace_all>true</replace_all>
34898
+ </edit>`;
34899
+ createToolDefinition = `
34900
+ ## create
34901
+ Description: ${createDescription}
34902
+
34903
+ When to use:
34904
+ - For creating brand new files from scratch
34905
+ - When you need to add configuration files, documentation, or new modules
34906
+ - For generating boilerplate code or templates
34907
+ - When you have the complete content ready to write
34908
+
34909
+ When NOT to use:
34910
+ - For editing existing files (use 'edit' tool instead)
34911
+ - When a file already exists unless you explicitly want to overwrite it
34912
+
34913
+ Parameters:
34914
+ - file_path: (required) Path where the file should be created
34915
+ - content: (required) Complete content to write to the file
34916
+ - overwrite: (optional, default: false) Whether to overwrite if file already exists
34917
+
34918
+ Important notes:
34919
+ - Parent directories will be created automatically if they don't exist
34920
+ - The tool will fail if the file already exists and overwrite is false
34921
+ - Be careful with the overwrite option as it completely replaces existing files
34922
+
34923
+ Examples:
34924
+ <create>
34925
+ <file_path>src/newFile.js</file_path>
34926
+ <content>export function hello() {
34927
+ return "Hello, world!";
34928
+ }</content>
34929
+ </create>
34930
+
34931
+ <create>
34932
+ <file_path>README.md</file_path>
34933
+ <content># My Project
34934
+
34935
+ This is a new project.</content>
34936
+ <overwrite>true</overwrite>
34937
+ </create>`;
34938
+ }
34939
+ });
34940
+
34624
34941
  // src/tools/common.js
34625
34942
  function buildToolTagPattern(tools2 = DEFAULT_VALID_TOOLS) {
34626
34943
  const allTools = [...tools2];
@@ -34637,7 +34954,9 @@ function getValidParamsForTool(toolName) {
34637
34954
  extract: extractSchema,
34638
34955
  delegate: delegateSchema,
34639
34956
  bash: bashSchema,
34640
- attempt_completion: attemptCompletionSchema
34957
+ attempt_completion: attemptCompletionSchema,
34958
+ edit: editSchema,
34959
+ create: createSchema
34641
34960
  };
34642
34961
  const schema = schemaMap[toolName];
34643
34962
  if (!schema) {
@@ -34646,9 +34965,12 @@ function getValidParamsForTool(toolName) {
34646
34965
  if (toolName === "attempt_completion") {
34647
34966
  return ["result"];
34648
34967
  }
34649
- if (schema && schema._def && schema._def.shape) {
34968
+ if (schema._def && schema._def.shape) {
34650
34969
  return Object.keys(schema._def.shape());
34651
34970
  }
34971
+ if (schema.properties) {
34972
+ return Object.keys(schema.properties);
34973
+ }
34652
34974
  return [];
34653
34975
  }
34654
34976
  function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
@@ -34748,10 +35070,10 @@ function parseAndResolvePaths(pathStr, cwd) {
34748
35070
  if (!pathStr) return [];
34749
35071
  const paths = pathStr.split(",").map((p4) => p4.trim()).filter((p4) => p4.length > 0);
34750
35072
  return paths.map((p4) => {
34751
- if ((0, import_path5.isAbsolute)(p4)) {
35073
+ if ((0, import_path6.isAbsolute)(p4)) {
34752
35074
  return p4;
34753
35075
  }
34754
- return cwd ? (0, import_path5.resolve)(cwd, p4) : p4;
35076
+ return cwd ? (0, import_path6.resolve)(cwd, p4) : p4;
34755
35077
  });
34756
35078
  }
34757
35079
  function resolveTargetPath(target, cwd) {
@@ -34769,17 +35091,18 @@ function resolveTargetPath(target, cwd) {
34769
35091
  filePart = target;
34770
35092
  suffix = "";
34771
35093
  }
34772
- if (!(0, import_path5.isAbsolute)(filePart) && cwd) {
34773
- filePart = (0, import_path5.resolve)(cwd, filePart);
35094
+ if (!(0, import_path6.isAbsolute)(filePart) && cwd) {
35095
+ filePart = (0, import_path6.resolve)(cwd, filePart);
34774
35096
  }
34775
35097
  return filePart + suffix;
34776
35098
  }
34777
- var import_path5, searchSchema, querySchema, extractSchema, delegateSchema, bashSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, bashToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, DEFAULT_VALID_TOOLS;
35099
+ var import_path6, searchSchema, querySchema, extractSchema, delegateSchema, bashSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, bashToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, DEFAULT_VALID_TOOLS;
34778
35100
  var init_common2 = __esm({
34779
35101
  "src/tools/common.js"() {
34780
35102
  "use strict";
34781
35103
  init_zod();
34782
- import_path5 = require("path");
35104
+ import_path6 = require("path");
35105
+ init_edit();
34783
35106
  searchSchema = external_exports.object({
34784
35107
  query: external_exports.string().describe("Search query with Elasticsearch syntax. Use quotes for exact matches, AND/OR for boolean logic, - for negation."),
34785
35108
  path: external_exports.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.')
@@ -36187,7 +36510,7 @@ var init_escape = __esm({
36187
36510
  });
36188
36511
 
36189
36512
  // node_modules/minimatch/dist/esm/index.js
36190
- var import_brace_expansion, minimatch, starDotExtRE, starDotExtTest, starDotExtTestDot, starDotExtTestNocase, starDotExtTestNocaseDot, starDotStarRE, starDotStarTest, starDotStarTestDot, dotStarRE, dotStarTest, starRE, starTest, starTestDot, qmarksRE, qmarksTestNocase, qmarksTestNocaseDot, qmarksTestDot, qmarksTest, qmarksTestNoExt, qmarksTestNoExtDot, defaultPlatform, path5, sep, GLOBSTAR, qmark2, star2, twoStarDot, twoStarNoDot, filter, ext, defaults, braceExpand, makeRe, match, globMagic, regExpEscape2, Minimatch;
36513
+ var import_brace_expansion, minimatch, starDotExtRE, starDotExtTest, starDotExtTestDot, starDotExtTestNocase, starDotExtTestNocaseDot, starDotStarRE, starDotStarTest, starDotStarTestDot, dotStarRE, dotStarTest, starRE, starTest, starTestDot, qmarksRE, qmarksTestNocase, qmarksTestNocaseDot, qmarksTestDot, qmarksTest, qmarksTestNoExt, qmarksTestNoExtDot, defaultPlatform, path5, sep2, GLOBSTAR, qmark2, star2, twoStarDot, twoStarNoDot, filter, ext, defaults, braceExpand, makeRe, match, globMagic, regExpEscape2, Minimatch;
36191
36514
  var init_esm = __esm({
36192
36515
  "node_modules/minimatch/dist/esm/index.js"() {
36193
36516
  import_brace_expansion = __toESM(require_brace_expansion(), 1);
@@ -36260,8 +36583,8 @@ var init_esm = __esm({
36260
36583
  win32: { sep: "\\" },
36261
36584
  posix: { sep: "/" }
36262
36585
  };
36263
- sep = defaultPlatform === "win32" ? path5.win32.sep : path5.posix.sep;
36264
- minimatch.sep = sep;
36586
+ sep2 = defaultPlatform === "win32" ? path5.win32.sep : path5.posix.sep;
36587
+ minimatch.sep = sep2;
36265
36588
  GLOBSTAR = Symbol("globstar **");
36266
36589
  minimatch.GLOBSTAR = GLOBSTAR;
36267
36590
  qmark2 = "[^/]";
@@ -39175,22 +39498,22 @@ var init_esm3 = __esm({
39175
39498
  });
39176
39499
 
39177
39500
  // node_modules/path-scurry/dist/esm/index.js
39178
- var import_node_path, import_node_url, import_fs4, actualFS, import_promises, realpathSync, defaultFS, fsFromOption, uncDriveRegexp, uncToDrive, eitherSep, UNKNOWN, IFIFO, IFCHR, IFDIR, IFBLK, IFREG, IFLNK, IFSOCK, IFMT, IFMT_UNKNOWN, READDIR_CALLED, LSTAT_CALLED, ENOTDIR, ENOENT, ENOREADLINK, ENOREALPATH, ENOCHILD, TYPEMASK, entToType, normalizeCache, normalize, normalizeNocaseCache, normalizeNocase, ResolveCache, ChildrenCache, setAsCwd, PathBase, PathWin32, PathPosix, PathScurryBase, PathScurryWin32, PathScurryPosix, PathScurryDarwin, Path, PathScurry;
39501
+ var import_node_path, import_node_url, import_fs6, actualFS, import_promises, realpathSync, defaultFS, fsFromOption, uncDriveRegexp, uncToDrive, eitherSep, UNKNOWN, IFIFO, IFCHR, IFDIR, IFBLK, IFREG, IFLNK, IFSOCK, IFMT, IFMT_UNKNOWN, READDIR_CALLED, LSTAT_CALLED, ENOTDIR, ENOENT, ENOREADLINK, ENOREALPATH, ENOCHILD, TYPEMASK, entToType, normalizeCache, normalize, normalizeNocaseCache, normalizeNocase, ResolveCache, ChildrenCache, setAsCwd, PathBase, PathWin32, PathPosix, PathScurryBase, PathScurryWin32, PathScurryPosix, PathScurryDarwin, Path, PathScurry;
39179
39502
  var init_esm4 = __esm({
39180
39503
  "node_modules/path-scurry/dist/esm/index.js"() {
39181
39504
  init_esm2();
39182
39505
  import_node_path = require("node:path");
39183
39506
  import_node_url = require("node:url");
39184
- import_fs4 = require("fs");
39507
+ import_fs6 = require("fs");
39185
39508
  actualFS = __toESM(require("node:fs"), 1);
39186
39509
  import_promises = require("node:fs/promises");
39187
39510
  init_esm3();
39188
- realpathSync = import_fs4.realpathSync.native;
39511
+ realpathSync = import_fs6.realpathSync.native;
39189
39512
  defaultFS = {
39190
- lstatSync: import_fs4.lstatSync,
39191
- readdir: import_fs4.readdir,
39192
- readdirSync: import_fs4.readdirSync,
39193
- readlinkSync: import_fs4.readlinkSync,
39513
+ lstatSync: import_fs6.lstatSync,
39514
+ readdir: import_fs6.readdir,
39515
+ readdirSync: import_fs6.readdirSync,
39516
+ readlinkSync: import_fs6.readlinkSync,
39194
39517
  realpathSync,
39195
39518
  promises: {
39196
39519
  lstat: import_promises.lstat,
@@ -42099,7 +42422,7 @@ function createWrappedTools(baseTools) {
42099
42422
  }
42100
42423
  return wrappedTools;
42101
42424
  }
42102
- var import_child_process6, import_util11, import_crypto3, import_events, import_fs5, import_fs6, import_path6, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
42425
+ var import_child_process6, import_util11, import_crypto3, import_events, import_fs7, import_fs8, import_path7, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
42103
42426
  var init_probeTool = __esm({
42104
42427
  "src/agent/probeTool.js"() {
42105
42428
  "use strict";
@@ -42108,9 +42431,9 @@ var init_probeTool = __esm({
42108
42431
  import_util11 = require("util");
42109
42432
  import_crypto3 = require("crypto");
42110
42433
  import_events = require("events");
42111
- import_fs5 = __toESM(require("fs"), 1);
42112
- import_fs6 = require("fs");
42113
- import_path6 = __toESM(require("path"), 1);
42434
+ import_fs7 = __toESM(require("fs"), 1);
42435
+ import_fs8 = require("fs");
42436
+ import_path7 = __toESM(require("path"), 1);
42114
42437
  init_esm5();
42115
42438
  init_symlink_utils();
42116
42439
  toolCallEmitter = new import_events.EventEmitter();
@@ -42199,17 +42522,17 @@ var init_probeTool = __esm({
42199
42522
  execute: async (params) => {
42200
42523
  const { directory = ".", workingDirectory } = params;
42201
42524
  const baseCwd = workingDirectory || process.cwd();
42202
- const secureBaseDir = import_path6.default.resolve(baseCwd);
42525
+ const secureBaseDir = import_path7.default.resolve(baseCwd);
42203
42526
  const isDependencyPath = directory.startsWith("/dep/") || directory.startsWith("go:") || directory.startsWith("js:") || directory.startsWith("rust:");
42204
42527
  let targetDir;
42205
- if (import_path6.default.isAbsolute(directory)) {
42206
- targetDir = import_path6.default.resolve(directory);
42207
- if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path6.default.sep) && targetDir !== secureBaseDir) {
42528
+ if (import_path7.default.isAbsolute(directory)) {
42529
+ targetDir = import_path7.default.resolve(directory);
42530
+ if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path7.default.sep) && targetDir !== secureBaseDir) {
42208
42531
  throw new Error(`Path traversal attempt detected. Cannot access directory outside workspace: ${directory}`);
42209
42532
  }
42210
42533
  } else {
42211
- targetDir = import_path6.default.resolve(secureBaseDir, directory);
42212
- if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path6.default.sep) && targetDir !== secureBaseDir) {
42534
+ targetDir = import_path7.default.resolve(secureBaseDir, directory);
42535
+ if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path7.default.sep) && targetDir !== secureBaseDir) {
42213
42536
  throw new Error(`Path traversal attempt detected. Access denied: ${directory}`);
42214
42537
  }
42215
42538
  }
@@ -42218,7 +42541,7 @@ var init_probeTool = __esm({
42218
42541
  console.log(`[DEBUG] Listing files in directory: ${targetDir}`);
42219
42542
  }
42220
42543
  try {
42221
- const files = await import_fs6.promises.readdir(targetDir, { withFileTypes: true });
42544
+ const files = await import_fs8.promises.readdir(targetDir, { withFileTypes: true });
42222
42545
  const formatSize = (size) => {
42223
42546
  if (size < 1024) return `${size}B`;
42224
42547
  if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)}K`;
@@ -42226,7 +42549,7 @@ var init_probeTool = __esm({
42226
42549
  return `${(size / (1024 * 1024 * 1024)).toFixed(1)}G`;
42227
42550
  };
42228
42551
  const entries = await Promise.all(files.map(async (file) => {
42229
- const fullPath = import_path6.default.join(targetDir, file.name);
42552
+ const fullPath = import_path7.default.join(targetDir, file.name);
42230
42553
  const entryType = await getEntryType(file, fullPath);
42231
42554
  return {
42232
42555
  name: file.name,
@@ -42263,17 +42586,17 @@ var init_probeTool = __esm({
42263
42586
  throw new Error("Pattern is required for file search");
42264
42587
  }
42265
42588
  const baseCwd = workingDirectory || process.cwd();
42266
- const secureBaseDir = import_path6.default.resolve(baseCwd);
42589
+ const secureBaseDir = import_path7.default.resolve(baseCwd);
42267
42590
  const isDependencyPath = directory.startsWith("/dep/") || directory.startsWith("go:") || directory.startsWith("js:") || directory.startsWith("rust:");
42268
42591
  let targetDir;
42269
- if (import_path6.default.isAbsolute(directory)) {
42270
- targetDir = import_path6.default.resolve(directory);
42271
- if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path6.default.sep) && targetDir !== secureBaseDir) {
42592
+ if (import_path7.default.isAbsolute(directory)) {
42593
+ targetDir = import_path7.default.resolve(directory);
42594
+ if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path7.default.sep) && targetDir !== secureBaseDir) {
42272
42595
  throw new Error(`Path traversal attempt detected. Cannot access directory outside workspace: ${directory}`);
42273
42596
  }
42274
42597
  } else {
42275
- targetDir = import_path6.default.resolve(secureBaseDir, directory);
42276
- if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path6.default.sep) && targetDir !== secureBaseDir) {
42598
+ targetDir = import_path7.default.resolve(secureBaseDir, directory);
42599
+ if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path7.default.sep) && targetDir !== secureBaseDir) {
42277
42600
  throw new Error(`Path traversal attempt detected. Access denied: ${directory}`);
42278
42601
  }
42279
42602
  }
@@ -80598,11 +80921,11 @@ function loadMCPConfigurationFromPath(configPath) {
80598
80921
  if (!configPath) {
80599
80922
  throw new Error("Config path is required");
80600
80923
  }
80601
- if (!(0, import_fs7.existsSync)(configPath)) {
80924
+ if (!(0, import_fs9.existsSync)(configPath)) {
80602
80925
  throw new Error(`MCP configuration file not found: ${configPath}`);
80603
80926
  }
80604
80927
  try {
80605
- const content = (0, import_fs7.readFileSync)(configPath, "utf8");
80928
+ const content = (0, import_fs9.readFileSync)(configPath, "utf8");
80606
80929
  const config = JSON.parse(content);
80607
80930
  if (process.env.DEBUG === "1" || process.env.DEBUG_MCP === "1") {
80608
80931
  console.error(`[MCP DEBUG] Loaded configuration from: ${configPath}`);
@@ -80617,19 +80940,19 @@ function loadMCPConfiguration() {
80617
80940
  // Environment variable path
80618
80941
  process.env.MCP_CONFIG_PATH,
80619
80942
  // Local project paths
80620
- (0, import_path7.join)(process.cwd(), ".mcp", "config.json"),
80621
- (0, import_path7.join)(process.cwd(), "mcp.config.json"),
80943
+ (0, import_path8.join)(process.cwd(), ".mcp", "config.json"),
80944
+ (0, import_path8.join)(process.cwd(), "mcp.config.json"),
80622
80945
  // Home directory paths
80623
- (0, import_path7.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
80624
- (0, import_path7.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
80946
+ (0, import_path8.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
80947
+ (0, import_path8.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
80625
80948
  // Claude-style config location
80626
- (0, import_path7.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
80949
+ (0, import_path8.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
80627
80950
  ].filter(Boolean);
80628
80951
  let config = null;
80629
80952
  for (const configPath of configPaths) {
80630
- if ((0, import_fs7.existsSync)(configPath)) {
80953
+ if ((0, import_fs9.existsSync)(configPath)) {
80631
80954
  try {
80632
- const content = (0, import_fs7.readFileSync)(configPath, "utf8");
80955
+ const content = (0, import_fs9.readFileSync)(configPath, "utf8");
80633
80956
  config = JSON.parse(content);
80634
80957
  if (process.env.DEBUG === "1" || process.env.DEBUG_MCP === "1") {
80635
80958
  console.error(`[MCP DEBUG] Loaded configuration from: ${configPath}`);
@@ -80741,16 +81064,16 @@ function parseEnabledServers(config) {
80741
81064
  }
80742
81065
  return servers;
80743
81066
  }
80744
- var import_fs7, import_path7, import_os3, import_url4, __filename4, __dirname4, DEFAULT_TIMEOUT, MAX_TIMEOUT, DEFAULT_CONFIG;
81067
+ var import_fs9, import_path8, import_os3, import_url4, __filename4, __dirname4, DEFAULT_TIMEOUT, MAX_TIMEOUT, DEFAULT_CONFIG;
80745
81068
  var init_config = __esm({
80746
81069
  "src/agent/mcp/config.js"() {
80747
81070
  "use strict";
80748
- import_fs7 = require("fs");
80749
- import_path7 = require("path");
81071
+ import_fs9 = require("fs");
81072
+ import_path8 = require("path");
80750
81073
  import_os3 = require("os");
80751
81074
  import_url4 = require("url");
80752
81075
  __filename4 = (0, import_url4.fileURLToPath)("file:///");
80753
- __dirname4 = (0, import_path7.dirname)(__filename4);
81076
+ __dirname4 = (0, import_path8.dirname)(__filename4);
80754
81077
  DEFAULT_TIMEOUT = 3e4;
80755
81078
  MAX_TIMEOUT = 6e5;
80756
81079
  DEFAULT_CONFIG = {
@@ -80758,7 +81081,7 @@ var init_config = __esm({
80758
81081
  // Example probe server configuration
80759
81082
  "probe-local": {
80760
81083
  command: "node",
80761
- args: [(0, import_path7.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
81084
+ args: [(0, import_path8.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
80762
81085
  transport: "stdio",
80763
81086
  enabled: false
80764
81087
  },
@@ -82880,12 +83203,12 @@ async function createEnhancedClaudeCLIEngine(options = {}) {
82880
83203
  console.log("[DEBUG] Built-in MCP server started");
82881
83204
  console.log("[DEBUG] MCP URL:", `http://${host}:${port}/mcp`);
82882
83205
  }
82883
- mcpConfigPath = import_path8.default.join(import_os4.default.tmpdir(), `probe-mcp-${session.id}.json`);
83206
+ mcpConfigPath = import_path9.default.join(import_os4.default.tmpdir(), `probe-mcp-${session.id}.json`);
82884
83207
  const mcpConfig = {
82885
83208
  mcpServers: {
82886
83209
  probe: {
82887
83210
  command: "node",
82888
- args: [import_path8.default.join(process.cwd(), "mcp-probe-server.js")],
83211
+ args: [import_path9.default.join(process.cwd(), "mcp-probe-server.js")],
82889
83212
  env: {
82890
83213
  PROBE_WORKSPACE: process.cwd(),
82891
83214
  DEBUG: debug ? "true" : "false"
@@ -83254,14 +83577,14 @@ function combinePrompts(systemPrompt, customPrompt, agent) {
83254
83577
  }
83255
83578
  return systemPrompt || "";
83256
83579
  }
83257
- var import_child_process7, import_crypto5, import_promises2, import_path8, import_os4, import_events3;
83580
+ var import_child_process7, import_crypto5, import_promises2, import_path9, import_os4, import_events3;
83258
83581
  var init_enhanced_claude_code = __esm({
83259
83582
  "src/agent/engines/enhanced-claude-code.js"() {
83260
83583
  "use strict";
83261
83584
  import_child_process7 = require("child_process");
83262
83585
  import_crypto5 = require("crypto");
83263
83586
  import_promises2 = __toESM(require("fs/promises"), 1);
83264
- import_path8 = __toESM(require("path"), 1);
83587
+ import_path9 = __toESM(require("path"), 1);
83265
83588
  import_os4 = __toESM(require("os"), 1);
83266
83589
  import_events3 = require("events");
83267
83590
  init_built_in_server();
@@ -83605,11 +83928,11 @@ function createEnhancedVercelEngine(agent) {
83605
83928
  }
83606
83929
  };
83607
83930
  }
83608
- var import_ai;
83931
+ var import_ai2;
83609
83932
  var init_enhanced_vercel = __esm({
83610
83933
  "src/agent/engines/enhanced-vercel.js"() {
83611
83934
  "use strict";
83612
- import_ai = require("ai");
83935
+ import_ai2 = require("ai");
83613
83936
  }
83614
83937
  });
83615
83938
 
@@ -83618,7 +83941,7 @@ var ProbeAgent_exports = {};
83618
83941
  __export(ProbeAgent_exports, {
83619
83942
  ProbeAgent: () => ProbeAgent
83620
83943
  });
83621
- var import_dotenv, import_anthropic2, import_openai2, import_google2, import_ai2, import_crypto7, import_events4, import_fs8, import_promises3, import_path9, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
83944
+ var import_dotenv, import_anthropic2, import_openai2, import_google2, import_ai3, import_crypto7, import_events4, import_fs10, import_promises3, import_path10, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
83622
83945
  var init_ProbeAgent = __esm({
83623
83946
  "src/agent/ProbeAgent.js"() {
83624
83947
  "use strict";
@@ -83627,12 +83950,12 @@ var init_ProbeAgent = __esm({
83627
83950
  import_openai2 = require("@ai-sdk/openai");
83628
83951
  import_google2 = require("@ai-sdk/google");
83629
83952
  init_dist3();
83630
- import_ai2 = require("ai");
83953
+ import_ai3 = require("ai");
83631
83954
  import_crypto7 = require("crypto");
83632
83955
  import_events4 = require("events");
83633
- import_fs8 = require("fs");
83956
+ import_fs10 = require("fs");
83634
83957
  import_promises3 = require("fs/promises");
83635
- import_path9 = require("path");
83958
+ import_path10 = require("path");
83636
83959
  init_tokenCounter();
83637
83960
  init_InMemoryStorageAdapter();
83638
83961
  init_HookManager();
@@ -83959,7 +84282,7 @@ var init_ProbeAgent = __esm({
83959
84282
  if (!imagePath) {
83960
84283
  throw new Error("Image path is required");
83961
84284
  }
83962
- const filename = (0, import_path9.basename)(imagePath);
84285
+ const filename = (0, import_path10.basename)(imagePath);
83963
84286
  const extension = filename.toLowerCase().split(".").pop();
83964
84287
  if (!extension || !SUPPORTED_IMAGE_EXTENSIONS.includes(extension)) {
83965
84288
  throw new Error(`Invalid or unsupported image extension: ${extension}. Supported formats: ${SUPPORTED_IMAGE_EXTENSIONS.join(", ")}`);
@@ -84277,7 +84600,7 @@ var init_ProbeAgent = __esm({
84277
84600
  }
84278
84601
  if (!this.fallbackManager) {
84279
84602
  return await this.retryManager.executeWithRetry(
84280
- () => (0, import_ai2.streamText)(options),
84603
+ () => (0, import_ai3.streamText)(options),
84281
84604
  {
84282
84605
  provider: this.apiType,
84283
84606
  model: this.model
@@ -84299,7 +84622,7 @@ var init_ProbeAgent = __esm({
84299
84622
  debug: this.debug
84300
84623
  });
84301
84624
  return await providerRetryManager.executeWithRetry(
84302
- () => (0, import_ai2.streamText)(fallbackOptions),
84625
+ () => (0, import_ai3.streamText)(fallbackOptions),
84303
84626
  {
84304
84627
  provider: config.provider,
84305
84628
  model
@@ -84514,7 +84837,7 @@ var init_ProbeAgent = __esm({
84514
84837
  let resolvedPath2 = imagePath;
84515
84838
  if (!imagePath.includes("/") && !imagePath.includes("\\")) {
84516
84839
  for (const dir of listFilesDirectories) {
84517
- const potentialPath = (0, import_path9.resolve)(dir, imagePath);
84840
+ const potentialPath = (0, import_path10.resolve)(dir, imagePath);
84518
84841
  const loaded = await this.loadImageIfValid(potentialPath);
84519
84842
  if (loaded) {
84520
84843
  if (this.debug) {
@@ -84539,7 +84862,7 @@ var init_ProbeAgent = __esm({
84539
84862
  let match2;
84540
84863
  while ((match2 = fileHeaderPattern.exec(content)) !== null) {
84541
84864
  const filePath = match2[1].trim();
84542
- const dir = (0, import_path9.dirname)(filePath);
84865
+ const dir = (0, import_path10.dirname)(filePath);
84543
84866
  if (dir && dir !== ".") {
84544
84867
  directories.push(dir);
84545
84868
  if (this.debug) {
@@ -84584,17 +84907,17 @@ var init_ProbeAgent = __esm({
84584
84907
  const allowedDirs = this.allowedFolders && this.allowedFolders.length > 0 ? this.allowedFolders : [process.cwd()];
84585
84908
  let absolutePath;
84586
84909
  let isPathAllowed2 = false;
84587
- if ((0, import_path9.isAbsolute)(imagePath)) {
84588
- absolutePath = (0, import_path9.normalize)((0, import_path9.resolve)(imagePath));
84910
+ if ((0, import_path10.isAbsolute)(imagePath)) {
84911
+ absolutePath = (0, import_path10.normalize)((0, import_path10.resolve)(imagePath));
84589
84912
  isPathAllowed2 = allowedDirs.some((dir) => {
84590
- const normalizedDir = (0, import_path9.normalize)((0, import_path9.resolve)(dir));
84591
- return absolutePath === normalizedDir || absolutePath.startsWith(normalizedDir + import_path9.sep);
84913
+ const normalizedDir = (0, import_path10.normalize)((0, import_path10.resolve)(dir));
84914
+ return absolutePath === normalizedDir || absolutePath.startsWith(normalizedDir + import_path10.sep);
84592
84915
  });
84593
84916
  } else {
84594
84917
  for (const dir of allowedDirs) {
84595
- const normalizedDir = (0, import_path9.normalize)((0, import_path9.resolve)(dir));
84596
- const resolvedPath2 = (0, import_path9.normalize)((0, import_path9.resolve)(dir, imagePath));
84597
- if (resolvedPath2 === normalizedDir || resolvedPath2.startsWith(normalizedDir + import_path9.sep)) {
84918
+ const normalizedDir = (0, import_path10.normalize)((0, import_path10.resolve)(dir));
84919
+ const resolvedPath2 = (0, import_path10.normalize)((0, import_path10.resolve)(dir, imagePath));
84920
+ if (resolvedPath2 === normalizedDir || resolvedPath2.startsWith(normalizedDir + import_path10.sep)) {
84598
84921
  absolutePath = resolvedPath2;
84599
84922
  isPathAllowed2 = true;
84600
84923
  break;
@@ -85526,10 +85849,10 @@ ${toolResultContent}
85526
85849
  try {
85527
85850
  let resolvedWorkingDirectory = this.cwd || this.allowedFolders && this.allowedFolders[0] || process.cwd();
85528
85851
  if (params.workingDirectory) {
85529
- const requestedDir = (0, import_path9.isAbsolute)(params.workingDirectory) ? (0, import_path9.resolve)(params.workingDirectory) : (0, import_path9.resolve)(resolvedWorkingDirectory, params.workingDirectory);
85852
+ const requestedDir = (0, import_path10.isAbsolute)(params.workingDirectory) ? (0, import_path10.resolve)(params.workingDirectory) : (0, import_path10.resolve)(resolvedWorkingDirectory, params.workingDirectory);
85530
85853
  const isWithinAllowed = !this.allowedFolders || this.allowedFolders.length === 0 || this.allowedFolders.some((folder) => {
85531
- const resolvedFolder = (0, import_path9.resolve)(folder);
85532
- return requestedDir === resolvedFolder || requestedDir.startsWith(resolvedFolder + import_path9.sep);
85854
+ const resolvedFolder = (0, import_path10.resolve)(folder);
85855
+ return requestedDir === resolvedFolder || requestedDir.startsWith(resolvedFolder + import_path10.sep);
85533
85856
  });
85534
85857
  if (isWithinAllowed) {
85535
85858
  resolvedWorkingDirectory = requestedDir;
@@ -86479,7 +86802,9 @@ async function delegate({
86479
86802
  debug,
86480
86803
  tracer,
86481
86804
  path: path9,
86482
- // Inherit from parent
86805
+ // Workspace root (from delegateTool)
86806
+ cwd: path9,
86807
+ // Explicitly set cwd to workspace root to prevent path doubling
86483
86808
  provider,
86484
86809
  // Inherit from parent
86485
86810
  model,
@@ -86690,11 +87015,11 @@ var init_delegate = __esm({
86690
87015
  });
86691
87016
 
86692
87017
  // src/tools/vercel.js
86693
- var import_ai3, searchTool, queryTool, extractTool, delegateTool;
87018
+ var import_ai4, searchTool, queryTool, extractTool, delegateTool;
86694
87019
  var init_vercel = __esm({
86695
87020
  "src/tools/vercel.js"() {
86696
87021
  "use strict";
86697
- import_ai3 = require("ai");
87022
+ import_ai4 = require("ai");
86698
87023
  init_search();
86699
87024
  init_query();
86700
87025
  init_extract();
@@ -86702,7 +87027,7 @@ var init_vercel = __esm({
86702
87027
  init_common2();
86703
87028
  searchTool = (options = {}) => {
86704
87029
  const { sessionId, maxTokens = 1e4, debug = false, outline = false } = options;
86705
- return (0, import_ai3.tool)({
87030
+ return (0, import_ai4.tool)({
86706
87031
  name: "search",
86707
87032
  description: searchDescription,
86708
87033
  inputSchema: searchSchema,
@@ -86748,7 +87073,7 @@ var init_vercel = __esm({
86748
87073
  };
86749
87074
  queryTool = (options = {}) => {
86750
87075
  const { debug = false } = options;
86751
- return (0, import_ai3.tool)({
87076
+ return (0, import_ai4.tool)({
86752
87077
  name: "query",
86753
87078
  description: queryDescription,
86754
87079
  inputSchema: querySchema,
@@ -86784,7 +87109,7 @@ var init_vercel = __esm({
86784
87109
  };
86785
87110
  extractTool = (options = {}) => {
86786
87111
  const { debug = false, outline = false } = options;
86787
- return (0, import_ai3.tool)({
87112
+ return (0, import_ai4.tool)({
86788
87113
  name: "extract",
86789
87114
  description: extractDescription,
86790
87115
  inputSchema: extractSchema,
@@ -86860,7 +87185,7 @@ var init_vercel = __esm({
86860
87185
  };
86861
87186
  delegateTool = (options = {}) => {
86862
87187
  const { debug = false, timeout = 300, cwd, allowedFolders, enableBash = false, bashConfig } = options;
86863
- return (0, import_ai3.tool)({
87188
+ return (0, import_ai4.tool)({
86864
87189
  name: "delegate",
86865
87190
  description: delegateDescription,
86866
87191
  inputSchema: delegateSchema,
@@ -86889,14 +87214,15 @@ var init_vercel = __esm({
86889
87214
  if (model !== void 0 && model !== null && typeof model !== "string") {
86890
87215
  throw new TypeError("model must be a string, null, or undefined");
86891
87216
  }
86892
- const effectivePath = path9 || cwd || allowedFolders && allowedFolders[0];
87217
+ const workspaceRoot = allowedFolders && allowedFolders[0];
87218
+ const effectivePath = path9 || workspaceRoot || cwd;
86893
87219
  if (debug) {
86894
87220
  console.error(`Executing delegate with task: "${task.substring(0, 100)}${task.length > 100 ? "..." : ""}"`);
86895
87221
  if (parentSessionId) {
86896
87222
  console.error(`Parent session: ${parentSessionId}`);
86897
87223
  }
86898
87224
  if (effectivePath && effectivePath !== path9) {
86899
- console.error(`Using inherited path: ${effectivePath}`);
87225
+ console.error(`Using workspace root: ${effectivePath} (cwd was: ${cwd || "not set"})`);
86900
87226
  }
86901
87227
  }
86902
87228
  const result = await delegate({
@@ -87843,8 +88169,8 @@ async function executeBashCommand(command, options = {}) {
87843
88169
  } = options;
87844
88170
  let cwd = workingDirectory;
87845
88171
  try {
87846
- cwd = (0, import_path10.resolve)(cwd);
87847
- if (!(0, import_fs9.existsSync)(cwd)) {
88172
+ cwd = (0, import_path11.resolve)(cwd);
88173
+ if (!(0, import_fs11.existsSync)(cwd)) {
87848
88174
  throw new Error(`Working directory does not exist: ${cwd}`);
87849
88175
  }
87850
88176
  } catch (error2) {
@@ -88068,7 +88394,7 @@ function validateExecutionOptions(options = {}) {
88068
88394
  if (options.workingDirectory) {
88069
88395
  if (typeof options.workingDirectory !== "string") {
88070
88396
  errors.push("workingDirectory must be a string");
88071
- } else if (!(0, import_fs9.existsSync)(options.workingDirectory)) {
88397
+ } else if (!(0, import_fs11.existsSync)(options.workingDirectory)) {
88072
88398
  errors.push(`workingDirectory does not exist: ${options.workingDirectory}`);
88073
88399
  }
88074
88400
  }
@@ -88081,24 +88407,24 @@ function validateExecutionOptions(options = {}) {
88081
88407
  warnings
88082
88408
  };
88083
88409
  }
88084
- var import_child_process9, import_path10, import_fs9;
88410
+ var import_child_process9, import_path11, import_fs11;
88085
88411
  var init_bashExecutor = __esm({
88086
88412
  "src/agent/bashExecutor.js"() {
88087
88413
  "use strict";
88088
88414
  import_child_process9 = require("child_process");
88089
- import_path10 = require("path");
88090
- import_fs9 = require("fs");
88415
+ import_path11 = require("path");
88416
+ import_fs11 = require("fs");
88091
88417
  init_bashCommandUtils();
88092
88418
  }
88093
88419
  });
88094
88420
 
88095
88421
  // src/tools/bash.js
88096
- var import_ai4, import_path11, bashTool;
88422
+ var import_ai5, import_path12, bashTool;
88097
88423
  var init_bash = __esm({
88098
88424
  "src/tools/bash.js"() {
88099
88425
  "use strict";
88100
- import_ai4 = require("ai");
88101
- import_path11 = require("path");
88426
+ import_ai5 = require("ai");
88427
+ import_path12 = require("path");
88102
88428
  init_bashPermissions();
88103
88429
  init_bashExecutor();
88104
88430
  bashTool = (options = {}) => {
@@ -88127,7 +88453,7 @@ var init_bash = __esm({
88127
88453
  }
88128
88454
  return process.cwd();
88129
88455
  };
88130
- return (0, import_ai4.tool)({
88456
+ return (0, import_ai5.tool)({
88131
88457
  name: "bash",
88132
88458
  description: `Execute bash commands for system exploration and development tasks.
88133
88459
 
@@ -88207,12 +88533,12 @@ For code exploration, try these safe alternatives:
88207
88533
  - npm list, pip list for package information`;
88208
88534
  }
88209
88535
  const defaultDir = getDefaultWorkingDirectory();
88210
- const workingDir = workingDirectory ? (0, import_path11.isAbsolute)(workingDirectory) ? (0, import_path11.resolve)(workingDirectory) : (0, import_path11.resolve)(defaultDir, workingDirectory) : defaultDir;
88536
+ const workingDir = workingDirectory ? (0, import_path12.isAbsolute)(workingDirectory) ? (0, import_path12.resolve)(workingDirectory) : (0, import_path12.resolve)(defaultDir, workingDirectory) : defaultDir;
88211
88537
  if (allowedFolders && allowedFolders.length > 0) {
88212
- const resolvedWorkingDir = (0, import_path11.resolve)(workingDir);
88538
+ const resolvedWorkingDir = (0, import_path12.resolve)(workingDir);
88213
88539
  const isAllowed = allowedFolders.some((folder) => {
88214
- const resolvedFolder = (0, import_path11.resolve)(folder);
88215
- return resolvedWorkingDir === resolvedFolder || resolvedWorkingDir.startsWith(resolvedFolder + import_path11.sep);
88540
+ const resolvedFolder = (0, import_path12.resolve)(folder);
88541
+ return resolvedWorkingDir === resolvedFolder || resolvedWorkingDir.startsWith(resolvedFolder + import_path12.sep);
88216
88542
  });
88217
88543
  if (!isAllowed) {
88218
88544
  return `Error: Working directory "${workingDir}" is not within allowed folders: ${allowedFolders.join(", ")}`;
@@ -88264,323 +88590,6 @@ Command failed with exit code ${result.exitCode}`;
88264
88590
  }
88265
88591
  });
88266
88592
 
88267
- // src/tools/edit.js
88268
- function isPathAllowed(filePath, allowedFolders) {
88269
- if (!allowedFolders || allowedFolders.length === 0) {
88270
- const resolvedPath3 = (0, import_path12.resolve)(filePath);
88271
- const cwd = (0, import_path12.resolve)(process.cwd());
88272
- return resolvedPath3 === cwd || resolvedPath3.startsWith(cwd + import_path12.sep);
88273
- }
88274
- const resolvedPath2 = (0, import_path12.resolve)(filePath);
88275
- return allowedFolders.some((folder) => {
88276
- const allowedPath = (0, import_path12.resolve)(folder);
88277
- return resolvedPath2 === allowedPath || resolvedPath2.startsWith(allowedPath + import_path12.sep);
88278
- });
88279
- }
88280
- function parseFileToolOptions(options = {}) {
88281
- return {
88282
- debug: options.debug || false,
88283
- allowedFolders: options.allowedFolders || [],
88284
- cwd: options.cwd
88285
- };
88286
- }
88287
- var import_ai5, import_fs10, import_path12, import_fs11, editTool, createTool, editSchema, createSchema, editDescription, createDescription, editToolDefinition, createToolDefinition;
88288
- var init_edit = __esm({
88289
- "src/tools/edit.js"() {
88290
- "use strict";
88291
- import_ai5 = require("ai");
88292
- import_fs10 = require("fs");
88293
- import_path12 = require("path");
88294
- import_fs11 = require("fs");
88295
- editTool = (options = {}) => {
88296
- const { debug, allowedFolders, cwd } = parseFileToolOptions(options);
88297
- return (0, import_ai5.tool)({
88298
- name: "edit",
88299
- description: `Edit files using exact string replacement (Claude Code style).
88300
-
88301
- This tool performs exact string replacements in files. It requires the old_string to match exactly what's in the file, including all whitespace and indentation.
88302
-
88303
- Parameters:
88304
- - file_path: Path to the file to edit (absolute or relative)
88305
- - old_string: Exact text to find and replace (must be unique in the file unless replace_all is true)
88306
- - new_string: Text to replace with
88307
- - replace_all: (optional) Replace all occurrences instead of requiring uniqueness
88308
-
88309
- Important:
88310
- - The old_string must match EXACTLY including whitespace
88311
- - If old_string appears multiple times and replace_all is false, the edit will fail
88312
- - Use larger context around the string to ensure uniqueness when needed`,
88313
- inputSchema: {
88314
- type: "object",
88315
- properties: {
88316
- file_path: {
88317
- type: "string",
88318
- description: "Path to the file to edit"
88319
- },
88320
- old_string: {
88321
- type: "string",
88322
- description: "Exact text to find and replace"
88323
- },
88324
- new_string: {
88325
- type: "string",
88326
- description: "Text to replace with"
88327
- },
88328
- replace_all: {
88329
- type: "boolean",
88330
- description: "Replace all occurrences (default: false)",
88331
- default: false
88332
- }
88333
- },
88334
- required: ["file_path", "old_string", "new_string"]
88335
- },
88336
- execute: async ({ file_path, old_string, new_string, replace_all = false }) => {
88337
- try {
88338
- if (!file_path || typeof file_path !== "string" || file_path.trim() === "") {
88339
- return `Error editing file: Invalid file_path - must be a non-empty string`;
88340
- }
88341
- if (old_string === void 0 || old_string === null || typeof old_string !== "string") {
88342
- return `Error editing file: Invalid old_string - must be a string`;
88343
- }
88344
- if (new_string === void 0 || new_string === null || typeof new_string !== "string") {
88345
- return `Error editing file: Invalid new_string - must be a string`;
88346
- }
88347
- const resolvedPath2 = (0, import_path12.isAbsolute)(file_path) ? file_path : (0, import_path12.resolve)(cwd || process.cwd(), file_path);
88348
- if (debug) {
88349
- console.error(`[Edit] Attempting to edit file: ${resolvedPath2}`);
88350
- }
88351
- if (!isPathAllowed(resolvedPath2, allowedFolders)) {
88352
- return `Error editing file: Permission denied - ${file_path} is outside allowed directories`;
88353
- }
88354
- if (!(0, import_fs11.existsSync)(resolvedPath2)) {
88355
- return `Error editing file: File not found - ${file_path}`;
88356
- }
88357
- const content = await import_fs10.promises.readFile(resolvedPath2, "utf-8");
88358
- if (!content.includes(old_string)) {
88359
- return `Error editing file: String not found - the specified old_string was not found in ${file_path}`;
88360
- }
88361
- const occurrences = content.split(old_string).length - 1;
88362
- if (!replace_all && occurrences > 1) {
88363
- return `Error editing file: Multiple occurrences found - the old_string appears ${occurrences} times. Use replace_all: true to replace all occurrences, or provide more context to make the string unique.`;
88364
- }
88365
- let newContent;
88366
- if (replace_all) {
88367
- newContent = content.replaceAll(old_string, new_string);
88368
- } else {
88369
- newContent = content.replace(old_string, new_string);
88370
- }
88371
- if (newContent === content) {
88372
- return `Error editing file: No changes made - old_string and new_string might be the same`;
88373
- }
88374
- await import_fs10.promises.writeFile(resolvedPath2, newContent, "utf-8");
88375
- const replacedCount = replace_all ? occurrences : 1;
88376
- if (debug) {
88377
- console.error(`[Edit] Successfully edited ${resolvedPath2}, replaced ${replacedCount} occurrence(s)`);
88378
- }
88379
- return `Successfully edited ${file_path} (${replacedCount} replacement${replacedCount !== 1 ? "s" : ""})`;
88380
- } catch (error2) {
88381
- console.error("[Edit] Error:", error2);
88382
- return `Error editing file: ${error2.message}`;
88383
- }
88384
- }
88385
- });
88386
- };
88387
- createTool = (options = {}) => {
88388
- const { debug, allowedFolders, cwd } = parseFileToolOptions(options);
88389
- return (0, import_ai5.tool)({
88390
- name: "create",
88391
- description: `Create new files with specified content.
88392
-
88393
- This tool creates new files in the filesystem. It will create parent directories if they don't exist.
88394
-
88395
- Parameters:
88396
- - file_path: Path where the file should be created (absolute or relative)
88397
- - content: Content to write to the file
88398
- - overwrite: (optional) Whether to overwrite if file exists (default: false)
88399
-
88400
- Important:
88401
- - By default, will fail if the file already exists
88402
- - Set overwrite: true to replace existing files
88403
- - Parent directories will be created automatically if needed`,
88404
- inputSchema: {
88405
- type: "object",
88406
- properties: {
88407
- file_path: {
88408
- type: "string",
88409
- description: "Path where the file should be created"
88410
- },
88411
- content: {
88412
- type: "string",
88413
- description: "Content to write to the file"
88414
- },
88415
- overwrite: {
88416
- type: "boolean",
88417
- description: "Overwrite if file exists (default: false)",
88418
- default: false
88419
- }
88420
- },
88421
- required: ["file_path", "content"]
88422
- },
88423
- execute: async ({ file_path, content, overwrite = false }) => {
88424
- try {
88425
- if (!file_path || typeof file_path !== "string" || file_path.trim() === "") {
88426
- return `Error creating file: Invalid file_path - must be a non-empty string`;
88427
- }
88428
- if (content === void 0 || content === null || typeof content !== "string") {
88429
- return `Error creating file: Invalid content - must be a string`;
88430
- }
88431
- const resolvedPath2 = (0, import_path12.isAbsolute)(file_path) ? file_path : (0, import_path12.resolve)(cwd || process.cwd(), file_path);
88432
- if (debug) {
88433
- console.error(`[Create] Attempting to create file: ${resolvedPath2}`);
88434
- }
88435
- if (!isPathAllowed(resolvedPath2, allowedFolders)) {
88436
- return `Error creating file: Permission denied - ${file_path} is outside allowed directories`;
88437
- }
88438
- if ((0, import_fs11.existsSync)(resolvedPath2) && !overwrite) {
88439
- return `Error creating file: File already exists - ${file_path}. Use overwrite: true to replace it.`;
88440
- }
88441
- const dir = (0, import_path12.dirname)(resolvedPath2);
88442
- await import_fs10.promises.mkdir(dir, { recursive: true });
88443
- await import_fs10.promises.writeFile(resolvedPath2, content, "utf-8");
88444
- const action = (0, import_fs11.existsSync)(resolvedPath2) && overwrite ? "overwrote" : "created";
88445
- const bytes = Buffer.byteLength(content, "utf-8");
88446
- if (debug) {
88447
- console.error(`[Create] Successfully ${action} ${resolvedPath2}`);
88448
- }
88449
- return `Successfully ${action} ${file_path} (${bytes} bytes)`;
88450
- } catch (error2) {
88451
- console.error("[Create] Error:", error2);
88452
- return `Error creating file: ${error2.message}`;
88453
- }
88454
- }
88455
- });
88456
- };
88457
- editSchema = {
88458
- type: "object",
88459
- properties: {
88460
- file_path: {
88461
- type: "string",
88462
- description: "Path to the file to edit"
88463
- },
88464
- old_string: {
88465
- type: "string",
88466
- description: "Exact text to find and replace"
88467
- },
88468
- new_string: {
88469
- type: "string",
88470
- description: "Text to replace with"
88471
- },
88472
- replace_all: {
88473
- type: "boolean",
88474
- description: "Replace all occurrences (default: false)"
88475
- }
88476
- },
88477
- required: ["file_path", "old_string", "new_string"]
88478
- };
88479
- createSchema = {
88480
- type: "object",
88481
- properties: {
88482
- file_path: {
88483
- type: "string",
88484
- description: "Path where the file should be created"
88485
- },
88486
- content: {
88487
- type: "string",
88488
- description: "Content to write to the file"
88489
- },
88490
- overwrite: {
88491
- type: "boolean",
88492
- description: "Overwrite if file exists (default: false)"
88493
- }
88494
- },
88495
- required: ["file_path", "content"]
88496
- };
88497
- editDescription = "Edit files using exact string replacement. Requires exact match including whitespace.";
88498
- createDescription = "Create new files with specified content. Will create parent directories if needed.";
88499
- editToolDefinition = `
88500
- ## edit
88501
- Description: ${editDescription}
88502
-
88503
- When to use:
88504
- - For precise, surgical edits to existing files
88505
- - When you need to change specific lines or blocks of code
88506
- - For renaming functions, variables, or updating configuration values
88507
- - When the exact text to replace is known and unique (or use replace_all for multiple occurrences)
88508
-
88509
- When NOT to use:
88510
- - For creating new files (use 'create' tool instead)
88511
- - When you cannot determine the exact text to replace
88512
- - When changes span multiple locations that would be better handled together
88513
-
88514
- Parameters:
88515
- - file_path: (required) Path to the file to edit
88516
- - old_string: (required) Exact text to find and replace (must match including whitespace, newlines, and indentation)
88517
- - new_string: (required) Text to replace with
88518
- - replace_all: (optional, default: false) Replace all occurrences if the string appears multiple times
88519
-
88520
- Important notes:
88521
- - The old_string MUST match EXACTLY, including all whitespace, indentation, and line breaks
88522
- - If old_string appears multiple times and replace_all is false, the tool will fail
88523
- - Always verify the exact formatting of the text you want to replace
88524
-
88525
- Examples:
88526
- <edit>
88527
- <file_path>src/main.js</file_path>
88528
- <old_string>function oldName() {
88529
- return 42;
88530
- }</old_string>
88531
- <new_string>function newName() {
88532
- return 42;
88533
- }</new_string>
88534
- </edit>
88535
-
88536
- <edit>
88537
- <file_path>config.json</file_path>
88538
- <old_string>"debug": false</old_string>
88539
- <new_string>"debug": true</new_string>
88540
- <replace_all>true</replace_all>
88541
- </edit>`;
88542
- createToolDefinition = `
88543
- ## create
88544
- Description: ${createDescription}
88545
-
88546
- When to use:
88547
- - For creating brand new files from scratch
88548
- - When you need to add configuration files, documentation, or new modules
88549
- - For generating boilerplate code or templates
88550
- - When you have the complete content ready to write
88551
-
88552
- When NOT to use:
88553
- - For editing existing files (use 'edit' tool instead)
88554
- - When a file already exists unless you explicitly want to overwrite it
88555
-
88556
- Parameters:
88557
- - file_path: (required) Path where the file should be created
88558
- - content: (required) Complete content to write to the file
88559
- - overwrite: (optional, default: false) Whether to overwrite if file already exists
88560
-
88561
- Important notes:
88562
- - Parent directories will be created automatically if they don't exist
88563
- - The tool will fail if the file already exists and overwrite is false
88564
- - Be careful with the overwrite option as it completely replaces existing files
88565
-
88566
- Examples:
88567
- <create>
88568
- <file_path>src/newFile.js</file_path>
88569
- <content>export function hello() {
88570
- return "Hello, world!";
88571
- }</content>
88572
- </create>
88573
-
88574
- <create>
88575
- <file_path>README.md</file_path>
88576
- <content># My Project
88577
-
88578
- This is a new project.</content>
88579
- <overwrite>true</overwrite>
88580
- </create>`;
88581
- }
88582
- });
88583
-
88584
88593
  // src/tools/langchain.js
88585
88594
  function createSearchTool(options = {}) {
88586
88595
  const { cwd } = options;