wave-agent-sdk 0.0.8 → 0.0.10
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 +92 -23
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +340 -137
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/managers/aiManager.d.ts +14 -36
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +74 -77
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +4 -3
- package/dist/managers/hookManager.d.ts +3 -8
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +39 -29
- package/dist/managers/liveConfigManager.d.ts +55 -18
- package/dist/managers/liveConfigManager.d.ts.map +1 -1
- package/dist/managers/liveConfigManager.js +372 -90
- package/dist/managers/lspManager.d.ts +43 -0
- package/dist/managers/lspManager.d.ts.map +1 -0
- package/dist/managers/lspManager.js +326 -0
- package/dist/managers/messageManager.d.ts +8 -16
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +52 -74
- package/dist/managers/permissionManager.d.ts +66 -0
- package/dist/managers/permissionManager.d.ts.map +1 -0
- package/dist/managers/permissionManager.js +208 -0
- package/dist/managers/skillManager.d.ts +1 -0
- package/dist/managers/skillManager.d.ts.map +1 -1
- package/dist/managers/skillManager.js +2 -1
- package/dist/managers/slashCommandManager.d.ts.map +1 -1
- package/dist/managers/slashCommandManager.js +0 -1
- package/dist/managers/subagentManager.d.ts +8 -23
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +97 -117
- package/dist/managers/toolManager.d.ts +38 -1
- package/dist/managers/toolManager.d.ts.map +1 -1
- package/dist/managers/toolManager.js +66 -2
- package/dist/services/aiService.d.ts +3 -1
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +123 -30
- package/dist/services/configurationService.d.ts +116 -0
- package/dist/services/configurationService.d.ts.map +1 -0
- package/dist/services/configurationService.js +585 -0
- package/dist/services/fileWatcher.d.ts.map +1 -1
- package/dist/services/fileWatcher.js +5 -6
- package/dist/services/hook.d.ts +7 -124
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +46 -458
- package/dist/services/jsonlHandler.d.ts +24 -15
- package/dist/services/jsonlHandler.d.ts.map +1 -1
- package/dist/services/jsonlHandler.js +67 -88
- package/dist/services/memory.d.ts +0 -9
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +2 -49
- package/dist/services/session.d.ts +82 -33
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +275 -181
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +72 -13
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +25 -0
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +30 -6
- package/dist/tools/lspTool.d.ts +6 -0
- package/dist/tools/lspTool.d.ts.map +1 -0
- package/dist/tools/lspTool.js +589 -0
- package/dist/tools/multiEditTool.d.ts.map +1 -1
- package/dist/tools/multiEditTool.js +26 -7
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +111 -2
- package/dist/tools/skillTool.js +2 -2
- package/dist/tools/todoWriteTool.d.ts.map +1 -1
- package/dist/tools/todoWriteTool.js +23 -0
- package/dist/tools/types.d.ts +11 -8
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/writeTool.d.ts.map +1 -1
- package/dist/tools/writeTool.js +25 -9
- package/dist/types/commands.d.ts +0 -1
- package/dist/types/commands.d.ts.map +1 -1
- package/dist/types/config.d.ts +4 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/configuration.d.ts +69 -0
- package/dist/types/configuration.d.ts.map +1 -0
- package/dist/types/configuration.js +8 -0
- package/dist/types/core.d.ts +10 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/environment.d.ts +41 -0
- package/dist/types/environment.d.ts.map +1 -1
- package/dist/types/fileSearch.d.ts +5 -0
- package/dist/types/fileSearch.d.ts.map +1 -0
- package/dist/types/fileSearch.js +1 -0
- package/dist/types/hooks.d.ts +11 -2
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +1 -7
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +5 -0
- package/dist/types/lsp.d.ts +90 -0
- package/dist/types/lsp.d.ts.map +1 -0
- package/dist/types/lsp.js +4 -0
- package/dist/types/messaging.d.ts +6 -11
- package/dist/types/messaging.d.ts.map +1 -1
- package/dist/types/permissions.d.ts +35 -0
- package/dist/types/permissions.d.ts.map +1 -0
- package/dist/types/permissions.js +12 -0
- package/dist/types/session.d.ts +1 -6
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/skills.d.ts +1 -0
- package/dist/types/skills.d.ts.map +1 -1
- package/dist/types/tools.d.ts +35 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +4 -0
- package/dist/utils/abortUtils.d.ts +34 -0
- package/dist/utils/abortUtils.d.ts.map +1 -0
- package/dist/utils/abortUtils.js +92 -0
- package/dist/utils/bashHistory.d.ts +4 -0
- package/dist/utils/bashHistory.d.ts.map +1 -1
- package/dist/utils/bashHistory.js +21 -4
- package/dist/utils/builtinSubagents.d.ts +7 -0
- package/dist/utils/builtinSubagents.d.ts.map +1 -0
- package/dist/utils/builtinSubagents.js +65 -0
- package/dist/utils/cacheControlUtils.d.ts +8 -33
- package/dist/utils/cacheControlUtils.d.ts.map +1 -1
- package/dist/utils/cacheControlUtils.js +83 -126
- package/dist/utils/constants.d.ts +0 -12
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +1 -13
- package/dist/utils/convertMessagesForAPI.d.ts +2 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +33 -14
- package/dist/utils/fileSearch.d.ts +14 -0
- package/dist/utils/fileSearch.d.ts.map +1 -0
- package/dist/utils/fileSearch.js +88 -0
- package/dist/utils/fileUtils.d.ts +14 -2
- package/dist/utils/fileUtils.d.ts.map +1 -1
- package/dist/utils/fileUtils.js +101 -17
- package/dist/utils/globalLogger.d.ts +0 -14
- package/dist/utils/globalLogger.d.ts.map +1 -1
- package/dist/utils/globalLogger.js +0 -16
- package/dist/utils/largeOutputHandler.d.ts +15 -0
- package/dist/utils/largeOutputHandler.d.ts.map +1 -0
- package/dist/utils/largeOutputHandler.js +40 -0
- package/dist/utils/markdownParser.d.ts.map +1 -1
- package/dist/utils/markdownParser.js +1 -17
- package/dist/utils/messageOperations.d.ts +1 -11
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +7 -24
- package/dist/utils/pathEncoder.d.ts +4 -0
- package/dist/utils/pathEncoder.d.ts.map +1 -1
- package/dist/utils/pathEncoder.js +16 -9
- package/dist/utils/subagentParser.d.ts +2 -2
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +10 -7
- package/dist/utils/tokenEstimator.d.ts +39 -0
- package/dist/utils/tokenEstimator.d.ts.map +1 -0
- package/dist/utils/tokenEstimator.js +55 -0
- package/package.json +5 -8
- package/src/agent.ts +460 -216
- package/src/index.ts +2 -0
- package/src/managers/aiManager.ts +107 -111
- package/src/managers/backgroundBashManager.ts +4 -3
- package/src/managers/hookManager.ts +44 -39
- package/src/managers/liveConfigManager.ts +524 -138
- package/src/managers/lspManager.ts +434 -0
- package/src/managers/messageManager.ts +73 -103
- package/src/managers/permissionManager.ts +276 -0
- package/src/managers/skillManager.ts +3 -1
- package/src/managers/slashCommandManager.ts +1 -2
- package/src/managers/subagentManager.ts +116 -159
- package/src/managers/toolManager.ts +95 -3
- package/src/services/aiService.ts +207 -26
- package/src/services/configurationService.ts +762 -0
- package/src/services/fileWatcher.ts +5 -6
- package/src/services/hook.ts +50 -631
- package/src/services/jsonlHandler.ts +84 -100
- package/src/services/memory.ts +2 -59
- package/src/services/session.ts +338 -213
- package/src/tools/bashTool.ts +89 -16
- package/src/tools/deleteFileTool.ts +36 -0
- package/src/tools/editTool.ts +41 -7
- package/src/tools/lspTool.ts +760 -0
- package/src/tools/multiEditTool.ts +37 -8
- package/src/tools/readTool.ts +125 -2
- package/src/tools/skillTool.ts +2 -2
- package/src/tools/todoWriteTool.ts +33 -1
- package/src/tools/types.ts +15 -9
- package/src/tools/writeTool.ts +36 -10
- package/src/types/commands.ts +0 -1
- package/src/types/config.ts +5 -0
- package/src/types/configuration.ts +73 -0
- package/src/types/core.ts +11 -0
- package/src/types/environment.ts +44 -0
- package/src/types/fileSearch.ts +4 -0
- package/src/types/hooks.ts +14 -11
- package/src/types/index.ts +5 -0
- package/src/types/lsp.ts +96 -0
- package/src/types/messaging.ts +8 -13
- package/src/types/permissions.ts +48 -0
- package/src/types/session.ts +3 -8
- package/src/types/skills.ts +1 -0
- package/src/types/tools.ts +38 -0
- package/src/utils/abortUtils.ts +118 -0
- package/src/utils/bashHistory.ts +28 -4
- package/src/utils/builtinSubagents.ts +71 -0
- package/src/utils/cacheControlUtils.ts +106 -171
- package/src/utils/constants.ts +1 -16
- package/src/utils/convertMessagesForAPI.ts +38 -14
- package/src/utils/fileSearch.ts +107 -0
- package/src/utils/fileUtils.ts +114 -19
- package/src/utils/globalLogger.ts +0 -17
- package/src/utils/largeOutputHandler.ts +55 -0
- package/src/utils/markdownParser.ts +1 -19
- package/src/utils/messageOperations.ts +7 -35
- package/src/utils/pathEncoder.ts +24 -9
- package/src/utils/subagentParser.ts +11 -8
- package/src/utils/tokenEstimator.ts +68 -0
- package/dist/constants/events.d.ts +0 -28
- package/dist/constants/events.d.ts.map +0 -1
- package/dist/constants/events.js +0 -27
- package/dist/services/configurationWatcher.d.ts +0 -120
- package/dist/services/configurationWatcher.d.ts.map +0 -1
- package/dist/services/configurationWatcher.js +0 -439
- package/dist/services/memoryStore.d.ts +0 -81
- package/dist/services/memoryStore.d.ts.map +0 -1
- package/dist/services/memoryStore.js +0 -200
- package/dist/types/memoryStore.d.ts +0 -82
- package/dist/types/memoryStore.d.ts.map +0 -1
- package/dist/types/memoryStore.js +0 -7
- package/dist/utils/configResolver.d.ts +0 -65
- package/dist/utils/configResolver.d.ts.map +0 -1
- package/dist/utils/configResolver.js +0 -210
- package/src/constants/events.ts +0 -38
- package/src/services/configurationWatcher.ts +0 -622
- package/src/services/memoryStore.ts +0 -279
- package/src/types/memoryStore.ts +0 -94
- package/src/utils/configResolver.ts +0 -302
|
@@ -2,7 +2,6 @@ import { readFile, writeFile } from "fs/promises";
|
|
|
2
2
|
import { logger } from "../utils/globalLogger.js";
|
|
3
3
|
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
4
4
|
import { resolvePath, getDisplayPath } from "../utils/path.js";
|
|
5
|
-
import { diffLines } from "diff";
|
|
6
5
|
|
|
7
6
|
interface EditOperation {
|
|
8
7
|
old_string: string;
|
|
@@ -182,7 +181,7 @@ export const multiEditTool: ToolPlugin = {
|
|
|
182
181
|
return {
|
|
183
182
|
success: false,
|
|
184
183
|
content: "",
|
|
185
|
-
error: `Edit operation ${i + 1}: old_string not found in current content
|
|
184
|
+
error: `Edit operation ${i + 1}: old_string not found in current content`,
|
|
186
185
|
};
|
|
187
186
|
}
|
|
188
187
|
|
|
@@ -217,6 +216,42 @@ export const multiEditTool: ToolPlugin = {
|
|
|
217
216
|
}
|
|
218
217
|
}
|
|
219
218
|
|
|
219
|
+
// Permission check after validation but before real operation
|
|
220
|
+
if (
|
|
221
|
+
context.permissionManager &&
|
|
222
|
+
context.permissionMode &&
|
|
223
|
+
context.permissionMode !== "bypassPermissions"
|
|
224
|
+
) {
|
|
225
|
+
if (context.permissionManager.isRestrictedTool("MultiEdit")) {
|
|
226
|
+
try {
|
|
227
|
+
const permissionContext = context.permissionManager.createContext(
|
|
228
|
+
"MultiEdit",
|
|
229
|
+
context.permissionMode,
|
|
230
|
+
context.canUseToolCallback,
|
|
231
|
+
{ file_path: filePath, edits },
|
|
232
|
+
);
|
|
233
|
+
const permissionResult =
|
|
234
|
+
await context.permissionManager.checkPermission(
|
|
235
|
+
permissionContext,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
if (permissionResult.behavior === "deny") {
|
|
239
|
+
return {
|
|
240
|
+
success: false,
|
|
241
|
+
content: "",
|
|
242
|
+
error: `MultiEdit operation denied by user, reason: ${permissionResult.message || "No reason provided"}`,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
} catch {
|
|
246
|
+
return {
|
|
247
|
+
success: false,
|
|
248
|
+
content: "",
|
|
249
|
+
error: "Permission check failed",
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
220
255
|
// Write file
|
|
221
256
|
try {
|
|
222
257
|
await writeFile(resolvedPath, currentContent, "utf-8");
|
|
@@ -228,9 +263,6 @@ export const multiEditTool: ToolPlugin = {
|
|
|
228
263
|
};
|
|
229
264
|
}
|
|
230
265
|
|
|
231
|
-
// Generate diff information
|
|
232
|
-
const diffResult = diffLines(originalContent, currentContent);
|
|
233
|
-
|
|
234
266
|
const shortResult = isNewFile
|
|
235
267
|
? `Created file with ${edits.length} operations`
|
|
236
268
|
: `Applied ${edits.length} edits`;
|
|
@@ -244,9 +276,6 @@ export const multiEditTool: ToolPlugin = {
|
|
|
244
276
|
content: detailedContent,
|
|
245
277
|
shortResult,
|
|
246
278
|
filePath: resolvedPath,
|
|
247
|
-
originalContent,
|
|
248
|
-
newContent: currentContent,
|
|
249
|
-
diffResult,
|
|
250
279
|
};
|
|
251
280
|
} catch (error) {
|
|
252
281
|
const errorMessage =
|
package/src/tools/readTool.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { readFile } from "fs/promises";
|
|
1
|
+
import { readFile, stat } from "fs/promises";
|
|
2
|
+
import { extname } from "path";
|
|
2
3
|
import { logger } from "../utils/globalLogger.js";
|
|
3
4
|
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
4
5
|
import { resolvePath, getDisplayPath } from "../utils/path.js";
|
|
@@ -6,6 +7,123 @@ import {
|
|
|
6
7
|
isBinaryDocument,
|
|
7
8
|
getBinaryDocumentError,
|
|
8
9
|
} from "../utils/fileFormat.js";
|
|
10
|
+
import { convertImageToBase64 } from "../utils/messageOperations.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Supported image file extensions
|
|
14
|
+
*/
|
|
15
|
+
const SUPPORTED_IMAGE_EXTENSIONS = [
|
|
16
|
+
"png",
|
|
17
|
+
"jpeg",
|
|
18
|
+
"jpg",
|
|
19
|
+
"gif",
|
|
20
|
+
"webp",
|
|
21
|
+
] as const;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check if a file path represents an image file
|
|
25
|
+
* @param filePath - Path to the file
|
|
26
|
+
* @returns true if the file is a supported image format
|
|
27
|
+
*/
|
|
28
|
+
function isImageFile(filePath: string): boolean {
|
|
29
|
+
const ext = extname(filePath).toLowerCase().substring(1);
|
|
30
|
+
return (SUPPORTED_IMAGE_EXTENSIONS as readonly string[]).includes(ext);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Validate image file size
|
|
35
|
+
* @param filePath - Path to the image file
|
|
36
|
+
* @param maxSizeBytes - Maximum allowed file size in bytes (default: 20MB)
|
|
37
|
+
* @returns Promise<boolean> - true if file size is within limit
|
|
38
|
+
*/
|
|
39
|
+
async function validateImageFileSize(
|
|
40
|
+
filePath: string,
|
|
41
|
+
maxSizeBytes: number = 20 * 1024 * 1024,
|
|
42
|
+
): Promise<boolean> {
|
|
43
|
+
try {
|
|
44
|
+
const stats = await stat(filePath);
|
|
45
|
+
return stats.size <= maxSizeBytes;
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get MIME type for image file based on extension
|
|
53
|
+
* @param filePath - Path to the image file
|
|
54
|
+
* @returns MIME type string
|
|
55
|
+
*/
|
|
56
|
+
function getImageMimeType(filePath: string): string {
|
|
57
|
+
const ext = extname(filePath).toLowerCase().substring(1);
|
|
58
|
+
switch (ext) {
|
|
59
|
+
case "png":
|
|
60
|
+
return "image/png";
|
|
61
|
+
case "jpg":
|
|
62
|
+
case "jpeg":
|
|
63
|
+
return "image/jpeg";
|
|
64
|
+
case "gif":
|
|
65
|
+
return "image/gif";
|
|
66
|
+
case "webp":
|
|
67
|
+
return "image/webp";
|
|
68
|
+
default:
|
|
69
|
+
return "image/png"; // Default fallback
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Process an image file and return ToolResult with image data
|
|
75
|
+
* @param filePath - Path to the image file
|
|
76
|
+
* @param context - Tool execution context
|
|
77
|
+
* @returns Promise<ToolResult> with image data
|
|
78
|
+
*/
|
|
79
|
+
async function processImageFile(
|
|
80
|
+
filePath: string,
|
|
81
|
+
context: ToolContext,
|
|
82
|
+
): Promise<ToolResult> {
|
|
83
|
+
try {
|
|
84
|
+
// Resolve path
|
|
85
|
+
const actualFilePath = filePath.startsWith("/")
|
|
86
|
+
? filePath
|
|
87
|
+
: resolvePath(filePath, context.workdir);
|
|
88
|
+
|
|
89
|
+
// Validate file size
|
|
90
|
+
const isValidSize = await validateImageFileSize(actualFilePath);
|
|
91
|
+
if (!isValidSize) {
|
|
92
|
+
const stats = await stat(actualFilePath);
|
|
93
|
+
const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
|
|
94
|
+
return {
|
|
95
|
+
success: false,
|
|
96
|
+
content: "",
|
|
97
|
+
error: `Image file exceeds 20MB limit (actual: ${sizeMB}MB)`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Convert image to base64
|
|
102
|
+
const imageDataUrl = convertImageToBase64(actualFilePath);
|
|
103
|
+
const mimeType = getImageMimeType(actualFilePath);
|
|
104
|
+
|
|
105
|
+
// Extract base64 data from data URL (remove data:image/type;base64, prefix)
|
|
106
|
+
const base64Data = imageDataUrl.split(",")[1] || "";
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
success: true,
|
|
110
|
+
content: `Image file processed: ${getDisplayPath(filePath, context.workdir)}\nFormat: ${mimeType}\nSize: Available for AI processing`,
|
|
111
|
+
shortResult: `Image processed (${mimeType})`,
|
|
112
|
+
images: [
|
|
113
|
+
{
|
|
114
|
+
data: base64Data,
|
|
115
|
+
mediaType: mimeType,
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
};
|
|
119
|
+
} catch (error) {
|
|
120
|
+
return {
|
|
121
|
+
success: false,
|
|
122
|
+
content: "",
|
|
123
|
+
error: `Failed to process image: ${error instanceof Error ? error.message : String(error)}`,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
9
127
|
|
|
10
128
|
/**
|
|
11
129
|
* Read Tool Plugin - Read file content
|
|
@@ -17,7 +135,7 @@ export const readTool: ToolPlugin = {
|
|
|
17
135
|
function: {
|
|
18
136
|
name: "Read",
|
|
19
137
|
description:
|
|
20
|
-
"Reads a file from the local filesystem. You can access any file directly by using this tool.\nAssume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned.\n\nUsage:\n- The file_path parameter must be an absolute path, not a relative path\n- By default, it reads up to 2000 lines starting from the beginning of the file\n- You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters\n- Any lines longer than 2000 characters will be truncated\n- Results are returned using cat -n format, with line numbers starting at 1\n- This tool allows
|
|
138
|
+
"Reads a file from the local filesystem. You can access any file directly by using this tool.\nAssume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned.\n\nUsage:\n- The file_path parameter must be an absolute path, not a relative path\n- By default, it reads up to 2000 lines starting from the beginning of the file\n- You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters\n- Any lines longer than 2000 characters will be truncated\n- Results are returned using cat -n format, with line numbers starting at 1\n- This tool allows Agent to read images (eg PNG, JPG, etc). When reading an image file the contents are presented visually as Agent is a multimodal LLM.\n- This tool can read Jupyter notebooks (.ipynb files) and returns all cells with their outputs, combining code, text, and visualizations.\n- You have the capability to call multiple tools in a single response. It is always better to speculatively read multiple files as a batch that are potentially useful.\n- You will regularly be asked to read screenshots. If the user provides a path to a screenshot ALWAYS use this tool to view the file at the path. This tool will work with all temporary file paths like /var/folders/123/abc/T/TemporaryItems/NSIRD_screencaptureui_ZfB1tD/Screenshot.png\n- If you read a file that exists but has empty contents you will receive a system reminder warning in place of file contents.\n- Binary document formats (PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX) are not supported and will return an error.",
|
|
21
139
|
parameters: {
|
|
22
140
|
type: "object",
|
|
23
141
|
properties: {
|
|
@@ -65,6 +183,11 @@ export const readTool: ToolPlugin = {
|
|
|
65
183
|
};
|
|
66
184
|
}
|
|
67
185
|
|
|
186
|
+
// Check if this is an image file
|
|
187
|
+
if (isImageFile(filePath)) {
|
|
188
|
+
return processImageFile(filePath, context);
|
|
189
|
+
}
|
|
190
|
+
|
|
68
191
|
try {
|
|
69
192
|
// Note: New Read tool requires absolute paths, so we don't use resolvePath
|
|
70
193
|
// But for compatibility, if it's not an absolute path, we still try to resolve
|
package/src/tools/skillTool.ts
CHANGED
|
@@ -23,11 +23,11 @@ export function createSkillTool(skillManager: SkillManager): ToolPlugin {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
return {
|
|
26
|
-
name: "
|
|
26
|
+
name: "Skill",
|
|
27
27
|
config: {
|
|
28
28
|
type: "function",
|
|
29
29
|
function: {
|
|
30
|
-
name: "
|
|
30
|
+
name: "Skill",
|
|
31
31
|
description: getToolDescription(),
|
|
32
32
|
parameters: {
|
|
33
33
|
type: "object",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ToolPlugin, ToolResult } from "./types.js";
|
|
1
|
+
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
2
2
|
|
|
3
3
|
interface TodoItem {
|
|
4
4
|
content: string;
|
|
@@ -101,6 +101,38 @@ When in doubt, use this tool. Being proactive with task management demonstrates
|
|
|
101
101
|
},
|
|
102
102
|
},
|
|
103
103
|
|
|
104
|
+
formatCompactParams: (
|
|
105
|
+
params: Record<string, unknown>,
|
|
106
|
+
context: ToolContext,
|
|
107
|
+
) => {
|
|
108
|
+
void context; // Context not needed for this tool
|
|
109
|
+
try {
|
|
110
|
+
const { todos } = params as { todos?: TodoItem[] };
|
|
111
|
+
|
|
112
|
+
// Handle invalid or missing tasks array
|
|
113
|
+
if (!todos || !Array.isArray(todos)) {
|
|
114
|
+
return "invalid todos";
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Handle empty task list
|
|
118
|
+
if (todos.length === 0) {
|
|
119
|
+
return "0 tasks";
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Count completed tasks
|
|
123
|
+
const completedCount = todos.filter(
|
|
124
|
+
(todo) => todo && todo.status === "completed",
|
|
125
|
+
).length;
|
|
126
|
+
const totalCount = todos.length;
|
|
127
|
+
|
|
128
|
+
// Format with proper singular/plural
|
|
129
|
+
const taskWord = totalCount === 1 ? "task" : "tasks";
|
|
130
|
+
return `${completedCount}/${totalCount} ${taskWord}`;
|
|
131
|
+
} catch {
|
|
132
|
+
return "invalid todos";
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
|
|
104
136
|
execute: async (args: Record<string, unknown>): Promise<ToolResult> => {
|
|
105
137
|
try {
|
|
106
138
|
// Validate arguments
|
package/src/tools/types.ts
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { ChatCompletionFunctionTool } from "openai/resources.js";
|
|
6
|
+
import type {
|
|
7
|
+
PermissionMode,
|
|
8
|
+
PermissionCallback,
|
|
9
|
+
} from "../types/permissions.js";
|
|
6
10
|
|
|
7
11
|
export interface ToolPlugin {
|
|
8
12
|
name: string;
|
|
@@ -23,15 +27,7 @@ export interface ToolResult {
|
|
|
23
27
|
error?: string;
|
|
24
28
|
// Short output, used to display summary information in collapsed state
|
|
25
29
|
shortResult?: string;
|
|
26
|
-
//
|
|
27
|
-
originalContent?: string;
|
|
28
|
-
newContent?: string;
|
|
29
|
-
diffResult?: Array<{
|
|
30
|
-
count?: number;
|
|
31
|
-
value: string;
|
|
32
|
-
added?: boolean;
|
|
33
|
-
removed?: boolean;
|
|
34
|
-
}>;
|
|
30
|
+
// File path for operations that affect files
|
|
35
31
|
filePath?: string;
|
|
36
32
|
// Image data, for supporting multimedia content
|
|
37
33
|
images?: Array<{
|
|
@@ -44,4 +40,14 @@ export interface ToolContext {
|
|
|
44
40
|
abortSignal?: AbortSignal;
|
|
45
41
|
backgroundBashManager?: import("../managers/backgroundBashManager.js").BackgroundBashManager;
|
|
46
42
|
workdir: string;
|
|
43
|
+
/** Permission mode for this tool execution */
|
|
44
|
+
permissionMode?: PermissionMode;
|
|
45
|
+
/** Custom permission callback */
|
|
46
|
+
canUseToolCallback?: PermissionCallback;
|
|
47
|
+
/** Permission manager instance for permission checks */
|
|
48
|
+
permissionManager?: import("../managers/permissionManager.js").PermissionManager;
|
|
49
|
+
/** MCP manager instance for calling MCP tools */
|
|
50
|
+
mcpManager?: import("../managers/mcpManager.js").McpManager;
|
|
51
|
+
/** LSP manager instance for code intelligence */
|
|
52
|
+
lspManager?: import("../types/lsp.js").ILspManager;
|
|
47
53
|
}
|
package/src/tools/writeTool.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { dirname } from "path";
|
|
|
3
3
|
import { logger } from "../utils/globalLogger.js";
|
|
4
4
|
import type { ToolPlugin, ToolResult, ToolContext } from "./types.js";
|
|
5
5
|
import { resolvePath, getDisplayPath } from "../utils/path.js";
|
|
6
|
-
import { diffLines } from "diff";
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* File Write Tool Plugin
|
|
@@ -80,9 +79,6 @@ export const writeTool: ToolPlugin = {
|
|
|
80
79
|
content: `File ${filePath} already has the same content, no changes needed`,
|
|
81
80
|
shortResult: "No changes needed",
|
|
82
81
|
filePath: resolvedPath,
|
|
83
|
-
originalContent,
|
|
84
|
-
newContent: content,
|
|
85
|
-
diffResult: [],
|
|
86
82
|
};
|
|
87
83
|
}
|
|
88
84
|
|
|
@@ -102,6 +98,42 @@ export const writeTool: ToolPlugin = {
|
|
|
102
98
|
}
|
|
103
99
|
}
|
|
104
100
|
|
|
101
|
+
// Permission check after validation but before real operation
|
|
102
|
+
if (
|
|
103
|
+
context.permissionManager &&
|
|
104
|
+
context.permissionMode &&
|
|
105
|
+
context.permissionMode !== "bypassPermissions"
|
|
106
|
+
) {
|
|
107
|
+
if (context.permissionManager.isRestrictedTool("Write")) {
|
|
108
|
+
try {
|
|
109
|
+
const permissionContext = context.permissionManager.createContext(
|
|
110
|
+
"Write",
|
|
111
|
+
context.permissionMode,
|
|
112
|
+
context.canUseToolCallback,
|
|
113
|
+
{ file_path: filePath, content },
|
|
114
|
+
);
|
|
115
|
+
const permissionResult =
|
|
116
|
+
await context.permissionManager.checkPermission(
|
|
117
|
+
permissionContext,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
if (permissionResult.behavior === "deny") {
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
content: "",
|
|
124
|
+
error: `Write operation denied by user, reason: ${permissionResult.message || "No reason provided"}`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
} catch {
|
|
128
|
+
return {
|
|
129
|
+
success: false,
|
|
130
|
+
content: "",
|
|
131
|
+
error: "Permission check failed",
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
105
137
|
// Write file
|
|
106
138
|
try {
|
|
107
139
|
await writeFile(resolvedPath, content, "utf-8");
|
|
@@ -113,9 +145,6 @@ export const writeTool: ToolPlugin = {
|
|
|
113
145
|
};
|
|
114
146
|
}
|
|
115
147
|
|
|
116
|
-
// Generate diff information
|
|
117
|
-
const diffResult = diffLines(originalContent, content);
|
|
118
|
-
|
|
119
148
|
const shortResult = isExistingFile ? "File overwritten" : "File created";
|
|
120
149
|
|
|
121
150
|
const lines = content.split("\n").length;
|
|
@@ -129,9 +158,6 @@ export const writeTool: ToolPlugin = {
|
|
|
129
158
|
content: detailedContent,
|
|
130
159
|
shortResult,
|
|
131
160
|
filePath: resolvedPath,
|
|
132
|
-
originalContent,
|
|
133
|
-
newContent: content,
|
|
134
|
-
diffResult,
|
|
135
161
|
};
|
|
136
162
|
} catch (error) {
|
|
137
163
|
const errorMessage =
|
package/src/types/commands.ts
CHANGED
package/src/types/config.ts
CHANGED
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
* Dependencies: None
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import OpenAI from "openai";
|
|
7
|
+
|
|
6
8
|
export interface GatewayConfig {
|
|
7
9
|
apiKey: string;
|
|
8
10
|
baseURL: string;
|
|
11
|
+
defaultHeaders?: Record<string, string>;
|
|
12
|
+
fetchOptions?: OpenAI["fetchOptions"];
|
|
13
|
+
fetch?: OpenAI["fetch"];
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
export interface ModelConfig {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Management Types
|
|
3
|
+
*
|
|
4
|
+
* Types for centralized configuration loading and validation services.
|
|
5
|
+
* These support the refactored configuration architecture that separates
|
|
6
|
+
* configuration management from hook execution.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { WaveConfiguration } from "./hooks.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Result of configuration loading operations with detailed status information
|
|
13
|
+
*/
|
|
14
|
+
export interface ConfigurationLoadResult {
|
|
15
|
+
/** The loaded configuration, or null if loading failed */
|
|
16
|
+
configuration: WaveConfiguration | null;
|
|
17
|
+
/** Whether the loading operation was successful */
|
|
18
|
+
success: boolean;
|
|
19
|
+
/** Error message if loading failed */
|
|
20
|
+
error?: string;
|
|
21
|
+
/** Path of the successfully loaded file */
|
|
22
|
+
sourcePath?: string;
|
|
23
|
+
/** Non-critical warnings during loading */
|
|
24
|
+
warnings: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Result of configuration validation operations
|
|
29
|
+
*/
|
|
30
|
+
export interface ValidationResult {
|
|
31
|
+
/** Whether the configuration is valid */
|
|
32
|
+
isValid: boolean;
|
|
33
|
+
/** Critical errors that prevent configuration use */
|
|
34
|
+
errors: string[];
|
|
35
|
+
/** Non-critical warnings about the configuration */
|
|
36
|
+
warnings: string[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Configuration file paths organized by category
|
|
41
|
+
*/
|
|
42
|
+
export interface ConfigurationPaths {
|
|
43
|
+
/** User-specific configuration file paths in priority order */
|
|
44
|
+
userPaths: string[];
|
|
45
|
+
/** Project-specific configuration file paths in priority order */
|
|
46
|
+
projectPaths: string[];
|
|
47
|
+
/** All configuration paths combined */
|
|
48
|
+
allPaths: string[];
|
|
49
|
+
/** Only the paths that actually exist on the filesystem */
|
|
50
|
+
existingPaths: string[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Options for configuring the ConfigurationService
|
|
55
|
+
*/
|
|
56
|
+
export interface ConfigurationServiceOptions {
|
|
57
|
+
/** Working directory for resolving project configurations */
|
|
58
|
+
workdir: string;
|
|
59
|
+
/** Optional logger for configuration operations */
|
|
60
|
+
logger?: Logger;
|
|
61
|
+
/** Whether to enable validation during loading (default: true) */
|
|
62
|
+
enableValidation?: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Minimal logger interface for configuration services
|
|
67
|
+
*/
|
|
68
|
+
interface Logger {
|
|
69
|
+
error: (...args: unknown[]) => void;
|
|
70
|
+
warn: (...args: unknown[]) => void;
|
|
71
|
+
info: (...args: unknown[]) => void;
|
|
72
|
+
debug: (...args: unknown[]) => void;
|
|
73
|
+
}
|
package/src/types/core.ts
CHANGED
|
@@ -70,6 +70,17 @@ export interface ClaudeUsage extends CompletionUsage {
|
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Represents a diff change for tool parameter-based diff display
|
|
75
|
+
* Contains the old content and new content for comparison
|
|
76
|
+
*/
|
|
77
|
+
export interface Change {
|
|
78
|
+
/** The original content (empty string for additions) */
|
|
79
|
+
oldContent: string;
|
|
80
|
+
/** The new content (empty string for deletions) */
|
|
81
|
+
newContent: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
73
84
|
export class ConfigurationError extends Error {
|
|
74
85
|
constructor(
|
|
75
86
|
message: string,
|
package/src/types/environment.ts
CHANGED
|
@@ -58,3 +58,47 @@ export interface EnvironmentMergeOptions {
|
|
|
58
58
|
/** Whether to validate variable names for common patterns */
|
|
59
59
|
validateVariableNames?: boolean;
|
|
60
60
|
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Result of environment variable processing operations
|
|
64
|
+
*/
|
|
65
|
+
export interface EnvironmentProcessResult {
|
|
66
|
+
/** The processed environment variables */
|
|
67
|
+
processedVars: Record<string, string>;
|
|
68
|
+
/** Any conflicts that occurred during processing */
|
|
69
|
+
conflicts: EnvironmentConflict[];
|
|
70
|
+
/** Non-critical warnings during processing */
|
|
71
|
+
warnings: string[];
|
|
72
|
+
/** Whether the variables were successfully applied to process.env */
|
|
73
|
+
applied: boolean;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Enhanced environment merge context with conflict details
|
|
78
|
+
*/
|
|
79
|
+
export interface EnvironmentMergeContext {
|
|
80
|
+
/** User-provided environment variables */
|
|
81
|
+
userVars: Record<string, string>;
|
|
82
|
+
/** Project-provided environment variables */
|
|
83
|
+
projectVars: Record<string, string>;
|
|
84
|
+
/** Final merged environment variables */
|
|
85
|
+
mergedVars: Record<string, string>;
|
|
86
|
+
/** Detailed conflict information */
|
|
87
|
+
conflicts: EnvironmentConflict[];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Detailed information about an environment variable conflict
|
|
92
|
+
*/
|
|
93
|
+
export interface EnvironmentConflict {
|
|
94
|
+
/** The environment variable key */
|
|
95
|
+
key: string;
|
|
96
|
+
/** Value from user configuration */
|
|
97
|
+
userValue: string;
|
|
98
|
+
/** Value from project configuration */
|
|
99
|
+
projectValue: string;
|
|
100
|
+
/** Final resolved value (which source won) */
|
|
101
|
+
resolvedValue: string;
|
|
102
|
+
/** Which source provided the final value */
|
|
103
|
+
source: "user" | "project";
|
|
104
|
+
}
|
package/src/types/hooks.ts
CHANGED
|
@@ -5,22 +5,14 @@
|
|
|
5
5
|
* enabling automated actions at specific workflow points.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { join } from "path";
|
|
9
|
-
import { homedir } from "os";
|
|
10
|
-
|
|
11
|
-
// Session path utility (simplified version for hooks)
|
|
12
|
-
export function getSessionFilePath(sessionId: string): string {
|
|
13
|
-
const shortId = sessionId.split("_")[2] || sessionId.slice(-8);
|
|
14
|
-
return join(homedir(), ".wave", "sessions", `session_${shortId}.json`);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
8
|
// Hook event types - trigger points in the AI workflow
|
|
18
9
|
export type HookEvent =
|
|
19
10
|
| "PreToolUse"
|
|
20
11
|
| "PostToolUse"
|
|
21
12
|
| "UserPromptSubmit"
|
|
22
13
|
| "Stop"
|
|
23
|
-
| "SubagentStop"
|
|
14
|
+
| "SubagentStop"
|
|
15
|
+
| "Notification";
|
|
24
16
|
|
|
25
17
|
// Individual hook command configuration
|
|
26
18
|
export interface HookCommand {
|
|
@@ -38,6 +30,11 @@ export interface HookEventConfig {
|
|
|
38
30
|
export interface WaveConfiguration {
|
|
39
31
|
hooks?: Partial<Record<HookEvent, HookEventConfig[]>>;
|
|
40
32
|
env?: Record<string, string>; // Environment variables key-value pairs
|
|
33
|
+
defaultMode?: "default" | "bypassPermissions" | "acceptEdits"; // Default permission mode for restricted tools
|
|
34
|
+
/** New field for persistent permissions */
|
|
35
|
+
permissions?: {
|
|
36
|
+
allow?: string[];
|
|
37
|
+
};
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
// Legacy alias for backward compatibility - will be deprecated
|
|
@@ -117,6 +114,7 @@ export function isValidHookEvent(event: string): event is HookEvent {
|
|
|
117
114
|
"UserPromptSubmit",
|
|
118
115
|
"Stop",
|
|
119
116
|
"SubagentStop",
|
|
117
|
+
"Notification",
|
|
120
118
|
].includes(event);
|
|
121
119
|
}
|
|
122
120
|
|
|
@@ -155,7 +153,7 @@ export interface HookJsonInput {
|
|
|
155
153
|
session_id: string; // Format: "wave_session_{uuid}_{shortId}"
|
|
156
154
|
transcript_path: string; // Format: "~/.wave/sessions/session_{shortId}.json"
|
|
157
155
|
cwd: string; // Absolute path to current working directory
|
|
158
|
-
hook_event_name: HookEvent; // "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop" | "SubagentStop"
|
|
156
|
+
hook_event_name: HookEvent; // "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop" | "SubagentStop" | "Notification"
|
|
159
157
|
|
|
160
158
|
// Optional fields based on event type
|
|
161
159
|
tool_name?: string; // Present for PreToolUse, PostToolUse
|
|
@@ -163,6 +161,8 @@ export interface HookJsonInput {
|
|
|
163
161
|
tool_response?: unknown; // Present for PostToolUse only
|
|
164
162
|
user_prompt?: string; // Present for UserPromptSubmit only
|
|
165
163
|
subagent_type?: string; // Present when hook is executed by a subagent
|
|
164
|
+
message?: string; // Present for Notification events
|
|
165
|
+
notification_type?: string; // Present for Notification events
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
// Extended context interface for passing additional data to hook executor
|
|
@@ -172,8 +172,11 @@ export interface ExtendedHookExecutionContext extends HookExecutionContext {
|
|
|
172
172
|
cwd?: string; // Current working directory
|
|
173
173
|
toolInput?: unknown; // Tool input parameters (PreToolUse/PostToolUse)
|
|
174
174
|
toolResponse?: unknown; // Tool execution result (PostToolUse only)
|
|
175
|
+
env?: Record<string, string>; // Additional environment variables (from configuration)
|
|
175
176
|
userPrompt?: string; // User prompt text (UserPromptSubmit only)
|
|
176
177
|
subagentType?: string; // Subagent type when hook is executed by a subagent
|
|
178
|
+
message?: string; // Notification message (Notification only)
|
|
179
|
+
notificationType?: string; // Notification type (Notification only)
|
|
177
180
|
}
|
|
178
181
|
|
|
179
182
|
// Environment variables injected into hook processes
|
package/src/types/index.ts
CHANGED
|
@@ -23,3 +23,8 @@ export * from "./skills.js";
|
|
|
23
23
|
export * from "./config.js";
|
|
24
24
|
export * from "./session.js";
|
|
25
25
|
export * from "./environment.js";
|
|
26
|
+
export * from "./configuration.js"; // New configuration management types
|
|
27
|
+
export * from "./permissions.js";
|
|
28
|
+
export * from "./tools.js"; // Tool parameter types
|
|
29
|
+
export * from "./fileSearch.js"; // File search types
|
|
30
|
+
export * from "./lsp.js";
|