@robota-sdk/agent-tools 3.0.0-beta.58 → 3.0.0-beta.59
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/README.md +1 -1
- package/dist/node/index.cjs +18 -0
- package/dist/node/index.js +24 -6
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -59,7 +59,7 @@ const agent = new Robota({
|
|
|
59
59
|
|
|
60
60
|
## Edit and Write Safety
|
|
61
61
|
|
|
62
|
-
Recent file tool updates keep write/edit behavior atomic and make Edit tool results easier for higher layers to display. The Edit tool returns line metadata for changed regions, allowing the CLI to render concise context hunks instead of dumping full files or opaque summaries.
|
|
62
|
+
Recent file tool updates keep write/edit behavior atomic and make Edit tool results easier for higher layers to display. Atomic replacements preserve existing target mode bits, so executable scripts remain executable after Write or Edit updates. The Edit tool returns line metadata for changed regions, allowing the CLI to render concise context hunks instead of dumping full files or opaque summaries.
|
|
63
63
|
|
|
64
64
|
## Tool Infrastructure
|
|
65
65
|
|
package/dist/node/index.cjs
CHANGED
|
@@ -1038,18 +1038,36 @@ var import_node_crypto = require("crypto");
|
|
|
1038
1038
|
var import_promises2 = require("fs/promises");
|
|
1039
1039
|
var import_node_path = require("path");
|
|
1040
1040
|
var TEMP_RANDOM_BYTES = 6;
|
|
1041
|
+
var PRESERVED_MODE_BITS = 4095;
|
|
1042
|
+
var MISSING_FILE_ERROR_CODE = "ENOENT";
|
|
1041
1043
|
function createTempFilePath(filePath) {
|
|
1042
1044
|
const dir = (0, import_node_path.dirname)(filePath);
|
|
1043
1045
|
const name = (0, import_node_path.basename)(filePath);
|
|
1044
1046
|
const suffix = (0, import_node_crypto.randomBytes)(TEMP_RANDOM_BYTES).toString("hex");
|
|
1045
1047
|
return (0, import_node_path.join)(dir, `.${name}.robota-tmp-${process.pid}-${Date.now()}-${suffix}`);
|
|
1046
1048
|
}
|
|
1049
|
+
async function readExistingMode(filePath) {
|
|
1050
|
+
try {
|
|
1051
|
+
const fileStats = await (0, import_promises2.stat)(filePath);
|
|
1052
|
+
return fileStats.mode & PRESERVED_MODE_BITS;
|
|
1053
|
+
} catch (error) {
|
|
1054
|
+
if (error instanceof Error && hasErrorCode(error, MISSING_FILE_ERROR_CODE)) return void 0;
|
|
1055
|
+
throw error;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
function hasErrorCode(error, code) {
|
|
1059
|
+
return "code" in error && error.code === code;
|
|
1060
|
+
}
|
|
1047
1061
|
async function atomicWriteUtf8File(filePath, content) {
|
|
1048
1062
|
const dir = (0, import_node_path.dirname)(filePath);
|
|
1049
1063
|
await (0, import_promises2.mkdir)(dir, { recursive: true });
|
|
1064
|
+
const existingMode = await readExistingMode(filePath);
|
|
1050
1065
|
const tempFilePath = createTempFilePath(filePath);
|
|
1051
1066
|
try {
|
|
1052
1067
|
await (0, import_promises2.writeFile)(tempFilePath, content, "utf8");
|
|
1068
|
+
if (existingMode !== void 0) {
|
|
1069
|
+
await (0, import_promises2.chmod)(tempFilePath, existingMode);
|
|
1070
|
+
}
|
|
1053
1071
|
await (0, import_promises2.rename)(tempFilePath, filePath);
|
|
1054
1072
|
} catch (error) {
|
|
1055
1073
|
await (0, import_promises2.rm)(tempFilePath, { force: true }).catch(() => void 0);
|
package/dist/node/index.js
CHANGED
|
@@ -985,21 +985,39 @@ import { z as z3 } from "zod";
|
|
|
985
985
|
|
|
986
986
|
// src/builtins/atomic-file-write.ts
|
|
987
987
|
import { randomBytes } from "crypto";
|
|
988
|
-
import { mkdir, rename, rm, writeFile } from "fs/promises";
|
|
988
|
+
import { chmod, mkdir, rename, rm, stat as stat2, writeFile } from "fs/promises";
|
|
989
989
|
import { basename, dirname, join } from "path";
|
|
990
990
|
var TEMP_RANDOM_BYTES = 6;
|
|
991
|
+
var PRESERVED_MODE_BITS = 4095;
|
|
992
|
+
var MISSING_FILE_ERROR_CODE = "ENOENT";
|
|
991
993
|
function createTempFilePath(filePath) {
|
|
992
994
|
const dir = dirname(filePath);
|
|
993
995
|
const name = basename(filePath);
|
|
994
996
|
const suffix = randomBytes(TEMP_RANDOM_BYTES).toString("hex");
|
|
995
997
|
return join(dir, `.${name}.robota-tmp-${process.pid}-${Date.now()}-${suffix}`);
|
|
996
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
|
+
}
|
|
997
1011
|
async function atomicWriteUtf8File(filePath, content) {
|
|
998
1012
|
const dir = dirname(filePath);
|
|
999
1013
|
await mkdir(dir, { recursive: true });
|
|
1014
|
+
const existingMode = await readExistingMode(filePath);
|
|
1000
1015
|
const tempFilePath = createTempFilePath(filePath);
|
|
1001
1016
|
try {
|
|
1002
1017
|
await writeFile(tempFilePath, content, "utf8");
|
|
1018
|
+
if (existingMode !== void 0) {
|
|
1019
|
+
await chmod(tempFilePath, existingMode);
|
|
1020
|
+
}
|
|
1003
1021
|
await rename(tempFilePath, filePath);
|
|
1004
1022
|
} catch (error) {
|
|
1005
1023
|
await rm(tempFilePath, { force: true }).catch(() => void 0);
|
|
@@ -1115,7 +1133,7 @@ var editTool = createZodFunctionTool(
|
|
|
1115
1133
|
);
|
|
1116
1134
|
|
|
1117
1135
|
// src/builtins/glob-tool.ts
|
|
1118
|
-
import { stat as
|
|
1136
|
+
import { stat as stat3 } from "fs/promises";
|
|
1119
1137
|
import { resolve } from "path";
|
|
1120
1138
|
import fg from "fast-glob";
|
|
1121
1139
|
import { z as z5 } from "zod";
|
|
@@ -1152,7 +1170,7 @@ async function globFileTool(args) {
|
|
|
1152
1170
|
matches.map(async (p) => {
|
|
1153
1171
|
const absPath = resolve(cwd, p);
|
|
1154
1172
|
try {
|
|
1155
|
-
const s = await
|
|
1173
|
+
const s = await stat3(absPath);
|
|
1156
1174
|
return { path: p, mtime: s.mtimeMs };
|
|
1157
1175
|
} catch {
|
|
1158
1176
|
return { path: p, mtime: 0 };
|
|
@@ -1187,7 +1205,7 @@ var globTool = createZodFunctionTool(
|
|
|
1187
1205
|
);
|
|
1188
1206
|
|
|
1189
1207
|
// src/builtins/grep-tool.ts
|
|
1190
|
-
import { readFile as readFile3, readdir, stat as
|
|
1208
|
+
import { readFile as readFile3, readdir, stat as stat4 } from "fs/promises";
|
|
1191
1209
|
import { join as join2, resolve as resolve2 } from "path";
|
|
1192
1210
|
import { z as z6 } from "zod";
|
|
1193
1211
|
var GrepSchema = z6.object({
|
|
@@ -1225,7 +1243,7 @@ async function collectFiles(dirPath, glob) {
|
|
|
1225
1243
|
const fullPath = join2(current, name);
|
|
1226
1244
|
let fileStat;
|
|
1227
1245
|
try {
|
|
1228
|
-
fileStat = await
|
|
1246
|
+
fileStat = await stat4(fullPath);
|
|
1229
1247
|
} catch {
|
|
1230
1248
|
continue;
|
|
1231
1249
|
}
|
|
@@ -1295,7 +1313,7 @@ async function grepFileTool(args) {
|
|
|
1295
1313
|
}
|
|
1296
1314
|
let targetStat;
|
|
1297
1315
|
try {
|
|
1298
|
-
targetStat = await
|
|
1316
|
+
targetStat = await stat4(targetPath);
|
|
1299
1317
|
} catch {
|
|
1300
1318
|
const result2 = {
|
|
1301
1319
|
success: false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robota-sdk/agent-tools",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.59",
|
|
4
4
|
"description": "Tool registry and implementations for Robota SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/node/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"zod": "^3.24.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@robota-sdk/agent-core": "3.0.0-beta.
|
|
37
|
+
"@robota-sdk/agent-core": "3.0.0-beta.59"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"openapi-types": "^12.1.3",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"tsup": "^8.0.1",
|
|
43
43
|
"typescript": "^5.3.3",
|
|
44
44
|
"vitest": "^1.6.1",
|
|
45
|
-
"@robota-sdk/agent-core": "3.0.0-beta.
|
|
45
|
+
"@robota-sdk/agent-core": "3.0.0-beta.59"
|
|
46
46
|
},
|
|
47
47
|
"license": "MIT",
|
|
48
48
|
"publishConfig": {
|