@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,60 @@
1
+ /**
2
+ * Tree Traversal Utilities for Directory Operations
3
+ * Based on standard tree traversal algorithms
4
+ */
5
+ export type TraversableNode<T extends TraversableNode<T> = TraversableNode<any>> = {
6
+ children?: T[];
7
+ };
8
+ export type TraversalType = "bfs" | "pre" | "post";
9
+ /**
10
+ * Generator-based Pre-Order traversal (DFS)
11
+ * Useful for processing directories before their contents
12
+ * Order: current -> left -> right (parent -> children)
13
+ */
14
+ export declare function walkPreOrder<T extends TraversableNode<T>>(node: T | null | undefined): Generator<T, void, undefined>;
15
+ /**
16
+ * Generator-based Post-Order traversal (DFS)
17
+ * Useful for processing directory contents before the directory itself
18
+ * Order: left -> right -> current (children -> parent)
19
+ * Good for operations like delete (delete files before directory)
20
+ */
21
+ export declare function walkPostOrder<T extends TraversableNode<T>>(node: T | null | undefined): Generator<T, void, undefined>;
22
+ /**
23
+ * Generator-based Breadth-First Search (BFS)
24
+ * Processes directories level by level
25
+ * Good for finding files at specific depth or displaying hierarchy
26
+ */
27
+ export declare function walkBFS<T extends TraversableNode<T>>(node: T | null | undefined): Generator<T, void, undefined>;
28
+ /**
29
+ * BFS with level information
30
+ * Returns [node, level] tuples
31
+ */
32
+ export declare function walkBFSWithLevel<T extends TraversableNode<T>>(node: T | null | undefined): Generator<[T, number], void, undefined>;
33
+ /**
34
+ * Get all nodes at a specific level
35
+ */
36
+ export declare function getNodesAtLevel<T extends TraversableNode<T>>(root: T | null | undefined, targetLevel: number): T[];
37
+ /**
38
+ * Find node by predicate using BFS (finds closest match)
39
+ */
40
+ export declare function findNode<T extends TraversableNode<T>>(root: T | null | undefined, predicate: (node: T) => boolean): T | null;
41
+ /**
42
+ * Find all nodes matching predicate
43
+ */
44
+ export declare function findAllNodes<T extends TraversableNode<T>>(root: T | null | undefined, predicate: (node: T) => boolean): T[];
45
+ /**
46
+ * Count total nodes in tree
47
+ */
48
+ export declare function countNodes<T extends TraversableNode<T>>(root: T | null | undefined): number;
49
+ /**
50
+ * Get maximum depth of tree
51
+ */
52
+ export declare function getMaxDepth<T extends TraversableNode<T>>(root: T | null | undefined): number;
53
+ /**
54
+ * Flatten tree to array using specified traversal
55
+ */
56
+ export declare function flattenTree<T extends TraversableNode<T>>(root: T | null | undefined, traversalType?: TraversalType): T[];
57
+ /**
58
+ * Example usage for directory trees
59
+ */
60
+ export declare function exampleUsage(): void;
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Tree Traversal Utilities for Directory Operations
3
+ * Based on standard tree traversal algorithms
4
+ */
5
+ /**
6
+ * Generator-based Pre-Order traversal (DFS)
7
+ * Useful for processing directories before their contents
8
+ * Order: current -> left -> right (parent -> children)
9
+ */
10
+ export function* walkPreOrder(node) {
11
+ if (!node)
12
+ return;
13
+ const stack = [node];
14
+ while (stack.length) {
15
+ const item = stack.pop();
16
+ if (!item) {
17
+ continue;
18
+ }
19
+ yield item;
20
+ // Push children in reverse order (right first) so left is processed first
21
+ if (item.children) {
22
+ for (let i = item.children.length - 1; i >= 0; i--) {
23
+ stack.push(item.children[i]);
24
+ }
25
+ }
26
+ }
27
+ }
28
+ /**
29
+ * Generator-based Post-Order traversal (DFS)
30
+ * Useful for processing directory contents before the directory itself
31
+ * Order: left -> right -> current (children -> parent)
32
+ * Good for operations like delete (delete files before directory)
33
+ */
34
+ export function* walkPostOrder(node) {
35
+ if (!node)
36
+ return;
37
+ const tempStack = [node];
38
+ const resultStack = [];
39
+ while (tempStack.length) {
40
+ const item = tempStack.pop();
41
+ if (!item) {
42
+ continue;
43
+ }
44
+ resultStack.push(item);
45
+ // Push children in normal order
46
+ if (item.children) {
47
+ for (const child of item.children) {
48
+ tempStack.push(child);
49
+ }
50
+ }
51
+ }
52
+ // Yield in reverse order
53
+ while (resultStack.length) {
54
+ const item = resultStack.pop();
55
+ if (item) {
56
+ yield item;
57
+ }
58
+ }
59
+ }
60
+ /**
61
+ * Generator-based Breadth-First Search (BFS)
62
+ * Processes directories level by level
63
+ * Good for finding files at specific depth or displaying hierarchy
64
+ */
65
+ export function* walkBFS(node) {
66
+ if (!node)
67
+ return;
68
+ const queue = [node];
69
+ while (queue.length) {
70
+ const item = queue.shift();
71
+ if (!item) {
72
+ continue;
73
+ }
74
+ yield item;
75
+ if (item.children) {
76
+ for (const child of item.children) {
77
+ queue.push(child);
78
+ }
79
+ }
80
+ }
81
+ }
82
+ /**
83
+ * BFS with level information
84
+ * Returns [node, level] tuples
85
+ */
86
+ export function* walkBFSWithLevel(node) {
87
+ if (!node)
88
+ return;
89
+ const queue = [[node, 0]];
90
+ while (queue.length) {
91
+ const [item, level] = queue.shift();
92
+ if (!item) {
93
+ continue;
94
+ }
95
+ yield [item, level];
96
+ if (item.children) {
97
+ for (const child of item.children) {
98
+ queue.push([child, level + 1]);
99
+ }
100
+ }
101
+ }
102
+ }
103
+ /**
104
+ * Get all nodes at a specific level
105
+ */
106
+ export function getNodesAtLevel(root, targetLevel) {
107
+ const nodes = [];
108
+ for (const [node, level] of walkBFSWithLevel(root)) {
109
+ if (level === targetLevel) {
110
+ nodes.push(node);
111
+ }
112
+ else if (level > targetLevel) {
113
+ break; // BFS guarantees we won't find more at target level
114
+ }
115
+ }
116
+ return nodes;
117
+ }
118
+ /**
119
+ * Find node by predicate using BFS (finds closest match)
120
+ */
121
+ export function findNode(root,
122
+ // eslint-disable-next-line no-unused-vars
123
+ predicate) {
124
+ for (const node of walkBFS(root)) {
125
+ if (predicate(node)) {
126
+ return node;
127
+ }
128
+ }
129
+ return null;
130
+ }
131
+ /**
132
+ * Find all nodes matching predicate
133
+ */
134
+ export function findAllNodes(root,
135
+ // eslint-disable-next-line no-unused-vars
136
+ predicate) {
137
+ const results = [];
138
+ for (const node of walkBFS(root)) {
139
+ if (predicate(node)) {
140
+ results.push(node);
141
+ }
142
+ }
143
+ return results;
144
+ }
145
+ /**
146
+ * Count total nodes in tree
147
+ */
148
+ export function countNodes(root) {
149
+ let count = 0;
150
+ for (const node of walkBFS(root)) {
151
+ void node;
152
+ count++;
153
+ }
154
+ return count;
155
+ }
156
+ /**
157
+ * Get maximum depth of tree
158
+ */
159
+ export function getMaxDepth(root) {
160
+ let maxDepth = 0;
161
+ for (const [, level] of walkBFSWithLevel(root)) {
162
+ maxDepth = Math.max(maxDepth, level);
163
+ }
164
+ return maxDepth;
165
+ }
166
+ /**
167
+ * Flatten tree to array using specified traversal
168
+ */
169
+ export function flattenTree(root, traversalType = "bfs") {
170
+ const walker = traversalType === "pre"
171
+ ? walkPreOrder
172
+ : traversalType === "post"
173
+ ? walkPostOrder
174
+ : walkBFS;
175
+ return Array.from(walker(root));
176
+ }
177
+ /**
178
+ * Example usage for directory trees
179
+ */
180
+ export function exampleUsage() {
181
+ // Example tree structure (like directory tree from getWorkspaceInfo)
182
+ const tree = {
183
+ name: "project",
184
+ type: "directory",
185
+ children: [
186
+ {
187
+ name: "src",
188
+ type: "directory",
189
+ children: [
190
+ { name: "index.js", type: "file" },
191
+ { name: "utils.js", type: "file" },
192
+ ],
193
+ },
194
+ {
195
+ name: "package.json",
196
+ type: "file",
197
+ },
198
+ ],
199
+ };
200
+ console.log("=== BFS Traversal (Level by Level) ===");
201
+ for (const node of walkBFS(tree)) {
202
+ console.log(node.name);
203
+ }
204
+ console.log("\n=== Pre-Order Traversal (Parent First) ===");
205
+ for (const node of walkPreOrder(tree)) {
206
+ console.log(node.name);
207
+ }
208
+ console.log("\n=== Post-Order Traversal (Children First) ===");
209
+ for (const node of walkPostOrder(tree)) {
210
+ console.log(node.name);
211
+ }
212
+ console.log("\n=== Find all files ===");
213
+ const files = findAllNodes(tree, (node) => node.type === "file");
214
+ console.log(files.map((f) => f.name));
215
+ console.log("\n=== Get depth ===");
216
+ console.log("Max depth:", getMaxDepth(tree));
217
+ }
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ type SearchEngine = "duckduckgo" | "bing";
3
+ type SearchResult = {
4
+ title: string;
5
+ url: string;
6
+ };
7
+ type SearchWebParams = {
8
+ query: string;
9
+ engine?: SearchEngine;
10
+ maxResults?: number;
11
+ };
12
+ type SearchWebResult = {
13
+ success: true;
14
+ results: SearchResult[];
15
+ } | {
16
+ success: false;
17
+ error: string;
18
+ };
19
+ export declare function searchWeb({ query, engine, maxResults, }: SearchWebParams): Promise<SearchWebResult>;
20
+ export declare const webSearchTool: {
21
+ description: string;
22
+ parameters: z.ZodObject<{
23
+ query: z.ZodString;
24
+ engine: z.ZodDefault<z.ZodEnum<["duckduckgo", "bing"]>>;
25
+ maxResults: z.ZodDefault<z.ZodNumber>;
26
+ }, "strip", z.ZodTypeAny, {
27
+ query?: string;
28
+ maxResults?: number;
29
+ engine?: "duckduckgo" | "bing";
30
+ }, {
31
+ query?: string;
32
+ maxResults?: number;
33
+ engine?: "duckduckgo" | "bing";
34
+ }>;
35
+ execute: typeof searchWeb;
36
+ };
37
+ export default webSearchTool;
@@ -0,0 +1,80 @@
1
+ import { z } from "zod";
2
+ import BrowserManager from "../../library/BrowserManager.js";
3
+ /**
4
+ * Web search tool using a search API
5
+ * @param {Object} params
6
+ * @param {string} params.query - Search query
7
+ * @param {number} [params.maxResults=5] - Max results to return
8
+ * @returns {Promise<Object>} Search results
9
+ */
10
+ // Engine-specific selectors that target actual search result links,
11
+ // avoiding nav/footer/ad anchors returned by a broad querySelectorAll("a").
12
+ const RESULT_SELECTORS = {
13
+ duckduckgo: "[data-testid='result-title-a']",
14
+ bing: ".b_algo h2 a",
15
+ };
16
+ async function webSearch(query, engine = "duckduckgo", maxResults = 5) {
17
+ if (!query) {
18
+ throw new Error("Search query is required");
19
+ }
20
+ const browserManager = await BrowserManager.getInstance();
21
+ const page = await browserManager.newPage();
22
+ try {
23
+ const url = engine === "duckduckgo"
24
+ ? `https://duckduckgo.com/?q=${encodeURIComponent(query)}`
25
+ : `https://bing.com/search?q=${encodeURIComponent(query)}`;
26
+ // "domcontentloaded" is sufficient for scraping rendered HTML and is
27
+ // significantly faster than "networkidle2".
28
+ await page.goto(url, { waitUntil: "domcontentloaded", timeout: 15000 });
29
+ const selector = RESULT_SELECTORS[engine] ?? RESULT_SELECTORS.duckduckgo;
30
+ const results = await page.evaluate((resultSelector, limit) => {
31
+ return Array.from(document.querySelectorAll(resultSelector))
32
+ .slice(0, limit)
33
+ .map((a) => ({
34
+ title: a.textContent?.trim() ?? "",
35
+ url: a.href,
36
+ }));
37
+ }, selector, maxResults);
38
+ return results;
39
+ }
40
+ finally {
41
+ await page.close();
42
+ }
43
+ }
44
+ //this is the function that out webSearchTool will be calling
45
+ export async function searchWeb({ query, engine, maxResults = 5, }) {
46
+ try {
47
+ //performs web search and returns results, if failed it returns error
48
+ const results = await webSearch(query, engine, maxResults);
49
+ return {
50
+ success: true,
51
+ results,
52
+ };
53
+ }
54
+ catch (error) {
55
+ const err = error;
56
+ return {
57
+ success: false,
58
+ error: err.message,
59
+ };
60
+ }
61
+ }
62
+ export const webSearchTool = {
63
+ description: "Search the web for real-time information",
64
+ parameters: z.object({
65
+ query: z.string().describe("The search query to look up on the web"),
66
+ engine: z
67
+ .enum(["duckduckgo", "bing"])
68
+ .default("duckduckgo")
69
+ .describe("Search engine to use"),
70
+ maxResults: z
71
+ .number()
72
+ .int()
73
+ .min(1)
74
+ .max(20)
75
+ .default(5)
76
+ .describe("Maximum number of results to return"),
77
+ }),
78
+ execute: searchWeb,
79
+ };
80
+ export default webSearchTool;
@@ -0,0 +1,59 @@
1
+ import { z } from "zod";
2
+ type WriteFileParams = {
3
+ filePath: string;
4
+ content: string;
5
+ encoding?: BufferEncoding;
6
+ createDirectories?: boolean;
7
+ };
8
+ type WriteFileSuccessResult = {
9
+ success: true;
10
+ filePath: string;
11
+ fileExisted: boolean;
12
+ size: number;
13
+ created: Date;
14
+ modified: Date;
15
+ linesAdded: number;
16
+ linesRemoved: number;
17
+ diff: string;
18
+ oldContent: string;
19
+ newContent: string;
20
+ };
21
+ type WriteFileErrorResult = {
22
+ success: false;
23
+ error: string;
24
+ };
25
+ type WriteFileResult = WriteFileSuccessResult | WriteFileErrorResult;
26
+ /**
27
+ * Tool for writing content to files
28
+ * @param {Object} params - The parameters for writing a file
29
+ * @param {string} params.filePath - The path to the file to write
30
+ * @param {string} params.content - The content to write to the file
31
+ * @param {string} [params.encoding='utf8'] - The encoding to use when writing the file
32
+ * @param {boolean} [params.createDirectories=true] - Whether to create parent directories if they don't exist
33
+ * @returns {Promise<Object>} Object containing success status and file info or error
34
+ */
35
+ export declare function writeFile({ filePath, content, encoding, createDirectories, }: WriteFileParams): Promise<WriteFileResult>;
36
+ /**
37
+ * Tool metadata for agent system
38
+ */
39
+ export declare const writeFileTool: {
40
+ description: string;
41
+ parameters: z.ZodObject<{
42
+ filePath: z.ZodString;
43
+ content: z.ZodString;
44
+ encoding: z.ZodDefault<z.ZodEnum<["utf8", "ascii", "base64", "binary", "hex"]>>;
45
+ createDirectories: z.ZodDefault<z.ZodBoolean>;
46
+ }, "strip", z.ZodTypeAny, {
47
+ content?: string;
48
+ encoding?: "ascii" | "utf8" | "base64" | "binary" | "hex";
49
+ filePath?: string;
50
+ createDirectories?: boolean;
51
+ }, {
52
+ content?: string;
53
+ encoding?: "ascii" | "utf8" | "base64" | "binary" | "hex";
54
+ filePath?: string;
55
+ createDirectories?: boolean;
56
+ }>;
57
+ execute: typeof writeFile;
58
+ };
59
+ export default writeFileTool;
@@ -0,0 +1,97 @@
1
+ import fs from "fs/promises";
2
+ import path from "path";
3
+ import { z } from "zod";
4
+ import { generateDiff } from "../utils/diffUtils.js";
5
+ /**
6
+ * Tool for writing content to files
7
+ * @param {Object} params - The parameters for writing a file
8
+ * @param {string} params.filePath - The path to the file to write
9
+ * @param {string} params.content - The content to write to the file
10
+ * @param {string} [params.encoding='utf8'] - The encoding to use when writing the file
11
+ * @param {boolean} [params.createDirectories=true] - Whether to create parent directories if they don't exist
12
+ * @returns {Promise<Object>} Object containing success status and file info or error
13
+ */
14
+ export async function writeFile({ filePath, content, encoding = "utf8", createDirectories = true, }) {
15
+ try {
16
+ // Validate input
17
+ if (!filePath) {
18
+ return {
19
+ success: false,
20
+ error: "File path is required",
21
+ };
22
+ }
23
+ if (content === undefined || content === null) {
24
+ return {
25
+ success: false,
26
+ error: "Content is required",
27
+ };
28
+ }
29
+ // Resolve to absolute path
30
+ const absolutePath = path.resolve(filePath);
31
+ // Track whether the file existed before this write so undo can decide
32
+ // between restoring content vs deleting a newly created file.
33
+ let fileExisted = false;
34
+ // Try to read existing content for diff (may not exist for new files)
35
+ let oldContent = "";
36
+ try {
37
+ fileExisted = true;
38
+ oldContent = await fs.readFile(absolutePath, encoding);
39
+ }
40
+ catch {
41
+ // File doesn't exist yet - that's fine
42
+ }
43
+ // Create parent directories if needed
44
+ if (createDirectories) {
45
+ const dir = path.dirname(absolutePath);
46
+ await fs.mkdir(dir, { recursive: true });
47
+ }
48
+ // Write file content
49
+ await fs.writeFile(absolutePath, content, encoding);
50
+ // Get file stats
51
+ const stats = await fs.stat(absolutePath);
52
+ // Generate diff for UI display (includes accurate line counts)
53
+ const { diff, linesAdded, linesRemoved } = generateDiff(oldContent, content, absolutePath);
54
+ return {
55
+ success: true,
56
+ filePath: absolutePath,
57
+ fileExisted,
58
+ size: stats.size,
59
+ created: stats.birthtime,
60
+ modified: stats.mtime,
61
+ linesAdded,
62
+ linesRemoved,
63
+ diff,
64
+ oldContent,
65
+ newContent: content,
66
+ };
67
+ }
68
+ catch (error) {
69
+ const err = error;
70
+ return {
71
+ success: false,
72
+ error: err.message,
73
+ };
74
+ }
75
+ }
76
+ /**
77
+ * Tool metadata for agent system
78
+ */
79
+ export const writeFileTool = {
80
+ description: "Write content to a file, creating it if it doesn't exist",
81
+ parameters: z.object({
82
+ filePath: z
83
+ .string()
84
+ .describe("The path to the file to write (can be relative or absolute)"),
85
+ content: z.string().describe("The content to write to the file"),
86
+ encoding: z
87
+ .enum(["utf8", "ascii", "base64", "binary", "hex"])
88
+ .default("utf8")
89
+ .describe("The encoding to use when writing the file"),
90
+ createDirectories: z
91
+ .boolean()
92
+ .default(true)
93
+ .describe("Whether to create parent directories if they don't exist"),
94
+ }),
95
+ execute: writeFile,
96
+ };
97
+ export default writeFileTool;
@@ -0,0 +1,12 @@
1
+ import { WorkspaceMutationBridge } from "./workspaceMutationBridge.js";
2
+ type CapturedResult = {
3
+ toolCallId: string;
4
+ result: Record<string, unknown>;
5
+ };
6
+ export declare class CapturedWorkspaceMutationBridge extends WorkspaceMutationBridge {
7
+ private readonly processedResults;
8
+ takeProcessedResults(generationId: string, toolCallIds: string[]): CapturedResult[];
9
+ clearProcessedResults(generationId: string): void;
10
+ processToolResult(args: Parameters<WorkspaceMutationBridge["processToolResult"]>[0]): Promise<import("@mastra/core/agent").MessageList>;
11
+ }
12
+ export {};
@@ -0,0 +1,67 @@
1
+ import { WorkspaceMutationBridge } from "./workspaceMutationBridge.js";
2
+ import { redactToolResult } from "./toolResultSafetyProcessor.js";
3
+ const getGenerationId = (requestContext) => {
4
+ if (!requestContext || typeof requestContext !== "object")
5
+ return undefined;
6
+ const get = requestContext.get;
7
+ if (typeof get !== "function")
8
+ return undefined;
9
+ const value = get.call(requestContext, "workspaceMutationGenerationId");
10
+ return typeof value === "string" && value.length > 0 ? value : undefined;
11
+ };
12
+ export class CapturedWorkspaceMutationBridge extends WorkspaceMutationBridge {
13
+ processedResults = new Map();
14
+ takeProcessedResults(generationId, toolCallIds) {
15
+ const results = [];
16
+ const generationResults = this.processedResults.get(generationId);
17
+ if (!generationResults)
18
+ return results;
19
+ for (const toolCallId of toolCallIds) {
20
+ const result = generationResults.get(toolCallId);
21
+ if (!result)
22
+ continue;
23
+ generationResults.delete(toolCallId);
24
+ results.push({ toolCallId, result });
25
+ }
26
+ if (generationResults.size === 0) {
27
+ this.processedResults.delete(generationId);
28
+ }
29
+ return results;
30
+ }
31
+ clearProcessedResults(generationId) {
32
+ this.processedResults.delete(generationId);
33
+ }
34
+ async processToolResult(args) {
35
+ const messageList = args.messageList;
36
+ const generationId = getGenerationId(args.requestContext);
37
+ const originalUpdateToolInvocation = messageList.updateToolInvocation;
38
+ messageList.updateToolInvocation = (update) => {
39
+ const invocation = update.toolInvocation;
40
+ const sanitizedResult = redactToolResult(invocation?.result).result;
41
+ if (invocation?.state === "result" &&
42
+ typeof invocation.toolCallId === "string" &&
43
+ sanitizedResult &&
44
+ typeof sanitizedResult === "object" &&
45
+ generationId) {
46
+ let generationResults = this.processedResults.get(generationId);
47
+ if (!generationResults) {
48
+ generationResults = new Map();
49
+ this.processedResults.set(generationId, generationResults);
50
+ }
51
+ generationResults.set(invocation.toolCallId, sanitizedResult);
52
+ }
53
+ return originalUpdateToolInvocation.call(messageList, {
54
+ ...update,
55
+ toolInvocation: invocation
56
+ ? { ...invocation, result: sanitizedResult }
57
+ : invocation,
58
+ });
59
+ };
60
+ try {
61
+ return await super.processToolResult(args);
62
+ }
63
+ finally {
64
+ messageList.updateToolInvocation = originalUpdateToolInvocation;
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,14 @@
1
+ type DiffResult = {
2
+ diff: string;
3
+ linesAdded: number;
4
+ linesRemoved: number;
5
+ };
6
+ /**
7
+ * Generate a unified diff string from old and new content
8
+ * @param {string} oldContent - The original content
9
+ * @param {string} newContent - The modified content
10
+ * @param {string} filePath - The file path (used for diff header)
11
+ * @returns {{diff: string, linesAdded: number, linesRemoved: number}} Diff result with accurate line counts
12
+ */
13
+ export declare function generateDiff(oldContent: string, newContent: string, filePath: string): DiffResult;
14
+ export {};
@@ -0,0 +1,39 @@
1
+ import path from "path";
2
+ import { diffLines } from "diff";
3
+ /**
4
+ * Generate a unified diff string from old and new content
5
+ * @param {string} oldContent - The original content
6
+ * @param {string} newContent - The modified content
7
+ * @param {string} filePath - The file path (used for diff header)
8
+ * @returns {{diff: string, linesAdded: number, linesRemoved: number}} Diff result with accurate line counts
9
+ */
10
+ export function generateDiff(oldContent, newContent, filePath) {
11
+ const changes = diffLines(oldContent, newContent);
12
+ let diff = `--- a/${path.basename(filePath)}\n+++ b/${path.basename(filePath)}\n`;
13
+ let linesAdded = 0;
14
+ let linesRemoved = 0;
15
+ changes.forEach((part) => {
16
+ const lines = part.value
17
+ .split("\n")
18
+ .filter((line, idx, arr) => idx < arr.length - 1 || line !== "");
19
+ if (part.added) {
20
+ linesAdded += lines.length;
21
+ lines.forEach((line) => {
22
+ diff += `+${line}\n`;
23
+ });
24
+ }
25
+ else if (part.removed) {
26
+ linesRemoved += lines.length;
27
+ lines.forEach((line) => {
28
+ diff += `-${line}\n`;
29
+ });
30
+ }
31
+ else {
32
+ // Context lines (unchanged)
33
+ lines.forEach((line) => {
34
+ diff += ` ${line}\n`;
35
+ });
36
+ }
37
+ });
38
+ return { diff, linesAdded, linesRemoved };
39
+ }