@xpert-ai/plugin-sdk 3.8.0 → 3.8.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xpert-ai/plugin-sdk",
3
- "version": "3.8.0",
3
+ "version": "3.8.1",
4
4
  "license": "AGPL-3.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,6 +33,25 @@ export interface GrepMatch {
33
33
  /** The matching line text */
34
34
  text: string;
35
35
  }
36
+ /**
37
+ * Read mode for file reading operations.
38
+ */
39
+ export type ReadMode = 'slice' | 'indentation';
40
+ /**
41
+ * Configuration for indentation-aware file reading.
42
+ */
43
+ export interface IndentationOptions {
44
+ /** Anchor line number (1-indexed), defaults to offset */
45
+ anchor_line?: number;
46
+ /** Maximum indentation depth to collect; 0 means unlimited */
47
+ max_levels?: number;
48
+ /** Whether to include sibling blocks at the same indentation level */
49
+ include_siblings?: boolean;
50
+ /** Whether to include header lines (comments) above the anchor block */
51
+ include_header?: boolean;
52
+ /** Hard cap on returned lines */
53
+ max_lines?: number;
54
+ }
36
55
  /**
37
56
  * File data structure used by backends.
38
57
  *
@@ -88,6 +107,39 @@ export interface EditResult {
88
107
  /** Metadata for the edit operation, attached to the ToolMessage */
89
108
  metadata?: Record<string, unknown>;
90
109
  }
110
+ /**
111
+ * Single edit operation for multi-edit.
112
+ */
113
+ export interface EditOperation {
114
+ /** String to find and replace */
115
+ oldString: string;
116
+ /** Replacement string */
117
+ newString: string;
118
+ /** If true, replace all occurrences (default: false) */
119
+ replaceAll?: boolean;
120
+ }
121
+ /**
122
+ * Result from backend multi-edit operations.
123
+ *
124
+ * Checkpoint backends populate filesUpdate with {file_path: file_data} for LangGraph state.
125
+ * External backends set filesUpdate to null (already persisted to disk/S3/database/etc).
126
+ */
127
+ export interface MultiEditResult {
128
+ /** Error message on failure, undefined on success */
129
+ error?: string;
130
+ /** File path of edited file, undefined on failure */
131
+ path?: string;
132
+ /**
133
+ * State update dict for checkpoint backends, null for external storage.
134
+ * Checkpoint backends populate this with {file_path: file_data} for LangGraph state.
135
+ * External backends set null (already persisted to disk/S3/database/etc).
136
+ */
137
+ filesUpdate?: Record<string, FileData> | null;
138
+ /** Results from each individual edit operation */
139
+ results?: EditResult[];
140
+ /** Metadata for the multi-edit operation, attached to the ToolMessage */
141
+ metadata?: Record<string, unknown>;
142
+ }
91
143
  /**
92
144
  * Result of code execution.
93
145
  * Simplified schema optimized for LLM consumption.
@@ -146,15 +198,27 @@ export interface BackendProtocol {
146
198
  * @returns List of FileInfo objects for files and directories directly in the directory
147
199
  */
148
200
  lsInfo(path: string): MaybePromise<FileInfo[]>;
201
+ /**
202
+ * List directory contents recursively with depth control and pagination.
203
+ *
204
+ * @param dirPath - Absolute path to directory
205
+ * @param offset - 1-indexed entry number to start from (default: 1)
206
+ * @param limit - Maximum number of entries to return (default: 25)
207
+ * @param depth - Maximum depth to traverse (default: 2)
208
+ * @returns Human-readable directory tree with indentation
209
+ */
210
+ listDir(dirPath: string, offset?: number, limit?: number, depth?: number): MaybePromise<string>;
149
211
  /**
150
212
  * Read file content with line numbers or an error string.
151
213
  *
152
214
  * @param filePath - Absolute file path
153
- * @param offset - Line offset to start reading from (0-indexed), default 0
154
- * @param limit - Maximum number of lines to read, default 500
215
+ * @param offset - Line offset to start reading from (1-indexed), default 1
216
+ * @param limit - Maximum number of lines to read, default 2000
217
+ * @param mode - Read mode: 'slice' (default) or 'indentation'
218
+ * @param indentation - Configuration for indentation mode
155
219
  * @returns Formatted file content with line numbers, or error message
156
220
  */
157
- read(filePath: string, offset?: number, limit?: number): MaybePromise<string>;
221
+ read(filePath: string, offset?: number, limit?: number, mode?: ReadMode, indentation?: IndentationOptions): MaybePromise<string>;
158
222
  /**
159
223
  * Structured search results or error string for invalid input.
160
224
  *
@@ -162,10 +226,19 @@ export interface BackendProtocol {
162
226
  *
163
227
  * @param pattern - Regex pattern to search for
164
228
  * @param path - Base path to search from (default: null)
165
- * @param glob - Optional glob pattern to filter files (e.g., "*.py")
229
+ * @param include - Optional glob pattern to filter files (e.g., "*.py")
166
230
  * @returns List of GrepMatch objects or error string for invalid regex
167
231
  */
