@robota-sdk/agent-tools 3.0.0-beta.6 → 3.0.0-beta.60

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.
@@ -165,7 +165,9 @@ function zodToJsonSchema(schema, options = {}) {
165
165
  type: "object",
166
166
  properties,
167
167
  required,
168
- ...options.allowAdditionalProperties && { additionalProperties: true }
168
+ ...(options.allowAdditionalProperties || schemaDef.unknownKeys === "passthrough") && {
169
+ additionalProperties: true
170
+ }
169
171
  };
170
172
  }
171
173
  function convertZodTypeToProperty(typeObj) {
@@ -244,6 +246,100 @@ function isRequiredField(typeObj) {
244
246
  return typeDef.typeName !== "ZodOptional" && typeDef.typeName !== "ZodNullable" && typeDef.typeName !== "ZodDefault";
245
247
  }
246
248
 
249
+ // src/implementations/function-tool/parameter-validator.ts
250
+ function validateParameterType(key, value, schema) {
251
+ const expectedType = schema["type"];
252
+ switch (expectedType) {
253
+ case "string":
254
+ if (typeof value !== "string") {
255
+ return `Parameter "${key}" must be a string, got ${typeof value}`;
256
+ }
257
+ break;
258
+ case "number":
259
+ if (typeof value !== "number" || isNaN(value)) {
260
+ return `Parameter "${key}" must be a number, got ${typeof value}`;
261
+ }
262
+ break;
263
+ case "boolean":
264
+ if (typeof value !== "boolean") {
265
+ return `Parameter "${key}" must be a boolean, got ${typeof value}`;
266
+ }
267
+ break;
268
+ case "array":
269
+ if (!Array.isArray(value)) {
270
+ return `Parameter "${key}" must be an array, got ${typeof value}`;
271
+ }
272
+ if (schema.items) {
273
+ for (let i = 0; i < value.length; i++) {
274
+ const itemError = validateParameterType(`${key}[${i}]`, value[i], schema.items);
275
+ if (itemError) {
276
+ return itemError;
277
+ }
278
+ }
279
+ }
280
+ break;
281
+ case "object":
282
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
283
+ return `Parameter "${key}" must be an object, got ${typeof value}`;
284
+ }
285
+ break;
286
+ }
287
+ if (schema.enum && schema.enum.length > 0) {
288
+ const enumValues = schema.enum;
289
+ let isValidEnum = false;
290
+ for (const enumValue of enumValues) {
291
+ if (value === enumValue) {
292
+ isValidEnum = true;
293
+ break;
294
+ }
295
+ }
296
+ if (!isValidEnum) {
297
+ return `Parameter "${key}" must be one of: ${enumValues.join(", ")}, got ${value}`;
298
+ }
299
+ }
300
+ return void 0;
301
+ }
302
+ function getValidationErrors(parameters, schemaRequired, schemaProperties, additionalProperties) {
303
+ const errors = [];
304
+ for (const field of schemaRequired) {
305
+ if (!(field in parameters)) {
306
+ errors.push(`Missing required parameter: ${field}`);
307
+ }
308
+ }
309
+ for (const [key, value] of Object.entries(parameters)) {
310
+ const paramSchema = schemaProperties[key];
311
+ if (!paramSchema) {
312
+ if (additionalProperties === true) {
313
+ continue;
314
+ }
315
+ if (additionalProperties && typeof additionalProperties === "object") {
316
+ const additionalTypeError = validateParameterType(key, value, additionalProperties);
317
+ if (additionalTypeError) errors.push(additionalTypeError);
318
+ continue;
319
+ }
320
+ errors.push(`Unknown parameter: ${key}`);
321
+ continue;
322
+ }
323
+ const typeError = validateParameterType(key, value, paramSchema);
324
+ if (typeError) {
325
+ errors.push(typeError);
326
+ }
327
+ }
328
+ return errors;
329
+ }
330
+ function validateToolParameters(parameters, schemaRequired, schemaProperties, additionalProperties) {
331
+ const errors = getValidationErrors(
332
+ parameters,
333
+ schemaRequired,
334
+ schemaProperties,
335
+ additionalProperties
336
+ );
337
+ return {
338
+ isValid: errors.length === 0,
339
+ errors
340
+ };
341
+ }
342
+
247
343
  // src/implementations/function-tool.ts
