@agent-api/sdk 1.1.5 → 1.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.
@@ -0,0 +1,318 @@
1
+ import { spawn } from "node:child_process";
2
+ import path from "node:path";
3
+ export class HostLocalShellRunner {
4
+ cwd;
5
+ shell;
6
+ timeoutMs;
7
+ maxOutputBytes;
8
+ env;
9
+ constructor(options = {}) {
10
+ this.cwd = path.resolve(options.cwd ?? process.cwd());
11
+ this.shell = options.shell ?? true;
12
+ this.timeoutMs = positiveInteger(options.timeoutMs, 2 * 60 * 1000, "timeoutMs");
13
+ this.maxOutputBytes = positiveInteger(options.maxOutputBytes, 128 * 1024, "maxOutputBytes");
14
+ this.env = { ...process.env, ...(options.env ?? {}) };
15
+ }
16
+ async run(request, context = {}) {
17
+ const command = requiredString(request.command, "command");
18
+ const cwd = resolveContainedPath(this.cwd, request.workdir);
19
+ const timeoutMs = request.timeoutMs == null
20
+ ? this.timeoutMs
21
+ : positiveInteger(request.timeoutMs, this.timeoutMs, "timeoutMs");
22
+ const started = Date.now();
23
+ const stdout = new BoundedText(this.maxOutputBytes);
24
+ const stderr = new BoundedText(this.maxOutputBytes);
25
+ let timedOut = false;
26
+ return await new Promise((resolve, reject) => {
27
+ const child = spawn(command, [], {
28
+ cwd,
29
+ env: { ...this.env, ...(request.env ?? {}) },
30
+ shell: this.shell,
31
+ stdio: ["ignore", "pipe", "pipe"],
32
+ windowsHide: true,
33
+ });
34
+ let settled = false;
35
+ const finish = (exitCode, signal) => {
36
+ if (settled)
37
+ return;
38
+ settled = true;
39
+ clearTimeout(timer);
40
+ context.signal?.removeEventListener("abort", abort);
41
+ const stdoutText = stdout.text();
42
+ const stderrText = stderr.text();
43
+ const output = [stdoutText, stderrText].filter(Boolean).join(stderrText ? "\n" : "");
44
+ resolve({
45
+ ok: true,
46
+ command,
47
+ description: request.description,
48
+ cwd,
49
+ exit_code: exitCode,
50
+ signal,
51
+ stdout: stdoutText,
52
+ stderr: stderrText,
53
+ output: output || "(no output)",
54
+ duration_ms: Date.now() - started,
55
+ timed_out: timedOut,
56
+ truncated: stdout.truncated || stderr.truncated,
57
+ });
58
+ };
59
+ const kill = () => {
60
+ if (child.killed)
61
+ return;
62
+ child.kill(process.platform === "win32" ? undefined : "SIGTERM");
63
+ setTimeout(() => {
64
+ if (!child.killed)
65
+ child.kill(process.platform === "win32" ? undefined : "SIGKILL");
66
+ }, 3000).unref();
67
+ };
68
+ const abort = () => {
69
+ kill();
70
+ };
71
+ const timer = setTimeout(() => {
72
+ timedOut = true;
73
+ kill();
74
+ }, timeoutMs);
75
+ timer.unref();
76
+ if (context.signal?.aborted) {
77
+ abort();
78
+ }
79
+ else {
80
+ context.signal?.addEventListener("abort", abort, { once: true });
81
+ }
82
+ child.stdout?.on("data", (chunk) => stdout.append(chunk));
83
+ child.stderr?.on("data", (chunk) => stderr.append(chunk));
84
+ child.on("error", (error) => {
85
+ if (settled)
86
+ return;
87
+ settled = true;
88
+ clearTimeout(timer);
89
+ context.signal?.removeEventListener("abort", abort);
90
+ reject(error);
91
+ });
92
+ child.on("close", finish);
93
+ });
94
+ }
95
+ }
96
+ export class LocalShellDriver {
97
+ accessMode;
98
+ runner;
99
+ constructor(options = {}) {
100
+ const cwd = options.workdir?.root ?? options.cwd;
101
+ this.accessMode = options.accessMode ?? "approval";
102
+ this.runner = options.runner ?? new HostLocalShellRunner({
103
+ cwd,
104
+ shell: options.shell,
105
+ timeoutMs: options.timeoutMs,
106
+ maxOutputBytes: options.maxOutputBytes,
107
+ });
108
+ }
109
+ async dispatch(args, context = {}) {
110
+ const request = shellRequest(args);
111
+ if (this.accessMode !== "full") {
112
+ return shellApprovalRequired(request);
113
+ }
114
+ return shellToolResult(await this.runner.run(request, context));
115
+ }
116
+ requiresApproval() {
117
+ return this.accessMode !== "full";
118
+ }
119
+ }
120
+ export function createLocalShellToolRegistry(options = {}) {
121
+ const toolName = options.toolName ?? "local_shell";
122
+ const driver = new LocalShellDriver(options);
123
+ const hostRunner = driver.runner instanceof HostLocalShellRunner ? driver.runner : undefined;
124
+ const definition = localShellToolDefinition(toolName, {
125
+ accessMode: driver.accessMode,
126
+ cwd: options.workdir?.root ?? hostRunner?.cwd ?? options.cwd,
127
+ shell: hostRunner?.shell ?? options.shell,
128
+ timeoutMs: hostRunner?.timeoutMs ?? options.timeoutMs,
129
+ maxOutputBytes: hostRunner?.maxOutputBytes ?? options.maxOutputBytes,
130
+ });
131
+ return {
132
+ accessMode: driver.accessMode,
133
+ toolName,
134
+ definitions: () => [{ ...definition }],
135
+ handlers: () => ({ [toolName]: (args) => driver.dispatch(args) }),
136
+ execute: async (name, args, context = {}) => {
137
+ if (name !== toolName) {
138
+ throw new Error(`unknown local shell tool: ${name}`);
139
+ }
140
+ return await driver.dispatch(args, context);
141
+ },
142
+ requiresApproval: (name) => name === toolName && driver.requiresApproval(),
143
+ };
144
+ }
145
+ export function localShellToolDefinition(name = "local_shell", options = {}) {
146
+ return {
147
+ type: "function",
148
+ name,
149
+ description: localShellToolDescription(options),
150
+ parameters: localShellToolParameters(),
151
+ strict: false,
152
+ };
153
+ }
154
+ export function localShellToolInstructions(options = {}) {
155
+ return localShellToolDescription(options);
156
+ }
157
+ function localShellToolDescription(options = {}) {
158
+ const platform = options.platform ?? process.platform;
159
+ const shell = shellDisplayName(options.shell);
160
+ const accessMode = options.accessMode ?? "approval";
161
+ const cwd = options.cwd ? path.resolve(options.cwd) : undefined;
162
+ const timeoutMs = options.timeoutMs ?? 2 * 60 * 1000;
163
+ const maxOutputBytes = options.maxOutputBytes ?? 128 * 1024;
164
+ return [
165
+ "Run a local shell command through one model-facing primitive.",
166
+ "Prefer local_workdir for file discovery, reading, and editing. Use local_shell for package managers, tests, build commands, git, and other process-level tasks.",
167
+ `Execution environment: platform=${platform}; shell=${shell}; access_mode=${accessMode}; default_timeout_ms=${timeoutMs}; max_output_bytes=${maxOutputBytes}.`,
168
+ cwd ? `Default cwd: ${cwd}. Relative command paths resolve from this cwd unless workdir is set.` : "Relative command paths resolve from the configured cwd unless workdir is set.",
169
+ "The workdir parameter must be a relative child path of the configured cwd. Use workdir instead of cd when possible.",
170
+ "Absolute paths inside the command are permitted by the host OS if the user/process has permission; this tool is not a filesystem sandbox or security sandbox.",
171
+ "Captured stdout/stderr may be truncated when output exceeds the advertised max_output_bytes.",
172
+ "In approval mode, calls return requires_approval instead of executing. In full mode, commands execute immediately.",
173
+ shellGuidance(platform, options.shell),
174
+ ].filter(Boolean).join(" ");
175
+ }
176
+ function localShellToolParameters() {
177
+ return {
178
+ type: "object",
179
+ properties: {
180
+ command: {
181
+ type: "string",
182
+ description: "Shell command to execute. Keep it focused and quote paths containing spaces.",
183
+ },
184
+ description: {
185
+ type: "string",
186
+ description: "Short human-readable description of why this command is being run.",
187
+ },
188
+ workdir: {
189
+ type: "string",
190
+ description: "Optional relative working directory. Use this instead of cd. Absolute paths are rejected by the default host runner.",
191
+ },
192
+ timeout_ms: {
193
+ type: "integer",
194
+ description: "Optional timeout in milliseconds.",
195
+ },
196
+ },
197
+ required: ["command"],
198
+ additionalProperties: false,
199
+ };
200
+ }
201
+ function shellRequest(args) {
202
+ return {
203
+ command: requiredString(args.command, "command"),
204
+ description: optionalString(args.description, "description"),
205
+ workdir: optionalString(args.workdir, "workdir"),
206
+ timeoutMs: optionalNumber(args.timeoutMs ?? args.timeout_ms, "timeout_ms"),
207
+ };
208
+ }
209
+ function shellApprovalRequired(request) {
210
+ return {
211
+ ok: false,
212
+ requires_approval: true,
213
+ action: "run",
214
+ command: request.command,
215
+ description: request.description,
216
+ workdir: request.workdir,
217
+ timeout_ms: request.timeoutMs,
218
+ message: "local_shell command execution requires approval",
219
+ };
220
+ }
221
+ function shellToolResult(result) {
222
+ return {
223
+ ...result,
224
+ action: "run",
225
+ };
226
+ }
227
+ function resolveContainedPath(root, child) {
228
+ if (!child)
229
+ return root;
230
+ if (path.isAbsolute(child)) {
231
+ throw new Error("workdir must be relative to the configured local shell cwd");
232
+ }
233
+ const resolved = path.resolve(root, child);
234
+ const relative = path.relative(root, resolved);
235
+ if (relative.startsWith("..") || path.isAbsolute(relative)) {
236
+ throw new Error("workdir must stay inside the configured local shell cwd");
237
+ }
238
+ return resolved;
239
+ }
240
+ function requiredString(value, name) {
241
+ if (typeof value !== "string" || !value.trim()) {
242
+ throw new Error(`${name} must be a non-empty string`);
243
+ }
244
+ return value;
245
+ }
246
+ function optionalString(value, name) {
247
+ if (value == null || value === "")
248
+ return undefined;
249
+ if (typeof value !== "string") {
250
+ throw new Error(`${name} must be a string`);
251
+ }
252
+ return value;
253
+ }
254
+ function optionalNumber(value, name) {
255
+ if (value == null)
256
+ return undefined;
257
+ if (typeof value !== "number" || !Number.isFinite(value)) {
258
+ throw new Error(`${name} must be a number`);
259
+ }
260
+ return Math.trunc(value);
261
+ }
262
+ function positiveInteger(value, fallback, name) {
263
+ if (value == null)
264
+ return fallback;
265
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
266
+ throw new Error(`${name} must be a positive number`);
267
+ }
268
+ return Math.trunc(value);
269
+ }
270
+ function shellDisplayName(shell) {
271
+ if (typeof shell === "string" && shell.trim())
272
+ return shell;
273
+ if (shell === false)
274
+ return "direct process execution";
275
+ if (process.platform === "win32")
276
+ return "cmd.exe";
277
+ return "/bin/sh";
278
+ }
279
+ function shellGuidance(platform, shell) {
280
+ const name = typeof shell === "string" ? path.basename(shell).toLowerCase() : shellDisplayName(shell).toLowerCase();
281
+ if (platform === "win32" || name.includes("powershell") || name === "pwsh") {
282
+ return "On Windows/PowerShell, prefer PowerShell-compatible commands and quote paths with spaces.";
283
+ }
284
+ if (name.includes("cmd.exe") || name === "cmd") {
285
+ return "On cmd.exe, prefer cmd-compatible syntax and use && only for dependent command chaining.";
286
+ }
287
+ return "On POSIX shells, prefer portable shell syntax, quote paths with spaces, and use && only when later commands depend on earlier success.";
288
+ }
289
+ class BoundedText {
290
+ maxBytes;
291
+ chunks = [];
292
+ size = 0;
293
+ truncated = false;
294
+ constructor(maxBytes) {
295
+ this.maxBytes = maxBytes;
296
+ }
297
+ append(chunk) {
298
+ this.chunks.push(chunk);
299
+ this.size += chunk.byteLength;
300
+ while (this.size > this.maxBytes && this.chunks.length > 1) {
301
+ const removed = this.chunks.shift();
302
+ if (!removed)
303
+ break;
304
+ this.size -= removed.byteLength;
305
+ this.truncated = true;
306
+ }
307
+ if (this.size > this.maxBytes && this.chunks.length === 1) {
308
+ const current = this.chunks[0];
309
+ this.chunks[0] = current.subarray(current.byteLength - this.maxBytes);
310
+ this.size = this.chunks[0].byteLength;
311
+ this.truncated = true;
312
+ }
313
+ }
314
+ text() {
315
+ const value = Buffer.concat(this.chunks, this.size).toString("utf8");
316
+ return this.truncated ? `...output truncated...\n${value}` : value;
317
+ }
318
+ }
@@ -1,27 +1,27 @@
1
1
  import type { FunctionTool } from "../types/tools.js";
