@dexto/tools-process 1.5.8 → 1.6.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/dist/bash-exec-tool.cjs +40 -23
- package/dist/bash-exec-tool.d.ts +27 -9
- package/dist/bash-exec-tool.d.ts.map +1 -0
- package/dist/bash-exec-tool.js +43 -23
- package/dist/bash-output-tool.cjs +13 -5
- package/dist/bash-output-tool.d.ts +13 -8
- package/dist/bash-output-tool.d.ts.map +1 -0
- package/dist/bash-output-tool.js +13 -5
- package/dist/command-pattern-utils.cjs +83 -0
- package/dist/command-pattern-utils.d.ts +29 -0
- package/dist/command-pattern-utils.d.ts.map +1 -0
- package/dist/command-pattern-utils.js +56 -0
- package/dist/command-pattern-utils.test.cjs +80 -0
- package/dist/command-pattern-utils.test.d.ts +2 -0
- package/dist/command-pattern-utils.test.d.ts.map +1 -0
- package/dist/command-pattern-utils.test.js +83 -0
- package/dist/command-validator.d.ts +5 -8
- package/dist/command-validator.d.ts.map +1 -0
- package/dist/error-codes.d.ts +2 -3
- package/dist/error-codes.d.ts.map +1 -0
- package/dist/errors.d.ts +4 -7
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.cjs +6 -3
- package/dist/index.d.cts +485 -11
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -2
- package/dist/kill-process-tool.cjs +13 -5
- package/dist/kill-process-tool.d.ts +13 -8
- package/dist/kill-process-tool.d.ts.map +1 -0
- package/dist/kill-process-tool.js +13 -5
- package/dist/process-service.cjs +11 -1
- package/dist/process-service.d.ts +12 -11
- package/dist/process-service.d.ts.map +1 -0
- package/dist/process-service.js +11 -1
- package/dist/{tool-provider.cjs → tool-factory-config.cjs} +6 -48
- package/dist/{tool-provider.d.ts → tool-factory-config.d.ts} +8 -27
- package/dist/tool-factory-config.d.ts.map +1 -0
- package/dist/{tool-provider.js → tool-factory-config.js} +2 -44
- package/dist/tool-factory.cjs +89 -0
- package/dist/tool-factory.d.ts +4 -0
- package/dist/tool-factory.d.ts.map +1 -0
- package/dist/tool-factory.js +65 -0
- package/dist/types.d.ts +9 -10
- package/dist/types.d.ts.map +1 -0
- package/package.json +5 -4
- package/dist/bash-exec-tool.d.cts +0 -17
- package/dist/bash-output-tool.d.cts +0 -16
- package/dist/command-validator.d.cts +0 -52
- package/dist/error-codes.d.cts +0 -26
- package/dist/errors.d.cts +0 -90
- package/dist/kill-process-tool.d.cts +0 -16
- package/dist/process-service.d.cts +0 -96
- package/dist/tool-provider.d.cts +0 -72
- package/dist/types.d.cts +0 -108
package/dist/bash-exec-tool.cjs
CHANGED
|
@@ -33,9 +33,11 @@ __export(bash_exec_tool_exports, {
|
|
|
33
33
|
module.exports = __toCommonJS(bash_exec_tool_exports);
|
|
34
34
|
var path = __toESM(require("node:path"), 1);
|
|
35
35
|
var import_zod = require("zod");
|
|
36
|
+
var import_core = require("@dexto/core");
|
|
36
37
|
var import_errors = require("./errors.js");
|
|
38
|
+
var import_command_pattern_utils = require("./command-pattern-utils.js");
|
|
37
39
|
const BashExecInputSchema = import_zod.z.object({
|
|
38
|
-
command: import_zod.z.string().describe("Shell command to execute"),
|
|
40
|
+
command: import_zod.z.string().min(1).describe("Shell command to execute"),
|
|
39
41
|
description: import_zod.z.string().optional().describe("Human-readable description of what the command does (5-10 words)"),
|
|
40
42
|
timeout: import_zod.z.number().int().positive().max(6e5).optional().default(12e4).describe(
|
|
41
43
|
"Timeout in milliseconds (max: 600000 = 10 minutes, default: 120000 = 2 minutes)"
|
|
@@ -43,9 +45,10 @@ const BashExecInputSchema = import_zod.z.object({
|
|
|
43
45
|
run_in_background: import_zod.z.boolean().optional().default(false).describe("Execute command in background (default: false)"),
|
|
44
46
|
cwd: import_zod.z.string().optional().describe("Working directory for command execution (optional)")
|
|
45
47
|
}).strict();
|
|
46
|
-
function createBashExecTool(
|
|
47
|
-
return {
|
|
48
|
+
function createBashExecTool(getProcessService) {
|
|
49
|
+
return (0, import_core.defineTool)({
|
|
48
50
|
id: "bash_exec",
|
|
51
|
+
aliases: ["bash"],
|
|
49
52
|
description: `Execute a shell command in the project root directory.
|
|
50
53
|
|
|
51
54
|
IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. Do NOT use it for file operations - use the specialized tools instead:
|
|
@@ -92,27 +95,39 @@ Each command runs in a fresh shell, so cd does not persist between calls.
|
|
|
92
95
|
|
|
93
96
|
Security: Dangerous commands are blocked. Injection attempts are detected. Requires approval with pattern-based session memory.`,
|
|
94
97
|
inputSchema: BashExecInputSchema,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
generatePreview: async (input, _context) => {
|
|
99
|
-
const { command, run_in_background } = input;
|
|
100
|
-
const preview = {
|
|
101
|
-
type: "shell",
|
|
102
|
-
command,
|
|
103
|
-
exitCode: 0,
|
|
104
|
-
// Placeholder - not executed yet
|
|
105
|
-
duration: 0,
|
|
106
|
-
// Placeholder - not executed yet
|
|
107
|
-
...run_in_background !== void 0 && { isBackground: run_in_background }
|
|
108
|
-
};
|
|
109
|
-
return preview;
|
|
98
|
+
approval: {
|
|
99
|
+
patternKey: (input) => (0, import_command_pattern_utils.generateCommandPatternKey)(input.command),
|
|
100
|
+
suggestPatterns: (input) => (0, import_command_pattern_utils.generateCommandPatternSuggestions)(input.command)
|
|
110
101
|
},
|
|
111
|
-
|
|
102
|
+
presentation: {
|
|
103
|
+
describeHeader: (input) => (0, import_core.createLocalToolCallHeader)({
|
|
104
|
+
title: "Bash",
|
|
105
|
+
argsText: (0, import_core.truncateForHeader)(input.command, 140)
|
|
106
|
+
}),
|
|
107
|
+
/**
|
|
108
|
+
* Generate preview for approval UI - shows the command to be executed
|
|
109
|
+
*/
|
|
110
|
+
preview: async (input, _context) => {
|
|
111
|
+
const { command, run_in_background } = input;
|
|
112
|
+
const preview = {
|
|
113
|
+
type: "shell",
|
|
114
|
+
title: "Bash",
|
|
115
|
+
command,
|
|
116
|
+
exitCode: 0,
|
|
117
|
+
// Placeholder - not executed yet
|
|
118
|
+
duration: 0,
|
|
119
|
+
// Placeholder - not executed yet
|
|
120
|
+
isBackground: run_in_background
|
|
121
|
+
};
|
|
122
|
+
return preview;
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
async execute(input, context) {
|
|
126
|
+
const resolvedProcessService = await getProcessService(context);
|
|
112
127
|
const { command, description, timeout, run_in_background, cwd } = input;
|
|
113
128
|
let validatedCwd = cwd;
|
|
114
129
|
if (cwd) {
|
|
115
|
-
const baseDir =
|
|
130
|
+
const baseDir = resolvedProcessService.getConfig().workingDirectory || process.cwd();
|
|
116
131
|
const candidatePath = path.isAbsolute(cwd) ? path.resolve(cwd) : path.resolve(baseDir, cwd);
|
|
117
132
|
const relativePath = path.relative(baseDir, candidatePath);
|
|
118
133
|
const isOutsideBase = relativePath.startsWith("..") || path.isAbsolute(relativePath);
|
|
@@ -124,17 +139,18 @@ Security: Dangerous commands are blocked. Injection attempts are detected. Requi
|
|
|
124
139
|
}
|
|
125
140
|
validatedCwd = candidatePath;
|
|
126
141
|
}
|
|
127
|
-
const result = await
|
|
142
|
+
const result = await resolvedProcessService.executeCommand(command, {
|
|
128
143
|
description,
|
|
129
144
|
timeout,
|
|
130
145
|
runInBackground: run_in_background,
|
|
131
146
|
cwd: validatedCwd,
|
|
132
147
|
// Pass abort signal for cancellation support
|
|
133
|
-
abortSignal: context
|
|
148
|
+
abortSignal: context.abortSignal
|
|
134
149
|
});
|
|
135
150
|
if ("stdout" in result) {
|
|
136
151
|
const _display = {
|
|
137
152
|
type: "shell",
|
|
153
|
+
title: "Bash",
|
|
138
154
|
command,
|
|
139
155
|
exitCode: result.exitCode,
|
|
140
156
|
duration: result.duration,
|
|
@@ -152,6 +168,7 @@ Security: Dangerous commands are blocked. Injection attempts are detected. Requi
|
|
|
152
168
|
} else {
|
|
153
169
|
const _display = {
|
|
154
170
|
type: "shell",
|
|
171
|
+
title: "Bash",
|
|
155
172
|
command,
|
|
156
173
|
exitCode: 0,
|
|
157
174
|
// Background process hasn't exited yet
|
|
@@ -166,7 +183,7 @@ Security: Dangerous commands are blocked. Injection attempts are detected. Requi
|
|
|
166
183
|
};
|
|
167
184
|
}
|
|
168
185
|
}
|
|
169
|
-
};
|
|
186
|
+
});
|
|
170
187
|
}
|
|
171
188
|
// Annotate the CommonJS export names for ESM import in node:
|
|
172
189
|
0 && (module.exports = {
|
package/dist/bash-exec-tool.d.ts
CHANGED
|
@@ -1,17 +1,35 @@
|
|
|
1
|
-
import { InternalTool } from '@dexto/core';
|
|
2
|
-
import { ProcessService } from './process-service.js';
|
|
3
|
-
import './types.js';
|
|
4
|
-
|
|
5
1
|
/**
|
|
6
2
|
* Bash Execute Tool
|
|
7
3
|
*
|
|
8
4
|
* Internal tool for executing shell commands.
|
|
9
|
-
*
|
|
5
|
+
* Pattern-based approval support is declared on the tool (ToolManager stays generic).
|
|
10
6
|
*/
|
|
11
|
-
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { Tool, ToolExecutionContext } from '@dexto/core';
|
|
9
|
+
import { ProcessService } from './process-service.js';
|
|
10
|
+
declare const BashExecInputSchema: z.ZodObject<{
|
|
11
|
+
command: z.ZodString;
|
|
12
|
+
description: z.ZodOptional<z.ZodString>;
|
|
13
|
+
timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
14
|
+
run_in_background: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
15
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
16
|
+
}, "strict", z.ZodTypeAny, {
|
|
17
|
+
command: string;
|
|
18
|
+
timeout: number;
|
|
19
|
+
run_in_background: boolean;
|
|
20
|
+
cwd?: string | undefined;
|
|
21
|
+
description?: string | undefined;
|
|
22
|
+
}, {
|
|
23
|
+
command: string;
|
|
24
|
+
timeout?: number | undefined;
|
|
25
|
+
cwd?: string | undefined;
|
|
26
|
+
description?: string | undefined;
|
|
27
|
+
run_in_background?: boolean | undefined;
|
|
28
|
+
}>;
|
|
12
29
|
/**
|
|
13
30
|
* Create the bash_exec internal tool
|
|
14
31
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export {
|
|
32
|
+
export type ProcessServiceGetter = (context: ToolExecutionContext) => Promise<ProcessService>;
|
|
33
|
+
export declare function createBashExecTool(getProcessService: ProcessServiceGetter): Tool<typeof BashExecInputSchema>;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=bash-exec-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash-exec-tool.d.ts","sourceRoot":"","sources":["../src/bash-exec-tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAQtD,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAwBZ,CAAC;AAEd;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;AAE9F,wBAAgB,kBAAkB,CAC9B,iBAAiB,EAAE,oBAAoB,GACxC,IAAI,CAAC,OAAO,mBAAmB,CAAC,CAmKlC"}
|
package/dist/bash-exec-tool.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { createLocalToolCallHeader, defineTool, truncateForHeader } from "@dexto/core";
|
|
3
4
|
import { ProcessError } from "./errors.js";
|
|
5
|
+
import {
|
|
6
|
+
generateCommandPatternKey,
|
|
7
|
+
generateCommandPatternSuggestions
|
|
8
|
+
} from "./command-pattern-utils.js";
|
|
4
9
|
const BashExecInputSchema = z.object({
|
|
5
|
-
command: z.string().describe("Shell command to execute"),
|
|
10
|
+
command: z.string().min(1).describe("Shell command to execute"),
|
|
6
11
|
description: z.string().optional().describe("Human-readable description of what the command does (5-10 words)"),
|
|
7
12
|
timeout: z.number().int().positive().max(6e5).optional().default(12e4).describe(
|
|
8
13
|
"Timeout in milliseconds (max: 600000 = 10 minutes, default: 120000 = 2 minutes)"
|
|
@@ -10,9 +15,10 @@ const BashExecInputSchema = z.object({
|
|
|
10
15
|
run_in_background: z.boolean().optional().default(false).describe("Execute command in background (default: false)"),
|
|
11
16
|
cwd: z.string().optional().describe("Working directory for command execution (optional)")
|
|
12
17
|
}).strict();
|
|
13
|
-
function createBashExecTool(
|
|
14
|
-
return {
|
|
18
|
+
function createBashExecTool(getProcessService) {
|
|
19
|
+
return defineTool({
|
|
15
20
|
id: "bash_exec",
|
|
21
|
+
aliases: ["bash"],
|
|
16
22
|
description: `Execute a shell command in the project root directory.
|
|
17
23
|
|
|
18
24
|
IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. Do NOT use it for file operations - use the specialized tools instead:
|
|
@@ -59,27 +65,39 @@ Each command runs in a fresh shell, so cd does not persist between calls.
|
|
|
59
65
|
|
|
60
66
|
Security: Dangerous commands are blocked. Injection attempts are detected. Requires approval with pattern-based session memory.`,
|
|
61
67
|
inputSchema: BashExecInputSchema,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
generatePreview: async (input, _context) => {
|
|
66
|
-
const { command, run_in_background } = input;
|
|
67
|
-
const preview = {
|
|
68
|
-
type: "shell",
|
|
69
|
-
command,
|
|
70
|
-
exitCode: 0,
|
|
71
|
-
// Placeholder - not executed yet
|
|
72
|
-
duration: 0,
|
|
73
|
-
// Placeholder - not executed yet
|
|
74
|
-
...run_in_background !== void 0 && { isBackground: run_in_background }
|
|
75
|
-
};
|
|
76
|
-
return preview;
|
|
68
|
+
approval: {
|
|
69
|
+
patternKey: (input) => generateCommandPatternKey(input.command),
|
|
70
|
+
suggestPatterns: (input) => generateCommandPatternSuggestions(input.command)
|
|
77
71
|
},
|
|
78
|
-
|
|
72
|
+
presentation: {
|
|
73
|
+
describeHeader: (input) => createLocalToolCallHeader({
|
|
74
|
+
title: "Bash",
|
|
75
|
+
argsText: truncateForHeader(input.command, 140)
|
|
76
|
+
}),
|
|
77
|
+
/**
|
|
78
|
+
* Generate preview for approval UI - shows the command to be executed
|
|
79
|
+
*/
|
|
80
|
+
preview: async (input, _context) => {
|
|
81
|
+
const { command, run_in_background } = input;
|
|
82
|
+
const preview = {
|
|
83
|
+
type: "shell",
|
|
84
|
+
title: "Bash",
|
|
85
|
+
command,
|
|
86
|
+
exitCode: 0,
|
|
87
|
+
// Placeholder - not executed yet
|
|
88
|
+
duration: 0,
|
|
89
|
+
// Placeholder - not executed yet
|
|
90
|
+
isBackground: run_in_background
|
|
91
|
+
};
|
|
92
|
+
return preview;
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
async execute(input, context) {
|
|
96
|
+
const resolvedProcessService = await getProcessService(context);
|
|
79
97
|
const { command, description, timeout, run_in_background, cwd } = input;
|
|
80
98
|
let validatedCwd = cwd;
|
|
81
99
|
if (cwd) {
|
|
82
|
-
const baseDir =
|
|
100
|
+
const baseDir = resolvedProcessService.getConfig().workingDirectory || process.cwd();
|
|
83
101
|
const candidatePath = path.isAbsolute(cwd) ? path.resolve(cwd) : path.resolve(baseDir, cwd);
|
|
84
102
|
const relativePath = path.relative(baseDir, candidatePath);
|
|
85
103
|
const isOutsideBase = relativePath.startsWith("..") || path.isAbsolute(relativePath);
|
|
@@ -91,17 +109,18 @@ Security: Dangerous commands are blocked. Injection attempts are detected. Requi
|
|
|
91
109
|
}
|
|
92
110
|
validatedCwd = candidatePath;
|
|
93
111
|
}
|
|
94
|
-
const result = await
|
|
112
|
+
const result = await resolvedProcessService.executeCommand(command, {
|
|
95
113
|
description,
|
|
96
114
|
timeout,
|
|
97
115
|
runInBackground: run_in_background,
|
|
98
116
|
cwd: validatedCwd,
|
|
99
117
|
// Pass abort signal for cancellation support
|
|
100
|
-
abortSignal: context
|
|
118
|
+
abortSignal: context.abortSignal
|
|
101
119
|
});
|
|
102
120
|
if ("stdout" in result) {
|
|
103
121
|
const _display = {
|
|
104
122
|
type: "shell",
|
|
123
|
+
title: "Bash",
|
|
105
124
|
command,
|
|
106
125
|
exitCode: result.exitCode,
|
|
107
126
|
duration: result.duration,
|
|
@@ -119,6 +138,7 @@ Security: Dangerous commands are blocked. Injection attempts are detected. Requi
|
|
|
119
138
|
} else {
|
|
120
139
|
const _display = {
|
|
121
140
|
type: "shell",
|
|
141
|
+
title: "Bash",
|
|
122
142
|
command,
|
|
123
143
|
exitCode: 0,
|
|
124
144
|
// Background process hasn't exited yet
|
|
@@ -133,7 +153,7 @@ Security: Dangerous commands are blocked. Injection attempts are detected. Requi
|
|
|
133
153
|
};
|
|
134
154
|
}
|
|
135
155
|
}
|
|
136
|
-
};
|
|
156
|
+
});
|
|
137
157
|
}
|
|
138
158
|
export {
|
|
139
159
|
createBashExecTool
|
|
@@ -22,17 +22,25 @@ __export(bash_output_tool_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(bash_output_tool_exports);
|
|
24
24
|
var import_zod = require("zod");
|
|
25
|
+
var import_core = require("@dexto/core");
|
|
25
26
|
const BashOutputInputSchema = import_zod.z.object({
|
|
26
27
|
process_id: import_zod.z.string().describe("Process ID from bash_exec (when run_in_background=true)")
|
|
27
28
|
}).strict();
|
|
28
|
-
function createBashOutputTool(
|
|
29
|
-
return {
|
|
29
|
+
function createBashOutputTool(getProcessService) {
|
|
30
|
+
return (0, import_core.defineTool)({
|
|
30
31
|
id: "bash_output",
|
|
31
32
|
description: "Retrieve output from a background process started with bash_exec. Returns stdout, stderr, status (running/completed/failed), exit code, and duration. Each call returns only new output since last read. The output buffer is cleared after reading. Use this tool to monitor long-running commands.",
|
|
32
33
|
inputSchema: BashOutputInputSchema,
|
|
33
|
-
|
|
34
|
+
presentation: {
|
|
35
|
+
describeHeader: (input) => (0, import_core.createLocalToolCallHeader)({
|
|
36
|
+
title: "Bash Output",
|
|
37
|
+
argsText: (0, import_core.truncateForHeader)(input.process_id, 80)
|
|
38
|
+
})
|
|
39
|
+
},
|
|
40
|
+
async execute(input, context) {
|
|
41
|
+
const resolvedProcessService = await getProcessService(context);
|
|
34
42
|
const { process_id } = input;
|
|
35
|
-
const result = await
|
|
43
|
+
const result = await resolvedProcessService.getProcessOutput(process_id);
|
|
36
44
|
return {
|
|
37
45
|
stdout: result.stdout,
|
|
38
46
|
stderr: result.stderr,
|
|
@@ -41,7 +49,7 @@ function createBashOutputTool(processService) {
|
|
|
41
49
|
...result.duration !== void 0 && { duration: result.duration }
|
|
42
50
|
};
|
|
43
51
|
}
|
|
44
|
-
};
|
|
52
|
+
});
|
|
45
53
|
}
|
|
46
54
|
// Annotate the CommonJS export names for ESM import in node:
|
|
47
55
|
0 && (module.exports = {
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import { InternalTool } from '@dexto/core';
|
|
2
|
-
import { ProcessService } from './process-service.js';
|
|
3
|
-
import './types.js';
|
|
4
|
-
|
|
5
1
|
/**
|
|
6
2
|
* Bash Output Tool
|
|
7
3
|
*
|
|
8
4
|
* Internal tool for retrieving output from background processes
|
|
9
5
|
*/
|
|
10
|
-
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import type { Tool } from '@dexto/core';
|
|
8
|
+
import type { ProcessServiceGetter } from './bash-exec-tool.js';
|
|
9
|
+
declare const BashOutputInputSchema: z.ZodObject<{
|
|
10
|
+
process_id: z.ZodString;
|
|
11
|
+
}, "strict", z.ZodTypeAny, {
|
|
12
|
+
process_id: string;
|
|
13
|
+
}, {
|
|
14
|
+
process_id: string;
|
|
15
|
+
}>;
|
|
11
16
|
/**
|
|
12
17
|
* Create the bash_output internal tool
|
|
13
18
|
*/
|
|
14
|
-
declare function createBashOutputTool(
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
export declare function createBashOutputTool(getProcessService: ProcessServiceGetter): Tool<typeof BashOutputInputSchema>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=bash-output-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash-output-tool.d.ts","sourceRoot":"","sources":["../src/bash-output-tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,QAAA,MAAM,qBAAqB;;;;;;EAId,CAAC;AAEd;;GAEG;AACH,wBAAgB,oBAAoB,CAChC,iBAAiB,EAAE,oBAAoB,GACxC,IAAI,CAAC,OAAO,qBAAqB,CAAC,CA+BpC"}
|
package/dist/bash-output-tool.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { createLocalToolCallHeader, defineTool, truncateForHeader } from "@dexto/core";
|
|
2
3
|
const BashOutputInputSchema = z.object({
|
|
3
4
|
process_id: z.string().describe("Process ID from bash_exec (when run_in_background=true)")
|
|
4
5
|
}).strict();
|
|
5
|
-
function createBashOutputTool(
|
|
6
|
-
return {
|
|
6
|
+
function createBashOutputTool(getProcessService) {
|
|
7
|
+
return defineTool({
|
|
7
8
|
id: "bash_output",
|
|
8
9
|
description: "Retrieve output from a background process started with bash_exec. Returns stdout, stderr, status (running/completed/failed), exit code, and duration. Each call returns only new output since last read. The output buffer is cleared after reading. Use this tool to monitor long-running commands.",
|
|
9
10
|
inputSchema: BashOutputInputSchema,
|
|
10
|
-
|
|
11
|
+
presentation: {
|
|
12
|
+
describeHeader: (input) => createLocalToolCallHeader({
|
|
13
|
+
title: "Bash Output",
|
|
14
|
+
argsText: truncateForHeader(input.process_id, 80)
|
|
15
|
+
})
|
|
16
|
+
},
|
|
17
|
+
async execute(input, context) {
|
|
18
|
+
const resolvedProcessService = await getProcessService(context);
|
|
11
19
|
const { process_id } = input;
|
|
12
|
-
const result = await
|
|
20
|
+
const result = await resolvedProcessService.getProcessOutput(process_id);
|
|
13
21
|
return {
|
|
14
22
|
stdout: result.stdout,
|
|
15
23
|
stderr: result.stderr,
|
|
@@ -18,7 +26,7 @@ function createBashOutputTool(processService) {
|
|
|
18
26
|
...result.duration !== void 0 && { duration: result.duration }
|
|
19
27
|
};
|
|
20
28
|
}
|
|
21
|
-
};
|
|
29
|
+
});
|
|
22
30
|
}
|
|
23
31
|
export {
|
|
24
32
|
createBashOutputTool
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var command_pattern_utils_exports = {};
|
|
20
|
+
__export(command_pattern_utils_exports, {
|
|
21
|
+
DANGEROUS_COMMAND_PREFIXES: () => DANGEROUS_COMMAND_PREFIXES,
|
|
22
|
+
generateCommandPatternKey: () => generateCommandPatternKey,
|
|
23
|
+
generateCommandPatternSuggestions: () => generateCommandPatternSuggestions,
|
|
24
|
+
isDangerousCommand: () => isDangerousCommand
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(command_pattern_utils_exports);
|
|
27
|
+
const DANGEROUS_COMMAND_PREFIXES = [
|
|
28
|
+
"rm",
|
|
29
|
+
"chmod",
|
|
30
|
+
"chown",
|
|
31
|
+
"chgrp",
|
|
32
|
+
"sudo",
|
|
33
|
+
"su",
|
|
34
|
+
"dd",
|
|
35
|
+
"mkfs",
|
|
36
|
+
"fdisk",
|
|
37
|
+
"parted",
|
|
38
|
+
"kill",
|
|
39
|
+
"killall",
|
|
40
|
+
"pkill",
|
|
41
|
+
"shutdown",
|
|
42
|
+
"reboot",
|
|
43
|
+
"halt",
|
|
44
|
+
"poweroff"
|
|
45
|
+
];
|
|
46
|
+
function isDangerousCommand(command) {
|
|
47
|
+
const tokens = command.trim().split(/\s+/);
|
|
48
|
+
if (!tokens[0]) return false;
|
|
49
|
+
const head = tokens[0].toLowerCase();
|
|
50
|
+
return DANGEROUS_COMMAND_PREFIXES.includes(head);
|
|
51
|
+
}
|
|
52
|
+
function generateCommandPatternKey(command) {
|
|
53
|
+
const tokens = command.trim().split(/\s+/);
|
|
54
|
+
if (!tokens[0]) return null;
|
|
55
|
+
const head = tokens[0].toLowerCase();
|
|
56
|
+
if (isDangerousCommand(command)) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const subcommand = tokens.slice(1).find((arg) => !arg.startsWith("-"));
|
|
60
|
+
return subcommand ? `${head} ${subcommand.toLowerCase()} *` : `${head} *`;
|
|
61
|
+
}
|
|
62
|
+
function generateCommandPatternSuggestions(command) {
|
|
63
|
+
const tokens = command.trim().toLowerCase().split(/\s+/);
|
|
64
|
+
if (!tokens[0]) return [];
|
|
65
|
+
const head = tokens[0];
|
|
66
|
+
if (isDangerousCommand(command)) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
const patterns = [];
|
|
70
|
+
const nonFlagArgs = tokens.slice(1).filter((arg) => !arg.startsWith("-"));
|
|
71
|
+
if (nonFlagArgs.length > 0) {
|
|
72
|
+
patterns.push(`${head} ${nonFlagArgs[0]} *`);
|
|
73
|
+
}
|
|
74
|
+
patterns.push(`${head} *`);
|
|
75
|
+
return patterns;
|
|
76
|
+
}
|
|
77
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
78
|
+
0 && (module.exports = {
|
|
79
|
+
DANGEROUS_COMMAND_PREFIXES,
|
|
80
|
+
generateCommandPatternKey,
|
|
81
|
+
generateCommandPatternSuggestions,
|
|
82
|
+
isDangerousCommand
|
|
83
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for generating approval patterns for shell commands.
|
|
3
|
+
*
|
|
4
|
+
* Pattern-based approvals allow users to approve command patterns like "git *"
|
|
5
|
+
* that automatically cover future matching commands (e.g., "git status", "git push").
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Commands that should never get auto-approve pattern suggestions.
|
|
9
|
+
* These require explicit approval each time for safety.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DANGEROUS_COMMAND_PREFIXES: readonly ["rm", "chmod", "chown", "chgrp", "sudo", "su", "dd", "mkfs", "fdisk", "parted", "kill", "killall", "pkill", "shutdown", "reboot", "halt", "poweroff"];
|
|
12
|
+
export declare function isDangerousCommand(command: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Generate the pattern key for a shell command.
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* - "ls -la" → "ls *" (flags don't count as subcommand)
|
|
18
|
+
* - "git push origin" → "git push *" (first non-flag arg is subcommand)
|
|
19
|
+
* - "rm -rf /" → null (dangerous command)
|
|
20
|
+
*/
|
|
21
|
+
export declare function generateCommandPatternKey(command: string): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Generate suggested patterns for UI selection.
|
|
24
|
+
* Returns progressively broader patterns from specific to general.
|
|
25
|
+
*
|
|
26
|
+
* Example: "git push origin main" → ["git push *", "git *"]
|
|
27
|
+
*/
|
|
28
|
+
export declare function generateCommandPatternSuggestions(command: string): string[];
|
|
29
|
+
//# sourceMappingURL=command-pattern-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-pattern-utils.d.ts","sourceRoot":"","sources":["../src/command-pattern-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,eAAO,MAAM,0BAA0B,iKAkB7B,CAAC;AAEX,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAK3D;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYxE;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB3E"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const DANGEROUS_COMMAND_PREFIXES = [
|
|
2
|
+
"rm",
|
|
3
|
+
"chmod",
|
|
4
|
+
"chown",
|
|
5
|
+
"chgrp",
|
|
6
|
+
"sudo",
|
|
7
|
+
"su",
|
|
8
|
+
"dd",
|
|
9
|
+
"mkfs",
|
|
10
|
+
"fdisk",
|
|
11
|
+
"parted",
|
|
12
|
+
"kill",
|
|
13
|
+
"killall",
|
|
14
|
+
"pkill",
|
|
15
|
+
"shutdown",
|
|
16
|
+
"reboot",
|
|
17
|
+
"halt",
|
|
18
|
+
"poweroff"
|
|
19
|
+
];
|
|
20
|
+
function isDangerousCommand(command) {
|
|
21
|
+
const tokens = command.trim().split(/\s+/);
|
|
22
|
+
if (!tokens[0]) return false;
|
|
23
|
+
const head = tokens[0].toLowerCase();
|
|
24
|
+
return DANGEROUS_COMMAND_PREFIXES.includes(head);
|
|
25
|
+
}
|
|
26
|
+
function generateCommandPatternKey(command) {
|
|
27
|
+
const tokens = command.trim().split(/\s+/);
|
|
28
|
+
if (!tokens[0]) return null;
|
|
29
|
+
const head = tokens[0].toLowerCase();
|
|
30
|
+
if (isDangerousCommand(command)) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const subcommand = tokens.slice(1).find((arg) => !arg.startsWith("-"));
|
|
34
|
+
return subcommand ? `${head} ${subcommand.toLowerCase()} *` : `${head} *`;
|
|
35
|
+
}
|
|
36
|
+
function generateCommandPatternSuggestions(command) {
|
|
37
|
+
const tokens = command.trim().toLowerCase().split(/\s+/);
|
|
38
|
+
if (!tokens[0]) return [];
|
|
39
|
+
const head = tokens[0];
|
|
40
|
+
if (isDangerousCommand(command)) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
const patterns = [];
|
|
44
|
+
const nonFlagArgs = tokens.slice(1).filter((arg) => !arg.startsWith("-"));
|
|
45
|
+
if (nonFlagArgs.length > 0) {
|
|
46
|
+
patterns.push(`${head} ${nonFlagArgs[0]} *`);
|
|
47
|
+
}
|
|
48
|
+
patterns.push(`${head} *`);
|
|
49
|
+
return patterns;
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
DANGEROUS_COMMAND_PREFIXES,
|
|
53
|
+
generateCommandPatternKey,
|
|
54
|
+
generateCommandPatternSuggestions,
|
|
55
|
+
isDangerousCommand
|
|
56
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_command_pattern_utils = require("./command-pattern-utils.js");
|
|
3
|
+
var import_vitest = require("vitest");
|
|
4
|
+
(0, import_vitest.describe)("command-pattern-utils", () => {
|
|
5
|
+
(0, import_vitest.describe)("isDangerousCommand", () => {
|
|
6
|
+
(0, import_vitest.it)("should detect dangerous commands", () => {
|
|
7
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("rm -rf /")).toBe(true);
|
|
8
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("sudo apt install")).toBe(true);
|
|
9
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("chmod 777 file")).toBe(true);
|
|
10
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("kill -9 1234")).toBe(true);
|
|
11
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("dd if=/dev/zero of=/dev/sda")).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
(0, import_vitest.it)("should not flag safe commands", () => {
|
|
14
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("ls -la")).toBe(false);
|
|
15
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("git status")).toBe(false);
|
|
16
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("npm install")).toBe(false);
|
|
17
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("cat file.txt")).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
(0, import_vitest.it)("should be case-insensitive", () => {
|
|
20
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("RM -rf /")).toBe(true);
|
|
21
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("SUDO apt install")).toBe(true);
|
|
22
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("Chmod 777 file")).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
(0, import_vitest.it)("should handle empty input", () => {
|
|
25
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)("")).toBe(false);
|
|
26
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.isDangerousCommand)(" ")).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
(0, import_vitest.describe)("generateCommandPatternKey", () => {
|
|
30
|
+
(0, import_vitest.it)("should generate patterns for simple commands", () => {
|
|
31
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("ls")).toBe("ls *");
|
|
32
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("pwd")).toBe("pwd *");
|
|
33
|
+
});
|
|
34
|
+
(0, import_vitest.it)("should ignore flags when choosing subcommand", () => {
|
|
35
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("ls -la")).toBe("ls *");
|
|
36
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("git -v status")).toBe("git status *");
|
|
37
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("npm --verbose install")).toBe("npm install *");
|
|
38
|
+
});
|
|
39
|
+
(0, import_vitest.it)("should generate subcommand patterns", () => {
|
|
40
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("git status")).toBe("git status *");
|
|
41
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("git push origin main")).toBe("git push *");
|
|
42
|
+
});
|
|
43
|
+
(0, import_vitest.it)("should return null for dangerous commands", () => {
|
|
44
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("rm -rf /")).toBeNull();
|
|
45
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("sudo apt install")).toBeNull();
|
|
46
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("shutdown -h now")).toBeNull();
|
|
47
|
+
});
|
|
48
|
+
(0, import_vitest.it)("should handle empty input", () => {
|
|
49
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)("")).toBeNull();
|
|
50
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)(" ")).toBeNull();
|
|
51
|
+
});
|
|
52
|
+
(0, import_vitest.it)("should trim and normalize whitespace", () => {
|
|
53
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)(" ls -la ")).toBe("ls *");
|
|
54
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternKey)(" git push origin ")).toBe("git push *");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
(0, import_vitest.describe)("generateCommandPatternSuggestions", () => {
|
|
58
|
+
(0, import_vitest.it)("should generate broad-to-narrow suggestions", () => {
|
|
59
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternSuggestions)("ls")).toEqual(["ls *"]);
|
|
60
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternSuggestions)("git push origin main")).toEqual([
|
|
61
|
+
"git push *",
|
|
62
|
+
"git *"
|
|
63
|
+
]);
|
|
64
|
+
});
|
|
65
|
+
(0, import_vitest.it)("should return empty for dangerous commands", () => {
|
|
66
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternSuggestions)("rm -rf /")).toEqual([]);
|
|
67
|
+
});
|
|
68
|
+
(0, import_vitest.it)("should handle empty input", () => {
|
|
69
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternSuggestions)("")).toEqual([]);
|
|
70
|
+
(0, import_vitest.expect)((0, import_command_pattern_utils.generateCommandPatternSuggestions)(" ")).toEqual([]);
|
|
71
|
+
});
|
|
72
|
+
(0, import_vitest.it)("should keep suggestions consistent with pattern key", () => {
|
|
73
|
+
const command = "git push origin main";
|
|
74
|
+
const patternKey = (0, import_command_pattern_utils.generateCommandPatternKey)(command);
|
|
75
|
+
const suggestions = (0, import_command_pattern_utils.generateCommandPatternSuggestions)(command);
|
|
76
|
+
(0, import_vitest.expect)(patternKey).toBe("git push *");
|
|
77
|
+
(0, import_vitest.expect)(suggestions[0]).toBe(patternKey);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-pattern-utils.test.d.ts","sourceRoot":"","sources":["../src/command-pattern-utils.test.ts"],"names":[],"mappings":""}
|