@4onstudios/iris-agent 0.1.0
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/LICENSE +21 -0
- package/README.md +690 -0
- package/dist/api/acp/acpServer.d.ts +23 -0
- package/dist/api/acp/acpServer.js +814 -0
- package/dist/api/acp/index.d.ts +2 -0
- package/dist/api/acp/index.js +2 -0
- package/dist/api/acp/irisClient.d.ts +58 -0
- package/dist/api/acp/irisClient.js +214 -0
- package/dist/api/agent.d.ts +14 -0
- package/dist/api/agent.js +4171 -0
- package/dist/api/backendService.d.ts +4 -0
- package/dist/api/backendService.js +14 -0
- package/dist/api/core/agent/host/AgentContract.d.ts +82 -0
- package/dist/api/core/agent/host/AgentContract.js +1 -0
- package/dist/api/core/agent/host/AgentRegistry.d.ts +24 -0
- package/dist/api/core/agent/host/AgentRegistry.js +125 -0
- package/dist/api/core/agent/host/defaultRegistry.d.ts +15 -0
- package/dist/api/core/agent/host/defaultRegistry.js +46 -0
- package/dist/api/core/agent/host/externalAgentLifecycle.d.ts +65 -0
- package/dist/api/core/agent/host/externalAgentLifecycle.js +117 -0
- package/dist/api/core/agent/host/hostSessionManager.d.ts +111 -0
- package/dist/api/core/agent/host/hostSessionManager.js +352 -0
- package/dist/api/core/agent/host/index.d.ts +5 -0
- package/dist/api/core/agent/host/index.js +5 -0
- package/dist/api/core/agent/index.d.ts +87 -0
- package/dist/api/core/agent/index.js +1024 -0
- package/dist/api/core/agent/publicContracts.d.ts +35 -0
- package/dist/api/core/agent/publicContracts.js +103 -0
- package/dist/api/core/agent/tools/applyDiff.d.ts +51 -0
- package/dist/api/core/agent/tools/applyDiff.js +131 -0
- package/dist/api/core/agent/tools/backgroundTasks.d.ts +240 -0
- package/dist/api/core/agent/tools/backgroundTasks.js +313 -0
- package/dist/api/core/agent/tools/createDirectory.d.ts +43 -0
- package/dist/api/core/agent/tools/createDirectory.js +77 -0
- package/dist/api/core/agent/tools/deleteFile.d.ts +37 -0
- package/dist/api/core/agent/tools/deleteFile.js +66 -0
- package/dist/api/core/agent/tools/editFile.d.ts +73 -0
- package/dist/api/core/agent/tools/editFile.js +173 -0
- package/dist/api/core/agent/tools/executeCommand.d.ts +59 -0
- package/dist/api/core/agent/tools/executeCommand.js +250 -0
- package/dist/api/core/agent/tools/fileContent.d.ts +54 -0
- package/dist/api/core/agent/tools/fileContent.js +227 -0
- package/dist/api/core/agent/tools/findDefinition.d.ts +72 -0
- package/dist/api/core/agent/tools/findDefinition.js +109 -0
- package/dist/api/core/agent/tools/findReferences.d.ts +86 -0
- package/dist/api/core/agent/tools/findReferences.js +135 -0
- package/dist/api/core/agent/tools/formatDocument.d.ts +67 -0
- package/dist/api/core/agent/tools/formatDocument.js +90 -0
- package/dist/api/core/agent/tools/getCodeActions.d.ts +77 -0
- package/dist/api/core/agent/tools/getCodeActions.js +97 -0
- package/dist/api/core/agent/tools/getCodeCompletion.d.ts +77 -0
- package/dist/api/core/agent/tools/getCodeCompletion.js +174 -0
- package/dist/api/core/agent/tools/getCodeContext.d.ts +14 -0
- package/dist/api/core/agent/tools/getCodeContext.js +282 -0
- package/dist/api/core/agent/tools/getSignatureHelp.d.ts +61 -0
- package/dist/api/core/agent/tools/getSignatureHelp.js +85 -0
- package/dist/api/core/agent/tools/getSymbols.d.ts +50 -0
- package/dist/api/core/agent/tools/getSymbols.js +164 -0
- package/dist/api/core/agent/tools/getSymbolsLSP.d.ts +58 -0
- package/dist/api/core/agent/tools/getSymbolsLSP.js +147 -0
- package/dist/api/core/agent/tools/getTypeInfo.d.ts +70 -0
- package/dist/api/core/agent/tools/getTypeInfo.js +84 -0
- package/dist/api/core/agent/tools/getWorkspaceInfo.d.ts +80 -0
- package/dist/api/core/agent/tools/getWorkspaceInfo.js +281 -0
- package/dist/api/core/agent/tools/getWorkspaceSymbols.d.ts +53 -0
- package/dist/api/core/agent/tools/getWorkspaceSymbols.js +97 -0
- package/dist/api/core/agent/tools/grepSearch.d.ts +100 -0
- package/dist/api/core/agent/tools/grepSearch.js +211 -0
- package/dist/api/core/agent/tools/languageModelToolsIntegration.d.ts +13 -0
- package/dist/api/core/agent/tools/languageModelToolsIntegration.js +22 -0
- package/dist/api/core/agent/tools/listDirectory.d.ts +66 -0
- package/dist/api/core/agent/tools/listDirectory.js +161 -0
- package/dist/api/core/agent/tools/mcpTools.d.ts +48 -0
- package/dist/api/core/agent/tools/mcpTools.js +442 -0
- package/dist/api/core/agent/tools/queryKnowledgeGraph.d.ts +120 -0
- package/dist/api/core/agent/tools/queryKnowledgeGraph.js +306 -0
- package/dist/api/core/agent/tools/readFile.d.ts +92 -0
- package/dist/api/core/agent/tools/readFile.js +337 -0
- package/dist/api/core/agent/tools/renameFile.d.ts +49 -0
- package/dist/api/core/agent/tools/renameFile.js +86 -0
- package/dist/api/core/agent/tools/renameSymbol.d.ts +70 -0
- package/dist/api/core/agent/tools/renameSymbol.js +106 -0
- package/dist/api/core/agent/tools/runTerminalCommand.d.ts +72 -0
- package/dist/api/core/agent/tools/runTerminalCommand.js +69 -0
- package/dist/api/core/agent/tools/searchFiles.d.ts +82 -0
- package/dist/api/core/agent/tools/searchFiles.js +280 -0
- package/dist/api/core/agent/tools/terminalAutoApprove.d.ts +3 -0
- package/dist/api/core/agent/tools/terminalAutoApprove.js +676 -0
- package/dist/api/core/agent/tools/treeTraversal.d.ts +60 -0
- package/dist/api/core/agent/tools/treeTraversal.js +217 -0
- package/dist/api/core/agent/tools/webSearch.d.ts +37 -0
- package/dist/api/core/agent/tools/webSearch.js +80 -0
- package/dist/api/core/agent/tools/writeFile.d.ts +59 -0
- package/dist/api/core/agent/tools/writeFile.js +97 -0
- package/dist/api/core/agent/utils/capturedWorkspaceMutationBridge.d.ts +12 -0
- package/dist/api/core/agent/utils/capturedWorkspaceMutationBridge.js +67 -0
- package/dist/api/core/agent/utils/diffUtils.d.ts +14 -0
- package/dist/api/core/agent/utils/diffUtils.js +39 -0
- package/dist/api/core/agent/utils/environmentSnapshot.d.ts +42 -0
- package/dist/api/core/agent/utils/environmentSnapshot.js +213 -0
- package/dist/api/core/agent/utils/errorRecovery.d.ts +49 -0
- package/dist/api/core/agent/utils/errorRecovery.js +229 -0
- package/dist/api/core/agent/utils/multimodalTokenLimiter.d.ts +8 -0
- package/dist/api/core/agent/utils/multimodalTokenLimiter.js +238 -0
- package/dist/api/core/agent/utils/openRouterModelSettings.d.ts +12 -0
- package/dist/api/core/agent/utils/openRouterModelSettings.js +34 -0
- package/dist/api/core/agent/utils/pathRecovery.d.ts +1 -0
- package/dist/api/core/agent/utils/pathRecovery.js +29 -0
- package/dist/api/core/agent/utils/repoMapIndex.d.ts +3 -0
- package/dist/api/core/agent/utils/repoMapIndex.js +197 -0
- package/dist/api/core/agent/utils/skillsDiscovery.d.ts +10 -0
- package/dist/api/core/agent/utils/skillsDiscovery.js +50 -0
- package/dist/api/core/agent/utils/toolCallBudget.d.ts +9 -0
- package/dist/api/core/agent/utils/toolCallBudget.js +55 -0
- package/dist/api/core/agent/utils/toolLifecycle.d.ts +30 -0
- package/dist/api/core/agent/utils/toolLifecycle.js +361 -0
- package/dist/api/core/agent/utils/toolResultSafetyProcessor.d.ts +12 -0
- package/dist/api/core/agent/utils/toolResultSafetyProcessor.js +57 -0
- package/dist/api/core/agent/utils/workspaceMutationBridge.d.ts +13 -0
- package/dist/api/core/agent/utils/workspaceMutationBridge.js +149 -0
- package/dist/api/core/agent/utils/workspacePathGuard.d.ts +7 -0
- package/dist/api/core/agent/utils/workspacePathGuard.js +79 -0
- package/dist/api/core/containers/chat/toolResultSerialization.d.ts +8 -0
- package/dist/api/core/containers/chat/toolResultSerialization.js +71 -0
- package/dist/api/core/library/BrowserManager.d.ts +11 -0
- package/dist/api/core/library/BrowserManager.js +66 -0
- package/dist/api/core/library/desktopWorkspace.d.ts +1 -0
- package/dist/api/core/library/desktopWorkspace.js +3 -0
- package/dist/api/core/library/extensionManager.d.ts +10 -0
- package/dist/api/core/library/extensionManager.js +27 -0
- package/dist/api/core/library/knowledgeGraph.d.ts +268 -0
- package/dist/api/core/library/knowledgeGraph.js +989 -0
- package/dist/api/core/library/languageModelTools.d.ts +141 -0
- package/dist/api/core/library/languageModelTools.js +207 -0
- package/dist/api/core/library/localRuntime.d.ts +23 -0
- package/dist/api/core/library/localRuntime.js +144 -0
- package/dist/api/core/library/lsp/coreLsp.d.ts +367 -0
- package/dist/api/core/library/lsp/coreLsp.js +2076 -0
- package/dist/api/core/library/lsp/protocol.d.ts +25 -0
- package/dist/api/core/library/lsp/protocol.js +1 -0
- package/dist/api/core/library/lsp/serverManager.d.ts +37 -0
- package/dist/api/core/library/lsp/serverManager.js +427 -0
- package/dist/api/core/library/mcpServerProvider.d.ts +69 -0
- package/dist/api/core/library/mcpServerProvider.js +152 -0
- package/dist/api/core/library/mcpSettings.d.ts +20 -0
- package/dist/api/core/library/mcpSettings.js +131 -0
- package/dist/api/core/library/patternMatcher.d.ts +66 -0
- package/dist/api/core/library/patternMatcher.js +284 -0
- package/dist/api/core/library/regexEscape.d.ts +4 -0
- package/dist/api/core/library/regexEscape.js +4 -0
- package/dist/api/core/library/runtimeEventBus.d.ts +27 -0
- package/dist/api/core/library/runtimeEventBus.js +78 -0
- package/dist/api/core/library/safetyMiddleware.d.ts +98 -0
- package/dist/api/core/library/safetyMiddleware.js +215 -0
- package/dist/api/core/library/tauri.d.ts +71 -0
- package/dist/api/core/library/tauri.js +222 -0
- package/dist/api/core/library/tauriImport.d.ts +5 -0
- package/dist/api/core/library/tauriImport.js +7 -0
- package/dist/api/core/library/terminalAutoApproveSettings.d.ts +32 -0
- package/dist/api/core/library/terminalAutoApproveSettings.js +529 -0
- package/dist/api/core/library/workspaceIdentity.d.ts +10 -0
- package/dist/api/core/library/workspaceIdentity.js +49 -0
- package/dist/api/core/library/workspaceSummary.d.ts +19 -0
- package/dist/api/core/library/workspaceSummary.js +35 -0
- package/dist/api/core/skills/agent-customization/SKILL.md +27 -0
- package/dist/api/core/skills/bug-fix/SKILL.md +21 -0
- package/dist/api/core/skills/create-pr/SKILL.md +32 -0
- package/dist/api/core/skills/dev-server/SKILL.md +20 -0
- package/dist/api/core/skills/fix-suggestions/SKILL.md +21 -0
- package/dist/api/core/skills/github-search/SKILL.md +21 -0
- package/dist/api/core/skills/github-summary/SKILL.md +25 -0
- package/dist/api/core/skills/integration-tests/SKILL.md +29 -0
- package/dist/api/core/skills/pr-comments/SKILL.md +23 -0
- package/dist/api/core/skills/project-setup/SKILL.md +20 -0
- package/dist/api/core/skills/search-integration/SKILL.md +19 -0
- package/dist/api/core/skills/search-results/SKILL.md +19 -0
- package/dist/api/core/skills/typescript-upgrade/SKILL.md +21 -0
- package/dist/api/data/runStore.d.ts +46 -0
- package/dist/api/data/runStore.js +244 -0
- package/dist/api/helpers/agentUtils.d.ts +11 -0
- package/dist/api/helpers/agentUtils.js +23 -0
- package/dist/api/helpers/modelTokenLimits.d.ts +2 -0
- package/dist/api/helpers/modelTokenLimits.js +158 -0
- package/dist/api/helpers/observationalMemory.d.ts +10 -0
- package/dist/api/helpers/observationalMemory.js +36 -0
- package/dist/api/helpers/promptBudget.d.ts +30 -0
- package/dist/api/helpers/promptBudget.js +216 -0
- package/dist/api/helpers/resolveImageMessageParts.d.ts +9 -0
- package/dist/api/helpers/resolveImageMessageParts.js +140 -0
- package/dist/api/helpers/slashCommands.d.ts +31 -0
- package/dist/api/helpers/slashCommands.js +129 -0
- package/dist/api/helpers/tokenUsage.d.ts +19 -0
- package/dist/api/helpers/tokenUsage.js +81 -0
- package/dist/api/routes/fileRoutes.d.ts +2 -0
- package/dist/api/routes/fileRoutes.js +108 -0
- package/dist/api/routes/lspDocumentRoutes.d.ts +4 -0
- package/dist/api/routes/lspDocumentRoutes.js +84 -0
- package/dist/api/routes/lspHierarchyRoutes.d.ts +4 -0
- package/dist/api/routes/lspHierarchyRoutes.js +122 -0
- package/dist/api/routes/lspPositionRoutes.d.ts +4 -0
- package/dist/api/routes/lspPositionRoutes.js +263 -0
- package/dist/api/routes/lspQueryRoutes.d.ts +4 -0
- package/dist/api/routes/lspQueryRoutes.js +679 -0
- package/dist/api/routes/lspResolveRoutes.d.ts +4 -0
- package/dist/api/routes/lspResolveRoutes.js +143 -0
- package/dist/api/routes/lspSemanticDocumentRoutes.d.ts +4 -0
- package/dist/api/routes/lspSemanticDocumentRoutes.js +98 -0
- package/dist/api/routes/semanticRoutes.d.ts +2 -0
- package/dist/api/routes/semanticRoutes.js +126 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +160 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +38 -0
- package/package.json +100 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment Snapshot Generator
|
|
3
|
+
* Pre-gathers environment information at conversation start
|
|
4
|
+
* Reduces exploratory turns and provides immediate context
|
|
5
|
+
*/
|
|
6
|
+
type SnapshotPackageInfo = {
|
|
7
|
+
name?: string;
|
|
8
|
+
version?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
scripts: string[];
|
|
11
|
+
dependencies: string[];
|
|
12
|
+
devDependencies: string[];
|
|
13
|
+
};
|
|
14
|
+
type EnvironmentSnapshot = {
|
|
15
|
+
cwd: string;
|
|
16
|
+
fileTree: string;
|
|
17
|
+
readme: string | null;
|
|
18
|
+
packageInfo: SnapshotPackageInfo | null;
|
|
19
|
+
git: {
|
|
20
|
+
branch: string;
|
|
21
|
+
status: string;
|
|
22
|
+
};
|
|
23
|
+
environment: {
|
|
24
|
+
python: string;
|
|
25
|
+
node: string;
|
|
26
|
+
npm: string;
|
|
27
|
+
};
|
|
28
|
+
generatedAt: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Generate comprehensive environment snapshot
|
|
32
|
+
* @param {string} workspacePath - Workspace root path
|
|
33
|
+
* @returns {Promise<object>} Environment snapshot data
|
|
34
|
+
*/
|
|
35
|
+
export declare const getEnvironmentSnapshot: (workspacePath: string) => Promise<EnvironmentSnapshot>;
|
|
36
|
+
/**
|
|
37
|
+
* Format snapshot as markdown for agent consumption
|
|
38
|
+
* @param {object} snapshot - Environment snapshot from getEnvironmentSnapshot
|
|
39
|
+
* @returns {string} Formatted markdown
|
|
40
|
+
*/
|
|
41
|
+
export declare const formatSnapshotAsMarkdown: (snapshot: EnvironmentSnapshot) => string;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment Snapshot Generator
|
|
3
|
+
* Pre-gathers environment information at conversation start
|
|
4
|
+
* Reduces exploratory turns and provides immediate context
|
|
5
|
+
*/
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import { exec } from "child_process";
|
|
9
|
+
import { promisify } from "util";
|
|
10
|
+
const execAsync = promisify(exec);
|
|
11
|
+
/**
|
|
12
|
+
* Read file if it exists, return null otherwise
|
|
13
|
+
* @param {string} filePath - Path to file
|
|
14
|
+
* @returns {Promise<string|null>} File content or null
|
|
15
|
+
*/
|
|
16
|
+
const readFileIfExists = async (filePath) => {
|
|
17
|
+
try {
|
|
18
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
19
|
+
return content;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Generate file tree with depth limit
|
|
27
|
+
* @param {string} dirPath - Directory path
|
|
28
|
+
* @param {object} options - Options {maxDepth, currentDepth}
|
|
29
|
+
* @returns {Promise<string>} File tree string
|
|
30
|
+
*/
|
|
31
|
+
const generateFileTree = async (dirPath, options = {}) => {
|
|
32
|
+
const { maxDepth = 3, currentDepth = 0, ignorePatterns = ["node_modules", ".git", "dist", "build", "coverage"], } = options;
|
|
33
|
+
if (currentDepth >= maxDepth) {
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
38
|
+
let tree = "";
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
// Skip ignored patterns
|
|
41
|
+
if (ignorePatterns.includes(entry.name)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const indent = " ".repeat(currentDepth);
|
|
45
|
+
const prefix = entry.isDirectory() ? "📁 " : "📄 ";
|
|
46
|
+
tree += `${indent}${prefix}${entry.name}\n`;
|
|
47
|
+
if (entry.isDirectory()) {
|
|
48
|
+
const subPath = path.join(dirPath, entry.name);
|
|
49
|
+
const subTree = await generateFileTree(subPath, {
|
|
50
|
+
maxDepth,
|
|
51
|
+
currentDepth: currentDepth + 1,
|
|
52
|
+
ignorePatterns,
|
|
53
|
+
});
|
|
54
|
+
tree += subTree;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return tree;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
return "";
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Run command safely, return output or empty string on error
|
|
65
|
+
* @param {string} command - Command to run
|
|
66
|
+
* @param {object} options - Exec options
|
|
67
|
+
* @returns {Promise<string>} Command output
|
|
68
|
+
*/
|
|
69
|
+
const runCommandSafe = async (command, options = {}) => {
|
|
70
|
+
try {
|
|
71
|
+
const { stdout } = await execAsync(command, {
|
|
72
|
+
timeout: 5000,
|
|
73
|
+
maxBuffer: 1024 * 1024, // 1MB
|
|
74
|
+
...options,
|
|
75
|
+
});
|
|
76
|
+
return String(stdout).trim();
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
return "";
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Generate comprehensive environment snapshot
|
|
84
|
+
* @param {string} workspacePath - Workspace root path
|
|
85
|
+
* @returns {Promise<object>} Environment snapshot data
|
|
86
|
+
*/
|
|
87
|
+
export const getEnvironmentSnapshot = async (workspacePath) => {
|
|
88
|
+
console.log("📸 Generating environment snapshot...");
|
|
89
|
+
const startTime = Date.now();
|
|
90
|
+
// Run operations in parallel where possible
|
|
91
|
+
const [cwd, fileTree, readme, packageJson, gitBranch, gitStatus, pythonVersion, nodeVersion, npmVersion,] = await Promise.all([
|
|
92
|
+
// Current working directory
|
|
93
|
+
Promise.resolve(workspacePath),
|
|
94
|
+
// File tree (limited depth)
|
|
95
|
+
generateFileTree(workspacePath, { maxDepth: 3 }),
|
|
96
|
+
// README
|
|
97
|
+
readFileIfExists(path.join(workspacePath, "README.md")),
|
|
98
|
+
// package.json
|
|
99
|
+
readFileIfExists(path.join(workspacePath, "package.json")),
|
|
100
|
+
// Git info
|
|
101
|
+
runCommandSafe("git branch --show-current", { cwd: workspacePath }),
|
|
102
|
+
runCommandSafe("git status --short", { cwd: workspacePath }),
|
|
103
|
+
// Environment versions
|
|
104
|
+
runCommandSafe("python --version || python3 --version"),
|
|
105
|
+
runCommandSafe("node --version"),
|
|
106
|
+
runCommandSafe("npm --version"),
|
|
107
|
+
]);
|
|
108
|
+
// Parse package.json if available
|
|
109
|
+
let packageInfo = null;
|
|
110
|
+
if (packageJson) {
|
|
111
|
+
try {
|
|
112
|
+
const pkg = JSON.parse(packageJson);
|
|
113
|
+
packageInfo = {
|
|
114
|
+
name: typeof pkg.name === "string" ? pkg.name : undefined,
|
|
115
|
+
version: typeof pkg.version === "string" ? pkg.version : undefined,
|
|
116
|
+
description: typeof pkg.description === "string" ? pkg.description : undefined,
|
|
117
|
+
scripts: Object.keys(pkg.scripts || {}),
|
|
118
|
+
dependencies: Object.keys(pkg.dependencies || {}),
|
|
119
|
+
devDependencies: Object.keys(pkg.devDependencies || {}),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
packageInfo = null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const elapsed = Date.now() - startTime;
|
|
127
|
+
console.log(`✅ Environment snapshot generated in ${elapsed}ms`);
|
|
128
|
+
return {
|
|
129
|
+
cwd,
|
|
130
|
+
fileTree,
|
|
131
|
+
readme: readme ? readme.substring(0, 2000) : null, // Limit README size
|
|
132
|
+
packageInfo,
|
|
133
|
+
git: {
|
|
134
|
+
branch: gitBranch || "unknown",
|
|
135
|
+
status: gitStatus || "",
|
|
136
|
+
},
|
|
137
|
+
environment: {
|
|
138
|
+
python: pythonVersion || "not installed",
|
|
139
|
+
node: nodeVersion || "not installed",
|
|
140
|
+
npm: npmVersion || "not installed",
|
|
141
|
+
},
|
|
142
|
+
generatedAt: new Date().toISOString(),
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Format snapshot as markdown for agent consumption
|
|
147
|
+
* @param {object} snapshot - Environment snapshot from getEnvironmentSnapshot
|
|
148
|
+
* @returns {string} Formatted markdown
|
|
149
|
+
*/
|
|
150
|
+
export const formatSnapshotAsMarkdown = (snapshot) => {
|
|
151
|
+
let markdown = `## Initial Environment State
|
|
152
|
+
|
|
153
|
+
Generated at: ${snapshot.generatedAt}
|
|
154
|
+
|
|
155
|
+
### Working Directory
|
|
156
|
+
\`\`\`
|
|
157
|
+
${snapshot.cwd}
|
|
158
|
+
\`\`\`
|
|
159
|
+
|
|
160
|
+
`;
|
|
161
|
+
// File tree
|
|
162
|
+
if (snapshot.fileTree) {
|
|
163
|
+
markdown += `### File Structure (depth 3)
|
|
164
|
+
\`\`\`
|
|
165
|
+
${snapshot.fileTree}
|
|
166
|
+
\`\`\`
|
|
167
|
+
|
|
168
|
+
`;
|
|
169
|
+
}
|
|
170
|
+
// Package info
|
|
171
|
+
if (snapshot.packageInfo) {
|
|
172
|
+
markdown += `### Project: ${snapshot.packageInfo.name}
|
|
173
|
+
- **Version:** ${snapshot.packageInfo.version}
|
|
174
|
+
${snapshot.packageInfo.description
|
|
175
|
+
? `- **Description:** ${snapshot.packageInfo.description}`
|
|
176
|
+
: ""}
|
|
177
|
+
|
|
178
|
+
**Available Scripts:**
|
|
179
|
+
${snapshot.packageInfo.scripts.map((s) => `- \`npm run ${s}\``).join("\n")}
|
|
180
|
+
|
|
181
|
+
**Dependencies:** ${snapshot.packageInfo.dependencies.length} packages
|
|
182
|
+
**Dev Dependencies:** ${snapshot.packageInfo.devDependencies.length} packages
|
|
183
|
+
|
|
184
|
+
`;
|
|
185
|
+
}
|
|
186
|
+
// Git info
|
|
187
|
+
if (snapshot.git.branch !== "unknown") {
|
|
188
|
+
markdown += `### Git
|
|
189
|
+
- **Branch:** ${snapshot.git.branch}
|
|
190
|
+
${snapshot.git.status
|
|
191
|
+
? `- **Status:**\n\`\`\`\n${snapshot.git.status}\n\`\`\`\n`
|
|
192
|
+
: ""}
|
|
193
|
+
`;
|
|
194
|
+
}
|
|
195
|
+
// Environment
|
|
196
|
+
markdown += `### Environment
|
|
197
|
+
- **Node:** ${snapshot.environment.node}
|
|
198
|
+
- **NPM:** ${snapshot.environment.npm}
|
|
199
|
+
- **Python:** ${snapshot.environment.python}
|
|
200
|
+
|
|
201
|
+
`;
|
|
202
|
+
// README excerpt
|
|
203
|
+
if (snapshot.readme) {
|
|
204
|
+
markdown += `### README.md (excerpt)
|
|
205
|
+
\`\`\`
|
|
206
|
+
${snapshot.readme}
|
|
207
|
+
${snapshot.readme.length >= 2000 ? "\n... (truncated)" : ""}
|
|
208
|
+
\`\`\`
|
|
209
|
+
|
|
210
|
+
`;
|
|
211
|
+
}
|
|
212
|
+
return markdown;
|
|
213
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Recovery Utilities
|
|
3
|
+
* Automatic retry logic and error-specific recovery strategies
|
|
4
|
+
*/
|
|
5
|
+
type ToolParams = Record<string, unknown>;
|
|
6
|
+
type ToolResult = Record<string, unknown> & {
|
|
7
|
+
success?: boolean;
|
|
8
|
+
error?: string;
|
|
9
|
+
};
|
|
10
|
+
type ToolLike = {
|
|
11
|
+
name?: string;
|
|
12
|
+
execute: (params: ToolParams) => Promise<ToolResult>;
|
|
13
|
+
};
|
|
14
|
+
type ToolLikeGeneric<TParams extends ToolParams, TResult extends ToolResult> = {
|
|
15
|
+
name?: string;
|
|
16
|
+
execute: (params: TParams) => Promise<TResult>;
|
|
17
|
+
};
|
|
18
|
+
type RecoveryOptions = {
|
|
19
|
+
maxRetries?: number;
|
|
20
|
+
searchFiles?: ((pattern: string) => Promise<string[]>) | null;
|
|
21
|
+
workspacePath?: string;
|
|
22
|
+
timeout?: number;
|
|
23
|
+
};
|
|
24
|
+
type RecoveryMiddlewareOptions = {
|
|
25
|
+
maxRetries?: number;
|
|
26
|
+
onError?: ((error: Error, attempt: number, params: ToolParams) => Promise<boolean> | boolean) | null;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Execute tool with automatic retry and error recovery
|
|
30
|
+
* @param {object} tool - Tool object with execute method
|
|
31
|
+
* @param {object} params - Tool parameters
|
|
32
|
+
* @param {object} options - Options {maxRetries, searchFiles}
|
|
33
|
+
* @returns {Promise<any>} Tool result
|
|
34
|
+
*/
|
|
35
|
+
export declare const executeToolWithRecovery: <TParams extends ToolParams, TResult extends ToolResult>(tool: ToolLikeGeneric<TParams, TResult>, params: TParams, options?: RecoveryOptions) => Promise<TResult | ToolResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Wrap multiple tools with recovery
|
|
38
|
+
* @param {object[]} tools - Array of tool objects
|
|
39
|
+
* @returns {object[]} Tools with recovery wrappers
|
|
40
|
+
*/
|
|
41
|
+
export declare const wrapToolsWithRecovery: (tools: ToolLike[]) => ToolLike[];
|
|
42
|
+
/**
|
|
43
|
+
* Create error recovery middleware for tool execution
|
|
44
|
+
* @param {Function} executeFunc - Original execute function
|
|
45
|
+
* @param {object} options - Recovery options
|
|
46
|
+
* @returns {Function} Wrapped execute function
|
|
47
|
+
*/
|
|
48
|
+
export declare const createRecoveryMiddleware: (executeFunc: (params: ToolParams) => Promise<ToolResult>, options?: RecoveryMiddlewareOptions) => (params: ToolParams) => Promise<ToolResult>;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Recovery Utilities
|
|
3
|
+
* Automatic retry logic and error-specific recovery strategies
|
|
4
|
+
*/
|
|
5
|
+
import path from "path";
|
|
6
|
+
const isNonRetryableSecurityError = (message) => {
|
|
7
|
+
const normalized = message.toLowerCase();
|
|
8
|
+
return (normalized.includes("security error")
|
|
9
|
+
|| normalized.includes("outside workspace root")
|
|
10
|
+
|| normalized.includes("outside workspace boundary")
|
|
11
|
+
|| normalized.includes("access denied"));
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Execute tool with automatic retry and error recovery
|
|
15
|
+
* @param {object} tool - Tool object with execute method
|
|
16
|
+
* @param {object} params - Tool parameters
|
|
17
|
+
* @param {object} options - Options {maxRetries, searchFiles}
|
|
18
|
+
* @returns {Promise<any>} Tool result
|
|
19
|
+
*/
|
|
20
|
+
export const executeToolWithRecovery = async (tool, params, options = {}) => {
|
|
21
|
+
const { maxRetries = 2, searchFiles = null } = options;
|
|
22
|
+
let lastError = null;
|
|
23
|
+
const toolLabel = tool.name || "unnamed_tool";
|
|
24
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
25
|
+
try {
|
|
26
|
+
// Execute the tool
|
|
27
|
+
const result = await tool.execute(params);
|
|
28
|
+
// If successful and this was a retry, log the recovery
|
|
29
|
+
if (attempt > 0 && result && !result.error) {
|
|
30
|
+
console.log(`✅ Tool ${toolLabel} succeeded after ${attempt} ${attempt === 1 ? "retry" : "retries"}`);
|
|
31
|
+
}
|
|
32
|
+
// If successful, reset error tracking
|
|
33
|
+
if (result && !result.error) {
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
// If result has error but not an exception, treat as soft error
|
|
37
|
+
if (result && result.error) {
|
|
38
|
+
lastError = new Error(String(result.error));
|
|
39
|
+
throw lastError;
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
const err = error;
|
|
45
|
+
lastError = err;
|
|
46
|
+
console.warn(`⚠️ Tool ${toolLabel} failed (attempt ${attempt + 1}/${maxRetries + 1}):`, err.message);
|
|
47
|
+
if (isNonRetryableSecurityError(err.message)) {
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
// Don't retry on last attempt
|
|
51
|
+
if (attempt === maxRetries) {
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
// Attempt to fix common issues
|
|
55
|
+
const recoveryResult = await attemptRecovery(tool, params, err, {
|
|
56
|
+
searchFiles,
|
|
57
|
+
});
|
|
58
|
+
if (recoveryResult.recovered) {
|
|
59
|
+
console.log(`✅ Recovered from error: ${recoveryResult.strategy}`);
|
|
60
|
+
// Update params with recovered values
|
|
61
|
+
Object.assign(params, recoveryResult.params);
|
|
62
|
+
continue; // Retry with updated params
|
|
63
|
+
}
|
|
64
|
+
// If recovery failed, wait before retry
|
|
65
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * (attempt + 1)));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// All retries failed, return error response
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: lastError?.message || "Unknown error",
|
|
72
|
+
suggestion: getErrorSuggestion(lastError || new Error("Unknown error"), tool.name || "unknown"),
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Attempt to recover from common errors
|
|
77
|
+
* @param {object} tool - Tool object
|
|
78
|
+
* @param {object} params - Original params
|
|
79
|
+
* @param {Error} error - Error that occurred
|
|
80
|
+
* @param {object} context - Additional context {searchFiles}
|
|
81
|
+
* @returns {Promise<object>} {recovered, strategy, params}
|
|
82
|
+
*/
|
|
83
|
+
const attemptRecovery = async (tool, params, error, context = {}) => {
|
|
84
|
+
const { searchFiles } = context;
|
|
85
|
+
void tool;
|
|
86
|
+
// File not found - try searching for it
|
|
87
|
+
if (error.code === "ENOENT" || error.message.includes("no such file")) {
|
|
88
|
+
console.log("🔍 File not found, attempting search...");
|
|
89
|
+
if (searchFiles && typeof params.filePath === "string") {
|
|
90
|
+
try {
|
|
91
|
+
const fileName = path.basename(params.filePath);
|
|
92
|
+
const searchResult = await searchFiles(`**/*${fileName}*`);
|
|
93
|
+
if (searchResult && searchResult.length > 0) {
|
|
94
|
+
console.log(`✅ Found file at: ${searchResult[0]}`);
|
|
95
|
+
return {
|
|
96
|
+
recovered: true,
|
|
97
|
+
strategy: "file_search",
|
|
98
|
+
params: { ...params, filePath: searchResult[0] },
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (searchError) {
|
|
103
|
+
const err = searchError;
|
|
104
|
+
console.warn("Search failed:", err.message);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Permission denied
|
|
109
|
+
if (error.message.includes("permission denied") || error.code === "EACCES") {
|
|
110
|
+
return {
|
|
111
|
+
recovered: false,
|
|
112
|
+
strategy: "permission_error",
|
|
113
|
+
suggestion: "This operation requires elevated permissions. Please check file permissions or run with appropriate access.",
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// Path traversal / invalid path
|
|
117
|
+
if (error.message.includes("path") && error.message.includes("invalid")) {
|
|
118
|
+
console.log("🔍 Invalid path, attempting normalization...");
|
|
119
|
+
if (typeof params.filePath === "string") {
|
|
120
|
+
const normalized = path.normalize(params.filePath);
|
|
121
|
+
if (normalized !== params.filePath) {
|
|
122
|
+
return {
|
|
123
|
+
recovered: true,
|
|
124
|
+
strategy: "path_normalization",
|
|
125
|
+
params: { ...params, filePath: normalized },
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Timeout error
|
|
131
|
+
if (error.message.includes("timeout") || error.code === "ETIMEDOUT") {
|
|
132
|
+
console.log("⏱️ Timeout detected, will retry with longer timeout...");
|
|
133
|
+
return {
|
|
134
|
+
recovered: true,
|
|
135
|
+
strategy: "increase_timeout",
|
|
136
|
+
params: {
|
|
137
|
+
...params,
|
|
138
|
+
timeout: (typeof params.timeout === "number" ? params.timeout : 5000) * 2,
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// No recovery strategy found
|
|
143
|
+
return { recovered: false };
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Get helpful error suggestion based on error and tool
|
|
147
|
+
* @param {Error} error - The error
|
|
148
|
+
* @param {string} toolName - Tool name
|
|
149
|
+
* @returns {string} Suggestion text
|
|
150
|
+
*/
|
|
151
|
+
const getErrorSuggestion = (error, toolName) => {
|
|
152
|
+
const message = error.message.toLowerCase();
|
|
153
|
+
void toolName;
|
|
154
|
+
if (message.includes("not found") || message.includes("enoent")) {
|
|
155
|
+
return "File or directory not found. Try using searchFiles to locate the correct path, or verify the path exists in the workspace.";
|
|
156
|
+
}
|
|
157
|
+
if (message.includes("permission")) {
|
|
158
|
+
return "Permission denied. Check file permissions or try a different approach that doesn't require elevated access.";
|
|
159
|
+
}
|
|
160
|
+
if (message.includes("timeout")) {
|
|
161
|
+
return "Operation timed out. The file or operation may be too large. Try processing smaller chunks or using a different approach.";
|
|
162
|
+
}
|
|
163
|
+
if (message.includes("syntax") || message.includes("parse")) {
|
|
164
|
+
return "Syntax or parsing error. Verify the content format and try again with corrected syntax.";
|
|
165
|
+
}
|
|
166
|
+
if (message.includes("network") || message.includes("connection")) {
|
|
167
|
+
return "Network or connection error. Check internet connectivity and try again.";
|
|
168
|
+
}
|
|
169
|
+
// Generic suggestion
|
|
170
|
+
return "Operation failed. Review the error message and try an alternative approach or break the task into smaller steps.";
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Wrap multiple tools with recovery
|
|
174
|
+
* @param {object[]} tools - Array of tool objects
|
|
175
|
+
* @returns {object[]} Tools with recovery wrappers
|
|
176
|
+
*/
|
|
177
|
+
export const wrapToolsWithRecovery = (tools) => {
|
|
178
|
+
return tools.map((tool) => ({
|
|
179
|
+
...tool,
|
|
180
|
+
execute: async (params) => {
|
|
181
|
+
const searchTool = tools.find((t) => t.name === "searchFiles");
|
|
182
|
+
return executeToolWithRecovery(tool, params, {
|
|
183
|
+
// Pass searchFiles tool if available for file recovery
|
|
184
|
+
searchFiles: searchTool
|
|
185
|
+
? async (pattern) => {
|
|
186
|
+
const result = await searchTool.execute({ pattern });
|
|
187
|
+
const files = result.files;
|
|
188
|
+
return Array.isArray(files)
|
|
189
|
+
? files.filter((file) => typeof file === "string")
|
|
190
|
+
: [];
|
|
191
|
+
}
|
|
192
|
+
: null,
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
}));
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Create error recovery middleware for tool execution
|
|
199
|
+
* @param {Function} executeFunc - Original execute function
|
|
200
|
+
* @param {object} options - Recovery options
|
|
201
|
+
* @returns {Function} Wrapped execute function
|
|
202
|
+
*/
|
|
203
|
+
export const createRecoveryMiddleware = (
|
|
204
|
+
// eslint-disable-next-line no-unused-vars
|
|
205
|
+
executeFunc, options = {}) => {
|
|
206
|
+
return async (params) => {
|
|
207
|
+
const { maxRetries = 2, onError = null } = options;
|
|
208
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
209
|
+
try {
|
|
210
|
+
return await executeFunc(params);
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
const err = error;
|
|
214
|
+
if (onError) {
|
|
215
|
+
const shouldRetry = await onError(err, attempt, params);
|
|
216
|
+
if (!shouldRetry || attempt === maxRetries) {
|
|
217
|
+
throw err;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else if (attempt === maxRetries) {
|
|
221
|
+
throw err;
|
|
222
|
+
}
|
|
223
|
+
// Wait before retry
|
|
224
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * (attempt + 1)));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
throw new Error("Recovery middleware exhausted retries without result");
|
|
228
|
+
};
|
|
229
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TokenLimiterProcessor } from "@mastra/core/processors";
|
|
2
|
+
import type { ProcessInputStepArgs } from "@mastra/core/processors";
|
|
3
|
+
export declare const redactMultimodalPayloads: (messages: unknown[]) => (() => void);
|
|
4
|
+
export declare class MultimodalTokenLimiterProcessor extends TokenLimiterProcessor {
|
|
5
|
+
private readonly supportsVision;
|
|
6
|
+
constructor(limit: number, supportsVision?: boolean);
|
|
7
|
+
processInputStep(args: ProcessInputStepArgs): Promise<void>;
|
|
8
|
+
}
|