168
- grepRaw(pattern: string, path?: string | null, glob?: string | null): MaybePromise<GrepMatch[] | string>;
232
+ grepRaw(pattern: string, path?: string | null, include?: string | null): MaybePromise<GrepMatch[] | string>;
233
+ /**
234
+ * Search file contents for a regex pattern, returning human-readable output.
235
+ *
236
+ * @param pattern - Regex pattern to search for
237
+ * @param path - Base path to search from (default: workspace root)
238
+ * @param include - Optional glob pattern to filter files (e.g., "*.js", "*.{ts,tsx}")
239
+ * @returns Human-readable output with matches grouped by file
240
+ */
241
+ grep(pattern: string, path?: string | null, include?: string | null): MaybePromise<string>;
169
242
  /**
170
243
  * Structured glob matching returning FileInfo objects.
171
244
  *
@@ -174,6 +247,14 @@ export interface BackendProtocol {
174
247
  * @returns List of FileInfo objects matching the pattern
175
248
  */
176
249
  globInfo(pattern: string, path?: string): MaybePromise<FileInfo[]>;
250
+ /**
251
+ * Find files matching a glob pattern, returning human-readable output.
252
+ *
253
+ * @param pattern - Glob pattern (e.g., `*.py`, `**\/*.ts`)
254
+ * @param path - Base path to search from (default: workspace root)
255
+ * @returns Human-readable output with matching file paths
256
+ */
257
+ glob(pattern: string, path?: string): MaybePromise<string>;
177
258
  /**
178
259
  * Create a new file.
179
260
  *
@@ -182,6 +263,14 @@ export interface BackendProtocol {
182
263
  * @returns WriteResult with error populated on failure
183
264
  */
184
265
  write(filePath: string, content: string): MaybePromise<WriteResult>;
266
+ /**
267
+ * Append content to a file. Creates the file if it doesn't exist.
268
+ *
269
+ * @param filePath - Absolute file path
270
+ * @param content - Content to append
271
+ * @returns WriteResult with error populated on failure
272
+ */
273
+ append(filePath: string, content: string): MaybePromise<WriteResult>;
185
274
  /**
186
275
  * Edit a file by replacing string occurrences.
187
276
  *
@@ -192,6 +281,16 @@ export interface BackendProtocol {
192
281
  * @returns EditResult with error, path, filesUpdate, and occurrences
193
282
  */
194
283
  edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean): MaybePromise<EditResult>;
284
+ /**
285
+ * Perform multiple sequential edits on a single file.
286
+ * All edits are applied sequentially, with each edit operating on the result of the previous edit.
287
+ * All edits must succeed for the operation to succeed (atomic).
288
+ *
289
+ * @param filePath - Absolute file path
290
+ * @param edits - Array of edit operations to perform sequentially
291
+ * @returns MultiEditResult with error, path, filesUpdate, and individual results
292
+ */
293
+ multiEdit(filePath: string, edits: EditOperation[]): MaybePromise<MultiEditResult>;
195
294
  /**
196
295
  * Upload multiple files.
197
296
  *
@@ -220,6 +319,25 @@ export interface SandboxBackendProtocol extends BackendProtocol {
220
319
  * @returns ExecuteResponse with combined output, exit code, and truncation flag
221
320
  */
222
321
  execute(command: string): MaybePromise<ExecuteResponse>;
322
+ /**
323
+ * Execute a command with line-by-line streaming output.
324
+ *
325
+ * When implemented, the middleware layer can push incremental output
326
+ * to the frontend as each line arrives, rather than waiting for the
327
+ * command to finish. Implementations MUST buffer partial lines and
328
+ * only invoke `onLine` with complete lines (LF-terminated).
329
+ *
330
+ * The returned `ExecuteResponse.output` contains the full collected
331
+ * output, identical to what `execute()` would return.
332
+ *
333
+ * Falls back to `execute()` + single `onLine` call in `BaseSandbox`
334
+ * when a concrete backend does not override this method.
335
+ *
336
+ * @param command - Full shell command string to execute
337
+ * @param onLine - Callback invoked once per complete output line
338
+ * @returns ExecuteResponse with combined output, exit code, and truncation flag
339
+ */
340
+ streamExecute?(command: string, onLine: (line: string) => void): MaybePromise<ExecuteResponse>;
223
341
  /** Unique identifier for the sandbox backend instance */
224
342
  readonly id: string;
225
343
  }
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * Requires Node.js 20+ on the sandbox host.
9
9
  */
