wave-agent-sdk 0.0.7 → 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 +105 -24
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +438 -53
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/managers/aiManager.d.ts +18 -7
- package/dist/managers/aiManager.d.ts.map +1 -1
- package/dist/managers/aiManager.js +254 -142
- package/dist/managers/backgroundBashManager.d.ts.map +1 -1
- package/dist/managers/backgroundBashManager.js +11 -9
- package/dist/managers/hookManager.d.ts +6 -6
- package/dist/managers/hookManager.d.ts.map +1 -1
- package/dist/managers/hookManager.js +81 -39
- package/dist/managers/liveConfigManager.d.ts +95 -0
- package/dist/managers/liveConfigManager.d.ts.map +1 -0
- package/dist/managers/liveConfigManager.js +442 -0
- 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 +41 -24
- package/dist/managers/messageManager.d.ts.map +1 -1
- package/dist/managers/messageManager.js +184 -73
- 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 +4 -2
- package/dist/managers/subagentManager.d.ts +42 -6
- package/dist/managers/subagentManager.d.ts.map +1 -1
- package/dist/managers/subagentManager.js +213 -62
- 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 +15 -5
- package/dist/services/aiService.d.ts.map +1 -1
- package/dist/services/aiService.js +446 -77
- 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 +69 -0
- package/dist/services/fileWatcher.d.ts.map +1 -0
- package/dist/services/fileWatcher.js +212 -0
- package/dist/services/hook.d.ts +5 -40
- package/dist/services/hook.d.ts.map +1 -1
- package/dist/services/hook.js +47 -109
- package/dist/services/jsonlHandler.d.ts +71 -0
- package/dist/services/jsonlHandler.d.ts.map +1 -0
- package/dist/services/jsonlHandler.js +236 -0
- package/dist/services/memory.d.ts.map +1 -1
- package/dist/services/memory.js +33 -11
- package/dist/services/session.d.ts +116 -52
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +415 -143
- package/dist/tools/bashTool.d.ts.map +1 -1
- package/dist/tools/bashTool.js +77 -17
- package/dist/tools/deleteFileTool.d.ts.map +1 -1
- package/dist/tools/deleteFileTool.js +27 -1
- package/dist/tools/editTool.d.ts.map +1 -1
- package/dist/tools/editTool.js +33 -8
- 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 +30 -10
- package/dist/tools/readTool.d.ts.map +1 -1
- package/dist/tools/readTool.js +113 -3
- 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 +30 -15
- package/dist/types/commands.d.ts +4 -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 +45 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/environment.d.ts +83 -0
- package/dist/types/environment.d.ts.map +1 -0
- package/dist/types/environment.js +21 -0
- 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 +18 -3
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/hooks.js +8 -8
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +7 -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 +19 -12
- 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 +15 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +7 -0
- 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 +48 -30
- 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 +96 -0
- package/dist/utils/cacheControlUtils.d.ts.map +1 -0
- package/dist/utils/cacheControlUtils.js +324 -0
- package/dist/utils/commandPathResolver.d.ts +52 -0
- package/dist/utils/commandPathResolver.d.ts.map +1 -0
- package/dist/utils/commandPathResolver.js +145 -0
- package/dist/utils/configPaths.d.ts +85 -0
- package/dist/utils/configPaths.d.ts.map +1 -0
- package/dist/utils/configPaths.js +121 -0
- package/dist/utils/constants.d.ts +1 -13
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +2 -14
- package/dist/utils/convertMessagesForAPI.d.ts +2 -1
- package/dist/utils/convertMessagesForAPI.d.ts.map +1 -1
- package/dist/utils/convertMessagesForAPI.js +39 -18
- package/dist/utils/customCommands.d.ts.map +1 -1
- package/dist/utils/customCommands.js +66 -21
- 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 +27 -0
- package/dist/utils/fileUtils.d.ts.map +1 -0
- package/dist/utils/fileUtils.js +145 -0
- package/dist/utils/globalLogger.d.ts +88 -0
- package/dist/utils/globalLogger.d.ts.map +1 -0
- package/dist/utils/globalLogger.js +120 -0
- 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/mcpUtils.d.ts.map +1 -1
- package/dist/utils/mcpUtils.js +25 -3
- package/dist/utils/messageOperations.d.ts +20 -18
- package/dist/utils/messageOperations.d.ts.map +1 -1
- package/dist/utils/messageOperations.js +30 -38
- package/dist/utils/pathEncoder.d.ts +108 -0
- package/dist/utils/pathEncoder.d.ts.map +1 -0
- package/dist/utils/pathEncoder.js +279 -0
- package/dist/utils/subagentParser.d.ts +2 -2
- package/dist/utils/subagentParser.d.ts.map +1 -1
- package/dist/utils/subagentParser.js +12 -8
- package/dist/utils/tokenCalculation.d.ts +26 -0
- package/dist/utils/tokenCalculation.d.ts.map +1 -0
- package/dist/utils/tokenCalculation.js +36 -0
- 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 +6 -6
- package/src/agent.ts +586 -78
- package/src/index.ts +4 -0
- package/src/managers/aiManager.ts +341 -192
- package/src/managers/backgroundBashManager.ts +11 -9
- package/src/managers/hookManager.ts +102 -54
- package/src/managers/liveConfigManager.ts +634 -0
- package/src/managers/lspManager.ts +434 -0
- package/src/managers/messageManager.ts +258 -121
- package/src/managers/permissionManager.ts +276 -0
- package/src/managers/skillManager.ts +3 -1
- package/src/managers/slashCommandManager.ts +5 -3
- package/src/managers/subagentManager.ts +295 -76
- package/src/managers/toolManager.ts +95 -3
- package/src/services/aiService.ts +656 -84
- package/src/services/configurationService.ts +762 -0
- package/src/services/fileWatcher.ts +300 -0
- package/src/services/hook.ts +54 -144
- package/src/services/jsonlHandler.ts +303 -0
- package/src/services/memory.ts +34 -11
- package/src/services/session.ts +522 -173
- package/src/tools/bashTool.ts +94 -20
- package/src/tools/deleteFileTool.ts +38 -1
- package/src/tools/editTool.ts +44 -9
- package/src/tools/lspTool.ts +760 -0
- package/src/tools/multiEditTool.ts +41 -11
- package/src/tools/readTool.ts +127 -3
- 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 +43 -16
- package/src/types/commands.ts +6 -1
- package/src/types/config.ts +5 -0
- package/src/types/configuration.ts +73 -0
- package/src/types/core.ts +55 -0
- package/src/types/environment.ts +104 -0
- package/src/types/fileSearch.ts +4 -0
- package/src/types/hooks.ts +32 -16
- package/src/types/index.ts +7 -0
- package/src/types/lsp.ts +96 -0
- package/src/types/messaging.ts +21 -14
- package/src/types/permissions.ts +48 -0
- package/src/types/session.ts +20 -0
- 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 +55 -31
- package/src/utils/builtinSubagents.ts +71 -0
- package/src/utils/cacheControlUtils.ts +475 -0
- package/src/utils/commandPathResolver.ts +189 -0
- package/src/utils/configPaths.ts +163 -0
- package/src/utils/constants.ts +2 -17
- package/src/utils/convertMessagesForAPI.ts +44 -18
- package/src/utils/customCommands.ts +90 -22
- package/src/utils/fileSearch.ts +107 -0
- package/src/utils/fileUtils.ts +160 -0
- package/src/utils/globalLogger.ts +128 -0
- package/src/utils/largeOutputHandler.ts +55 -0
- package/src/utils/markdownParser.ts +1 -19
- package/src/utils/mcpUtils.ts +34 -3
- package/src/utils/messageOperations.ts +47 -53
- package/src/utils/pathEncoder.ts +394 -0
- package/src/utils/subagentParser.ts +13 -9
- package/src/utils/tokenCalculation.ts +43 -0
- package/src/utils/tokenEstimator.ts +68 -0
- package/dist/utils/configResolver.d.ts +0 -38
- package/dist/utils/configResolver.d.ts.map +0 -1
- package/dist/utils/configResolver.js +0 -106
- package/src/utils/configResolver.ts +0 -142
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path encoding utility for converting working directory paths to filesystem-safe names
|
|
3
|
+
* Handles cross-platform directory name encoding for project-based session organization
|
|
4
|
+
*/
|
|
5
|
+
import { resolve, join } from "path";
|
|
6
|
+
import { createHash } from "crypto";
|
|
7
|
+
import { realpath, mkdir } from "fs/promises";
|
|
8
|
+
import { homedir, platform } from "os";
|
|
9
|
+
/**
|
|
10
|
+
* PathEncoder class for converting working directory paths to filesystem-safe names
|
|
11
|
+
*/
|
|
12
|
+
export class PathEncoder {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.options = {
|
|
15
|
+
maxLength: options.maxLength ?? 200,
|
|
16
|
+
pathSeparatorReplacement: options.pathSeparatorReplacement ?? "-",
|
|
17
|
+
spaceReplacement: options.spaceReplacement ?? "_",
|
|
18
|
+
invalidCharReplacement: options.invalidCharReplacement ?? "_",
|
|
19
|
+
preserveCase: options.preserveCase ?? false,
|
|
20
|
+
hashLength: options.hashLength ?? 8,
|
|
21
|
+
};
|
|
22
|
+
this.constraints = this.getFilesystemConstraints();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Encode a working directory path to a filesystem-safe directory name
|
|
26
|
+
*/
|
|
27
|
+
async encode(originalPath) {
|
|
28
|
+
// Resolve symbolic links and normalize path
|
|
29
|
+
const resolvedPath = await this.resolvePath(originalPath);
|
|
30
|
+
return this.encodeSync(resolvedPath);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Synchronously encode a path to a filesystem-safe directory name
|
|
34
|
+
* Note: Does not resolve symbolic links - use encode() for full path resolution
|
|
35
|
+
*/
|
|
36
|
+
encodeSync(pathToEncode) {
|
|
37
|
+
// Convert to safe directory name
|
|
38
|
+
let encoded = pathToEncode;
|
|
39
|
+
// Remove leading slash to avoid empty directory names
|
|
40
|
+
if (encoded.startsWith("/")) {
|
|
41
|
+
encoded = encoded.substring(1);
|
|
42
|
+
}
|
|
43
|
+
// Replace path separators with hyphens
|
|
44
|
+
encoded = encoded.replace(/[/\\]/g, this.options.pathSeparatorReplacement);
|
|
45
|
+
// Replace spaces with underscores
|
|
46
|
+
encoded = encoded.replace(/\s+/g, this.options.spaceReplacement);
|
|
47
|
+
// Replace invalid characters with underscores
|
|
48
|
+
const escapedChars = this.constraints.invalidCharacters
|
|
49
|
+
.map((c) => `\\${c}`)
|
|
50
|
+
.join("");
|
|
51
|
+
const invalidChars = new RegExp(`[${escapedChars}]`, "g");
|
|
52
|
+
encoded = encoded.replace(invalidChars, this.options.invalidCharReplacement);
|
|
53
|
+
// Convert to lowercase unless preserveCase is true
|
|
54
|
+
if (!this.options.preserveCase) {
|
|
55
|
+
encoded = encoded.toLowerCase();
|
|
56
|
+
}
|
|
57
|
+
// Handle length limit with hash
|
|
58
|
+
if (encoded.length > this.options.maxLength) {
|
|
59
|
+
const hash = this.generateHash(pathToEncode, this.options.hashLength);
|
|
60
|
+
const maxBaseLength = this.options.maxLength - this.options.hashLength - 1; // -1 for separator
|
|
61
|
+
encoded = `${encoded.substring(0, maxBaseLength)}-${hash}`;
|
|
62
|
+
}
|
|
63
|
+
return encoded;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Decode an encoded directory name back to original path (limited functionality)
|
|
67
|
+
* Note: This is best-effort as encoding is lossy
|
|
68
|
+
*/
|
|
69
|
+
async decode(encodedName) {
|
|
70
|
+
return this.decodeSync(encodedName);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Synchronously decode an encoded directory name back to original path (limited functionality)
|
|
74
|
+
* Note: This is best-effort as encoding is lossy
|
|
75
|
+
*/
|
|
76
|
+
decodeSync(encodedName) {
|
|
77
|
+
// This is a simplified version - full reversal is not always possible
|
|
78
|
+
// due to lossy encoding (case changes, character replacements, hashing)
|
|
79
|
+
// Check if this has a hash suffix
|
|
80
|
+
const hashPattern = new RegExp(`-[a-f0-9]{${this.options.hashLength}}$`);
|
|
81
|
+
if (hashPattern.test(encodedName)) {
|
|
82
|
+
// Cannot reliably decode hashed paths
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
// Attempt basic reversal
|
|
86
|
+
let decoded = encodedName;
|
|
87
|
+
// Reverse path separator replacement
|
|
88
|
+
decoded = decoded.replace(new RegExp(this.options.pathSeparatorReplacement, "g"), "/");
|
|
89
|
+
// Reverse space replacement
|
|
90
|
+
decoded = decoded.replace(new RegExp(this.options.spaceReplacement, "g"), " ");
|
|
91
|
+
// Add leading slash
|
|
92
|
+
decoded = `/${decoded}`;
|
|
93
|
+
return decoded;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Resolve symbolic links and normalize path before encoding
|
|
97
|
+
*/
|
|
98
|
+
async resolvePath(path) {
|
|
99
|
+
try {
|
|
100
|
+
// Expand tilde to home directory
|
|
101
|
+
const expandedPath = this.expandTilde(path);
|
|
102
|
+
// Resolve to absolute path
|
|
103
|
+
const absolutePath = resolve(expandedPath);
|
|
104
|
+
// Resolve symbolic links
|
|
105
|
+
const resolvedPath = await realpath(absolutePath);
|
|
106
|
+
return resolvedPath;
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
throw new Error(`Failed to resolve path "${path}": ${error}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get project directory info without creating the directory
|
|
114
|
+
*/
|
|
115
|
+
async getProjectDirectory(originalPath, baseSessionDir) {
|
|
116
|
+
// Resolve the original path and check for symbolic links
|
|
117
|
+
const expandedPath = this.expandTilde(originalPath);
|
|
118
|
+
const absolutePath = resolve(expandedPath);
|
|
119
|
+
let resolvedPath;
|
|
120
|
+
let isSymbolicLink = false;
|
|
121
|
+
try {
|
|
122
|
+
resolvedPath = await realpath(absolutePath);
|
|
123
|
+
isSymbolicLink = resolvedPath !== absolutePath;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// If realpath fails, use the absolute path
|
|
127
|
+
resolvedPath = absolutePath;
|
|
128
|
+
}
|
|
129
|
+
// Encode the resolved path
|
|
130
|
+
const encodedName = await this.encode(resolvedPath);
|
|
131
|
+
const encodedPath = join(baseSessionDir, encodedName);
|
|
132
|
+
// Generate hash if encoding resulted in truncation
|
|
133
|
+
let pathHash;
|
|
134
|
+
if (resolvedPath.length > this.options.maxLength) {
|
|
135
|
+
pathHash = this.generateHash(resolvedPath, this.options.hashLength);
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
originalPath: resolvedPath,
|
|
139
|
+
encodedName,
|
|
140
|
+
encodedPath,
|
|
141
|
+
pathHash,
|
|
142
|
+
isSymbolicLink,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Create project directory entity from original path
|
|
147
|
+
*/
|
|
148
|
+
async createProjectDirectory(originalPath, baseSessionDir) {
|
|
149
|
+
const projectDirectory = await this.getProjectDirectory(originalPath, baseSessionDir);
|
|
150
|
+
// Ensure the encoded directory exists
|
|
151
|
+
try {
|
|
152
|
+
await mkdir(projectDirectory.encodedPath, { recursive: true });
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Ignore errors if directory already exists
|
|
156
|
+
}
|
|
157
|
+
return projectDirectory;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Validate that an encoded name is filesystem-safe
|
|
161
|
+
*/
|
|
162
|
+
validateEncodedName(encodedName) {
|
|
163
|
+
// Check length
|
|
164
|
+
if (encodedName.length > this.constraints.maxDirectoryNameLength) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
// Check for invalid characters
|
|
168
|
+
for (const char of this.constraints.invalidCharacters) {
|
|
169
|
+
if (encodedName.includes(char)) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Check for reserved names
|
|
174
|
+
const lowerName = encodedName.toLowerCase();
|
|
175
|
+
if (this.constraints.reservedNames.some((reserved) => reserved.toLowerCase() === lowerName)) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
// Check for empty or dots-only names
|
|
179
|
+
if (!encodedName.trim() || /^\.+$/.test(encodedName)) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Handle encoding collisions by generating unique names
|
|
186
|
+
*/
|
|
187
|
+
resolveCollision(baseName, existingNames) {
|
|
188
|
+
if (!existingNames.has(baseName)) {
|
|
189
|
+
return baseName;
|
|
190
|
+
}
|
|
191
|
+
// Try numbered suffixes first
|
|
192
|
+
for (let i = 1; i <= 999; i++) {
|
|
193
|
+
const candidate = `${baseName}-${i}`;
|
|
194
|
+
if (!existingNames.has(candidate)) {
|
|
195
|
+
return candidate;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// If all numbered suffixes are taken, use hash
|
|
199
|
+
const hash = this.generateHash(baseName + Date.now(), this.options.hashLength);
|
|
200
|
+
return `${baseName}-${hash}`;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get platform-specific filesystem constraints
|
|
204
|
+
*/
|
|
205
|
+
getFilesystemConstraints() {
|
|
206
|
+
const currentPlatform = platform();
|
|
207
|
+
switch (currentPlatform) {
|
|
208
|
+
case "win32":
|
|
209
|
+
return {
|
|
210
|
+
maxDirectoryNameLength: 255,
|
|
211
|
+
maxPathLength: 260,
|
|
212
|
+
invalidCharacters: ["<", ">", ":", '"', "|", "?", "*"],
|
|
213
|
+
reservedNames: [
|
|
214
|
+
"CON",
|
|
215
|
+
"PRN",
|
|
216
|
+
"AUX",
|
|
217
|
+
"NUL",
|
|
218
|
+
"COM1",
|
|
219
|
+
"COM2",
|
|
220
|
+
"COM3",
|
|
221
|
+
"COM4",
|
|
222
|
+
"COM5",
|
|
223
|
+
"COM6",
|
|
224
|
+
"COM7",
|
|
225
|
+
"COM8",
|
|
226
|
+
"COM9",
|
|
227
|
+
"LPT1",
|
|
228
|
+
"LPT2",
|
|
229
|
+
"LPT3",
|
|
230
|
+
"LPT4",
|
|
231
|
+
"LPT5",
|
|
232
|
+
"LPT6",
|
|
233
|
+
"LPT7",
|
|
234
|
+
"LPT8",
|
|
235
|
+
"LPT9",
|
|
236
|
+
],
|
|
237
|
+
caseSensitive: false,
|
|
238
|
+
};
|
|
239
|
+
case "darwin":
|
|
240
|
+
return {
|
|
241
|
+
maxDirectoryNameLength: 255,
|
|
242
|
+
maxPathLength: 1024,
|
|
243
|
+
invalidCharacters: [":"],
|
|
244
|
+
reservedNames: [],
|
|
245
|
+
caseSensitive: false, // HFS+ is case-insensitive by default
|
|
246
|
+
};
|
|
247
|
+
default: // Linux and other Unix-like systems
|
|
248
|
+
return {
|
|
249
|
+
maxDirectoryNameLength: 255,
|
|
250
|
+
maxPathLength: 4096,
|
|
251
|
+
invalidCharacters: ["\0"],
|
|
252
|
+
reservedNames: [],
|
|
253
|
+
caseSensitive: true,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Generate hash for collision resolution
|
|
259
|
+
*/
|
|
260
|
+
generateHash(input, length) {
|
|
261
|
+
return createHash("sha256")
|
|
262
|
+
.update(input)
|
|
263
|
+
.digest("hex")
|
|
264
|
+
.substring(0, length);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Expand tilde (~) to home directory
|
|
268
|
+
*/
|
|
269
|
+
expandTilde(path) {
|
|
270
|
+
if (path.startsWith("~/") || path === "~") {
|
|
271
|
+
return path.replace(/^~/, homedir());
|
|
272
|
+
}
|
|
273
|
+
return path;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Default PathEncoder instance
|
|
278
|
+
*/
|
|
279
|
+
export const pathEncoder = new PathEncoder();
|
|
@@ -5,11 +5,11 @@ export interface SubagentConfiguration {
|
|
|
5
5
|
model?: string;
|
|
6
6
|
systemPrompt: string;
|
|
7
7
|
filePath: string;
|
|
8
|
-
scope: "project" | "user";
|
|
8
|
+
scope: "project" | "user" | "builtin";
|
|
9
9
|
priority: number;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* Load all subagent configurations from project and user directories
|
|
12
|
+
* Load all subagent configurations from project and user directories, plus built-in subagents
|
|
13
13
|
*/
|
|
14
14
|
export declare function loadSubagentConfigurations(workdir: string): Promise<SubagentConfiguration[]>;
|
|
15
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagentParser.d.ts","sourceRoot":"","sources":["../../src/utils/subagentParser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"subagentParser.d.ts","sourceRoot":"","sources":["../../src/utils/subagentParser.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;CAClB;AA+KD;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAsBlC;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAGvC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFileSync, readdirSync, statSync } from "fs";
|
|
2
2
|
import { join, extname } from "path";
|
|
3
|
+
import { logger } from "./globalLogger.js";
|
|
3
4
|
/**
|
|
4
5
|
* Parse YAML frontmatter from markdown file content
|
|
5
6
|
*/
|
|
@@ -67,10 +68,10 @@ function validateConfiguration(config, filePath) {
|
|
|
67
68
|
if (!config.description) {
|
|
68
69
|
throw new Error(`Missing required field 'description' in ${filePath}`);
|
|
69
70
|
}
|
|
70
|
-
// Validate name pattern
|
|
71
|
-
const namePattern = /^[a-
|
|
71
|
+
// Validate name pattern - allow letters (upper/lowercase), numbers, and hyphens
|
|
72
|
+
const namePattern = /^[a-zA-Z][a-zA-Z0-9-]*$/;
|
|
72
73
|
if (!namePattern.test(config.name)) {
|
|
73
|
-
throw new Error(`Invalid subagent name '${config.name}' in ${filePath}. Must start with a letter and contain only
|
|
74
|
+
throw new Error(`Invalid subagent name '${config.name}' in ${filePath}. Must start with a letter and contain only letters, numbers, and hyphens.`);
|
|
74
75
|
}
|
|
75
76
|
// Validate model if specified - allow any non-empty string
|
|
76
77
|
if (config.model && typeof config.model !== "string") {
|
|
@@ -120,7 +121,7 @@ function scanSubagentDirectory(dirPath, scope) {
|
|
|
120
121
|
}
|
|
121
122
|
catch (parseError) {
|
|
122
123
|
// Log error but continue with other files
|
|
123
|
-
|
|
124
|
+
logger.warn(`Warning: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
}
|
|
@@ -131,17 +132,20 @@ function scanSubagentDirectory(dirPath, scope) {
|
|
|
131
132
|
return configurations;
|
|
132
133
|
}
|
|
133
134
|
/**
|
|
134
|
-
* Load all subagent configurations from project and user directories
|
|
135
|
+
* Load all subagent configurations from project and user directories, plus built-in subagents
|
|
135
136
|
*/
|
|
136
137
|
export async function loadSubagentConfigurations(workdir) {
|
|
137
138
|
const projectDir = join(workdir, ".wave", "agents");
|
|
138
139
|
const userDir = join(process.env.HOME || "~", ".wave", "agents");
|
|
140
|
+
// Load configurations from all sources
|
|
141
|
+
const { getBuiltinSubagents } = await import("./builtinSubagents.js");
|
|
142
|
+
const builtinConfigs = getBuiltinSubagents();
|
|
139
143
|
const projectConfigs = scanSubagentDirectory(projectDir, "project");
|
|
140
144
|
const userConfigs = scanSubagentDirectory(userDir, "user");
|
|
141
|
-
// Merge configurations, with project configs taking precedence
|
|
145
|
+
// Merge configurations, with project configs taking highest precedence
|
|
142
146
|
const configMap = new Map();
|
|
143
|
-
// Process in reverse priority order (
|
|
144
|
-
for (const config of [...userConfigs, ...projectConfigs]) {
|
|
147
|
+
// Process in reverse priority order (built-in first, then user, then project)
|
|
148
|
+
for (const config of [...builtinConfigs, ...userConfigs, ...projectConfigs]) {
|
|
145
149
|
configMap.set(config.name, config);
|
|
146
150
|
}
|
|
147
151
|
return Array.from(configMap.values()).sort((a, b) => {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Usage } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Calculate comprehensive total tokens including cache-related tokens
|
|
4
|
+
*
|
|
5
|
+
* This function computes the true total token cost by including:
|
|
6
|
+
* - Base total_tokens (prompt + completion)
|
|
7
|
+
* - Cache read tokens (cost savings indicator)
|
|
8
|
+
* - Cache creation tokens (cache investment)
|
|
9
|
+
*
|
|
10
|
+
* For accurate cost tracking with Claude models that support cache control.
|
|
11
|
+
*
|
|
12
|
+
* @param usage - Usage statistics from AI operation
|
|
13
|
+
* @returns Comprehensive total including all cache-related tokens
|
|
14
|
+
*/
|
|
15
|
+
export declare function calculateComprehensiveTotalTokens(usage: Usage): number;
|
|
16
|
+
/**
|
|
17
|
+
* Extract the latest total tokens from the last message with usage data
|
|
18
|
+
* Uses comprehensive calculation that includes cache tokens for accurate tracking
|
|
19
|
+
*
|
|
20
|
+
* @param messages - Array of messages to search
|
|
21
|
+
* @returns Comprehensive total tokens from the most recent usage data, or 0 if none found
|
|
22
|
+
*/
|
|
23
|
+
export declare function extractLatestTotalTokens(messages: Array<{
|
|
24
|
+
usage?: Usage;
|
|
25
|
+
}>): number;
|
|
26
|
+
//# sourceMappingURL=tokenCalculation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenCalculation.d.ts","sourceRoot":"","sources":["../../src/utils/tokenCalculation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C;;;;;;;;;;;;GAYG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAMtE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,KAAK,CAAC;IAAE,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GACjC,MAAM,CAUR"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate comprehensive total tokens including cache-related tokens
|
|
3
|
+
*
|
|
4
|
+
* This function computes the true total token cost by including:
|
|
5
|
+
* - Base total_tokens (prompt + completion)
|
|
6
|
+
* - Cache read tokens (cost savings indicator)
|
|
7
|
+
* - Cache creation tokens (cache investment)
|
|
8
|
+
*
|
|
9
|
+
* For accurate cost tracking with Claude models that support cache control.
|
|
10
|
+
*
|
|
11
|
+
* @param usage - Usage statistics from AI operation
|
|
12
|
+
* @returns Comprehensive total including all cache-related tokens
|
|
13
|
+
*/
|
|
14
|
+
export function calculateComprehensiveTotalTokens(usage) {
|
|
15
|
+
const baseTokens = usage.total_tokens;
|
|
16
|
+
const cacheReadTokens = usage.cache_read_input_tokens || 0;
|
|
17
|
+
const cacheCreateTokens = usage.cache_creation_input_tokens || 0;
|
|
18
|
+
return baseTokens + cacheReadTokens + cacheCreateTokens;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Extract the latest total tokens from the last message with usage data
|
|
22
|
+
* Uses comprehensive calculation that includes cache tokens for accurate tracking
|
|
23
|
+
*
|
|
24
|
+
* @param messages - Array of messages to search
|
|
25
|
+
* @returns Comprehensive total tokens from the most recent usage data, or 0 if none found
|
|
26
|
+
*/
|
|
27
|
+
export function extractLatestTotalTokens(messages) {
|
|
28
|
+
// Find the last message with usage data (iterate backwards for efficiency)
|
|
29
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
30
|
+
const message = messages[i];
|
|
31
|
+
if (message.usage) {
|
|
32
|
+
return calculateComprehensiveTotalTokens(message.usage);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return 0; // No usage data found
|
|
36
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple token estimation utility for text content
|
|
3
|
+
*
|
|
4
|
+
* This provides a fast approximation of token count without requiring
|
|
5
|
+
* actual tokenization, which would be expensive for large content.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Estimate the number of tokens in a text string
|
|
9
|
+
*
|
|
10
|
+
* Uses a simple heuristic based on character count and common patterns:
|
|
11
|
+
* - Average token length varies by language and content type
|
|
12
|
+
* - English text: ~4-5 characters per token
|
|
13
|
+
* - Code/structured text: ~3-4 characters per token
|
|
14
|
+
* - Numbers/symbols: ~2-3 characters per token
|
|
15
|
+
*
|
|
16
|
+
* This function uses a conservative estimate of 4 characters per token
|
|
17
|
+
* which works well for mixed content (text + code + symbols).
|
|
18
|
+
*
|
|
19
|
+
* @param text - The text to estimate tokens for
|
|
20
|
+
* @returns Estimated number of tokens
|
|
21
|
+
*/
|
|
22
|
+
export declare function estimateTokenCount(text: string): number;
|
|
23
|
+
/**
|
|
24
|
+
* Check if estimated token count exceeds a threshold
|
|
25
|
+
*
|
|
26
|
+
* @param text - The text to check
|
|
27
|
+
* @param threshold - Token threshold (default: 20,000)
|
|
28
|
+
* @returns True if estimated tokens exceed threshold
|
|
29
|
+
*/
|
|
30
|
+
export declare function exceedsTokenThreshold(text: string, threshold?: number): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Get a human-readable description of estimated token usage
|
|
33
|
+
*
|
|
34
|
+
* @param text - The text to analyze
|
|
35
|
+
* @param threshold - Token threshold for comparison
|
|
36
|
+
* @returns Description string with token count and threshold info
|
|
37
|
+
*/
|
|
38
|
+
export declare function getTokenUsageDescription(text: string, threshold?: number): string;
|
|
39
|
+
//# sourceMappingURL=tokenEstimator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenEstimator.d.ts","sourceRoot":"","sources":["../../src/utils/tokenEstimator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcvD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,MAAc,GACxB,OAAO,CAET;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,MAAc,GACxB,MAAM,CAKR"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple token estimation utility for text content
|
|
3
|
+
*
|
|
4
|
+
* This provides a fast approximation of token count without requiring
|
|
5
|
+
* actual tokenization, which would be expensive for large content.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Estimate the number of tokens in a text string
|
|
9
|
+
*
|
|
10
|
+
* Uses a simple heuristic based on character count and common patterns:
|
|
11
|
+
* - Average token length varies by language and content type
|
|
12
|
+
* - English text: ~4-5 characters per token
|
|
13
|
+
* - Code/structured text: ~3-4 characters per token
|
|
14
|
+
* - Numbers/symbols: ~2-3 characters per token
|
|
15
|
+
*
|
|
16
|
+
* This function uses a conservative estimate of 4 characters per token
|
|
17
|
+
* which works well for mixed content (text + code + symbols).
|
|
18
|
+
*
|
|
19
|
+
* @param text - The text to estimate tokens for
|
|
20
|
+
* @returns Estimated number of tokens
|
|
21
|
+
*/
|
|
22
|
+
export function estimateTokenCount(text) {
|
|
23
|
+
if (!text || text.length === 0) {
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
// Base estimation: 4 characters per token (conservative)
|
|
27
|
+
const baseEstimate = Math.ceil(text.length / 4);
|
|
28
|
+
// Adjust for whitespace (spaces don't contribute much to token count)
|
|
29
|
+
const whitespaceCount = (text.match(/\s/g) || []).length;
|
|
30
|
+
const adjustedEstimate = Math.ceil((text.length - whitespaceCount * 0.5) / 4);
|
|
31
|
+
// Use the more conservative (higher) estimate
|
|
32
|
+
return Math.max(baseEstimate, adjustedEstimate);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if estimated token count exceeds a threshold
|
|
36
|
+
*
|
|
37
|
+
* @param text - The text to check
|
|
38
|
+
* @param threshold - Token threshold (default: 20,000)
|
|
39
|
+
* @returns True if estimated tokens exceed threshold
|
|
40
|
+
*/
|
|
41
|
+
export function exceedsTokenThreshold(text, threshold = 20000) {
|
|
42
|
+
return estimateTokenCount(text) > threshold;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get a human-readable description of estimated token usage
|
|
46
|
+
*
|
|
47
|
+
* @param text - The text to analyze
|
|
48
|
+
* @param threshold - Token threshold for comparison
|
|
49
|
+
* @returns Description string with token count and threshold info
|
|
50
|
+
*/
|
|
51
|
+
export function getTokenUsageDescription(text, threshold = 20000) {
|
|
52
|
+
const estimatedTokens = estimateTokenCount(text);
|
|
53
|
+
const exceedsThreshold = estimatedTokens > threshold;
|
|
54
|
+
return `${estimatedTokens.toLocaleString()} tokens (${exceedsThreshold ? "exceeds" : "within"} ${threshold.toLocaleString()} limit)`;
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wave-agent-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "SDK for building AI-powered development tools and agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -21,25 +21,25 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@modelcontextprotocol/sdk": "^1.18.2",
|
|
23
23
|
"@vscode/ripgrep": "^1.15.14",
|
|
24
|
-
"
|
|
25
|
-
"glob": "^
|
|
24
|
+
"chokidar": "^5.0.0",
|
|
25
|
+
"glob": "^13.0.0",
|
|
26
26
|
"minimatch": "^10.0.3",
|
|
27
27
|
"openai": "^5.12.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"rimraf": "^6.
|
|
30
|
+
"rimraf": "^6.1.2",
|
|
31
31
|
"tsc-alias": "^1.8.16",
|
|
32
32
|
"tsx": "^4.20.4",
|
|
33
33
|
"vitest": "^3.2.4"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
|
-
"node": ">=
|
|
36
|
+
"node": ">=22.0.0"
|
|
37
37
|
},
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "rimraf dist && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
41
41
|
"type-check": "tsc --noEmit --incremental",
|
|
42
|
-
"
|
|
42
|
+
"watch": "tsc -p tsconfig.build.json --watch & tsc-alias -p tsconfig.build.json --watch",
|
|
43
43
|
"test": "vitest run",
|
|
44
44
|
"lint": "eslint --cache",
|
|
45
45
|
"format": "prettier --write ."
|