@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.
Files changed (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +690 -0
  3. package/dist/api/acp/acpServer.d.ts +23 -0
  4. package/dist/api/acp/acpServer.js +814 -0
  5. package/dist/api/acp/index.d.ts +2 -0
  6. package/dist/api/acp/index.js +2 -0
  7. package/dist/api/acp/irisClient.d.ts +58 -0
  8. package/dist/api/acp/irisClient.js +214 -0
  9. package/dist/api/agent.d.ts +14 -0
  10. package/dist/api/agent.js +4171 -0
  11. package/dist/api/backendService.d.ts +4 -0
  12. package/dist/api/backendService.js +14 -0
  13. package/dist/api/core/agent/host/AgentContract.d.ts +82 -0
  14. package/dist/api/core/agent/host/AgentContract.js +1 -0
  15. package/dist/api/core/agent/host/AgentRegistry.d.ts +24 -0
  16. package/dist/api/core/agent/host/AgentRegistry.js +125 -0
  17. package/dist/api/core/agent/host/defaultRegistry.d.ts +15 -0
  18. package/dist/api/core/agent/host/defaultRegistry.js +46 -0
  19. package/dist/api/core/agent/host/externalAgentLifecycle.d.ts +65 -0
  20. package/dist/api/core/agent/host/externalAgentLifecycle.js +117 -0
  21. package/dist/api/core/agent/host/hostSessionManager.d.ts +111 -0
  22. package/dist/api/core/agent/host/hostSessionManager.js +352 -0
  23. package/dist/api/core/agent/host/index.d.ts +5 -0
  24. package/dist/api/core/agent/host/index.js +5 -0
  25. package/dist/api/core/agent/index.d.ts +87 -0
  26. package/dist/api/core/agent/index.js +1024 -0
  27. package/dist/api/core/agent/publicContracts.d.ts +35 -0
  28. package/dist/api/core/agent/publicContracts.js +103 -0
  29. package/dist/api/core/agent/tools/applyDiff.d.ts +51 -0
  30. package/dist/api/core/agent/tools/applyDiff.js +131 -0
  31. package/dist/api/core/agent/tools/backgroundTasks.d.ts +240 -0
  32. package/dist/api/core/agent/tools/backgroundTasks.js +313 -0
  33. package/dist/api/core/agent/tools/createDirectory.d.ts +43 -0
  34. package/dist/api/core/agent/tools/createDirectory.js +77 -0
  35. package/dist/api/core/agent/tools/deleteFile.d.ts +37 -0
  36. package/dist/api/core/agent/tools/deleteFile.js +66 -0
  37. package/dist/api/core/agent/tools/editFile.d.ts +73 -0
  38. package/dist/api/core/agent/tools/editFile.js +173 -0
  39. package/dist/api/core/agent/tools/executeCommand.d.ts +59 -0
  40. package/dist/api/core/agent/tools/executeCommand.js +250 -0
  41. package/dist/api/core/agent/tools/fileContent.d.ts +54 -0
  42. package/dist/api/core/agent/tools/fileContent.js +227 -0
  43. package/dist/api/core/agent/tools/findDefinition.d.ts +72 -0
  44. package/dist/api/core/agent/tools/findDefinition.js +109 -0
  45. package/dist/api/core/agent/tools/findReferences.d.ts +86 -0
  46. package/dist/api/core/agent/tools/findReferences.js +135 -0
  47. package/dist/api/core/agent/tools/formatDocument.d.ts +67 -0
  48. package/dist/api/core/agent/tools/formatDocument.js +90 -0
  49. package/dist/api/core/agent/tools/getCodeActions.d.ts +77 -0
  50. package/dist/api/core/agent/tools/getCodeActions.js +97 -0
  51. package/dist/api/core/agent/tools/getCodeCompletion.d.ts +77 -0
  52. package/dist/api/core/agent/tools/getCodeCompletion.js +174 -0
  53. package/dist/api/core/agent/tools/getCodeContext.d.ts +14 -0
  54. package/dist/api/core/agent/tools/getCodeContext.js +282 -0
  55. package/dist/api/core/agent/tools/getSignatureHelp.d.ts +61 -0
  56. package/dist/api/core/agent/tools/getSignatureHelp.js +85 -0
  57. package/dist/api/core/agent/tools/getSymbols.d.ts +50 -0
  58. package/dist/api/core/agent/tools/getSymbols.js +164 -0
  59. package/dist/api/core/agent/tools/getSymbolsLSP.d.ts +58 -0
  60. package/dist/api/core/agent/tools/getSymbolsLSP.js +147 -0
  61. package/dist/api/core/agent/tools/getTypeInfo.d.ts +70 -0
  62. package/dist/api/core/agent/tools/getTypeInfo.js +84 -0
  63. package/dist/api/core/agent/tools/getWorkspaceInfo.d.ts +80 -0
  64. package/dist/api/core/agent/tools/getWorkspaceInfo.js +281 -0
  65. package/dist/api/core/agent/tools/getWorkspaceSymbols.d.ts +53 -0
  66. package/dist/api/core/agent/tools/getWorkspaceSymbols.js +97 -0
  67. package/dist/api/core/agent/tools/grepSearch.d.ts +100 -0
  68. package/dist/api/core/agent/tools/grepSearch.js +211 -0
  69. package/dist/api/core/agent/tools/languageModelToolsIntegration.d.ts +13 -0
  70. package/dist/api/core/agent/tools/languageModelToolsIntegration.js +22 -0
  71. package/dist/api/core/agent/tools/listDirectory.d.ts +66 -0
  72. package/dist/api/core/agent/tools/listDirectory.js +161 -0
  73. package/dist/api/core/agent/tools/mcpTools.d.ts +48 -0
  74. package/dist/api/core/agent/tools/mcpTools.js +442 -0
  75. package/dist/api/core/agent/tools/queryKnowledgeGraph.d.ts +120 -0
  76. package/dist/api/core/agent/tools/queryKnowledgeGraph.js +306 -0
  77. package/dist/api/core/agent/tools/readFile.d.ts +92 -0
  78. package/dist/api/core/agent/tools/readFile.js +337 -0
  79. package/dist/api/core/agent/tools/renameFile.d.ts +49 -0
  80. package/dist/api/core/agent/tools/renameFile.js +86 -0
  81. package/dist/api/core/agent/tools/renameSymbol.d.ts +70 -0
  82. package/dist/api/core/agent/tools/renameSymbol.js +106 -0
  83. package/dist/api/core/agent/tools/runTerminalCommand.d.ts +72 -0
  84. package/dist/api/core/agent/tools/runTerminalCommand.js +69 -0
  85. package/dist/api/core/agent/tools/searchFiles.d.ts +82 -0
  86. package/dist/api/core/agent/tools/searchFiles.js +280 -0
  87. package/dist/api/core/agent/tools/terminalAutoApprove.d.ts +3 -0
  88. package/dist/api/core/agent/tools/terminalAutoApprove.js +676 -0
  89. package/dist/api/core/agent/tools/treeTraversal.d.ts +60 -0
  90. package/dist/api/core/agent/tools/treeTraversal.js +217 -0
  91. package/dist/api/core/agent/tools/webSearch.d.ts +37 -0
  92. package/dist/api/core/agent/tools/webSearch.js +80 -0
  93. package/dist/api/core/agent/tools/writeFile.d.ts +59 -0
  94. package/dist/api/core/agent/tools/writeFile.js +97 -0
  95. package/dist/api/core/agent/utils/capturedWorkspaceMutationBridge.d.ts +12 -0
  96. package/dist/api/core/agent/utils/capturedWorkspaceMutationBridge.js +67 -0
  97. package/dist/api/core/agent/utils/diffUtils.d.ts +14 -0
  98. package/dist/api/core/agent/utils/diffUtils.js +39 -0
  99. package/dist/api/core/agent/utils/environmentSnapshot.d.ts +42 -0
  100. package/dist/api/core/agent/utils/environmentSnapshot.js +213 -0
  101. package/dist/api/core/agent/utils/errorRecovery.d.ts +49 -0
  102. package/dist/api/core/agent/utils/errorRecovery.js +229 -0
  103. package/dist/api/core/agent/utils/multimodalTokenLimiter.d.ts +8 -0
  104. package/dist/api/core/agent/utils/multimodalTokenLimiter.js +238 -0
  105. package/dist/api/core/agent/utils/openRouterModelSettings.d.ts +12 -0
  106. package/dist/api/core/agent/utils/openRouterModelSettings.js +34 -0
  107. package/dist/api/core/agent/utils/pathRecovery.d.ts +1 -0
  108. package/dist/api/core/agent/utils/pathRecovery.js +29 -0
  109. package/dist/api/core/agent/utils/repoMapIndex.d.ts +3 -0
  110. package/dist/api/core/agent/utils/repoMapIndex.js +197 -0
  111. package/dist/api/core/agent/utils/skillsDiscovery.d.ts +10 -0
  112. package/dist/api/core/agent/utils/skillsDiscovery.js +50 -0
  113. package/dist/api/core/agent/utils/toolCallBudget.d.ts +9 -0
  114. package/dist/api/core/agent/utils/toolCallBudget.js +55 -0
  115. package/dist/api/core/agent/utils/toolLifecycle.d.ts +30 -0
  116. package/dist/api/core/agent/utils/toolLifecycle.js +361 -0
  117. package/dist/api/core/agent/utils/toolResultSafetyProcessor.d.ts +12 -0
  118. package/dist/api/core/agent/utils/toolResultSafetyProcessor.js +57 -0
  119. package/dist/api/core/agent/utils/workspaceMutationBridge.d.ts +13 -0
  120. package/dist/api/core/agent/utils/workspaceMutationBridge.js +149 -0
  121. package/dist/api/core/agent/utils/workspacePathGuard.d.ts +7 -0
  122. package/dist/api/core/agent/utils/workspacePathGuard.js +79 -0
  123. package/dist/api/core/containers/chat/toolResultSerialization.d.ts +8 -0
  124. package/dist/api/core/containers/chat/toolResultSerialization.js +71 -0
  125. package/dist/api/core/library/BrowserManager.d.ts +11 -0
  126. package/dist/api/core/library/BrowserManager.js +66 -0
  127. package/dist/api/core/library/desktopWorkspace.d.ts +1 -0
  128. package/dist/api/core/library/desktopWorkspace.js +3 -0
  129. package/dist/api/core/library/extensionManager.d.ts +10 -0
  130. package/dist/api/core/library/extensionManager.js +27 -0
  131. package/dist/api/core/library/knowledgeGraph.d.ts +268 -0
  132. package/dist/api/core/library/knowledgeGraph.js +989 -0
  133. package/dist/api/core/library/languageModelTools.d.ts +141 -0
  134. package/dist/api/core/library/languageModelTools.js +207 -0
  135. package/dist/api/core/library/localRuntime.d.ts +23 -0
  136. package/dist/api/core/library/localRuntime.js +144 -0
  137. package/dist/api/core/library/lsp/coreLsp.d.ts +367 -0
  138. package/dist/api/core/library/lsp/coreLsp.js +2076 -0
  139. package/dist/api/core/library/lsp/protocol.d.ts +25 -0
  140. package/dist/api/core/library/lsp/protocol.js +1 -0
  141. package/dist/api/core/library/lsp/serverManager.d.ts +37 -0
  142. package/dist/api/core/library/lsp/serverManager.js +427 -0
  143. package/dist/api/core/library/mcpServerProvider.d.ts +69 -0
  144. package/dist/api/core/library/mcpServerProvider.js +152 -0
  145. package/dist/api/core/library/mcpSettings.d.ts +20 -0
  146. package/dist/api/core/library/mcpSettings.js +131 -0
  147. package/dist/api/core/library/patternMatcher.d.ts +66 -0
  148. package/dist/api/core/library/patternMatcher.js +284 -0
  149. package/dist/api/core/library/regexEscape.d.ts +4 -0
  150. package/dist/api/core/library/regexEscape.js +4 -0
  151. package/dist/api/core/library/runtimeEventBus.d.ts +27 -0
  152. package/dist/api/core/library/runtimeEventBus.js +78 -0
  153. package/dist/api/core/library/safetyMiddleware.d.ts +98 -0
  154. package/dist/api/core/library/safetyMiddleware.js +215 -0
  155. package/dist/api/core/library/tauri.d.ts +71 -0
  156. package/dist/api/core/library/tauri.js +222 -0
  157. package/dist/api/core/library/tauriImport.d.ts +5 -0
  158. package/dist/api/core/library/tauriImport.js +7 -0
  159. package/dist/api/core/library/terminalAutoApproveSettings.d.ts +32 -0
  160. package/dist/api/core/library/terminalAutoApproveSettings.js +529 -0
  161. package/dist/api/core/library/workspaceIdentity.d.ts +10 -0
  162. package/dist/api/core/library/workspaceIdentity.js +49 -0
  163. package/dist/api/core/library/workspaceSummary.d.ts +19 -0
  164. package/dist/api/core/library/workspaceSummary.js +35 -0
  165. package/dist/api/core/skills/agent-customization/SKILL.md +27 -0
  166. package/dist/api/core/skills/bug-fix/SKILL.md +21 -0
  167. package/dist/api/core/skills/create-pr/SKILL.md +32 -0
  168. package/dist/api/core/skills/dev-server/SKILL.md +20 -0
  169. package/dist/api/core/skills/fix-suggestions/SKILL.md +21 -0
  170. package/dist/api/core/skills/github-search/SKILL.md +21 -0
  171. package/dist/api/core/skills/github-summary/SKILL.md +25 -0
  172. package/dist/api/core/skills/integration-tests/SKILL.md +29 -0
  173. package/dist/api/core/skills/pr-comments/SKILL.md +23 -0
  174. package/dist/api/core/skills/project-setup/SKILL.md +20 -0
  175. package/dist/api/core/skills/search-integration/SKILL.md +19 -0
  176. package/dist/api/core/skills/search-results/SKILL.md +19 -0
  177. package/dist/api/core/skills/typescript-upgrade/SKILL.md +21 -0
  178. package/dist/api/data/runStore.d.ts +46 -0
  179. package/dist/api/data/runStore.js +244 -0
  180. package/dist/api/helpers/agentUtils.d.ts +11 -0
  181. package/dist/api/helpers/agentUtils.js +23 -0
  182. package/dist/api/helpers/modelTokenLimits.d.ts +2 -0
  183. package/dist/api/helpers/modelTokenLimits.js +158 -0
  184. package/dist/api/helpers/observationalMemory.d.ts +10 -0
  185. package/dist/api/helpers/observationalMemory.js +36 -0
  186. package/dist/api/helpers/promptBudget.d.ts +30 -0
  187. package/dist/api/helpers/promptBudget.js +216 -0
  188. package/dist/api/helpers/resolveImageMessageParts.d.ts +9 -0
  189. package/dist/api/helpers/resolveImageMessageParts.js +140 -0
  190. package/dist/api/helpers/slashCommands.d.ts +31 -0
  191. package/dist/api/helpers/slashCommands.js +129 -0
  192. package/dist/api/helpers/tokenUsage.d.ts +19 -0
  193. package/dist/api/helpers/tokenUsage.js +81 -0
  194. package/dist/api/routes/fileRoutes.d.ts +2 -0
  195. package/dist/api/routes/fileRoutes.js +108 -0
  196. package/dist/api/routes/lspDocumentRoutes.d.ts +4 -0
  197. package/dist/api/routes/lspDocumentRoutes.js +84 -0
  198. package/dist/api/routes/lspHierarchyRoutes.d.ts +4 -0
  199. package/dist/api/routes/lspHierarchyRoutes.js +122 -0
  200. package/dist/api/routes/lspPositionRoutes.d.ts +4 -0
  201. package/dist/api/routes/lspPositionRoutes.js +263 -0
  202. package/dist/api/routes/lspQueryRoutes.d.ts +4 -0
  203. package/dist/api/routes/lspQueryRoutes.js +679 -0
  204. package/dist/api/routes/lspResolveRoutes.d.ts +4 -0
  205. package/dist/api/routes/lspResolveRoutes.js +143 -0
  206. package/dist/api/routes/lspSemanticDocumentRoutes.d.ts +4 -0
  207. package/dist/api/routes/lspSemanticDocumentRoutes.js +98 -0
  208. package/dist/api/routes/semanticRoutes.d.ts +2 -0
  209. package/dist/api/routes/semanticRoutes.js +126 -0
  210. package/dist/cli.d.ts +8 -0
  211. package/dist/cli.js +160 -0
  212. package/dist/index.d.ts +1 -0
  213. package/dist/index.js +1 -0
  214. package/dist/server.d.ts +2 -0
  215. package/dist/server.js +38 -0
  216. 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
+ }