@agent-api/sdk 1.2.0 → 1.2.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 CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog — @agent-api/sdk
2
2
 
3
+ ## 1.2.2
4
+
5
+ ### Added
6
+
7
+ - Added `RequestOptions.signal` so CLI, TUI, and desktop integrations can abort in-flight HTTP requests and response streams before a response ID is available.
8
+ - Documented and tested response cancellation behavior alongside the existing `responses.cancel(responseID)` backend cancellation API.
9
+
10
+ ## 1.2.1
11
+
12
+ ### Added
13
+
14
+ - Added a model-facing `local_shell` tool primitive with approval/full-access modes, bounded host command execution, timeout handling, execution-environment context, and a pluggable command-runner boundary for future isolation backends.
15
+
3
16
  ## 1.2.0
4
17
 
5
18
  ### Added
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Production JavaScript/TypeScript SDK for the Managed Agent API.
4
4
 
5
- **Published on npm:** [`@agent-api/sdk`](https://www.npmjs.com/package/@agent-api/sdk) (v1.1.4)
5
+ **Published on npm:** [`@agent-api/sdk`](https://www.npmjs.com/package/@agent-api/sdk) (v1.2.2)
6
6
 
7
7
  ## Install
8
8
 
@@ -44,7 +44,7 @@ Public package entrypoints:
44
44
 
45
45
  - `@agent-api/sdk`: browser-safe REST client, public types, auth, responses, models, presets, tools, volumes, and skills HTTP APIs.
46
46
  - `@agent-api/sdk/browser`: explicit alias of the browser-safe REST client entry.
47
- - `@agent-api/sdk/local`: Node-only local runtime, workdir, context, and local workdir tool support.
47
+ - `@agent-api/sdk/local`: Node-only local runtime, workdir, context, local workdir tools, and local shell tools.
48
48
  - `@agent-api/sdk/node`: Node aggregate entry for local helpers such as `localSkillFromDirectory()` plus `NodeAgentAPI`.
49
49
 
50
50
  ```
@@ -125,14 +125,15 @@ const response = await client.agent.create({
125
125
 
126
126
  ```typescript
127
127
  import { resolvePresetTools } from "@agent-api/sdk";
128
- import { createLocalWorkdirToolRegistry, LocalWorkdir } from "@agent-api/sdk/local";
128
+ import { createLocalShellToolRegistry, createLocalWorkdirToolRegistry, LocalWorkdir } from "@agent-api/sdk/local";
129
129
 
130
130
  const workdir = new LocalWorkdir("/path/to/project", { trusted: true });
131
- const registry = createLocalWorkdirToolRegistry(workdir);
131
+ const workdirRegistry = createLocalWorkdirToolRegistry(workdir);
132
+ const shellRegistry = createLocalShellToolRegistry({ workdir });
132
133
 
133
134
  const { tools } = await resolvePresetTools(client, {
134
135
  preset: "pro-search",
135
- tools: registry.definitions(),
136
+ tools: [...workdirRegistry.definitions(), ...shellRegistry.definitions()],
136
137
  });
137
138
 
138
139
  const response = await client.agent.create({
@@ -189,12 +190,15 @@ The runtime provides:
189
190
  - Atomic text/JSON writes, byte reads/writes, recursive listing, copy, remove, and stat helpers.
190
191
  - Local workdir operations inspired by platform volumes: `listEntries`, `searchEntries`, `readFile`, `writeFile`, `deletePath`, `createDirectory`, `readLines`, `patchLines`, `grep`, and `summarize`.
191
192
  - First-class local workdirs with default ignore rules, scoped workbench operations, patch previews, snapshots, diffs, file-watch handles, and budgeted context packaging.
193
+ - Model-facing local tools for workdir operations (`local_workdir`) and command execution (`local_shell`) with approval/full-access dispatch conventions.
192
194
  - Typed local errors, `.gitignore` loading, sensitivity classification, and multi-file edit plans with rollback on failure.
193
195
  - JSON config helpers for typed app settings.
194
196
  - Local skill discovery built on `localSkillFromDirectory()`.
195
197
 
196
198
  Keep UI and OS interaction policy in your host framework. Electron, Tauri, Qt, or native apps should call this layer from their trusted local process and expose only the capabilities their UI needs.
197
199
 
200
+ `local_shell` executes commands through a pluggable command runner. The default `HostLocalShellRunner` runs on the user's local machine, bounds captured output, enforces a timeout, and confines relative `workdir` overrides under the configured cwd. It is not a security sandbox; use approval mode unless your application intentionally grants full local command access.
201
+
198
202
  ```typescript
199
203
  const workdir = local.data.child("workdirs/demo");
200
204
 
@@ -253,6 +257,7 @@ const context = await createLocalContextPackage(project, {
253
257
 
254
258
  - **Retries:** automatic exponential backoff for network failures, 429, and 5xx (default 2 retries).
255
259
  - **Timeouts:** 10 minute default for requests; 1 hour for streaming agent runs (configurable via `timeout` / `streamTimeout`).
260
+ - **Cancellation:** pass `signal` in request options to abort local HTTP waiting, and call `client.responses.cancel(responseID)` for backend best-effort cancellation after a response ID exists.
256
261
  - **Typed errors:** `AuthenticationError`, `RateLimitError`, `NotFoundError`, `BadRequestError`, etc.
257
262
  - **Pagination:** `listPage` returns a cursor page; `listIterator` auto-fetches all pages.
258
263
 
@@ -269,7 +274,7 @@ const stream = await client.responses.create({
269
274
  preset: "fast-search",
270
275
  input: "Summarize today's AI news.",
271
276
  stream: true,
272
- });
277
+ }, { signal: abortController.signal });
273
278
 
274
279
  for await (const event of stream) {
275
280
  if (event.type === "response.output_text.delta") {
@@ -33,6 +33,9 @@ export class HTTPClient {
33
33
  return await this.fetchOnce(method, path, body, options, stream, rawBody);
34
34
  }
35
35
  catch (error) {
36
+ if (options.signal?.aborted) {
37
+ throw error;
38
+ }
36
39
  if (!(error instanceof APIError) || attempt >= maxRetries) {
37
40
  throw error;
38
41
  }
@@ -43,14 +46,29 @@ export class HTTPClient {
43
46
  }
44
47
  attempt += 1;
45
48
  const delayMs = retryDelayMs(error, attempt);
46
- await sleep(delayMs);
49
+ await sleep(delayMs, options.signal);
47
50
  }
48
51
  }
49
52
  }
50
53
  async fetchOnce(method, path, body, options, stream, rawBody) {
51
54
  const controller = new AbortController();
52
55
  const timeout = options.timeout ?? (stream ? this.options.streamTimeout : this.options.timeout);
53
- const timeoutID = setTimeout(() => controller.abort(), timeout);
56
+ let timedOut = false;
57
+ let callerAborted = options.signal?.aborted ?? false;
58
+ const timeoutID = setTimeout(() => {
59
+ timedOut = true;
60
+ controller.abort();
61
+ }, timeout);
62
+ const abortFromCaller = () => {
63
+ callerAborted = true;
64
+ controller.abort();
65
+ };
66
+ if (options.signal?.aborted) {
67
+ controller.abort();
68
+ }
69
+ else {
70
+ options.signal?.addEventListener("abort", abortFromCaller, { once: true });
71
+ }
54
72
  try {
55
73
  const headers = {
56
74
  Accept: stream ? "text/event-stream" : "application/json",
@@ -80,12 +98,19 @@ export class HTTPClient {
80
98
  throw error;
81
99
  }
82
100
  if (error instanceof Error && error.name === "AbortError") {
83
- throw new APIConnectionError(`Request timed out after ${timeout}ms`, error);
101
+ if (callerAborted || options.signal?.aborted) {
102
+ throw new APIConnectionError("Request aborted", error);
103
+ }
104
+ if (timedOut) {
105
+ throw new APIConnectionError(`Request timed out after ${timeout}ms`, error);
106
+ }
107
+ throw new APIConnectionError("Request aborted", error);
84
108
  }
85
109
  throw new APIConnectionError("Request failed", error);
86
110
  }
87
111
  finally {
88
112
  clearTimeout(timeoutID);
113
+ options.signal?.removeEventListener("abort", abortFromCaller);
89
114
  }
90
115
  }
91
116
  }
@@ -99,6 +124,23 @@ function retryDelayMs(error, attempt) {
99
124
  const jitter = Math.floor(Math.random() * 100);
100
125
  return exponential + jitter;
101
126
  }
102
- function sleep(ms) {
103
- return new Promise((resolve) => setTimeout(resolve, ms));
127
+ function sleep(ms, signal) {
128
+ if (!signal) {
129
+ return new Promise((resolve) => setTimeout(resolve, ms));
130
+ }
131
+ if (signal.aborted) {
132
+ return Promise.reject(new APIConnectionError("Request aborted"));
133
+ }
134
+ return new Promise((resolve, reject) => {
135
+ const timeout = setTimeout(() => {
136
+ signal.removeEventListener("abort", abort);
137
+ resolve();
138
+ }, ms);
139
+ const abort = () => {
140
+ clearTimeout(timeout);
141
+ signal.removeEventListener("abort", abort);
142
+ reject(new APIConnectionError("Request aborted"));
143
+ };
144
+ signal.addEventListener("abort", abort, { once: true });
145
+ });
104
146
  }
@@ -1,3 +1,4 @@
1
1
  export * from "./core.js";
2
2
  export * from "./context.js";
3
+ export * from "./shell.js";
3
4
  export * from "./tools.js";
@@ -1,3 +1,4 @@
1
1
  export * from "./core.js";
2
2
  export * from "./context.js";
3
+ export * from "./shell.js";
3
4
  export * from "./tools.js";
@@ -0,0 +1,82 @@
1
+ import type { FunctionTool } from "../types/tools.js";
2
+ import type { LocalWorkdir } from "./core.js";
3
+ export type LocalShellAccessMode = "approval" | "full";
4
+ export interface LocalShellRequest {
5
+ command: string;
6
+ description?: string;
7
+ workdir?: string;
8
+ timeoutMs?: number;
9
+ env?: Record<string, string | undefined>;
10
+ }
11
+ export interface LocalShellContext {
12
+ signal?: AbortSignal;
13
+ }
14
+ export interface LocalShellResult {
15
+ ok: boolean;
16
+ command: string;
17
+ description?: string;
18
+ cwd: string;
19
+ exit_code: number | null;
20
+ signal: NodeJS.Signals | null;
21
+ stdout: string;
22
+ stderr: string;
23
+ output: string;
24
+ duration_ms: number;
25
+ timed_out: boolean;
26
+ truncated: boolean;
27
+ }
28
+ export interface LocalCommandRunner {
29
+ run(request: LocalShellRequest, context?: LocalShellContext): Promise<LocalShellResult>;
30
+ }
31
+ export interface HostLocalShellRunnerOptions {
32
+ cwd?: string;
33
+ shell?: string | boolean;
34
+ timeoutMs?: number;
35
+ maxOutputBytes?: number;
36
+ env?: NodeJS.ProcessEnv;
37
+ }
38
+ export declare class HostLocalShellRunner implements LocalCommandRunner {
39
+ readonly cwd: string;
40
+ readonly shell: string | boolean;
41
+ readonly timeoutMs: number;
42
+ readonly maxOutputBytes: number;
43
+ readonly env: NodeJS.ProcessEnv;
44
+ constructor(options?: HostLocalShellRunnerOptions);
45
+ run(request: LocalShellRequest, context?: LocalShellContext): Promise<LocalShellResult>;
46
+ }
47
+ export interface LocalShellToolRegistryOptions {
48
+ accessMode?: LocalShellAccessMode;
49
+ toolName?: string;
50
+ runner?: LocalCommandRunner;
51
+ cwd?: string;
52
+ workdir?: LocalWorkdir;
53
+ shell?: string | boolean;
54
+ timeoutMs?: number;
55
+ maxOutputBytes?: number;
56
+ }
57
+ export interface LocalShellToolPresentationOptions {
58
+ accessMode?: LocalShellAccessMode;
59
+ cwd?: string;
60
+ shell?: string | boolean;
61
+ platform?: NodeJS.Platform;
62
+ timeoutMs?: number;
63
+ maxOutputBytes?: number;
64
+ }
65
+ export interface LocalShellToolRegistry {
66
+ readonly accessMode: LocalShellAccessMode;
67
+ readonly toolName: string;
68
+ definitions(): FunctionTool[];
69
+ handlers(): Record<string, (args: Record<string, unknown>) => Promise<Record<string, unknown>>>;
70
+ execute(name: string, args: Record<string, unknown>, context?: LocalShellContext): Promise<Record<string, unknown>>;
71
+ requiresApproval(name: string, args?: Record<string, unknown>): boolean;
72
+ }
73
+ export declare class LocalShellDriver {
74
+ readonly accessMode: LocalShellAccessMode;
75
+ readonly runner: LocalCommandRunner;
76
+ constructor(options?: LocalShellToolRegistryOptions);
77
+ dispatch(args: Record<string, unknown>, context?: LocalShellContext): Promise<Record<string, unknown>>;
78
+ requiresApproval(): boolean;
79
+ }
80
+ export declare function createLocalShellToolRegistry(options?: LocalShellToolRegistryOptions): LocalShellToolRegistry;
81
+ export declare function localShellToolDefinition(name?: string, options?: LocalShellToolPresentationOptions): FunctionTool;
82
+ export declare function localShellToolInstructions(options?: LocalShellToolPresentationOptions): string;
@@ -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
+ }
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 { LocalWorkdirDriver, createLocalWorkdirToolRegistry, localWorkdirToolDefinition, localWorkdirToolInstructions, } from "./local/tools.js";
5
- export type { LocalWorkdirAction, LocalWorkdirAccessMode, LocalWorkdirToolRegistry, LocalWorkdirToolRegistryOptions, } 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 { LocalWorkdirDriver, createLocalWorkdirToolRegistry, localWorkdirToolDefinition, localWorkdirToolInstructions, } 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";
@@ -20,6 +20,8 @@ export interface ClientOptions {
20
20
  export interface RequestOptions {
21
21
  headers?: Record<string, string>;
22
22
  timeout?: number;
23
+ /** Abort the underlying HTTP request or stream from caller-controlled UI/runtime state. */
24
+ signal?: AbortSignal;
23
25
  /** Override automatic retries for this request. */
24
26
  maxRetries?: number;
25
27
  }
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "1.2.0";
2
- export declare const USER_AGENT = "@agent-api/sdk/1.2.0";
1
+ export declare const VERSION = "1.2.2";
2
+ export declare const USER_AGENT = "@agent-api/sdk/1.2.2";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = "1.2.0";
1
+ export const VERSION = "1.2.2";
2
2
  export const USER_AGENT = `@agent-api/sdk/${VERSION}`;
@@ -36,6 +36,9 @@ class HTTPClient {
36
36
  return await this.fetchOnce(method, path, body, options, stream, rawBody);
37
37
  }
38
38
  catch (error) {
39
+ if (options.signal?.aborted) {
40
+ throw error;
41
+ }
39
42
  if (!(error instanceof errors_js_1.APIError) || attempt >= maxRetries) {
40
43
  throw error;
41
44
  }
@@ -46,14 +49,29 @@ class HTTPClient {
46
49
  }
47
50
  attempt += 1;
48
51
  const delayMs = retryDelayMs(error, attempt);
49
- await sleep(delayMs);
52
+ await sleep(delayMs, options.signal);
50
53
  }
51
54
  }
52
55
  }
53
56
  async fetchOnce(method, path, body, options, stream, rawBody) {
54
57
  const controller = new AbortController();
55
58
  const timeout = options.timeout ?? (stream ? this.options.streamTimeout : this.options.timeout);
56
- const timeoutID = setTimeout(() => controller.abort(), timeout);
59
+ let timedOut = false;
60
+ let callerAborted = options.signal?.aborted ?? false;
61
+ const timeoutID = setTimeout(() => {
62
+ timedOut = true;
63
+ controller.abort();
64
+ }, timeout);
65
+ const abortFromCaller = () => {
66
+ callerAborted = true;
67
+ controller.abort();
68
+ };
69
+ if (options.signal?.aborted) {
70
+ controller.abort();
71
+ }
72
+ else {
73
+ options.signal?.addEventListener("abort", abortFromCaller, { once: true });
74
+ }
57
75
  try {
58
76
  const headers = {
59
77
  Accept: stream ? "text/event-stream" : "application/json",
@@ -83,12 +101,19 @@ class HTTPClient {
83
101
  throw error;
84
102
  }
85
103
  if (error instanceof Error && error.name === "AbortError") {
86
- throw new errors_js_1.APIConnectionError(`Request timed out after ${timeout}ms`, error);
104
+ if (callerAborted || options.signal?.aborted) {
105
+ throw new errors_js_1.APIConnectionError("Request aborted", error);
106
+ }
107
+ if (timedOut) {
108
+ throw new errors_js_1.APIConnectionError(`Request timed out after ${timeout}ms`, error);
109
+ }
110
+ throw new errors_js_1.APIConnectionError("Request aborted", error);
87
111
  }
88
112
  throw new errors_js_1.APIConnectionError("Request failed", error);
89
113
  }
90
114
  finally {
91
115
  clearTimeout(timeoutID);
116
+ options.signal?.removeEventListener("abort", abortFromCaller);
92
117
  }
93
118
  }
94
119
  }
@@ -103,6 +128,23 @@ function retryDelayMs(error, attempt) {
103
128
  const jitter = Math.floor(Math.random() * 100);
104
129
  return exponential + jitter;
105
130
  }
106
- function sleep(ms) {
107
- return new Promise((resolve) => setTimeout(resolve, ms));
131
+ function sleep(ms, signal) {
132
+ if (!signal) {
133
+ return new Promise((resolve) => setTimeout(resolve, ms));
134
+ }
135
+ if (signal.aborted) {
136
+ return Promise.reject(new errors_js_1.APIConnectionError("Request aborted"));
137
+ }
138
+ return new Promise((resolve, reject) => {
139
+ const timeout = setTimeout(() => {
140
+ signal.removeEventListener("abort", abort);
141
+ resolve();
142
+ }, ms);
143
+ const abort = () => {
144
+ clearTimeout(timeout);
145
+ signal.removeEventListener("abort", abort);
146
+ reject(new errors_js_1.APIConnectionError("Request aborted"));
147
+ };
148
+ signal.addEventListener("abort", abort, { once: true });
149
+ });
108
150
  }
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./core.js"), exports);
18
18
  __exportStar(require("./context.js"), exports);
19
+ __exportStar(require("./shell.js"), exports);
19
20
  __exportStar(require("./tools.js"), exports);
@@ -0,0 +1,329 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LocalShellDriver = exports.HostLocalShellRunner = void 0;
7
+ exports.createLocalShellToolRegistry = createLocalShellToolRegistry;
8
+ exports.localShellToolDefinition = localShellToolDefinition;
9
+ exports.localShellToolInstructions = localShellToolInstructions;
10
+ const node_child_process_1 = require("node:child_process");
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ class HostLocalShellRunner {
13
+ cwd;
14
+ shell;
15
+ timeoutMs;
16
+ maxOutputBytes;
17
+ env;
18
+ constructor(options = {}) {
19
+ this.cwd = node_path_1.default.resolve(options.cwd ?? process.cwd());
20
+ this.shell = options.shell ?? true;
21
+ this.timeoutMs = positiveInteger(options.timeoutMs, 2 * 60 * 1000, "timeoutMs");
22
+ this.maxOutputBytes = positiveInteger(options.maxOutputBytes, 128 * 1024, "maxOutputBytes");
23
+ this.env = { ...process.env, ...(options.env ?? {}) };
24
+ }
25
+ async run(request, context = {}) {
26
+ const command = requiredString(request.command, "command");
27
+ const cwd = resolveContainedPath(this.cwd, request.workdir);
28
+ const timeoutMs = request.timeoutMs == null
29
+ ? this.timeoutMs
30
+ : positiveInteger(request.timeoutMs, this.timeoutMs, "timeoutMs");
31
+ const started = Date.now();
32
+ const stdout = new BoundedText(this.maxOutputBytes);
33
+ const stderr = new BoundedText(this.maxOutputBytes);
34
+ let timedOut = false;
35
+ return await new Promise((resolve, reject) => {
36
+ const child = (0, node_child_process_1.spawn)(command, [], {
37
+ cwd,
38
+ env: { ...this.env, ...(request.env ?? {}) },
39
+ shell: this.shell,
40
+ stdio: ["ignore", "pipe", "pipe"],
41
+ windowsHide: true,
42
+ });
43
+ let settled = false;
44
+ const finish = (exitCode, signal) => {
45
+ if (settled)
46
+ return;
47
+ settled = true;
48
+ clearTimeout(timer);
49
+ context.signal?.removeEventListener("abort", abort);
50
+ const stdoutText = stdout.text();
51
+ const stderrText = stderr.text();
52
+ const output = [stdoutText, stderrText].filter(Boolean).join(stderrText ? "\n" : "");
53
+ resolve({
54
+ ok: true,
55
+ command,
56
+ description: request.description,
57
+ cwd,
58
+ exit_code: exitCode,
59
+ signal,
60
+ stdout: stdoutText,
61
+ stderr: stderrText,
62
+ output: output || "(no output)",
63
+ duration_ms: Date.now() - started,
64
+ timed_out: timedOut,
65
+ truncated: stdout.truncated || stderr.truncated,
66
+ });
67
+ };
68
+ const kill = () => {
69
+ if (child.killed)
70
+ return;
71
+ child.kill(process.platform === "win32" ? undefined : "SIGTERM");
72
+ setTimeout(() => {
73
+ if (!child.killed)
74
+ child.kill(process.platform === "win32" ? undefined : "SIGKILL");
75
+ }, 3000).unref();
76
+ };
77
+ const abort = () => {
78
+ kill();
79
+ };
80
+ const timer = setTimeout(() => {
81
+ timedOut = true;
82
+ kill();
83
+ }, timeoutMs);
84
+ timer.unref();
85
+ if (context.signal?.aborted) {
86
+ abort();
87
+ }
88
+ else {
89
+ context.signal?.addEventListener("abort", abort, { once: true });
90
+ }
91
+ child.stdout?.on("data", (chunk) => stdout.append(chunk));
92
+ child.stderr?.on("data", (chunk) => stderr.append(chunk));
93
+ child.on("error", (error) => {
94
+ if (settled)
95
+ return;
96
+ settled = true;
97
+ clearTimeout(timer);
98
+ context.signal?.removeEventListener("abort", abort);
99
+ reject(error);
100
+ });
101
+ child.on("close", finish);
102
+ });
103
+ }
104
+ }
105
+ exports.HostLocalShellRunner = HostLocalShellRunner;
106
+ class LocalShellDriver {
107
+ accessMode;
108
+ runner;
109
+ constructor(options = {}) {
110
+ const cwd = options.workdir?.root ?? options.cwd;
111
+ this.accessMode = options.accessMode ?? "approval";
112
+ this.runner = options.runner ?? new HostLocalShellRunner({
113
+ cwd,
114
+ shell: options.shell,
115
+ timeoutMs: options.timeoutMs,
116
+ maxOutputBytes: options.maxOutputBytes,
117
+ });
118
+ }
119
+ async dispatch(args, context = {}) {
120
+ const request = shellRequest(args);
121
+ if (this.accessMode !== "full") {
122
+ return shellApprovalRequired(request);
123
+ }
124
+ return shellToolResult(await this.runner.run(request, context));
125
+ }
126
+ requiresApproval() {
127
+ return this.accessMode !== "full";
128
+ }
129
+ }
130
+ exports.LocalShellDriver = LocalShellDriver;
131
+ function createLocalShellToolRegistry(options = {}) {
132
+ const toolName = options.toolName ?? "local_shell";
133
+ const driver = new LocalShellDriver(options);
134
+ const hostRunner = driver.runner instanceof HostLocalShellRunner ? driver.runner : undefined;
135
+ const definition = localShellToolDefinition(toolName, {
136
+ accessMode: driver.accessMode,
137
+ cwd: options.workdir?.root ?? hostRunner?.cwd ?? options.cwd,
138
+ shell: hostRunner?.shell ?? options.shell,
139
+ timeoutMs: hostRunner?.timeoutMs ?? options.timeoutMs,
140
+ maxOutputBytes: hostRunner?.maxOutputBytes ?? options.maxOutputBytes,
141
+ });
142
+ return {
143
+ accessMode: driver.accessMode,
144
+ toolName,
145
+ definitions: () => [{ ...definition }],
146
+ handlers: () => ({ [toolName]: (args) => driver.dispatch(args) }),
147
+ execute: async (name, args, context = {}) => {
148
+ if (name !== toolName) {
149
+ throw new Error(`unknown local shell tool: ${name}`);
150
+ }
151
+ return await driver.dispatch(args, context);
152
+ },
153
+ requiresApproval: (name) => name === toolName && driver.requiresApproval(),
154
+ };
155
+ }
156
+ function localShellToolDefinition(name = "local_shell", options = {}) {
157
+ return {
158
+ type: "function",
159
+ name,
160
+ description: localShellToolDescription(options),
161
+ parameters: localShellToolParameters(),
162
+ strict: false,
163
+ };
164
+ }
165
+ function localShellToolInstructions(options = {}) {
166
+ return localShellToolDescription(options);
167
+ }
168
+ function localShellToolDescription(options = {}) {
169
+ const platform = options.platform ?? process.platform;
170
+ const shell = shellDisplayName(options.shell);
171
+ const accessMode = options.accessMode ?? "approval";
172
+ const cwd = options.cwd ? node_path_1.default.resolve(options.cwd) : undefined;
173
+ const timeoutMs = options.timeoutMs ?? 2 * 60 * 1000;
174
+ const maxOutputBytes = options.maxOutputBytes ?? 128 * 1024;
175
+ return [
176
+ "Run a local shell command through one model-facing primitive.",
177
+ "Prefer local_workdir for file discovery, reading, and editing. Use local_shell for package managers, tests, build commands, git, and other process-level tasks.",
178
+ `Execution environment: platform=${platform}; shell=${shell}; access_mode=${accessMode}; default_timeout_ms=${timeoutMs}; max_output_bytes=${maxOutputBytes}.`,
179
+ 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.",
180
+ "The workdir parameter must be a relative child path of the configured cwd. Use workdir instead of cd when possible.",
181
+ "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.",
182
+ "Captured stdout/stderr may be truncated when output exceeds the advertised max_output_bytes.",
183
+ "In approval mode, calls return requires_approval instead of executing. In full mode, commands execute immediately.",
184
+ shellGuidance(platform, options.shell),
185
+ ].filter(Boolean).join(" ");
186
+ }
187
+ function localShellToolParameters() {
188
+ return {
189
+ type: "object",
190
+ properties: {
191
+ command: {
192
+ type: "string",
193
+ description: "Shell command to execute. Keep it focused and quote paths containing spaces.",
194
+ },
195
+ description: {
196
+ type: "string",
197
+ description: "Short human-readable description of why this command is being run.",
198
+ },
199
+ workdir: {
200
+ type: "string",
201
+ description: "Optional relative working directory. Use this instead of cd. Absolute paths are rejected by the default host runner.",
202
+ },
203
+ timeout_ms: {
204
+ type: "integer",
205
+ description: "Optional timeout in milliseconds.",
206
+ },
207
+ },
208
+ required: ["command"],
209
+ additionalProperties: false,
210
+ };
211
+ }
212
+ function shellRequest(args) {
213
+ return {
214
+ command: requiredString(args.command, "command"),
215
+ description: optionalString(args.description, "description"),
216
+ workdir: optionalString(args.workdir, "workdir"),
217
+ timeoutMs: optionalNumber(args.timeoutMs ?? args.timeout_ms, "timeout_ms"),
218
+ };
219
+ }
220
+ function shellApprovalRequired(request) {
221
+ return {
222
+ ok: false,
223
+ requires_approval: true,
224
+ action: "run",
225
+ command: request.command,
226
+ description: request.description,
227
+ workdir: request.workdir,
228
+ timeout_ms: request.timeoutMs,
229
+ message: "local_shell command execution requires approval",
230
+ };
231
+ }
232
+ function shellToolResult(result) {
233
+ return {
234
+ ...result,
235
+ action: "run",
236
+ };
237
+ }
238
+ function resolveContainedPath(root, child) {
239
+ if (!child)
240
+ return root;
241
+ if (node_path_1.default.isAbsolute(child)) {
242
+ throw new Error("workdir must be relative to the configured local shell cwd");
243
+ }
244
+ const resolved = node_path_1.default.resolve(root, child);
245
+ const relative = node_path_1.default.relative(root, resolved);
246
+ if (relative.startsWith("..") || node_path_1.default.isAbsolute(relative)) {
247
+ throw new Error("workdir must stay inside the configured local shell cwd");
248
+ }
249
+ return resolved;
250
+ }
251
+ function requiredString(value, name) {
252
+ if (typeof value !== "string" || !value.trim()) {
253
+ throw new Error(`${name} must be a non-empty string`);
254
+ }
255
+ return value;
256
+ }
257
+ function optionalString(value, name) {
258
+ if (value == null || value === "")
259
+ return undefined;
260
+ if (typeof value !== "string") {
261
+ throw new Error(`${name} must be a string`);
262
+ }
263
+ return value;
264
+ }
265
+ function optionalNumber(value, name) {
266
+ if (value == null)
267
+ return undefined;
268
+ if (typeof value !== "number" || !Number.isFinite(value)) {
269
+ throw new Error(`${name} must be a number`);
270
+ }
271
+ return Math.trunc(value);
272
+ }
273
+ function positiveInteger(value, fallback, name) {
274
+ if (value == null)
275
+ return fallback;
276
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
277
+ throw new Error(`${name} must be a positive number`);
278
+ }
279
+ return Math.trunc(value);
280
+ }
281
+ function shellDisplayName(shell) {
282
+ if (typeof shell === "string" && shell.trim())
283
+ return shell;
284
+ if (shell === false)
285
+ return "direct process execution";
286
+ if (process.platform === "win32")
287
+ return "cmd.exe";
288
+ return "/bin/sh";
289
+ }
290
+ function shellGuidance(platform, shell) {
291
+ const name = typeof shell === "string" ? node_path_1.default.basename(shell).toLowerCase() : shellDisplayName(shell).toLowerCase();
292
+ if (platform === "win32" || name.includes("powershell") || name === "pwsh") {
293
+ return "On Windows/PowerShell, prefer PowerShell-compatible commands and quote paths with spaces.";
294
+ }
295
+ if (name.includes("cmd.exe") || name === "cmd") {
296
+ return "On cmd.exe, prefer cmd-compatible syntax and use && only for dependent command chaining.";
297
+ }
298
+ return "On POSIX shells, prefer portable shell syntax, quote paths with spaces, and use && only when later commands depend on earlier success.";
299
+ }
300
+ class BoundedText {
301
+ maxBytes;
302
+ chunks = [];
303
+ size = 0;
304
+ truncated = false;
305
+ constructor(maxBytes) {
306
+ this.maxBytes = maxBytes;
307
+ }
308
+ append(chunk) {
309
+ this.chunks.push(chunk);
310
+ this.size += chunk.byteLength;
311
+ while (this.size > this.maxBytes && this.chunks.length > 1) {
312
+ const removed = this.chunks.shift();
313
+ if (!removed)
314
+ break;
315
+ this.size -= removed.byteLength;
316
+ this.truncated = true;
317
+ }
318
+ if (this.size > this.maxBytes && this.chunks.length === 1) {
319
+ const current = this.chunks[0];
320
+ this.chunks[0] = current.subarray(current.byteLength - this.maxBytes);
321
+ this.size = this.chunks[0].byteLength;
322
+ this.truncated = true;
323
+ }
324
+ }
325
+ text() {
326
+ const value = Buffer.concat(this.chunks, this.size).toString("utf8");
327
+ return this.truncated ? `...output truncated...\n${value}` : value;
328
+ }
329
+ }
package/dist-cjs/node.js CHANGED
@@ -14,17 +14,22 @@ 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.runLocalSkillHandlers = exports.pendingLocalSkillCalls = exports.localSkillFromDirectory = exports.localWorkdirToolInstructions = exports.localWorkdirToolDefinition = exports.createLocalWorkdirToolRegistry = exports.LocalWorkdirDriver = exports.NodeSkillsResource = exports.NodeAgentAPI = void 0;
17
+ exports.runLocalSkillHandlers = exports.pendingLocalSkillCalls = exports.localSkillFromDirectory = exports.localWorkdirToolInstructions = exports.localWorkdirToolDefinition = exports.createLocalWorkdirToolRegistry = exports.localShellToolInstructions = exports.localShellToolDefinition = exports.LocalShellDriver = exports.HostLocalShellRunner = exports.LocalWorkdirDriver = exports.createLocalShellToolRegistry = exports.NodeSkillsResource = exports.NodeAgentAPI = void 0;
18
18
  __exportStar(require("./index.js"), exports);
19
19
  var node_client_js_1 = require("./node-client.js");
20
20
  Object.defineProperty(exports, "NodeAgentAPI", { enumerable: true, get: function () { return node_client_js_1.NodeAgentAPI; } });
21
21
  var skills_node_js_1 = require("./resources/skills-node.js");
22
22
  Object.defineProperty(exports, "NodeSkillsResource", { enumerable: true, get: function () { return skills_node_js_1.NodeSkillsResource; } });
23
- var tools_js_1 = require("./local/tools.js");
24
- Object.defineProperty(exports, "LocalWorkdirDriver", { enumerable: true, get: function () { return tools_js_1.LocalWorkdirDriver; } });
25
- Object.defineProperty(exports, "createLocalWorkdirToolRegistry", { enumerable: true, get: function () { return tools_js_1.createLocalWorkdirToolRegistry; } });
26
- Object.defineProperty(exports, "localWorkdirToolDefinition", { enumerable: true, get: function () { return tools_js_1.localWorkdirToolDefinition; } });
27
- Object.defineProperty(exports, "localWorkdirToolInstructions", { enumerable: true, get: function () { return tools_js_1.localWorkdirToolInstructions; } });
23
+ var index_js_1 = require("./local/index.js");
24
+ Object.defineProperty(exports, "createLocalShellToolRegistry", { enumerable: true, get: function () { return index_js_1.createLocalShellToolRegistry; } });
25
+ Object.defineProperty(exports, "LocalWorkdirDriver", { enumerable: true, get: function () { return index_js_1.LocalWorkdirDriver; } });
26
+ Object.defineProperty(exports, "HostLocalShellRunner", { enumerable: true, get: function () { return index_js_1.HostLocalShellRunner; } });
27
+ Object.defineProperty(exports, "LocalShellDriver", { enumerable: true, get: function () { return index_js_1.LocalShellDriver; } });
28
+ Object.defineProperty(exports, "localShellToolDefinition", { enumerable: true, get: function () { return index_js_1.localShellToolDefinition; } });
29
+ Object.defineProperty(exports, "localShellToolInstructions", { enumerable: true, get: function () { return index_js_1.localShellToolInstructions; } });
30
+ Object.defineProperty(exports, "createLocalWorkdirToolRegistry", { enumerable: true, get: function () { return index_js_1.createLocalWorkdirToolRegistry; } });
31
+ Object.defineProperty(exports, "localWorkdirToolDefinition", { enumerable: true, get: function () { return index_js_1.localWorkdirToolDefinition; } });
32
+ Object.defineProperty(exports, "localWorkdirToolInstructions", { enumerable: true, get: function () { return index_js_1.localWorkdirToolInstructions; } });
28
33
  var local_skills_js_1 = require("./local-skills.js");
29
34
  Object.defineProperty(exports, "localSkillFromDirectory", { enumerable: true, get: function () { return local_skills_js_1.localSkillFromDirectory; } });
30
35
  Object.defineProperty(exports, "pendingLocalSkillCalls", { enumerable: true, get: function () { return local_skills_js_1.pendingLocalSkillCalls; } });
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.USER_AGENT = exports.VERSION = void 0;
4
- exports.VERSION = "1.2.0";
4
+ exports.VERSION = "1.2.2";
5
5
  exports.USER_AGENT = `@agent-api/sdk/${exports.VERSION}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-api/sdk",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Production JavaScript SDK for the Managed Agent API",
5
5
  "license": "MIT",
6
6
  "repository": {