wave-agent-sdk 0.0.10 → 0.0.11
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/agent.d.ts.map +1 -1
- package/dist/agent.js +25 -14
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/managers/permissionManager.d.ts +9 -0
- package/dist/managers/permissionManager.d.ts.map +1 -1
- package/dist/managers/permissionManager.js +166 -6
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +66 -27
- package/dist/types/permissions.d.ts +4 -0
- package/dist/types/permissions.d.ts.map +1 -1
- package/dist/utils/bashParser.d.ts +24 -0
- package/dist/utils/bashParser.d.ts.map +1 -0
- package/dist/utils/bashParser.js +413 -0
- package/dist/utils/pathSafety.d.ts +10 -0
- package/dist/utils/pathSafety.d.ts.map +1 -0
- package/dist/utils/pathSafety.js +23 -0
- package/package.json +5 -2
- package/src/agent.ts +28 -13
- package/src/index.ts +1 -0
- package/src/managers/permissionManager.ts +210 -6
- package/src/tools/bashTool.ts +72 -32
- package/src/types/permissions.ts +4 -0
- package/src/utils/bashParser.ts +444 -0
- package/src/utils/pathSafety.ts +26 -0
- package/dist/utils/largeOutputHandler.d.ts +0 -15
- package/dist/utils/largeOutputHandler.d.ts.map +0 -1
- package/dist/utils/largeOutputHandler.js +0 -40
- package/dist/utils/tokenEstimator.d.ts +0 -39
- package/dist/utils/tokenEstimator.d.ts.map +0 -1
- package/dist/utils/tokenEstimator.js +0 -55
- package/src/utils/largeOutputHandler.ts +0 -55
- package/src/utils/tokenEstimator.ts +0 -68
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* handles custom callback integration.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import path from "node:path";
|
|
9
10
|
import type {
|
|
10
11
|
PermissionDecision,
|
|
11
12
|
ToolPermissionContext,
|
|
@@ -14,6 +15,16 @@ import type {
|
|
|
14
15
|
} from "../types/permissions.js";
|
|
15
16
|
import { RESTRICTED_TOOLS } from "../types/permissions.js";
|
|
16
17
|
import type { Logger } from "../types/index.js";
|
|
18
|
+
import {
|
|
19
|
+
splitBashCommand,
|
|
20
|
+
stripEnvVars,
|
|
21
|
+
stripRedirections,
|
|
22
|
+
getSmartPrefix,
|
|
23
|
+
DANGEROUS_COMMANDS,
|
|
24
|
+
} from "../utils/bashParser.js";
|
|
25
|
+
import { isPathInside } from "../utils/pathSafety.js";
|
|
26
|
+
|
|
27
|
+
const SAFE_COMMANDS = ["cd", "ls", "pwd"];
|
|
17
28
|
|
|
18
29
|
export interface PermissionManagerOptions {
|
|
19
30
|
/** Logger for debugging permission decisions */
|
|
@@ -239,18 +250,71 @@ export class PermissionManager {
|
|
|
239
250
|
callback?: PermissionCallback,
|
|
240
251
|
toolInput?: Record<string, unknown>,
|
|
241
252
|
): ToolPermissionContext {
|
|
253
|
+
let suggestedPrefix: string | undefined;
|
|
254
|
+
if (toolName === "Bash" && toolInput?.command) {
|
|
255
|
+
const command = String(toolInput.command);
|
|
256
|
+
const parts = splitBashCommand(command);
|
|
257
|
+
// Only suggest prefix for single commands to avoid confusion with complex chains
|
|
258
|
+
if (parts.length === 1) {
|
|
259
|
+
const processedPart = stripRedirections(stripEnvVars(parts[0]));
|
|
260
|
+
suggestedPrefix = getSmartPrefix(processedPart) ?? undefined;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
242
264
|
const context: ToolPermissionContext = {
|
|
243
265
|
toolName,
|
|
244
266
|
permissionMode,
|
|
245
267
|
canUseToolCallback: callback,
|
|
246
268
|
toolInput,
|
|
269
|
+
suggestedPrefix,
|
|
247
270
|
};
|
|
248
271
|
|
|
272
|
+
// Set hidePersistentOption for dangerous or out-of-bounds bash commands
|
|
273
|
+
if (toolName === "Bash" && toolInput?.command) {
|
|
274
|
+
const command = String(toolInput.command);
|
|
275
|
+
const workdir = toolInput.workdir as string | undefined;
|
|
276
|
+
const parts = splitBashCommand(command);
|
|
277
|
+
|
|
278
|
+
const isDangerous = parts.some((part) => {
|
|
279
|
+
const processedPart = stripRedirections(stripEnvVars(part));
|
|
280
|
+
const commandMatch = processedPart.match(/^(\w+)(\s+.*)?$/);
|
|
281
|
+
if (commandMatch) {
|
|
282
|
+
const cmd = commandMatch[1];
|
|
283
|
+
const args = commandMatch[2]?.trim() || "";
|
|
284
|
+
|
|
285
|
+
// Check blacklist
|
|
286
|
+
if (DANGEROUS_COMMANDS.includes(cmd)) {
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Check out-of-bounds for cd and ls
|
|
291
|
+
if (workdir && (cmd === "cd" || cmd === "ls")) {
|
|
292
|
+
const pathArgs =
|
|
293
|
+
(args.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || []).filter(
|
|
294
|
+
(arg) => !arg.startsWith("-"),
|
|
295
|
+
) || [];
|
|
296
|
+
|
|
297
|
+
return pathArgs.some((pathArg) => {
|
|
298
|
+
const cleanPath = pathArg.replace(/^['"](.*)['"]$/, "$1");
|
|
299
|
+
const absolutePath = path.resolve(workdir, cleanPath);
|
|
300
|
+
return !isPathInside(absolutePath, workdir);
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return false;
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
if (isDangerous) {
|
|
308
|
+
context.hidePersistentOption = true;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
249
312
|
this.logger?.debug("Created permission context", {
|
|
250
313
|
toolName,
|
|
251
314
|
permissionMode,
|
|
252
315
|
hasCallback: !!callback,
|
|
253
316
|
hasToolInput: !!toolInput,
|
|
317
|
+
suggestedPrefix,
|
|
254
318
|
});
|
|
255
319
|
|
|
256
320
|
return context;
|
|
@@ -261,16 +325,156 @@ export class PermissionManager {
|
|
|
261
325
|
*/
|
|
262
326
|
private isAllowedByRule(context: ToolPermissionContext): boolean {
|
|
263
327
|
if (context.toolName === "Bash" && context.toolInput?.command) {
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
328
|
+
const command = String(context.toolInput.command);
|
|
329
|
+
const parts = splitBashCommand(command);
|
|
330
|
+
if (parts.length === 0) return false;
|
|
331
|
+
|
|
332
|
+
const workdir = context.toolInput?.workdir as string | undefined;
|
|
333
|
+
|
|
334
|
+
return parts.every((part) => {
|
|
335
|
+
const processedPart = stripRedirections(stripEnvVars(part));
|
|
336
|
+
|
|
337
|
+
// Check for safe commands
|
|
338
|
+
const commandMatch = processedPart.match(/^(\w+)(\s+.*)?$/);
|
|
339
|
+
if (commandMatch) {
|
|
340
|
+
const cmd = commandMatch[1];
|
|
341
|
+
const args = commandMatch[2]?.trim() || "";
|
|
342
|
+
|
|
343
|
+
if (SAFE_COMMANDS.includes(cmd)) {
|
|
344
|
+
if (workdir) {
|
|
345
|
+
if (cmd === "pwd") {
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// For cd and ls, check paths
|
|
350
|
+
const pathArgs =
|
|
351
|
+
(args.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || []).filter(
|
|
352
|
+
(arg) => !arg.startsWith("-"),
|
|
353
|
+
) || [];
|
|
354
|
+
|
|
355
|
+
if (pathArgs.length === 0) {
|
|
356
|
+
// cd or ls without arguments operates on current dir (workdir)
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const allPathsSafe = pathArgs.every((pathArg) => {
|
|
361
|
+
// Remove quotes if present
|
|
362
|
+
const cleanPath = pathArg.replace(/^['"](.*)['"]$/, "$1");
|
|
363
|
+
const absolutePath = path.resolve(workdir, cleanPath);
|
|
364
|
+
return isPathInside(absolutePath, workdir);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
if (allPathsSafe) {
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
269
372
|
}
|
|
270
|
-
|
|
373
|
+
|
|
374
|
+
const action = `${context.toolName}(${processedPart})`;
|
|
375
|
+
const allowedByRule = this.allowedRules.some((rule) => {
|
|
376
|
+
if (rule.endsWith(":*)")) {
|
|
377
|
+
const prefix = rule.slice(0, -3);
|
|
378
|
+
return action.startsWith(prefix);
|
|
379
|
+
}
|
|
380
|
+
return action === rule;
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
if (allowedByRule) return true;
|
|
384
|
+
return !this.isRestrictedTool(context.toolName);
|
|
271
385
|
});
|
|
272
386
|
}
|
|
273
387
|
// Add other tools if needed in the future
|
|
274
388
|
return false;
|
|
275
389
|
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Expand a bash command into individual permission rules, filtering out safe commands.
|
|
393
|
+
* Used when saving permissions to the allow list.
|
|
394
|
+
*
|
|
395
|
+
* @param command The full bash command string
|
|
396
|
+
* @param workdir The working directory for path safety checks
|
|
397
|
+
* @returns Array of permission rules in "Bash(cmd)" format
|
|
398
|
+
*/
|
|
399
|
+
public expandBashRule(command: string, workdir: string): string[] {
|
|
400
|
+
const parts = splitBashCommand(command);
|
|
401
|
+
const rules: string[] = [];
|
|
402
|
+
|
|
403
|
+
for (const part of parts) {
|
|
404
|
+
const processedPart = stripRedirections(stripEnvVars(part));
|
|
405
|
+
|
|
406
|
+
// Check for safe commands
|
|
407
|
+
const commandMatch = processedPart.match(/^(\w+)(\s+.*)?$/);
|
|
408
|
+
let isSafe = false;
|
|
409
|
+
|
|
410
|
+
if (commandMatch) {
|
|
411
|
+
const cmd = commandMatch[1];
|
|
412
|
+
const args = commandMatch[2]?.trim() || "";
|
|
413
|
+
|
|
414
|
+
if (SAFE_COMMANDS.includes(cmd)) {
|
|
415
|
+
if (cmd === "pwd") {
|
|
416
|
+
isSafe = true;
|
|
417
|
+
} else {
|
|
418
|
+
// For cd and ls, check paths
|
|
419
|
+
const pathArgs =
|
|
420
|
+
(args.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || []).filter(
|
|
421
|
+
(arg) => !arg.startsWith("-"),
|
|
422
|
+
) || [];
|
|
423
|
+
|
|
424
|
+
if (pathArgs.length === 0) {
|
|
425
|
+
isSafe = true;
|
|
426
|
+
} else {
|
|
427
|
+
const allPathsSafe = pathArgs.every((pathArg) => {
|
|
428
|
+
const cleanPath = pathArg.replace(/^['"](.*)['"]$/, "$1");
|
|
429
|
+
const absolutePath = path.resolve(workdir, cleanPath);
|
|
430
|
+
return isPathInside(absolutePath, workdir);
|
|
431
|
+
});
|
|
432
|
+
if (allPathsSafe) {
|
|
433
|
+
isSafe = true;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (!isSafe) {
|
|
441
|
+
// Check if command is dangerous or out-of-bounds
|
|
442
|
+
const commandMatch = processedPart.match(/^(\w+)(\s+.*)?$/);
|
|
443
|
+
if (commandMatch) {
|
|
444
|
+
const cmd = commandMatch[1];
|
|
445
|
+
const args = commandMatch[2]?.trim() || "";
|
|
446
|
+
|
|
447
|
+
if (DANGEROUS_COMMANDS.includes(cmd)) {
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (cmd === "cd" || cmd === "ls") {
|
|
452
|
+
const pathArgs =
|
|
453
|
+
(args.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || []).filter(
|
|
454
|
+
(arg) => !arg.startsWith("-"),
|
|
455
|
+
) || [];
|
|
456
|
+
|
|
457
|
+
const isOutOfBounds = pathArgs.some((pathArg) => {
|
|
458
|
+
const cleanPath = pathArg.replace(/^['"](.*)['"]$/, "$1");
|
|
459
|
+
const absolutePath = path.resolve(workdir, cleanPath);
|
|
460
|
+
return !isPathInside(absolutePath, workdir);
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
if (isOutOfBounds) {
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const smartPrefix = getSmartPrefix(processedPart);
|
|
470
|
+
if (smartPrefix) {
|
|
471
|
+
rules.push(`Bash(${smartPrefix}:*)`);
|
|
472
|
+
} else {
|
|
473
|
+
rules.push(`Bash(${processedPart})`);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
return rules;
|
|
479
|
+
}
|
|
276
480
|
}
|
package/src/tools/bashTool.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { spawn, ChildProcess } from "child_process";
|
|
2
2
|
import { logger } from "../utils/globalLogger.js";
|
|
3
3
|
import { stripAnsiColors } from "../utils/stringUtils.js";
|
|
4
|
-
import { handleLargeOutput } from "../utils/largeOutputHandler.js";
|
|
5
4
|
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
6
5
|
|
|
6
|
+
const MAX_OUTPUT_LENGTH = 30000;
|
|
7
|
+
const BASH_DEFAULT_TIMEOUT_MS = 120000;
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* Bash command execution tool - supports both foreground and background execution
|
|
9
11
|
*/
|
|
@@ -13,8 +15,52 @@ export const bashTool: ToolPlugin = {
|
|
|
13
15
|
type: "function",
|
|
14
16
|
function: {
|
|
15
17
|
name: "Bash",
|
|
16
|
-
description:
|
|
17
|
-
|
|
18
|
+
description: `Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures.
|
|
19
|
+
|
|
20
|
+
IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead.
|
|
21
|
+
|
|
22
|
+
Before executing the command, please follow these steps:
|
|
23
|
+
|
|
24
|
+
1. Directory Verification:
|
|
25
|
+
- If the command will create new directories or files, first use \`ls\` to verify the parent directory exists and is the correct location
|
|
26
|
+
- For example, before running "mkdir foo/bar", first use \`ls foo\` to check that "foo" exists and is the intended parent directory
|
|
27
|
+
|
|
28
|
+
2. Command Execution:
|
|
29
|
+
- Always quote file paths that contain spaces with double quotes (e.g., cd "path with spaces/file.txt")
|
|
30
|
+
- Examples of proper quoting:
|
|
31
|
+
- cd "/Users/name/My Documents" (correct)
|
|
32
|
+
- cd /Users/name/My Documents (incorrect - will fail)
|
|
33
|
+
- python "/path/with spaces/script.py" (correct)
|
|
34
|
+
- python /path/with spaces/script.py (incorrect - will fail)
|
|
35
|
+
- After ensuring proper quoting, execute the command.
|
|
36
|
+
- Capture the output of the command.
|
|
37
|
+
|
|
38
|
+
Usage notes:
|
|
39
|
+
- The command argument is required.
|
|
40
|
+
- You can specify an optional timeout in milliseconds (up to ${BASH_DEFAULT_TIMEOUT_MS}ms / ${BASH_DEFAULT_TIMEOUT_MS / 60000} minutes). If not specified, commands will timeout after ${BASH_DEFAULT_TIMEOUT_MS}ms (${BASH_DEFAULT_TIMEOUT_MS / 60000} minutes).
|
|
41
|
+
- It is very helpful if you write a clear, concise description of what this command does in 5-10 words.
|
|
42
|
+
- If the output exceeds ${MAX_OUTPUT_LENGTH} characters, output will be truncated before being returned to you.
|
|
43
|
+
- You can use the \`run_in_background\` parameter to run the command in the background, which allows you to continue working while the command runs. You can monitor the output using the Bash tool as it becomes available. You do not need to use '&' at the end of the command when using this parameter.
|
|
44
|
+
- Avoid using Bash with the \`find\`, \`grep\`, \`cat\`, \`head\`, \`tail\`, \`sed\`, \`awk\`, or \`echo\` commands, unless explicitly instructed or when these commands are truly necessary for the task. Instead, always prefer using the dedicated tools for these commands:
|
|
45
|
+
- File search: Use Glob (NOT find or ls)
|
|
46
|
+
- Content search: Use Grep (NOT grep or rg)
|
|
47
|
+
- Read files: Use Read (NOT cat/head/tail)
|
|
48
|
+
- Edit files: Use Edit (NOT sed/awk)
|
|
49
|
+
- Write files: Use Write (NOT echo >/cat <<EOF)
|
|
50
|
+
- Communication: Output text directly (NOT echo/printf)
|
|
51
|
+
- When issuing multiple commands:
|
|
52
|
+
- If the commands are independent and can run in parallel, make multiple Bash tool calls in a single message. For example, if you need to run "git status" and "git diff", send a single message with two Bash tool calls in parallel.
|
|
53
|
+
- If the commands depend on each other and must run sequentially, use a single Bash call with '&&' to chain them together (e.g., \`git add . && git commit -m "message" && git push\`). For instance, if one operation must complete before another starts (like mkdir before cp, Write before Bash for git operations, or git add before git commit), run these operations sequentially instead.
|
|
54
|
+
- Use ';' only when you need to run commands sequentially but don't care if earlier commands fail
|
|
55
|
+
- DO NOT use newlines to separate commands (newlines are ok in quoted strings)
|
|
56
|
+
- Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of \`cd\`. You may use \`cd\` if the User explicitly requests it.
|
|
57
|
+
<good-example>
|
|
58
|
+
pytest /foo/bar/tests
|
|
59
|
+
</good-example>
|
|
60
|
+
<bad-example>
|
|
61
|
+
cd /foo/bar && pytest tests
|
|
62
|
+
</bad-example>
|
|
63
|
+
`,
|
|
18
64
|
parameters: {
|
|
19
65
|
type: "object",
|
|
20
66
|
properties: {
|
|
@@ -48,10 +94,10 @@ export const bashTool: ToolPlugin = {
|
|
|
48
94
|
const command = args.command as string;
|
|
49
95
|
const runInBackground = args.run_in_background as boolean | undefined;
|
|
50
96
|
const description = args.description as string | undefined;
|
|
51
|
-
// Set default timeout:
|
|
97
|
+
// Set default timeout: BASH_DEFAULT_TIMEOUT_MS for foreground, no timeout for background
|
|
52
98
|
const timeout =
|
|
53
99
|
(args.timeout as number | undefined) ??
|
|
54
|
-
(runInBackground ? undefined :
|
|
100
|
+
(runInBackground ? undefined : BASH_DEFAULT_TIMEOUT_MS);
|
|
55
101
|
|
|
56
102
|
if (!command || typeof command !== "string") {
|
|
57
103
|
return {
|
|
@@ -90,6 +136,7 @@ export const bashTool: ToolPlugin = {
|
|
|
90
136
|
description,
|
|
91
137
|
run_in_background: runInBackground,
|
|
92
138
|
timeout,
|
|
139
|
+
workdir: context.workdir,
|
|
93
140
|
},
|
|
94
141
|
);
|
|
95
142
|
const permissionResult =
|
|
@@ -238,32 +285,23 @@ export const bashTool: ToolPlugin = {
|
|
|
238
285
|
const combinedOutput =
|
|
239
286
|
outputBuffer + (errorBuffer ? "\n" + errorBuffer : "");
|
|
240
287
|
|
|
241
|
-
// Handle large output by
|
|
288
|
+
// Handle large output by truncation if needed
|
|
242
289
|
const finalOutput =
|
|
243
290
|
combinedOutput || `Command executed with exit code: ${exitCode}`;
|
|
244
|
-
|
|
245
|
-
.
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
resolve({
|
|
259
|
-
success: exitCode === 0,
|
|
260
|
-
content: finalOutput,
|
|
261
|
-
error:
|
|
262
|
-
exitCode !== 0
|
|
263
|
-
? `Command failed with exit code: ${exitCode}`
|
|
264
|
-
: undefined,
|
|
265
|
-
});
|
|
266
|
-
});
|
|
291
|
+
const content =
|
|
292
|
+
finalOutput.length > MAX_OUTPUT_LENGTH
|
|
293
|
+
? finalOutput.substring(0, MAX_OUTPUT_LENGTH) +
|
|
294
|
+
"\n\n... (output truncated)"
|
|
295
|
+
: finalOutput;
|
|
296
|
+
|
|
297
|
+
resolve({
|
|
298
|
+
success: exitCode === 0,
|
|
299
|
+
content,
|
|
300
|
+
error:
|
|
301
|
+
exitCode !== 0
|
|
302
|
+
? `Command failed with exit code: ${exitCode}`
|
|
303
|
+
: undefined,
|
|
304
|
+
});
|
|
267
305
|
}
|
|
268
306
|
});
|
|
269
307
|
|
|
@@ -374,13 +412,15 @@ export const bashOutputTool: ToolPlugin = {
|
|
|
374
412
|
}
|
|
375
413
|
|
|
376
414
|
const finalContent = content || "No output available";
|
|
377
|
-
const
|
|
378
|
-
|
|
415
|
+
const processedContent =
|
|
416
|
+
finalContent.length > MAX_OUTPUT_LENGTH
|
|
417
|
+
? finalContent.substring(0, MAX_OUTPUT_LENGTH) +
|
|
418
|
+
"\n\n... (output truncated)"
|
|
419
|
+
: finalContent;
|
|
379
420
|
|
|
380
421
|
return {
|
|
381
422
|
success: true,
|
|
382
423
|
content: processedContent,
|
|
383
|
-
filePath,
|
|
384
424
|
shortResult: `${bashId}: ${output.status}${shell.exitCode !== undefined ? ` (${shell.exitCode})` : ""}`,
|
|
385
425
|
error: undefined,
|
|
386
426
|
};
|
package/src/types/permissions.ts
CHANGED
|
@@ -33,6 +33,10 @@ export interface ToolPermissionContext {
|
|
|
33
33
|
canUseToolCallback?: PermissionCallback;
|
|
34
34
|
/** Tool input parameters for better context */
|
|
35
35
|
toolInput?: Record<string, unknown>;
|
|
36
|
+
/** Suggested prefix for bash commands */
|
|
37
|
+
suggestedPrefix?: string;
|
|
38
|
+
/** Whether to hide the persistent permission option (e.g., "Don't ask again") in the UI */
|
|
39
|
+
hidePersistentOption?: boolean;
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
/** List of tools that require permission checks in default mode */
|