@swoop111/dsh-tool-fs 0.2.0-rc.2 → 0.2.0-rc.2.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/lib/index.js +463 -463
- package/lib/types/completion.d.ts +41 -41
- package/lib/types/diff.d.ts +33 -33
- package/lib/types/edit.d.ts +44 -44
- package/lib/types/error.d.ts +18 -18
- package/lib/types/index.d.ts +18 -18
- package/lib/types/read-image.d.ts +56 -56
- package/lib/types/read-render.d.ts +89 -89
- package/lib/types/read-target.d.ts +24 -24
- package/lib/types/read.d.ts +89 -89
- package/lib/types/sandbox.d.ts +55 -55
- package/lib/types/session-cwd.d.ts +20 -20
- package/lib/types/structure.d.ts +46 -46
- package/lib/types/write.d.ts +37 -37
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -8,16 +8,16 @@ import { structuredPatch } from "diff";
|
|
|
8
8
|
import { basename, extname } from "node:path";
|
|
9
9
|
import { AttachmentError, AttachmentId } from "@deepseek-ai/dsh-attachment";
|
|
10
10
|
import { ESCALATION_TARGETS, approveEscalation, escalationHintMarker, sandboxDenialMarker, sandboxPermissionsDescription, validateEscalationArgs } from "@deepseek-ai/dsh-sandbox";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
19
|
const READ_MAX_LINE_LENGTH = 2e3;
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
const READ_MAX_BYTES = 50 * 1024;
|
|
22
22
|
function newAccumulator() {
|
|
23
23
|
return {
|
|
@@ -60,14 +60,14 @@ function finish(acc, request, displayPath) {
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
const OFFSET_OUT_OF_RANGE_RE = /^offset (-?\d+) is out of range for "(?:[^"\\]|\\"|\\\\)*" \((\d+) lines\)$/u;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
71
|
function parseOffsetOutOfRange(error) {
|
|
72
72
|
if (!(error instanceof FsError) || error.code !== "FS_NOT_FOUND") return void 0;
|
|
73
73
|
const match = error.message.match(OFFSET_OUT_OF_RANGE_RE);
|
|
@@ -79,15 +79,15 @@ function parseOffsetOutOfRange(error) {
|
|
|
79
79
|
totalLines
|
|
80
80
|
} : void 0;
|
|
81
81
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
91
|
async function buildWindow(chunks, request, displayPath) {
|
|
92
92
|
const acc = newAccumulator();
|
|
93
93
|
const lineBufferCap = request.maxLineLength + 1;
|
|
@@ -114,12 +114,12 @@ async function buildWindow(chunks, request, displayPath) {
|
|
|
114
114
|
if (lineBuffer.length > 0) flushLine();
|
|
115
115
|
return finish(acc, request, displayPath);
|
|
116
116
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
123
|
function formatReadOutput(displayPath, outcome) {
|
|
124
124
|
const endLine = outcome.lines.at(-1)?.number ?? Math.max(0, outcome.offset - 1);
|
|
125
125
|
let footer;
|
|
@@ -132,30 +132,30 @@ function formatReadOutput(displayPath, outcome) {
|
|
|
132
132
|
${outcome.lines.length > 0 ? `${outcome.lines.map((line) => `${line.number}: ${line.text}`).join("\n")}\n\n${footer}` : footer}${outcome.repairNote === void 0 ? "" : `\n(repair: ${outcome.repairNote})`}
|
|
133
133
|
</content>`;
|
|
134
134
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
141
|
function isFileTextLine(value) {
|
|
142
142
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
143
143
|
const { number, text } = value;
|
|
144
144
|
return typeof number === "number" && Number.isInteger(number) && number >= 1 && typeof text === "string";
|
|
145
145
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
159
|
function readMetaFromMeta(meta) {
|
|
160
160
|
if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return void 0;
|
|
161
161
|
const { path, offset, lines, totalLines, lang } = meta;
|
|
@@ -177,30 +177,30 @@ function readMetaFromMeta(meta) {
|
|
|
177
177
|
...lang === void 0 ? {} : { lang }
|
|
178
178
|
};
|
|
179
179
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
195
|
function sessionCwd(exec) {
|
|
196
196
|
return exec.agent?.session.header.cwd;
|
|
197
197
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
204
|
function sessionResolveOptions(exec, policyWorkspaceRoot) {
|
|
205
205
|
const cwd = policyWorkspaceRoot ?? sessionCwd(exec);
|
|
206
206
|
return {
|
|
@@ -208,19 +208,19 @@ function sessionResolveOptions(exec, policyWorkspaceRoot) {
|
|
|
208
208
|
signal: exec.signal
|
|
209
209
|
};
|
|
210
210
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
224
|
async function resolveRegularReadTarget(ctx, exec, requestedPath) {
|
|
225
225
|
const target = await ctx.fs.resolve(requestedPath, sessionResolveOptions(exec));
|
|
226
226
|
const info = await ctx.fs.stat(target, exec.signal);
|
|
@@ -234,18 +234,18 @@ async function resolveRegularReadTarget(ctx, exec, requestedPath) {
|
|
|
234
234
|
info
|
|
235
235
|
};
|
|
236
236
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
249
249
|
async function repairTargetPath(ctx, exec, requestedPath, knownPaths) {
|
|
250
250
|
const cwd = sessionCwd(exec);
|
|
251
251
|
return await repairMissingPath(requestedPath, {
|
|
@@ -258,7 +258,7 @@ async function repairTargetPath(ctx, exec, requestedPath, knownPaths) {
|
|
|
258
258
|
}
|
|
259
259
|
});
|
|
260
260
|
}
|
|
261
|
-
|
|
261
|
+
|
|
262
262
|
function fsPathExplorer(ctx, signal) {
|
|
263
263
|
return { listDir: async (directory) => {
|
|
264
264
|
const target = await ctx.fs.resolve(directory, { signal }).catch(() => void 0);
|
|
@@ -266,23 +266,23 @@ function fsPathExplorer(ctx, signal) {
|
|
|
266
266
|
return await ctx.fs.listDir(target, signal).then((entries) => entries.map((entry) => entry.name)).catch(() => void 0);
|
|
267
267
|
} };
|
|
268
268
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
|
|
286
286
|
function fenceLine(line) {
|
|
287
287
|
const rest = line.slice(line.length - line.trimStart().length);
|
|
288
288
|
if (line.length - rest.length > 3) return void 0;
|
|
@@ -298,12 +298,12 @@ function fenceLine(line) {
|
|
|
298
298
|
info
|
|
299
299
|
};
|
|
300
300
|
}
|
|
301
|
-
|
|
301
|
+
|
|
302
302
|
function closesFence(marker, line) {
|
|
303
303
|
const candidate = fenceLine(line);
|
|
304
304
|
return candidate !== void 0 && candidate.marker.slice(0, 1) === marker.slice(0, 1) && candidate.marker.length >= marker.length && candidate.info.trim().length === 0;
|
|
305
305
|
}
|
|
306
|
-
|
|
306
|
+
|
|
307
307
|
function codeBrackets(line, state) {
|
|
308
308
|
const found = [];
|
|
309
309
|
let quote;
|
|
@@ -344,15 +344,15 @@ function codeBrackets(line, state) {
|
|
|
344
344
|
}
|
|
345
345
|
return found;
|
|
346
346
|
}
|
|
347
|
-
|
|
347
|
+
|
|
348
348
|
function isOpener(ch) {
|
|
349
349
|
return ch === "(" || ch === "[" || ch === "{";
|
|
350
350
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
|
|
356
356
|
function scan(lines) {
|
|
357
357
|
const state = { inBlockComment: false };
|
|
358
358
|
const openBracketLines = [];
|
|
@@ -378,13 +378,13 @@ function scan(lines) {
|
|
|
378
378
|
openBracketLines
|
|
379
379
|
};
|
|
380
380
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
|
|
388
388
|
function detectOpenIndent(lines) {
|
|
389
389
|
const lastLine = lines.findLast((line) => line.trim().length > 0);
|
|
390
390
|
if (lastLine === void 0) return void 0;
|
|
@@ -407,11 +407,11 @@ function detectOpenIndent(lines) {
|
|
|
407
407
|
lineIndex: 0
|
|
408
408
|
};
|
|
409
409
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
415
415
|
function detectOpenTail(lines) {
|
|
416
416
|
const facts = scan(lines);
|
|
417
417
|
if (facts.fence !== void 0) return {
|
|
@@ -427,14 +427,14 @@ function detectOpenTail(lines) {
|
|
|
427
427
|
};
|
|
428
428
|
return detectOpenIndent(lines);
|
|
429
429
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
|
|
438
438
|
function detectOpenIndentHead(window, preceding) {
|
|
439
439
|
const firstContent = window.find((line) => line.trim().length > 0);
|
|
440
440
|
if (firstContent === void 0) return void 0;
|
|
@@ -448,15 +448,15 @@ function detectOpenIndentHead(window, preceding) {
|
|
|
448
448
|
};
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
460
|
function detectOpenHead(window, preceding) {
|
|
461
461
|
if (preceding.length === 0) return void 0;
|
|
462
462
|
const facts = scan(preceding);
|
|
@@ -471,12 +471,12 @@ function detectOpenHead(window, preceding) {
|
|
|
471
471
|
};
|
|
472
472
|
return detectOpenIndentHead(window, preceding);
|
|
473
473
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
|
|
480
480
|
function closureLength(construct, appended) {
|
|
481
481
|
if (construct.kind === "fence") {
|
|
482
482
|
for (const [index, line] of appended.entries()) if (closesFence(construct.marker, line)) return index + 1;
|
|
@@ -499,7 +499,7 @@ function closureLength(construct, appended) {
|
|
|
499
499
|
}
|
|
500
500
|
return cut + 1;
|
|
501
501
|
}
|
|
502
|
-
|
|
502
|
+
|
|
503
503
|
function indentWidth(line) {
|
|
504
504
|
let width = 0;
|
|
505
505
|
for (const ch of line) if (ch === " ") width += 1;
|
|
@@ -507,28 +507,28 @@ function indentWidth(line) {
|
|
|
507
507
|
else break;
|
|
508
508
|
return width;
|
|
509
509
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
532
|
async function completeWindow(lines, supply, tuning) {
|
|
533
533
|
if (lines.length === 0) return void 0;
|
|
534
534
|
let head = [];
|
|
@@ -563,35 +563,35 @@ async function completeWindow(lines, supply, tuning) {
|
|
|
563
563
|
...tailRule === void 0 ? {} : { tailRule }
|
|
564
564
|
};
|
|
565
565
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
|
|
574
574
|
const READ_LIMIT = 2e3;
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
|
|
579
579
|
const STREAM_MIN_SIZE = 10 * 1024 * 1024;
|
|
580
580
|
function parsePositiveInteger(value, name) {
|
|
581
581
|
if (!Number.isFinite(value) || !Number.isInteger(value) || value < 1) throw new Error(`${name} must be a positive integer`);
|
|
582
582
|
return value;
|
|
583
583
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
|
|
595
595
|
function parseReadArgs(args, maxLimit, repairEnabled = true) {
|
|
596
596
|
if (args.file_path.trim().length === 0) throw new Error("file_path must be a non-empty string");
|
|
597
597
|
const repair = repairEnabled ? repairReadArgs(args.offset, args.limit, maxLimit) : void 0;
|
|
@@ -606,20 +606,20 @@ function parseReadArgs(args, maxLimit, repairEnabled = true) {
|
|
|
606
606
|
...repair === void 0 ? {} : { repairs: repair.repairs }
|
|
607
607
|
};
|
|
608
608
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
|
|
613
613
|
function duplicateMessage(verdict) {
|
|
614
614
|
const { record, steps } = verdict;
|
|
615
615
|
return `duplicate read blocked: lines ${record.offset}-${record.endLine} unchanged, delivered ${steps} step${steps === 1 ? "" : "s"} ago; that content is still above. Use offset=${record.endLine + 1}, or force=true.`;
|
|
616
616
|
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
|
|
623
623
|
function applyReadTool(ctx, caps, repair) {
|
|
624
624
|
ctx.systemPrompt.section({
|
|
625
625
|
name: "tool:read",
|
|
@@ -848,17 +848,17 @@ function applyReadTool(ctx, caps, repair) {
|
|
|
848
848
|
}
|
|
849
849
|
}));
|
|
850
850
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
|
|
861
|
+
|
|
862
862
|
function computeHunkDiffs(path, before, after) {
|
|
863
863
|
const patch = structuredPatch("", "", before, after, void 0, void 0, { context: 3 });
|
|
864
864
|
const diffs = [];
|
|
@@ -883,63 +883,63 @@ function computeHunkDiffs(path, before, after) {
|
|
|
883
883
|
}
|
|
884
884
|
return diffs;
|
|
885
885
|
}
|
|
886
|
-
|
|
886
|
+
|
|
887
887
|
function isFileDiff(value) {
|
|
888
888
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
889
889
|
const { path, oldText, newText } = value;
|
|
890
890
|
return typeof path === "string" && (oldText === null || typeof oldText === "string") && typeof newText === "string";
|
|
891
891
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
|
|
898
898
|
function diffsFromMeta(meta) {
|
|
899
899
|
if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return void 0;
|
|
900
900
|
const diffs = meta.diffs;
|
|
901
901
|
if (!Array.isArray(diffs) || diffs.length === 0 || !diffs.every(isFileDiff)) return void 0;
|
|
902
902
|
return diffs;
|
|
903
903
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
|
|
923
923
|
function remediateFsError(error, displayPath) {
|
|
924
924
|
if (!(error instanceof FsError)) return error;
|
|
925
925
|
if (error.code === "FS_NOT_OBSERVED") return new FsError(`cannot modify "${displayPath}": file has not been read — read the file, then retry`, error.code, { cause: error });
|
|
926
926
|
if (error.code === "FS_STALE_VERSION") return new FsError(`${error.message} — re-read the file, then retry`, error.code, { cause: error });
|
|
927
927
|
return error;
|
|
928
928
|
}
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
|
|
943
943
|
function parseWriteArgs(args) {
|
|
944
944
|
if (args.file_path.trim().length === 0) throw new Error("file_path must be a non-empty string");
|
|
945
945
|
return {
|
|
@@ -947,13 +947,13 @@ function parseWriteArgs(args) {
|
|
|
947
947
|
content: args.content
|
|
948
948
|
};
|
|
949
949
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
|
|
957
957
|
function formatWriteOutput(displayPath, outcome, hint) {
|
|
958
958
|
return `<path>${displayPath}</path>
|
|
959
959
|
<type>file</type>
|
|
@@ -961,12 +961,12 @@ function formatWriteOutput(displayPath, outcome, hint) {
|
|
|
961
961
|
${outcome.operation === "create" ? "Created" : "Updated"} file${hint === void 0 ? "" : `\n(hint: ${hint})`}
|
|
962
962
|
</content>`;
|
|
963
963
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
|
|
970
970
|
function applyWriteTool(ctx, sandbox, hints) {
|
|
971
971
|
ctx.systemPrompt.section({
|
|
972
972
|
name: "tool:write",
|
|
@@ -1082,37 +1082,37 @@ function applyWriteTool(ctx, sandbox, hints) {
|
|
|
1082
1082
|
}
|
|
1083
1083
|
}));
|
|
1084
1084
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
1103
|
const ABSENT_TARGET_CODES = new Set([
|
|
1104
1104
|
"FS_NOT_FOUND",
|
|
1105
1105
|
"FS_STALE_VERSION",
|
|
1106
1106
|
"FS_EDIT_NOT_FOUND",
|
|
1107
1107
|
"FS_NOT_OBSERVED"
|
|
1108
1108
|
]);
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
1116
|
function parseEditArgs(args) {
|
|
1117
1117
|
if (args.file_path.trim().length === 0) throw new Error("file_path must be a non-empty string");
|
|
1118
1118
|
if (args.old_string.length === 0) throw new Error("old_string must be a non-empty string");
|
|
@@ -1124,32 +1124,32 @@ function parseEditArgs(args) {
|
|
|
1124
1124
|
replaceAll: args.replace_all ?? false
|
|
1125
1125
|
};
|
|
1126
1126
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1127
|
+
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
1133
|
function formatEditOutput(displayPath, replaceAll) {
|
|
1134
1134
|
return replaceAll ? `The file ${displayPath} has been updated. All occurrences were successfully replaced.` : `The file ${displayPath} has been updated successfully.`;
|
|
1135
1135
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
1153
|
async function repairEditFailure(ctx, sandbox, repair, target, input, intent, exec, sandboxPolicy, error) {
|
|
1154
1154
|
const mapped = sandbox.mapError(error, sandboxPolicy);
|
|
1155
1155
|
if (!repair.enabled || input.replaceAll || !(mapped instanceof FsError) || mapped.code !== "FS_EDIT_NOT_FOUND" && mapped.code !== "FS_AMBIGUOUS_EDIT") throw remediateFsError(mapped, target.displayPath);
|
|
@@ -1178,12 +1178,12 @@ async function repairEditFailure(ctx, sandbox, repair, target, input, intent, ex
|
|
|
1178
1178
|
if (hints.length === 0 || !(base instanceof FsError)) throw base;
|
|
1179
1179
|
throw new FsError(`${base.message} ${hints.join(" ")}`, base.code, { cause: base });
|
|
1180
1180
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1181
|
+
|
|
1182
|
+
|
|
1183
|
+
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
|
|
1187
1187
|
function applyEditTool(ctx, sandbox, repair) {
|
|
1188
1188
|
ctx.systemPrompt.section({
|
|
1189
1189
|
name: "tool:edit",
|
|
@@ -1316,21 +1316,21 @@ function applyEditTool(ctx, sandbox, repair) {
|
|
|
1316
1316
|
}
|
|
1317
1317
|
}));
|
|
1318
1318
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1319
|
+
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
|
|
1334
1334
|
const IMAGE_EXTENSIONS = {
|
|
1335
1335
|
".png": "image/png",
|
|
1336
1336
|
".jpg": "image/jpeg",
|
|
@@ -1362,11 +1362,11 @@ function matchesAscii(data, offset, value) {
|
|
|
1362
1362
|
for (let index = 0; index < value.length; index += 1) if (data[offset + index] !== value.charCodeAt(index)) return false;
|
|
1363
1363
|
return true;
|
|
1364
1364
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
|
|
1369
|
+
|
|
1370
1370
|
function sniffImageMediaType(data) {
|
|
1371
1371
|
if (matchesBytes(data, 0, PNG_SIGNATURE)) return "image/png";
|
|
1372
1372
|
if (matchesBytes(data, 0, JPEG_SIGNATURE)) return "image/jpeg";
|
|
@@ -1421,22 +1421,22 @@ const IMAGE_VALUE_SCHEMA = {
|
|
|
1421
1421
|
}
|
|
1422
1422
|
}
|
|
1423
1423
|
};
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1424
|
+
|
|
1425
|
+
|
|
1426
|
+
|
|
1427
|
+
|
|
1428
|
+
|
|
1429
1429
|
function imageMediaTypeForPath(filePath) {
|
|
1430
1430
|
return IMAGE_EXTENSIONS[extname(filePath).toLowerCase()];
|
|
1431
1431
|
}
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1432
|
+
|
|
1433
|
+
|
|
1434
|
+
|
|
1435
|
+
|
|
1436
|
+
|
|
1437
|
+
|
|
1438
|
+
|
|
1439
|
+
|
|
1440
1440
|
async function assertImageCapableRoute(ctx, exec, requestedPath) {
|
|
1441
1441
|
const routed = exec.agent?.session.requestHeader()?.config;
|
|
1442
1442
|
const provider = routed?.provider ?? exec.agent?.options.provider;
|
|
@@ -1446,16 +1446,16 @@ async function assertImageCapableRoute(ctx, exec, requestedPath) {
|
|
|
1446
1446
|
const active = await llm.resolveModelInfo(provider, model, exec.signal);
|
|
1447
1447
|
if (active.inputModalities === void 0 || !active.inputModalities.includes("image")) throw new Error(`cannot read "${requestedPath}" as an image: model "${model}" does not declare image input; switch to an image-capable model to read images`);
|
|
1448
1448
|
}
|
|
1449
|
-
|
|
1449
|
+
|
|
1450
1450
|
function assertDeploymentAccepts(attachments, mediaType, displayPath) {
|
|
1451
1451
|
if (!attachments.imageLimits.mediaTypes.includes(mediaType)) throw new Error(`cannot read "${displayPath}": ${mediaType} images are not accepted by this deployment`);
|
|
1452
1452
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1453
|
+
|
|
1454
|
+
|
|
1455
|
+
|
|
1456
|
+
|
|
1457
|
+
|
|
1458
|
+
|
|
1459
1459
|
function imageRefFromValue(image) {
|
|
1460
1460
|
return {
|
|
1461
1461
|
attachmentId: AttachmentId(image.attachmentId),
|
|
@@ -1467,14 +1467,14 @@ function imageRefFromValue(image) {
|
|
|
1467
1467
|
...image.originalDimensions === void 0 ? {} : { originalDimensions: { ...image.originalDimensions } }
|
|
1468
1468
|
};
|
|
1469
1469
|
}
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
|
|
1473
|
+
|
|
1474
|
+
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+
|
|
1478
1478
|
function formatImageReadOutput(displayPath, image) {
|
|
1479
1479
|
let scaled = "";
|
|
1480
1480
|
if (image.originalDimensions !== void 0) {
|
|
@@ -1489,11 +1489,11 @@ function formatImageReadOutput(displayPath, image) {
|
|
|
1489
1489
|
${image.mediaType} image, ${image.width}x${image.height} px, ${image.bytes} bytes${scaled}
|
|
1490
1490
|
</content>`;
|
|
1491
1491
|
}
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1492
|
+
|
|
1493
|
+
|
|
1494
|
+
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
1497
|
function imageReadContent(value) {
|
|
1498
1498
|
return [{
|
|
1499
1499
|
type: "text",
|
|
@@ -1503,15 +1503,15 @@ function imageReadContent(value) {
|
|
|
1503
1503
|
attachment: imageRefFromValue(value.image)
|
|
1504
1504
|
}];
|
|
1505
1505
|
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1506
|
+
|
|
1507
|
+
|
|
1508
|
+
|
|
1509
|
+
|
|
1510
|
+
|
|
1511
|
+
|
|
1512
|
+
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
1515
|
function applyReadImageTool(ctx) {
|
|
1516
1516
|
ctx.tools.register(defineTool({
|
|
1517
1517
|
name: "read_image",
|
|
@@ -1597,29 +1597,29 @@ function applyReadImageTool(ctx) {
|
|
|
1597
1597
|
}
|
|
1598
1598
|
}));
|
|
1599
1599
|
}
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
|
|
1605
|
+
|
|
1606
|
+
|
|
1607
|
+
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
|
|
1611
|
+
|
|
1612
|
+
|
|
1613
|
+
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
|
|
1617
|
+
|
|
1618
1618
|
var FsSandboxController = class {
|
|
1619
1619
|
ctx;
|
|
1620
|
-
|
|
1620
|
+
|
|
1621
1621
|
escalationModes;
|
|
1622
|
-
|
|
1622
|
+
|
|
1623
1623
|
policy;
|
|
1624
1624
|
constructor(ctx) {
|
|
1625
1625
|
this.ctx = ctx;
|
|
@@ -1628,13 +1628,13 @@ var FsSandboxController = class {
|
|
|
1628
1628
|
this.policy = defaultMode === void 0 ? void 0 : ctx.get("sandboxPolicy");
|
|
1629
1629
|
if (defaultMode !== void 0 && this.policy === void 0) throw new Error("tool-fs: the mounted filesystem confines but ctx.sandboxPolicy is missing");
|
|
1630
1630
|
}
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1631
|
+
|
|
1632
|
+
|
|
1633
|
+
|
|
1634
|
+
|
|
1635
|
+
|
|
1636
|
+
|
|
1637
|
+
|
|
1638
1638
|
schemaFields() {
|
|
1639
1639
|
return {
|
|
1640
1640
|
sandbox_permissions: {
|
|
@@ -1648,19 +1648,19 @@ var FsSandboxController = class {
|
|
|
1648
1648
|
}
|
|
1649
1649
|
};
|
|
1650
1650
|
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1651
|
+
|
|
1652
|
+
|
|
1653
|
+
|
|
1654
|
+
|
|
1655
|
+
|
|
1656
|
+
|
|
1657
|
+
|
|
1658
|
+
|
|
1659
|
+
|
|
1660
|
+
|
|
1661
|
+
|
|
1662
|
+
|
|
1663
|
+
|
|
1664
1664
|
async resolvePolicy(toolName, args, exec) {
|
|
1665
1665
|
validateEscalationArgs(args.sandbox_permissions, args.justification);
|
|
1666
1666
|
const standingPolicy = this.policy?.resolve({ ...exec.agent ? { session: exec.agent.session } : {} });
|
|
@@ -1684,45 +1684,45 @@ var FsSandboxController = class {
|
|
|
1684
1684
|
mode: approvedMode
|
|
1685
1685
|
};
|
|
1686
1686
|
}
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1687
|
+
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
|
|
1698
|
+
|
|
1699
|
+
|
|
1700
|
+
|
|
1701
1701
|
mapError(error, policy) {
|
|
1702
1702
|
if (!(error instanceof FsError) || error.code !== "FS_SANDBOX_DENIED") return error;
|
|
1703
1703
|
const mode = policy.mode;
|
|
1704
1704
|
return new FsError(`${sandboxDenialMarker(mode)}\n${escalationHintMarker("operation")}`, "FS_SANDBOX_DENIED", { cause: error });
|
|
1705
1705
|
}
|
|
1706
1706
|
};
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1707
|
+
|
|
1708
|
+
|
|
1709
|
+
|
|
1710
|
+
|
|
1711
|
+
|
|
1712
|
+
|
|
1713
|
+
|
|
1714
|
+
|
|
1715
|
+
|
|
1716
1716
|
const name = "tool-fs";
|
|
1717
|
-
|
|
1717
|
+
|
|
1718
1718
|
const inject = [
|
|
1719
1719
|
"tools",
|
|
1720
1720
|
"fs",
|
|
1721
1721
|
"systemPrompt"
|
|
1722
1722
|
];
|
|
1723
|
-
|
|
1723
|
+
|
|
1724
1724
|
const DEFAULT_DUPLICATE_STEPS = 4;
|
|
1725
|
-
|
|
1725
|
+
|
|
1726
1726
|
const DEFAULT_COMPLETION_MAX_LINES = 40;
|
|
1727
1727
|
const Config = z.object({
|
|
1728
1728
|
readLimit: z.number().default(READ_LIMIT),
|
|
@@ -1767,11 +1767,11 @@ const Config = z.object({
|
|
|
1767
1767
|
}),
|
|
1768
1768
|
writeRepair: z.object({ pathHint: z.boolean().default(true) }).default({ pathHint: true })
|
|
1769
1769
|
});
|
|
1770
|
-
|
|
1770
|
+
|
|
1771
1771
|
function assertPositiveInteger(name, value) {
|
|
1772
1772
|
if (!Number.isInteger(value) || value < 1) throw new Error(`tool-fs: ${name} must be a positive integer`);
|
|
1773
1773
|
}
|
|
1774
|
-
|
|
1774
|
+
|
|
1775
1775
|
function apply(ctx, config) {
|
|
1776
1776
|
const resolved = config;
|
|
1777
1777
|
assertPositiveInteger("readLimit", resolved.readLimit);
|
|
@@ -1834,5 +1834,5 @@ function apply(ctx, config) {
|
|
|
1834
1834
|
priorPaths: (session, limit) => sessionPaths.priorPaths(session, limit)
|
|
1835
1835
|
});
|
|
1836
1836
|
}
|
|
1837
|
-
|
|
1837
|
+
|
|
1838
1838
|
export { Config, apply, inject, name };
|