wave-agent-sdk 0.10.2 → 0.10.4

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.
@@ -0,0 +1,95 @@
1
+ # Wave Hooks Configuration
2
+
3
+ Hooks allow you to automate tasks when certain events occur in Wave. This document provides detailed guidance on how to configure complex hooks in `settings.json`.
4
+
5
+ ## Hook Events
6
+
7
+ Wave supports the following hook events:
8
+
9
+ - `WorktreeCreate`: Triggered when a new worktree is created.
10
+ - `TaskStart`: Triggered when a task starts.
11
+ - `TaskComplete`: Triggered when a task is completed.
12
+ - `TaskError`: Triggered when a task fails.
13
+ - `SessionStart`: Triggered when a new session starts.
14
+ - `SessionEnd`: Triggered when a session ends.
15
+
16
+ ## Hook Configuration Structure
17
+
18
+ Hooks are configured in the `hooks` field of `settings.json`. Each event can have multiple hook configurations.
19
+
20
+ ```json
21
+ {
22
+ "hooks": {
23
+ "WorktreeCreate": [
24
+ {
25
+ "command": "pnpm install",
26
+ "description": "Install dependencies in new worktree",
27
+ "blocking": true,
28
+ "timeout": 300000
29
+ }
30
+ ],
31
+ "TaskComplete": [
32
+ {
33
+ "command": "pnpm test",
34
+ "description": "Run tests after task completion",
35
+ "blocking": false
36
+ }
37
+ ]
38
+ }
39
+ }
40
+ ```
41
+
42
+ ## Hook Configuration Fields
43
+
44
+ - `command`: The shell command to execute.
45
+ - `description`: A brief description of the hook's purpose.
46
+ - `blocking`: (Optional) Whether the hook should block the main agent's execution (default: `false`).
47
+ - `timeout`: (Optional) Maximum execution time in milliseconds (default: `60000`).
48
+ - `env`: (Optional) Environment variables specific to this hook.
49
+ - `cwd`: (Optional) Working directory for the hook command.
50
+
51
+ ## Advanced Hook Examples
52
+
53
+ ### 1. Conditional Hooks
54
+ You can use shell logic within the `command` field to create conditional hooks.
55
+ ```json
56
+ {
57
+ "hooks": {
58
+ "TaskComplete": [
59
+ {
60
+ "command": "if [ \"$WAVE_TASK_STATUS\" = \"completed\" ]; then pnpm lint; fi",
61
+ "description": "Run linting only on successful task completion"
62
+ }
63
+ ]
64
+ }
65
+ }
66
+ ```
67
+
68
+ ### 2. Hook Chaining
69
+ You can chain multiple commands in a single hook or define multiple hooks for the same event.
70
+ ```json
71
+ {
72
+ "hooks": {
73
+ "WorktreeCreate": [
74
+ {
75
+ "command": "pnpm install && pnpm build",
76
+ "description": "Install and build in new worktree"
77
+ }
78
+ ]
79
+ }
80
+ }
81
+ ```
82
+
83
+ ### 3. Using Environment Variables
84
+ Wave provides several environment variables to hooks:
85
+ - `WAVE_PROJECT_DIR`: The root directory of the project.
86
+ - `WAVE_SESSION_ID`: The current session ID.
87
+ - `WAVE_TASK_ID`: The current task ID (if applicable).
88
+ - `WAVE_TASK_STATUS`: The status of the task (for `TaskComplete` and `TaskError`).
89
+
90
+ ## Best Practices
91
+
92
+ - **Keep hooks fast**: Long-running hooks can slow down your workflow, especially if they are `blocking`.
93
+ - **Use descriptive names**: Help yourself and others understand what each hook does.
94
+ - **Test your hooks**: Run the commands manually first to ensure they work as expected.
95
+ - **Use local overrides**: For machine-specific hooks, use `.wave/settings.local.json`.
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: settings
3
+ description: Manage Wave settings and get guidance on settings.json
4
+ allowed-tools: Bash, Read, Write
5
+ ---
6
+
7
+ # Wave Settings Skill
8
+
9
+ This skill helps you manage your Wave configuration and provides guidance on how to use `settings.json`.
10
+
11
+ ## What is `settings.json`?
12
+
13
+ `settings.json` is the central configuration file for Wave. It allows you to customize hooks, environment variables, tool permissions, and more.
14
+
15
+ Wave looks for `settings.json` in three scopes:
16
+ 1. **User Scope**: Global settings for all projects. Located at `~/.wave/settings.json`.
17
+ 2. **Project Scope**: Settings specific to the current project. Located at `.wave/settings.json` in your project root.
18
+ 3. **Local Scope**: Local overrides for the current project (not committed to git). Located at `.wave/settings.local.json`.
19
+
20
+ ## Common Settings
21
+
22
+ ### 1. Hooks
23
+ Hooks allow you to automate tasks when certain events occur (e.g., `WorktreeCreate`, `TaskStart`).
24
+ For detailed hook configuration, see [HOOKS.md](${WAVE_SKILL_DIR}/HOOKS.md).
25
+
26
+ ### 2. Environment Variables
27
+ Set environment variables that will be available to all tools and hooks.
28
+ ```json
29
+ {
30
+ "env": {
31
+ "NODE_ENV": "development",
32
+ "API_KEY": "your-api-key"
33
+ }
34
+ }
35
+ ```
36
+
37
+ ### 3. Permissions
38
+ Manage tool permissions and define the "Safe Zone".
39
+ ```json
40
+ {
41
+ "permissions": {
42
+ "allow": ["Bash", "Read"],
43
+ "deny": ["Write"],
44
+ "defaultMode": "interactive",
45
+ "additionalDirectories": ["/tmp/wave-exports"]
46
+ }
47
+ }
48
+ ```
49
+
50
+ ### 4. Enabled Plugins
51
+ Enable or disable specific plugins.
52
+ ```json
53
+ {
54
+ "enabledPlugins": {
55
+ "git-plugin": true,
56
+ "experimental-plugin": false
57
+ }
58
+ }
59
+ ```
60
+
61
+ ### 5. Model and Token Configuration
62
+ Define which AI models Wave should use and set token limits via environment variables.
63
+ ```json
64
+ {
65
+ "env": {
66
+ "WAVE_MODEL": "gemini-3-flash",
67
+ "WAVE_FAST_MODEL": "gemini-2.5-flash",
68
+ "WAVE_MAX_INPUT_TOKENS": "100000",
69
+ "WAVE_MAX_OUTPUT_TOKENS": "4096"
70
+ }
71
+ }
72
+ ```
73
+
74
+ ### 6. Other Settings
75
+ - `language`: Preferred language for agent communication (e.g., `"en"`, `"zh"`).
76
+ - `autoMemoryEnabled`: Enable or disable auto-memory (default: `true`).
77
+
78
+ ## How to use this skill
79
+
80
+ You can ask me to:
81
+ - "Show my current settings"
82
+ - "Update my project settings to enable auto-memory"
83
+ - "How do I configure a post-commit hook?"
84
+ - "What are the available permission modes?"
85
+
86
+ I will guide you through the process and ensure your configuration is valid.
@@ -1 +1 @@
1
- {"version":3,"file":"aiManager.d.ts","sourceRoot":"","sources":["../../src/managers/aiManager.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,KAAK,EAEN,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAKlD,MAAM,WAAW,kBAAkB;IACjC,wBAAwB,CAAC,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,SAAS;IAYlB,OAAO,CAAC,SAAS;IAXZ,SAAS,EAAE,OAAO,CAAS;IAClC,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,mBAAmB,CAAgC;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,aAAa,CAAC,CAAS;gBAIrB,SAAS,EAAE,SAAS,EAC5B,OAAO,EAAE,gBAAgB;IAU3B,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,KAAK,aAAa,GAIxB;IAED,OAAO,KAAK,WAAW,GAItB;IAED,OAAO,KAAK,qBAAqB,GAEhC;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,KAAK,gBAAgB,GAM3B;IAED,OAAO,KAAK,iBAAiB,GAE5B;IAED,OAAO,KAAK,oBAAoB,GAE/B;IAGM,gBAAgB,IAAI,aAAa;IAIjC,cAAc,IAAI,WAAW;IA6B7B,iBAAiB,IAAI,MAAM;IAI3B,WAAW,IAAI,MAAM,GAAG,SAAS;IAIjC,oBAAoB,IAAI,OAAO;IAItC,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,SAAS,CAAqB;IAEtC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAsBvB,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAItC,cAAc,IAAI,IAAI;IAuB7B,OAAO,CAAC,qBAAqB;YAsBf,8BAA8B;IAgFrC,gBAAgB,IAAI,OAAO;IAI3B,gBAAgB,CAAC,aAAa,EAAE,OAAO,GAAG,IAAI;IAOrD,OAAO,KAAK,eAAe,GAE1B;IAED,OAAO,KAAK,YAAY,GAEvB;IAEY,aAAa,CACxB,OAAO,GAAE;QACP,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,oEAAoE;QACpE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,iEAAiE;QACjE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;KACf,GACL,OAAO,CAAC,IAAI,CAAC;IAihBhB;;;;OAIG;YACW,gBAAgB;IAiE9B;;;OAGG;YACW,sBAAsB;IA6DpC;;OAEG;YACW,uBAAuB;CAwDtC"}
1
+ {"version":3,"file":"aiManager.d.ts","sourceRoot":"","sources":["../../src/managers/aiManager.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,KAAK,EAEN,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAKlD,MAAM,WAAW,kBAAkB;IACjC,wBAAwB,CAAC,EAAE,CAAC,aAAa,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,SAAS;IAYlB,OAAO,CAAC,SAAS;IAXZ,SAAS,EAAE,OAAO,CAAS;IAClC,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,mBAAmB,CAAgC;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,aAAa,CAAC,CAAS;gBAIrB,SAAS,EAAE,SAAS,EAC5B,OAAO,EAAE,gBAAgB;IAU3B,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,KAAK,aAAa,GAIxB;IAED,OAAO,KAAK,WAAW,GAItB;IAED,OAAO,KAAK,qBAAqB,GAEhC;IAED,OAAO,KAAK,WAAW,GAEtB;IAED,OAAO,KAAK,gBAAgB,GAM3B;IAED,OAAO,KAAK,iBAAiB,GAE5B;IAED,OAAO,KAAK,oBAAoB,GAE/B;IAGM,gBAAgB,IAAI,aAAa;IAIjC,cAAc,IAAI,WAAW;IA6B7B,iBAAiB,IAAI,MAAM;IAI3B,WAAW,IAAI,MAAM,GAAG,SAAS;IAIjC,oBAAoB,IAAI,OAAO;IAItC,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,SAAS,CAAqB;IAEtC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAsBvB,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAItC,cAAc,IAAI,IAAI;IAuB7B,OAAO,CAAC,qBAAqB;YAsBf,8BAA8B;IAgFrC,gBAAgB,IAAI,OAAO;IAI3B,gBAAgB,CAAC,aAAa,EAAE,OAAO,GAAG,IAAI;IAOrD,OAAO,KAAK,eAAe,GAE1B;IAED,OAAO,KAAK,YAAY,GAEvB;IAEY,aAAa,CACxB,OAAO,GAAE;QACP,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,oEAAoE;QACpE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,iEAAiE;QACjE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;KACf,GACL,OAAO,CAAC,IAAI,CAAC;IAkhBhB;;;;OAIG;YACW,gBAAgB;IAiE9B;;;OAGG;YACW,sBAAsB;IA6DpC;;OAEG;YACW,uBAAuB;CAwDtC"}
@@ -296,6 +296,7 @@ export class AIManager {
296
296
  isSubagent: !!this.subagentType,
297
297
  planMode: planModeOptions,
298
298
  autoMemory: autoMemoryOptions,
299
+ permissionMode: currentMode,
299
300
  }), // Pass custom system prompt
300
301
  maxTokens: maxTokens, // Pass max tokens override
301
302
  };
