@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,152 @@
1
+ /**
2
+ * MCP Server Definition Provider
3
+ * Provides MCP servers from application settings
4
+ */
5
+ import { EventEmitter } from "events";
6
+ /**
7
+ * Default MCP Server Provider
8
+ * Provides servers from application settings/configuration
9
+ */
10
+ export class DefaultMcpServerProvider extends EventEmitter {
11
+ servers = [];
12
+ changeListeners = new Set();
13
+ constructor(servers = []) {
14
+ super();
15
+ this.servers = servers;
16
+ }
17
+ /**
18
+ * Update the list of available servers
19
+ */
20
+ updateServers(servers) {
21
+ this.servers = servers;
22
+ this.notifyChange();
23
+ }
24
+ /**
25
+ * Provide available MCP servers
26
+ */
27
+ async provideMcpServerDefinitions(signal) {
28
+ if (signal?.aborted) {
29
+ throw new Error("Operation cancelled");
30
+ }
31
+ // Return enabled servers
32
+ return this.servers.filter(server => server.enabled);
33
+ }
34
+ /**
35
+ * Optional: resolve server before starting
36
+ * Can be used for authentication, validation, etc.
37
+ */
38
+ async resolveMcpServerDefinition(server, signal) {
39
+ if (signal?.aborted) {
40
+ throw new Error("Operation cancelled");
41
+ }
42
+ // For now, just return the server as-is
43
+ // In the future, this could:
44
+ // - Validate the server configuration
45
+ // - Prompt for authentication if needed
46
+ // - Expand environment variables
47
+ // - Check if the command exists
48
+ return server;
49
+ }
50
+ /**
51
+ * Listen for server changes
52
+ */
53
+ onDidChangeMcpServerDefinitions(listener) {
54
+ this.changeListeners.add(listener);
55
+ return () => {
56
+ this.changeListeners.delete(listener);
57
+ };
58
+ }
59
+ /**
60
+ * Notify listeners of changes
61
+ */
62
+ notifyChange() {
63
+ for (const listener of this.changeListeners) {
64
+ try {
65
+ listener();
66
+ }
67
+ catch (error) {
68
+ console.error("Error in MCP server change listener:", error);
69
+ }
70
+ }
71
+ }
72
+ }
73
+ /**
74
+ * Dynamic MCP Server Provider
75
+ * Can discover servers from various sources
76
+ */
77
+ export class DynamicMcpServerProvider extends EventEmitter {
78
+ discoveryFunctions = [];
79
+ changeListeners = new Set();
80
+ /**
81
+ * Register a discovery function
82
+ */
83
+ registerDiscovery(fn) {
84
+ this.discoveryFunctions.push(fn);
85
+ this.notifyChange();
86
+ return () => {
87
+ const index = this.discoveryFunctions.indexOf(fn);
88
+ if (index >= 0) {
89
+ this.discoveryFunctions.splice(index, 1);
90
+ this.notifyChange();
91
+ }
92
+ };
93
+ }
94
+ /**
95
+ * Provide available MCP servers by running all discovery functions
96
+ */
97
+ async provideMcpServerDefinitions(signal) {
98
+ const allServers = [];
99
+ for (const discover of this.discoveryFunctions) {
100
+ try {
101
+ const servers = await discover(signal);
102
+ allServers.push(...servers);
103
+ }
104
+ catch (error) {
105
+ console.error("Error discovering MCP servers:", error);
106
+ }
107
+ }
108
+ // Deduplicate by server ID
109
+ const seen = new Set();
110
+ return allServers.filter(server => {
111
+ if (seen.has(server.id)) {
112
+ return false;
113
+ }
114
+ seen.add(server.id);
115
+ return true;
116
+ });
117
+ }
118
+ /**
119
+ * Listen for server changes
120
+ */
121
+ onDidChangeMcpServerDefinitions(listener) {
122
+ this.changeListeners.add(listener);
123
+ return () => {
124
+ this.changeListeners.delete(listener);
125
+ };
126
+ }
127
+ /**
128
+ * Notify listeners of changes
129
+ */
130
+ notifyChange() {
131
+ for (const listener of this.changeListeners) {
132
+ try {
133
+ listener();
134
+ }
135
+ catch (error) {
136
+ console.error("Error in MCP server change listener:", error);
137
+ }
138
+ }
139
+ }
140
+ }
141
+ /**
142
+ * Create a default provider from static configuration
143
+ */
144
+ export function createDefaultProvider(servers) {
145
+ return new DefaultMcpServerProvider(servers);
146
+ }
147
+ /**
148
+ * Create a dynamic provider for runtime discovery
149
+ */
150
+ export function createDynamicProvider() {
151
+ return new DynamicMcpServerProvider();
152
+ }
@@ -0,0 +1,20 @@
1
+ export declare const MCP_SERVERS_STORAGE_KEY = "settings.mcpServers";
2
+ export declare const MAX_MCP_SERVERS = 10;
3
+ export type McpServerConfig = {
4
+ id: string;
5
+ name: string;
6
+ command: string;
7
+ args: string[];
8
+ env: Record<string, string>;
9
+ enabled: boolean;
10
+ };
11
+ export declare const normalizeMcpServerCommandLine: (command: string, args: string[]) => {
12
+ command: string;
13
+ args: string[];
14
+ };
15
+ export declare const sanitizeMcpServer: (input: unknown, index?: number) => McpServerConfig | null;
16
+ export declare const sanitizeMcpServers: (input: unknown, maxServers?: number) => McpServerConfig[];
17
+ export declare const toStableMcpFingerprint: (servers: McpServerConfig[]) => string;
18
+ export declare const loadMcpServersFromStorage: () => McpServerConfig[];
19
+ export declare const saveMcpServersToStorage: (servers: McpServerConfig[]) => void;
20
+ export declare const getEnabledMcpServersFromStorage: () => McpServerConfig[];
@@ -0,0 +1,131 @@
1
+ export const MCP_SERVERS_STORAGE_KEY = "settings.mcpServers";
2
+ export const MAX_MCP_SERVERS = 10;
3
+ const MAX_COMMAND_LENGTH = 300;
4
+ const MAX_NAME_LENGTH = 100;
5
+ const MAX_ARG_LENGTH = 500;
6
+ const MAX_ARGS = 40;
7
+ const MAX_ENV_VARS = 60;
8
+ const MAX_ENV_KEY_LENGTH = 120;
9
+ const MAX_ENV_VALUE_LENGTH = 2000;
10
+ const isSafeEnvKey = (key) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
11
+ const splitCommandString = (value) => {
12
+ const parts = [];
13
+ const regex = /[^\s"']+|"([^"]*)"|'([^']*)'/g;
14
+ let match;
15
+ while ((match = regex.exec(value)) !== null) {
16
+ parts.push(match[1] ?? match[2] ?? match[0]);
17
+ }
18
+ return parts;
19
+ };
20
+ export const normalizeMcpServerCommandLine = (command, args) => {
21
+ const normalizedCommand = command.trim();
22
+ const tokens = splitCommandString(normalizedCommand);
23
+ if (tokens.length === 0) {
24
+ return { command: normalizedCommand, args: [...args] };
25
+ }
26
+ return {
27
+ command: tokens[0],
28
+ args: [...tokens.slice(1), ...args],
29
+ };
30
+ };
31
+ const safeString = (value, maxLength) => typeof value === "string" ? value.trim().slice(0, maxLength) : "";
32
+ const sanitizeArgs = (args) => {
33
+ if (!Array.isArray(args))
34
+ return [];
35
+ return args
36
+ .map((entry) => safeString(entry, MAX_ARG_LENGTH))
37
+ .filter(Boolean)
38
+ .slice(0, MAX_ARGS);
39
+ };
40
+ const sanitizeEnv = (env) => {
41
+ if (!env || typeof env !== "object" || Array.isArray(env))
42
+ return {};
43
+ const entries = Object.entries(env)
44
+ .map(([key, value]) => [safeString(key, MAX_ENV_KEY_LENGTH), safeString(value, MAX_ENV_VALUE_LENGTH)])
45
+ .filter(([key]) => key.length > 0 && isSafeEnvKey(key))
46
+ .slice(0, MAX_ENV_VARS);
47
+ return Object.fromEntries(entries);
48
+ };
49
+ const getDefaultId = (index) => `mcp-${Date.now()}-${index}`;
50
+ const normalizeMcpServerDraft = (input, index = 0) => {
51
+ if (!input || typeof input !== "object" || Array.isArray(input))
52
+ return null;
53
+ const raw = input;
54
+ const id = safeString(raw.id, 120) || getDefaultId(index);
55
+ const command = safeString(raw.command, MAX_COMMAND_LENGTH);
56
+ const name = safeString(raw.name, MAX_NAME_LENGTH) || command || "New MCP Server";
57
+ return {
58
+ id,
59
+ name,
60
+ command,
61
+ args: sanitizeArgs(raw.args),
62
+ env: sanitizeEnv(raw.env),
63
+ enabled: raw.enabled !== false,
64
+ };
65
+ };
66
+ const normalizeMcpServerDrafts = (input, maxServers = MAX_MCP_SERVERS) => {
67
+ if (!Array.isArray(input))
68
+ return [];
69
+ return input
70
+ .map((entry, index) => normalizeMcpServerDraft(entry, index))
71
+ .filter((entry) => entry !== null)
72
+ .slice(0, maxServers);
73
+ };
74
+ export const sanitizeMcpServer = (input, index = 0) => {
75
+ if (!input || typeof input !== "object" || Array.isArray(input))
76
+ return null;
77
+ const raw = input;
78
+ const command = safeString(raw.command, MAX_COMMAND_LENGTH);
79
+ if (!command)
80
+ return null;
81
+ const id = safeString(raw.id, 120) || getDefaultId(index);
82
+ const name = safeString(raw.name, MAX_NAME_LENGTH) || command;
83
+ return {
84
+ id,
85
+ name,
86
+ command,
87
+ args: sanitizeArgs(raw.args),
88
+ env: sanitizeEnv(raw.env),
89
+ enabled: raw.enabled !== false,
90
+ };
91
+ };
92
+ export const sanitizeMcpServers = (input, maxServers = MAX_MCP_SERVERS) => {
93
+ if (!Array.isArray(input))
94
+ return [];
95
+ return input
96
+ .map((entry, index) => sanitizeMcpServer(entry, index))
97
+ .filter((entry) => entry !== null)
98
+ .slice(0, maxServers);
99
+ };
100
+ export const toStableMcpFingerprint = (servers) => {
101
+ const normalized = servers
102
+ .map((server) => ({
103
+ id: server.id,
104
+ name: server.name,
105
+ command: server.command,
106
+ args: [...server.args],
107
+ env: Object.fromEntries(Object.entries(server.env).sort(([a], [b]) => a.localeCompare(b))),
108
+ enabled: server.enabled,
109
+ }))
110
+ .sort((a, b) => a.id.localeCompare(b.id));
111
+ return JSON.stringify(normalized);
112
+ };
113
+ export const loadMcpServersFromStorage = () => {
114
+ if (typeof window === "undefined")
115
+ return [];
116
+ try {
117
+ const raw = localStorage.getItem(MCP_SERVERS_STORAGE_KEY);
118
+ if (!raw)
119
+ return [];
120
+ return normalizeMcpServerDrafts(JSON.parse(raw));
121
+ }
122
+ catch {
123
+ return [];
124
+ }
125
+ };
126
+ export const saveMcpServersToStorage = (servers) => {
127
+ if (typeof window === "undefined")
128
+ return;
129
+ localStorage.setItem(MCP_SERVERS_STORAGE_KEY, JSON.stringify(normalizeMcpServerDrafts(servers)));
130
+ };
131
+ export const getEnabledMcpServersFromStorage = () => sanitizeMcpServers(loadMcpServersFromStorage().filter((server) => server.enabled));
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Pattern Matcher - Advanced code pattern detection and matching
3
+ * Inspired by spaCy's pattern matching for code analysis
4
+ */
5
+ type PatternRuleValue = CodeToken[keyof CodeToken] | CodeToken[keyof CodeToken][];
6
+ type PatternRule = Partial<Record<keyof CodeToken | "OP", PatternRuleValue>>;
7
+ type CodeToken = {
8
+ text: string;
9
+ type: string;
10
+ pos: string;
11
+ line: number;
12
+ index: number;
13
+ };
14
+ type PatternMatch = {
15
+ pattern: string;
16
+ tokens: CodeToken[];
17
+ start: number;
18
+ end: number;
19
+ };
20
+ export declare class Pattern {
21
+ name: string;
22
+ rules: PatternRule[];
23
+ constructor(name: string, rules: PatternRule[]);
24
+ match(tokens: CodeToken[]): PatternMatch[] | null;
25
+ tokenMatchesRule(token: CodeToken, rule: PatternRule): boolean;
26
+ }
27
+ export declare class CodeMatcher {
28
+ patterns: Map<string, Pattern>;
29
+ tokenCache: Map<string, CodeToken[]>;
30
+ constructor();
31
+ /**
32
+ * Add a pattern to match
33
+ */
34
+ addPattern(name: string, rules: PatternRule[]): void;
35
+ /**
36
+ * Remove a pattern
37
+ */
38
+ removePattern(name: string): void;
39
+ /**
40
+ * Match patterns in code
41
+ */
42
+ match(code: string, patternNames?: string[] | null): PatternMatch[];
43
+ /**
44
+ * Tokenize code into analyzable tokens
45
+ */
46
+ tokenize(code: string): CodeToken[];
47
+ /**
48
+ * Tokenize a single line
49
+ */
50
+ tokenizeLine(line: string, lineNum: number): CodeToken[];
51
+ /**
52
+ * Get token type
53
+ */
54
+ getTokenType(token: string): "KEYWORD" | "CLASS_NAME" | "NUMBER" | "IDENTIFIER" | "BRACKET" | "PUNCTUATION" | "OPERATOR" | "UNKNOWN";
55
+ /**
56
+ * Get part of speech (simplified for code)
57
+ */
58
+ getPartOfSpeech(token: string, type: string): string;
59
+ /**
60
+ * Clear token cache
61
+ */
62
+ clearCache(): void;
63
+ }
64
+ export declare const CommonPatterns: Record<string, PatternRule[]>;
65
+ export declare function createDefaultMatcher(): CodeMatcher;
66
+ export default CodeMatcher;
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Pattern Matcher - Advanced code pattern detection and matching
3
+ * Inspired by spaCy's pattern matching for code analysis
4
+ */
5
+ export class Pattern {
6
+ name;
7
+ rules;
8
+ constructor(name, rules) {
9
+ this.name = name;
10
+ this.rules = rules; // Array of matching rules
11
+ }
12
+ match(tokens) {
13
+ // Check if tokens match this pattern
14
+ if (tokens.length < this.rules.length)
15
+ return null;
16
+ const matches = [];
17
+ for (let i = 0; i <= tokens.length - this.rules.length; i++) {
18
+ let isMatch = true;
19
+ const matchedTokens = [];
20
+ for (let j = 0; j < this.rules.length; j++) {
21
+ const token = tokens[i + j];
22
+ const rule = this.rules[j];
23
+ if (!this.tokenMatchesRule(token, rule)) {
24
+ isMatch = false;
25
+ break;
26
+ }
27
+ matchedTokens.push(token);
28
+ }
29
+ if (isMatch) {
30
+ matches.push({
31
+ pattern: this.name,
32
+ tokens: matchedTokens,
33
+ start: i,
34
+ end: i + this.rules.length,
35
+ });
36
+ }
37
+ }
38
+ return matches.length > 0 ? matches : null;
39
+ }
40
+ tokenMatchesRule(token, rule) {
41
+ // Check if token matches the rule criteria
42
+ for (const [key, value] of Object.entries(rule)) {
43
+ if (key === "OP")
44
+ continue; // Optional operator, handle separately
45
+ const tokenValue = token[key];
46
+ if (Array.isArray(value)) {
47
+ if (!value.includes(tokenValue))
48
+ return false;
49
+ }
50
+ else {
51
+ if (tokenValue !== value)
52
+ return false;
53
+ }
54
+ }
55
+ return true;
56
+ }
57
+ }
58
+ export class CodeMatcher {
59
+ patterns;
60
+ tokenCache;
61
+ constructor() {
62
+ this.patterns = new Map();
63
+ this.tokenCache = new Map();
64
+ }
65
+ /**
66
+ * Add a pattern to match
67
+ */
68
+ addPattern(name, rules) {
69
+ const pattern = new Pattern(name, rules);
70
+ this.patterns.set(name, pattern);
71
+ }
72
+ /**
73
+ * Remove a pattern
74
+ */
75
+ removePattern(name) {
76
+ this.patterns.delete(name);
77
+ }
78
+ /**
79
+ * Match patterns in code
80
+ */
81
+ match(code, patternNames = null) {
82
+ const tokens = this.tokenize(code);
83
+ const allMatches = [];
84
+ const patternsToMatch = patternNames
85
+ ? patternNames.flatMap((name) => {
86
+ const pattern = this.patterns.get(name);
87
+ return pattern ? [pattern] : [];
88
+ })
89
+ : Array.from(this.patterns.values());
90
+ patternsToMatch.forEach((pattern) => {
91
+ const matches = pattern.match(tokens);
92
+ if (matches) {
93
+ allMatches.push(...matches);
94
+ }
95
+ });
96
+ return allMatches;
97
+ }
98
+ /**
99
+ * Tokenize code into analyzable tokens
100
+ */
101
+ tokenize(code) {
102
+ const cacheKey = code.substring(0, 100); // Cache based on first 100 chars
103
+ const cachedTokens = this.tokenCache.get(cacheKey);
104
+ if (cachedTokens) {
105
+ return cachedTokens;
106
+ }
107
+ const tokens = [];
108
+ const lines = code.split("\n");
109
+ lines.forEach((line, lineNum) => {
110
+ // Tokenize each line
111
+ const lineTokens = this.tokenizeLine(line, lineNum);
112
+ tokens.push(...lineTokens);
113
+ });
114
+ this.tokenCache.set(cacheKey, tokens);
115
+ return tokens;
116
+ }
117
+ /**
118
+ * Tokenize a single line
119
+ */
120
+ tokenizeLine(line, lineNum) {
121
+ const tokens = [];
122
+ // Simple tokenization - split by whitespace and operators
123
+ const regex = /(\w+|\[|\]|[{}();,.]|=>|===|==|=|!==|!=|<=|>=|<|>|\+\+|--|\+|-|\*|\/|&&|\|\||!)/g;
124
+ let match;
125
+ while ((match = regex.exec(line)) !== null) {
126
+ const token = match[0];
127
+ const type = this.getTokenType(token);
128
+ tokens.push({
129
+ text: token,
130
+ type: type,
131
+ pos: this.getPartOfSpeech(token, type),
132
+ line: lineNum,
133
+ index: match.index,
134
+ });
135
+ }
136
+ return tokens;
137
+ }
138
+ /**
139
+ * Get token type
140
+ */
141
+ getTokenType(token) {
142
+ // Keywords
143
+ const keywords = new Set([
144
+ "function",
145
+ "class",
146
+ "const",
147
+ "let",
148
+ "var",
149
+ "if",
150
+ "else",
151
+ "for",
152
+ "while",
153
+ "return",
154
+ "import",
155
+ "export",
156
+ "from",
157
+ "default",
158
+ "async",
159
+ "await",
160
+ "new",
161
+ "this",
162
+ "super",
163
+ "extends",
164
+ "implements",
165
+ "interface",
166
+ "type",
167
+ "enum",
168
+ "public",
169
+ "private",
170
+ "protected",
171
+ "static",
172
+ ]);
173
+ if (keywords.has(token))
174
+ return "KEYWORD";
175
+ if (/^[A-Z]/.test(token))
176
+ return "CLASS_NAME";
177
+ if (/^\d+$/.test(token))
178
+ return "NUMBER";
179
+ if (/^[a-z_]\w*$/.test(token))
180
+ return "IDENTIFIER";
181
+ if (/^[{}[\]()]$/.test(token))
182
+ return "BRACKET";
183
+ if (/^[;,.]$/.test(token))
184
+ return "PUNCTUATION";
185
+ if (/^(=>|===|==|=|!==|!=|<=|>=|<|>|\+\+|--|\+|-|\*|\/|&&|\|\||!)$/.test(token))
186
+ return "OPERATOR";
187
+ return "UNKNOWN";
188
+ }
189
+ /**
190
+ * Get part of speech (simplified for code)
191
+ */
192
+ getPartOfSpeech(token, type) {
193
+ if (type === "KEYWORD") {
194
+ if (["function", "class", "const", "let", "var"].includes(token)) {
195
+ return "DECL"; // Declaration
196
+ }
197
+ if (["if", "else", "for", "while", "return"].includes(token)) {
198
+ return "CTRL"; // Control flow
199
+ }
200
+ }
201
+ if (type === "IDENTIFIER")
202
+ return "NOUN";
203
+ if (type === "OPERATOR")
204
+ return "VERB";
205
+ return type;
206
+ }
207
+ /**
208
+ * Clear token cache
209
+ */
210
+ clearCache() {
211
+ this.tokenCache.clear();
212
+ }
213
+ }
214
+ // Pre-defined patterns for common code structures
215
+ export const CommonPatterns = {
216
+ // Function declaration: function name() {}
217
+ FUNCTION_DECLARATION: [
218
+ { type: "KEYWORD", text: "function" },
219
+ { type: "IDENTIFIER" },
220
+ { type: "BRACKET", text: "(" },
221
+ ],
222
+ // Class declaration: class Name
223
+ CLASS_DECLARATION: [
224
+ { type: "KEYWORD", text: "class" },
225
+ { type: "CLASS_NAME" },
226
+ ],
227
+ // Class with inheritance: class Name extends Parent
228
+ CLASS_INHERITANCE: [
229
+ { type: "KEYWORD", text: "class" },
230
+ { type: "CLASS_NAME" },
231
+ { type: "KEYWORD", text: "extends" },
232
+ { type: "CLASS_NAME" },
233
+ ],
234
+ // Variable declaration: const name =
235
+ VARIABLE_DECLARATION: [
236
+ { type: "KEYWORD", text: ["const", "let", "var"] },
237
+ { type: "IDENTIFIER" },
238
+ { type: "OPERATOR", text: "=" },
239
+ ],
240
+ // Import statement: import X from 'Y'
241
+ IMPORT_STATEMENT: [
242
+ { type: "KEYWORD", text: "import" },
243
+ { type: "IDENTIFIER" },
244
+ { type: "KEYWORD", text: "from" },
245
+ ],
246
+ // Method call: object.method()
247
+ METHOD_CALL: [
248
+ { type: "IDENTIFIER" },
249
+ { type: "PUNCTUATION", text: "." },
250
+ { type: "IDENTIFIER" },
251
+ { type: "BRACKET", text: "(" },
252
+ ],
253
+ // Arrow function: () =>
254
+ ARROW_FUNCTION: [
255
+ { type: "BRACKET", text: "(" },
256
+ { type: "BRACKET", text: ")" },
257
+ { type: "OPERATOR", text: "=>" },
258
+ ],
259
+ // Async function: async function
260
+ ASYNC_FUNCTION: [
261
+ { type: "KEYWORD", text: "async" },
262
+ { type: "KEYWORD", text: "function" },
263
+ ],
264
+ // Interface implementation: class X implements Y
265
+ INTERFACE_IMPLEMENTATION: [
266
+ { type: "KEYWORD", text: "class" },
267
+ { type: "CLASS_NAME" },
268
+ { type: "KEYWORD", text: "implements" },
269
+ ],
270
+ // Constructor: constructor()
271
+ CONSTRUCTOR: [
272
+ { type: "IDENTIFIER", text: "constructor" },
273
+ { type: "BRACKET", text: "(" },
274
+ ],
275
+ };
276
+ // Create a default matcher with common patterns
277
+ export function createDefaultMatcher() {
278
+ const matcher = new CodeMatcher();
279
+ Object.entries(CommonPatterns).forEach(([name, rules]) => {
280
+ matcher.addPattern(name, rules);
281
+ });
282
+ return matcher;
283
+ }
284
+ export default CodeMatcher;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Escape a string so it can be used as a literal in a JavaScript RegExp.
3
+ */
4
+ export declare const escapeRegExp: (value: string) => string;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Escape a string so it can be used as a literal in a JavaScript RegExp.
3
+ */
4
+ export const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -0,0 +1,27 @@
1
+ type RuntimeEventListener = (data?: unknown) => void;
2
+ declare class RuntimeEventBus {
3
+ listeners: Map<string, Set<RuntimeEventListener>>;
4
+ buffer: Map<string, unknown>;
5
+ eventHistory: Array<{
6
+ event: string;
7
+ timestamp: number;
8
+ dataSize: number;
9
+ }>;
10
+ maxHistorySize: number;
11
+ subscribe(event: string, listener: RuntimeEventListener): () => void;
12
+ emit(event: string, data?: unknown): void;
13
+ trackEvent(event: string, data: unknown): void;
14
+ getStatistics(): Record<string, number>;
15
+ clear(): void;
16
+ }
17
+ export declare const runtimeEventBus: RuntimeEventBus;
18
+ export declare const RuntimeEvents: {
19
+ readonly FILE_OPEN: "file:open";
20
+ readonly CODE_CHANGE: "code:change";
21
+ readonly CONTEXT_UPDATE: "kg:context:update";
22
+ readonly CONTEXT_QUERY: "kg:context:query";
23
+ readonly TOKEN_USAGE: "kg:token:usage";
24
+ readonly CACHE_HIT: "kg:cache:hit";
25
+ readonly CACHE_MISS: "kg:cache:miss";
26
+ };
27
+ export default RuntimeEventBus;