aws-runtime-bridge 1.9.33 → 1.9.41

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 (324) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +66 -5
  2. package/dist/adapter/AcodeSdkAdapter.d.ts.map +1 -1
  3. package/dist/adapter/AcodeSdkAdapter.js +771 -69
  4. package/dist/adapter/ClaudeSdkAdapter.d.ts +6 -0
  5. package/dist/adapter/ClaudeSdkAdapter.d.ts.map +1 -1
  6. package/dist/adapter/ClaudeSdkAdapter.js +24 -1
  7. package/dist/adapter/OpencodeSdkAdapter.d.ts +19 -0
  8. package/dist/adapter/OpencodeSdkAdapter.d.ts.map +1 -1
  9. package/dist/adapter/OpencodeSdkAdapter.js +62 -0
  10. package/dist/adapter/idle-poll-loop.d.ts +2 -1
  11. package/dist/adapter/idle-poll-loop.d.ts.map +1 -1
  12. package/dist/adapter/types.d.ts +86 -9
  13. package/dist/adapter/types.d.ts.map +1 -1
  14. package/dist/adapter/types.js +15 -5
  15. package/dist/index.js +15 -0
  16. package/dist/routes/acode-todos.d.ts +11 -0
  17. package/dist/routes/acode-todos.d.ts.map +1 -0
  18. package/dist/routes/acode-todos.js +75 -0
  19. package/dist/routes/ai-sources.js +4 -1
  20. package/dist/routes/dashboard.d.ts.map +1 -1
  21. package/dist/routes/dashboard.js +1 -1
  22. package/dist/routes/memory.d.ts +1 -1
  23. package/dist/routes/memory.d.ts.map +1 -1
  24. package/dist/routes/memory.js +3 -3
  25. package/dist/routes/pty.d.ts.map +1 -1
  26. package/dist/routes/pty.js +9 -0
  27. package/dist/routes/runtime-binding.d.ts.map +1 -1
  28. package/dist/routes/runtime-binding.js +6 -3
  29. package/dist/routes/sessions.js +89 -4
  30. package/dist/routes/sub-agents.d.ts +14 -0
  31. package/dist/routes/sub-agents.d.ts.map +1 -0
  32. package/dist/routes/sub-agents.js +267 -0
  33. package/dist/routes/terminal.d.ts +12 -1
  34. package/dist/routes/terminal.d.ts.map +1 -1
  35. package/dist/routes/terminal.js +326 -24
  36. package/dist/services/acode-package.d.ts +8 -1
  37. package/dist/services/acode-package.d.ts.map +1 -1
  38. package/dist/services/acode-package.js +33 -4
  39. package/dist/services/agent-event-store.d.ts +1 -0
  40. package/dist/services/agent-event-store.d.ts.map +1 -1
  41. package/dist/services/aws-client-agent-mcp.d.ts.map +1 -1
  42. package/dist/services/aws-client-agent-mcp.js +11 -4
  43. package/dist/services/event-delta-pusher.js +4 -4
  44. package/dist/services/fileSnapshotStore.js +1 -1
  45. package/dist/services/legacy-path-migration.d.ts +3 -0
  46. package/dist/services/legacy-path-migration.d.ts.map +1 -0
  47. package/dist/services/legacy-path-migration.js +66 -0
  48. package/dist/services/lifecycle-state.d.ts.map +1 -1
  49. package/dist/services/lifecycle-state.js +1 -1
  50. package/dist/services/runtime-binding.d.ts +5 -0
  51. package/dist/services/runtime-binding.d.ts.map +1 -1
  52. package/dist/services/runtime-binding.js +33 -1
  53. package/dist/services/session-output.d.ts +10 -1
  54. package/dist/services/session-output.d.ts.map +1 -1
  55. package/dist/services/session-output.js +54 -4
  56. package/dist/services/sub-agent-manager-instance.d.ts +4 -0
  57. package/dist/services/sub-agent-manager-instance.d.ts.map +1 -0
  58. package/dist/services/sub-agent-manager-instance.js +12 -0
  59. package/dist/services/workspace-files.d.ts +1 -0
  60. package/dist/services/workspace-files.d.ts.map +1 -1
  61. package/dist/services/workspace-files.js +57 -1
  62. package/package/acode/dist/ask-user-question-tool.d.ts +47 -0
  63. package/package/acode/dist/ask-user-question-tool.d.ts.map +1 -0
  64. package/package/acode/dist/ask-user-question-tool.js +233 -0
  65. package/package/acode/dist/built-in-file-tools.d.ts +2 -0
  66. package/package/acode/dist/built-in-file-tools.d.ts.map +1 -1
  67. package/package/acode/dist/built-in-file-tools.js +504 -3
  68. package/package/acode/dist/compaction.d.ts +242 -0
  69. package/package/acode/dist/compaction.d.ts.map +1 -0
  70. package/package/acode/dist/compaction.js +919 -0
  71. package/package/acode/dist/config.d.ts +6 -1
  72. package/package/acode/dist/config.d.ts.map +1 -1
  73. package/package/acode/dist/config.js +27 -2
  74. package/package/acode/dist/index.d.ts +4 -0
  75. package/package/acode/dist/index.d.ts.map +1 -1
  76. package/package/acode/dist/index.js +4 -0
  77. package/package/acode/dist/runtime.d.ts +257 -0
  78. package/package/acode/dist/runtime.d.ts.map +1 -1
  79. package/package/acode/dist/runtime.js +1843 -191
  80. package/package/acode/dist/skill-tool.d.ts +30 -0
  81. package/package/acode/dist/skill-tool.d.ts.map +1 -0
  82. package/package/acode/dist/skill-tool.js +174 -0
  83. package/package/acode/dist/sub-agent-manager.d.ts +264 -0
  84. package/package/acode/dist/sub-agent-manager.d.ts.map +1 -0
  85. package/package/acode/dist/sub-agent-manager.js +825 -0
  86. package/package/acode/dist/sub-agent-store.d.ts +40 -0
  87. package/package/acode/dist/sub-agent-store.d.ts.map +1 -0
  88. package/package/acode/dist/sub-agent-store.js +164 -0
  89. package/package/acode/dist/sub-agent-tools.d.ts +72 -0
  90. package/package/acode/dist/sub-agent-tools.d.ts.map +1 -0
  91. package/package/acode/dist/sub-agent-tools.js +429 -0
  92. package/package/acode/dist/sub-agent-types.d.ts +85 -0
  93. package/package/acode/dist/sub-agent-types.d.ts.map +1 -0
  94. package/package/acode/dist/sub-agent-types.js +8 -0
  95. package/package/acode/dist/todo-store.d.ts +42 -0
  96. package/package/acode/dist/todo-store.d.ts.map +1 -0
  97. package/package/acode/dist/todo-store.js +68 -0
  98. package/package/acode/dist/todo-tool.d.ts +6 -0
  99. package/package/acode/dist/todo-tool.d.ts.map +1 -0
  100. package/package/acode/dist/todo-tool.js +138 -0
  101. package/package/acode/dist/types.d.ts +41 -1
  102. package/package/acode/dist/types.d.ts.map +1 -1
  103. package/package/acode/package.json +13 -2
  104. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +9 -0
  105. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
  106. package/package/aws-client-agent-mcp/dist/agent-client.js +69 -10
  107. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
  108. package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -1
  109. package/package/aws-client-agent-mcp/dist/config.js +4 -0
  110. package/package/aws-client-agent-mcp/dist/config.js.map +1 -1
  111. package/package/aws-client-agent-mcp/dist/constants.d.ts +2 -0
  112. package/package/aws-client-agent-mcp/dist/constants.d.ts.map +1 -1
  113. package/package/aws-client-agent-mcp/dist/constants.js +3 -1
  114. package/package/aws-client-agent-mcp/dist/constants.js.map +1 -1
  115. package/package/aws-client-agent-mcp/dist/context-manager.d.ts +4 -1
  116. package/package/aws-client-agent-mcp/dist/context-manager.d.ts.map +1 -1
  117. package/package/aws-client-agent-mcp/dist/context-manager.js +6 -2
  118. package/package/aws-client-agent-mcp/dist/context-manager.js.map +1 -1
  119. package/package/aws-client-agent-mcp/dist/context-manager.test.js +5 -3
  120. package/package/aws-client-agent-mcp/dist/context-manager.test.js.map +1 -1
  121. package/package/aws-client-agent-mcp/dist/http-client.d.ts +5 -0
  122. package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
  123. package/package/aws-client-agent-mcp/dist/http-client.js +15 -1
  124. package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
  125. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +162 -71
  126. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
  127. package/package/aws-client-agent-mcp/dist/mcp-server.js +1007 -504
  128. package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
  129. package/package/aws-client-agent-mcp/dist/mcp-server.test.js +371 -253
  130. package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -1
  131. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +6 -17
  132. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -1
  133. package/package/aws-client-agent-mcp/dist/mcp-tools.js +20 -75
  134. package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -1
  135. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +45 -45
  136. package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +1 -1
  137. package/package/aws-client-agent-mcp/dist/memory-store.js +114 -162
  138. package/package/aws-client-agent-mcp/dist/memory-store.js.map +1 -1
  139. package/package/aws-client-agent-mcp/dist/memory-store.test.js +175 -164
  140. package/package/aws-client-agent-mcp/dist/memory-store.test.js.map +1 -1
  141. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts +3 -9
  142. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts.map +1 -1
  143. package/package/aws-client-agent-mcp/dist/memory-tools.js +31 -58
  144. package/package/aws-client-agent-mcp/dist/memory-tools.js.map +1 -1
  145. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +40 -9
  146. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts.map +1 -1
  147. package/package/aws-client-agent-mcp/dist/message-buffer.js +123 -23
  148. package/package/aws-client-agent-mcp/dist/message-buffer.js.map +1 -1
  149. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +13 -13
  150. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts.map +1 -1
  151. package/package/aws-client-agent-mcp/dist/server-memory-store.js +23 -16
  152. package/package/aws-client-agent-mcp/dist/server-memory-store.js.map +1 -1
  153. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts.map +1 -1
  154. package/package/aws-client-agent-mcp/dist/status-reporter.js +8 -5
  155. package/package/aws-client-agent-mcp/dist/status-reporter.js.map +1 -1
  156. package/package/aws-client-agent-mcp/dist/status-reporter.test.js +93 -0
  157. package/package/aws-client-agent-mcp/dist/status-reporter.test.js.map +1 -1
  158. package/package/aws-client-agent-mcp/dist/types.d.ts +12 -25
  159. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
  160. package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
  161. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +34 -1
  162. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
  163. package/package/aws-client-agent-mcp/dist/websocket-client.js +146 -18
  164. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
  165. package/package.json +17 -7
  166. package/dist/adapter/AcodeSdkAdapter.test.d.ts +0 -2
  167. package/dist/adapter/AcodeSdkAdapter.test.d.ts.map +0 -1
  168. package/dist/adapter/AcodeSdkAdapter.test.js +0 -2000
  169. package/dist/adapter/AdapterRegistry.test.d.ts +0 -5
  170. package/dist/adapter/AdapterRegistry.test.d.ts.map +0 -1
  171. package/dist/adapter/AdapterRegistry.test.js +0 -118
  172. package/dist/adapter/ClaudeSdkAdapter.test.d.ts +0 -2
  173. package/dist/adapter/ClaudeSdkAdapter.test.d.ts.map +0 -1
  174. package/dist/adapter/ClaudeSdkAdapter.test.js +0 -311
  175. package/dist/adapter/CodexSdkAdapter.test.d.ts +0 -2
  176. package/dist/adapter/CodexSdkAdapter.test.d.ts.map +0 -1
  177. package/dist/adapter/CodexSdkAdapter.test.js +0 -270
  178. package/dist/adapter/OpencodeSdkAdapter.test.d.ts +0 -2
  179. package/dist/adapter/OpencodeSdkAdapter.test.d.ts.map +0 -1
  180. package/dist/adapter/OpencodeSdkAdapter.test.js +0 -158
  181. package/dist/adapter/acode-tool-names.test.d.ts +0 -2
  182. package/dist/adapter/acode-tool-names.test.d.ts.map +0 -1
  183. package/dist/adapter/acode-tool-names.test.js +0 -28
  184. package/dist/adapter/adapter.test.d.ts +0 -5
  185. package/dist/adapter/adapter.test.d.ts.map +0 -1
  186. package/dist/adapter/adapter.test.js +0 -180
  187. package/dist/adapter/idle-poll-loop.test.d.ts +0 -2
  188. package/dist/adapter/idle-poll-loop.test.d.ts.map +0 -1
  189. package/dist/adapter/idle-poll-loop.test.js +0 -85
  190. package/dist/adapter/types.test.d.ts +0 -2
  191. package/dist/adapter/types.test.d.ts.map +0 -1
  192. package/dist/adapter/types.test.js +0 -50
  193. package/dist/adapters/cc-switch/mcp-acode.test.d.ts +0 -2
  194. package/dist/adapters/cc-switch/mcp-acode.test.d.ts.map +0 -1
  195. package/dist/adapters/cc-switch/mcp-acode.test.js +0 -80
  196. package/dist/adapters/cc-switch/mcp-claudecode.test.d.ts +0 -2
  197. package/dist/adapters/cc-switch/mcp-claudecode.test.d.ts.map +0 -1
  198. package/dist/adapters/cc-switch/mcp-claudecode.test.js +0 -75
  199. package/dist/adapters/cc-switch/mcp-codex.test.d.ts +0 -2
  200. package/dist/adapters/cc-switch/mcp-codex.test.d.ts.map +0 -1
  201. package/dist/adapters/cc-switch/mcp-codex.test.js +0 -126
  202. package/dist/adapters/cc-switch/mcp-opencode.test.d.ts +0 -2
  203. package/dist/adapters/cc-switch/mcp-opencode.test.d.ts.map +0 -1
  204. package/dist/adapters/cc-switch/mcp-opencode.test.js +0 -62
  205. package/dist/adapters/cc-switch/skill-directory.test.d.ts +0 -2
  206. package/dist/adapters/cc-switch/skill-directory.test.d.ts.map +0 -1
  207. package/dist/adapters/cc-switch/skill-directory.test.js +0 -74
  208. package/dist/config.test.d.ts +0 -2
  209. package/dist/config.test.d.ts.map +0 -1
  210. package/dist/config.test.js +0 -107
  211. package/dist/routes/ai-sources.test.d.ts +0 -2
  212. package/dist/routes/ai-sources.test.d.ts.map +0 -1
  213. package/dist/routes/ai-sources.test.js +0 -169
  214. package/dist/routes/file-browser.test.d.ts +0 -5
  215. package/dist/routes/file-browser.test.d.ts.map +0 -1
  216. package/dist/routes/file-browser.test.js +0 -155
  217. package/dist/routes/git.test.d.ts +0 -2
  218. package/dist/routes/git.test.d.ts.map +0 -1
  219. package/dist/routes/git.test.js +0 -330
  220. package/dist/routes/instance.test.d.ts +0 -5
  221. package/dist/routes/instance.test.d.ts.map +0 -1
  222. package/dist/routes/instance.test.js +0 -389
  223. package/dist/routes/mcp.test.d.ts +0 -5
  224. package/dist/routes/mcp.test.d.ts.map +0 -1
  225. package/dist/routes/mcp.test.js +0 -92
  226. package/dist/routes/memory-route-wiring.test.d.ts +0 -2
  227. package/dist/routes/memory-route-wiring.test.d.ts.map +0 -1
  228. package/dist/routes/memory-route-wiring.test.js +0 -15
  229. package/dist/routes/memory.test.d.ts +0 -2
  230. package/dist/routes/memory.test.d.ts.map +0 -1
  231. package/dist/routes/memory.test.js +0 -177
  232. package/dist/routes/properties.test.d.ts +0 -5
  233. package/dist/routes/properties.test.d.ts.map +0 -1
  234. package/dist/routes/properties.test.js +0 -72
  235. package/dist/routes/pty.test.d.ts +0 -2
  236. package/dist/routes/pty.test.d.ts.map +0 -1
  237. package/dist/routes/pty.test.js +0 -82
  238. package/dist/routes/runtime-binding.test.d.ts +0 -2
  239. package/dist/routes/runtime-binding.test.d.ts.map +0 -1
  240. package/dist/routes/runtime-binding.test.js +0 -32
  241. package/dist/routes/sessions.test.d.ts +0 -5
  242. package/dist/routes/sessions.test.d.ts.map +0 -1
  243. package/dist/routes/sessions.test.js +0 -86
  244. package/dist/routes/skills.test.d.ts +0 -5
  245. package/dist/routes/skills.test.d.ts.map +0 -1
  246. package/dist/routes/skills.test.js +0 -50
  247. package/dist/routes/system-metrics.test.d.ts +0 -2
  248. package/dist/routes/system-metrics.test.d.ts.map +0 -1
  249. package/dist/routes/system-metrics.test.js +0 -16
  250. package/dist/routes/terminal.stop-options.test.d.ts +0 -2
  251. package/dist/routes/terminal.stop-options.test.d.ts.map +0 -1
  252. package/dist/routes/terminal.stop-options.test.js +0 -39
  253. package/dist/routes/terminal.test.d.ts +0 -2
  254. package/dist/routes/terminal.test.d.ts.map +0 -1
  255. package/dist/routes/terminal.test.js +0 -746
  256. package/dist/routes/yml.test.d.ts +0 -5
  257. package/dist/routes/yml.test.d.ts.map +0 -1
  258. package/dist/routes/yml.test.js +0 -58
  259. package/dist/services/ai-source-apply.test.d.ts +0 -2
  260. package/dist/services/ai-source-apply.test.d.ts.map +0 -1
  261. package/dist/services/ai-source-apply.test.js +0 -138
  262. package/dist/services/auto-register.test.d.ts +0 -2
  263. package/dist/services/auto-register.test.d.ts.map +0 -1
  264. package/dist/services/auto-register.test.js +0 -184
  265. package/dist/services/aws-client-agent-mcp.test.d.ts +0 -2
  266. package/dist/services/aws-client-agent-mcp.test.d.ts.map +0 -1
  267. package/dist/services/aws-client-agent-mcp.test.js +0 -242
  268. package/dist/services/bridge-package-publish-hooks.test.d.ts +0 -2
  269. package/dist/services/bridge-package-publish-hooks.test.d.ts.map +0 -1
  270. package/dist/services/bridge-package-publish-hooks.test.js +0 -136
  271. package/dist/services/cc-switch-discovery.test.d.ts +0 -2
  272. package/dist/services/cc-switch-discovery.test.d.ts.map +0 -1
  273. package/dist/services/cc-switch-discovery.test.js +0 -56
  274. package/dist/services/cli-commands.test.d.ts +0 -2
  275. package/dist/services/cli-commands.test.d.ts.map +0 -1
  276. package/dist/services/cli-commands.test.js +0 -230
  277. package/dist/services/instance-init-service.test.d.ts +0 -2
  278. package/dist/services/instance-init-service.test.d.ts.map +0 -1
  279. package/dist/services/instance-init-service.test.js +0 -140
  280. package/dist/services/instance-state.test.d.ts +0 -2
  281. package/dist/services/instance-state.test.d.ts.map +0 -1
  282. package/dist/services/instance-state.test.js +0 -245
  283. package/dist/services/mcp-launch-binding-queue.test.d.ts +0 -2
  284. package/dist/services/mcp-launch-binding-queue.test.d.ts.map +0 -1
  285. package/dist/services/mcp-launch-binding-queue.test.js +0 -181
  286. package/dist/services/runtime-binding.test.d.ts +0 -2
  287. package/dist/services/runtime-binding.test.d.ts.map +0 -1
  288. package/dist/services/runtime-binding.test.js +0 -78
  289. package/dist/services/runtime-lifecycle-policy.test.d.ts +0 -2
  290. package/dist/services/runtime-lifecycle-policy.test.d.ts.map +0 -1
  291. package/dist/services/runtime-lifecycle-policy.test.js +0 -41
  292. package/dist/services/session-output.test.d.ts +0 -5
  293. package/dist/services/session-output.test.d.ts.map +0 -1
  294. package/dist/services/session-output.test.js +0 -177
  295. package/dist/services/startup-config-wizard.test.d.ts +0 -2
  296. package/dist/services/startup-config-wizard.test.d.ts.map +0 -1
  297. package/dist/services/startup-config-wizard.test.js +0 -184
  298. package/dist/services/terminal-persistence.test.d.ts +0 -5
  299. package/dist/services/terminal-persistence.test.d.ts.map +0 -1
  300. package/dist/services/terminal-persistence.test.js +0 -159
  301. package/dist/services/tool-installer.test.d.ts +0 -2
  302. package/dist/services/tool-installer.test.d.ts.map +0 -1
  303. package/dist/services/tool-installer.test.js +0 -225
  304. package/dist/services/workspace-files.test.d.ts +0 -2
  305. package/dist/services/workspace-files.test.d.ts.map +0 -1
  306. package/dist/services/workspace-files.test.js +0 -648
  307. package/dist/services/workspace-watch.test.d.ts +0 -2
  308. package/dist/services/workspace-watch.test.d.ts.map +0 -1
  309. package/dist/services/workspace-watch.test.js +0 -38
  310. package/dist/utils/file-utils.test.d.ts +0 -2
  311. package/dist/utils/file-utils.test.d.ts.map +0 -1
  312. package/dist/utils/file-utils.test.js +0 -244
  313. package/dist/utils/logger.test.d.ts +0 -2
  314. package/dist/utils/logger.test.d.ts.map +0 -1
  315. package/dist/utils/logger.test.js +0 -93
  316. package/dist/utils/sdk-package-loader.test.d.ts +0 -2
  317. package/dist/utils/sdk-package-loader.test.d.ts.map +0 -1
  318. package/dist/utils/sdk-package-loader.test.js +0 -84
  319. package/dist/utils/validation.test.d.ts +0 -2
  320. package/dist/utils/validation.test.d.ts.map +0 -1
  321. package/dist/utils/validation.test.js +0 -88
  322. package/dist/utils/yaml-utils.test.d.ts +0 -2
  323. package/dist/utils/yaml-utils.test.d.ts.map +0 -1
  324. package/dist/utils/yaml-utils.test.js +0 -363
