@dexto/tools-process 1.5.3 → 1.5.5

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.
@@ -46,7 +46,51 @@ const BashExecInputSchema = import_zod.z.object({
46
46
  function createBashExecTool(processService) {
47
47
  return {
48
48
  id: "bash_exec",
49
- description: "Execute a shell command with 2-minute default timeout. Returns stdout, stderr, exit code, and duration. For long-running commands (servers, watchers, npm run dev), MUST use run_in_background=true (use bash_output to retrieve results later). Commands ending with & are blocked - use run_in_background instead. Requires approval (with pattern-based session memory). Always quote file paths with spaces. Security: dangerous commands are blocked, injection attempts are detected.",
49
+ description: `Execute a shell command in the project root directory.
50
+
51
+ IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. Do NOT use it for file operations - use the specialized tools instead:
52
+ - File search: Use glob_files (NOT find or ls)
53
+ - Content search: Use grep_content (NOT grep or rg)
54
+ - Read files: Use read_file (NOT cat/head/tail)
55
+ - Edit files: Use edit_file (NOT sed/awk)
56
+ - Write files: Use write_file (NOT echo/cat with heredoc)
57
+
58
+ Before executing the command, follow these steps:
59
+
60
+ 1. Directory Verification:
61
+ - If the command will create new directories or files, first use ls to verify the parent directory exists and is the correct location
62
+ - For example, before running "mkdir foo/bar", first use ls foo to check that "foo" exists
63
+
64
+ 2. Command Execution:
65
+ - Always quote file paths that contain spaces with double quotes
66
+ - Examples of proper quoting:
67
+ - cd "/Users/name/My Documents" (correct)
68
+ - cd /Users/name/My Documents (incorrect - will fail)
69
+ - python "/path/with spaces/script.py" (correct)
70
+ - python /path/with spaces/script.py (incorrect - will fail)
71
+
72
+ Usage notes:
73
+ - The command argument is required.
74
+ - You can specify an optional timeout in milliseconds (max 600000ms / 10 minutes). Default is 120000ms (2 minutes).
75
+ - The description parameter should be a clear, concise summary of what the command does (5-10 words for simple commands, more context for complex commands).
76
+ - If the output exceeds 1MB, it will be truncated.
77
+ - You can use run_in_background=true to run the command in the background. Use this when you don't need the result immediately. You do not need to check the output right away - use bash_output to retrieve results later. Commands ending with & are blocked; use run_in_background instead.
78
+
79
+ When issuing multiple commands:
80
+ - If the commands are independent and can run in parallel, make multiple bash_exec calls in a single response.
81
+ - If the commands depend on each other and must run sequentially, use a single call with && to chain them (e.g., git add . && git commit -m "msg" && git push).
82
+ - Use ; only when you need to run commands sequentially but don't care if earlier commands fail.
83
+ - Do NOT use newlines to separate commands (newlines are ok in quoted strings).
84
+
85
+ Try to maintain your working directory throughout the session by using absolute paths and avoiding usage of cd. You may use cd if the user explicitly requests it.
86
+ - GOOD: pnpm test
87
+ - GOOD: pytest /absolute/path/to/tests
88
+ - BAD: cd /project && pnpm test
89
+ - BAD: cd /some/path && command
90
+
91
+ Each command runs in a fresh shell, so cd does not persist between calls.
92
+
93
+ Security: Dangerous commands are blocked. Injection attempts are detected. Requires approval with pattern-based session memory.`,
50
94
  inputSchema: BashExecInputSchema,
51
95
  /**
52
96
  * Generate preview for approval UI - shows the command to be executed
@@ -13,7 +13,51 @@ const BashExecInputSchema = z.object({
13
13
  function createBashExecTool(processService) {
14
14
  return {
15
15
  id: "bash_exec",
16
- description: "Execute a shell command with 2-minute default timeout. Returns stdout, stderr, exit code, and duration. For long-running commands (servers, watchers, npm run dev), MUST use run_in_background=true (use bash_output to retrieve results later). Commands ending with & are blocked - use run_in_background instead. Requires approval (with pattern-based session memory). Always quote file paths with spaces. Security: dangerous commands are blocked, injection attempts are detected.",
16
+ description: `Execute a shell command in the project root directory.
17
+
18
+ IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. Do NOT use it for file operations - use the specialized tools instead:
19
+ - File search: Use glob_files (NOT find or ls)
20
+ - Content search: Use grep_content (NOT grep or rg)
21
+ - Read files: Use read_file (NOT cat/head/tail)
22
+ - Edit files: Use edit_file (NOT sed/awk)
23
+ - Write files: Use write_file (NOT echo/cat with heredoc)
24
+
25
+ Before executing the command, follow these steps:
26
+
27
+ 1. Directory Verification:
28
+ - If the command will create new directories or files, first use ls to verify the parent directory exists and is the correct location
29
+ - For example, before running "mkdir foo/bar", first use ls foo to check that "foo" exists
30
+
31
+ 2. Command Execution:
32
+ - Always quote file paths that contain spaces with double quotes
33
+ - Examples of proper quoting:
34
+ - cd "/Users/name/My Documents" (correct)
35
+ - cd /Users/name/My Documents (incorrect - will fail)
36
+ - python "/path/with spaces/script.py" (correct)
37
+ - python /path/with spaces/script.py (incorrect - will fail)
38
+
39
+ Usage notes:
40
+ - The command argument is required.
41
+ - You can specify an optional timeout in milliseconds (max 600000ms / 10 minutes). Default is 120000ms (2 minutes).
42
+ - The description parameter should be a clear, concise summary of what the command does (5-10 words for simple commands, more context for complex commands).
43
+ - If the output exceeds 1MB, it will be truncated.
44
+ - You can use run_in_background=true to run the command in the background. Use this when you don't need the result immediately. You do not need to check the output right away - use bash_output to retrieve results later. Commands ending with & are blocked; use run_in_background instead.
45
+
46
+ When issuing multiple commands:
47
+ - If the commands are independent and can run in parallel, make multiple bash_exec calls in a single response.
48
+ - If the commands depend on each other and must run sequentially, use a single call with && to chain them (e.g., git add . && git commit -m "msg" && git push).
49
+ - Use ; only when you need to run commands sequentially but don't care if earlier commands fail.
50
+ - Do NOT use newlines to separate commands (newlines are ok in quoted strings).
51
+
52
+ Try to maintain your working directory throughout the session by using absolute paths and avoiding usage of cd. You may use cd if the user explicitly requests it.
53
+ - GOOD: pnpm test
54
+ - GOOD: pytest /absolute/path/to/tests
55
+ - BAD: cd /project && pnpm test
56
+ - BAD: cd /some/path && command
57
+
58
+ Each command runs in a fresh shell, so cd does not persist between calls.
59
+
60
+ Security: Dangerous commands are blocked. Injection attempts are detected. Requires approval with pattern-based session memory.`,
17
61
  inputSchema: BashExecInputSchema,
18
62
  /**
19
63
  * Generate preview for approval UI - shows the command to be executed
package/dist/errors.cjs CHANGED
@@ -23,6 +23,7 @@ __export(errors_exports, {
23
23
  module.exports = __toCommonJS(errors_exports);
24
24
  var import_core = require("@dexto/core");
25
25
  var import_error_codes = require("./error-codes.js");
26
+ const PROCESS_SCOPE = "process";
26
27
  class ProcessError {
27
28
  constructor() {
28
29
  }
@@ -32,7 +33,7 @@ class ProcessError {
32
33
  static invalidCommand(command, reason) {
33
34
  return new import_core.DextoRuntimeError(
34
35
  import_error_codes.ProcessErrorCode.INVALID_COMMAND,
35
- import_core.ErrorScope.PROCESS,
36
+ PROCESS_SCOPE,
36
37
  import_core.ErrorType.USER,
37
38
  `Invalid command: ${command}. ${reason}`,
38
39
  { command, reason }
@@ -44,7 +45,7 @@ class ProcessError {
44
45
  static commandBlocked(command, reason) {
45
46
  return new import_core.DextoRuntimeError(
46
47
  import_error_codes.ProcessErrorCode.COMMAND_BLOCKED,
47
- import_core.ErrorScope.PROCESS,
48
+ PROCESS_SCOPE,
48
49
  import_core.ErrorType.FORBIDDEN,
49
50
  `Command is blocked: ${command}. ${reason}`,
50
51
  { command, reason }
@@ -56,7 +57,7 @@ class ProcessError {
56
57
  static commandTooLong(length, maxLength) {
57
58
  return new import_core.DextoRuntimeError(
58
59
  import_error_codes.ProcessErrorCode.COMMAND_TOO_LONG,
59
- import_core.ErrorScope.PROCESS,
60
+ PROCESS_SCOPE,
60
61
  import_core.ErrorType.USER,
61
62
  `Command too long: ${length} characters. Maximum allowed: ${maxLength}`,
62
63
  { length, maxLength }
@@ -68,7 +69,7 @@ class ProcessError {
68
69
  static commandInjection(command, pattern) {
69
70
  return new import_core.DextoRuntimeError(
70
71
  import_error_codes.ProcessErrorCode.INJECTION_DETECTED,
71
- import_core.ErrorScope.PROCESS,
72
+ PROCESS_SCOPE,
72
73
  import_core.ErrorType.FORBIDDEN,
73
74
  `Potential command injection detected in: ${command}. Pattern: ${pattern}`,
74
75
  { command, pattern }
@@ -80,7 +81,7 @@ class ProcessError {
80
81
  static approvalRequired(command, reason) {
81
82
  return new import_core.DextoRuntimeError(
82
83
  import_error_codes.ProcessErrorCode.APPROVAL_REQUIRED,
83
- import_core.ErrorScope.PROCESS,
84
+ PROCESS_SCOPE,
84
85
  import_core.ErrorType.FORBIDDEN,
85
86
  `Command requires approval: ${command}${reason ? `. ${reason}` : ""}`,
86
87
  { command, reason },
@@ -93,7 +94,7 @@ class ProcessError {
93
94
  static approvalDenied(command) {
94
95
  return new import_core.DextoRuntimeError(
95
96
  import_error_codes.ProcessErrorCode.APPROVAL_DENIED,
96
- import_core.ErrorScope.PROCESS,
97
+ PROCESS_SCOPE,
97
98
  import_core.ErrorType.FORBIDDEN,
98
99
  `Command approval denied by user: ${command}`,
99
100
  { command }
@@ -105,7 +106,7 @@ class ProcessError {
105
106
  static executionFailed(command, cause) {
106
107
  return new import_core.DextoRuntimeError(
107
108
  import_error_codes.ProcessErrorCode.EXECUTION_FAILED,
108
- import_core.ErrorScope.PROCESS,
109
+ PROCESS_SCOPE,
109
110
  import_core.ErrorType.SYSTEM,
110
111
  `Command execution failed: ${command}. ${cause}`,
111
112
  { command, cause }
@@ -117,7 +118,7 @@ class ProcessError {
117
118
  static timeout(command, timeout) {
118
119
  return new import_core.DextoRuntimeError(
119
120
  import_error_codes.ProcessErrorCode.TIMEOUT,
120
- import_core.ErrorScope.PROCESS,
121
+ PROCESS_SCOPE,
121
122
  import_core.ErrorType.TIMEOUT,
122
123
  `Command timed out after ${timeout}ms: ${command}`,
123
124
  { command, timeout },
@@ -130,7 +131,7 @@ class ProcessError {
130
131
  static permissionDenied(command) {
131
132
  return new import_core.DextoRuntimeError(
132
133
  import_error_codes.ProcessErrorCode.PERMISSION_DENIED,
133
- import_core.ErrorScope.PROCESS,
134
+ PROCESS_SCOPE,
134
135
  import_core.ErrorType.FORBIDDEN,
135
136
  `Permission denied: ${command}`,
136
137
  { command }
@@ -142,7 +143,7 @@ class ProcessError {
142
143
  static commandNotFound(command) {
143
144
  return new import_core.DextoRuntimeError(
144
145
  import_error_codes.ProcessErrorCode.COMMAND_NOT_FOUND,
145
- import_core.ErrorScope.PROCESS,
146
+ PROCESS_SCOPE,
146
147
  import_core.ErrorType.NOT_FOUND,
147
148
  `Command not found: ${command}`,
148
149
  { command },
@@ -155,7 +156,7 @@ class ProcessError {
155
156
  static invalidWorkingDirectory(path, reason) {
156
157
  return new import_core.DextoRuntimeError(
157
158
  import_error_codes.ProcessErrorCode.WORKING_DIRECTORY_INVALID,
158
- import_core.ErrorScope.PROCESS,
159
+ PROCESS_SCOPE,
159
160
  import_core.ErrorType.USER,
160
161
  `Invalid working directory: ${path}. ${reason}`,
161
162
  { path, reason }
@@ -167,7 +168,7 @@ class ProcessError {
167
168
  static processNotFound(processId) {
168
169
  return new import_core.DextoRuntimeError(
169
170
  import_error_codes.ProcessErrorCode.PROCESS_NOT_FOUND,
170
- import_core.ErrorScope.PROCESS,
171
+ PROCESS_SCOPE,
171
172
  import_core.ErrorType.NOT_FOUND,
172
173
  `Process not found: ${processId}`,
173
174
  { processId }
@@ -179,7 +180,7 @@ class ProcessError {
179
180
  static tooManyProcesses(current, max) {
180
181
  return new import_core.DextoRuntimeError(
181
182
  import_error_codes.ProcessErrorCode.TOO_MANY_PROCESSES,
182
- import_core.ErrorScope.PROCESS,
183
+ PROCESS_SCOPE,
183
184
  import_core.ErrorType.USER,
184
185
  `Too many concurrent processes: ${current}. Maximum allowed: ${max}`,
185
186
  { current, max },
@@ -192,7 +193,7 @@ class ProcessError {
192
193
  static killFailed(processId, cause) {
193
194
  return new import_core.DextoRuntimeError(
194
195
  import_error_codes.ProcessErrorCode.KILL_FAILED,
195
- import_core.ErrorScope.PROCESS,
196
+ PROCESS_SCOPE,
196
197
  import_core.ErrorType.SYSTEM,
197
198
  `Failed to kill process ${processId}: ${cause}`,
198
199
  { processId, cause }
@@ -204,7 +205,7 @@ class ProcessError {
204
205
  static outputBufferFull(processId, size, maxSize) {
205
206
  return new import_core.DextoRuntimeError(
206
207
  import_error_codes.ProcessErrorCode.OUTPUT_BUFFER_FULL,
207
- import_core.ErrorScope.PROCESS,
208
+ PROCESS_SCOPE,
208
209
  import_core.ErrorType.SYSTEM,
209
210
  `Output buffer full for process ${processId}: ${size} bytes. Maximum: ${maxSize}`,
210
211
  { processId, size, maxSize },
@@ -217,7 +218,7 @@ class ProcessError {
217
218
  static invalidConfig(reason) {
218
219
  return new import_core.DextoRuntimeError(
219
220
  import_error_codes.ProcessErrorCode.INVALID_CONFIG,
220
- import_core.ErrorScope.PROCESS,
221
+ PROCESS_SCOPE,
221
222
  import_core.ErrorType.USER,
222
223
  `Invalid Process configuration: ${reason}`,
223
224
  { reason }
@@ -229,7 +230,7 @@ class ProcessError {
229
230
  static notInitialized() {
230
231
  return new import_core.DextoRuntimeError(
231
232
  import_error_codes.ProcessErrorCode.SERVICE_NOT_INITIALIZED,
232
- import_core.ErrorScope.PROCESS,
233
+ PROCESS_SCOPE,
233
234
  import_core.ErrorType.SYSTEM,
234
235
  "ProcessService has not been initialized",
235
236
  {},
package/dist/errors.js CHANGED
@@ -1,4 +1,5 @@
1
- import { DextoRuntimeError, ErrorScope, ErrorType } from "@dexto/core";
1
+ import { DextoRuntimeError, ErrorType } from "@dexto/core";
2
+ const PROCESS_SCOPE = "process";
2
3
  import { ProcessErrorCode } from "./error-codes.js";
3
4
  class ProcessError {
4
5
  constructor() {
@@ -9,7 +10,7 @@ class ProcessError {
9
10
  static invalidCommand(command, reason) {
10
11
  return new DextoRuntimeError(
11
12
  ProcessErrorCode.INVALID_COMMAND,
12
- ErrorScope.PROCESS,
13
+ PROCESS_SCOPE,
13
14
  ErrorType.USER,
14
15
  `Invalid command: ${command}. ${reason}`,
15
16
  { command, reason }
@@ -21,7 +22,7 @@ class ProcessError {
21
22
  static commandBlocked(command, reason) {
22
23
  return new DextoRuntimeError(
23
24
  ProcessErrorCode.COMMAND_BLOCKED,
24
- ErrorScope.PROCESS,
25
+ PROCESS_SCOPE,
25
26
  ErrorType.FORBIDDEN,
26
27
  `Command is blocked: ${command}. ${reason}`,
27
28
  { command, reason }
@@ -33,7 +34,7 @@ class ProcessError {
33
34
  static commandTooLong(length, maxLength) {
34
35
  return new DextoRuntimeError(
35
36
  ProcessErrorCode.COMMAND_TOO_LONG,
36
- ErrorScope.PROCESS,
37
+ PROCESS_SCOPE,
37
38
  ErrorType.USER,
38
39
  `Command too long: ${length} characters. Maximum allowed: ${maxLength}`,
39
40
  { length, maxLength }
@@ -45,7 +46,7 @@ class ProcessError {
45
46
  static commandInjection(command, pattern) {
46
47
  return new DextoRuntimeError(
47
48
  ProcessErrorCode.INJECTION_DETECTED,
48
- ErrorScope.PROCESS,
49
+ PROCESS_SCOPE,
49
50
  ErrorType.FORBIDDEN,
50
51
  `Potential command injection detected in: ${command}. Pattern: ${pattern}`,
51
52
  { command, pattern }
@@ -57,7 +58,7 @@ class ProcessError {
57
58
  static approvalRequired(command, reason) {
58
59
  return new DextoRuntimeError(
59
60
  ProcessErrorCode.APPROVAL_REQUIRED,
60
- ErrorScope.PROCESS,
61
+ PROCESS_SCOPE,
61
62
  ErrorType.FORBIDDEN,
62
63
  `Command requires approval: ${command}${reason ? `. ${reason}` : ""}`,
63
64
  { command, reason },
@@ -70,7 +71,7 @@ class ProcessError {
70
71
  static approvalDenied(command) {
71
72
  return new DextoRuntimeError(
72
73
  ProcessErrorCode.APPROVAL_DENIED,
73
- ErrorScope.PROCESS,
74
+ PROCESS_SCOPE,
74
75
  ErrorType.FORBIDDEN,
75
76
  `Command approval denied by user: ${command}`,
76
77
  { command }
@@ -82,7 +83,7 @@ class ProcessError {
82
83
  static executionFailed(command, cause) {
83
84
  return new DextoRuntimeError(
84
85
  ProcessErrorCode.EXECUTION_FAILED,
85
- ErrorScope.PROCESS,
86
+ PROCESS_SCOPE,
86
87
  ErrorType.SYSTEM,
87
88
  `Command execution failed: ${command}. ${cause}`,
88
89
  { command, cause }
@@ -94,7 +95,7 @@ class ProcessError {
94
95
  static timeout(command, timeout) {
95
96
  return new DextoRuntimeError(
96
97
  ProcessErrorCode.TIMEOUT,
97
- ErrorScope.PROCESS,
98
+ PROCESS_SCOPE,
98
99
  ErrorType.TIMEOUT,
99
100
  `Command timed out after ${timeout}ms: ${command}`,
100
101
  { command, timeout },
@@ -107,7 +108,7 @@ class ProcessError {
107
108
  static permissionDenied(command) {
108
109
  return new DextoRuntimeError(
109
110
  ProcessErrorCode.PERMISSION_DENIED,
110
- ErrorScope.PROCESS,
111
+ PROCESS_SCOPE,
111
112
  ErrorType.FORBIDDEN,
112
113
  `Permission denied: ${command}`,
113
114
  { command }
@@ -119,7 +120,7 @@ class ProcessError {
119
120
  static commandNotFound(command) {
120
121
  return new DextoRuntimeError(
121
122
  ProcessErrorCode.COMMAND_NOT_FOUND,
122
- ErrorScope.PROCESS,
123
+ PROCESS_SCOPE,
123
124
  ErrorType.NOT_FOUND,
124
125
  `Command not found: ${command}`,
125
126
  { command },
@@ -132,7 +133,7 @@ class ProcessError {
132
133
  static invalidWorkingDirectory(path, reason) {
133
134
  return new DextoRuntimeError(
134
135
  ProcessErrorCode.WORKING_DIRECTORY_INVALID,
135
- ErrorScope.PROCESS,
136
+ PROCESS_SCOPE,
136
137
  ErrorType.USER,
137
138
  `Invalid working directory: ${path}. ${reason}`,
138
139
  { path, reason }
@@ -144,7 +145,7 @@ class ProcessError {
144
145
  static processNotFound(processId) {
145
146
  return new DextoRuntimeError(
146
147
  ProcessErrorCode.PROCESS_NOT_FOUND,
147
- ErrorScope.PROCESS,
148
+ PROCESS_SCOPE,
148
149
  ErrorType.NOT_FOUND,
149
150
  `Process not found: ${processId}`,
150
151
  { processId }
@@ -156,7 +157,7 @@ class ProcessError {
156
157
  static tooManyProcesses(current, max) {
157
158
  return new DextoRuntimeError(
158
159
  ProcessErrorCode.TOO_MANY_PROCESSES,
159
- ErrorScope.PROCESS,
160
+ PROCESS_SCOPE,
160
161
  ErrorType.USER,
161
162
  `Too many concurrent processes: ${current}. Maximum allowed: ${max}`,
162
163
  { current, max },
@@ -169,7 +170,7 @@ class ProcessError {
169
170
  static killFailed(processId, cause) {
170
171
  return new DextoRuntimeError(
171
172
  ProcessErrorCode.KILL_FAILED,
172
- ErrorScope.PROCESS,
173
+ PROCESS_SCOPE,
173
174
  ErrorType.SYSTEM,
174
175
  `Failed to kill process ${processId}: ${cause}`,
175
176
  { processId, cause }
@@ -181,7 +182,7 @@ class ProcessError {
181
182
  static outputBufferFull(processId, size, maxSize) {
182
183
  return new DextoRuntimeError(
183
184
  ProcessErrorCode.OUTPUT_BUFFER_FULL,
184
- ErrorScope.PROCESS,
185
+ PROCESS_SCOPE,
185
186
  ErrorType.SYSTEM,
186
187
  `Output buffer full for process ${processId}: ${size} bytes. Maximum: ${maxSize}`,
187
188
  { processId, size, maxSize },
@@ -194,7 +195,7 @@ class ProcessError {
194
195
  static invalidConfig(reason) {
195
196
  return new DextoRuntimeError(
196
197
  ProcessErrorCode.INVALID_CONFIG,
197
- ErrorScope.PROCESS,
198
+ PROCESS_SCOPE,
198
199
  ErrorType.USER,
199
200
  `Invalid Process configuration: ${reason}`,
200
201
  { reason }
@@ -206,7 +207,7 @@ class ProcessError {
206
207
  static notInitialized() {
207
208
  return new DextoRuntimeError(
208
209
  ProcessErrorCode.SERVICE_NOT_INITIALIZED,
209
- ErrorScope.PROCESS,
210
+ PROCESS_SCOPE,
210
211
  ErrorType.SYSTEM,
211
212
  "ProcessService has not been initialized",
212
213
  {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexto/tools-process",
3
- "version": "1.5.3",
3
+ "version": "1.5.5",
4
4
  "description": "Process tools provider for Dexto agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -20,7 +20,7 @@
20
20
  ],
21
21
  "dependencies": {
22
22
  "zod": "^3.25.0",
23
- "@dexto/core": "1.5.3"
23
+ "@dexto/core": "1.5.5"
24
24
  },
25
25
  "devDependencies": {
26
26
  "tsup": "^8.0.0",