248
344
  var FunctionTool = class {
249
345
  schema;
@@ -274,7 +370,12 @@ var FunctionTool = class {
274
370
  async execute(parameters, context) {
275
371
  const toolName = this.schema.name;
276
372
  if (!this.validate(parameters)) {
277
- const errors = this.getValidationErrors(parameters);
373
+ const errors = getValidationErrors(
374
+ parameters,
375
+ this.schema.parameters.required || [],
376
+ this.schema.parameters.properties || {},
377
+ this.schema.parameters.additionalProperties
378
+ );
278
379
  throw new ValidationError2(`Invalid parameters for tool "${toolName}": ${errors.join(", ")}`);
279
380
  }
280
381
  const startTime = Date.now();
@@ -310,17 +411,23 @@ var FunctionTool = class {
310
411
  * Validate parameters (simple boolean result)
311
412
  */
312
413
  validate(parameters) {
313
- return this.getValidationErrors(parameters).length === 0;
414
+ return getValidationErrors(
415
+ parameters,
416
+ this.schema.parameters.required || [],
417
+ this.schema.parameters.properties || {},
418
+ this.schema.parameters.additionalProperties
419
+ ).length === 0;
314
420
  }
315
421
  /**
316
422
  * Validate tool parameters with detailed result
317
423
  */
318
424
  validateParameters(parameters) {
319
- const errors = this.getValidationErrors(parameters);
320
- return {
321
- isValid: errors.length === 0,
322
- errors
323
- };
425
+ return validateToolParameters(
426
+ parameters,
427
+ this.schema.parameters.required || [],
428
+ this.schema.parameters.properties || {},
429
+ this.schema.parameters.additionalProperties
430
+ );
324
431
  }
325
432
  /**
326
433
  * Get tool description
@@ -328,86 +435,6 @@ var FunctionTool = class {
328
435
  getDescription() {
329
436
  return this.schema.description;
330
437
  }
331
- /**
332
- * Get detailed validation errors
333
- */
334
- getValidationErrors(parameters) {
335
- const errors = [];
336
- const required = this.schema.parameters.required || [];
337
- const properties = this.schema.parameters.properties || {};
338
- for (const field of required) {
339
- if (!(field in parameters)) {
340
- errors.push(`Missing required parameter: ${field}`);
341
- }
342
- }
343
- for (const [key, value] of Object.entries(parameters)) {
344
- const paramSchema = properties[key];
345
- if (!paramSchema) {
346
- errors.push(`Unknown parameter: ${key}`);
347
- continue;
348
- }
349
- const typeError = this.validateParameterType(key, value, paramSchema);
350
- if (typeError) {
351
- errors.push(typeError);
352
- }
353
- }
354
- return errors;
355
- }
356
- /**
357
- * Validate individual parameter type
358
- */
359
- validateParameterType(key, value, schema) {
360
- const expectedType = schema["type"];
361
- switch (expectedType) {
362
- case "string":
363
- if (typeof value !== "string") {
364
- return `Parameter "${key}" must be a string, got ${typeof value}`;
365
- }
366
- break;
367
- case "number":
368
- if (typeof value !== "number" || isNaN(value)) {
369
- return `Parameter "${key}" must be a number, got ${typeof value}`;
370
- }
371
- break;
372
- case "boolean":
373
- if (typeof value !== "boolean") {
374
- return `Parameter "${key}" must be a boolean, got ${typeof value}`;
375
- }
376
- break;
377
- case "array":
378
- if (!Array.isArray(value)) {
379
- return `Parameter "${key}" must be an array, got ${typeof value}`;
380
- }
381
- if (schema.items) {
382
- for (let i = 0; i < value.length; i++) {
383
- const itemError = this.validateParameterType(`${key}[${i}]`, value[i], schema.items);
384
- if (itemError) {
385
- return itemError;
386
- }
387
- }
388
- }
389
- break;
390
- case "object":
391
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
392
- return `Parameter "${key}" must be an object, got ${typeof value}`;
393
- }
394
- break;
395
- }
396
- if (schema.enum && schema.enum.length > 0) {
397
- const enumValues = schema.enum;
398
- let isValidEnum = false;
399
- for (const enumValue of enumValues) {
400
- if (value === enumValue) {
401
- isValidEnum = true;
402
- break;
403
- }
404
- }
405
- if (!isValidEnum) {
406
- return `Parameter "${key}" must be one of: ${enumValues.join(", ")}, got ${value}`;
407
- }
408
- }
409
- return void 0;
410
- }
411
438
  /**
412
439
  * Validate constructor inputs
413
440
  */
@@ -451,6 +478,132 @@ function createZodFunctionTool(name, description, zodSchema, fn) {
451
478
 
452
479
  // src/implementations/openapi-tool.ts
453
480
  import { ToolExecutionError as ToolExecutionError2, ValidationError as ValidationError3 } from "@robota-sdk/agent-core";
481
+
482
+ // src/implementations/openapi-schema-converter.ts
483
+ var HTTP_METHODS = [
484
+ "get",
485
+ "post",
486
+ "put",
487
+ "delete",
488
+ "patch",
489
+ "head",
490
+ "options"
491
+ ];
492
+ function findOperation(apiSpec, operationId) {
493
+ for (const [path, pathItem] of Object.entries(apiSpec.paths || {})) {
494
+ if (!pathItem) continue;
495
+ for (const method of HTTP_METHODS) {
496
+ const operation = pathItem[method];
497
+ if (operation?.operationId === operationId) {
498
+ return { method, path, operation };
499
+ }
500
+ }
501
+ }
502
+ return void 0;
503
+ }
504
+ function mapOpenAPIType(type) {
505
+ switch (type) {
506
+ case "string":
507
+ return "string";
508
+ case "number":
509
+ return "number";
510
+ case "integer":
511
+ return "integer";
512
+ case "boolean":
513
+ return "boolean";
514
+ case "array":
515
+ return "array";
516
+ case "object":
517
+ return "object";
518
+ default:
519
+ return "string";
520
+ }
521
+ }
522
+ function convertOpenAPISchemaToParameterSchema(schema) {
523
+ if ("$ref" in schema) {
524
+ return { type: "object" };
525
+ }
526
+ const result = {
527
+ type: mapOpenAPIType(schema.type)
528
+ };
529
+ if (schema.description) {
530
+ result.description = schema.description;
531
+ }
532
+ if (schema.enum) {
533
+ result.enum = schema.enum;
534
+ }
535
+ if (schema.minimum !== void 0) {
536
+ result.minimum = schema.minimum;
537
+ }
538
+ if (schema.maximum !== void 0) {
539
+ result.maximum = schema.maximum;
540
+ }
541
+ if (schema.pattern) {
542
+ result.pattern = schema.pattern;
543
+ }
544
+ if (schema.format) {
545
+ result.format = schema.format;
546
+ }
547
+ if (schema.default !== void 0) {
548
+ result.default = schema.default;
549
+ }
550
+ if (schema.type === "array" && schema.items) {
551
+ result.items = convertOpenAPISchemaToParameterSchema(schema.items);
552
+ }
553
+ if (schema.type === "object" && schema.properties) {
554
+ result.properties = {};
555
+ for (const [propName, propSchema] of Object.entries(schema.properties)) {
556
+ result.properties[propName] = convertOpenAPISchemaToParameterSchema(propSchema);
557
+ }
558
+ if (schema.required && schema.required.length > 0) {
559
+ result.required = schema.required;
560
+ }
561
+ }
562
+ return result;
563
+ }
564
+ function convertOpenAPIParamToSchema(param) {
565
+ const schema = param.schema;
566
+ return convertOpenAPISchemaToParameterSchema(schema);
567
+ }
568
+ function createSchemaFromOperation(operationId, opSpec) {
569
+ const properties = {};
570
+ const required = [];
571
+ const params = opSpec.parameters || [];
572
+ for (const param of params) {
573
+ properties[param.name] = convertOpenAPIParamToSchema(param);
574
+ if (param.required) {
575
+ required.push(param.name);
576
+ }
577
+ }
578
+ if (opSpec.requestBody) {
579
+ const requestBody = opSpec.requestBody;
580
+ const jsonContent = requestBody.content?.["application/json"];
581
+ if (jsonContent?.schema) {
582
+ const bodySchema = convertOpenAPISchemaToParameterSchema(jsonContent.schema);
583
+ if (bodySchema.type === "object" && bodySchema.properties) {
584
+ Object.assign(properties, bodySchema.properties);
585
+ const schemaWithRequired = bodySchema;
586
+ if (schemaWithRequired.required) {
587
+ required.push(...schemaWithRequired.required);
588
+ }
589
+ }
590
+ }
591
+ }
592
+ const schemaParams = {
593
+ type: "object",
594
+ properties
595
+ };
596
+ if (required.length > 0) {
597
+ schemaParams.required = required;
598
+ }
599
+ return {
600
+ name: operationId,
601
+ description: opSpec.summary || opSpec.description || `OpenAPI operation: ${operationId}`,
602
+ parameters: schemaParams
603
+ };
604
+ }
605
+
606
+ // src/implementations/openapi-tool.ts
454
607
  var OpenAPITool = class {
455
608
  schema;
456
609
  apiSpec;
@@ -557,36 +710,13 @@ var OpenAPITool = class {
557
710
  * @private
558
711
  */
559
712
  async executeAPICall(parameters, _context) {
560
- const operation = this.findOperation();
713
+ const operation = findOperation(this.apiSpec, this.operationId);
561
714
  if (!operation) {
562
715
  throw new Error(`Operation ${this.operationId} not found in OpenAPI spec`);
563
716
  }
564
- const requestConfig = this.buildRequestConfig(operation, parameters);
717
+ this.buildRequestConfig(operation, parameters);
565
718
  throw new Error("Not implemented: actual API execution is not yet available");
566
719
  }
567
- /**
568
- * Find the operation in the OpenAPI specification
569
- */
570
- findOperation() {
571
- for (const [path, pathItem] of Object.entries(this.apiSpec.paths || {})) {
572
- if (!pathItem) continue;
573
- for (const method of [
574
- "get",
575
- "post",
576
- "put",
577
- "delete",
578
- "patch",
579
- "head",
580
- "options"
581
- ]) {
582
- const operation = pathItem[method];
583
- if (operation?.operationId === this.operationId) {
584
- return { method, path, operation };
585
- }
586
- }
587
- }
588
- return void 0;
589
- }
590
720
  /**
591
721
  * Build HTTP request configuration from OpenAPI operation and parameters
592
722
  */
@@ -658,121 +788,13 @@ var OpenAPITool = class {
658
788
  * Create tool schema from OpenAPI operation specification
659
789
  */
660
790
  createSchemaFromOpenAPI() {
661
- const operation = this.findOperation();
791
+ const operation = findOperation(this.apiSpec, this.operationId);
662
792
  if (!operation) {
663
793
  throw new Error(
664
794
  `[STRICT-POLICY][EMITTER-CONTRACT] OpenAPI operation not found: ${this.operationId}. Emitter contract must provide a valid operationId present in the OpenAPI document.`
665
795
  );
666
796
  }
667
- const { operation: opSpec } = operation;
668
- const properties = {};
669
- const required = [];
670
- const params = opSpec.parameters || [];
671
- for (const param of params) {
672
- properties[param.name] = this.convertOpenAPIParamToSchema(param);
673
- if (param.required) {
674
- required.push(param.name);
675
- }
676
- }
677
- if (opSpec.requestBody) {
678
- const requestBody = opSpec.requestBody;
679
- const jsonContent = requestBody.content?.["application/json"];
680
- if (jsonContent?.schema) {
681
- const bodySchema = this.convertOpenAPISchemaToParameterSchema(jsonContent.schema);
682
- if (bodySchema.type === "object" && bodySchema.properties) {
683
- Object.assign(properties, bodySchema.properties);
684
- const schemaWithRequired = bodySchema;
685
- if (schemaWithRequired.required) {
686
- required.push(...schemaWithRequired.required);
687
- }
688
- }
689
- }
690
- }
691
- const schemaParams = {
692
- type: "object",
693
- properties
694
- };
695
- if (required.length > 0) {
696
- schemaParams.required = required;
697
- }
698
- return {
699
- name: this.operationId,
700
- description: opSpec.summary || opSpec.description || `OpenAPI operation: ${this.operationId}`,
701
- parameters: schemaParams
702
- };
703
- }
704
- /**
705
- * Convert OpenAPI parameter to tool parameter schema
706
- */
707
- convertOpenAPIParamToSchema(param) {
708
- const schema = param.schema;
709
- return this.convertOpenAPISchemaToParameterSchema(schema);
710
- }
711
- /**
712
- * Convert OpenAPI schema to parameter schema
713
- */
714
- convertOpenAPISchemaToParameterSchema(schema) {
715
- if ("$ref" in schema) {
716
- return { type: "object" };
717
- }
718
- const result = {
719
- type: this.mapOpenAPIType(schema.type)
720
- };
721
- if (schema.description) {
722
- result.description = schema.description;
723
- }
724
- if (schema.enum) {
725
- result.enum = schema.enum;
726
- }
727
- if (schema.minimum !== void 0) {
728
- result.minimum = schema.minimum;
729
- }
730
- if (schema.maximum !== void 0) {
731
- result.maximum = schema.maximum;
732
- }
733
- if (schema.pattern) {
734
- result.pattern = schema.pattern;
735
- }
736
- if (schema.format) {
737
- result.format = schema.format;
738
- }
739
- if (schema.default !== void 0) {
740
- result.default = schema.default;
741
- }
742
- if (schema.type === "array" && schema.items) {
743
- result.items = this.convertOpenAPISchemaToParameterSchema(schema.items);
744
- }
745
- if (schema.type === "object" && schema.properties) {
746
- result.properties = {};
747
- for (const [propName, propSchema] of Object.entries(schema.properties)) {
748
- result.properties[propName] = this.convertOpenAPISchemaToParameterSchema(propSchema);
749
- }
750
- if (schema.required && schema.required.length > 0) {
751
- result.required = schema.required;
752
- }
753
- }
754
- return result;
755
- }
756
- /**
757
- * Map OpenAPI type to JSON schema type
758
- */
759
- mapOpenAPIType(type) {
760
- switch (type) {
761
- case "string":
762
- return "string";
763
- case "number":
764
- return "number";
765
- case "integer":
766
- return "integer";
767
- case "boolean":
768
- return "boolean";
769
- case "array":
770
- return "array";
771
- case "object":
772
- return "object";
773
- default:
774
- return "string";
775
- }
797
+ return createSchemaFromOperation(this.operationId, operation.operation);
776
798
  }
777
799
  };
778
800
  function createOpenAPITool(config) {
@@ -809,6 +831,11 @@ async function runBash(args) {
809
831
  const timer = setTimeout(() => {
810
832
  timedOut = true;
811
833
  child.kill("SIGTERM");
834
+ settle({
835
+ success: false,
836
+ output: Buffer.concat(stdoutChunks).toString("utf8"),
837
+ error: `Command timed out after ${timeout}ms`
838
+ });
812
839
  }, timeout);
813
840
  function settle(result) {
814
841
  if (settled) return;
@@ -954,9 +981,51 @@ var readTool = createZodFunctionTool(
954
981
  );
955
982
 
956
983
  // src/builtins/write-tool.ts
957
- import { writeFile, mkdir } from "fs/promises";
958
- import { dirname } from "path";
959
984
  import { z as z3 } from "zod";
985
+
986
+ // src/builtins/atomic-file-write.ts
987
+ import { randomBytes } from "crypto";
988
+ import { chmod, mkdir, rename, rm, stat as stat2, writeFile } from "fs/promises";
989
+ import { basename, dirname, join } from "path";
990
+ var TEMP_RANDOM_BYTES = 6;
991
+ var PRESERVED_MODE_BITS = 4095;
992
+ var MISSING_FILE_ERROR_CODE = "ENOENT";
993
+ function createTempFilePath(filePath) {
994
+ const dir = dirname(filePath);
995
+ const name = basename(filePath);
996
+ const suffix = randomBytes(TEMP_RANDOM_BYTES).toString("hex");
997
+ return join(dir, `.${name}.robota-tmp-${process.pid}-${Date.now()}-${suffix}`);
998
+ }
999
+ async function readExistingMode(filePath) {
1000
+ try {
1001
+ const fileStats = await stat2(filePath);
1002
+ return fileStats.mode & PRESERVED_MODE_BITS;
1003
+ } catch (error) {
1004
+ if (error instanceof Error && hasErrorCode(error, MISSING_FILE_ERROR_CODE)) return void 0;
1005
+ throw error;
1006
+ }
1007
+ }
1008
+ function hasErrorCode(error, code) {
1009
+ return "code" in error && error.code === code;
1010
+ }
1011
+ async function atomicWriteUtf8File(filePath, content) {
1012
+ const dir = dirname(filePath);
1013
+ await mkdir(dir, { recursive: true });
1014
+ const existingMode = await readExistingMode(filePath);
1015
+ const tempFilePath = createTempFilePath(filePath);
1016
+ try {
1017
+ await writeFile(tempFilePath, content, "utf8");
1018
+ if (existingMode !== void 0) {
1019
+ await chmod(tempFilePath, existingMode);
1020
+ }
1021
+ await rename(tempFilePath, filePath);
1022
+ } catch (error) {
1023
+ await rm(tempFilePath, { force: true }).catch(() => void 0);
1024
+ throw error;
1025
+ }
1026
+ }
1027
+
1028
+ // src/builtins/write-tool.ts
960
1029
  var WriteSchema = z3.object({
961
1030
  filePath: z3.string().describe("The absolute path to the file to write"),
962
1031
  content: z3.string().describe("The content to write to the file")
@@ -964,8 +1033,7 @@ var WriteSchema = z3.object({
964
1033
  async function writeFileTool(args) {
965
1034
  const { filePath, content } = args;
966
1035
  try {
967
- await mkdir(dirname(filePath), { recursive: true });
968
- await writeFile(filePath, content, "utf8");
1036
+ await atomicWriteUtf8File(filePath, content);
969
1037
  const result = {
970
1038
  success: true,
971
1039
  output: `Written ${Buffer.byteLength(content, "utf8")} bytes to ${filePath}`
@@ -990,7 +1058,7 @@ var writeTool = createZodFunctionTool(
990
1058
  );
991
1059
 
992
1060
  // src/builtins/edit-tool.ts
993
- import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
1061
+ import { readFile as readFile2 } from "fs/promises";
994
1062
  import { z as z4 } from "zod";
995
1063
  var EditSchema = z4.object({
996
1064
  filePath: z4.string().describe("The absolute path to the file to modify"),
@@ -1036,7 +1104,7 @@ async function editFileTool(args) {
1036
1104
  }
1037
1105
  const updated = replaceAll ? content.split(oldString).join(newString) : content.slice(0, content.indexOf(oldString)) + newString + content.slice(content.indexOf(oldString) + oldString.length);
1038
1106
  try {
1039
- await writeFile2(filePath, updated, "utf8");
1107
+ await atomicWriteUtf8File(filePath, updated);
1040
1108
  } catch (err) {
1041
1109
  const result2 = {
1042
1110
  success: false,
@@ -1046,9 +1114,12 @@ async function editFileTool(args) {
1046
1114
  return JSON.stringify(result2);
1047
1115
  }
1048
1116
  const count = replaceAll ? content.split(oldString).length - 1 : 1;
1117
+ const matchIdx = content.indexOf(oldString);
1118
+ const startLine = matchIdx >= 0 ? content.substring(0, matchIdx).split("\n").length : 1;
1049
1119
  const result = {
1050
1120
  success: true,
1051
- output: `Replaced ${count} occurrence(s) in ${filePath}`
1121
+ output: `Replaced ${count} occurrence(s) in ${filePath}`,
1122
+ startLine
1052
1123
  };
1053
1124
  return JSON.stringify(result);
1054
1125
  }
@@ -1062,7 +1133,7 @@ var editTool = createZodFunctionTool(
1062
1133
  );
1063
1134
 
1064
1135
  // src/builtins/glob-tool.ts
1065
- import { stat as stat2 } from "fs/promises";
1136
+ import { stat as stat3 } from "fs/promises";
1066
1137
  import { resolve } from "path";
1067
1138
  import fg from "fast-glob";
1068
1139
  import { z as z5 } from "zod";
@@ -1099,7 +1170,7 @@ async function globFileTool(args) {
1099
1170
  matches.map(async (p) => {
1100
1171
  const absPath = resolve(cwd, p);
1101
1172
  try {
1102
- const s = await stat2(absPath);
1173
+ const s = await stat3(absPath);
1103
1174
  return { path: p, mtime: s.mtimeMs };
1104
1175
  } catch {
1105
1176
  return { path: p, mtime: 0 };
@@ -1134,8 +1205,8 @@ var globTool = createZodFunctionTool(
1134
1205
  );
1135
1206
 
1136
1207
  // src/builtins/grep-tool.ts
1137
- import { readFile as readFile3, readdir, stat as stat3 } from "fs/promises";
1138
- import { join, resolve as resolve2 } from "path";
1208
+ import { readFile as readFile3, readdir, stat as stat4 } from "fs/promises";
1209
+ import { join as join2, resolve as resolve2 } from "path";
1139
1210
  import { z as z6 } from "zod";
1140
1211
  var GrepSchema = z6.object({
1141
1212
  pattern: z6.string().describe("The regular expression pattern to search for in file contents"),
@@ -1169,10 +1240,10 @@ async function collectFiles(dirPath, glob) {
1169
1240
  }
1170
1241
  for (const name of entryNames) {
1171
1242
  if (name === "node_modules" || name === ".git") continue;
1172
- const fullPath = join(current, name);
1243
+ const fullPath = join2(current, name);
1173
1244
  let fileStat;
1174
1245
  try {
1175
- fileStat = await stat3(fullPath);
1246
+ fileStat = await stat4(fullPath);
1176
1247
  } catch {
1177
1248
  continue;
1178
1249
  }
@@ -1242,7 +1313,7 @@ async function grepFileTool(args) {
1242
1313
  }
1243
1314
  let targetStat;
1244
1315
  try {
1245
- targetStat = await stat3(targetPath);
1316
+ targetStat = await stat4(targetPath);
1246
1317
  } catch {
1247
1318
  const result2 = {
1248
1319
  success: false,