@@ -1,7 +1,36 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { promises as fs } from "node:fs";
2
+ import { promises as fs, createReadStream } from "node:fs";
3
3
  import path from "node:path";
4
+ import readline from "node:readline";
4
5
  import { runShellCommand, } from "./builtins/shellCommandRunner.js";
6
+ // ── read_file pagination & truncation constants ──────────────────────────────
7
+ const DEFAULT_READ_LIMIT = 2000;
8
+ const MAX_LINE_LENGTH = 2000;
9
+ const MAX_READ_BYTES = 50 * 1024; // 50 KB
10
+ const BINARY_SAMPLE_BYTES = 4096;
11
+ const BINARY_NON_PRINTABLE_RATIO = 0.3;
12
+ const BINARY_EXTENSIONS = new Set([
13
+ ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".webp", ".tiff", ".tif",
14
+ ".zip", ".gz", ".tar", ".rar", ".7z", ".bz2", ".xz", ".lz",
15
+ ".exe", ".dll", ".so", ".dylib", ".bin", ".o", ".a",
16
+ ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx",
17
+ ".mp3", ".mp4", ".avi", ".mov", ".wav", ".flv", ".mkv", ".ogg",
18
+ ".woff", ".woff2", ".ttf", ".otf", ".eot",
19
+ ".class", ".jar", ".war", ".ear",
20
+ ".pyc", ".pyo", ".node",
21
+ ".sqlite", ".db", ".mdb",
22
+ ".wasm",
23
+ ]);
24
+ // ─────────────────────────────────────────────────────────────────────────────
25
+ // ── grep search constants ────────────────────────────────────────────────────
26
+ const MAX_GREP_FILES = 1000;
27
+ const MAX_GREP_FILE_SIZE = 1024 * 1024; // 1 MB – skip larger files
28
+ const MAX_GREP_OUTPUT_BYTES = 256 * 1024; // 256 KB – cap total output
29
+ const DEFAULT_GREP_MAX_RESULTS = 1000;
30
+ const GREP_SKIP_DIRS = new Set([
31
+ ".git", "node_modules", "dist", "build", ".next", ".nuxt",
32
+ ".cache", ".turbo", ".output", "coverage", ".nyc_output",
33
+ ]);
5
34
  function toDisplayPath(targetPath) {
6
35
  return targetPath.replace(/\\/g, "/");
7
36
  }
