@dexto/tools-filesystem 1.5.8 → 1.6.0
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/directory-approval.cjs +94 -0
- package/dist/directory-approval.d.cts +22 -0
- package/dist/directory-approval.d.ts +20 -0
- package/dist/directory-approval.d.ts.map +1 -0
- package/dist/directory-approval.integration.test.cjs +303 -269
- package/dist/directory-approval.integration.test.d.ts +14 -2
- package/dist/directory-approval.integration.test.d.ts.map +1 -0
- package/dist/directory-approval.integration.test.js +309 -270
- package/dist/directory-approval.js +59 -0
- package/dist/edit-file-tool.cjs +57 -90
- package/dist/edit-file-tool.d.cts +20 -3
- package/dist/edit-file-tool.d.ts +22 -9
- package/dist/edit-file-tool.d.ts.map +1 -0
- package/dist/edit-file-tool.js +53 -76
- package/dist/edit-file-tool.test.cjs +66 -29
- package/dist/edit-file-tool.test.d.ts +7 -2
- package/dist/edit-file-tool.test.d.ts.map +1 -0
- package/dist/edit-file-tool.test.js +66 -29
- package/dist/error-codes.d.ts +2 -3
- package/dist/error-codes.d.ts.map +1 -0
- package/dist/errors.d.ts +4 -7
- package/dist/errors.d.ts.map +1 -0
- package/dist/file-tool-types.d.cts +7 -35
- package/dist/file-tool-types.d.ts +8 -40
- package/dist/file-tool-types.d.ts.map +1 -0
- package/dist/filesystem-service.cjs +18 -1
- package/dist/filesystem-service.d.cts +11 -6
- package/dist/filesystem-service.d.ts +14 -12
- package/dist/filesystem-service.d.ts.map +1 -0
- package/dist/filesystem-service.js +18 -1
- package/dist/filesystem-service.test.cjs +10 -2
- package/dist/filesystem-service.test.d.ts +7 -2
- package/dist/filesystem-service.test.d.ts.map +1 -0
- package/dist/filesystem-service.test.js +10 -2
- package/dist/glob-files-tool.cjs +22 -47
- package/dist/glob-files-tool.d.cts +17 -3
- package/dist/glob-files-tool.d.ts +19 -9
- package/dist/glob-files-tool.d.ts.map +1 -0
- package/dist/glob-files-tool.js +23 -48
- package/dist/grep-content-tool.cjs +29 -46
- package/dist/grep-content-tool.d.cts +26 -3
- package/dist/grep-content-tool.d.ts +28 -9
- package/dist/grep-content-tool.d.ts.map +1 -0
- package/dist/grep-content-tool.js +30 -47
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +10 -5
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -2
- package/dist/path-validator.d.cts +2 -2
- package/dist/path-validator.d.ts +6 -9
- package/dist/path-validator.d.ts.map +1 -0
- package/dist/path-validator.test.d.ts +7 -2
- package/dist/path-validator.test.d.ts.map +1 -0
- package/dist/read-file-tool.cjs +21 -60
- package/dist/read-file-tool.d.cts +17 -3
- package/dist/read-file-tool.d.ts +19 -9
- package/dist/read-file-tool.d.ts.map +1 -0
- package/dist/read-file-tool.js +22 -51
- package/dist/tool-factory-config.cjs +61 -0
- package/dist/{tool-provider.d.ts → tool-factory-config.d.cts} +9 -23
- package/dist/{tool-provider.d.cts → tool-factory-config.d.ts} +13 -30
- package/dist/tool-factory-config.d.ts.map +1 -0
- package/dist/tool-factory-config.js +36 -0
- package/dist/tool-factory.cjs +102 -0
- package/dist/tool-factory.d.cts +7 -0
- package/dist/tool-factory.d.ts +4 -0
- package/dist/tool-factory.d.ts.map +1 -0
- package/dist/tool-factory.js +81 -0
- package/dist/types.d.ts +17 -18
- package/dist/types.d.ts.map +1 -0
- package/dist/write-file-tool.cjs +45 -73
- package/dist/write-file-tool.d.cts +20 -3
- package/dist/write-file-tool.d.ts +22 -9
- package/dist/write-file-tool.d.ts.map +1 -0
- package/dist/write-file-tool.js +46 -68
- package/dist/write-file-tool.test.cjs +76 -32
- package/dist/write-file-tool.test.d.ts +7 -2
- package/dist/write-file-tool.test.d.ts.map +1 -0
- package/dist/write-file-tool.test.js +76 -32
- package/package.json +4 -3
- package/dist/tool-provider.cjs +0 -123
- package/dist/tool-provider.js +0 -99
package/dist/types.d.ts
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* Types and interfaces for file system operations including reading, writing,
|
|
5
5
|
* searching, and validation.
|
|
6
6
|
*/
|
|
7
|
-
type BufferEncoding = 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex';
|
|
7
|
+
export type BufferEncoding = 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex';
|
|
8
8
|
/**
|
|
9
9
|
* File content with metadata
|
|
10
10
|
*/
|
|
11
|
-
interface FileContent {
|
|
11
|
+
export interface FileContent {
|
|
12
12
|
content: string;
|
|
13
13
|
lines: number;
|
|
14
14
|
encoding: string;
|
|
@@ -19,7 +19,7 @@ interface FileContent {
|
|
|
19
19
|
/**
|
|
20
20
|
* Options for reading files
|
|
21
21
|
*/
|
|
22
|
-
interface ReadFileOptions {
|
|
22
|
+
export interface ReadFileOptions {
|
|
23
23
|
/** Maximum number of lines to read */
|
|
24
24
|
limit?: number | undefined;
|
|
25
25
|
/** Starting line number (1-based) */
|
|
@@ -30,7 +30,7 @@ interface ReadFileOptions {
|
|
|
30
30
|
/**
|
|
31
31
|
* File metadata for glob results
|
|
32
32
|
*/
|
|
33
|
-
interface FileMetadata {
|
|
33
|
+
export interface FileMetadata {
|
|
34
34
|
path: string;
|
|
35
35
|
size: number;
|
|
36
36
|
modified: Date;
|
|
@@ -39,7 +39,7 @@ interface FileMetadata {
|
|
|
39
39
|
/**
|
|
40
40
|
* Options for glob operations
|
|
41
41
|
*/
|
|
42
|
-
interface GlobOptions {
|
|
42
|
+
export interface GlobOptions {
|
|
43
43
|
/** Base directory to search from */
|
|
44
44
|
cwd?: string | undefined;
|
|
45
45
|
/** Maximum number of results */
|
|
@@ -50,7 +50,7 @@ interface GlobOptions {
|
|
|
50
50
|
/**
|
|
51
51
|
* Glob result
|
|
52
52
|
*/
|
|
53
|
-
interface GlobResult {
|
|
53
|
+
export interface GlobResult {
|
|
54
54
|
files: FileMetadata[];
|
|
55
55
|
truncated: boolean;
|
|
56
56
|
totalFound: number;
|
|
@@ -58,7 +58,7 @@ interface GlobResult {
|
|
|
58
58
|
/**
|
|
59
59
|
* Search match with context
|
|
60
60
|
*/
|
|
61
|
-
interface SearchMatch {
|
|
61
|
+
export interface SearchMatch {
|
|
62
62
|
file: string;
|
|
63
63
|
lineNumber: number;
|
|
64
64
|
line: string;
|
|
@@ -70,7 +70,7 @@ interface SearchMatch {
|
|
|
70
70
|
/**
|
|
71
71
|
* Options for content search (grep)
|
|
72
72
|
*/
|
|
73
|
-
interface GrepOptions {
|
|
73
|
+
export interface GrepOptions {
|
|
74
74
|
/** Base directory to search */
|
|
75
75
|
path?: string | undefined;
|
|
76
76
|
/** Glob pattern to filter files */
|
|
@@ -87,7 +87,7 @@ interface GrepOptions {
|
|
|
87
87
|
/**
|
|
88
88
|
* Search result
|
|
89
89
|
*/
|
|
90
|
-
interface SearchResult {
|
|
90
|
+
export interface SearchResult {
|
|
91
91
|
matches: SearchMatch[];
|
|
92
92
|
totalMatches: number;
|
|
93
93
|
truncated: boolean;
|
|
@@ -96,7 +96,7 @@ interface SearchResult {
|
|
|
96
96
|
/**
|
|
97
97
|
* Options for writing files
|
|
98
98
|
*/
|
|
99
|
-
interface WriteFileOptions {
|
|
99
|
+
export interface WriteFileOptions {
|
|
100
100
|
/** Create parent directories if they don't exist */
|
|
101
101
|
createDirs?: boolean | undefined;
|
|
102
102
|
/** File encoding (default: utf-8) */
|
|
@@ -107,7 +107,7 @@ interface WriteFileOptions {
|
|
|
107
107
|
/**
|
|
108
108
|
* Write result
|
|
109
109
|
*/
|
|
110
|
-
interface WriteResult {
|
|
110
|
+
export interface WriteResult {
|
|
111
111
|
success: boolean;
|
|
112
112
|
path: string;
|
|
113
113
|
bytesWritten: number;
|
|
@@ -118,7 +118,7 @@ interface WriteResult {
|
|
|
118
118
|
/**
|
|
119
119
|
* Edit operation
|
|
120
120
|
*/
|
|
121
|
-
interface EditOperation {
|
|
121
|
+
export interface EditOperation {
|
|
122
122
|
oldString: string;
|
|
123
123
|
newString: string;
|
|
124
124
|
replaceAll?: boolean | undefined;
|
|
@@ -126,7 +126,7 @@ interface EditOperation {
|
|
|
126
126
|
/**
|
|
127
127
|
* Options for editing files
|
|
128
128
|
*/
|
|
129
|
-
interface EditFileOptions {
|
|
129
|
+
export interface EditFileOptions {
|
|
130
130
|
/** Create backup before editing */
|
|
131
131
|
backup?: boolean;
|
|
132
132
|
/** File encoding */
|
|
@@ -135,7 +135,7 @@ interface EditFileOptions {
|
|
|
135
135
|
/**
|
|
136
136
|
* Edit result
|
|
137
137
|
*/
|
|
138
|
-
interface EditResult {
|
|
138
|
+
export interface EditResult {
|
|
139
139
|
success: boolean;
|
|
140
140
|
path: string;
|
|
141
141
|
changesCount: number;
|
|
@@ -148,7 +148,7 @@ interface EditResult {
|
|
|
148
148
|
/**
|
|
149
149
|
* Path validation result
|
|
150
150
|
*/
|
|
151
|
-
interface PathValidation {
|
|
151
|
+
export interface PathValidation {
|
|
152
152
|
isValid: boolean;
|
|
153
153
|
error?: string;
|
|
154
154
|
normalizedPath?: string;
|
|
@@ -156,7 +156,7 @@ interface PathValidation {
|
|
|
156
156
|
/**
|
|
157
157
|
* File system configuration
|
|
158
158
|
*/
|
|
159
|
-
interface FileSystemConfig {
|
|
159
|
+
export interface FileSystemConfig {
|
|
160
160
|
/** Allowed base paths */
|
|
161
161
|
allowedPaths: string[];
|
|
162
162
|
/** Blocked paths (relative to allowed paths) */
|
|
@@ -174,5 +174,4 @@ interface FileSystemConfig {
|
|
|
174
174
|
/** Working directory for glob/grep operations (defaults to process.cwd()) */
|
|
175
175
|
workingDirectory?: string | undefined;
|
|
176
176
|
}
|
|
177
|
-
|
|
178
|
-
export type { BufferEncoding, EditFileOptions, EditOperation, EditResult, FileContent, FileMetadata, FileSystemConfig, GlobOptions, GlobResult, GrepOptions, PathValidation, ReadFileOptions, SearchMatch, SearchResult, WriteFileOptions, WriteResult };
|
|
177
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/write-file-tool.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,33 +15,25 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
var write_file_tool_exports = {};
|
|
30
20
|
__export(write_file_tool_exports, {
|
|
31
21
|
createWriteFileTool: () => createWriteFileTool
|
|
32
22
|
});
|
|
33
23
|
module.exports = __toCommonJS(write_file_tool_exports);
|
|
34
|
-
var path = __toESM(require("node:path"), 1);
|
|
35
24
|
var import_node_crypto = require("node:crypto");
|
|
36
25
|
var import_zod = require("zod");
|
|
37
26
|
var import_diff = require("diff");
|
|
38
27
|
var import_core = require("@dexto/core");
|
|
39
28
|
var import_error_codes = require("./error-codes.js");
|
|
29
|
+
var import_directory_approval = require("./directory-approval.js");
|
|
40
30
|
const previewContentHashCache = /* @__PURE__ */ new Map();
|
|
41
31
|
const FILE_NOT_EXISTS_MARKER = null;
|
|
42
32
|
function computeContentHash(content) {
|
|
43
33
|
return (0, import_node_crypto.createHash)("sha256").update(content, "utf8").digest("hex");
|
|
44
34
|
}
|
|
45
35
|
const WriteFileInputSchema = import_zod.z.object({
|
|
46
|
-
file_path: import_zod.z.string().describe("Absolute path where the file should be written"),
|
|
36
|
+
file_path: import_zod.z.string().min(1).describe("Absolute path where the file should be written"),
|
|
47
37
|
content: import_zod.z.string().describe("Content to write to the file"),
|
|
48
38
|
create_dirs: import_zod.z.boolean().optional().default(false).describe("Create parent directories if they don't exist (default: false)"),
|
|
49
39
|
encoding: import_zod.z.enum(["utf-8", "ascii", "latin1", "utf16le"]).optional().default("utf-8").describe("File encoding (default: utf-8)")
|
|
@@ -62,80 +52,51 @@ function generateDiffPreview(filePath, originalContent, newContent) {
|
|
|
62
52
|
deletions
|
|
63
53
|
};
|
|
64
54
|
}
|
|
65
|
-
function createWriteFileTool(
|
|
66
|
-
|
|
67
|
-
let pendingApprovalParentDir;
|
|
68
|
-
return {
|
|
55
|
+
function createWriteFileTool(getFileSystemService) {
|
|
56
|
+
return (0, import_core.defineTool)({
|
|
69
57
|
id: "write_file",
|
|
58
|
+
displayName: "Write",
|
|
59
|
+
aliases: ["write"],
|
|
70
60
|
description: "Write content to a file. Creates a new file or overwrites existing file. Automatically creates backup of existing files before overwriting. Use create_dirs to create parent directories. Requires approval for all write operations. Returns success status, path, bytes written, and backup path if applicable.",
|
|
71
61
|
inputSchema: WriteFileInputSchema,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (!file_path) return null;
|
|
79
|
-
const isAllowed = await fileSystemService.isPathWithinConfigAllowed(file_path);
|
|
80
|
-
if (isAllowed) {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
if (directoryApproval?.isSessionApproved(file_path)) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
const absolutePath = path.resolve(file_path);
|
|
87
|
-
const parentDir = path.dirname(absolutePath);
|
|
88
|
-
pendingApprovalParentDir = parentDir;
|
|
89
|
-
return {
|
|
90
|
-
type: import_core.ApprovalType.DIRECTORY_ACCESS,
|
|
91
|
-
metadata: {
|
|
92
|
-
path: absolutePath,
|
|
93
|
-
parentDir,
|
|
94
|
-
operation: "write",
|
|
95
|
-
toolName: "write_file"
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
},
|
|
99
|
-
/**
|
|
100
|
-
* Handle approved directory access - remember the directory for session
|
|
101
|
-
*/
|
|
102
|
-
onApprovalGranted: (response) => {
|
|
103
|
-
if (!directoryApproval || !pendingApprovalParentDir) return;
|
|
104
|
-
const data = response.data;
|
|
105
|
-
const rememberDirectory = data?.rememberDirectory ?? false;
|
|
106
|
-
directoryApproval.addApproved(
|
|
107
|
-
pendingApprovalParentDir,
|
|
108
|
-
rememberDirectory ? "session" : "once"
|
|
109
|
-
);
|
|
110
|
-
pendingApprovalParentDir = void 0;
|
|
111
|
-
},
|
|
62
|
+
...(0, import_directory_approval.createDirectoryAccessApprovalHandlers)({
|
|
63
|
+
toolName: "write_file",
|
|
64
|
+
operation: "write",
|
|
65
|
+
getFileSystemService,
|
|
66
|
+
resolvePaths: (input, fileSystemService) => (0, import_directory_approval.resolveFilePath)(fileSystemService.getWorkingDirectory(), input.file_path)
|
|
67
|
+
}),
|
|
112
68
|
/**
|
|
113
69
|
* Generate preview for approval UI - shows diff or file creation info
|
|
114
70
|
* Stores content hash for change detection in execute phase.
|
|
115
71
|
*/
|
|
116
|
-
|
|
72
|
+
async generatePreview(input, context) {
|
|
117
73
|
const { file_path, content } = input;
|
|
74
|
+
const resolvedFileSystemService = await getFileSystemService(context);
|
|
75
|
+
const { path: resolvedPath } = (0, import_directory_approval.resolveFilePath)(
|
|
76
|
+
resolvedFileSystemService.getWorkingDirectory(),
|
|
77
|
+
file_path
|
|
78
|
+
);
|
|
118
79
|
try {
|
|
119
|
-
const originalFile = await
|
|
80
|
+
const originalFile = await resolvedFileSystemService.readFile(resolvedPath);
|
|
120
81
|
const originalContent = originalFile.content;
|
|
121
|
-
if (context
|
|
82
|
+
if (context.toolCallId) {
|
|
122
83
|
previewContentHashCache.set(
|
|
123
84
|
context.toolCallId,
|
|
124
85
|
computeContentHash(originalContent)
|
|
125
86
|
);
|
|
126
87
|
}
|
|
127
|
-
return generateDiffPreview(
|
|
88
|
+
return generateDiffPreview(resolvedPath, originalContent, content);
|
|
128
89
|
} catch (error) {
|
|
129
90
|
if (error instanceof import_core.DextoRuntimeError && error.code === import_error_codes.FileSystemErrorCode.FILE_NOT_FOUND) {
|
|
130
|
-
if (context
|
|
91
|
+
if (context.toolCallId) {
|
|
131
92
|
previewContentHashCache.set(context.toolCallId, FILE_NOT_EXISTS_MARKER);
|
|
132
93
|
}
|
|
133
94
|
const lineCount = content.split("\n").length;
|
|
134
95
|
const preview = {
|
|
135
96
|
type: "file",
|
|
136
|
-
path:
|
|
97
|
+
path: resolvedPath,
|
|
137
98
|
operation: "create",
|
|
138
|
-
size: content
|
|
99
|
+
size: Buffer.byteLength(content, "utf8"),
|
|
139
100
|
lineCount,
|
|
140
101
|
content
|
|
141
102
|
// Include content for approval preview
|
|
@@ -145,12 +106,17 @@ function createWriteFileTool(options) {
|
|
|
145
106
|
throw error;
|
|
146
107
|
}
|
|
147
108
|
},
|
|
148
|
-
|
|
109
|
+
async execute(input, context) {
|
|
110
|
+
const resolvedFileSystemService = await getFileSystemService(context);
|
|
149
111
|
const { file_path, content, create_dirs, encoding } = input;
|
|
112
|
+
const { path: resolvedPath } = (0, import_directory_approval.resolveFilePath)(
|
|
113
|
+
resolvedFileSystemService.getWorkingDirectory(),
|
|
114
|
+
file_path
|
|
115
|
+
);
|
|
150
116
|
let originalContent = null;
|
|
151
117
|
let fileExistsNow = false;
|
|
152
118
|
try {
|
|
153
|
-
const originalFile = await
|
|
119
|
+
const originalFile = await resolvedFileSystemService.readFile(resolvedPath);
|
|
154
120
|
originalContent = originalFile.content;
|
|
155
121
|
fileExistsNow = true;
|
|
156
122
|
} catch (error) {
|
|
@@ -161,24 +127,30 @@ function createWriteFileTool(options) {
|
|
|
161
127
|
throw error;
|
|
162
128
|
}
|
|
163
129
|
}
|
|
164
|
-
if (context
|
|
130
|
+
if (context.toolCallId && previewContentHashCache.has(context.toolCallId)) {
|
|
165
131
|
const expectedHash = previewContentHashCache.get(context.toolCallId);
|
|
166
132
|
previewContentHashCache.delete(context.toolCallId);
|
|
167
133
|
if (expectedHash === FILE_NOT_EXISTS_MARKER) {
|
|
168
134
|
if (fileExistsNow) {
|
|
169
|
-
throw import_core.ToolError.fileModifiedSincePreview("write_file",
|
|
135
|
+
throw import_core.ToolError.fileModifiedSincePreview("write_file", resolvedPath);
|
|
170
136
|
}
|
|
171
137
|
} else if (expectedHash !== null) {
|
|
172
138
|
if (!fileExistsNow) {
|
|
173
|
-
throw import_core.ToolError.fileModifiedSincePreview("write_file",
|
|
139
|
+
throw import_core.ToolError.fileModifiedSincePreview("write_file", resolvedPath);
|
|
140
|
+
}
|
|
141
|
+
if (originalContent === null) {
|
|
142
|
+
throw import_core.ToolError.executionFailed(
|
|
143
|
+
"write_file",
|
|
144
|
+
"Expected original file content when fileExistsNow is true"
|
|
145
|
+
);
|
|
174
146
|
}
|
|
175
147
|
const currentHash = computeContentHash(originalContent);
|
|
176
148
|
if (expectedHash !== currentHash) {
|
|
177
|
-
throw import_core.ToolError.fileModifiedSincePreview("write_file",
|
|
149
|
+
throw import_core.ToolError.fileModifiedSincePreview("write_file", resolvedPath);
|
|
178
150
|
}
|
|
179
151
|
}
|
|
180
152
|
}
|
|
181
|
-
const result = await
|
|
153
|
+
const result = await resolvedFileSystemService.writeFile(resolvedPath, content, {
|
|
182
154
|
createDirs: create_dirs,
|
|
183
155
|
encoding
|
|
184
156
|
});
|
|
@@ -187,13 +159,13 @@ function createWriteFileTool(options) {
|
|
|
187
159
|
const lineCount = content.split("\n").length;
|
|
188
160
|
_display = {
|
|
189
161
|
type: "file",
|
|
190
|
-
path:
|
|
162
|
+
path: resolvedPath,
|
|
191
163
|
operation: "create",
|
|
192
164
|
size: result.bytesWritten,
|
|
193
165
|
lineCount
|
|
194
166
|
};
|
|
195
167
|
} else {
|
|
196
|
-
_display = generateDiffPreview(
|
|
168
|
+
_display = generateDiffPreview(resolvedPath, originalContent, content);
|
|
197
169
|
}
|
|
198
170
|
return {
|
|
199
171
|
success: result.success,
|
|
@@ -203,7 +175,7 @@ function createWriteFileTool(options) {
|
|
|
203
175
|
_display
|
|
204
176
|
};
|
|
205
177
|
}
|
|
206
|
-
};
|
|
178
|
+
});
|
|
207
179
|
}
|
|
208
180
|
// Annotate the CommonJS export names for ESM import in node:
|
|
209
181
|
0 && (module.exports = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { Tool } from '@dexto/core';
|
|
3
|
+
import { FileSystemServiceGetter } from './file-tool-types.cjs';
|
|
3
4
|
import './filesystem-service.cjs';
|
|
4
5
|
import './types.cjs';
|
|
5
6
|
|
|
@@ -9,9 +10,25 @@ import './types.cjs';
|
|
|
9
10
|
* Internal tool for writing content to files (requires approval)
|
|
10
11
|
*/
|
|
11
12
|
|
|
13
|
+
declare const WriteFileInputSchema: z.ZodObject<{
|
|
14
|
+
file_path: z.ZodString;
|
|
15
|
+
content: z.ZodString;
|
|
16
|
+
create_dirs: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
17
|
+
encoding: z.ZodDefault<z.ZodOptional<z.ZodEnum<["utf-8", "ascii", "latin1", "utf16le"]>>>;
|
|
18
|
+
}, "strict", z.ZodTypeAny, {
|
|
19
|
+
encoding: "ascii" | "utf-8" | "utf16le" | "latin1";
|
|
20
|
+
content: string;
|
|
21
|
+
file_path: string;
|
|
22
|
+
create_dirs: boolean;
|
|
23
|
+
}, {
|
|
24
|
+
content: string;
|
|
25
|
+
file_path: string;
|
|
26
|
+
encoding?: "ascii" | "utf-8" | "utf16le" | "latin1" | undefined;
|
|
27
|
+
create_dirs?: boolean | undefined;
|
|
28
|
+
}>;
|
|
12
29
|
/**
|
|
13
30
|
* Create the write_file internal tool with directory approval support
|
|
14
31
|
*/
|
|
15
|
-
declare function createWriteFileTool(
|
|
32
|
+
declare function createWriteFileTool(getFileSystemService: FileSystemServiceGetter): Tool<typeof WriteFileInputSchema>;
|
|
16
33
|
|
|
17
34
|
export { createWriteFileTool };
|
|
@@ -1,17 +1,30 @@
|
|
|
1
|
-
import { InternalTool } from '@dexto/core';
|
|
2
|
-
import { FileToolOptions } from './file-tool-types.js';
|
|
3
|
-
import './filesystem-service.js';
|
|
4
|
-
import './types.js';
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* Write File Tool
|
|
8
3
|
*
|
|
9
4
|
* Internal tool for writing content to files (requires approval)
|
|
10
5
|
*/
|
|
11
|
-
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import type { Tool } from '@dexto/core';
|
|
8
|
+
import type { FileSystemServiceGetter } from './file-tool-types.js';
|
|
9
|
+
declare const WriteFileInputSchema: z.ZodObject<{
|
|
10
|
+
file_path: z.ZodString;
|
|
11
|
+
content: z.ZodString;
|
|
12
|
+
create_dirs: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
13
|
+
encoding: z.ZodDefault<z.ZodOptional<z.ZodEnum<["utf-8", "ascii", "latin1", "utf16le"]>>>;
|
|
14
|
+
}, "strict", z.ZodTypeAny, {
|
|
15
|
+
encoding: "ascii" | "utf-8" | "utf16le" | "latin1";
|
|
16
|
+
content: string;
|
|
17
|
+
file_path: string;
|
|
18
|
+
create_dirs: boolean;
|
|
19
|
+
}, {
|
|
20
|
+
content: string;
|
|
21
|
+
file_path: string;
|
|
22
|
+
encoding?: "ascii" | "utf-8" | "utf16le" | "latin1" | undefined;
|
|
23
|
+
create_dirs?: boolean | undefined;
|
|
24
|
+
}>;
|
|
12
25
|
/**
|
|
13
26
|
* Create the write_file internal tool with directory approval support
|
|
14
27
|
*/
|
|
15
|
-
declare function createWriteFileTool(
|
|
16
|
-
|
|
17
|
-
|
|
28
|
+
export declare function createWriteFileTool(getFileSystemService: FileSystemServiceGetter): Tool<typeof WriteFileInputSchema>;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=write-file-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-file-tool.d.ts","sourceRoot":"","sources":["../src/write-file-tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,aAAa,CAAC;AAG9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAuBpE,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;EAeb,CAAC;AAyBd;;GAEG;AACH,wBAAgB,mBAAmB,CAC/B,oBAAoB,EAAE,uBAAuB,GAC9C,IAAI,CAAC,OAAO,oBAAoB,CAAC,CA0KnC"}
|
package/dist/write-file-tool.js
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import * as path from "node:path";
|
|
2
1
|
import { createHash } from "node:crypto";
|
|
3
2
|
import { z } from "zod";
|
|
4
3
|
import { createPatch } from "diff";
|
|
5
|
-
import {
|
|
6
|
-
DextoRuntimeError,
|
|
7
|
-
ApprovalType,
|
|
8
|
-
ToolError
|
|
9
|
-
} from "@dexto/core";
|
|
4
|
+
import { DextoRuntimeError, ToolError, defineTool } from "@dexto/core";
|
|
10
5
|
import { FileSystemErrorCode } from "./error-codes.js";
|
|
6
|
+
import { createDirectoryAccessApprovalHandlers, resolveFilePath } from "./directory-approval.js";
|
|
11
7
|
const previewContentHashCache = /* @__PURE__ */ new Map();
|
|
12
8
|
const FILE_NOT_EXISTS_MARKER = null;
|
|
13
9
|
function computeContentHash(content) {
|
|
14
10
|
return createHash("sha256").update(content, "utf8").digest("hex");
|
|
15
11
|
}
|
|
16
12
|
const WriteFileInputSchema = z.object({
|
|
17
|
-
file_path: z.string().describe("Absolute path where the file should be written"),
|
|
13
|
+
file_path: z.string().min(1).describe("Absolute path where the file should be written"),
|
|
18
14
|
content: z.string().describe("Content to write to the file"),
|
|
19
15
|
create_dirs: z.boolean().optional().default(false).describe("Create parent directories if they don't exist (default: false)"),
|
|
20
16
|
encoding: z.enum(["utf-8", "ascii", "latin1", "utf16le"]).optional().default("utf-8").describe("File encoding (default: utf-8)")
|
|
@@ -33,80 +29,51 @@ function generateDiffPreview(filePath, originalContent, newContent) {
|
|
|
33
29
|
deletions
|
|
34
30
|
};
|
|
35
31
|
}
|
|
36
|
-
function createWriteFileTool(
|
|
37
|
-
|
|
38
|
-
let pendingApprovalParentDir;
|
|
39
|
-
return {
|
|
32
|
+
function createWriteFileTool(getFileSystemService) {
|
|
33
|
+
return defineTool({
|
|
40
34
|
id: "write_file",
|
|
35
|
+
displayName: "Write",
|
|
36
|
+
aliases: ["write"],
|
|
41
37
|
description: "Write content to a file. Creates a new file or overwrites existing file. Automatically creates backup of existing files before overwriting. Use create_dirs to create parent directories. Requires approval for all write operations. Returns success status, path, bytes written, and backup path if applicable.",
|
|
42
38
|
inputSchema: WriteFileInputSchema,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (!file_path) return null;
|
|
50
|
-
const isAllowed = await fileSystemService.isPathWithinConfigAllowed(file_path);
|
|
51
|
-
if (isAllowed) {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
if (directoryApproval?.isSessionApproved(file_path)) {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
const absolutePath = path.resolve(file_path);
|
|
58
|
-
const parentDir = path.dirname(absolutePath);
|
|
59
|
-
pendingApprovalParentDir = parentDir;
|
|
60
|
-
return {
|
|
61
|
-
type: ApprovalType.DIRECTORY_ACCESS,
|
|
62
|
-
metadata: {
|
|
63
|
-
path: absolutePath,
|
|
64
|
-
parentDir,
|
|
65
|
-
operation: "write",
|
|
66
|
-
toolName: "write_file"
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
},
|
|
70
|
-
/**
|
|
71
|
-
* Handle approved directory access - remember the directory for session
|
|
72
|
-
*/
|
|
73
|
-
onApprovalGranted: (response) => {
|
|
74
|
-
if (!directoryApproval || !pendingApprovalParentDir) return;
|
|
75
|
-
const data = response.data;
|
|
76
|
-
const rememberDirectory = data?.rememberDirectory ?? false;
|
|
77
|
-
directoryApproval.addApproved(
|
|
78
|
-
pendingApprovalParentDir,
|
|
79
|
-
rememberDirectory ? "session" : "once"
|
|
80
|
-
);
|
|
81
|
-
pendingApprovalParentDir = void 0;
|
|
82
|
-
},
|
|
39
|
+
...createDirectoryAccessApprovalHandlers({
|
|
40
|
+
toolName: "write_file",
|
|
41
|
+
operation: "write",
|
|
42
|
+
getFileSystemService,
|
|
43
|
+
resolvePaths: (input, fileSystemService) => resolveFilePath(fileSystemService.getWorkingDirectory(), input.file_path)
|
|
44
|
+
}),
|
|
83
45
|
/**
|
|
84
46
|
* Generate preview for approval UI - shows diff or file creation info
|
|
85
47
|
* Stores content hash for change detection in execute phase.
|
|
86
48
|
*/
|
|
87
|
-
|
|
49
|
+
async generatePreview(input, context) {
|
|
88
50
|
const { file_path, content } = input;
|
|
51
|
+
const resolvedFileSystemService = await getFileSystemService(context);
|
|
52
|
+
const { path: resolvedPath } = resolveFilePath(
|
|
53
|
+
resolvedFileSystemService.getWorkingDirectory(),
|
|
54
|
+
file_path
|
|
55
|
+
);
|
|
89
56
|
try {
|
|
90
|
-
const originalFile = await
|
|
57
|
+
const originalFile = await resolvedFileSystemService.readFile(resolvedPath);
|
|
91
58
|
const originalContent = originalFile.content;
|
|
92
|
-
if (context
|
|
59
|
+
if (context.toolCallId) {
|
|
93
60
|
previewContentHashCache.set(
|
|
94
61
|
context.toolCallId,
|
|
95
62
|
computeContentHash(originalContent)
|
|
96
63
|
);
|
|
97
64
|
}
|
|
98
|
-
return generateDiffPreview(
|
|
65
|
+
return generateDiffPreview(resolvedPath, originalContent, content);
|
|
99
66
|
} catch (error) {
|
|
100
67
|
if (error instanceof DextoRuntimeError && error.code === FileSystemErrorCode.FILE_NOT_FOUND) {
|
|
101
|
-
if (context
|
|
68
|
+
if (context.toolCallId) {
|
|
102
69
|
previewContentHashCache.set(context.toolCallId, FILE_NOT_EXISTS_MARKER);
|
|
103
70
|
}
|
|
104
71
|
const lineCount = content.split("\n").length;
|
|
105
72
|
const preview = {
|
|
106
73
|
type: "file",
|
|
107
|
-
path:
|
|
74
|
+
path: resolvedPath,
|
|
108
75
|
operation: "create",
|
|
109
|
-
size: content
|
|
76
|
+
size: Buffer.byteLength(content, "utf8"),
|
|
110
77
|
lineCount,
|
|
111
78
|
content
|
|
112
79
|
// Include content for approval preview
|
|
@@ -116,12 +83,17 @@ function createWriteFileTool(options) {
|
|
|
116
83
|
throw error;
|
|
117
84
|
}
|
|
118
85
|
},
|
|
119
|
-
|
|
86
|
+
async execute(input, context) {
|
|
87
|
+
const resolvedFileSystemService = await getFileSystemService(context);
|
|
120
88
|
const { file_path, content, create_dirs, encoding } = input;
|
|
89
|
+
const { path: resolvedPath } = resolveFilePath(
|
|
90
|
+
resolvedFileSystemService.getWorkingDirectory(),
|
|
91
|
+
file_path
|
|
92
|
+
);
|
|
121
93
|
let originalContent = null;
|
|
122
94
|
let fileExistsNow = false;
|
|
123
95
|
try {
|
|
124
|
-
const originalFile = await
|
|
96
|
+
const originalFile = await resolvedFileSystemService.readFile(resolvedPath);
|
|
125
97
|
originalContent = originalFile.content;
|
|
126
98
|
fileExistsNow = true;
|
|
127
99
|
} catch (error) {
|
|
@@ -132,24 +104,30 @@ function createWriteFileTool(options) {
|
|
|
132
104
|
throw error;
|
|
133
105
|
}
|
|
134
106
|
}
|
|
135
|
-
if (context
|
|
107
|
+
if (context.toolCallId && previewContentHashCache.has(context.toolCallId)) {
|
|
136
108
|
const expectedHash = previewContentHashCache.get(context.toolCallId);
|
|
137
109
|
previewContentHashCache.delete(context.toolCallId);
|
|
138
110
|
if (expectedHash === FILE_NOT_EXISTS_MARKER) {
|
|
139
111
|
if (fileExistsNow) {
|
|
140
|
-
throw ToolError.fileModifiedSincePreview("write_file",
|
|
112
|
+
throw ToolError.fileModifiedSincePreview("write_file", resolvedPath);
|
|
141
113
|
}
|
|
142
114
|
} else if (expectedHash !== null) {
|
|
143
115
|
if (!fileExistsNow) {
|
|
144
|
-
throw ToolError.fileModifiedSincePreview("write_file",
|
|
116
|
+
throw ToolError.fileModifiedSincePreview("write_file", resolvedPath);
|
|
117
|
+
}
|
|
118
|
+
if (originalContent === null) {
|
|
119
|
+
throw ToolError.executionFailed(
|
|
120
|
+
"write_file",
|
|
121
|
+
"Expected original file content when fileExistsNow is true"
|
|
122
|
+
);
|
|
145
123
|
}
|
|
146
124
|
const currentHash = computeContentHash(originalContent);
|
|
147
125
|
if (expectedHash !== currentHash) {
|
|
148
|
-
throw ToolError.fileModifiedSincePreview("write_file",
|
|
126
|
+
throw ToolError.fileModifiedSincePreview("write_file", resolvedPath);
|
|
149
127
|
}
|
|
150
128
|
}
|
|
151
129
|
}
|
|
152
|
-
const result = await
|
|
130
|
+
const result = await resolvedFileSystemService.writeFile(resolvedPath, content, {
|
|
153
131
|
createDirs: create_dirs,
|
|
154
132
|
encoding
|
|
155
133
|
});
|
|
@@ -158,13 +136,13 @@ function createWriteFileTool(options) {
|
|
|
158
136
|
const lineCount = content.split("\n").length;
|
|
159
137
|
_display = {
|
|
160
138
|
type: "file",
|
|
161
|
-
path:
|
|
139
|
+
path: resolvedPath,
|
|
162
140
|
operation: "create",
|
|
163
141
|
size: result.bytesWritten,
|
|
164
142
|
lineCount
|
|
165
143
|
};
|
|
166
144
|
} else {
|
|
167
|
-
_display = generateDiffPreview(
|
|
145
|
+
_display = generateDiffPreview(resolvedPath, originalContent, content);
|
|
168
146
|
}
|
|
169
147
|
return {
|
|
170
148
|
success: result.success,
|
|
@@ -174,7 +152,7 @@ function createWriteFileTool(options) {
|
|
|
174
152
|
_display
|
|
175
153
|
};
|
|
176
154
|
}
|
|
177
|
-
};
|
|
155
|
+
});
|
|
178
156
|
}
|
|
179
157
|
export {
|
|
180
158
|
createWriteFileTool
|