2
- import type { LocalWorkspace } from "./core.js";
3
- export type LocalWorkspaceAccessMode = "approval" | "full";
4
- export type LocalWorkspaceAction = "summarize" | "list" | "search" | "grep" | "read" | "read_lines" | "context" | "snapshot" | "classify_path" | "preview_edits" | "apply_edits" | "write" | "mkdir" | "delete";
5
- export interface LocalWorkspaceToolRegistryOptions {
6
- accessMode?: LocalWorkspaceAccessMode;
2
+ import type { LocalWorkdir } from "./core.js";
3
+ export type LocalWorkdirAccessMode = "approval" | "full";
4
+ export type LocalWorkdirAction = "summarize" | "list" | "search" | "grep" | "read" | "read_lines" | "context" | "snapshot" | "classify_path" | "preview_edits" | "apply_edits" | "write" | "mkdir" | "delete";
5
+ export interface LocalWorkdirToolRegistryOptions {
6
+ accessMode?: LocalWorkdirAccessMode;
7
7
  toolName?: string;
8
8
  }
9
- export interface LocalWorkspaceToolRegistry {
10
- readonly workspace: LocalWorkspace;
11
- readonly accessMode: LocalWorkspaceAccessMode;
9
+ export interface LocalWorkdirToolRegistry {
10
+ readonly workdir: LocalWorkdir;
11
+ readonly accessMode: LocalWorkdirAccessMode;
12
12
  readonly toolName: string;
13
13
  definitions(): FunctionTool[];
14
14
  handlers(): Record<string, (args: Record<string, unknown>) => Promise<Record<string, unknown>>>;
15
15
  execute(name: string, args: Record<string, unknown>): Promise<Record<string, unknown>>;
16
16
  requiresApproval(name: string, args?: Record<string, unknown>): boolean;
17
17
  }
18
- export interface LocalWorkspaceDriverOptions {
19
- accessMode?: LocalWorkspaceAccessMode;
18
+ export interface LocalWorkdirDriverOptions {
19
+ accessMode?: LocalWorkdirAccessMode;
20
20
  }
21
- export declare class LocalWorkspaceDriver {
22
- readonly workspace: LocalWorkspace;
23
- readonly accessMode: LocalWorkspaceAccessMode;
24
- constructor(workspace: LocalWorkspace, options?: LocalWorkspaceDriverOptions);
21
+ export declare class LocalWorkdirDriver {
22
+ readonly workdir: LocalWorkdir;
23
+ readonly accessMode: LocalWorkdirAccessMode;
24
+ constructor(workdir: LocalWorkdir, options?: LocalWorkdirDriverOptions);
25
25
  dispatch(args: Record<string, unknown>): Promise<Record<string, unknown>>;
26
26
  requiresApproval(args: Record<string, unknown>): boolean;
27
27
  private dispatchApplyEdits;
@@ -29,6 +29,6 @@ export declare class LocalWorkspaceDriver {
29
29
  private dispatchMkdir;
30
30
  private dispatchDelete;
31
31
  }
32
- export declare function createLocalWorkspaceToolRegistry(workspace: LocalWorkspace, options?: LocalWorkspaceToolRegistryOptions): LocalWorkspaceToolRegistry;
33
- export declare function localWorkspaceToolDefinition(name?: string): FunctionTool;
34
- export declare function localWorkspaceToolInstructions(): string;
32
+ export declare function createLocalWorkdirToolRegistry(workdir: LocalWorkdir, options?: LocalWorkdirToolRegistryOptions): LocalWorkdirToolRegistry;
33
+ export declare function localWorkdirToolDefinition(name?: string): FunctionTool;
34
+ export declare function localWorkdirToolInstructions(): string;
@@ -1,34 +1,34 @@
1
1
  import { createLocalContextPackage } from "./context.js";
2
- export class LocalWorkspaceDriver {
3
- workspace;
2
+ export class LocalWorkdirDriver {
3
+ workdir;
4
4
  accessMode;
5
- constructor(workspace, options = {}) {
6
- this.workspace = workspace;
5
+ constructor(workdir, options = {}) {
6
+ this.workdir = workdir;
7
7
  this.accessMode = options.accessMode ?? "approval";
8
8
  }
9
9
  async dispatch(args) {
10
- const action = workspaceAction(args);
10
+ const action = workdirAction(args);
11
11
  switch (action) {
12
12
  case "summarize":
13
- return localToolResult(action, localSummaryResult(await this.workspace.summarize(summaryArgs(args))));
13
+ return localToolResult(action, localSummaryResult(await this.workdir.summarize(summaryArgs(args))));
14
14
  case "list":
15
- return localToolResult(action, await this.workspace.listEntries(optionalStringArg(args, "path") ?? ".", listArgs(args)));
15
+ return localToolResult(action, await this.workdir.listEntries(optionalStringArg(args, "path") ?? ".", listArgs(args)));
16
16
  case "search":
17
- return localToolResult(action, await this.workspace.searchEntries(searchEntriesArgs(args)));
17
+ return localToolResult(action, await this.workdir.searchEntries(searchEntriesArgs(args)));
18
18
  case "grep":
19
- return localToolResult(action, await this.workspace.grep(grepArgs(args)));
19
+ return localToolResult(action, await this.workdir.grep(grepArgs(args)));
20
20
  case "read":
21
- return localToolResult(action, await this.workspace.readFile(stringArg(args, "path"), readFileArgs(args)));
21
+ return localToolResult(action, await this.workdir.readFile(stringArg(args, "path"), readFileArgs(args)));
22
22
  case "read_lines":
23
- return localToolResult(action, await this.workspace.readLines(stringArg(args, "path"), readLinesArgs(args)));
23
+ return localToolResult(action, await this.workdir.readLines(stringArg(args, "path"), readLinesArgs(args)));
24
24
  case "context":
25
- return localToolResult(action, await createLocalContextPackage(this.workspace, contextPackageArgs(args)));
25
+ return localToolResult(action, await createLocalContextPackage(this.workdir, contextPackageArgs(args)));
26
26
  case "snapshot":
27
- return localToolResult(action, await this.workspace.snapshot(snapshotArgs(args)));
27
+ return localToolResult(action, await this.workdir.snapshot(snapshotArgs(args)));
28
28
  case "classify_path":
29
- return localToolResult(action, this.workspace.classifyPath(stringArg(args, "path")));
29
+ return localToolResult(action, this.workdir.classifyPath(stringArg(args, "path")));
30
30
  case "preview_edits":
31
- return localToolResult(action, await this.workspace.previewEdits(editsArg(args)));
31
+ return localToolResult(action, await this.workdir.previewEdits(editsArg(args)));
32
32
  case "apply_edits":
33
33
  return await this.dispatchApplyEdits(args);
34
34
  case "write":
@@ -38,73 +38,73 @@ export class LocalWorkspaceDriver {
38
38
  case "delete":
39
39
  return await this.dispatchDelete(args);
40
40
  default:
41
- throw new Error(`unsupported local_workspace action: ${action}`);
41
+ throw new Error(`unsupported local_workdir action: ${action}`);
42
42
  }
43
43
  }
44
44
  requiresApproval(args) {
45
45
  if (this.accessMode === "full") {
46
46
  return false;
47
47
  }
48
- return mutatingLocalWorkspaceActions.has(workspaceAction(args));
48
+ return mutatingLocalWorkdirActions.has(workdirAction(args));
49
49
  }
50
50
  async dispatchApplyEdits(args) {
51
51
  const edits = editsArg(args);
52
52
  if (this.accessMode !== "full") {
53
- return approvalRequired("apply_edits", args, await this.workspace.previewEdits(edits));
53
+ return approvalRequired("apply_edits", args, await this.workdir.previewEdits(edits));
54
54
  }
55
- return localToolResult("apply_edits", await this.workspace.applyEdits(edits));
55
+ return localToolResult("apply_edits", await this.workdir.applyEdits(edits));
56
56
  }
57
57
  async dispatchWrite(args) {
58
58
  if (this.accessMode !== "full") {
59
59
  return approvalRequired("write", args);
60
60
  }
61
- return localToolResult("write", await this.workspace.writeText(stringArg(args, "path"), stringArg(args, "content")));
61
+ return localToolResult("write", await this.workdir.writeText(stringArg(args, "path"), stringArg(args, "content")));
62
62
  }
63
63
  async dispatchMkdir(args) {
64
64
  if (this.accessMode !== "full") {
65
65
  return approvalRequired("mkdir", args);
66
66
  }
67
- return localToolResult("mkdir", await this.workspace.createDirectory(stringArg(args, "path")));
67
+ return localToolResult("mkdir", await this.workdir.createDirectory(stringArg(args, "path")));
68
68
  }
69
69
  async dispatchDelete(args) {
70
70
  if (this.accessMode !== "full") {
71
71
  return approvalRequired("delete", args);
72
72
  }
73
- return localToolResult("delete", await this.workspace.deletePath(stringArg(args, "path")));
73
+ return localToolResult("delete", await this.workdir.deletePath(stringArg(args, "path")));
74
74
  }
75
75
  }
76
- export function createLocalWorkspaceToolRegistry(workspace, options = {}) {
77
- const toolName = options.toolName ?? "local_workspace";
78
- const driver = new LocalWorkspaceDriver(workspace, { accessMode: options.accessMode });
79
- const definition = localWorkspaceToolDefinition(toolName);
76
+ export function createLocalWorkdirToolRegistry(workdir, options = {}) {
77
+ const toolName = options.toolName ?? "local_workdir";
78
+ const driver = new LocalWorkdirDriver(workdir, { accessMode: options.accessMode });
79
+ const definition = localWorkdirToolDefinition(toolName);
80
80
  return {
81
- workspace,
81
+ workdir,
82
82
  accessMode: driver.accessMode,
83
83
  toolName,
84
84
  definitions: () => [{ ...definition }],
85
85
  handlers: () => ({ [toolName]: (args) => driver.dispatch(args) }),
86
86
  execute: async (name, args) => {
87
87
  if (name !== toolName) {
88
- throw new Error(`unknown local workspace tool: ${name}`);
88
+ throw new Error(`unknown local workdir tool: ${name}`);
89
89
  }
90
90
  return await driver.dispatch(args);
91
91
  },
92
92
  requiresApproval: (name, args = {}) => name === toolName && driver.requiresApproval(args),
93
93
  };
94
94
  }
95
- export function localWorkspaceToolDefinition(name = "local_workspace") {
95
+ export function localWorkdirToolDefinition(name = "local_workdir") {
96
96
  return {
97
97
  type: "function",
98
98
  name,
99
- description: localWorkspaceToolDescription,
100
- parameters: localWorkspaceToolParameters(),
99
+ description: localWorkdirToolDescription,
100
+ parameters: localWorkdirToolParameters(),
101
101
  strict: false,
102
102
  };
103
103
  }
104
- export function localWorkspaceToolInstructions() {
105
- return localWorkspaceToolDescription;
104
+ export function localWorkdirToolInstructions() {
105
+ return localWorkdirToolDescription;
106
106
  }
107
- const localWorkspaceActions = [
107
+ const localWorkdirActions = [
108
108
  "summarize",
109
109
  "list",
110
110
  "search",
@@ -120,24 +120,24 @@ const localWorkspaceActions = [
120
120
  "mkdir",
121
121
  "delete",
122
122
  ];
123
- const mutatingLocalWorkspaceActions = new Set([
123
+ const mutatingLocalWorkdirActions = new Set([
124
124
  "apply_edits",
125
125
  "write",
126
126
  "mkdir",
127
127
  "delete",
128
128
  ]);
129
- const localWorkspaceToolDescription = [
130
- "Inspect and modify the selected local workspace through one model-facing primitive.",
129
+ const localWorkdirToolDescription = [
130
+ "Inspect and modify the selected local workdir through one model-facing primitive.",
131
131
  "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.",
132
132
  "In approval mode, mutating actions return requires_approval with a safe preview instead of changing files. In full mode, mutating actions execute immediately.",
133
- "Paths are relative to the selected local workspace; never use absolute paths.",
133
+ "Paths are relative to the selected local workdir; never use absolute paths.",
134
134
  ].join(" ");
135
- function localWorkspaceToolParameters() {
135
+ function localWorkdirToolParameters() {
136
136
  return objectSchema({
137
137
  action: {
138
138
  type: "string",
139
- enum: localWorkspaceActions,
140
- description: "Workspace operation. Prefer summarize/list/search/grep before reading or editing. Prefer read_lines and apply_edits for source changes.",
139
+ enum: localWorkdirActions,
140
+ description: "Workdir operation. Prefer summarize/list/search/grep before reading or editing. Prefer read_lines and apply_edits for source changes.",
141
141
  },
142
142
  path: stringSchema("Relative path. File path for read/write/delete/edit actions; directory base for list/search/grep/summarize/context/snapshot."),
143
143
  query: stringSchema("Path/name query for search, or optional context query."),
@@ -168,17 +168,17 @@ function localWorkspaceToolParameters() {
168
168
  max_bytes_per_file: integerSchema("Maximum bytes per file."),
169
169
  max_previews: integerSchema("Maximum summary previews."),
170
170
  include_content: booleanSchema("Include file contents in context packages."),
171
- include_summary: booleanSchema("Include workspace summary in context packages."),
171
+ include_summary: booleanSchema("Include workdir summary in context packages."),
172
172
  include_search: booleanSchema("Include grep results in context packages when query is set."),
173
173
  include_secrets: booleanSchema("Include likely secret file contents in context packages."),
174
174
  hash: booleanSchema("Include SHA-256 hashes in snapshots."),
175
175
  }),
176
176
  }, ["action"]);
177
177
  }
178
- function workspaceAction(args) {
178
+ function workdirAction(args) {
179
179
  const value = stringArg(args, "action").trim().toLowerCase();
180
- if (!localWorkspaceActions.includes(value)) {
181
- throw new Error(`unsupported local_workspace action: ${value}`);
180
+ if (!localWorkdirActions.includes(value)) {
181
+ throw new Error(`unsupported local_workdir action: ${value}`);
182
182
  }
183
183
  return value;
184
184
  }
@@ -345,7 +345,7 @@ function approvalRequired(action, args, preview) {
345
345
  requires_approval: true,
346
346
  arguments: args,
347
347
  preview,
348
- message: `local_workspace action ${action} requires approval`,
348
+ message: `local_workdir action ${action} requires approval`,
349
349
  };
350
350
  }
351
351
  function objectSchema(properties, required = []) {
package/dist/node.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  export * from "./index.js";
2
2
  export { NodeAgentAPI } from "./node-client.js";
3
3
  export { NodeSkillsResource } from "./resources/skills-node.js";
4
- export { LocalWorkspaceDriver, createLocalWorkspaceToolRegistry, localWorkspaceToolDefinition, localWorkspaceToolInstructions, } from "./local/tools.js";
5
- export type { LocalWorkspaceAction, LocalWorkspaceAccessMode, LocalWorkspaceToolRegistry, LocalWorkspaceToolRegistryOptions, } from "./local/tools.js";
4
+ export { createLocalShellToolRegistry, LocalWorkdirDriver, HostLocalShellRunner, LocalShellDriver, localShellToolDefinition, localShellToolInstructions, createLocalWorkdirToolRegistry, localWorkdirToolDefinition, localWorkdirToolInstructions, } from "./local/index.js";
5
+ export type { LocalCommandRunner, LocalShellAccessMode, LocalShellContext, LocalShellRequest, LocalShellResult, LocalShellToolRegistry, LocalShellToolRegistryOptions, LocalWorkdirAction, LocalWorkdirAccessMode, LocalWorkdirToolRegistry, LocalWorkdirToolRegistryOptions, } from "./local/index.js";
6
6
  export { localSkillFromDirectory, pendingLocalSkillCalls, runLocalSkillHandlers } from "./local-skills.js";
7
7
  export type { LocalSkillDirectoryOptions } from "./local-skills.js";
8
8
  export * from "./local/index.js";
package/dist/node.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from "./index.js";
2
2
  export { NodeAgentAPI } from "./node-client.js";
3
3
  export { NodeSkillsResource } from "./resources/skills-node.js";
4
- export { LocalWorkspaceDriver, createLocalWorkspaceToolRegistry, localWorkspaceToolDefinition, localWorkspaceToolInstructions, } from "./local/tools.js";
4
+ export { createLocalShellToolRegistry, LocalWorkdirDriver, HostLocalShellRunner, LocalShellDriver, localShellToolDefinition, localShellToolInstructions, createLocalWorkdirToolRegistry, localWorkdirToolDefinition, localWorkdirToolInstructions, } from "./local/index.js";
5
5
  export { localSkillFromDirectory, pendingLocalSkillCalls, runLocalSkillHandlers } from "./local-skills.js";
6
6
  export * from "./local/index.js";
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "1.1.5";
2
- export declare const USER_AGENT = "@agent-api/sdk/1.1.5";
1
+ export declare const VERSION = "1.2.1";
2
+ export declare const USER_AGENT = "@agent-api/sdk/1.2.1";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = "1.1.5";
1
+ export const VERSION = "1.2.1";
2
2
  export const USER_AGENT = `@agent-api/sdk/${VERSION}`;