@@ -58,6 +87,42 @@ function readOptionalPositiveIntegerArg(args, names, fallback) {
58
87
  }
59
88
  return fallback;
60
89
  }
90
+ /**
91
+ * 检测文件是否为二进制文件。
92
+ * 主流程:先查扩展名黑名单 -> 再采样前 4KB 检测 NUL 字节或高比例不可见字符。
93
+ */
94
+ async function isBinaryFile(filePath) {
95
+ const ext = path.extname(filePath).toLowerCase();
96
+ if (BINARY_EXTENSIONS.has(ext)) {
97
+ return true;
98
+ }
99
+ const handle = await fs.open(filePath, "r");
100
+ try {
101
+ const buffer = Buffer.alloc(BINARY_SAMPLE_BYTES);
102
+ const { bytesRead } = await handle.read(buffer, 0, BINARY_SAMPLE_BYTES, 0);
103
+ if (bytesRead === 0) {
104
+ return false;
105
+ }
106
+ const sample = buffer.subarray(0, bytesRead);
107
+ // NUL byte = definitely binary
108
+ if (sample.includes(0)) {
109
+ return true;
110
+ }
111
+ // >30% non-printable characters = likely binary
112
+ let nonPrintable = 0;
113
+ for (let i = 0; i < bytesRead; i++) {
114
+ const byte = sample[i];
115
+ // Allow: tab(0x09), LF(0x0a), CR(0x0d), printable ASCII (0x20-0x7e), UTF-8 high bytes (0x80-0xff)
116
+ if (byte < 0x09 || (byte > 0x0d && byte < 0x20)) {
117
+ nonPrintable++;
118
+ }
119
+ }
120
+ return nonPrintable / bytesRead > BINARY_NON_PRINTABLE_RATIO;
121
+ }
122
+ finally {
123
+ await handle.close();
124
+ }
125
+ }
61
126
  function ensureInsideWorkspace(workspaceRoot, targetPath) {
62
127
  const resolvedTargetPath = path.resolve(targetPath);
63
128
  const relativePath = path.relative(workspaceRoot, resolvedTargetPath);
@@ -178,6 +243,249 @@ async function readFileInsideWorkspace(workingDirectory, filePath) {
178
243
  content: await fs.readFile(realTargetPath, "utf-8"),
179
244
  };
180
245
  }
