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
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { existsSync, readdirSync } from "fs";
|
|
1
|
+
import { existsSync, readdirSync, statSync } from "fs";
|
|
2
2
|
import { join, extname, basename } from "path";
|
|
3
3
|
import { homedir } from "os";
|
|
4
4
|
import { parseMarkdownFile } from "./markdownParser.js";
|
|
5
|
+
import { generateCommandId, getCommandSegments, getNamespace, getDepth, } from "./commandPathResolver.js";
|
|
6
|
+
import { logger } from "./globalLogger.js";
|
|
5
7
|
/**
|
|
6
8
|
* Get the project-specific commands directory
|
|
7
9
|
*/
|
|
@@ -15,39 +17,82 @@ export function getUserCommandsDir() {
|
|
|
15
17
|
return join(homedir(), ".wave", "commands");
|
|
16
18
|
}
|
|
17
19
|
/**
|
|
18
|
-
* Scan a directory for markdown command files
|
|
20
|
+
* Scan a directory for markdown command files with nested directory support
|
|
21
|
+
* @param dirPath - Root commands directory path
|
|
22
|
+
* @param maxDepth - Maximum nesting depth to scan (default: 1)
|
|
19
23
|
*/
|
|
20
|
-
function scanCommandsDirectory(dirPath) {
|
|
24
|
+
function scanCommandsDirectory(dirPath, maxDepth = 1) {
|
|
21
25
|
if (!existsSync(dirPath)) {
|
|
22
26
|
return [];
|
|
23
27
|
}
|
|
28
|
+
return scanCommandsDirectoryRecursive(dirPath, dirPath, 0, maxDepth);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Recursively scan directory for commands with depth control
|
|
32
|
+
* @param currentPath - Current directory being scanned
|
|
33
|
+
* @param rootPath - Root commands directory (for relative path calculation)
|
|
34
|
+
* @param currentDepth - Current nesting depth
|
|
35
|
+
* @param maxDepth - Maximum allowed depth
|
|
36
|
+
*/
|
|
37
|
+
function scanCommandsDirectoryRecursive(currentPath, rootPath, currentDepth, maxDepth) {
|
|
24
38
|
const commands = [];
|
|
25
39
|
try {
|
|
26
|
-
const
|
|
27
|
-
for (const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const filePath = join(dirPath, file);
|
|
32
|
-
const commandName = basename(file, ".md");
|
|
40
|
+
const entries = readdirSync(currentPath);
|
|
41
|
+
for (const entryName of entries) {
|
|
42
|
+
const fullPath = join(currentPath, entryName);
|
|
43
|
+
let isDirectory = false;
|
|
44
|
+
let isFile = false;
|
|
33
45
|
try {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
name: commandName,
|
|
38
|
-
description: config?.description, // Use description from frontmatter
|
|
39
|
-
filePath,
|
|
40
|
-
content,
|
|
41
|
-
config,
|
|
42
|
-
});
|
|
46
|
+
const stats = statSync(fullPath);
|
|
47
|
+
isDirectory = stats.isDirectory();
|
|
48
|
+
isFile = stats.isFile();
|
|
43
49
|
}
|
|
44
50
|
catch (error) {
|
|
45
|
-
|
|
51
|
+
// Skip entries that cannot be stat'd
|
|
52
|
+
logger.warn(`Cannot access ${fullPath}:`, error);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (isDirectory) {
|
|
56
|
+
// Skip subdirectories if we're at max depth
|
|
57
|
+
if (currentDepth >= maxDepth) {
|
|
58
|
+
logger.warn(`Skipping directory ${fullPath}: exceeds maximum nesting depth of ${maxDepth}`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// Recursively scan subdirectory
|
|
62
|
+
const nestedCommands = scanCommandsDirectoryRecursive(fullPath, rootPath, currentDepth + 1, maxDepth);
|
|
63
|
+
commands.push(...nestedCommands);
|
|
64
|
+
}
|
|
65
|
+
else if (isFile && extname(entryName) === ".md") {
|
|
66
|
+
// Process markdown file
|
|
67
|
+
try {
|
|
68
|
+
const commandId = generateCommandId(fullPath, rootPath);
|
|
69
|
+
const segments = getCommandSegments(fullPath, rootPath);
|
|
70
|
+
const namespace = getNamespace(segments);
|
|
71
|
+
const depth = getDepth(segments);
|
|
72
|
+
const { content, config } = parseMarkdownFile(fullPath);
|
|
73
|
+
commands.push({
|
|
74
|
+
id: commandId,
|
|
75
|
+
name: basename(entryName, ".md"),
|
|
76
|
+
description: config?.description,
|
|
77
|
+
filePath: fullPath,
|
|
78
|
+
content,
|
|
79
|
+
config,
|
|
80
|
+
// Nested command metadata
|
|
81
|
+
namespace,
|
|
82
|
+
isNested: depth > 0,
|
|
83
|
+
depth,
|
|
84
|
+
segments,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
logger.warn(`Failed to load custom command from ${fullPath}:`, error);
|
|
89
|
+
}
|
|
46
90
|
}
|
|
91
|
+
// Skip non-markdown files silently
|
|
47
92
|
}
|
|
48
93
|
}
|
|
49
94
|
catch (error) {
|
|
50
|
-
|
|
95
|
+
logger.warn(`Failed to scan commands directory ${currentPath}:`, error);
|
|
51
96
|
}
|
|
52
97
|
return commands;
|
|
53
98
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Path } from "glob";
|
|
2
|
+
import type { FileItem } from "../types/fileSearch.js";
|
|
3
|
+
/**
|
|
4
|
+
* Convert Path objects to FileItem objects
|
|
5
|
+
*/
|
|
6
|
+
export declare const convertPathsToFileItems: (paths: Path[]) => FileItem[];
|
|
7
|
+
/**
|
|
8
|
+
* Search files and directories using glob patterns
|
|
9
|
+
*/
|
|
10
|
+
export declare const searchFiles: (query: string, options?: {
|
|
11
|
+
maxResults?: number;
|
|
12
|
+
workingDirectory?: string;
|
|
13
|
+
}) => Promise<FileItem[]>;
|
|
14
|
+
//# sourceMappingURL=fileSearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileSearch.d.ts","sourceRoot":"","sources":["../../src/utils/fileSearch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,IAAI,EAAE,MAAM,MAAM,CAAC;AAE9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,OAAO,IAAI,EAAE,KAAG,QAAQ,EAK/D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,OAAO,MAAM,EACb,UAAU;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,KACA,OAAO,CAAC,QAAQ,EAAE,CAmFpB,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { globIterate } from "glob";
|
|
2
|
+
import { getGlobIgnorePatterns } from "./fileFilter.js";
|
|
3
|
+
/**
|
|
4
|
+
* Convert Path objects to FileItem objects
|
|
5
|
+
*/
|
|
6
|
+
export const convertPathsToFileItems = (paths) => {
|
|
7
|
+
return paths.map((pathObj) => ({
|
|
8
|
+
path: pathObj.relative(),
|
|
9
|
+
type: pathObj.isDirectory() ? "directory" : "file",
|
|
10
|
+
}));
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Search files and directories using glob patterns
|
|
14
|
+
*/
|
|
15
|
+
export const searchFiles = async (query, options) => {
|
|
16
|
+
const { maxResults = 10, workingDirectory = process.cwd() } = options || {};
|
|
17
|
+
try {
|
|
18
|
+
const globOptions = {
|
|
19
|
+
ignore: getGlobIgnorePatterns(workingDirectory),
|
|
20
|
+
maxDepth: 10,
|
|
21
|
+
nocase: true, // Case insensitive
|
|
22
|
+
dot: true, // Include hidden files and directories
|
|
23
|
+
cwd: workingDirectory, // Specify search root directory
|
|
24
|
+
withFileTypes: true, // Get Path objects instead of strings
|
|
25
|
+
};
|
|
26
|
+
// Build glob patterns based on query
|
|
27
|
+
let patterns = [];
|
|
28
|
+
if (!query.trim()) {
|
|
29
|
+
// When query is empty, show some common file types and directories
|
|
30
|
+
patterns = [
|
|
31
|
+
"**/*.{ts,tsx,js,jsx,json,py,java}", // Combine common file extensions
|
|
32
|
+
"*/", // First level directories
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Build multiple glob patterns to support more flexible search
|
|
37
|
+
patterns = [
|
|
38
|
+
// Match files with filenames containing query
|
|
39
|
+
`**/*${query}*`,
|
|
40
|
+
// Match files with query in path (match directory names)
|
|
41
|
+
`**/${query}*/**/*`,
|
|
42
|
+
// Match directory names containing query
|
|
43
|
+
`**/*${query}*/`,
|
|
44
|
+
// Match directories containing query in path
|
|
45
|
+
`**/${query}*/`,
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
// Collect results until we reach maxResults
|
|
49
|
+
const collectedPaths = [];
|
|
50
|
+
const seenPaths = new Set();
|
|
51
|
+
// Process each pattern sequentially
|
|
52
|
+
for (const pattern of patterns) {
|
|
53
|
+
if (collectedPaths.length >= maxResults) {
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
// Use globIterate to get results one by one
|
|
57
|
+
const iterator = globIterate(pattern, globOptions);
|
|
58
|
+
for await (const pathObj of iterator) {
|
|
59
|
+
if (collectedPaths.length >= maxResults) {
|
|
60
|
+
// Stop the iterator when we have enough results
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
const relativePath = pathObj.relative();
|
|
64
|
+
if (!seenPaths.has(relativePath)) {
|
|
65
|
+
seenPaths.add(relativePath);
|
|
66
|
+
collectedPaths.push(pathObj);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Sort collected paths: directories first, then files
|
|
71
|
+
collectedPaths.sort((a, b) => {
|
|
72
|
+
const aIsDir = a.isDirectory();
|
|
73
|
+
const bIsDir = b.isDirectory();
|
|
74
|
+
if (aIsDir && !bIsDir)
|
|
75
|
+
return -1;
|
|
76
|
+
if (!aIsDir && bIsDir)
|
|
77
|
+
return 1;
|
|
78
|
+
return a.relative().localeCompare(b.relative());
|
|
79
|
+
});
|
|
80
|
+
// Convert to FileItems
|
|
81
|
+
const fileItems = convertPathsToFileItems(collectedPaths);
|
|
82
|
+
return fileItems;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error("Glob search error:", error);
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the first line of a file efficiently using Node.js readline.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} filePath - The path to the file.
|
|
5
|
+
* @return {Promise<string>} - The first non-empty line of the file, or an empty string otherwise.
|
|
6
|
+
*/
|
|
7
|
+
export declare function readFirstLine(filePath: string): Promise<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Reads a file from the end and returns the last non-empty line.
|
|
10
|
+
*
|
|
11
|
+
* This version supports files that end with:
|
|
12
|
+
* - "\n" (Unix-style, including modern macOS)
|
|
13
|
+
* - "\r\n" (Windows-style)
|
|
14
|
+
* - "\r" (older Mac-style, HL7, etc.)
|
|
15
|
+
*
|
|
16
|
+
* @param {string} filePath - The path to the file.
|
|
17
|
+
* @param {number} [minLength=1] - Minimum length for the returned line.
|
|
18
|
+
* @return {Promise<string>} - The last non-empty line of the file, or an empty string if no non-empty lines found.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getLastLine(filePath: string, minLength?: number): Promise<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Ensures that a pattern is present in the global git ignore file.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} pattern - The pattern to add to global git ignore.
|
|
25
|
+
*/
|
|
26
|
+
export declare function ensureGlobalGitIgnore(pattern: string): Promise<void>;
|
|
27
|
+
//# sourceMappingURL=fileUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileUtils.d.ts","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBrE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAI,GACZ,OAAO,CAAC,MAAM,CAAC,CA8DjB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC1E"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { execSync } from "node:child_process";
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
/**
|
|
7
|
+
* Reads the first line of a file efficiently using Node.js readline.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} filePath - The path to the file.
|
|
10
|
+
* @return {Promise<string>} - The first non-empty line of the file, or an empty string otherwise.
|
|
11
|
+
*/
|
|
12
|
+
export async function readFirstLine(filePath) {
|
|
13
|
+
const { createInterface } = await import("node:readline");
|
|
14
|
+
const fileStream = createReadStream(filePath);
|
|
15
|
+
const rl = createInterface({
|
|
16
|
+
input: fileStream,
|
|
17
|
+
crlfDelay: Infinity, // Handle \r\n properly
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
for await (const line of rl) {
|
|
21
|
+
const trimmedLine = line.trim();
|
|
22
|
+
if (trimmedLine.length > 0) {
|
|
23
|
+
return trimmedLine;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return "";
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// If reading fails (e.g., file doesn't exist), return empty string
|
|
30
|
+
return "";
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
rl.close();
|
|
34
|
+
fileStream.destroy();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Reads a file from the end and returns the last non-empty line.
|
|
39
|
+
*
|
|
40
|
+
* This version supports files that end with:
|
|
41
|
+
* - "\n" (Unix-style, including modern macOS)
|
|
42
|
+
* - "\r\n" (Windows-style)
|
|
43
|
+
* - "\r" (older Mac-style, HL7, etc.)
|
|
44
|
+
*
|
|
45
|
+
* @param {string} filePath - The path to the file.
|
|
46
|
+
* @param {number} [minLength=1] - Minimum length for the returned line.
|
|
47
|
+
* @return {Promise<string>} - The last non-empty line of the file, or an empty string if no non-empty lines found.
|
|
48
|
+
*/
|
|
49
|
+
export async function getLastLine(filePath, minLength = 1) {
|
|
50
|
+
let fileHandle;
|
|
51
|
+
try {
|
|
52
|
+
const stats = await fs.stat(filePath);
|
|
53
|
+
const fileSize = stats.size;
|
|
54
|
+
if (fileSize === 0)
|
|
55
|
+
return "";
|
|
56
|
+
fileHandle = await fs.open(filePath, "r");
|
|
57
|
+
const bufferSize = 8 * 1024; // 8KB buffer is usually enough for the last line
|
|
58
|
+
const buffer = Buffer.alloc(bufferSize);
|
|
59
|
+
let lineEnd = null;
|
|
60
|
+
let lineStart = null;
|
|
61
|
+
let currentPosition = fileSize;
|
|
62
|
+
while (currentPosition > 0 && lineStart === null) {
|
|
63
|
+
const readSize = Math.min(bufferSize, currentPosition);
|
|
64
|
+
currentPosition -= readSize;
|
|
65
|
+
const { bytesRead } = await fileHandle.read(buffer, 0, readSize, currentPosition);
|
|
66
|
+
for (let i = bytesRead - 1; i >= 0; i--) {
|
|
67
|
+
const charCode = buffer[i];
|
|
68
|
+
if (lineEnd === null) {
|
|
69
|
+
// Still looking for the end of the last non-empty line (skip trailing newlines and whitespace)
|
|
70
|
+
if (charCode > 32) {
|
|
71
|
+
lineEnd = currentPosition + i + 1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Looking for the start of the line (the newline before it)
|
|
76
|
+
if (charCode === 10 || charCode === 13) {
|
|
77
|
+
lineStart = currentPosition + i + 1;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (lineEnd === null)
|
|
84
|
+
return "";
|
|
85
|
+
if (lineStart === null)
|
|
86
|
+
lineStart = 0;
|
|
87
|
+
const length = lineEnd - lineStart;
|
|
88
|
+
if (length < minLength)
|
|
89
|
+
return "";
|
|
90
|
+
const resultBuffer = Buffer.alloc(length);
|
|
91
|
+
await fileHandle.read(resultBuffer, 0, length, lineStart);
|
|
92
|
+
const result = resultBuffer.toString("utf8").trim();
|
|
93
|
+
return result.length >= minLength ? result : "";
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// If reading fails (e.g., file doesn't exist), return empty string
|
|
97
|
+
return "";
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
if (fileHandle) {
|
|
101
|
+
await fileHandle.close();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Ensures that a pattern is present in the global git ignore file.
|
|
107
|
+
*
|
|
108
|
+
* @param {string} pattern - The pattern to add to global git ignore.
|
|
109
|
+
*/
|
|
110
|
+
export async function ensureGlobalGitIgnore(pattern) {
|
|
111
|
+
try {
|
|
112
|
+
let globalIgnorePath;
|
|
113
|
+
try {
|
|
114
|
+
globalIgnorePath = execSync("git config --get core.excludesfile", {
|
|
115
|
+
encoding: "utf8",
|
|
116
|
+
}).trim();
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// If not set, use default paths
|
|
120
|
+
const xdgConfigHome = process.env.XDG_CONFIG_HOME || path.join(homedir(), ".config");
|
|
121
|
+
globalIgnorePath = path.join(xdgConfigHome, "git", "ignore");
|
|
122
|
+
}
|
|
123
|
+
if (!globalIgnorePath)
|
|
124
|
+
return;
|
|
125
|
+
// Ensure directory exists
|
|
126
|
+
await fs.mkdir(path.dirname(globalIgnorePath), { recursive: true });
|
|
127
|
+
let content = "";
|
|
128
|
+
try {
|
|
129
|
+
content = await fs.readFile(globalIgnorePath, "utf8");
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// File doesn't exist
|
|
133
|
+
}
|
|
134
|
+
const lines = content.split("\n").map((line) => line.trim());
|
|
135
|
+
if (!lines.includes(pattern)) {
|
|
136
|
+
const newContent = content.endsWith("\n") || content === ""
|
|
137
|
+
? `${content}${pattern}\n`
|
|
138
|
+
: `${content}\n${pattern}\n`;
|
|
139
|
+
await fs.writeFile(globalIgnorePath, newContent, "utf8");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Ignore errors
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global Logger Registry for Agent SDK
|
|
3
|
+
*
|
|
4
|
+
* Provides zero-overhead logging access for utility functions and services
|
|
5
|
+
* without requiring parameter passing. Maintains singleton logger instance
|
|
6
|
+
* accessible across all SDK modules.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Zero overhead when no logger configured (single null check)
|
|
10
|
+
* - Thread-safe in Node.js single-threaded environment
|
|
11
|
+
* - Maintains backward compatibility with existing Logger interface
|
|
12
|
+
* - Direct function delegation when configured
|
|
13
|
+
*/
|
|
14
|
+
import type { Logger } from "../types/core.js";
|
|
15
|
+
/**
|
|
16
|
+
* Configure the global logger instance used by utility functions and services
|
|
17
|
+
*
|
|
18
|
+
* @param logger - Logger instance implementing the Logger interface, or null to disable logging
|
|
19
|
+
* @returns void
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { setGlobalLogger } from './utils/globalLogger.js';
|
|
24
|
+
*
|
|
25
|
+
* // Configure logger
|
|
26
|
+
* setGlobalLogger(myLogger);
|
|
27
|
+
*
|
|
28
|
+
* // Disable logging
|
|
29
|
+
* setGlobalLogger(null);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function setGlobalLogger(logger: Logger | null): void;
|
|
33
|
+
/**
|
|
34
|
+
* Reset global logger to unconfigured state
|
|
35
|
+
* Equivalent to setGlobalLogger(null)
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* clearGlobalLogger(); // All subsequent logging calls become no-ops
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function clearGlobalLogger(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Check if global logger is currently configured
|
|
45
|
+
*
|
|
46
|
+
* @returns true if logger configured, false otherwise
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* if (isLoggerConfigured()) {
|
|
51
|
+
* // Perform expensive logging operation
|
|
52
|
+
* const debugInfo = generateDebugInfo();
|
|
53
|
+
* logger.debug(debugInfo);
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function isLoggerConfigured(): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Zero-overhead logging interface
|
|
60
|
+
*
|
|
61
|
+
* Performance characteristics:
|
|
62
|
+
* - Unconfigured: Single null check + early return (near-zero cost)
|
|
63
|
+
* - Configured: Null check + function delegation
|
|
64
|
+
* - No object creation or intermediate allocations
|
|
65
|
+
*/
|
|
66
|
+
export declare const logger: {
|
|
67
|
+
/**
|
|
68
|
+
* Log debug-level message through global logger
|
|
69
|
+
* No-op when global logger is null (zero overhead)
|
|
70
|
+
*/
|
|
71
|
+
readonly debug: (...args: unknown[]) => void;
|
|
72
|
+
/**
|
|
73
|
+
* Log info-level message through global logger
|
|
74
|
+
* No-op when global logger is null (zero overhead)
|
|
75
|
+
*/
|
|
76
|
+
readonly info: (...args: unknown[]) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Log warning-level message through global logger
|
|
79
|
+
* No-op when global logger is null (zero overhead)
|
|
80
|
+
*/
|
|
81
|
+
readonly warn: (...args: unknown[]) => void;
|
|
82
|
+
/**
|
|
83
|
+
* Log error-level message through global logger
|
|
84
|
+
* No-op when global logger is null (zero overhead)
|
|
85
|
+
*/
|
|
86
|
+
readonly error: (...args: unknown[]) => void;
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=globalLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"globalLogger.d.ts","sourceRoot":"","sources":["../../src/utils/globalLogger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAa/C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAMD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM;IACjB;;;OAGG;8BACc,OAAO,EAAE,KAAG,IAAI;IAKjC;;;OAGG;6BACa,OAAO,EAAE,KAAG,IAAI;IAKhC;;;OAGG;6BACa,OAAO,EAAE,KAAG,IAAI;IAKhC;;;OAGG;8BACc,OAAO,EAAE,KAAG,IAAI;CAIzB,CAAC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global Logger Registry for Agent SDK
|
|
3
|
+
*
|
|
4
|
+
* Provides zero-overhead logging access for utility functions and services
|
|
5
|
+
* without requiring parameter passing. Maintains singleton logger instance
|
|
6
|
+
* accessible across all SDK modules.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Zero overhead when no logger configured (single null check)
|
|
10
|
+
* - Thread-safe in Node.js single-threaded environment
|
|
11
|
+
* - Maintains backward compatibility with existing Logger interface
|
|
12
|
+
* - Direct function delegation when configured
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Module-level storage for the global logger instance
|
|
16
|
+
* null = unconfigured (logging calls are no-ops)
|
|
17
|
+
* Logger = configured (calls are forwarded)
|
|
18
|
+
*/
|
|
19
|
+
let globalLogger = null;
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// Registry Management API
|
|
22
|
+
// =============================================================================
|
|
23
|
+
/**
|
|
24
|
+
* Configure the global logger instance used by utility functions and services
|
|
25
|
+
*
|
|
26
|
+
* @param logger - Logger instance implementing the Logger interface, or null to disable logging
|
|
27
|
+
* @returns void
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import { setGlobalLogger } from './utils/globalLogger.js';
|
|
32
|
+
*
|
|
33
|
+
* // Configure logger
|
|
34
|
+
* setGlobalLogger(myLogger);
|
|
35
|
+
*
|
|
36
|
+
* // Disable logging
|
|
37
|
+
* setGlobalLogger(null);
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function setGlobalLogger(logger) {
|
|
41
|
+
globalLogger = logger;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Reset global logger to unconfigured state
|
|
45
|
+
* Equivalent to setGlobalLogger(null)
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* clearGlobalLogger(); // All subsequent logging calls become no-ops
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export function clearGlobalLogger() {
|
|
53
|
+
globalLogger = null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Check if global logger is currently configured
|
|
57
|
+
*
|
|
58
|
+
* @returns true if logger configured, false otherwise
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* if (isLoggerConfigured()) {
|
|
63
|
+
* // Perform expensive logging operation
|
|
64
|
+
* const debugInfo = generateDebugInfo();
|
|
65
|
+
* logger.debug(debugInfo);
|
|
66
|
+
* }
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export function isLoggerConfigured() {
|
|
70
|
+
return globalLogger !== null;
|
|
71
|
+
}
|
|
72
|
+
// =============================================================================
|
|
73
|
+
// Zero-Overhead Logging API
|
|
74
|
+
// =============================================================================
|
|
75
|
+
/**
|
|
76
|
+
* Zero-overhead logging interface
|
|
77
|
+
*
|
|
78
|
+
* Performance characteristics:
|
|
79
|
+
* - Unconfigured: Single null check + early return (near-zero cost)
|
|
80
|
+
* - Configured: Null check + function delegation
|
|
81
|
+
* - No object creation or intermediate allocations
|
|
82
|
+
*/
|
|
83
|
+
export const logger = {
|
|
84
|
+
/**
|
|
85
|
+
* Log debug-level message through global logger
|
|
86
|
+
* No-op when global logger is null (zero overhead)
|
|
87
|
+
*/
|
|
88
|
+
debug: (...args) => {
|
|
89
|
+
if (globalLogger === null)
|
|
90
|
+
return;
|
|
91
|
+
globalLogger.debug(...args);
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
* Log info-level message through global logger
|
|
95
|
+
* No-op when global logger is null (zero overhead)
|
|
96
|
+
*/
|
|
97
|
+
info: (...args) => {
|
|
98
|
+
if (globalLogger === null)
|
|
99
|
+
return;
|
|
100
|
+
globalLogger.info(...args);
|
|
101
|
+
},
|
|
102
|
+
/**
|
|
103
|
+
* Log warning-level message through global logger
|
|
104
|
+
* No-op when global logger is null (zero overhead)
|
|
105
|
+
*/
|
|
106
|
+
warn: (...args) => {
|
|
107
|
+
if (globalLogger === null)
|
|
108
|
+
return;
|
|
109
|
+
globalLogger.warn(...args);
|
|
110
|
+
},
|
|
111
|
+
/**
|
|
112
|
+
* Log error-level message through global logger
|
|
113
|
+
* No-op when global logger is null (zero overhead)
|
|
114
|
+
*/
|
|
115
|
+
error: (...args) => {
|
|
116
|
+
if (globalLogger === null)
|
|
117
|
+
return;
|
|
118
|
+
globalLogger.error(...args);
|
|
119
|
+
},
|
|
120
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const LARGE_OUTPUT_TOKEN_THRESHOLD = 20000;
|
|
2
|
+
/**
|
|
3
|
+
* Handle large command output by writing to temporary file when token threshold is exceeded
|
|
4
|
+
*
|
|
5
|
+
* Uses token-based threshold (20k tokens) to determine when output should be written to temp file.
|
|
6
|
+
* This provides accurate estimation of actual token cost for LLM processing.
|
|
7
|
+
*
|
|
8
|
+
* @param output - The command output string
|
|
9
|
+
* @returns Object containing processed content and optional file path
|
|
10
|
+
*/
|
|
11
|
+
export declare function handleLargeOutput(output: string): Promise<{
|
|
12
|
+
content: string;
|
|
13
|
+
filePath?: string;
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=largeOutputHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"largeOutputHandler.d.ts","sourceRoot":"","sources":["../../src/utils/largeOutputHandler.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,4BAA4B,QAAQ,CAAC;AAElD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC,CA8BD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { writeFile } from "fs/promises";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { tmpdir } from "os";
|
|
4
|
+
import { logger } from "./globalLogger.js";
|
|
5
|
+
import { estimateTokenCount, getTokenUsageDescription, } from "./tokenEstimator.js";
|
|
6
|
+
// Token threshold for writing output to temp file (20k tokens)
|
|
7
|
+
export const LARGE_OUTPUT_TOKEN_THRESHOLD = 20000;
|
|
8
|
+
/**
|
|
9
|
+
* Handle large command output by writing to temporary file when token threshold is exceeded
|
|
10
|
+
*
|
|
11
|
+
* Uses token-based threshold (20k tokens) to determine when output should be written to temp file.
|
|
12
|
+
* This provides accurate estimation of actual token cost for LLM processing.
|
|
13
|
+
*
|
|
14
|
+
* @param output - The command output string
|
|
15
|
+
* @returns Object containing processed content and optional file path
|
|
16
|
+
*/
|
|
17
|
+
export async function handleLargeOutput(output) {
|
|
18
|
+
const estimatedTokens = estimateTokenCount(output);
|
|
19
|
+
// Check token threshold
|
|
20
|
+
if (estimatedTokens <= LARGE_OUTPUT_TOKEN_THRESHOLD) {
|
|
21
|
+
return { content: output };
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
// Create temp file for large output
|
|
25
|
+
const tempFileName = `bash-output-${Date.now()}-${Math.random().toString(36).substr(2, 9)}.txt`;
|
|
26
|
+
const tempFilePath = join(tmpdir(), tempFileName);
|
|
27
|
+
await writeFile(tempFilePath, output, "utf8");
|
|
28
|
+
const sizeKB = Math.round(output.length / 1024);
|
|
29
|
+
const tokenDescription = getTokenUsageDescription(output, LARGE_OUTPUT_TOKEN_THRESHOLD);
|
|
30
|
+
return {
|
|
31
|
+
content: `Large output (${sizeKB} KB, ${tokenDescription}) written to temporary file. Use the Read tool to access the full content.`,
|
|
32
|
+
filePath: tempFilePath,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
logger.warn(`Failed to write large output to temp file: ${error}`);
|
|
37
|
+
// Fallback to direct output if temp file creation fails
|
|
38
|
+
return { content: output };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdownParser.d.ts","sourceRoot":"","sources":["../../src/utils/markdownParser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAElE,UAAU,kBAAkB;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,wBAAwB,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"markdownParser.d.ts","sourceRoot":"","sources":["../../src/utils/markdownParser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAElE,UAAU,kBAAkB;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,wBAAwB,CAAC;CACnC;AA6CD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CA+BtE;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAClD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAgBA;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,iBAAiB,EAAE,GAC3B,MAAM,CAcR"}
|