@sisu-ai/tool-terminal 7.0.1 → 7.1.0
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/dist/index.d.ts +25 -18
- package/dist/index.js +28 -10
- package/package.json +1 -1
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
|
-
},
|
|
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 (
|
|
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:
|
|
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
|
-
|
|
563
|
+
createdSessionId = randomUUID();
|
|
554
564
|
const expiresAt = Date.now() + cfg.sessions.ttlMs;
|
|
555
565
|
session = { cwd, env: {}, expiresAt };
|
|
556
|
-
sessions.set(
|
|
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:
|
|
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
|
-
|
|
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",
|