246
+ /**
247
+ * 分页流式读取工作区内文本文件,带行号前缀、双重截断上限和续读提示。
248
+ *
249
+ * 主流程:
250
+ * 1. 路径解析与安全校验(复用 resolveWorkspaceTarget + ensureInsideWorkspace + realpath)
251
+ * 2. 二进制检测(扩展名黑名单 + 4KB 采样)
252
+ * 3. createReadStream + readline 逐行流式读取,跳过 offset 前行
253
+ * 4. 收集 limit 行,同时持续计数总行数(用于底部提示)
254
+ * 5. 双重上限:行数 2000 + 字节 50KB,先触发先截断
255
+ * 6. 拼装行号前缀 + 底部续读提示
256
+ *
257
+ * 不修改 readFileInsideWorkspace,edit_file 仍使用全量读取。
258
+ */
259
+ async function readFileWithPagination(workingDirectory, filePath, offset, limit) {
260
+ const target = await resolveWorkspaceTarget(workingDirectory, filePath);
261
+ const realTargetPath = ensureInsideWorkspace(target.workspaceRoot, await fs.realpath(target.targetPath));
262
+ const stat = await fs.stat(realTargetPath);
263
+ if (!stat.isFile()) {
264
+ throw new Error(`Path is not a file: ${realTargetPath}`);
265
+ }
266
+ // ── 二进制检测 ──
267
+ if (await isBinaryFile(realTargetPath)) {
268
+ return {
269
+ workspaceRoot: target.workspaceRoot,
270
+ targetPath: realTargetPath,
271
+ content: "[Binary file, content skipped]",
272
+ isBinary: true,
273
+ truncated: false,
274
+ totalLines: 0,
275
+ shownFromLine: 0,
276
+ shownToLine: 0,
277
+ };
278
+ }
279
+ // ── 流式逐行读取 ──
280
+ const stream = createReadStream(realTargetPath, { encoding: "utf-8" });
281
+ const rl = readline.createInterface({
282
+ input: stream,
283
+ crlfDelay: Infinity,
284
+ });
285
+ try {
286
+ const outputLines = [];
287
+ let lineNumber = 0; // 0-indexed 内部计数
288
+ let totalLines = 0;
289
+ let bytes = 0;
290
+ let truncatedByLines = false;
291
+ let truncatedByBytes = false;
292
+ const startIndex = offset - 1; // 转为 0-indexed
293
+ for await (const text of rl) {
294
+ totalLines++;
295
+ // 跳过 offset 前的行
296
+ if (lineNumber < startIndex) {
297
+ lineNumber++;
298
+ continue;
299
+ }
300
+ // 已达 limit 上限:停止收集但继续计数
301
+ if (outputLines.length >= limit) {
302
+ truncatedByLines = true;
303
+ lineNumber++;
304
+ continue;
305
+ }
306
+ // 单行截断
307
+ let line = text;
308
+ if (line.length > MAX_LINE_LENGTH) {
309
+ line =
310
+ line.slice(0, MAX_LINE_LENGTH) +
311
+ `... (line truncated to ${MAX_LINE_LENGTH} chars)`;
312
+ }
313
+ const numberedLine = `${lineNumber + 1}: ${line}`;
314
+ const lineBytes = Buffer.byteLength(numberedLine, "utf-8") + 1; // +1 for \n
315
+ // 字节上限:停止读取(totalLines 不再准确)
316
+ if (bytes + lineBytes > MAX_READ_BYTES) {
317
+ truncatedByBytes = true;
318
+ break;
319
+ }
320
+ outputLines.push(numberedLine);
321
+ bytes += lineBytes;
322
+ lineNumber++;
323
+ }
324
+ // offset 超出文件总行数(空文件除外)
325
+ if (totalLines > 0 &&
326
+ outputLines.length === 0 &&
327
+ !truncatedByLines &&
328
+ !truncatedByBytes &&
329
+ startIndex >= totalLines) {
330
+ throw new Error(`offset ${offset} exceeds total line count ${totalLines} in file: ${realTargetPath}`);
331
+ }
332
+ const shownFromLine = outputLines.length > 0 ? offset : 0;
333
+ const shownToLine = outputLines.length > 0 ? offset + outputLines.length - 1 : 0;
334
+ // ── 底部续读提示 ──
335
+ let footer;
336
+ if (truncatedByBytes) {
337
+ footer = `Output capped at 50 KB. Showing lines ${shownFromLine}-${shownToLine}. Use offset=${shownToLine + 1} to continue.`;
338
+ }
339
+ else if (truncatedByLines) {
340
+ footer = `Showing lines ${shownFromLine}-${shownToLine} of ${totalLines}. Use offset=${shownToLine + 1} to continue.`;
341
+ }
342
+ else {
343
+ footer = `End of file - total ${totalLines} lines`;
344
+ }
345
+ const content = outputLines.length > 0
346
+ ? outputLines.join("\n") + "\n" + footer
347
+ : footer;
348
+ return {
349
+ workspaceRoot: target.workspaceRoot,
350
+ targetPath: realTargetPath,
351
+ content,
352
+ isBinary: false,
353
+ truncated: truncatedByLines || truncatedByBytes,
354
+ totalLines: truncatedByBytes ? -1 : totalLines,
355
+ shownFromLine,
356
+ shownToLine,
357
+ };
358
+ }
359
+ finally {
360
+ rl.close();
361
+ stream.destroy();
362
+ }
363
+ }
364
+ // ── grep helpers ──────────────────────────────────────────────────────────────
365
+ /**
366
+ * 将 glob 通配符转换为 RegExp(匹配文件 basename)。
367
+ * 支持:* (不跨 / ), ? (单个非 / 字符), {a,b} (分组), [abc] (字符类)。
368
+ */
369
+ function globToRegex(pattern) {
370
+ let regex = "";
371
+ let i = 0;
372
+ while (i < pattern.length) {
373
+ const char = pattern[i];
374
+ if (char === "*") {
375
+ regex += "[^/]*";
376
+ }
377
+ else if (char === "?") {
378
+ regex += "[^/]";
379
+ }
380
+ else if (char === "{") {
381
+ const end = pattern.indexOf("}", i);
382
+ if (end >= 0) {
383
+ const content = pattern.slice(i + 1, end);
384
+ regex += `(${content.split(",").join("|")})`;
385
+ i = end;
386
+ }
387
+ else {
388
+ regex += "\\{";
389
+ }
390
+ }
391
+ else if (char === "[") {
392
+ const end = pattern.indexOf("]", i);
393
+ if (end >= 0) {
394
+ regex += pattern.slice(i, end + 1);
395
+ i = end;
396
+ }
397
+ else {
398
+ regex += "\\[";
399
+ }
400
+ }
401
+ else if ("+^$.()|\\".includes(char)) {
402
+ regex += "\\" + char;
403
+ }
404
+ else {
405
+ regex += char;
406
+ }
407
+ i++;
408
+ }
409
+ return new RegExp(`^${regex}$`);
410
+ }
411
+ /**
412
+ * 递归遍历目录,返回所有匹配 include/exclude 的文件路径。
413
+ * 主流程:readdir -> 跳过 GREP_SKIP_DIRS 和隐藏目录 -> 递归子目录 -> 过滤文件名。
414
+ */
415
+ async function walkDirectory(dir, includeRegex, excludeRegex, maxFiles) {
416
+ const results = [];
417
+ async function walk(currentDir) {
418
+ if (results.length >= maxFiles)
419
+ return;
420
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
421
+ for (const entry of entries) {
422
+ if (results.length >= maxFiles)
423
+ return;
424
+ if (entry.name.startsWith(".") && entry.isDirectory())
425
+ continue;
426
+ const fullPath = path.join(currentDir, entry.name);
427
+ if (entry.isDirectory()) {
428
+ if (GREP_SKIP_DIRS.has(entry.name))
429
+ continue;
430
+ await walk(fullPath);
431
+ }
432
+ else if (entry.isFile()) {
433
+ if (includeRegex && !includeRegex.test(entry.name))
434
+ continue;
435
+ if (excludeRegex && excludeRegex.test(entry.name))
436
+ continue;
437
+ results.push(fullPath);
438
+ }
439
+ }
440
+ }
441
+ await walk(dir);
442
+ return results;
443
+ }
444
+ /**
445
+ * 在单个文件中搜索正则匹配,返回匹配行(含行号)或计数。
446
+ * 主流程:文件大小检查 -> 二进制检测 -> 流式逐行读取 -> 正则匹配 -> 收集结果。
447
+ */
448
+ async function searchInFile(filePath, workspaceRoot, options) {
449
+ const stat = await fs.stat(filePath);
450
+ if (stat.size > MAX_GREP_FILE_SIZE) {
451
+ return { matches: [], count: 0 };
452
+ }
453
+ if (await isBinaryFile(filePath)) {
454
+ return { matches: [], count: 0 };
455
+ }
456
+ const relativePath = path.relative(workspaceRoot, filePath).replace(/\\/g, "/");
457
+ const matches = [];
458
+ let count = 0;
459
+ const stream = createReadStream(filePath, { encoding: "utf-8" });
460
+ const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
461
+ try {
462
+ let lineNumber = 0;
463
+ for await (const text of rl) {
464
+ lineNumber++;
465
+ if (options.regex.test(text)) {
466
+ count++;
467
+ if (options.collectContent) {
468
+ let content = text;
469
+ if (content.length > MAX_LINE_LENGTH) {
470
+ content =
471
+ content.slice(0, MAX_LINE_LENGTH) +
472
+ `... (line truncated to ${MAX_LINE_LENGTH} chars)`;
473
+ }
474
+ matches.push({ file: relativePath, line: lineNumber, content });
475
+ if (matches.length >= options.maxResults)
476
+ break;
477
+ }
478
+ if (options.stopOnFirstMatch)
479
+ break;
480
+ }
481
+ }
482
+ }
483
+ finally {
484
+ rl.close();
485
+ stream.destroy();
486
+ }
487
+ return { matches, count };
488
+ }
181
489
  const MAX_COMMAND_TIMEOUT_MS = 10 * 60_000;