10
- import type { EditResult, ExecuteResponse, FileDownloadResponse, FileInfo, FileUploadResponse, GrepMatch, MaybePromise, SandboxBackendProtocol, WriteResult } from "./protocol";
10
+ import type { EditOperation, EditResult, ExecuteResponse, FileDownloadResponse, FileInfo, FileUploadResponse, GrepMatch, IndentationOptions, MaybePromise, MultiEditResult, ReadMode, SandboxBackendProtocol, WriteResult } from "./protocol";
11
11
  /**
12
12
  * Base sandbox implementation with execute() as the only abstract method.
13
13
  *
@@ -18,6 +18,7 @@ import type { EditResult, ExecuteResponse, FileDownloadResponse, FileInfo, FileU
18
18
  * Requires Node.js 20+ on the sandbox host.
19
19
  */
20
20
  export declare abstract class BaseSandbox implements SandboxBackendProtocol {
21
+ workingDirectory: string;
21
22
  /** Unique identifier for the sandbox backend */
22
23
  abstract readonly id: string;
23
24
  /**
@@ -25,6 +26,7 @@ export declare abstract class BaseSandbox implements SandboxBackendProtocol {
25
26
  * This is the only method concrete implementations must provide.
26
27
  */
27
28
  abstract execute(command: string): MaybePromise<ExecuteResponse>;
29
+ streamExecute(command: string, onLine: (line: string) => void): Promise<ExecuteResponse>;
28
30
  /**
29
31
  * Upload multiple files to the sandbox.
30
32
  * Implementations must support partial success.
@@ -42,29 +44,60 @@ export declare abstract class BaseSandbox implements SandboxBackendProtocol {
42
44
  * @returns List of FileInfo objects for files and directories directly in the directory.
43
45
  */
44
46
  lsInfo(path: string): Promise<FileInfo[]>;
47
+ /**
48
+ * List directory contents recursively with depth control and pagination.
49
+ *
50
+ * @param dirPath - Absolute path to directory
51
+ * @param offset - 1-indexed entry number to start from (default: 1)
52
+ * @param limit - Maximum number of entries to return (default: 25)
53
+ * @param depth - Maximum depth to traverse (default: 2)
54
+ * @returns Human-readable directory tree with indentation
55
+ */
56
+ listDir(dirPath: string, offset?: number, limit?: number, depth?: number): Promise<string>;
45
57
  /**
46
58
  * Read file content with line numbers.
47
59
  *
48
60
  * @param filePath - Absolute file path
49
- * @param offset - Line offset to start reading from (0-indexed)
61
+ * @param offset - Line offset to start reading from (1-indexed)
50
62
  * @param limit - Maximum number of lines to read
63
+ * @param mode - Read mode: 'slice' (default) or 'indentation'
64
+ * @param indentation - Configuration for indentation mode
51
65
  * @returns Formatted file content with line numbers, or error message
52
66
  */
53
- read(filePath: string, offset?: number, limit?: number): Promise<string>;
67
+ read(filePath: string, offset?: number, limit?: number, mode?: ReadMode, indentation?: IndentationOptions): Promise<string>;
54
68
  /**
55
69
  * Structured search results or error string for invalid input.
56
70
  */
57
- grepRaw(pattern: string, path?: string, glob?: string | null): Promise<GrepMatch[] | string>;
71
+ grepRaw(pattern: string, path?: string, include?: string | null): Promise<GrepMatch[] | string>;
72
+ /**
73
+ * Search file contents for a regex pattern, returning human-readable output.
74
+ */
75
+ grep(pattern: string, path?: string, include?: string | null): Promise<string>;
58
76
  /**
59
77
  * Structured glob matching returning FileInfo objects.
60
78
  */
61
79
  globInfo(pattern: string, path?: string): Promise<FileInfo[]>;
80
+ /**
81
+ * Find files matching a glob pattern, returning human-readable output.
82
+ */
83
+ glob(pattern: string, path?: string): Promise<string>;
62
84
  /**
63
85
  * Create a new file with content.
64
86
  */
65
87
  write(filePath: string, content: string): Promise<WriteResult>;
88
+ private writeViaUpload;
89
+ /**
90
+ * Append content to a file. Creates the file if it doesn't exist.
91
+ */
92
+ append(filePath: string, content: string): Promise<WriteResult>;
66
93
  /**
67
94
  * Edit a file by replacing string occurrences.
68
95
  */
69
96
  edit(filePath: string, oldString: string, newString: string, replaceAll?: boolean): Promise<EditResult>;
97
+ /**
98
+ * Perform multiple sequential edits on a single file.
99
+ * All edits are applied sequentially, with each edit operating on the result of the previous edit.
100
+ * All edits must succeed for the operation to succeed (atomic).
101
+ */
102
+ multiEdit(filePath: string, edits: EditOperation[]): Promise<MultiEditResult>;
70
103
  }