@@ -1 +1 @@
1
- {"version":3,"file":"permissionManager.d.ts","sourceRoot":"","sources":["../../src/managers/permissionManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permissionManager.d.ts","sourceRoot":"","sources":["../../src/managers/permissionManager.ts"],"names":[],"mappings":"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"}
@@ -312,6 +312,16 @@ export class PermissionManager {
312
312
  if (!this.isRestrictedTool(context.toolName)) {
313
313
  return { behavior: "allow" };
314
314
  }
315
+ // 2.1 If dontAsk mode, auto-deny restricted tools that were not allowed by rules above
316
+ if (context.permissionMode === "dontAsk") {
317
+ logger?.info("Restricted tool automatically denied in dontAsk mode", {
318
+ toolName: context.toolName,
319
+ });
320
+ return {
321
+ behavior: "deny",
322
+ message: `Tool '${context.toolName}' was automatically denied because 'dontAsk' permission mode is active and no pre-approved rule matches this call.`,
323
+ };
324
+ }
315
325
  // 3. If custom callback provided, call it and return result
316
326
  if (context.canUseToolCallback) {
317
327
  try {
@@ -1,4 +1,5 @@
1
1
  import { ToolPlugin } from "../tools/types.js";
2
+ import { PermissionMode } from "../types/permissions.js";
2
3
  export declare const BASE_SYSTEM_PROMPT = "You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.\n\n# Doing tasks\nThe user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:\n- NEVER propose changes to code you haven't read. If a user asks about or wants you to modify a file, read it first. Understand existing code before suggesting modifications.\n- Be careful not to introduce security vulnerabilities such as command injection, XSS, SQL injection, and other OWASP top 10 vulnerabilities. If you notice that you wrote insecure code, immediately fix it.\n- Avoid over-engineering. Only make changes that are directly requested or clearly necessary. Keep solutions simple and focused.\n - Don't add features, refactor code, or make \"improvements\" beyond what was asked. A bug fix doesn't need surrounding code cleaned up. A simple feature doesn't need extra configurability. Don't add docstrings, comments, or type annotations to code you didn't change. Only add comments where the logic isn't self-evident.\n - Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal code and framework guarantees. Only validate at system boundaries (user input, external APIs). Don't use feature flags or backwards-compatibility shims when you can just change the code.\n - Don't create helpers, utilities, or abstractions for one-time operations. Don't design for hypothetical future requirements. The right amount of complexity is the minimum needed for the current task\u2014three similar lines of code is better than a premature abstraction.\n- Avoid backwards-compatibility hacks like renaming unused `_vars`, re-exporting types, adding `// removed` comments for removed code, etc. If something is unused, delete it completely.";
3
4
  export declare const TOOL_POLICY = "\n# Tool usage policy\n- You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency.\n- However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead. Never use placeholders or guess missing parameters in tool calls.\n- If the user specifies that they want you to run tools \"in parallel\", you MUST send a single message with multiple tool use content blocks.";
4
5
  export declare function buildPlanModePrompt(planFilePath: string, planExists: boolean, isSubagent?: boolean): string;
@@ -22,5 +23,6 @@ export declare function buildSystemPrompt(basePrompt: string | undefined, tools:
22
23
  directory: string;
23
24
  content: string;
24
25
  };
26
+ permissionMode?: PermissionMode;
25
27
  }): string;
26
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAmB/C,eAAO,MAAM,kBAAkB,g9DAU+J,CAAC;AAE/L,eAAO,MAAM,WAAW,qvBAIqH,CAAC;AAE9I,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,OAAO,EACnB,UAAU,GAAE,OAAe,GAC1B,MAAM,CAmFR;AAED,eAAO,MAAM,qBAAqB,g9DAAqB,CAAC;AAExD,eAAO,MAAM,2BAA2B,igBAWO,CAAC;AAEhD,eAAO,MAAM,6BAA6B,izCAeK,CAAC;AAEhD,eAAO,MAAM,8BAA8B,mzEAmCuC,CAAC;AAEnF,eAAO,MAAM,2BAA2B,q3EAgDyG,CAAC;AAElJ,eAAO,MAAM,WAAW,4pDAqBjB,CAAC;AAER,eAAO,MAAM,+BAA+B,20CAsBG,CAAC;AAEhD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,UAAU,CAAC,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACE,GACL,MAAM,CA6CR"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAiBzD,eAAO,MAAM,kBAAkB,g9DAU+J,CAAC;AAE/L,eAAO,MAAM,WAAW,qvBAIqH,CAAC;AAE9I,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,OAAO,EACnB,UAAU,GAAE,OAAe,GAC1B,MAAM,CAmFR;AAED,eAAO,MAAM,qBAAqB,g9DAAqB,CAAC;AAExD,eAAO,MAAM,2BAA2B,igBAWO,CAAC;AAEhD,eAAO,MAAM,6BAA6B,izCAeK,CAAC;AAEhD,eAAO,MAAM,8BAA8B,mzEAmCuC,CAAC;AAEnF,eAAO,MAAM,2BAA2B,q3EAgDyG,CAAC;AAElJ,eAAO,MAAM,WAAW,4pDAqBjB,CAAC;AAER,eAAO,MAAM,+BAA+B,20CAsBG,CAAC;AAEhD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,UAAU,CAAC,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,cAAc,CAAC,EAAE,cAAc,CAAC;CAC5B,GACL,MAAM,CAiDR"}
@@ -265,6 +265,9 @@ export function buildSystemPrompt(basePrompt, tools, options = {}) {
265
265
  if (tools.length > 0) {
266
266
  prompt += `\n\n${TOOL_POLICY}`;
267
267
  }
268
+ if (options.permissionMode === "dontAsk") {
269
+ prompt += `\n\n# Permission Mode\nThe user has selected the 'dontAsk' permission mode. In this mode, any restricted tool call that does not match a pre-approved rule in 'permissions.allow' or 'temporaryRules' will be automatically denied without prompting the user. You will receive a 'Permission denied' error for such calls. This is intended to prevent interruptions for untrusted tools while allowing pre-approved ones to run seamlessly.`;
270
+ }
268
271
  if (options.language) {
269
272
  prompt += `\n\n# Language\nAlways respond in ${options.language}. Technical terms (e.g., code, tool names, file paths) should remain in their original language or English where appropriate.`;
270
273
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bashTool.d.ts","sourceRoot":"","sources":["../../src/tools/bashTool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AActE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA4XtB,CAAC"}
1
+ {"version":3,"file":"bashTool.d.ts","sourceRoot":"","sources":["../../src/tools/bashTool.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AAyCtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA0XtB,CAAC"}
@@ -1,9 +1,33 @@
1
1
  import { spawn } from "child_process";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import * as os from "os";
2
5
  import { logger } from "../utils/globalLogger.js";
3
6
  import { stripAnsiColors } from "../utils/stringUtils.js";
4
7
  import { BASH_TOOL_NAME, TASK_OUTPUT_TOOL_NAME, GLOB_TOOL_NAME, GREP_TOOL_NAME, READ_TOOL_NAME, EDIT_TOOL_NAME, WRITE_TOOL_NAME, } from "../constants/tools.js";
5
8
  const MAX_OUTPUT_LENGTH = 30000;
6
9
  const BASH_DEFAULT_TIMEOUT_MS = 120000;
10
+ /**
11
+ * Helper function to handle large output by truncation and persistence to a temporary file.
12
+ */
13
+ function processOutput(output) {
14
+ if (output.length <= MAX_OUTPUT_LENGTH) {
15
+ return output;
16
+ }
17
+ try {
18
+ const tempDir = os.tmpdir();
19
+ const fileName = `bash_output_${Date.now()}_${Math.random().toString(36).substring(2, 11)}.txt`;
20
+ const filePath = path.join(tempDir, fileName);
21
+ fs.writeFileSync(filePath, output, "utf8");
22
+ return (output.substring(0, MAX_OUTPUT_LENGTH) +
23
+ `\n\n... (output truncated)\nFull output persisted to: ${filePath}`);
24
+ }
25
+ catch (error) {
26
+ logger.error("Failed to persist large bash output:", error);
27
+ return (output.substring(0, MAX_OUTPUT_LENGTH) +
28
+ "\n\n... (output truncated, failed to persist full output)");
29
+ }
30
+ }
7
31
  /**
8
32
  * Bash command execution tool - supports both foreground and background execution
9
33
  */
@@ -63,7 +87,7 @@ Usage notes:
63
87
  - The command argument is required.
64
88
  - 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).
65
89
  - It is very helpful if you write a clear, concise description of what this command does in 5-10 words.
66
- - If the output exceeds ${MAX_OUTPUT_LENGTH} characters, output will be truncated before being returned to you.
90
+ - If the output exceeds ${MAX_OUTPUT_LENGTH} characters, output will be truncated and the full output will be persisted to a temporary file.
67
91
  - 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_NAME} tool as it becomes available. You do not need to use '&' at the end of the command when using this parameter.
68
92
  - Avoid using ${BASH_TOOL_NAME} with the \`find\`, \`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:
69
93
  - File search: Use ${GLOB_TOOL_NAME} (NOT find or ls)
@@ -248,7 +272,7 @@ Usage notes:
248
272
  }
249
273
  resolve({
250
274
  success: false,
251
- content: outputBuffer + (errorBuffer ? "\n" + errorBuffer : ""),
275
+ content: processOutput(outputBuffer + (errorBuffer ? "\n" + errorBuffer : "")),
252
276
  error: reason,
253
277
  });
254
278
  }
@@ -286,12 +310,9 @@ Usage notes:
286
310
  }
287
311
  const exitCode = code ?? 0;
288
312
  const combinedOutput = outputBuffer + (errorBuffer ? "\n" + errorBuffer : "");
289
- // Handle large output by truncation if needed
313
+ // Handle large output by truncation and persistence if needed
290
314
  const finalOutput = combinedOutput || `Command executed with exit code: ${exitCode}`;
291
- const content = finalOutput.length > MAX_OUTPUT_LENGTH
292
- ? finalOutput.substring(0, MAX_OUTPUT_LENGTH) +
293
- "\n\n... (output truncated)"
294
- : finalOutput;
315
+ const content = processOutput(finalOutput);
295
316
  const shortResult = combinedOutput
296
317
  .trim()
297
318
  .split("\n")
@@ -1 +1 @@
1
- {"version":3,"file":"readTool.d.ts","sourceRoot":"","sources":["../../src/tools/readTool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AA8HtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UAiOtB,CAAC"}
1
+ {"version":3,"file":"readTool.d.ts","sourceRoot":"","sources":["../../src/tools/readTool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,YAAY,CAAC;AA8HtE;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,UA2MtB,CAAC"}
@@ -204,26 +204,14 @@ Usage:
204
204
  shortResult: "Empty file",
205
205
  };
206
206
  }
207
- // Check content size limit (100KB)
208
- const MAX_CONTENT_SIZE = 100 * 1024; // 100KB
209
- let contentToProcess = fileContent;
210
- let contentTruncated = false;
211
- if (fileContent.length > MAX_CONTENT_SIZE) {
212
- contentToProcess = fileContent.substring(0, MAX_CONTENT_SIZE);
213
- contentTruncated = true;
214
- }
215
- const lines = contentToProcess.split("\n");
216
- const totalLines = lines.length;
217
- const originalTotalLines = fileContent.split("\n").length;
207
+ const allLines = fileContent.split("\n");
208
+ const totalLines = allLines.length;
218
209
  // Handle offset and limit
219
210
  let startLine = 1;
220
- let endLine = Math.min(totalLines, 2000); // Default maximum read 2000 lines
221
211
  if (typeof offset === "number") {
222
212
  startLine = Math.max(1, offset);
223
213
  }
224
- if (typeof limit === "number") {
225
- endLine = Math.min(totalLines, startLine + limit - 1);
226
- }
214
+ let endLine = Math.min(totalLines, startLine + (typeof limit === "number" ? limit : 2000) - 1);
227
215
  // If no offset and limit specified, read entire file (maximum 2000 lines)
228
216
  if (typeof offset !== "number" && typeof limit !== "number") {
229
217
  startLine = 1;
@@ -238,7 +226,7 @@ Usage:
238
226
  };
239
227
  }
240
228
  // Extract specified line range
241
- const selectedLines = lines.slice(startLine - 1, endLine);
229
+ const selectedLines = allLines.slice(startLine - 1, endLine);
242
230
  // Format output (cat -n format, with line numbers)
243
231
  const formattedContent = selectedLines
244
232
  .map((line, index) => {
@@ -250,11 +238,7 @@ Usage:
250
238
  .join("\n");
251
239
  // Add file information header
252
240
  let content = `File: ${filePath}\n`;
253
- if (contentTruncated) {
254
- content += `Content truncated at ${MAX_CONTENT_SIZE} bytes\n`;
255
- content += `Lines ${startLine}-${endLine} of ${totalLines} (original file: ${originalTotalLines} lines)\n`;
256
- }
257
- else if (startLine > 1 || endLine < totalLines) {
241
+ if (startLine > 1 || endLine < totalLines) {
258
242
  content += `Lines ${startLine}-${endLine} of ${totalLines}\n`;
259
243
  }
260
244
  else {
@@ -263,22 +247,14 @@ Usage:
263
247
  content += "─".repeat(50) + "\n";
264
248
  content += formattedContent;
265
249
  // If only showing partial content, add prompt
266
- if (endLine < totalLines || contentTruncated) {
250
+ if (endLine < totalLines) {
267
251
  content += `\n${"─".repeat(50)}\n`;
268
- if (contentTruncated) {
269
- content += `... content truncated due to size limit (${MAX_CONTENT_SIZE} bytes)`;
270
- if (endLine < totalLines) {
271
- content += ` and ${totalLines - endLine} more lines not shown`;
272
- }
273
- }
274
- else {
275
- content += `... ${totalLines - endLine} more lines not shown`;
276
- }
252
+ content += `... ${totalLines - endLine} more lines not shown`;
277
253
  }
278
254
  return {
279
255
  success: true,
280
256
  content,
281
- shortResult: `Read ${selectedLines.length} lines${totalLines > 2000 || contentTruncated ? " (truncated)" : ""}`,
257
+ shortResult: `Read ${selectedLines.length} lines${totalLines > 2000 ? " (truncated)" : ""}`,
282
258
  };
283
259
  }
284
260
  catch (error) {
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { AskUserQuestion, AskUserQuestionInput, AskUserQuestionOption } from "./tools.js";
6
6
  /** Permission mode configuration */
7
- export type PermissionMode = "default" | "bypassPermissions" | "acceptEdits" | "plan";
7
+ export type PermissionMode = "default" | "bypassPermissions" | "acceptEdits" | "plan" | "dontAsk";
8
8
  /** Result of a permission check */
9
9
  export interface PermissionDecision {
10
10
  /** Whether to allow or deny the operation */
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/types/permissions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AASpB,oCAAoC;AACpC,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,mBAAmB,GACnB,aAAa,GACb,MAAM,CAAC;AAEX,mCAAmC;AACnC,MAAM,WAAW,kBAAkB;IACjC,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,cAAc,CAAC;IACnC,2CAA2C;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,oDAAoD;AACpD,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEjC,mDAAmD;AACnD,MAAM,WAAW,qBAAqB;IACpC,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,cAAc,EAAE,cAAc,CAAC;IAC/B,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,yCAAyC;IACzC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2FAA2F;IAC3F,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,mEAAmE;AACnE,eAAO,MAAM,gBAAgB,uEAMnB,CAAC;AAEX,qCAAqC;AACrC,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D,eAAO,MAAM,2BAA2B,gCAAgC,CAAC;AAEzE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,CAAC"}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/types/permissions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AASpB,oCAAoC;AACpC,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,mBAAmB,GACnB,aAAa,GACb,MAAM,GACN,SAAS,CAAC;AAEd,mCAAmC;AACnC,MAAM,WAAW,kBAAkB;IACjC,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,cAAc,CAAC;IACnC,2CAA2C;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,oDAAoD;AACpD,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEjC,mDAAmD;AACnD,MAAM,WAAW,qBAAqB;IACpC,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,cAAc,EAAE,cAAc,CAAC;IAC/B,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,yCAAyC;IACzC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2FAA2F;IAC3F,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,mEAAmE;AACnE,eAAO,MAAM,gBAAgB,uEAMnB,CAAC;AAEX,qCAAqC;AACrC,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D,eAAO,MAAM,2BAA2B,gCAAgC,CAAC;AAEzE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.10.2",
3
+ "version": "0.10.4",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
@@ -47,7 +47,7 @@
47
47
  "license": "MIT",
48
48
  "scripts": {
49
49
  "postinstall": "node scripts/postinstall.js",
50
- "build": "rimraf dist && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
50
+ "build": "rimraf dist && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && cp -r src/builtin-skills dist/builtin-skills",
51
51
  "type-check": "tsc --noEmit --incremental",
52
52
  "watch": "tsc -p tsconfig.build.json --watch & tsc-alias -p tsconfig.build.json --watch",
53
53
  "test": "vitest run --reporter=dot",
@@ -457,6 +457,7 @@ export class AIManager {
457
457
  isSubagent: !!this.subagentType,
458
458
  planMode: planModeOptions,
459
459
  autoMemory: autoMemoryOptions,
460
+ permissionMode: currentMode,
460
461
  },
461
462
  ), // Pass custom system prompt
462
463
  maxTokens: maxTokens, // Pass max tokens override
@@ -421,6 +421,17 @@ export class PermissionManager {
421
421
  return { behavior: "allow" };
422
422
  }
423
423
 
424
+ // 2.1 If dontAsk mode, auto-deny restricted tools that were not allowed by rules above
425
+ if (context.permissionMode === "dontAsk") {
426
+ logger?.info("Restricted tool automatically denied in dontAsk mode", {
427
+ toolName: context.toolName,
428
+ });
429
+ return {
430
+ behavior: "deny",
431
+ message: `Tool '${context.toolName}' was automatically denied because 'dontAsk' permission mode is active and no pre-approved rule matches this call.`,
432
+ };
433
+ }
434
+
424
435
  // 3. If custom callback provided, call it and return result
425
436
  if (context.canUseToolCallback) {
426
437
  try {
@@ -2,6 +2,7 @@ import * as os from "node:os";
2
2
  import { ToolPlugin } from "../tools/types.js";
3
3
  import { isGitRepository } from "../utils/gitUtils.js";
4
4
  import { buildAutoMemoryPrompt } from "./autoMemory.js";
5
+ import { PermissionMode } from "../types/permissions.js";
5
6
  import {
6
7
  EXPLORE_SUBAGENT_TYPE,
7
8
  PLAN_SUBAGENT_TYPE,
@@ -307,6 +308,7 @@ export function buildSystemPrompt(
307
308
  directory: string;
308
309
  content: string;
309
310
  };
311
+ permissionMode?: PermissionMode;
310
312
  } = {},
311
313
  ): string {
312
314
  let prompt = basePrompt || DEFAULT_SYSTEM_PROMPT;
@@ -314,6 +316,10 @@ export function buildSystemPrompt(
314
316
  prompt += `\n\n${TOOL_POLICY}`;
315
317
  }
316
318
 
319
+ if (options.permissionMode === "dontAsk") {
320
+ prompt += `\n\n# Permission Mode\nThe user has selected the 'dontAsk' permission mode. In this mode, any restricted tool call that does not match a pre-approved rule in 'permissions.allow' or 'temporaryRules' will be automatically denied without prompting the user. You will receive a 'Permission denied' error for such calls. This is intended to prevent interruptions for untrusted tools while allowing pre-approved ones to run seamlessly.`;
321
+ }
322
+
317
323
  if (options.language) {
318
324
  prompt += `\n\n# Language\nAlways respond in ${options.language}. Technical terms (e.g., code, tool names, file paths) should remain in their original language or English where appropriate.`;
319
325
  }
@@ -1,4 +1,7 @@
1
1
  import { spawn, ChildProcess } from "child_process";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import * as os from "os";
2
5
  import { logger } from "../utils/globalLogger.js";
3
6
  import { stripAnsiColors } from "../utils/stringUtils.js";
4
7
  import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
@@ -15,6 +18,33 @@ import {
15
18
  const MAX_OUTPUT_LENGTH = 30000;
16
19
  const BASH_DEFAULT_TIMEOUT_MS = 120000;
17
20
 
21
+ /**
22
+ * Helper function to handle large output by truncation and persistence to a temporary file.
23
+ */
24
+ function processOutput(output: string): string {
25
+ if (output.length <= MAX_OUTPUT_LENGTH) {
26
+ return output;
27
+ }
28
+
29
+ try {
30
+ const tempDir = os.tmpdir();
31
+ const fileName = `bash_output_${Date.now()}_${Math.random().toString(36).substring(2, 11)}.txt`;
32
+ const filePath = path.join(tempDir, fileName);
33
+ fs.writeFileSync(filePath, output, "utf8");
34
+
35
+ return (
36
+ output.substring(0, MAX_OUTPUT_LENGTH) +
37
+ `\n\n... (output truncated)\nFull output persisted to: ${filePath}`
38
+ );
39
+ } catch (error) {
40
+ logger.error("Failed to persist large bash output:", error);
41
+ return (
42
+ output.substring(0, MAX_OUTPUT_LENGTH) +
43
+ "\n\n... (output truncated, failed to persist full output)"
44
+ );
45
+ }
46
+ }
47
+
18
48
  /**
19
49
  * Bash command execution tool - supports both foreground and background execution
20
50
  */
@@ -75,7 +105,7 @@ Usage notes:
75
105
  - The command argument is required.
76
106
  - 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).
77
107
  - It is very helpful if you write a clear, concise description of what this command does in 5-10 words.
78
- - If the output exceeds ${MAX_OUTPUT_LENGTH} characters, output will be truncated before being returned to you.
108
+ - If the output exceeds ${MAX_OUTPUT_LENGTH} characters, output will be truncated and the full output will be persisted to a temporary file.
79
109
  - 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_NAME} tool as it becomes available. You do not need to use '&' at the end of the command when using this parameter.