182
490
  const DEFAULT_COMMAND_TIMEOUT_MS = MAX_COMMAND_TIMEOUT_MS;
183
491
  const DEFAULT_COMMAND_INACTIVITY_TIMEOUT_MS = 60_000;
@@ -273,7 +581,12 @@ function readFileTool(workingDirectory) {
273
581
  kind: "builtin",
274
582
  toolName: "read_file",
275
583
  exposedName: "read_file",
276
- description: "Read a UTF-8 text file inside the current workspace.",
584
+ description: "Read a UTF-8 text file inside the current workspace. " +
585
+ "Returns content with line numbers in the format '<line>: <content>'. " +
586
+ "Supports offset (1-indexed line number to start from) and limit (max lines to return, default 2000). " +
587
+ "Output is capped at 2000 lines or 50 KB, whichever is reached first. " +
588
+ "Individual lines longer than 2000 characters are truncated. " +
589
+ "Avoid tiny repeated slices (e.g. 30-line chunks); read a larger window if more context is needed.",
277
590
  inputSchema: {
278
591
  type: "object",
279
592
  properties: {
@@ -281,19 +594,34 @@ function readFileTool(workingDirectory) {
281
594
  type: "string",
282
595
  description: "Workspace-relative file path to read.",
283
596
  },
597
+ offset: {
598
+ type: "number",
599
+ description: "Line number to start reading from (1-indexed). Defaults to 1.",
600
+ },
601
+ limit: {
602
+ type: "number",
603
+ description: "Maximum number of lines to return. Defaults to 2000.",
604
+ },
284
605
  },
285
606
  required: ["file_path"],
286
607
  additionalProperties: false,
287
608
  },
288
609
  async execute(args) {
289
610
  const filePath = readStringArg(args, ["file_path", "filePath"], "file_path");
290
- const result = await readFileInsideWorkspace(workingDirectory, filePath);
611
+ const offset = readOptionalPositiveIntegerArg(args, ["offset"], 1);
612
+ const limit = readOptionalPositiveIntegerArg(args, ["limit"], DEFAULT_READ_LIMIT);
613
+ const result = await readFileWithPagination(workingDirectory, filePath, offset, limit);
291
614
  return {
292
615
  ok: true,
293
616
  tool: "read_file",
294
617
  workspacePath: toDisplayPath(result.workspaceRoot),
295
618
  filePath: toDisplayPath(result.targetPath),
296
619
  content: result.content,
620
+ isBinary: result.isBinary,
621
+ truncated: result.truncated,
622
+ totalLines: result.totalLines,
623
+ shownFromLine: result.shownFromLine,
624
+ shownToLine: result.shownToLine,
297
625
  };
298
626
  },
299
627
  };
