@sisu-ai/tool-terminal 7.0.1 → 7.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,9 @@
1
+ <div align="right">
2
+ <a href="https://github.com/finger-gun/sisu"><img src="https://github.com/finger-gun/sisu/raw/main/sisu-light.svg" alt="ProjectSpecs" width="100" /></a>
3
+ </div>
4
+
5
+ ---
6
+
1
7
  # @sisu-ai/tool-terminal
2
8
 
3
9
  A secure terminal execution tool for Sisu agents. Provides sandboxed command execution with session support, a strict allow list, realpath-based path scoping, timeouts and basic file helpers. Commands run without a shell and reject control operators by default; optional shell-free pipelines (`|`) and sequences (`;`, `&&`, `||`) can be enabled via config.
@@ -153,3 +159,78 @@ Discover what you can do through examples or documentation. Check it out at http
153
159
  - [License](https://github.com/finger-gun/sisu/blob/main/LICENSE)
154
160
  - [Report a Bug](https://github.com/finger-gun/sisu/issues/new?template=bug_report.md)
155
161
  - [Request a Feature](https://github.com/finger-gun/sisu/issues/new?template=feature_request.md)
162
+
163
+ ---
164
+
165
+ ## Documentation
166
+
167
+ **Core** — [Package docs](packages/core/README.md) · [Error types](packages/core/ERROR_TYPES.md)
168
+
169
+ **Adapters** — [OpenAI](packages/adapters/openai/README.md) · [Anthropic](packages/adapters/anthropic/README.md) · [Ollama](packages/adapters/ollama/README.md)
170
+
171
+ <details>
172
+ <summary>All middleware packages</summary>
173
+
174
+ - [@sisu-ai/mw-agent-run-api](packages/middleware/agent-run-api/README.md)
175
+ - [@sisu-ai/mw-context-compressor](packages/middleware/context-compressor/README.md)
176
+ - [@sisu-ai/mw-control-flow](packages/middleware/control-flow/README.md)
177
+ - [@sisu-ai/mw-conversation-buffer](packages/middleware/conversation-buffer/README.md)
178
+ - [@sisu-ai/mw-cors](packages/middleware/cors/README.md)
179
+ - [@sisu-ai/mw-error-boundary](packages/middleware/error-boundary/README.md)
180
+ - [@sisu-ai/mw-guardrails](packages/middleware/guardrails/README.md)
181
+ - [@sisu-ai/mw-invariants](packages/middleware/invariants/README.md)
182
+ - [@sisu-ai/mw-orchestration](packages/middleware/orchestration/README.md)
183
+ - [@sisu-ai/mw-rag](packages/middleware/rag/README.md)
184
+ - [@sisu-ai/mw-react-parser](packages/middleware/react-parser/README.md)
185
+ - [@sisu-ai/mw-register-tools](packages/middleware/register-tools/README.md)
186
+ - [@sisu-ai/mw-tool-calling](packages/middleware/tool-calling/README.md)
187
+ - [@sisu-ai/mw-trace-viewer](packages/middleware/trace-viewer/README.md)
188
+ - [@sisu-ai/mw-usage-tracker](packages/middleware/usage-tracker/README.md)
189
+ </details>
190
+
191
+ <details>
192
+ <summary>All tool packages</summary>
193
+
194
+ - [@sisu-ai/tool-aws-s3](packages/tools/aws-s3/README.md)
195
+ - [@sisu-ai/tool-azure-blob](packages/tools/azure-blob/README.md)
196
+ - [@sisu-ai/tool-extract-urls](packages/tools/extract-urls/README.md)
197
+ - [@sisu-ai/tool-github-projects](packages/tools/github-projects/README.md)
198
+ - [@sisu-ai/tool-summarize-text](packages/tools/summarize-text/README.md)
199
+ - [@sisu-ai/tool-terminal](packages/tools/terminal/README.md)
200
+ - [@sisu-ai/tool-vec-chroma](packages/tools/vec-chroma/README.md)
201
+ - [@sisu-ai/tool-web-fetch](packages/tools/web-fetch/README.md)
202
+ - [@sisu-ai/tool-web-search-duckduckgo](packages/tools/web-search-duckduckgo/README.md)
203
+ - [@sisu-ai/tool-web-search-google](packages/tools/web-search-google/README.md)
204
+ - [@sisu-ai/tool-web-search-openai](packages/tools/web-search-openai/README.md)
205
+ - [@sisu-ai/tool-wikipedia](packages/tools/wikipedia/README.md)
206
+ </details>
207
+
208
+ <details>
209
+ <summary>All examples</summary>
210
+
211
+ **Anthropic** — [hello](examples/anthropic-hello/README.md) · [control-flow](examples/anthropic-control-flow/README.md) · [stream](examples/anthropic-stream/README.md) · [weather](examples/anthropic-weather/README.md)
212
+
213
+ **Ollama** — [hello](examples/ollama-hello/README.md) · [stream](examples/ollama-stream/README.md) · [vision](examples/ollama-vision/README.md) · [weather](examples/ollama-weather/README.md) · [web-search](examples/ollama-web-search/README.md)
214
+
215
+ **OpenAI** — [hello](examples/openai-hello/README.md) · [weather](examples/openai-weather/README.md) · [stream](examples/openai-stream/README.md) · [vision](examples/openai-vision/README.md) · [reasoning](examples/openai-reasoning/README.md) · [react](examples/openai-react/README.md) · [control-flow](examples/openai-control-flow/README.md) · [branch](examples/openai-branch/README.md) · [parallel](examples/openai-parallel/README.md) · [graph](examples/openai-graph/README.md) · [orchestration](examples/openai-orchestration/README.md) · [orchestration-adaptive](examples/openai-orchestration-adaptive/README.md) · [guardrails](examples/openai-guardrails/README.md) · [error-handling](examples/openai-error-handling/README.md) · [rag-chroma](examples/openai-rag-chroma/README.md) · [web-search](examples/openai-web-search/README.md) · [web-fetch](examples/openai-web-fetch/README.md) · [wikipedia](examples/openai-wikipedia/README.md) · [terminal](examples/openai-terminal/README.md) · [github-projects](examples/openai-github-projects/README.md) · [server](examples/openai-server/README.md) · [aws-s3](examples/openai-aws-s3/README.md) · [azure-blob](examples/openai-azure-blob/README.md)
216
+ </details>
217
+
218
+ ---
219
+
220
+ ## Contributing
221
+
222
+ We build Sisu in the open. Contributions welcome.
223
+
224
+ [Contributing Guide](CONTRIBUTING.md) · [Report a Bug](https://github.com/finger-gun/sisu/issues/new?template=bug_report.md) · [Request a Feature](https://github.com/finger-gun/sisu/issues/new?template=feature_request.md) · [Code of Conduct](CODE_OF_CONDUCT.md)
225
+
226
+ ---
227
+
228
+ <div align="center">
229
+
230
+ **[Star on GitHub](https://github.com/finger-gun/sisu)** if Sisu helps you build better agents.
231
+
232
+ *Quiet, determined, relentlessly useful.*
233
+
234
+ [Apache 2.0 License](LICENSE)
235
+
236
+ </div>
package/dist/index.d.ts CHANGED
@@ -28,6 +28,26 @@ export interface TerminalToolConfig {
28
28
  export declare const DEFAULT_CONFIG: TerminalToolConfig;
29
29
  export declare const TERMINAL_COMMANDS_ALLOW: ReadonlyArray<string>;
30
30
  export declare function defaultTerminalConfig(overrides?: Partial<TerminalToolConfig>): TerminalToolConfig;
31
+ interface TerminalPolicy {
32
+ allowed: boolean;
33
+ reason?: string;
34
+ allowedCommands?: string[];
35
+ allowedRoots?: string[];
36
+ }
37
+ interface TerminalRunResult {
38
+ exitCode: number;
39
+ stdout: string;
40
+ stderr: string;
41
+ durationMs: number;
42
+ policy: TerminalPolicy;
43
+ message?: string;
44
+ cwd: string;
45
+ }
46
+ interface TerminalReadResult {
47
+ contents: string;
48
+ policy: TerminalPolicy;
49
+ message?: string;
50
+ }
31
51
  export declare function createTerminalTool(config?: Partial<TerminalToolConfig>): {
32
52
  start_session: (args?: {
33
53
  cwd?: string;
@@ -42,17 +62,7 @@ export declare function createTerminalTool(config?: Partial<TerminalToolConfig>)
42
62
  env?: Record<string, string>;
43
63
  stdin?: string;
44
64
  sessionId?: string;
45
- }) => Promise<{
46
- exitCode: number;
47
- stdout: string;
48
- stderr: string;
49
- durationMs: number;
50
- policy: {
51
- allowed: boolean;
52
- reason?: string;
53
- };
54
- cwd: string;
55
- }>;
65
+ }) => Promise<TerminalRunResult>;
56
66
  cd: (args: {
57
67
  path: string;
58
68
  sessionId?: string;
@@ -64,16 +74,14 @@ export declare function createTerminalTool(config?: Partial<TerminalToolConfig>)
64
74
  path: string;
65
75
  encoding?: "utf8" | "base64";
66
76
  sessionId?: string;
67
- }) => Promise<{
68
- contents: string;
69
- }>;
77
+ }) => Promise<TerminalReadResult>;
70
78
  tools: (Tool<{
71
79
  command: string;
72
80
  cwd?: string;
73
81
  env?: Record<string, string>;
74
82
  stdin?: string;
75
83
  sessionId?: string;
76
- }, any> | Tool<{
84
+ }, TerminalRunResult> | Tool<{
77
85
  path: string;
78
86
  sessionId?: string;
79
87
  }, {
@@ -83,8 +91,7 @@ export declare function createTerminalTool(config?: Partial<TerminalToolConfig>)
83
91
  path: string;
84
92
  encoding?: "utf8" | "base64";
85
93
  sessionId?: string;
86
- }, {
87
- contents: string;
88
- }>)[];
94
+ }, TerminalReadResult>)[];
89
95
  };
