@agent-api/sdk 1.3.0 → 1.3.2
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/CHANGELOG.md +13 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/local/core.d.ts +1 -0
- package/dist/local/core.js +22 -1
- package/dist/local/tools.d.ts +1 -0
- package/dist/local/tools.js +38 -2
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/dist/volume-assets.d.ts +3 -0
- package/dist/volume-assets.js +37 -0
- package/dist-cjs/index.js +5 -1
- package/dist-cjs/local/core.js +22 -1
- package/dist-cjs/local/tools.js +38 -2
- package/dist-cjs/version.js +1 -1
- package/dist-cjs/volume-assets.js +42 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog — @agent-api/sdk
|
|
2
2
|
|
|
3
|
+
## 1.3.2
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added volume image asset helpers for normalizing private volume paths and checking supported image paths/content types.
|
|
8
|
+
|
|
9
|
+
## 1.3.1
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Made `local_workdir` grep behave like familiar grep: `path` may be omitted, a file path, or a directory subtree.
|
|
14
|
+
- Model-facing `local_workdir` execution errors now return structured `{ ok: false, error }` tool results instead of aborting agent runs.
|
|
15
|
+
|
|
3
16
|
## 1.3.0
|
|
4
17
|
|
|
5
18
|
### Added
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,6 @@ export * from "./types/index.js";
|
|
|
6
6
|
export { functionCallOutputInput, pendingFunctionCalls, runLocalFunctionHandlers, } from "./local-functions.js";
|
|
7
7
|
export type { LocalFunctionHandler, LocalFunctionHandlers } from "./local-functions.js";
|
|
8
8
|
export { mergeTools, publicToolToRequestTool, resolvePresetTools, resolvePresetToolsFromCatalog, } from "./preset-tools.js";
|
|
9
|
+
export { isSupportedVolumeImageContentType, isSupportedVolumeImagePath, normalizeVolumeAssetPath, } from "./volume-assets.js";
|
|
9
10
|
export type { PresetToolCatalogClient, ResolvePresetToolsOptions, ResolvePresetToolsResult, UnknownPresetToolBehavior, } from "./preset-tools.js";
|
|
10
11
|
export { AuthResource, DeviceAuthFlowError, browserAuthSessionExpiresWithin } from "./resources/auth.js";
|
package/dist/index.js
CHANGED
|
@@ -4,4 +4,5 @@ export { APIError, APIConnectionError, APIStatusError, AuthenticationError, BadR
|
|
|
4
4
|
export * from "./types/index.js";
|
|
5
5
|
export { functionCallOutputInput, pendingFunctionCalls, runLocalFunctionHandlers, } from "./local-functions.js";
|
|
6
6
|
export { mergeTools, publicToolToRequestTool, resolvePresetTools, resolvePresetToolsFromCatalog, } from "./preset-tools.js";
|
|
7
|
+
export { isSupportedVolumeImageContentType, isSupportedVolumeImagePath, normalizeVolumeAssetPath, } from "./volume-assets.js";
|
|
7
8
|
export { AuthResource, DeviceAuthFlowError, browserAuthSessionExpiresWithin } from "./resources/auth.js";
|
package/dist/local/core.d.ts
CHANGED
|
@@ -309,6 +309,7 @@ export declare class LocalFileStore {
|
|
|
309
309
|
readLines(relativePath: string, params: LocalReadLinesParams): Promise<LocalFileLines>;
|
|
310
310
|
patchLines(relativePath: string, params: LocalPatchLinesParams): Promise<LocalFileLinesPatch>;
|
|
311
311
|
grep(params: LocalGrepParams): Promise<LocalGrepResponse>;
|
|
312
|
+
private grepCandidates;
|
|
312
313
|
summarize(params?: LocalSummarizeParams): Promise<LocalSummary>;
|
|
313
314
|
private walk;
|
|
314
315
|
}
|
package/dist/local/core.js
CHANGED
|
@@ -310,7 +310,7 @@ export class LocalFileStore {
|
|
|
310
310
|
const maxFiles = positiveInt(params.maxFiles, 500);
|
|
311
311
|
const maxBytesPerFile = positiveInt(params.maxBytesPerFile, 512 * 1024);
|
|
312
312
|
const maxLineLength = positiveInt(params.maxLineLength, 500);
|
|
313
|
-
const stats = await this.
|
|
313
|
+
const stats = await this.grepCandidates(params.path ?? ".", params.ignore);
|
|
314
314
|
const matches = [];
|
|
315
315
|
let filesScanned = 0;
|
|
316
316
|
let scanTruncated = false;
|
|
@@ -348,6 +348,27 @@ export class LocalFileStore {
|
|
|
348
348
|
}
|
|
349
349
|
return { object: "list", matches, files_scanned: filesScanned, scan_truncated: scanTruncated };
|
|
350
350
|
}
|
|
351
|
+
async grepCandidates(relativePath, ignore) {
|
|
352
|
+
const fullPath = this.resolvePath(relativePath);
|
|
353
|
+
const info = await stat(fullPath);
|
|
354
|
+
const portablePath = toPortablePath(path.relative(this.root, fullPath)) || ".";
|
|
355
|
+
if (ignored(portablePath, ignore)) {
|
|
356
|
+
return [];
|
|
357
|
+
}
|
|
358
|
+
if (info.isFile()) {
|
|
359
|
+
return [{
|
|
360
|
+
path: portablePath,
|
|
361
|
+
fullPath,
|
|
362
|
+
type: "file",
|
|
363
|
+
size: info.size,
|
|
364
|
+
modifiedAt: info.mtime,
|
|
365
|
+
}];
|
|
366
|
+
}
|
|
367
|
+
if (info.isDirectory()) {
|
|
368
|
+
return await this.list(relativePath, { recursive: true, ignore });
|
|
369
|
+
}
|
|
370
|
+
return [];
|
|
371
|
+
}
|
|
351
372
|
async summarize(params = {}) {
|
|
352
373
|
const maxFiles = positiveInt(params.maxFiles, 2000);
|
|
353
374
|
const maxPreviews = positiveInt(params.maxPreviews, 20);
|
package/dist/local/tools.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export declare class LocalWorkdirDriver {
|
|
|
23
23
|
readonly accessMode: LocalWorkdirAccessMode;
|
|
24
24
|
constructor(workdir: LocalWorkdir, options?: LocalWorkdirDriverOptions);
|
|
25
25
|
dispatch(args: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
26
|
+
private dispatchUnsafe;
|
|
26
27
|
requiresApproval(args: Record<string, unknown>): boolean;
|
|
27
28
|
private dispatchApplyEdits;
|
|
28
29
|
private dispatchWrite;
|
package/dist/local/tools.js
CHANGED
|
@@ -7,6 +7,15 @@ export class LocalWorkdirDriver {
|
|
|
7
7
|
this.accessMode = options.accessMode ?? "approval";
|
|
8
8
|
}
|
|
9
9
|
async dispatch(args) {
|
|
10
|
+
const action = safeWorkdirAction(args);
|
|
11
|
+
try {
|
|
12
|
+
return await this.dispatchUnsafe(args);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
return localToolErrorResult(action, error);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async dispatchUnsafe(args) {
|
|
10
19
|
const action = workdirAction(args);
|
|
11
20
|
switch (action) {
|
|
12
21
|
case "summarize":
|
|
@@ -45,7 +54,8 @@ export class LocalWorkdirDriver {
|
|
|
45
54
|
if (this.accessMode === "full") {
|
|
46
55
|
return false;
|
|
47
56
|
}
|
|
48
|
-
|
|
57
|
+
const action = safeWorkdirAction(args);
|
|
58
|
+
return action !== "unknown" && mutatingLocalWorkdirActions.has(action);
|
|
49
59
|
}
|
|
50
60
|
async dispatchApplyEdits(args) {
|
|
51
61
|
const edits = editsArg(args);
|
|
@@ -129,6 +139,7 @@ const mutatingLocalWorkdirActions = new Set([
|
|
|
129
139
|
const localWorkdirToolDescription = [
|
|
130
140
|
"Inspect and modify the selected local workdir through one model-facing primitive.",
|
|
131
141
|
"Use action=list/search/grep/summarize/context to discover files, read/read_lines for file content, preview_edits before edits, and apply_edits/write/mkdir/delete only when mutation is intended.",
|
|
142
|
+
"grep searches file contents for a literal substring; path may be omitted, a file path, or a directory subtree.",
|
|
132
143
|
"In approval mode, mutating actions return requires_approval with a safe preview instead of changing files. In full mode, mutating actions execute immediately.",
|
|
133
144
|
"Paths are relative to the selected local workdir; never use absolute paths.",
|
|
134
145
|
].join(" ");
|
|
@@ -139,7 +150,7 @@ function localWorkdirToolParameters() {
|
|
|
139
150
|
enum: localWorkdirActions,
|
|
140
151
|
description: "Workdir operation. Prefer summarize/list/search/grep before reading or editing. Prefer read_lines and apply_edits for source changes.",
|
|
141
152
|
},
|
|
142
|
-
path: stringSchema("Relative path. File path for read/write/delete/edit actions
|
|
153
|
+
path: stringSchema("Relative path. File path for read/write/delete/edit actions. For grep, path may be a file or a directory subtree. For list/search/summarize/context/snapshot, path is a directory base."),
|
|
143
154
|
query: stringSchema("Path/name query for search, or optional context query."),
|
|
144
155
|
pattern: stringSchema("Literal text pattern for grep."),
|
|
145
156
|
content: stringSchema("Text content for write."),
|
|
@@ -182,6 +193,10 @@ function workdirAction(args) {
|
|
|
182
193
|
}
|
|
183
194
|
return value;
|
|
184
195
|
}
|
|
196
|
+
function safeWorkdirAction(args) {
|
|
197
|
+
const value = typeof args.action === "string" ? args.action.trim().toLowerCase() : "";
|
|
198
|
+
return localWorkdirActions.includes(value) ? value : "unknown";
|
|
199
|
+
}
|
|
185
200
|
function summaryArgs(args) {
|
|
186
201
|
return {
|
|
187
202
|
path: optionalStringArg(args, "path"),
|
|
@@ -277,6 +292,27 @@ function localToolResult(action, value) {
|
|
|
277
292
|
}
|
|
278
293
|
return { ok: true, action, result };
|
|
279
294
|
}
|
|
295
|
+
function localToolErrorResult(action, error) {
|
|
296
|
+
const details = errorDetails(error);
|
|
297
|
+
return {
|
|
298
|
+
ok: false,
|
|
299
|
+
action,
|
|
300
|
+
error: details.message,
|
|
301
|
+
code: details.code,
|
|
302
|
+
path: details.path,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function errorDetails(error) {
|
|
306
|
+
if (error instanceof Error) {
|
|
307
|
+
const record = error;
|
|
308
|
+
return {
|
|
309
|
+
code: typeof record.code === "string" ? record.code : undefined,
|
|
310
|
+
message: error.message || "local_workdir action failed",
|
|
311
|
+
path: typeof record.path === "string" ? record.path : undefined,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
return { message: String(error || "local_workdir action failed") };
|
|
315
|
+
}
|
|
280
316
|
function stringArg(args, key, alternateKey) {
|
|
281
317
|
const direct = args[key] ?? (alternateKey ? args[alternateKey] : undefined);
|
|
282
318
|
const fromOptions = args.options && typeof args.options === "object"
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "1.3.
|
|
2
|
-
export declare const USER_AGENT = "@agent-api/sdk/1.3.
|
|
1
|
+
export declare const VERSION = "1.3.2";
|
|
2
|
+
export declare const USER_AGENT = "@agent-api/sdk/1.3.2";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "1.3.
|
|
1
|
+
export const VERSION = "1.3.2";
|
|
2
2
|
export const USER_AGENT = `@agent-api/sdk/${VERSION}`;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function normalizeVolumeAssetPath(src: string | null | undefined): string;
|
|
2
|
+
export declare function isSupportedVolumeImagePath(src: string | null | undefined): boolean;
|
|
3
|
+
export declare function isSupportedVolumeImageContentType(contentType: string | null | undefined): boolean;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const SUPPORTED_VOLUME_IMAGE_EXTENSIONS = new Set([
|
|
2
|
+
".avif",
|
|
3
|
+
".bmp",
|
|
4
|
+
".gif",
|
|
5
|
+
".jpeg",
|
|
6
|
+
".jpg",
|
|
7
|
+
".png",
|
|
8
|
+
".svg",
|
|
9
|
+
".webp",
|
|
10
|
+
]);
|
|
11
|
+
export function normalizeVolumeAssetPath(src) {
|
|
12
|
+
const value = src?.trim() ?? "";
|
|
13
|
+
if (!value)
|
|
14
|
+
return "";
|
|
15
|
+
if (isExternalAssetTarget(value))
|
|
16
|
+
return "";
|
|
17
|
+
let path = value.split("#", 1)[0]?.split("?", 1)[0]?.trim() ?? "";
|
|
18
|
+
path = path.replace(/^\/agent-volume\/+/i, "");
|
|
19
|
+
path = path.replace(/^\/+/, "");
|
|
20
|
+
path = path.replace(/\/+/g, "/");
|
|
21
|
+
if (!path || path === "." || path.includes(".."))
|
|
22
|
+
return "";
|
|
23
|
+
return path;
|
|
24
|
+
}
|
|
25
|
+
export function isSupportedVolumeImagePath(src) {
|
|
26
|
+
const path = normalizeVolumeAssetPath(src).toLowerCase();
|
|
27
|
+
if (!path)
|
|
28
|
+
return false;
|
|
29
|
+
const dot = path.lastIndexOf(".");
|
|
30
|
+
return dot >= 0 && SUPPORTED_VOLUME_IMAGE_EXTENSIONS.has(path.slice(dot));
|
|
31
|
+
}
|
|
32
|
+
export function isSupportedVolumeImageContentType(contentType) {
|
|
33
|
+
return (contentType ?? "").split(";", 1)[0]?.trim().toLowerCase().startsWith("image/") ?? false;
|
|
34
|
+
}
|
|
35
|
+
function isExternalAssetTarget(src) {
|
|
36
|
+
return /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(src);
|
|
37
|
+
}
|
package/dist-cjs/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.browserAuthSessionExpiresWithin = exports.DeviceAuthFlowError = exports.AuthResource = exports.resolvePresetToolsFromCatalog = exports.resolvePresetTools = exports.publicToolToRequestTool = exports.mergeTools = exports.runLocalFunctionHandlers = exports.pendingFunctionCalls = exports.functionCallOutputInput = exports.parseResponseError = exports.isRetryableStatus = exports.RateLimitError = exports.PermissionDeniedError = exports.NotFoundError = exports.InternalServerError = exports.BadRequestError = exports.AuthenticationError = exports.APIStatusError = exports.APIConnectionError = exports.APIError = exports.collectPage = exports.Page = exports.VERSION = exports.DEFAULT_TIMEOUT_MS = exports.DEFAULT_STREAM_TIMEOUT_MS = exports.DEFAULT_MAX_RETRIES = exports.AgentAPI = void 0;
|
|
17
|
+
exports.browserAuthSessionExpiresWithin = exports.DeviceAuthFlowError = exports.AuthResource = exports.normalizeVolumeAssetPath = exports.isSupportedVolumeImagePath = exports.isSupportedVolumeImageContentType = exports.resolvePresetToolsFromCatalog = exports.resolvePresetTools = exports.publicToolToRequestTool = exports.mergeTools = exports.runLocalFunctionHandlers = exports.pendingFunctionCalls = exports.functionCallOutputInput = exports.parseResponseError = exports.isRetryableStatus = exports.RateLimitError = exports.PermissionDeniedError = exports.NotFoundError = exports.InternalServerError = exports.BadRequestError = exports.AuthenticationError = exports.APIStatusError = exports.APIConnectionError = exports.APIError = exports.collectPage = exports.Page = exports.VERSION = exports.DEFAULT_TIMEOUT_MS = exports.DEFAULT_STREAM_TIMEOUT_MS = exports.DEFAULT_MAX_RETRIES = exports.AgentAPI = void 0;
|
|
18
18
|
var client_js_1 = require("./client.js");
|
|
19
19
|
Object.defineProperty(exports, "AgentAPI", { enumerable: true, get: function () { return client_js_1.AgentAPI; } });
|
|
20
20
|
Object.defineProperty(exports, "DEFAULT_MAX_RETRIES", { enumerable: true, get: function () { return client_js_1.DEFAULT_MAX_RETRIES; } });
|
|
@@ -46,6 +46,10 @@ Object.defineProperty(exports, "mergeTools", { enumerable: true, get: function (
|
|
|
46
46
|
Object.defineProperty(exports, "publicToolToRequestTool", { enumerable: true, get: function () { return preset_tools_js_1.publicToolToRequestTool; } });
|
|
47
47
|
Object.defineProperty(exports, "resolvePresetTools", { enumerable: true, get: function () { return preset_tools_js_1.resolvePresetTools; } });
|
|
48
48
|
Object.defineProperty(exports, "resolvePresetToolsFromCatalog", { enumerable: true, get: function () { return preset_tools_js_1.resolvePresetToolsFromCatalog; } });
|
|
49
|
+
var volume_assets_js_1 = require("./volume-assets.js");
|
|
50
|
+
Object.defineProperty(exports, "isSupportedVolumeImageContentType", { enumerable: true, get: function () { return volume_assets_js_1.isSupportedVolumeImageContentType; } });
|
|
51
|
+
Object.defineProperty(exports, "isSupportedVolumeImagePath", { enumerable: true, get: function () { return volume_assets_js_1.isSupportedVolumeImagePath; } });
|
|
52
|
+
Object.defineProperty(exports, "normalizeVolumeAssetPath", { enumerable: true, get: function () { return volume_assets_js_1.normalizeVolumeAssetPath; } });
|
|
49
53
|
var auth_js_1 = require("./resources/auth.js");
|
|
50
54
|
Object.defineProperty(exports, "AuthResource", { enumerable: true, get: function () { return auth_js_1.AuthResource; } });
|
|
51
55
|
Object.defineProperty(exports, "DeviceAuthFlowError", { enumerable: true, get: function () { return auth_js_1.DeviceAuthFlowError; } });
|
package/dist-cjs/local/core.js
CHANGED
|
@@ -325,7 +325,7 @@ class LocalFileStore {
|
|
|
325
325
|
const maxFiles = positiveInt(params.maxFiles, 500);
|
|
326
326
|
const maxBytesPerFile = positiveInt(params.maxBytesPerFile, 512 * 1024);
|
|
327
327
|
const maxLineLength = positiveInt(params.maxLineLength, 500);
|
|
328
|
-
const stats = await this.
|
|
328
|
+
const stats = await this.grepCandidates(params.path ?? ".", params.ignore);
|
|
329
329
|
const matches = [];
|
|
330
330
|
let filesScanned = 0;
|
|
331
331
|
let scanTruncated = false;
|
|
@@ -363,6 +363,27 @@ class LocalFileStore {
|
|
|
363
363
|
}
|
|
364
364
|
return { object: "list", matches, files_scanned: filesScanned, scan_truncated: scanTruncated };
|
|
365
365
|
}
|
|
366
|
+
async grepCandidates(relativePath, ignore) {
|
|
367
|
+
const fullPath = this.resolvePath(relativePath);
|
|
368
|
+
const info = await (0, promises_1.stat)(fullPath);
|
|
369
|
+
const portablePath = toPortablePath(node_path_1.default.relative(this.root, fullPath)) || ".";
|
|
370
|
+
if (ignored(portablePath, ignore)) {
|
|
371
|
+
return [];
|
|
372
|
+
}
|
|
373
|
+
if (info.isFile()) {
|
|
374
|
+
return [{
|
|
375
|
+
path: portablePath,
|
|
376
|
+
fullPath,
|
|
377
|
+
type: "file",
|
|
378
|
+
size: info.size,
|
|
379
|
+
modifiedAt: info.mtime,
|
|
380
|
+
}];
|
|
381
|
+
}
|
|
382
|
+
if (info.isDirectory()) {
|
|
383
|
+
return await this.list(relativePath, { recursive: true, ignore });
|
|
384
|
+
}
|
|
385
|
+
return [];
|
|
386
|
+
}
|
|
366
387
|
async summarize(params = {}) {
|
|
367
388
|
const maxFiles = positiveInt(params.maxFiles, 2000);
|
|
368
389
|
const maxPreviews = positiveInt(params.maxPreviews, 20);
|
package/dist-cjs/local/tools.js
CHANGED
|
@@ -13,6 +13,15 @@ class LocalWorkdirDriver {
|
|
|
13
13
|
this.accessMode = options.accessMode ?? "approval";
|
|
14
14
|
}
|
|
15
15
|
async dispatch(args) {
|
|
16
|
+
const action = safeWorkdirAction(args);
|
|
17
|
+
try {
|
|
18
|
+
return await this.dispatchUnsafe(args);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
return localToolErrorResult(action, error);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async dispatchUnsafe(args) {
|
|
16
25
|
const action = workdirAction(args);
|
|
17
26
|
switch (action) {
|
|
18
27
|
case "summarize":
|
|
@@ -51,7 +60,8 @@ class LocalWorkdirDriver {
|
|
|
51
60
|
if (this.accessMode === "full") {
|
|
52
61
|
return false;
|
|
53
62
|
}
|
|
54
|
-
|
|
63
|
+
const action = safeWorkdirAction(args);
|
|
64
|
+
return action !== "unknown" && mutatingLocalWorkdirActions.has(action);
|
|
55
65
|
}
|
|
56
66
|
async dispatchApplyEdits(args) {
|
|
57
67
|
const edits = editsArg(args);
|
|
@@ -136,6 +146,7 @@ const mutatingLocalWorkdirActions = new Set([
|
|
|
136
146
|
const localWorkdirToolDescription = [
|
|
137
147
|
"Inspect and modify the selected local workdir through one model-facing primitive.",
|
|
138
148
|
"Use action=list/search/grep/summarize/context to discover files, read/read_lines for file content, preview_edits before edits, and apply_edits/write/mkdir/delete only when mutation is intended.",
|
|
149
|
+
"grep searches file contents for a literal substring; path may be omitted, a file path, or a directory subtree.",
|
|
139
150
|
"In approval mode, mutating actions return requires_approval with a safe preview instead of changing files. In full mode, mutating actions execute immediately.",
|
|
140
151
|
"Paths are relative to the selected local workdir; never use absolute paths.",
|
|
141
152
|
].join(" ");
|
|
@@ -146,7 +157,7 @@ function localWorkdirToolParameters() {
|
|
|
146
157
|
enum: localWorkdirActions,
|
|
147
158
|
description: "Workdir operation. Prefer summarize/list/search/grep before reading or editing. Prefer read_lines and apply_edits for source changes.",
|
|
148
159
|
},
|
|
149
|
-
path: stringSchema("Relative path. File path for read/write/delete/edit actions
|
|
160
|
+
path: stringSchema("Relative path. File path for read/write/delete/edit actions. For grep, path may be a file or a directory subtree. For list/search/summarize/context/snapshot, path is a directory base."),
|
|
150
161
|
query: stringSchema("Path/name query for search, or optional context query."),
|
|
151
162
|
pattern: stringSchema("Literal text pattern for grep."),
|
|
152
163
|
content: stringSchema("Text content for write."),
|
|
@@ -189,6 +200,10 @@ function workdirAction(args) {
|
|
|
189
200
|
}
|
|
190
201
|
return value;
|
|
191
202
|
}
|
|
203
|
+
function safeWorkdirAction(args) {
|
|
204
|
+
const value = typeof args.action === "string" ? args.action.trim().toLowerCase() : "";
|
|
205
|
+
return localWorkdirActions.includes(value) ? value : "unknown";
|
|
206
|
+
}
|
|
192
207
|
function summaryArgs(args) {
|
|
193
208
|
return {
|
|
194
209
|
path: optionalStringArg(args, "path"),
|
|
@@ -284,6 +299,27 @@ function localToolResult(action, value) {
|
|
|
284
299
|
}
|
|
285
300
|
return { ok: true, action, result };
|
|
286
301
|
}
|
|
302
|
+
function localToolErrorResult(action, error) {
|
|
303
|
+
const details = errorDetails(error);
|
|
304
|
+
return {
|
|
305
|
+
ok: false,
|
|
306
|
+
action,
|
|
307
|
+
error: details.message,
|
|
308
|
+
code: details.code,
|
|
309
|
+
path: details.path,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function errorDetails(error) {
|
|
313
|
+
if (error instanceof Error) {
|
|
314
|
+
const record = error;
|
|
315
|
+
return {
|
|
316
|
+
code: typeof record.code === "string" ? record.code : undefined,
|
|
317
|
+
message: error.message || "local_workdir action failed",
|
|
318
|
+
path: typeof record.path === "string" ? record.path : undefined,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
return { message: String(error || "local_workdir action failed") };
|
|
322
|
+
}
|
|
287
323
|
function stringArg(args, key, alternateKey) {
|
|
288
324
|
const direct = args[key] ?? (alternateKey ? args[alternateKey] : undefined);
|
|
289
325
|
const fromOptions = args.options && typeof args.options === "object"
|
package/dist-cjs/version.js
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeVolumeAssetPath = normalizeVolumeAssetPath;
|
|
4
|
+
exports.isSupportedVolumeImagePath = isSupportedVolumeImagePath;
|
|
5
|
+
exports.isSupportedVolumeImageContentType = isSupportedVolumeImageContentType;
|
|
6
|
+
const SUPPORTED_VOLUME_IMAGE_EXTENSIONS = new Set([
|
|
7
|
+
".avif",
|
|
8
|
+
".bmp",
|
|
9
|
+
".gif",
|
|
10
|
+
".jpeg",
|
|
11
|
+
".jpg",
|
|
12
|
+
".png",
|
|
13
|
+
".svg",
|
|
14
|
+
".webp",
|
|
15
|
+
]);
|
|
16
|
+
function normalizeVolumeAssetPath(src) {
|
|
17
|
+
const value = src?.trim() ?? "";
|
|
18
|
+
if (!value)
|
|
19
|
+
return "";
|
|
20
|
+
if (isExternalAssetTarget(value))
|
|
21
|
+
return "";
|
|
22
|
+
let path = value.split("#", 1)[0]?.split("?", 1)[0]?.trim() ?? "";
|
|
23
|
+
path = path.replace(/^\/agent-volume\/+/i, "");
|
|
24
|
+
path = path.replace(/^\/+/, "");
|
|
25
|
+
path = path.replace(/\/+/g, "/");
|
|
26
|
+
if (!path || path === "." || path.includes(".."))
|
|
27
|
+
return "";
|
|
28
|
+
return path;
|
|
29
|
+
}
|
|
30
|
+
function isSupportedVolumeImagePath(src) {
|
|
31
|
+
const path = normalizeVolumeAssetPath(src).toLowerCase();
|
|
32
|
+
if (!path)
|
|
33
|
+
return false;
|
|
34
|
+
const dot = path.lastIndexOf(".");
|
|
35
|
+
return dot >= 0 && SUPPORTED_VOLUME_IMAGE_EXTENSIONS.has(path.slice(dot));
|
|
36
|
+
}
|
|
37
|
+
function isSupportedVolumeImageContentType(contentType) {
|
|
38
|
+
return (contentType ?? "").split(";", 1)[0]?.trim().toLowerCase().startsWith("image/") ?? false;
|
|
39
|
+
}
|
|
40
|
+
function isExternalAssetTarget(src) {
|
|
41
|
+
return /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(src);
|
|
42
|
+
}
|