@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,4 @@
1
+ import type { NextFunction, Request, Response, Router } from "express";
2
+ type AuthMiddleware = (req: Request, res: Response, next: NextFunction) => void;
3
+ export declare const registerLspResolveRoutes: (router: Router, requireDesktopAuth: AuthMiddleware) => void;
4
+ export {};
@@ -0,0 +1,143 @@
1
+ import path from "path";
2
+ import { coreLsp } from "../core/library/lsp/coreLsp.js";
3
+ const resolveAbsolutePath = (workspacePath, filePath) => {
4
+ if (typeof filePath !== "string" || filePath.length === 0) {
5
+ return undefined;
6
+ }
7
+ return path.isAbsolute(filePath) ? filePath : path.join(workspacePath, filePath);
8
+ };
9
+ export const registerLspResolveRoutes = (router, requireDesktopAuth) => {
10
+ router.post("/lsp/completion/resolve", requireDesktopAuth, async (req, res) => {
11
+ try {
12
+ const { workspaceRoot, languageId, filePath, item } = req.body;
13
+ if (!item || typeof item !== "object") {
14
+ return res.status(400).json({ success: false, error: "item is required" });
15
+ }
16
+ const workspacePath = workspaceRoot || process.cwd();
17
+ coreLsp.setRootPath(workspacePath);
18
+ const absolutePath = resolveAbsolutePath(workspacePath, filePath);
19
+ const resolved = await coreLsp.resolveCompletionItem(item, typeof languageId === "string" ? languageId : undefined, absolutePath);
20
+ return res.json({ success: true, item: resolved });
21
+ }
22
+ catch (error) {
23
+ const err = error;
24
+ return res
25
+ .status(500)
26
+ .json({ success: false, error: err.message || "Failed to resolve completion item" });
27
+ }
28
+ });
29
+ router.post("/lsp/code-action/resolve", requireDesktopAuth, async (req, res) => {
30
+ try {
31
+ const { workspaceRoot, languageId, filePath, item } = req.body;
32
+ if (!item || typeof item !== "object") {
33
+ return res.status(400).json({ success: false, error: "item is required" });
34
+ }
35
+ const workspacePath = workspaceRoot || process.cwd();
36
+ coreLsp.setRootPath(workspacePath);
37
+ const absolutePath = resolveAbsolutePath(workspacePath, filePath);
38
+ const resolved = await coreLsp.resolveCodeAction(item, typeof languageId === "string" ? languageId : undefined, absolutePath);
39
+ return res.json({ success: true, item: resolved });
40
+ }
41
+ catch (error) {
42
+ const err = error;
43
+ return res
44
+ .status(500)
45
+ .json({ success: false, error: err.message || "Failed to resolve code action" });
46
+ }
47
+ });
48
+ router.post("/lsp/code-lens/resolve", requireDesktopAuth, async (req, res) => {
49
+ try {
50
+ const { workspaceRoot, languageId, filePath, item } = req.body;
51
+ if (!item || typeof item !== "object") {
52
+ return res.status(400).json({ success: false, error: "item is required" });
53
+ }
54
+ const workspacePath = workspaceRoot || process.cwd();
55
+ coreLsp.setRootPath(workspacePath);
56
+ const absolutePath = resolveAbsolutePath(workspacePath, filePath);
57
+ const resolved = await coreLsp.resolveCodeLens(item, typeof languageId === "string" ? languageId : undefined, absolutePath);
58
+ return res.json({ success: true, item: resolved });
59
+ }
60
+ catch (error) {
61
+ const err = error;
62
+ return res
63
+ .status(500)
64
+ .json({ success: false, error: err.message || "Failed to resolve code lens" });
65
+ }
66
+ });
67
+ router.post("/lsp/document-link/resolve", requireDesktopAuth, async (req, res) => {
68
+ try {
69
+ const { workspaceRoot, languageId, filePath, item } = req.body;
70
+ if (!item || typeof item !== "object") {
71
+ return res.status(400).json({ success: false, error: "item is required" });
72
+ }
73
+ const workspacePath = workspaceRoot || process.cwd();
74
+ coreLsp.setRootPath(workspacePath);
75
+ const absolutePath = resolveAbsolutePath(workspacePath, filePath);
76
+ const resolved = await coreLsp.resolveDocumentLink(item, typeof languageId === "string" ? languageId : undefined, absolutePath);
77
+ return res.json({ success: true, item: resolved });
78
+ }
79
+ catch (error) {
80
+ const err = error;
81
+ return res
82
+ .status(500)
83
+ .json({ success: false, error: err.message || "Failed to resolve document link" });
84
+ }
85
+ });
86
+ router.post("/lsp/workspace-symbol/resolve", requireDesktopAuth, async (req, res) => {
87
+ try {
88
+ const { workspaceRoot, languageId, item } = req.body;
89
+ if (!item || typeof item !== "object") {
90
+ return res.status(400).json({ success: false, error: "item is required" });
91
+ }
92
+ const workspacePath = workspaceRoot || process.cwd();
93
+ coreLsp.setRootPath(workspacePath);
94
+ const resolved = await coreLsp.resolveWorkspaceSymbol(item, typeof languageId === "string" ? languageId : undefined);
95
+ return res.json({ success: true, item: resolved });
96
+ }
97
+ catch (error) {
98
+ const err = error;
99
+ return res
100
+ .status(500)
101
+ .json({ success: false, error: err.message || "Failed to resolve workspace symbol" });
102
+ }
103
+ });
104
+ router.post("/lsp/inlay-hint/resolve", requireDesktopAuth, async (req, res) => {
105
+ try {
106
+ const { workspaceRoot, languageId, filePath, item } = req.body;
107
+ if (!item || typeof item !== "object") {
108
+ return res.status(400).json({ success: false, error: "item is required" });
109
+ }
110
+ const workspacePath = workspaceRoot || process.cwd();
111
+ coreLsp.setRootPath(workspacePath);
112
+ const absolutePath = resolveAbsolutePath(workspacePath, filePath);
113
+ const resolved = await coreLsp.resolveInlayHint(item, typeof languageId === "string" ? languageId : undefined, absolutePath);
114
+ return res.json({ success: true, item: resolved });
115
+ }
116
+ catch (error) {
117
+ const err = error;
118
+ return res
119
+ .status(500)
120
+ .json({ success: false, error: err.message || "Failed to resolve inlay hint" });
121
+ }
122
+ });
123
+ router.post("/lsp/inline-completion/resolve", requireDesktopAuth, async (req, res) => {
124
+ try {
125
+ const { workspaceRoot, languageId, filePath, item } = req.body;
126
+ if (!item || typeof item !== "object") {
127
+ return res.status(400).json({ success: false, error: "item is required" });
128
+ }
129
+ const workspacePath = workspaceRoot || process.cwd();
130
+ coreLsp.setRootPath(workspacePath);
131
+ const absolutePath = resolveAbsolutePath(workspacePath, filePath);
132
+ const resolved = await coreLsp.resolveInlineCompletionItem(item, typeof languageId === "string" ? languageId : undefined, absolutePath);
133
+ return res.json({ success: true, item: resolved });
134
+ }
135
+ catch (error) {
136
+ const err = error;
137
+ return res.status(500).json({
138
+ success: false,
139
+ error: err.message || "Failed to resolve inline completion item",
140
+ });
141
+ }
142
+ });
143
+ };
@@ -0,0 +1,4 @@
1
+ import type { NextFunction, Request, Response, Router } from "express";
2
+ type AuthMiddleware = (req: Request, res: Response, next: NextFunction) => void;
3
+ export declare const registerLspSemanticDocumentRoutes: (router: Router, requireDesktopAuth: AuthMiddleware) => void;
4
+ export {};
@@ -0,0 +1,98 @@
1
+ import path from "path";
2
+ import { coreLsp } from "../core/library/lsp/coreLsp.js";
3
+ const resolveAbsolutePath = (workspacePath, filePath) => path.isAbsolute(filePath) ? filePath : path.join(workspacePath, filePath);
4
+ export const registerLspSemanticDocumentRoutes = (router, requireDesktopAuth) => {
5
+ router.post("/lsp/semantic-tokens-range", requireDesktopAuth, async (req, res) => {
6
+ try {
7
+ const { filePath, workspaceRoot, startLine, startCharacter, endLine, endCharacter, } = req.body;
8
+ if (typeof filePath !== "string" || filePath.trim().length === 0) {
9
+ return res.status(400).json({ success: false, error: "filePath is required" });
10
+ }
11
+ if (typeof startLine !== "number" ||
12
+ typeof startCharacter !== "number" ||
13
+ typeof endLine !== "number" ||
14
+ typeof endCharacter !== "number") {
15
+ return res.status(400).json({
16
+ success: false,
17
+ error: "startLine, startCharacter, endLine, and endCharacter are required",
18
+ });
19
+ }
20
+ const workspacePath = workspaceRoot || process.cwd();
21
+ const absolutePath = resolveAbsolutePath(workspacePath, filePath);
22
+ coreLsp.setRootPath(workspacePath);
23
+ const semanticTokens = await coreLsp.getSemanticTokensRange(absolutePath, startLine, startCharacter, endLine, endCharacter);
24
+ if (!semanticTokens) {
25
+ return res.json({ success: false, error: "No semantic tokens available" });
26
+ }
27
+ return res.json({
28
+ success: true,
29
+ data: semanticTokens.data,
30
+ legend: semanticTokens.legend,
31
+ languageId: semanticTokens.languageId,
32
+ });
33
+ }
34
+ catch (error) {
35
+ const err = error;
36
+ return res
37
+ .status(500)
38
+ .json({ success: false, error: err.message || "Failed to get semantic tokens" });
39
+ }
40
+ });
41
+ router.post("/lsp/semantic-tokens-full", requireDesktopAuth, async (req, res) => {
42
+ try {
43
+ const { filePath, workspaceRoot } = req.body;
44
+ if (typeof filePath !== "string" || filePath.trim().length === 0) {
45
+ return res.status(400).json({ success: false, error: "filePath is required" });
46
+ }
47
+ const workspacePath = workspaceRoot || process.cwd();
48
+ const absolutePath = resolveAbsolutePath(workspacePath, filePath);
49
+ coreLsp.setRootPath(workspacePath);
50
+ const semanticTokens = await coreLsp.getSemanticTokensFull(absolutePath);
51
+ if (!semanticTokens) {
52
+ return res.json({ success: false, error: "No semantic tokens available" });
53
+ }
54
+ return res.json({
55
+ success: true,
56
+ data: semanticTokens.data,
57
+ resultId: semanticTokens.resultId,
58
+ legend: semanticTokens.legend,
59
+ languageId: semanticTokens.languageId,
60
+ });
61
+ }
62
+ catch (error) {
63
+ const err = error;
64
+ return res
65
+ .status(500)
66
+ .json({ success: false, error: err.message || "Failed to get semantic tokens" });
67
+ }
68
+ });
69
+ router.post("/lsp/semantic-tokens-delta", requireDesktopAuth, async (req, res) => {
70
+ try {
71
+ const { filePath, workspaceRoot, previousResultId } = req.body;
72
+ if (typeof filePath !== "string" || filePath.trim().length === 0) {
73
+ return res.status(400).json({ success: false, error: "filePath is required" });
74
+ }
75
+ const workspacePath = workspaceRoot || process.cwd();
76
+ const absolutePath = resolveAbsolutePath(workspacePath, filePath);
77
+ coreLsp.setRootPath(workspacePath);
78
+ const semanticTokens = await coreLsp.getSemanticTokensDocumentDelta(absolutePath, typeof previousResultId === "string" ? previousResultId : undefined);
79
+ if (!semanticTokens) {
80
+ return res.json({ success: false, error: "No semantic token delta available" });
81
+ }
82
+ return res.json({
83
+ success: true,
84
+ data: semanticTokens.data,
85
+ resultId: semanticTokens.resultId,
86
+ edits: semanticTokens.edits,
87
+ legend: semanticTokens.legend,
88
+ languageId: semanticTokens.languageId,
89
+ });
90
+ }
91
+ catch (error) {
92
+ const err = error;
93
+ return res
94
+ .status(500)
95
+ .json({ success: false, error: err.message || "Failed to get semantic token delta" });
96
+ }
97
+ });
98
+ };
@@ -0,0 +1,2 @@
1
+ import type { Router } from "express";
2
+ export declare const registerSemanticRoutes: (router: Router) => void;
@@ -0,0 +1,126 @@
1
+ import path from "path";
2
+ import { coreLsp } from "../core/library/lsp/coreLsp.js";
3
+ const LANGUAGE_ID_MAP = {
4
+ ts: "typescript",
5
+ tsx: "typescriptreact",
6
+ typescript: "typescript",
7
+ typescriptreact: "typescriptreact",
8
+ js: "javascript",
9
+ jsx: "javascriptreact",
10
+ javascript: "javascript",
11
+ javascriptreact: "javascriptreact",
12
+ py: "python",
13
+ python: "python",
14
+ };
15
+ const resolveSemanticLanguageId = (language) => LANGUAGE_ID_MAP[language.toLowerCase()];
16
+ const resolveSemanticFilePath = ({ filePath, workspacePath, languageId, }) => {
17
+ if (filePath) {
18
+ return path.isAbsolute(filePath) ? filePath : path.join(workspacePath, filePath);
19
+ }
20
+ return path.join(workspacePath, `.iris-semantic-preview.${languageId.startsWith("typescript")
21
+ ? "ts"
22
+ : languageId === "python"
23
+ ? "py"
24
+ : "js"}`);
25
+ };
26
+ export const registerSemanticRoutes = (router) => {
27
+ // POST /api/agent/semantic-tokens - Get semantic tokens for supported LSP snippets
28
+ router.post("/semantic-tokens", async (req, res) => {
29
+ try {
30
+ const { code, language, filePath, workspaceRoot } = req.body;
31
+ if (typeof code !== "string") {
32
+ return res.status(400).json({ success: false, error: "Code is required" });
33
+ }
34
+ if (typeof language !== "string" || language.length === 0) {
35
+ return res.status(400).json({ success: false, error: "Language is required" });
36
+ }
37
+ const languageId = resolveSemanticLanguageId(language);
38
+ if (!languageId) {
39
+ return res.status(400).json({
40
+ success: false,
41
+ error: `Semantic tokens are not supported for language: ${language}`,
42
+ });
43
+ }
44
+ const workspacePath = workspaceRoot || process.cwd();
45
+ const semanticFilePath = resolveSemanticFilePath({
46
+ filePath,
47
+ workspacePath,
48
+ languageId,
49
+ });
50
+ coreLsp.setRootPath(workspacePath);
51
+ const semanticTokens = await coreLsp.getSemanticTokensForCode(semanticFilePath, languageId, code);
52
+ if (!semanticTokens) {
53
+ // Distinguish "the language server can never start here" from a
54
+ // transient cold-start miss so the client knows not to retry.
55
+ const unavailable = coreLsp.isLanguageUnavailable(languageId);
56
+ return res.json({
57
+ success: false,
58
+ unavailable,
59
+ error: unavailable
60
+ ? `No language server available for ${languageId} in this workspace`
61
+ : "No semantic tokens available",
62
+ });
63
+ }
64
+ return res.json({
65
+ success: true,
66
+ data: semanticTokens.data,
67
+ legend: semanticTokens.legend,
68
+ languageId: semanticTokens.languageId,
69
+ });
70
+ }
71
+ catch (error) {
72
+ const err = error;
73
+ console.error("Semantic tokens error:", error);
74
+ return res.status(500).json({
75
+ success: false,
76
+ error: err.message || "Failed to fetch semantic tokens",
77
+ });
78
+ }
79
+ });
80
+ // POST /api/agent/semantic-tokens-delta - Get semantic token deltas for supported LSP snippets
81
+ router.post("/semantic-tokens-delta", async (req, res) => {
82
+ try {
83
+ const { code, language, filePath, workspaceRoot, previousResultId } = req.body;
84
+ if (typeof code !== "string") {
85
+ return res.status(400).json({ success: false, error: "Code is required" });
86
+ }
87
+ if (typeof language !== "string" || language.length === 0) {
88
+ return res.status(400).json({ success: false, error: "Language is required" });
89
+ }
90
+ const languageId = resolveSemanticLanguageId(language);
91
+ if (!languageId) {
92
+ return res.status(400).json({
93
+ success: false,
94
+ error: `Semantic tokens are not supported for language: ${language}`,
95
+ });
96
+ }
97
+ const workspacePath = workspaceRoot || process.cwd();
98
+ const semanticFilePath = resolveSemanticFilePath({
99
+ filePath,
100
+ workspacePath,
101
+ languageId,
102
+ });
103
+ coreLsp.setRootPath(workspacePath);
104
+ const semanticTokens = await coreLsp.getSemanticTokensDelta(semanticFilePath, languageId, code, typeof previousResultId === "string" ? previousResultId : undefined);
105
+ if (!semanticTokens) {
106
+ return res.json({ success: false, error: "No semantic tokens available" });
107
+ }
108
+ return res.json({
109
+ success: true,
110
+ data: semanticTokens.data,
111
+ edits: semanticTokens.edits,
112
+ resultId: semanticTokens.resultId,
113
+ legend: semanticTokens.legend,
114
+ languageId: semanticTokens.languageId,
115
+ });
116
+ }
117
+ catch (error) {
118
+ const err = error;
119
+ console.error("Semantic tokens delta error:", error);
120
+ return res.status(500).json({
121
+ success: false,
122
+ error: err.message || "Failed to fetch semantic token delta",
123
+ });
124
+ }
125
+ });
126
+ };
package/dist/cli.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * iris-agent CLI with ACP (Agent Client Protocol) support
4
+ * Usage:
5
+ * iris-agent --workspace /path/to/workspace --modelId openrouter/openai/gpt-4o --acp
6
+ * iris-agent --workspace /path/to/workspace --modelId openrouter/openai/gpt-4o --chat
7
+ */
8
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * iris-agent CLI with ACP (Agent Client Protocol) support
4
+ * Usage:
5
+ * iris-agent --workspace /path/to/workspace --modelId openrouter/openai/gpt-4o --acp
6
+ * iris-agent --workspace /path/to/workspace --modelId openrouter/openai/gpt-4o --chat
7
+ */
8
+ import yargs from "yargs";
9
+ import { hideBin } from "yargs/helpers";
10
+ import { createCodingAgent } from "./api/core/agent/index.js";
11
+ import { startAcpServer } from "./api/acp/acpServer.js";
12
+ const defaultModelId = process.env.MODEL_ID ||
13
+ process.env.OPENROUTER_MODEL ||
14
+ "openrouter/openai/gpt-4o";
15
+ const argv = yargs(hideBin(process.argv))
16
+ .option("workspace", {
17
+ alias: "w",
18
+ type: "string",
19
+ description: "Workspace root path",
20
+ required: true,
21
+ })
22
+ .option("acp", {
23
+ alias: "a",
24
+ type: "boolean",
25
+ description: "Start ACP (Agent Client Protocol) server mode",
26
+ default: false,
27
+ })
28
+ .option("chat", {
29
+ alias: "c",
30
+ type: "boolean",
31
+ description: "Interactive chat mode",
32
+ default: false,
33
+ })
34
+ .option("modelId", {
35
+ type: "string",
36
+ description: "Language model identifier",
37
+ default: defaultModelId,
38
+ })
39
+ .help()
40
+ .parseSync();
41
+ async function main() {
42
+ const workspaceRoot = argv.workspace;
43
+ const modelId = argv.modelId;
44
+ if (argv.acp) {
45
+ const stderrLog = console.error.bind(console);
46
+ console.log = stderrLog;
47
+ console.debug = stderrLog;
48
+ console.info = stderrLog;
49
+ console.warn = stderrLog;
50
+ console.dir = stderrLog;
51
+ console.table = stderrLog;
52
+ console.trace = stderrLog;
53
+ console.group = stderrLog;
54
+ console.groupCollapsed = stderrLog;
55
+ console.groupEnd = stderrLog;
56
+ }
57
+ console.log(`šŸš€ Iris Agent CLI`);
58
+ console.log(`šŸ“ Workspace: ${workspaceRoot}`);
59
+ console.log(`šŸ¤– Model: ${modelId}`);
60
+ if (argv.acp) {
61
+ console.log("šŸ”— Starting ACP server over stdio...");
62
+ await startAcpServer((requestedModelId, targetWorkspace) => createCodingAgent(requestedModelId || modelId, targetWorkspace || workspaceRoot), workspaceRoot);
63
+ }
64
+ else if (argv.chat) {
65
+ // Interactive chat mode
66
+ const agent = await createCodingAgent(modelId, workspaceRoot);
67
+ console.log(`šŸ’¬ Entering chat mode (type "exit" to quit)`);
68
+ await startChatMode(agent, workspaceRoot);
69
+ }
70
+ else {
71
+ // Default: show help
72
+ yargs(hideBin(process.argv))
73
+ .showHelp();
74
+ }
75
+ }
76
+ async function startChatMode(agent, workspaceRoot) {
77
+ const readline = await import("readline");
78
+ const rl = readline.createInterface({
79
+ input: process.stdin,
80
+ output: process.stdout,
81
+ });
82
+ const question = (prompt) => new Promise((resolve) => rl.question(prompt, resolve));
83
+ const threadId = `cli-chat-${Date.now()}`;
84
+ const resourceId = `cli-session`;
85
+ try {
86
+ while (true) {
87
+ const input = await question("\n> ");
88
+ const trimmedInput = input.trim();
89
+ if (!trimmedInput) {
90
+ continue;
91
+ }
92
+ if (trimmedInput.toLowerCase() === "exit" || trimmedInput.toLowerCase() === "quit") {
93
+ console.log("šŸ‘‹ Goodbye!");
94
+ break;
95
+ }
96
+ try {
97
+ console.log("šŸ¤” Processing...\n");
98
+ const options = {
99
+ threadId,
100
+ resourceId,
101
+ maxSteps: 50,
102
+ workspaceRoot,
103
+ };
104
+ if (typeof agent.stream === "function") {
105
+ const streamResult = await agent.stream(trimmedInput, options);
106
+ const reader = streamResult.fullStream.getReader();
107
+ let hasOutput = false;
108
+ while (true) {
109
+ const { done, value } = await reader.read();
110
+ if (done)
111
+ break;
112
+ if (value?.type === "text-delta" || value?.type === "reasoning-delta") {
113
+ const text = String(value.payload?.text || "");
114
+ if (text) {
115
+ process.stdout.write(text);
116
+ hasOutput = true;
117
+ }
118
+ }
119
+ else if (value?.type === "tool-call") {
120
+ const toolName = typeof value.payload?.toolName === "string"
121
+ ? value.payload.toolName
122
+ : "tool";
123
+ process.stdout.write(`\nāš™ļø [Calling tool: ${toolName}]... `);
124
+ }
125
+ else if (value?.type === "tool-result") {
126
+ process.stdout.write(`done.\n`);
127
+ }
128
+ }
129
+ if (!hasOutput && streamResult.text) {
130
+ const final = await streamResult.text;
131
+ if (final) {
132
+ console.log(final);
133
+ }
134
+ }
135
+ console.log();
136
+ }
137
+ else if (typeof agent.generate === "function") {
138
+ const result = await agent.generate(trimmedInput, options);
139
+ const text = typeof result === "string"
140
+ ? result
141
+ : result?.text || JSON.stringify(result, null, 2);
142
+ console.log("\nāœ… Agent Response:\n" + text);
143
+ }
144
+ else {
145
+ throw new Error("Agent does not support streaming or text generation");
146
+ }
147
+ }
148
+ catch (error) {
149
+ console.error("āŒ Error:", error);
150
+ }
151
+ }
152
+ }
153
+ finally {
154
+ rl.close();
155
+ }
156
+ }
157
+ main().catch((error) => {
158
+ console.error("āŒ Fatal error:", error);
159
+ process.exit(1);
160
+ });
@@ -0,0 +1 @@
1
+ export * from "./api/acp/index.js";
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./api/acp/index.js";
@@ -0,0 +1,2 @@
1
+ import "dotenv/config";
2
+ export declare const app: import("express-serve-static-core").Express;
package/dist/server.js ADDED
@@ -0,0 +1,38 @@
1
+ import "dotenv/config";
2
+ import express from "express";
3
+ import agentRouter from "./api/agent.js";
4
+ const port = Number(process.env.PORT || 8080);
5
+ const allowedOrigins = new Set((process.env.AGENT_ALLOWED_ORIGINS || "")
6
+ .split(",")
7
+ .map((origin) => origin.trim())
8
+ .filter(Boolean));
9
+ export const app = express();
10
+ app.disable("x-powered-by");
11
+ app.use((req, res, next) => {
12
+ const origin = req.get("origin");
13
+ if (!origin) {
14
+ return next();
15
+ }
16
+ if (!allowedOrigins.has(origin)) {
17
+ return res.status(403).json({ error: "Origin is not allowed" });
18
+ }
19
+ res.setHeader("Access-Control-Allow-Origin", origin);
20
+ res.setHeader("Vary", "Origin");
21
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Desktop-Token");
22
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
23
+ if (req.method === "OPTIONS") {
24
+ return res.sendStatus(204);
25
+ }
26
+ return next();
27
+ });
28
+ app.use(express.json({ limit: "10mb" }));
29
+ app.use(express.urlencoded({ extended: true, limit: "10mb" }));
30
+ app.get("/health", (_req, res) => {
31
+ res.json({ status: "ok" });
32
+ });
33
+ app.use("/api/agent", agentRouter);
34
+ if (import.meta.url === new URL(process.argv[1], "file:").href) {
35
+ app.listen(port, () => {
36
+ console.log(`Iris Agent listening on port ${port}`);
37
+ });
38
+ }