90
96
  export type TerminalTool = ReturnType<typeof createTerminalTool>;
97
+ export {};
package/dist/index.js CHANGED
@@ -87,6 +87,8 @@ function isPathAllowed(absPath, cfg, mode) {
87
87
  return true;
88
88
  }
89
89
  function looksLikePath(arg) {
90
+ if (/^https?:\/\//i.test(arg))
91
+ return false;
90
92
  return (arg.startsWith(".") ||
91
93
  arg.includes("/") ||
92
94
  /^(?:[A-Za-z]:[\\/]|\\\\)/.test(arg));
@@ -240,7 +242,7 @@ function commandPolicyCheck(args, cfg) {
240
242
  found.push("`...`");
241
243
  if (/>/.test(cmdStr))
242
244
  found.push(">");
243
- if (/<\<?/.test(cmdStr))
245
+ if (/<<?/.test(cmdStr))
244
246
  found.push("<");
245
247
  if (/(^|\s)&(\s|$)/.test(cmdStr))
246
248
  found.push("&");
@@ -373,7 +375,12 @@ export function createTerminalTool(config) {
373
375
  stdout: "",
374
376
  stderr: "",
375
377
  durationMs: 0,
376
- policy: pre,
378
+ policy: {
379
+ allowed: false,
380
+ reason: pre.reason,
381
+ allowedCommands: cfg.commands.allow,
382
+ },
383
+ message: `Command denied by policy. Allowed commands: ${cfg.commands.allow.join(", ")}.`,
377
384
  cwd,
378
385
  };
379
386
  }
@@ -431,7 +438,9 @@ export function createTerminalTool(config) {
431
438
  try {
432
439
  c.kill("SIGKILL");
433
440
  }
434
- catch { }
441
+ catch {
442
+ // ignore kill errors
443
+ }
435
444
  }
436
445
  };
437
446
  const onStdout = (d) => {
@@ -547,14 +556,14 @@ export function createTerminalTool(config) {
547
556
  }
548
557
  function cd(args) {
549
558
  let session = getSession(args.sessionId);
559
+ let createdSessionId;
550
560
  // If no valid session is provided, create one anchored at the first root
551
561
  if (!session) {
552
562
  const cwd = canonicalize(cfg.roots[0]);
553
- const sessionId = randomUUID();
563
+ createdSessionId = randomUUID();
554
564
  const expiresAt = Date.now() + cfg.sessions.ttlMs;
555
565
  session = { cwd, env: {}, expiresAt };
556
- sessions.set(sessionId, session);
557
- args._createdSessionId = sessionId;
566
+ sessions.set(createdSessionId, session);
558
567
  }
559
568
  const newPath = canonicalize(path.resolve(session.cwd, args.path));
560
569
  if (!isPathAllowed(newPath, cfg, "exec")) {
@@ -564,7 +573,7 @@ export function createTerminalTool(config) {
564
573
  session.expiresAt = Date.now() + cfg.sessions.ttlMs;
565
574
  return {
566
575
  cwd: session.cwd,
567
- sessionId: args._createdSessionId ?? args.sessionId,
576
+ sessionId: createdSessionId ?? args.sessionId,
568
577
  };
569
578
  }
570
579
  async function read_file(args) {
@@ -573,12 +582,21 @@ export function createTerminalTool(config) {
573
582
  const session = getSession(args.sessionId);
574
583
  const cwd = session?.cwd ?? cfg.roots[0];
575
584
  const abs = canonicalize(path.resolve(cwd, args.path));
576
- if (!isPathAllowed(abs, cfg, "read"))
577
- throw new Error("path outside allowed roots");
585
+ if (!isPathAllowed(abs, cfg, "read")) {
586
+ return {
587
+ contents: "",
588
+ policy: {
589
+ allowed: false,
590
+ reason: "path outside allowed roots",
591
+ allowedRoots: cfg.roots,
592
+ },
593
+ message: `Path denied by policy. Allowed roots: ${cfg.roots.join(", ")}.`,
594
+ };
595
+ }
578
596
  const buf = await fs.readFile(abs);
579
597
  const encoding = args.encoding ?? "utf8";
580
598
  const contents = encoding === "base64" ? buf.toString("base64") : buf.toString("utf8");
581
- return { contents };
599
+ return { contents, policy: { allowed: true } };
582
600
  }
583
601
  const runCommandTool = {
584
602
  name: "terminalRun",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisu-ai/tool-terminal",
3
- "version": "7.0.1",
3
+ "version": "7.1.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -12,7 +12,7 @@
12
12
  "zod": "^3.23.8"
13
13
  },
14
14
  "peerDependencies": {
15
- "@sisu-ai/core": "^2.3.1"
15
+ "@sisu-ai/core": "^2.3.2"
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",