@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,25 @@
1
+ export type JsonRpcId = number;
2
+ export type PendingRequestHandlers = {
3
+ resolve: (value: unknown) => void;
4
+ reject: (reason?: unknown) => void;
5
+ };
6
+ export type LspMessage = {
7
+ id?: JsonRpcId;
8
+ method?: string;
9
+ result?: unknown;
10
+ error?: {
11
+ message?: string;
12
+ };
13
+ };
14
+ export type LspPosition = {
15
+ line: number;
16
+ character: number;
17
+ };
18
+ export type LspSemanticLegend = {
19
+ tokenTypes: string[];
20
+ tokenModifiers: string[];
21
+ };
22
+ export type LspSemanticTokensResult = {
23
+ resultId?: string;
24
+ data?: number[];
25
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ export type ServerLaunchSpec = {
2
+ serverId: string;
3
+ languageId: string;
4
+ version: string;
5
+ source: "workspace" | "approved-registry";
6
+ signatureVerified: boolean;
7
+ sha256: string;
8
+ command: string;
9
+ args: string[];
10
+ cwd?: string;
11
+ };
12
+ export declare class ServerManager {
13
+ private workspaceRoot;
14
+ private serverCacheRoot;
15
+ private inventoryPath;
16
+ private manifestsDir;
17
+ private auditLogPath;
18
+ constructor();
19
+ setWorkspaceRoot(rootPath: string | null): void;
20
+ resolveLaunchSpec(languageId: string): Promise<ServerLaunchSpec | null>;
21
+ recordServerStarted(languageId: string, sha256?: string): Promise<void>;
22
+ recordServerStopped(languageId: string, sha256?: string): Promise<void>;
23
+ ensureOptionalServers(): Promise<void>;
24
+ private getWorkspaceRoot;
25
+ private getWorkspaceId;
26
+ private getPolicy;
27
+ private getLocalBinaryPath;
28
+ private resolveNodeLanguageServer;
29
+ private resolveSystemServer;
30
+ private resolveSystemBinaryPath;
31
+ private resolveCopilotLanguageServer;
32
+ private writeManifest;
33
+ private readInventory;
34
+ private audit;
35
+ }
36
+ export declare const serverManager: ServerManager;
37
+ export default ServerManager;
@@ -0,0 +1,427 @@
1
+ import { existsSync } from "fs";
2
+ import fs from "fs/promises";
3
+ import os from "os";
4
+ import path from "path";
5
+ import { createHash } from "crypto";
6
+ import { execFile } from "child_process";
7
+ import { promisify } from "util";
8
+ import { runtimeEventBus } from "../runtimeEventBus.js";
9
+ import { extensionManager } from "../extensionManager.js";
10
+ const execFileAsync = promisify(execFile);
11
+ const AUDIT_EVENT_BUS_TOPIC = "audit:language_server";
12
+ const getHomeCacheRoot = () => path.join(os.homedir(), ".iris", "language-servers");
13
+ const isBundledDesktopRuntime = () => process.env.TAURI_BUNDLED === "1";
14
+ const getApprovedChecksumMap = () => {
15
+ const raw = process.env.IRIS_LSP_APPROVED_SHA256_JSON;
16
+ if (!raw) {
17
+ return {};
18
+ }
19
+ try {
20
+ const parsed = JSON.parse(raw);
21
+ return parsed && typeof parsed === "object" ? parsed : {};
22
+ }
23
+ catch {
24
+ return {};
25
+ }
26
+ };
27
+ const getSystemServerOverrideMap = () => {
28
+ const raw = process.env.IRIS_LSP_SYSTEM_SERVER_OVERRIDE_JSON;
29
+ if (!raw) {
30
+ return {};
31
+ }
32
+ try {
33
+ const parsed = JSON.parse(raw);
34
+ return parsed && typeof parsed === "object" ? parsed : {};
35
+ }
36
+ catch {
37
+ return {};
38
+ }
39
+ };
40
+ const LANGUAGE_SERVER_POLICIES = {
41
+ python: {
42
+ id: "pyright",
43
+ languageId: "python",
44
+ command: "pyright-langserver",
45
+ args: ["--stdio"],
46
+ version: "1.1.405",
47
+ packageName: "pyright",
48
+ source: "approved-registry",
49
+ },
50
+ typescript: {
51
+ id: "typescript-language-server",
52
+ languageId: "typescript",
53
+ command: "typescript-language-server",
54
+ args: ["--stdio"],
55
+ version: "4.4.0",
56
+ source: "approved-registry",
57
+ },
58
+ javascript: {
59
+ id: "typescript-language-server",
60
+ languageId: "javascript",
61
+ command: "typescript-language-server",
62
+ args: ["--stdio"],
63
+ version: "4.4.0",
64
+ source: "approved-registry",
65
+ },
66
+ go: {
67
+ id: "gopls",
68
+ languageId: "go",
69
+ command: "gopls",
70
+ args: [],
71
+ version: "system",
72
+ source: "approved-registry",
73
+ },
74
+ rust: {
75
+ id: "rust-analyzer",
76
+ languageId: "rust",
77
+ command: "rust-analyzer",
78
+ args: [],
79
+ version: "system",
80
+ source: "approved-registry",
81
+ },
82
+ gdscript: {
83
+ id: "godot",
84
+ languageId: "gdscript",
85
+ command: "godot",
86
+ args: ["--headless", "--lsp"],
87
+ version: "system",
88
+ source: "approved-registry",
89
+ },
90
+ cpp: {
91
+ id: "clangd",
92
+ languageId: "cpp",
93
+ command: "clangd",
94
+ args: ["--background-index"],
95
+ version: "system",
96
+ source: "approved-registry",
97
+ },
98
+ };
99
+ const ensureDirectory = async (dirPath) => {
100
+ await fs.mkdir(dirPath, { recursive: true });
101
+ };
102
+ const sha256File = async (filePath) => {
103
+ const fileBuffer = await fs.readFile(filePath);
104
+ return createHash("sha256").update(fileBuffer).digest("hex");
105
+ };
106
+ export class ServerManager {
107
+ workspaceRoot = null;
108
+ serverCacheRoot;
109
+ inventoryPath;
110
+ manifestsDir;
111
+ auditLogPath;
112
+ constructor() {
113
+ this.serverCacheRoot = getHomeCacheRoot();
114
+ this.inventoryPath = path.join(this.serverCacheRoot, "inventory.json");
115
+ this.manifestsDir = path.join(this.serverCacheRoot, "manifests");
116
+ this.auditLogPath = path.join(this.serverCacheRoot, "audit.log");
117
+ }
118
+ setWorkspaceRoot(rootPath) {
119
+ this.workspaceRoot = rootPath;
120
+ if (extensionManager.isCopilotLanguageServerEnabled()) {
121
+ void this.ensureOptionalServers();
122
+ }
123
+ }
124
+ async resolveLaunchSpec(languageId) {
125
+ const policy = this.getPolicy(languageId);
126
+ if (!policy) {
127
+ return null;
128
+ }
129
+ switch (languageId) {
130
+ case "typescript":
131
+ case "typescriptreact":
132
+ case "javascript":
133
+ case "javascriptreact":
134
+ case "python":
135
+ return this.resolveNodeLanguageServer(policy);
136
+ case "go":
137
+ case "cpp":
138
+ case "c":
139
+ case "objc":
140
+ case "objcpp":
141
+ case "rust":
142
+ case "gdscript":
143
+ return this.resolveSystemServer(policy);
144
+ default:
145
+ return null;
146
+ }
147
+ }
148
+ async recordServerStarted(languageId, sha256 = "unknown") {
149
+ const policy = this.getPolicy(languageId);
150
+ if (!policy) {
151
+ return;
152
+ }
153
+ await this.audit("language_server_started", {
154
+ language: policy.languageId,
155
+ server_id: policy.id,
156
+ server_version: policy.version,
157
+ sha256,
158
+ outcome: "success",
159
+ });
160
+ }
161
+ async recordServerStopped(languageId, sha256 = "unknown") {
162
+ const policy = this.getPolicy(languageId);
163
+ if (!policy) {
164
+ return;
165
+ }
166
+ await this.audit("language_server_stopped", {
167
+ language: policy.languageId,
168
+ server_id: policy.id,
169
+ server_version: policy.version,
170
+ sha256,
171
+ outcome: "success",
172
+ });
173
+ }
174
+ async ensureOptionalServers() {
175
+ if (!extensionManager.isCopilotLanguageServerEnabled()) {
176
+ return;
177
+ }
178
+ try {
179
+ await this.resolveCopilotLanguageServer();
180
+ }
181
+ catch (error) {
182
+ console.warn("Failed to prepare Copilot language server:", error);
183
+ }
184
+ }
185
+ getWorkspaceRoot() {
186
+ return this.workspaceRoot || process.cwd();
187
+ }
188
+ getWorkspaceId() {
189
+ return this.getWorkspaceRoot();
190
+ }
191
+ getPolicy(languageId) {
192
+ if (languageId === "typescriptreact") {
193
+ return LANGUAGE_SERVER_POLICIES.typescript;
194
+ }
195
+ if (languageId === "javascriptreact") {
196
+ return LANGUAGE_SERVER_POLICIES.javascript;
197
+ }
198
+ if (languageId === "c" || languageId === "objc" || languageId === "objcpp") {
199
+ return LANGUAGE_SERVER_POLICIES.cpp;
200
+ }
201
+ return LANGUAGE_SERVER_POLICIES[languageId] || null;
202
+ }
203
+ getLocalBinaryPath(binaryName) {
204
+ const binDir = path.join(this.getWorkspaceRoot(), "node_modules", ".bin");
205
+ if (process.platform === "win32") {
206
+ for (const ext of [".cmd", ".exe", ""]) {
207
+ const candidate = path.join(binDir, `${binaryName}${ext}`);
208
+ if (existsSync(candidate)) {
209
+ return candidate;
210
+ }
211
+ }
212
+ return path.join(binDir, `${binaryName}.cmd`);
213
+ }
214
+ return path.join(binDir, binaryName);
215
+ }
216
+ async resolveNodeLanguageServer(policy) {
217
+ const packageName = policy.packageName || policy.id;
218
+ const localBinaryPath = this.getLocalBinaryPath(policy.command);
219
+ if (existsSync(localBinaryPath)) {
220
+ const checksum = await sha256File(localBinaryPath);
221
+ await this.writeManifest({
222
+ id: policy.id,
223
+ language: policy.languageId,
224
+ version: policy.version,
225
+ command: localBinaryPath,
226
+ sha256: checksum,
227
+ source: policy.source,
228
+ installed_at: new Date().toISOString(),
229
+ signature_verified: true,
230
+ });
231
+ await this.audit("language_server_signature_verified", {
232
+ language: policy.languageId,
233
+ server_id: policy.id,
234
+ server_version: policy.version,
235
+ sha256: checksum,
236
+ outcome: "success",
237
+ });
238
+ return {
239
+ serverId: policy.id,
240
+ languageId: policy.languageId,
241
+ version: policy.version,
242
+ source: "workspace",
243
+ signatureVerified: true,
244
+ sha256: checksum,
245
+ command: localBinaryPath,
246
+ args: policy.args,
247
+ cwd: this.getWorkspaceRoot(),
248
+ };
249
+ }
250
+ if (isBundledDesktopRuntime()) {
251
+ const details = `Missing workspace binary '${policy.command}' for ${policy.languageId} in bundled desktop mode; ` +
252
+ "npx fallback is disabled";
253
+ await this.audit("language_server_install_failed", {
254
+ language: policy.languageId,
255
+ server_id: policy.id,
256
+ server_version: policy.version,
257
+ sha256: "missing-workspace-binary",
258
+ outcome: "failure",
259
+ details,
260
+ });
261
+ throw new Error(`Missing workspace dependency '${policy.command}'. Install '${packageName}@${policy.version}' in this workspace to enable ${policy.languageId} LSP in desktop mode.`);
262
+ }
263
+ await this.audit("language_server_install_requested", {
264
+ language: policy.languageId,
265
+ server_id: policy.id,
266
+ server_version: policy.version,
267
+ sha256: "npm",
268
+ outcome: "success",
269
+ });
270
+ await this.writeManifest({
271
+ id: policy.id,
272
+ language: policy.languageId,
273
+ version: policy.version,
274
+ command: policy.command,
275
+ sha256: "npm-integrity",
276
+ source: policy.source,
277
+ installed_at: new Date().toISOString(),
278
+ signature_verified: true,
279
+ });
280
+ await this.audit("language_server_signature_verified", {
281
+ language: policy.languageId,
282
+ server_id: policy.id,
283
+ server_version: policy.version,
284
+ sha256: "npm-integrity",
285
+ outcome: "success",
286
+ details: "npm package integrity is delegated to npm registry and client verification",
287
+ });
288
+ await this.audit("language_server_installed", {
289
+ language: policy.languageId,
290
+ server_id: policy.id,
291
+ server_version: policy.version,
292
+ sha256: "npm-integrity",
293
+ outcome: "success",
294
+ });
295
+ return {
296
+ serverId: policy.id,
297
+ languageId: policy.languageId,
298
+ version: policy.version,
299
+ source: policy.source,
300
+ signatureVerified: true,
301
+ sha256: "npm-integrity",
302
+ command: "npx",
303
+ args: ["-y", "-p", `${packageName}@${policy.version}`, policy.command, ...policy.args],
304
+ cwd: this.getWorkspaceRoot(),
305
+ };
306
+ }
307
+ async resolveSystemServer(policy) {
308
+ const approvedHashes = getApprovedChecksumMap();
309
+ const binaryPath = await this.resolveSystemBinaryPath(policy);
310
+ const checksum = await sha256File(binaryPath);
311
+ const approvedHash = approvedHashes[policy.id] || approvedHashes[policy.languageId];
312
+ if (!approvedHash || approvedHash !== checksum) {
313
+ await this.audit("language_server_signature_failed", {
314
+ language: policy.languageId,
315
+ server_id: policy.id,
316
+ server_version: policy.version,
317
+ sha256: checksum,
318
+ outcome: "failure",
319
+ details: approvedHash
320
+ ? `checksum mismatch for ${policy.id}`
321
+ : `missing approved checksum for ${policy.id}`,
322
+ });
323
+ throw new Error(approvedHash
324
+ ? `Checksum verification failed for ${policy.id}`
325
+ : `Approved checksum not configured for ${policy.id}`);
326
+ }
327
+ await this.writeManifest({
328
+ id: policy.id,
329
+ language: policy.languageId,
330
+ version: policy.version,
331
+ command: binaryPath,
332
+ sha256: checksum,
333
+ source: policy.source,
334
+ installed_at: new Date().toISOString(),
335
+ signature_verified: true,
336
+ });
337
+ await this.audit("language_server_signature_verified", {
338
+ language: policy.languageId,
339
+ server_id: policy.id,
340
+ server_version: policy.version,
341
+ sha256: checksum,
342
+ outcome: "success",
343
+ details: "system binary launch requires explicit allowlist entry",
344
+ });
345
+ return {
346
+ serverId: policy.id,
347
+ languageId: policy.languageId,
348
+ version: policy.version,
349
+ source: policy.source,
350
+ signatureVerified: true,
351
+ sha256: checksum,
352
+ command: binaryPath,
353
+ args: policy.args,
354
+ cwd: this.getWorkspaceRoot(),
355
+ };
356
+ }
357
+ async resolveSystemBinaryPath(policy) {
358
+ const overrideMap = getSystemServerOverrideMap();
359
+ const overridePath = overrideMap[policy.id] || overrideMap[policy.languageId];
360
+ if (overridePath) {
361
+ return path.resolve(overridePath);
362
+ }
363
+ if (path.isAbsolute(policy.command) && existsSync(policy.command)) {
364
+ return policy.command;
365
+ }
366
+ const resolver = process.platform === "win32" ? "where" : "which";
367
+ const result = await execFileAsync(resolver, [policy.command]);
368
+ const firstPath = result.stdout
369
+ .split(/\r?\n/)
370
+ .map((line) => line.trim())
371
+ .find((line) => line.length > 0);
372
+ if (!firstPath) {
373
+ throw new Error(`Unable to resolve system binary path for ${policy.command}`);
374
+ }
375
+ return firstPath;
376
+ }
377
+ async resolveCopilotLanguageServer() {
378
+ const command = this.getLocalBinaryPath("copilot-language-server");
379
+ const checksum = existsSync(command) ? await sha256File(command) : "disabled";
380
+ return {
381
+ serverId: "copilot-language-server",
382
+ languageId: "copilot",
383
+ version: "workspace",
384
+ source: "workspace",
385
+ signatureVerified: existsSync(command),
386
+ sha256: checksum,
387
+ command: existsSync(command) ? command : "npx",
388
+ args: existsSync(command)
389
+ ? ["--stdio"]
390
+ : ["-y", "-p", "@github/copilot-language-server", "copilot-language-server", "--stdio"],
391
+ cwd: this.getWorkspaceRoot(),
392
+ };
393
+ }
394
+ async writeManifest(manifest) {
395
+ await ensureDirectory(this.manifestsDir);
396
+ const manifestPath = path.join(this.manifestsDir, `${manifest.id}-${manifest.language}.json`);
397
+ await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf8");
398
+ const inventory = await this.readInventory();
399
+ const key = `${manifest.id}:${manifest.language}`;
400
+ inventory[key] = manifest;
401
+ await fs.writeFile(this.inventoryPath, JSON.stringify(inventory, null, 2), "utf8");
402
+ }
403
+ async readInventory() {
404
+ try {
405
+ const raw = await fs.readFile(this.inventoryPath, "utf8");
406
+ const parsed = JSON.parse(raw);
407
+ return parsed && typeof parsed === "object" ? parsed : {};
408
+ }
409
+ catch {
410
+ return {};
411
+ }
412
+ }
413
+ async audit(eventName, payload) {
414
+ const event = {
415
+ event_name: eventName,
416
+ occurred_at: new Date().toISOString(),
417
+ actor_type: "system",
418
+ workspace_id: this.getWorkspaceId(),
419
+ ...payload,
420
+ };
421
+ await ensureDirectory(this.serverCacheRoot);
422
+ await fs.appendFile(this.auditLogPath, `${JSON.stringify(event)}\n`, "utf8");
423
+ runtimeEventBus.emit(AUDIT_EVENT_BUS_TOPIC, event);
424
+ }
425
+ }
426
+ export const serverManager = new ServerManager();
427
+ export default ServerManager;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * MCP Server Definition Provider
3
+ * Provides MCP servers from application settings
4
+ */
5
+ import type { McpServerConfig } from "./mcpSettings.js";
6
+ import type { McpServerDefinitionProvider } from "./languageModelTools.js";
7
+ import { EventEmitter } from "events";
8
+ /**
9
+ * Default MCP Server Provider
10
+ * Provides servers from application settings/configuration
11
+ */
12
+ export declare class DefaultMcpServerProvider extends EventEmitter implements McpServerDefinitionProvider {
13
+ private servers;
14
+ private changeListeners;
15
+ constructor(servers?: McpServerConfig[]);
16
+ /**
17
+ * Update the list of available servers
18
+ */
19
+ updateServers(servers: McpServerConfig[]): void;
20
+ /**
21
+ * Provide available MCP servers
22
+ */
23
+ provideMcpServerDefinitions(signal?: AbortSignal): Promise<McpServerConfig[]>;
24
+ /**
25
+ * Optional: resolve server before starting
26
+ * Can be used for authentication, validation, etc.
27
+ */
28
+ resolveMcpServerDefinition(server: McpServerConfig, signal?: AbortSignal): Promise<McpServerConfig>;
29
+ /**
30
+ * Listen for server changes
31
+ */
32
+ onDidChangeMcpServerDefinitions(listener: () => void): () => void;
33
+ /**
34
+ * Notify listeners of changes
35
+ */
36
+ private notifyChange;
37
+ }
38
+ /**
39
+ * Dynamic MCP Server Provider
40
+ * Can discover servers from various sources
41
+ */
42
+ export declare class DynamicMcpServerProvider extends EventEmitter implements McpServerDefinitionProvider {
43
+ private discoveryFunctions;
44
+ private changeListeners;
45
+ /**
46
+ * Register a discovery function
47
+ */
48
+ registerDiscovery(fn: (signal?: AbortSignal) => Promise<McpServerConfig[]>): () => void;
49
+ /**
50
+ * Provide available MCP servers by running all discovery functions
51
+ */
52
+ provideMcpServerDefinitions(signal?: AbortSignal): Promise<McpServerConfig[]>;
53
+ /**
54
+ * Listen for server changes
55
+ */
56
+ onDidChangeMcpServerDefinitions(listener: () => void): () => void;
57
+ /**
58
+ * Notify listeners of changes
59
+ */
60
+ notifyChange(): void;
61
+ }
62
+ /**
63
+ * Create a default provider from static configuration
64
+ */
65
+ export declare function createDefaultProvider(servers: McpServerConfig[]): DefaultMcpServerProvider;
66
+ /**
67
+ * Create a dynamic provider for runtime discovery
68
+ */
69
+ export declare function createDynamicProvider(): DynamicMcpServerProvider;