@@ -371,12 +699,185 @@ function bashTool(workingDirectory, agentId) {
371
699
  },
372
700
  };
373
701
  }
702
+ function grepTool(workingDirectory) {
703
+ return {
704
+ kind: "builtin",
705
+ toolName: "grep",
706
+ exposedName: "grep",
707
+ description: "Search file contents using regular expressions within the workspace. " +
708
+ "Returns matched lines with file paths and line numbers. " +
709
+ "Supports include/exclude glob patterns, case-insensitive matching, and three output modes " +
710
+ "(content, files_with_matches, count). Searches recursively through directories, " +
711
+ "skipping binary files, hidden directories, and common build/dependency directories (node_modules, .git, dist, etc.).",
712
+ inputSchema: {
713
+ type: "object",
714
+ properties: {
715
+ pattern: {
716
+ type: "string",
717
+ description: "Regular expression pattern to search for in file contents.",
718
+ },
719
+ path: {
720
+ type: "string",
721
+ description: "Workspace-relative file or directory path to search in. Defaults to the workspace root.",
722
+ },
723
+ include: {
724
+ type: "string",
725
+ description: "Glob pattern to filter files by name (e.g. '*.ts', '*.{js,ts}'). Only matching files are searched.",
726
+ },
727
+ exclude: {
728
+ type: "string",
729
+ description: "Glob pattern to exclude files by name (e.g. '*.test.ts'). Matching files are skipped.",
730
+ },
731
+ case_insensitive: {
732
+ type: "boolean",
733
+ description: "Case-insensitive matching. Default false.",
734
+ },
735
+ output_mode: {
736
+ type: "string",
737
+ enum: ["content", "files_with_matches", "count"],
738
+ description: "Output format: 'content' returns matched lines with line numbers (default), " +
739
+ "'files_with_matches' returns only file paths with matches, " +
740
+ "'count' returns match counts per file.",
741
+ },
742
+ max_results: {
743
+ type: "number",
744
+ description: "Maximum number of matched lines to return (content mode). Default 1000.",
745
+ },
746
+ },
747
+ required: ["pattern"],
748
+ additionalProperties: false,
749
+ },
750
+ /**
751
+ * grep 工具执行主流程:
752
+ * 1. 解析参数(pattern, path, include/exclude, output_mode 等)
753
+ * 2. 编译正则(含 case_insensitive 标志)
754
+ * 3. 解析搜索路径并校验 workspace 边界
755
+ * 4. 收集待搜索文件列表(单文件或递归遍历目录)
756
+ * 5. 逐文件搜索(流式读取 + 正则匹配)
757
+ * 6. 根据 output_mode 构建响应
758
+ */
759
+ async execute(args) {
760
+ const pattern = readStringArg(args, ["pattern"], "pattern");
761
+ const searchPath = readOptionalStringArg(args, ["path"]) || ".";
762
+ const includeGlob = readOptionalStringArg(args, ["include"]);
763
+ const excludeGlob = readOptionalStringArg(args, ["exclude"]);
764
+ const caseInsensitive = args.case_insensitive === true;
765
+ const outputMode = (() => {
766
+ const mode = args.output_mode;
767
+ if (mode === "files_with_matches" || mode === "count")
768
+ return mode;
769
+ return "content";
770
+ })();
771
+ const maxResults = readOptionalPositiveIntegerArg(args, ["max_results"], DEFAULT_GREP_MAX_RESULTS);
772
+ // ── 编译正则 ──
773
+ const flags = caseInsensitive ? "i" : "";
774
+ let regex;
775
+ try {
776
+ regex = new RegExp(pattern, flags);
777
+ }
778
+ catch (error) {
779
+ throw new Error(`Invalid regex pattern: ${error instanceof Error ? error.message : String(error)}`);
780
+ }
781
+ const includeRegex = includeGlob ? globToRegex(includeGlob) : null;
782
+ const excludeRegex = excludeGlob ? globToRegex(excludeGlob) : null;
783
+ // ── 解析搜索路径(复用 workspace 安全校验) ──
784
+ const target = await resolveWorkspaceTarget(workingDirectory, searchPath);
785
+ const realTargetPath = ensureInsideWorkspace(target.workspaceRoot, await fs.realpath(target.targetPath));
786
+ const targetStat = await fs.stat(realTargetPath);
787
+ // ── 收集文件列表 ──
788
+ let files;
789
+ if (targetStat.isFile()) {
790
+ files = [realTargetPath];
791
+ }
792
+ else if (targetStat.isDirectory()) {
793
+ files = await walkDirectory(realTargetPath, includeRegex, excludeRegex, MAX_GREP_FILES);
794
+ }
795
+ else {
796
+ throw new Error(`Path is neither a file nor a directory: ${realTargetPath}`);
797
+ }
798
+ // ── 逐文件搜索 ──
799
+ const allMatches = [];
800
+ const fileCounts = [];
801
+ const matchedFiles = [];
802
+ let totalMatches = 0;
803
+ let outputBytes = 0;
804
+ let truncated = false;
805
+ for (const filePath of files) {
806
+ // content 模式:全局 maxResults 上限
807
+ if (outputMode === "content" && allMatches.length >= maxResults) {
808
+ truncated = true;
809
+ break;
810
+ }
811
+ const searchOptions = {
812
+ regex,
813
+ maxResults: outputMode === "content"
814
+ ? maxResults - allMatches.length
815
+ : Number.MAX_SAFE_INTEGER,
816
+ collectContent: outputMode === "content",
817
+ stopOnFirstMatch: outputMode === "files_with_matches",
818
+ };
819
+ const result = await searchInFile(filePath, target.workspaceRoot, searchOptions);
820
+ if (result.count > 0) {
821
+ const relativePath = path
822
+ .relative(target.workspaceRoot, filePath)
823
+ .replace(/\\/g, "/");
824
+ matchedFiles.push(relativePath);
825
+ totalMatches += result.count;
826
+ if (outputMode === "content") {
827
+ for (const match of result.matches) {
828
+ const matchBytes = Buffer.byteLength(match.content, "utf-8") + 64;
829
+ if (outputBytes + matchBytes > MAX_GREP_OUTPUT_BYTES) {
830
+ truncated = true;
831
+ break;
832
+ }
833
+ outputBytes += matchBytes;
834
+ allMatches.push(match);
835
+ }
836
+ if (truncated)
837
+ break;
838
+ // max_results 截断:收集完本文件匹配后检查是否已达上限
839
+ if (allMatches.length >= maxResults) {
840
+ truncated = true;
841
+ break;
842
+ }
843
+ }
844
+ else if (outputMode === "count") {
845
+ fileCounts.push({ file: relativePath, count: result.count });
846
+ }
847
+ }
848
+ }
849
+ // ── 构建响应 ──
850
+ const response = {
851
+ ok: true,
852
+ tool: "grep",
853
+ pattern,
854
+ searchPath: toDisplayPath(target.targetPath),
855
+ outputMode,
856
+ filesSearched: files.length,
857
+ filesMatched: matchedFiles.length,
858
+ totalMatches,
859
+ truncated,
860
+ };
861
+ if (outputMode === "content") {
862
+ response.matches = allMatches;
863
+ }
864
+ else if (outputMode === "files_with_matches") {
865
+ response.matches = matchedFiles;
866
+ }
867
+ else {
868
+ response.matches = fileCounts;
869
+ }
870
+ return response;
871
+ },
872
+ };
873
+ }
374
874
  export function createBuiltInFileTools(workingDirectory, agentId) {
375
875
  const resolvedAgentId = agentId || "unknown";
376
876
  return [
377
877
  readFileTool(workingDirectory),
378
878
  writeFileTool(workingDirectory),
379
879
  editFileTool(workingDirectory),
880
+ grepTool(workingDirectory),
380
881
  bashTool(workingDirectory, resolvedAgentId),
381
882
  ];
382
883
  }