80
110
  - Avoid using ${BASH_TOOL_NAME} with the \`find\`, \`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:
81
111
  - File search: Use ${GLOB_TOOL_NAME} (NOT find or ls)
@@ -292,7 +322,9 @@ Usage notes:
292
322
 
293
323
  resolve({
294
324
  success: false,
295
- content: outputBuffer + (errorBuffer ? "\n" + errorBuffer : ""),
325
+ content: processOutput(
326
+ outputBuffer + (errorBuffer ? "\n" + errorBuffer : ""),
327
+ ),
296
328
  error: reason,
297
329
  });
298
330
  }
@@ -340,14 +372,10 @@ Usage notes:
340
372
  const combinedOutput =
341
373
  outputBuffer + (errorBuffer ? "\n" + errorBuffer : "");
342
374
 
343
- // Handle large output by truncation if needed
375
+ // Handle large output by truncation and persistence if needed
344
376
  const finalOutput =
345
377
  combinedOutput || `Command executed with exit code: ${exitCode}`;
346
- const content =
347
- finalOutput.length > MAX_OUTPUT_LENGTH
348
- ? finalOutput.substring(0, MAX_OUTPUT_LENGTH) +
349
- "\n\n... (output truncated)"
350
- : finalOutput;
378
+ const content = processOutput(finalOutput);
351
379
 
352
380
  const shortResult = combinedOutput
353
381
  .trim()
@@ -243,31 +243,19 @@ Usage:
243
243
  };
244
244
  }
245
245
 
246
- // Check content size limit (100KB)
247
- const MAX_CONTENT_SIZE = 100 * 1024; // 100KB
248
- let contentToProcess = fileContent;
249
- let contentTruncated = false;
250
-
251
- if (fileContent.length > MAX_CONTENT_SIZE) {
252
- contentToProcess = fileContent.substring(0, MAX_CONTENT_SIZE);
253
- contentTruncated = true;
254
- }
255
-
256
- const lines = contentToProcess.split("\n");
257
- const totalLines = lines.length;
258
- const originalTotalLines = fileContent.split("\n").length;
246
+ const allLines = fileContent.split("\n");
247
+ const totalLines = allLines.length;
259
248
 
260
249
  // Handle offset and limit
261
250
  let startLine = 1;
262
- let endLine = Math.min(totalLines, 2000); // Default maximum read 2000 lines
263
-
264
251
  if (typeof offset === "number") {
265
252
  startLine = Math.max(1, offset);
266
253
  }
267
254
 
268
- if (typeof limit === "number") {
269
- endLine = Math.min(totalLines, startLine + limit - 1);
270
- }
255
+ let endLine = Math.min(
256
+ totalLines,
257
+ startLine + (typeof limit === "number" ? limit : 2000) - 1,
258
+ );
271
259
 
272
260
  // If no offset and limit specified, read entire file (maximum 2000 lines)
273
261
  if (typeof offset !== "number" && typeof limit !== "number") {
@@ -285,7 +273,7 @@ Usage:
285
273
  }
286
274
 
287
275
  // Extract specified line range
288
- const selectedLines = lines.slice(startLine - 1, endLine);
276
+ const selectedLines = allLines.slice(startLine - 1, endLine);
289
277
 
290
278
  // Format output (cat -n format, with line numbers)
291
279
  const formattedContent = selectedLines
@@ -300,10 +288,7 @@ Usage:
300
288
 
301
289
  // Add file information header
302
290
  let content = `File: ${filePath}\n`;
303
- if (contentTruncated) {
304
- content += `Content truncated at ${MAX_CONTENT_SIZE} bytes\n`;
305
- content += `Lines ${startLine}-${endLine} of ${totalLines} (original file: ${originalTotalLines} lines)\n`;
306
- } else if (startLine > 1 || endLine < totalLines) {
291
+ if (startLine > 1 || endLine < totalLines) {
307
292
  content += `Lines ${startLine}-${endLine} of ${totalLines}\n`;
308
293
  } else {
309
294
  content += `Total lines: ${totalLines}\n`;
@@ -312,22 +297,15 @@ Usage:
312
297
  content += formattedContent;
313
298
 
314
299
  // If only showing partial content, add prompt
315
- if (endLine < totalLines || contentTruncated) {
300
+ if (endLine < totalLines) {
316
301
  content += `\n${"─".repeat(50)}\n`;
317
- if (contentTruncated) {
318
- content += `... content truncated due to size limit (${MAX_CONTENT_SIZE} bytes)`;
319
- if (endLine < totalLines) {
320
- content += ` and ${totalLines - endLine} more lines not shown`;
321
- }
322
- } else {
323
- content += `... ${totalLines - endLine} more lines not shown`;
324
- }
302
+ content += `... ${totalLines - endLine} more lines not shown`;
325
303
  }
326
304
 
327
305
  return {
328
306
  success: true,
329
307
  content,
330
- shortResult: `Read ${selectedLines.length} lines${totalLines > 2000 || contentTruncated ? " (truncated)" : ""}`,
308
+ shortResult: `Read ${selectedLines.length} lines${totalLines > 2000 ? " (truncated)" : ""}`,
331
309
  };
332
310
  } catch (error) {
333
311
  return {
@@ -21,7 +21,8 @@ export type PermissionMode =
21
21
  | "default"
22
22
  | "bypassPermissions"
23
23
  | "acceptEdits"
24
- | "plan";
24
+ | "plan"
25
+ | "dontAsk";
25
26
 
26
27
  /** Result of a permission check */
27
28
  export interface PermissionDecision {