@mastra/core 1.7.0 → 1.8.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 (498) hide show
  1. package/CHANGELOG.md +218 -0
  2. package/dist/agent/agent-legacy.d.ts +15 -0
  3. package/dist/agent/agent-legacy.d.ts.map +1 -1
  4. package/dist/agent/agent.d.ts +7 -0
  5. package/dist/agent/agent.d.ts.map +1 -1
  6. package/dist/agent/agent.types.d.ts +311 -2
  7. package/dist/agent/agent.types.d.ts.map +1 -1
  8. package/dist/agent/index.cjs +13 -13
  9. package/dist/agent/index.d.ts +3 -1
  10. package/dist/agent/index.d.ts.map +1 -1
  11. package/dist/agent/index.js +2 -2
  12. package/dist/agent/message-list/index.cjs +18 -18
  13. package/dist/agent/message-list/index.js +1 -1
  14. package/dist/agent/message-list/merge/MessageMerger.d.ts.map +1 -1
  15. package/dist/agent/message-list/message-list.d.ts.map +1 -1
  16. package/dist/agent/workflows/prepare-stream/map-results-step.d.ts.map +1 -1
  17. package/dist/agent/workflows/prepare-stream/prepare-tools-step.d.ts.map +1 -1
  18. package/dist/{chunk-A72NTLFT.cjs → chunk-2IO5Q7OZ.cjs} +7 -7
  19. package/dist/{chunk-A72NTLFT.cjs.map → chunk-2IO5Q7OZ.cjs.map} +1 -1
  20. package/dist/{chunk-DFCRXDVK.js → chunk-2KHPZJNU.js} +10 -8
  21. package/dist/chunk-2KHPZJNU.js.map +1 -0
  22. package/dist/{chunk-R4N65TLG.js → chunk-2R5MQMSA.js} +35 -16
  23. package/dist/chunk-2R5MQMSA.js.map +1 -0
  24. package/dist/{chunk-ZSBM2SVU.js → chunk-4H5F6AFP.js} +1064 -226
  25. package/dist/chunk-4H5F6AFP.js.map +1 -0
  26. package/dist/{chunk-BQHWJLXU.js → chunk-63G75DJE.js} +9 -3
  27. package/dist/chunk-63G75DJE.js.map +1 -0
  28. package/dist/{chunk-SBOHDNIZ.cjs → chunk-6GSWC5ZA.cjs} +2 -2
  29. package/dist/{chunk-SBOHDNIZ.cjs.map → chunk-6GSWC5ZA.cjs.map} +1 -1
  30. package/dist/{chunk-QTAS3HND.cjs → chunk-6Q2UD3XF.cjs} +21 -14
  31. package/dist/chunk-6Q2UD3XF.cjs.map +1 -0
  32. package/dist/{chunk-GPJGPARM.js → chunk-DTPR3JAM.js} +2 -2
  33. package/dist/{chunk-GPJGPARM.js.map → chunk-DTPR3JAM.js.map} +1 -1
  34. package/dist/{chunk-NN26FSKL.js → chunk-FHJ2KIU5.js} +3 -3
  35. package/dist/{chunk-NN26FSKL.js.map → chunk-FHJ2KIU5.js.map} +1 -1
  36. package/dist/{chunk-RABITNTG.cjs → chunk-HWG7NPJA.cjs} +55 -55
  37. package/dist/{chunk-RABITNTG.cjs.map → chunk-HWG7NPJA.cjs.map} +1 -1
  38. package/dist/{chunk-HB6T4554.cjs → chunk-KH3G65IS.cjs} +10 -8
  39. package/dist/chunk-KH3G65IS.cjs.map +1 -0
  40. package/dist/{chunk-YQG7NBPR.cjs → chunk-KZ4IKNPN.cjs} +25 -23
  41. package/dist/chunk-KZ4IKNPN.cjs.map +1 -0
  42. package/dist/{chunk-6DUTLERJ.js → chunk-MRV5NCPC.js} +3 -3
  43. package/dist/{chunk-6DUTLERJ.js.map → chunk-MRV5NCPC.js.map} +1 -1
  44. package/dist/{chunk-O7PZ4VOO.cjs → chunk-N3ROEJG4.cjs} +12 -10
  45. package/dist/chunk-N3ROEJG4.cjs.map +1 -0
  46. package/dist/{chunk-7EXW4AAG.js → chunk-NXKI2L4X.js} +6 -4
  47. package/dist/chunk-NXKI2L4X.js.map +1 -0
  48. package/dist/{chunk-QWTB53GS.js → chunk-OSEPGSLN.js} +6 -6
  49. package/dist/{chunk-QWTB53GS.js.map → chunk-OSEPGSLN.js.map} +1 -1
  50. package/dist/{chunk-6OXW5E2O.js → chunk-PI7ONENO.js} +4 -4
  51. package/dist/{chunk-6OXW5E2O.js.map → chunk-PI7ONENO.js.map} +1 -1
  52. package/dist/{chunk-KUXNBWN7.js → chunk-Q4MV4XKX.js} +8 -6
  53. package/dist/chunk-Q4MV4XKX.js.map +1 -0
  54. package/dist/{chunk-7UAJ6LMR.cjs → chunk-QKQGKEN7.cjs} +1078 -241
  55. package/dist/chunk-QKQGKEN7.cjs.map +1 -0
  56. package/dist/{chunk-IC5OUWKJ.js → chunk-SP7P6Z4L.js} +19 -2
  57. package/dist/chunk-SP7P6Z4L.js.map +1 -0
  58. package/dist/{chunk-QDH6MVJ7.cjs → chunk-TGUDI64A.cjs} +14 -14
  59. package/dist/{chunk-QDH6MVJ7.cjs.map → chunk-TGUDI64A.cjs.map} +1 -1
  60. package/dist/{chunk-EAZ6YDCQ.cjs → chunk-U3HBG2GU.cjs} +9 -2
  61. package/dist/chunk-U3HBG2GU.cjs.map +1 -0
  62. package/dist/{chunk-6QBN6MZY.cjs → chunk-VAKB5EXJ.cjs} +42 -23
  63. package/dist/chunk-VAKB5EXJ.cjs.map +1 -0
  64. package/dist/{chunk-QSHV7GPT.js → chunk-VBPU6CLZ.js} +3808 -3026
  65. package/dist/chunk-VBPU6CLZ.js.map +1 -0
  66. package/dist/{chunk-2X66GWF5.cjs → chunk-VTVCMIAI.cjs} +3905 -3121
  67. package/dist/chunk-VTVCMIAI.cjs.map +1 -0
  68. package/dist/{chunk-PHHJLGZU.cjs → chunk-XNWF6CYR.cjs} +6 -6
  69. package/dist/{chunk-PHHJLGZU.cjs.map → chunk-XNWF6CYR.cjs.map} +1 -1
  70. package/dist/{chunk-T6GAM3SQ.js → chunk-ZRPTWYWJ.js} +18 -11
  71. package/dist/chunk-ZRPTWYWJ.js.map +1 -0
  72. package/dist/{chunk-DB7U2C5B.cjs → chunk-ZXOWG32X.cjs} +19 -2
  73. package/dist/chunk-ZXOWG32X.cjs.map +1 -0
  74. package/dist/datasets/experiment/index.d.ts.map +1 -1
  75. package/dist/datasets/experiment/scorer.d.ts +1 -1
  76. package/dist/datasets/experiment/scorer.d.ts.map +1 -1
  77. package/dist/datasets/index.cjs +17 -17
  78. package/dist/datasets/index.js +2 -2
  79. package/dist/docs/SKILL.md +300 -0
  80. package/dist/docs/assets/SOURCE_MAP.json +1423 -0
  81. package/dist/docs/references/docs-agents-adding-voice.md +349 -0
  82. package/dist/docs/references/docs-agents-agent-approval.md +558 -0
  83. package/dist/docs/references/docs-agents-agent-memory.md +209 -0
  84. package/dist/docs/references/docs-agents-guardrails.md +374 -0
  85. package/dist/docs/references/docs-agents-network-approval.md +275 -0
  86. package/dist/docs/references/docs-agents-networks.md +299 -0
  87. package/dist/docs/references/docs-agents-overview.md +304 -0
  88. package/dist/docs/references/docs-agents-processors.md +622 -0
  89. package/dist/docs/references/docs-agents-structured-output.md +273 -0
  90. package/dist/docs/references/docs-agents-supervisor-agents.md +304 -0
  91. package/dist/docs/references/docs-agents-using-tools.md +214 -0
  92. package/dist/docs/references/docs-evals-custom-scorers.md +519 -0
  93. package/dist/docs/references/docs-evals-overview.md +141 -0
  94. package/dist/docs/references/docs-evals-running-in-ci.md +124 -0
  95. package/dist/docs/references/docs-memory-memory-processors.md +314 -0
  96. package/dist/docs/references/docs-memory-observational-memory.md +248 -0
  97. package/dist/docs/references/docs-memory-overview.md +45 -0
  98. package/dist/docs/references/docs-memory-semantic-recall.md +272 -0
  99. package/dist/docs/references/docs-memory-storage.md +261 -0
  100. package/dist/docs/references/docs-memory-working-memory.md +400 -0
  101. package/dist/docs/references/docs-observability-datasets-overview.md +198 -0
  102. package/dist/docs/references/docs-observability-datasets-running-experiments.md +274 -0
  103. package/dist/docs/references/docs-observability-logging.md +99 -0
  104. package/dist/docs/references/docs-observability-overview.md +70 -0
  105. package/dist/docs/references/docs-observability-tracing-bridges-otel.md +209 -0
  106. package/dist/docs/references/docs-observability-tracing-exporters-arize.md +272 -0
  107. package/dist/docs/references/docs-observability-tracing-exporters-braintrust.md +111 -0
  108. package/dist/docs/references/docs-observability-tracing-exporters-cloud.md +127 -0
  109. package/dist/docs/references/docs-observability-tracing-exporters-datadog.md +187 -0
  110. package/dist/docs/references/docs-observability-tracing-exporters-default.md +209 -0
  111. package/dist/docs/references/docs-observability-tracing-exporters-laminar.md +100 -0
  112. package/dist/docs/references/docs-observability-tracing-exporters-langfuse.md +213 -0
  113. package/dist/docs/references/docs-observability-tracing-exporters-langsmith.md +198 -0
  114. package/dist/docs/references/docs-observability-tracing-exporters-otel.md +476 -0
  115. package/dist/docs/references/docs-observability-tracing-exporters-posthog.md +148 -0
  116. package/dist/docs/references/docs-observability-tracing-overview.md +1112 -0
  117. package/dist/docs/references/docs-rag-chunking-and-embedding.md +183 -0
  118. package/dist/docs/references/docs-rag-graph-rag.md +215 -0
  119. package/dist/docs/references/docs-rag-overview.md +72 -0
  120. package/dist/docs/references/docs-rag-retrieval.md +515 -0
  121. package/dist/docs/references/docs-rag-vector-databases.md +645 -0
  122. package/dist/docs/references/docs-server-auth-auth0.md +220 -0
  123. package/dist/docs/references/docs-server-auth-clerk.md +132 -0
  124. package/dist/docs/references/docs-server-auth-composite-auth.md +234 -0
  125. package/dist/docs/references/docs-server-auth-custom-auth-provider.md +513 -0
  126. package/dist/docs/references/docs-server-auth-firebase.md +272 -0
  127. package/dist/docs/references/docs-server-auth-jwt.md +110 -0
  128. package/dist/docs/references/docs-server-auth-simple-auth.md +180 -0
  129. package/dist/docs/references/docs-server-auth-supabase.md +117 -0
  130. package/dist/docs/references/docs-server-auth-workos.md +186 -0
  131. package/dist/docs/references/docs-server-custom-adapters.md +378 -0
  132. package/dist/docs/references/docs-server-custom-api-routes.md +267 -0
  133. package/dist/docs/references/docs-server-mastra-client.md +243 -0
  134. package/dist/docs/references/docs-server-mastra-server.md +71 -0
  135. package/dist/docs/references/docs-server-middleware.md +225 -0
  136. package/dist/docs/references/docs-server-request-context.md +471 -0
  137. package/dist/docs/references/docs-streaming-events.md +237 -0
  138. package/dist/docs/references/docs-streaming-tool-streaming.md +175 -0
  139. package/dist/docs/references/docs-streaming-workflow-streaming.md +109 -0
  140. package/dist/docs/references/docs-voice-overview.md +959 -0
  141. package/dist/docs/references/docs-voice-speech-to-speech.md +102 -0
  142. package/dist/docs/references/docs-voice-speech-to-text.md +79 -0
  143. package/dist/docs/references/docs-voice-text-to-speech.md +83 -0
  144. package/dist/docs/references/docs-workflows-agents-and-tools.md +166 -0
  145. package/dist/docs/references/docs-workflows-control-flow.md +822 -0
  146. package/dist/docs/references/docs-workflows-error-handling.md +360 -0
  147. package/dist/docs/references/docs-workflows-human-in-the-loop.md +215 -0
  148. package/dist/docs/references/docs-workflows-overview.md +370 -0
  149. package/dist/docs/references/docs-workflows-snapshots.md +238 -0
  150. package/dist/docs/references/docs-workflows-suspend-and-resume.md +205 -0
  151. package/dist/docs/references/docs-workflows-time-travel.md +309 -0
  152. package/dist/docs/references/docs-workflows-workflow-state.md +181 -0
  153. package/dist/docs/references/docs-workspace-filesystem.md +164 -0
  154. package/dist/docs/references/docs-workspace-overview.md +239 -0
  155. package/dist/docs/references/docs-workspace-sandbox.md +63 -0
  156. package/dist/docs/references/docs-workspace-search.md +243 -0
  157. package/dist/docs/references/docs-workspace-skills.md +169 -0
  158. package/dist/docs/references/guides-agent-frameworks-ai-sdk.md +140 -0
  159. package/dist/docs/references/reference-agents-agent.md +141 -0
  160. package/dist/docs/references/reference-agents-generate.md +186 -0
  161. package/dist/docs/references/reference-agents-generateLegacy.md +173 -0
  162. package/dist/docs/references/reference-agents-getDefaultGenerateOptions.md +36 -0
  163. package/dist/docs/references/reference-agents-getDefaultOptions.md +34 -0
  164. package/dist/docs/references/reference-agents-getDefaultStreamOptions.md +36 -0
  165. package/dist/docs/references/reference-agents-getDescription.md +21 -0
  166. package/dist/docs/references/reference-agents-getInstructions.md +34 -0
  167. package/dist/docs/references/reference-agents-getLLM.md +37 -0
  168. package/dist/docs/references/reference-agents-getMemory.md +34 -0
  169. package/dist/docs/references/reference-agents-getModel.md +34 -0
  170. package/dist/docs/references/reference-agents-getTools.md +29 -0
  171. package/dist/docs/references/reference-agents-getVoice.md +34 -0
  172. package/dist/docs/references/reference-agents-listAgents.md +35 -0
  173. package/dist/docs/references/reference-agents-listScorers.md +34 -0
  174. package/dist/docs/references/reference-agents-listTools.md +34 -0
  175. package/dist/docs/references/reference-agents-listWorkflows.md +34 -0
  176. package/dist/docs/references/reference-agents-network.md +133 -0
  177. package/dist/docs/references/reference-ai-sdk-chat-route.md +82 -0
  178. package/dist/docs/references/reference-ai-sdk-network-route.md +74 -0
  179. package/dist/docs/references/reference-ai-sdk-to-ai-sdk-stream.md +231 -0
  180. package/dist/docs/references/reference-ai-sdk-with-mastra.md +59 -0
  181. package/dist/docs/references/reference-ai-sdk-workflow-route.md +79 -0
  182. package/dist/docs/references/reference-auth-auth0.md +73 -0
  183. package/dist/docs/references/reference-auth-clerk.md +36 -0
  184. package/dist/docs/references/reference-auth-firebase.md +80 -0
  185. package/dist/docs/references/reference-auth-jwt.md +26 -0
  186. package/dist/docs/references/reference-auth-supabase.md +33 -0
  187. package/dist/docs/references/reference-auth-workos.md +84 -0
  188. package/dist/docs/references/reference-client-js-agents.md +437 -0
  189. package/dist/docs/references/reference-configuration.md +752 -0
  190. package/dist/docs/references/reference-core-addGateway.md +42 -0
  191. package/dist/docs/references/reference-core-getAgent.md +21 -0
  192. package/dist/docs/references/reference-core-getAgentById.md +21 -0
  193. package/dist/docs/references/reference-core-getDeployer.md +22 -0
  194. package/dist/docs/references/reference-core-getGateway.md +38 -0
  195. package/dist/docs/references/reference-core-getGatewayById.md +41 -0
  196. package/dist/docs/references/reference-core-getLogger.md +22 -0
  197. package/dist/docs/references/reference-core-getMCPServer.md +47 -0
  198. package/dist/docs/references/reference-core-getMCPServerById.md +55 -0
  199. package/dist/docs/references/reference-core-getMemory.md +50 -0
  200. package/dist/docs/references/reference-core-getScorer.md +54 -0
  201. package/dist/docs/references/reference-core-getScorerById.md +54 -0
  202. package/dist/docs/references/reference-core-getServer.md +22 -0
  203. package/dist/docs/references/reference-core-getStorage.md +22 -0
  204. package/dist/docs/references/reference-core-getStoredAgentById.md +89 -0
  205. package/dist/docs/references/reference-core-getTelemetry.md +22 -0
  206. package/dist/docs/references/reference-core-getVector.md +22 -0
  207. package/dist/docs/references/reference-core-getWorkflow.md +42 -0
  208. package/dist/docs/references/reference-core-listAgents.md +21 -0
  209. package/dist/docs/references/reference-core-listGateways.md +40 -0
  210. package/dist/docs/references/reference-core-listLogs.md +38 -0
  211. package/dist/docs/references/reference-core-listLogsByRunId.md +36 -0
  212. package/dist/docs/references/reference-core-listMCPServers.md +55 -0
  213. package/dist/docs/references/reference-core-listMemory.md +56 -0
  214. package/dist/docs/references/reference-core-listScorers.md +29 -0
  215. package/dist/docs/references/reference-core-listStoredAgents.md +93 -0
  216. package/dist/docs/references/reference-core-listVectors.md +22 -0
  217. package/dist/docs/references/reference-core-listWorkflows.md +21 -0
  218. package/dist/docs/references/reference-core-mastra-class.md +66 -0
  219. package/dist/docs/references/reference-core-mastra-model-gateway.md +153 -0
  220. package/dist/docs/references/reference-core-setLogger.md +26 -0
  221. package/dist/docs/references/reference-core-setStorage.md +27 -0
  222. package/dist/docs/references/reference-datasets-addItem.md +37 -0
  223. package/dist/docs/references/reference-datasets-addItems.md +35 -0
  224. package/dist/docs/references/reference-datasets-compareExperiments.md +52 -0
  225. package/dist/docs/references/reference-datasets-create.md +51 -0
  226. package/dist/docs/references/reference-datasets-dataset.md +82 -0
  227. package/dist/docs/references/reference-datasets-datasets-manager.md +94 -0
  228. package/dist/docs/references/reference-datasets-delete.md +25 -0
  229. package/dist/docs/references/reference-datasets-deleteExperiment.md +27 -0
  230. package/dist/docs/references/reference-datasets-deleteItem.md +27 -0
  231. package/dist/docs/references/reference-datasets-deleteItems.md +29 -0
  232. package/dist/docs/references/reference-datasets-get.md +31 -0
  233. package/dist/docs/references/reference-datasets-getDetails.md +47 -0
  234. package/dist/docs/references/reference-datasets-getExperiment.md +30 -0
  235. package/dist/docs/references/reference-datasets-getItem.md +33 -0
  236. package/dist/docs/references/reference-datasets-getItemHistory.md +31 -0
  237. package/dist/docs/references/reference-datasets-list.md +31 -0
  238. package/dist/docs/references/reference-datasets-listExperimentResults.md +39 -0
  239. package/dist/docs/references/reference-datasets-listExperiments.md +33 -0
  240. package/dist/docs/references/reference-datasets-listItems.md +46 -0
  241. package/dist/docs/references/reference-datasets-listVersions.md +33 -0
  242. package/dist/docs/references/reference-datasets-startExperiment.md +62 -0
  243. package/dist/docs/references/reference-datasets-startExperimentAsync.md +43 -0
  244. package/dist/docs/references/reference-datasets-update.md +48 -0
  245. package/dist/docs/references/reference-datasets-updateItem.md +38 -0
  246. package/dist/docs/references/reference-evals-answer-relevancy.md +105 -0
  247. package/dist/docs/references/reference-evals-answer-similarity.md +99 -0
  248. package/dist/docs/references/reference-evals-bias.md +120 -0
  249. package/dist/docs/references/reference-evals-completeness.md +136 -0
  250. package/dist/docs/references/reference-evals-content-similarity.md +101 -0
  251. package/dist/docs/references/reference-evals-context-precision.md +196 -0
  252. package/dist/docs/references/reference-evals-create-scorer.md +270 -0
  253. package/dist/docs/references/reference-evals-faithfulness.md +114 -0
  254. package/dist/docs/references/reference-evals-hallucination.md +213 -0
  255. package/dist/docs/references/reference-evals-keyword-coverage.md +128 -0
  256. package/dist/docs/references/reference-evals-mastra-scorer.md +123 -0
  257. package/dist/docs/references/reference-evals-run-evals.md +179 -0
  258. package/dist/docs/references/reference-evals-scorer-utils.md +326 -0
  259. package/dist/docs/references/reference-evals-textual-difference.md +113 -0
  260. package/dist/docs/references/reference-evals-tone-consistency.md +119 -0
  261. package/dist/docs/references/reference-evals-toxicity.md +123 -0
  262. package/dist/docs/references/reference-harness-harness-class.md +708 -0
  263. package/dist/docs/references/reference-logging-pino-logger.md +117 -0
  264. package/dist/docs/references/reference-memory-deleteMessages.md +38 -0
  265. package/dist/docs/references/reference-memory-memory-class.md +147 -0
  266. package/dist/docs/references/reference-memory-observational-memory.md +565 -0
  267. package/dist/docs/references/reference-observability-tracing-bridges-otel.md +131 -0
  268. package/dist/docs/references/reference-observability-tracing-configuration.md +178 -0
  269. package/dist/docs/references/reference-observability-tracing-exporters-console-exporter.md +138 -0
  270. package/dist/docs/references/reference-observability-tracing-exporters-datadog.md +116 -0
  271. package/dist/docs/references/reference-observability-tracing-instances.md +107 -0
  272. package/dist/docs/references/reference-observability-tracing-interfaces.md +743 -0
  273. package/dist/docs/references/reference-observability-tracing-processors-sensitive-data-filter.md +144 -0
  274. package/dist/docs/references/reference-observability-tracing-spans.md +224 -0
  275. package/dist/docs/references/reference-processors-batch-parts-processor.md +61 -0
  276. package/dist/docs/references/reference-processors-language-detector.md +82 -0
  277. package/dist/docs/references/reference-processors-message-history-processor.md +85 -0
  278. package/dist/docs/references/reference-processors-moderation-processor.md +104 -0
  279. package/dist/docs/references/reference-processors-pii-detector.md +108 -0
  280. package/dist/docs/references/reference-processors-processor-interface.md +521 -0
  281. package/dist/docs/references/reference-processors-prompt-injection-detector.md +72 -0
  282. package/dist/docs/references/reference-processors-semantic-recall-processor.md +117 -0
  283. package/dist/docs/references/reference-processors-system-prompt-scrubber.md +80 -0
  284. package/dist/docs/references/reference-processors-token-limiter-processor.md +115 -0
  285. package/dist/docs/references/reference-processors-tool-call-filter.md +85 -0
  286. package/dist/docs/references/reference-processors-tool-search-processor.md +111 -0
  287. package/dist/docs/references/reference-processors-unicode-normalizer.md +62 -0
  288. package/dist/docs/references/reference-processors-working-memory-processor.md +152 -0
  289. package/dist/docs/references/reference-rag-database-config.md +261 -0
  290. package/dist/docs/references/reference-rag-embeddings.md +92 -0
  291. package/dist/docs/references/reference-server-mastra-server.md +298 -0
  292. package/dist/docs/references/reference-server-register-api-route.md +249 -0
  293. package/dist/docs/references/reference-storage-cloudflare-d1.md +218 -0
  294. package/dist/docs/references/reference-storage-composite.md +235 -0
  295. package/dist/docs/references/reference-storage-lance.md +131 -0
  296. package/dist/docs/references/reference-storage-libsql.md +135 -0
  297. package/dist/docs/references/reference-storage-mongodb.md +262 -0
  298. package/dist/docs/references/reference-storage-mssql.md +157 -0
  299. package/dist/docs/references/reference-storage-overview.md +121 -0
  300. package/dist/docs/references/reference-storage-postgresql.md +526 -0
  301. package/dist/docs/references/reference-storage-upstash.md +160 -0
  302. package/dist/docs/references/reference-streaming-ChunkType.md +292 -0
  303. package/dist/docs/references/reference-streaming-agents-MastraModelOutput.md +182 -0
  304. package/dist/docs/references/reference-streaming-agents-streamLegacy.md +142 -0
  305. package/dist/docs/references/reference-streaming-workflows-observeStream.md +42 -0
  306. package/dist/docs/references/reference-streaming-workflows-resumeStream.md +61 -0
  307. package/dist/docs/references/reference-streaming-workflows-stream.md +88 -0
  308. package/dist/docs/references/reference-streaming-workflows-timeTravelStream.md +142 -0
  309. package/dist/docs/references/reference-templates-overview.md +194 -0
  310. package/dist/docs/references/reference-tools-create-tool.md +237 -0
  311. package/dist/docs/references/reference-tools-graph-rag-tool.md +182 -0
  312. package/dist/docs/references/reference-tools-mcp-client.md +954 -0
  313. package/dist/docs/references/reference-tools-mcp-server.md +1271 -0
  314. package/dist/docs/references/reference-tools-vector-query-tool.md +459 -0
  315. package/dist/docs/references/reference-vectors-libsql.md +305 -0
  316. package/dist/docs/references/reference-vectors-mongodb.md +295 -0
  317. package/dist/docs/references/reference-vectors-pg.md +408 -0
  318. package/dist/docs/references/reference-vectors-upstash.md +294 -0
  319. package/dist/docs/references/reference-voice-composite-voice.md +121 -0
  320. package/dist/docs/references/reference-voice-mastra-voice.md +311 -0
  321. package/dist/docs/references/reference-voice-voice.addInstructions.md +55 -0
  322. package/dist/docs/references/reference-voice-voice.addTools.md +67 -0
  323. package/dist/docs/references/reference-voice-voice.connect.md +94 -0
  324. package/dist/docs/references/reference-voice-voice.events.md +37 -0
  325. package/dist/docs/references/reference-voice-voice.listen.md +164 -0
  326. package/dist/docs/references/reference-voice-voice.on.md +111 -0
  327. package/dist/docs/references/reference-voice-voice.speak.md +157 -0
  328. package/dist/docs/references/reference-workflows-run-methods-cancel.md +86 -0
  329. package/dist/docs/references/reference-workflows-run-methods-restart.md +33 -0
  330. package/dist/docs/references/reference-workflows-run-methods-resume.md +59 -0
  331. package/dist/docs/references/reference-workflows-run-methods-start.md +58 -0
  332. package/dist/docs/references/reference-workflows-run-methods-startAsync.md +67 -0
  333. package/dist/docs/references/reference-workflows-run-methods-timeTravel.md +142 -0
  334. package/dist/docs/references/reference-workflows-run.md +59 -0
  335. package/dist/docs/references/reference-workflows-step.md +119 -0
  336. package/dist/docs/references/reference-workflows-workflow-methods-branch.md +25 -0
  337. package/dist/docs/references/reference-workflows-workflow-methods-commit.md +17 -0
  338. package/dist/docs/references/reference-workflows-workflow-methods-create-run.md +63 -0
  339. package/dist/docs/references/reference-workflows-workflow-methods-dountil.md +25 -0
  340. package/dist/docs/references/reference-workflows-workflow-methods-dowhile.md +25 -0
  341. package/dist/docs/references/reference-workflows-workflow-methods-foreach.md +118 -0
  342. package/dist/docs/references/reference-workflows-workflow-methods-map.md +93 -0
  343. package/dist/docs/references/reference-workflows-workflow-methods-parallel.md +21 -0
  344. package/dist/docs/references/reference-workflows-workflow-methods-sleep.md +35 -0
  345. package/dist/docs/references/reference-workflows-workflow-methods-sleepUntil.md +35 -0
  346. package/dist/docs/references/reference-workflows-workflow-methods-then.md +21 -0
  347. package/dist/docs/references/reference-workflows-workflow.md +157 -0
  348. package/dist/docs/references/reference-workspace-filesystem.md +255 -0
  349. package/dist/docs/references/reference-workspace-local-filesystem.md +343 -0
  350. package/dist/docs/references/reference-workspace-local-sandbox.md +301 -0
  351. package/dist/docs/references/reference-workspace-sandbox.md +87 -0
  352. package/dist/docs/references/reference-workspace-workspace-class.md +244 -0
  353. package/dist/docs/references/reference.md +277 -0
  354. package/dist/evals/index.cjs +20 -20
  355. package/dist/evals/index.js +3 -3
  356. package/dist/evals/run/index.d.ts +9 -2
  357. package/dist/evals/run/index.d.ts.map +1 -1
  358. package/dist/evals/scoreTraces/index.cjs +5 -5
  359. package/dist/evals/scoreTraces/index.js +2 -2
  360. package/dist/harness/harness.d.ts +6 -0
  361. package/dist/harness/harness.d.ts.map +1 -1
  362. package/dist/harness/index.cjs +28 -13
  363. package/dist/harness/index.cjs.map +1 -1
  364. package/dist/harness/index.js +20 -5
  365. package/dist/harness/index.js.map +1 -1
  366. package/dist/index.cjs +2 -2
  367. package/dist/index.js +1 -1
  368. package/dist/integration/index.cjs +2 -2
  369. package/dist/integration/index.js +1 -1
  370. package/dist/llm/index.cjs +6 -6
  371. package/dist/llm/index.js +1 -1
  372. package/dist/llm/model/embedding-router.d.ts.map +1 -1
  373. package/dist/llm/model/model.loop.d.ts +1 -1
  374. package/dist/llm/model/model.loop.d.ts.map +1 -1
  375. package/dist/loop/index.cjs +20 -12
  376. package/dist/loop/index.js +1 -1
  377. package/dist/loop/network/index.d.ts.map +1 -1
  378. package/dist/loop/network/validation.d.ts +51 -0
  379. package/dist/loop/network/validation.d.ts.map +1 -1
  380. package/dist/loop/test-utils/generateText.d.ts.map +1 -1
  381. package/dist/loop/test-utils/options.d.ts.map +1 -1
  382. package/dist/loop/test-utils/streamObject.d.ts.map +1 -1
  383. package/dist/loop/types.d.ts +15 -0
  384. package/dist/loop/types.d.ts.map +1 -1
  385. package/dist/loop/workflows/agentic-execution/index.d.ts +3 -0
  386. package/dist/loop/workflows/agentic-execution/index.d.ts.map +1 -1
  387. package/dist/loop/workflows/agentic-execution/is-task-complete-step.d.ts +126 -0
  388. package/dist/loop/workflows/agentic-execution/is-task-complete-step.d.ts.map +1 -0
  389. package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts +3 -1
  390. package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts.map +1 -1
  391. package/dist/loop/workflows/agentic-execution/llm-mapping-step.d.ts +1 -0
  392. package/dist/loop/workflows/agentic-execution/llm-mapping-step.d.ts.map +1 -1
  393. package/dist/loop/workflows/agentic-execution/tool-call-step.d.ts.map +1 -1
  394. package/dist/loop/workflows/agentic-loop/index.d.ts +3 -0
  395. package/dist/loop/workflows/agentic-loop/index.d.ts.map +1 -1
  396. package/dist/loop/workflows/schema.d.ts +3 -0
  397. package/dist/loop/workflows/schema.d.ts.map +1 -1
  398. package/dist/mastra/index.cjs +2 -2
  399. package/dist/mastra/index.d.ts +9 -5
  400. package/dist/mastra/index.d.ts.map +1 -1
  401. package/dist/mastra/index.js +1 -1
  402. package/dist/memory/index.cjs +14 -14
  403. package/dist/memory/index.js +1 -1
  404. package/dist/processor-provider/index.cjs +10 -10
  405. package/dist/processor-provider/index.js +1 -1
  406. package/dist/processors/index.cjs +42 -42
  407. package/dist/processors/index.js +1 -1
  408. package/dist/processors/processors/skills.d.ts.map +1 -1
  409. package/dist/relevance/index.cjs +3 -3
  410. package/dist/relevance/index.js +1 -1
  411. package/dist/storage/constants.cjs +56 -56
  412. package/dist/storage/constants.js +1 -1
  413. package/dist/storage/domains/memory/inmemory.d.ts.map +1 -1
  414. package/dist/storage/index.cjs +160 -160
  415. package/dist/storage/index.js +2 -2
  416. package/dist/storage/types.d.ts +2 -3
  417. package/dist/storage/types.d.ts.map +1 -1
  418. package/dist/stream/aisdk/v5/compat/prepare-tools.d.ts.map +1 -1
  419. package/dist/stream/base/output.d.ts +1 -0
  420. package/dist/stream/base/output.d.ts.map +1 -1
  421. package/dist/stream/index.cjs +11 -11
  422. package/dist/stream/index.js +2 -2
  423. package/dist/stream/types.d.ts +27 -1
  424. package/dist/stream/types.d.ts.map +1 -1
  425. package/dist/test-utils/llm-mock.cjs +4 -4
  426. package/dist/test-utils/llm-mock.js +1 -1
  427. package/dist/tool-loop-agent/index.cjs +4 -4
  428. package/dist/tool-loop-agent/index.js +1 -1
  429. package/dist/tools/index.cjs +9 -5
  430. package/dist/tools/index.d.ts +1 -1
  431. package/dist/tools/index.d.ts.map +1 -1
  432. package/dist/tools/index.js +1 -1
  433. package/dist/tools/is-vercel-tool.cjs +2 -2
  434. package/dist/tools/is-vercel-tool.js +1 -1
  435. package/dist/tools/toolchecks.d.ts +10 -0
  436. package/dist/tools/toolchecks.d.ts.map +1 -1
  437. package/dist/utils.cjs +23 -23
  438. package/dist/utils.js +1 -1
  439. package/dist/vector/index.cjs +7 -7
  440. package/dist/vector/index.js +1 -1
  441. package/dist/vector/types.d.ts +9 -1
  442. package/dist/vector/types.d.ts.map +1 -1
  443. package/dist/workflows/evented/index.cjs +10 -10
  444. package/dist/workflows/evented/index.js +1 -1
  445. package/dist/workflows/index.cjs +25 -25
  446. package/dist/workflows/index.js +1 -1
  447. package/dist/workflows/types.d.ts +14 -1
  448. package/dist/workflows/types.d.ts.map +1 -1
  449. package/dist/workflows/workflow.d.ts +3 -17
  450. package/dist/workflows/workflow.d.ts.map +1 -1
  451. package/dist/workspace/filesystem/composite-filesystem.d.ts +5 -0
  452. package/dist/workspace/filesystem/composite-filesystem.d.ts.map +1 -1
  453. package/dist/workspace/filesystem/filesystem.d.ts +12 -0
  454. package/dist/workspace/filesystem/filesystem.d.ts.map +1 -1
  455. package/dist/workspace/filesystem/fs-utils.d.ts +12 -0
  456. package/dist/workspace/filesystem/fs-utils.d.ts.map +1 -1
  457. package/dist/workspace/filesystem/local-filesystem.d.ts +6 -0
  458. package/dist/workspace/filesystem/local-filesystem.d.ts.map +1 -1
  459. package/dist/workspace/index.cjs +66 -66
  460. package/dist/workspace/index.js +1 -1
  461. package/dist/workspace/lsp/client.d.ts +76 -0
  462. package/dist/workspace/lsp/client.d.ts.map +1 -0
  463. package/dist/workspace/lsp/index.d.ts +6 -0
  464. package/dist/workspace/lsp/index.d.ts.map +1 -0
  465. package/dist/workspace/lsp/language.d.ts +16 -0
  466. package/dist/workspace/lsp/language.d.ts.map +1 -0
  467. package/dist/workspace/lsp/manager.d.ts +72 -0
  468. package/dist/workspace/lsp/manager.d.ts.map +1 -0
  469. package/dist/workspace/lsp/servers.d.ts +43 -0
  470. package/dist/workspace/lsp/servers.d.ts.map +1 -0
  471. package/dist/workspace/lsp/types.d.ts +45 -0
  472. package/dist/workspace/lsp/types.d.ts.map +1 -0
  473. package/dist/workspace/tools/ast-edit.d.ts.map +1 -1
  474. package/dist/workspace/tools/edit-file.d.ts.map +1 -1
  475. package/dist/workspace/tools/helpers.d.ts +13 -0
  476. package/dist/workspace/tools/helpers.d.ts.map +1 -1
  477. package/dist/workspace/tools/write-file.d.ts.map +1 -1
  478. package/dist/workspace/workspace.d.ts +33 -0
  479. package/dist/workspace/workspace.d.ts.map +1 -1
  480. package/package.json +10 -8
  481. package/dist/chunk-2X66GWF5.cjs.map +0 -1
  482. package/dist/chunk-6QBN6MZY.cjs.map +0 -1
  483. package/dist/chunk-7EXW4AAG.js.map +0 -1
  484. package/dist/chunk-7UAJ6LMR.cjs.map +0 -1
  485. package/dist/chunk-BQHWJLXU.js.map +0 -1
  486. package/dist/chunk-DB7U2C5B.cjs.map +0 -1
  487. package/dist/chunk-DFCRXDVK.js.map +0 -1
  488. package/dist/chunk-EAZ6YDCQ.cjs.map +0 -1
  489. package/dist/chunk-HB6T4554.cjs.map +0 -1
  490. package/dist/chunk-IC5OUWKJ.js.map +0 -1
  491. package/dist/chunk-KUXNBWN7.js.map +0 -1
  492. package/dist/chunk-O7PZ4VOO.cjs.map +0 -1
  493. package/dist/chunk-QSHV7GPT.js.map +0 -1
  494. package/dist/chunk-QTAS3HND.cjs.map +0 -1
  495. package/dist/chunk-R4N65TLG.js.map +0 -1
  496. package/dist/chunk-T6GAM3SQ.js.map +0 -1
  497. package/dist/chunk-YQG7NBPR.cjs.map +0 -1
  498. package/dist/chunk-ZSBM2SVU.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkEAZ6YDCQ_cjs = require('./chunk-EAZ6YDCQ.cjs');
3
+ var chunkU3HBG2GU_cjs = require('./chunk-U3HBG2GU.cjs');
4
4
  var chunkRO47SMI7_cjs = require('./chunk-RO47SMI7.cjs');
5
5
  var chunk7XAECHYL_cjs = require('./chunk-7XAECHYL.cjs');
6
6
  var posixPath = require('path/posix');
@@ -8,12 +8,13 @@ var fs = require('fs');
8
8
  var fs2 = require('fs/promises');
9
9
  var nodePath = require('path');
10
10
  var picomatch = require('picomatch');
11
+ var module$1 = require('module');
12
+ var url = require('url');
13
+ var childProcess = require('child_process');
11
14
  var crypto = require('crypto');
12
15
  var matter = require('gray-matter');
13
16
  var os = require('os');
14
- var childProcess = require('child_process');
15
17
  var stream = require('stream');
16
- var module$1 = require('module');
17
18
  var zod = require('zod');
18
19
 
19
20
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
@@ -41,10 +42,10 @@ var posixPath__default = /*#__PURE__*/_interopDefault(posixPath);
41
42
  var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2);
42
43
  var nodePath__namespace = /*#__PURE__*/_interopNamespace(nodePath);
43
44
  var picomatch__default = /*#__PURE__*/_interopDefault(picomatch);
45
+ var childProcess__namespace = /*#__PURE__*/_interopNamespace(childProcess);
44
46
  var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
45
47
  var matter__default = /*#__PURE__*/_interopDefault(matter);
46
48
  var os__namespace = /*#__PURE__*/_interopNamespace(os);
47
- var childProcess__namespace = /*#__PURE__*/_interopNamespace(childProcess);
48
49
 
49
50
  // src/workspace/errors.ts
50
51
  var WorkspaceError = class extends Error {
@@ -98,59 +99,59 @@ var WorkspaceReadOnlyError = class extends WorkspaceError {
98
99
  }
99
100
  };
100
101
  var FilesystemError = class extends Error {
101
- constructor(message, code, path4) {
102
+ constructor(message, code, path6) {
102
103
  super(message);
103
104
  this.code = code;
104
- this.path = path4;
105
+ this.path = path6;
105
106
  this.name = "FilesystemError";
106
107
  }
107
108
  };
108
109
  var FileNotFoundError = class extends FilesystemError {
109
- constructor(path4) {
110
- super(`File not found: ${path4}`, "ENOENT", path4);
110
+ constructor(path6) {
111
+ super(`File not found: ${path6}`, "ENOENT", path6);
111
112
  this.name = "FileNotFoundError";
112
113
  }
113
114
  };
114
115
  var DirectoryNotFoundError = class extends FilesystemError {
115
- constructor(path4) {
116
- super(`Directory not found: ${path4}`, "ENOENT", path4);
116
+ constructor(path6) {
117
+ super(`Directory not found: ${path6}`, "ENOENT", path6);
117
118
  this.name = "DirectoryNotFoundError";
118
119
  }
119
120
  };
120
121
  var FileExistsError = class extends FilesystemError {
121
- constructor(path4) {
122
- super(`File already exists: ${path4}`, "EEXIST", path4);
122
+ constructor(path6) {
123
+ super(`File already exists: ${path6}`, "EEXIST", path6);
123
124
  this.name = "FileExistsError";
124
125
  }
125
126
  };
126
127
  var IsDirectoryError = class extends FilesystemError {
127
- constructor(path4) {
128
- super(`Path is a directory: ${path4}`, "EISDIR", path4);
128
+ constructor(path6) {
129
+ super(`Path is a directory: ${path6}`, "EISDIR", path6);
129
130
  this.name = "IsDirectoryError";
130
131
  }
131
132
  };
132
133
  var NotDirectoryError = class extends FilesystemError {
133
- constructor(path4) {
134
- super(`Path is not a directory: ${path4}`, "ENOTDIR", path4);
134
+ constructor(path6) {
135
+ super(`Path is not a directory: ${path6}`, "ENOTDIR", path6);
135
136
  this.name = "NotDirectoryError";
136
137
  }
137
138
  };
138
139
  var DirectoryNotEmptyError = class extends FilesystemError {
139
- constructor(path4) {
140
- super(`Directory not empty: ${path4}`, "ENOTEMPTY", path4);
140
+ constructor(path6) {
141
+ super(`Directory not empty: ${path6}`, "ENOTEMPTY", path6);
141
142
  this.name = "DirectoryNotEmptyError";
142
143
  }
143
144
  };
144
145
  var PermissionError = class extends FilesystemError {
145
- constructor(path4, operation) {
146
- super(`Permission denied: ${operation} on ${path4}`, "EACCES", path4);
146
+ constructor(path6, operation) {
147
+ super(`Permission denied: ${operation} on ${path6}`, "EACCES", path6);
147
148
  this.operation = operation;
148
149
  this.name = "PermissionError";
149
150
  }
150
151
  };
151
152
  var FileReadRequiredError = class extends FilesystemError {
152
- constructor(path4, reason) {
153
- super(reason, "EREAD_REQUIRED", path4);
153
+ constructor(path6, reason) {
154
+ super(reason, "EREAD_REQUIRED", path6);
154
155
  this.name = "FileReadRequiredError";
155
156
  }
156
157
  };
@@ -186,8 +187,8 @@ var CompositeFilesystem = class {
186
187
  constructor(config) {
187
188
  this.id = `cfs-${Date.now().toString(36)}`;
188
189
  this._mounts = /* @__PURE__ */ new Map();
189
- for (const [path4, fs5] of Object.entries(config.mounts)) {
190
- const normalized = this.normalizePath(path4);
190
+ for (const [path6, fs5] of Object.entries(config.mounts)) {
191
+ const normalized = this.normalizePath(path6);
191
192
  this._mounts.set(normalized, fs5);
192
193
  }
193
194
  if (this._mounts.size === 0) {
@@ -238,27 +239,36 @@ var CompositeFilesystem = class {
238
239
  * Get the underlying filesystem for a given path.
239
240
  * Returns undefined if the path doesn't resolve to any mount.
240
241
  */
241
- getFilesystemForPath(path4) {
242
- const resolved = this.resolveMount(path4);
242
+ getFilesystemForPath(path6) {
243
+ const resolved = this.resolveMount(path6);
243
244
  return resolved?.fs;
244
245
  }
245
246
  /**
246
247
  * Get the mount path for a given path.
247
248
  * Returns undefined if the path doesn't resolve to any mount.
248
249
  */
249
- getMountPathForPath(path4) {
250
- const resolved = this.resolveMount(path4);
250
+ getMountPathForPath(path6) {
251
+ const resolved = this.resolveMount(path6);
251
252
  return resolved?.mountPath;
252
253
  }
253
- normalizePath(path4) {
254
- if (!path4 || path4 === "/") return "/";
255
- let n = posixPath__default.default.normalize(path4);
254
+ /**
255
+ * Resolve a workspace-relative path to an absolute disk path.
256
+ * Strips the mount prefix and delegates to the underlying filesystem.
257
+ */
258
+ resolveAbsolutePath(path6) {
259
+ const r = this.resolveMount(path6);
260
+ if (!r) return void 0;
261
+ return r.fs.resolveAbsolutePath?.(r.fsPath);
262
+ }
263
+ normalizePath(path6) {
264
+ if (!path6 || path6 === "/") return "/";
265
+ let n = posixPath__default.default.normalize(path6);
256
266
  if (!n.startsWith("/")) n = `/${n}`;
257
267
  if (n.length > 1 && n.endsWith("/")) n = n.slice(0, -1);
258
268
  return n;
259
269
  }
260
- resolveMount(path4) {
261
- const normalized = this.normalizePath(path4);
270
+ resolveMount(path6) {
271
+ const normalized = this.normalizePath(path6);
262
272
  let best = null;
263
273
  for (const [mountPath, fs5] of this._mounts) {
264
274
  if (normalized === mountPath || normalized.startsWith(mountPath + "/")) {
@@ -273,8 +283,8 @@ var CompositeFilesystem = class {
273
283
  if (!fsPath.startsWith("/")) fsPath = "/" + fsPath;
274
284
  return { fs: best.fs, fsPath, mountPath: best.mountPath };
275
285
  }
276
- getVirtualEntries(path4) {
277
- const normalized = this.normalizePath(path4);
286
+ getVirtualEntries(path6) {
287
+ const normalized = this.normalizePath(path6);
278
288
  if (this.resolveMount(normalized)) return null;
279
289
  const entriesMap = /* @__PURE__ */ new Map();
280
290
  for (const [mountPath, fs5] of this._mounts.entries()) {
@@ -301,8 +311,8 @@ var CompositeFilesystem = class {
301
311
  }
302
312
  return entriesMap.size > 0 ? Array.from(entriesMap.values()) : null;
303
313
  }
304
- isVirtualPath(path4) {
305
- const normalized = this.normalizePath(path4);
314
+ isVirtualPath(path6) {
315
+ const normalized = this.normalizePath(path6);
306
316
  if (normalized === "/" && !this._mounts.has("/")) return true;
307
317
  for (const mountPath of this._mounts.keys()) {
308
318
  if (mountPath.startsWith(normalized + "/")) return true;
@@ -313,9 +323,9 @@ var CompositeFilesystem = class {
313
323
  * Assert that a filesystem is writable (not read-only).
314
324
  * @throws {PermissionError} if the filesystem is read-only
315
325
  */
316
- assertWritable(fs5, path4, operation) {
326
+ assertWritable(fs5, path6, operation) {
317
327
  if (fs5.readOnly) {
318
- throw new PermissionError(path4, `${operation} (filesystem is read-only)`);
328
+ throw new PermissionError(path6, `${operation} (filesystem is read-only)`);
319
329
  }
320
330
  }
321
331
  // ===========================================================================
@@ -349,27 +359,27 @@ var CompositeFilesystem = class {
349
359
  }
350
360
  this.status = "destroyed";
351
361
  }
352
- async readFile(path4, options) {
353
- const r = this.resolveMount(path4);
354
- if (!r) throw new Error(`No mount for path: ${path4}`);
362
+ async readFile(path6, options) {
363
+ const r = this.resolveMount(path6);
364
+ if (!r) throw new Error(`No mount for path: ${path6}`);
355
365
  return r.fs.readFile(r.fsPath, options);
356
366
  }
357
- async writeFile(path4, content, options) {
358
- const r = this.resolveMount(path4);
359
- if (!r) throw new Error(`No mount for path: ${path4}`);
360
- this.assertWritable(r.fs, path4, "writeFile");
367
+ async writeFile(path6, content, options) {
368
+ const r = this.resolveMount(path6);
369
+ if (!r) throw new Error(`No mount for path: ${path6}`);
370
+ this.assertWritable(r.fs, path6, "writeFile");
361
371
  return r.fs.writeFile(r.fsPath, content, options);
362
372
  }
363
- async appendFile(path4, content) {
364
- const r = this.resolveMount(path4);
365
- if (!r) throw new Error(`No mount for path: ${path4}`);
366
- this.assertWritable(r.fs, path4, "appendFile");
373
+ async appendFile(path6, content) {
374
+ const r = this.resolveMount(path6);
375
+ if (!r) throw new Error(`No mount for path: ${path6}`);
376
+ this.assertWritable(r.fs, path6, "appendFile");
367
377
  return r.fs.appendFile(r.fsPath, content);
368
378
  }
369
- async deleteFile(path4, options) {
370
- const r = this.resolveMount(path4);
371
- if (!r) throw new Error(`No mount for path: ${path4}`);
372
- this.assertWritable(r.fs, path4, "deleteFile");
379
+ async deleteFile(path6, options) {
380
+ const r = this.resolveMount(path6);
381
+ if (!r) throw new Error(`No mount for path: ${path6}`);
382
+ this.assertWritable(r.fs, path6, "deleteFile");
373
383
  return r.fs.deleteFile(r.fsPath, options);
374
384
  }
375
385
  async copyFile(src, dest, options) {
@@ -397,35 +407,35 @@ var CompositeFilesystem = class {
397
407
  await this.copyFile(src, dest, options);
398
408
  await srcR.fs.deleteFile(srcR.fsPath);
399
409
  }
400
- async readdir(path4, options) {
401
- const virtual = this.getVirtualEntries(path4);
410
+ async readdir(path6, options) {
411
+ const virtual = this.getVirtualEntries(path6);
402
412
  if (virtual) return virtual;
403
- const r = this.resolveMount(path4);
404
- if (!r) throw new Error(`No mount for path: ${path4}`);
413
+ const r = this.resolveMount(path6);
414
+ if (!r) throw new Error(`No mount for path: ${path6}`);
405
415
  return r.fs.readdir(r.fsPath, options);
406
416
  }
407
- async mkdir(path4, options) {
408
- const r = this.resolveMount(path4);
409
- if (!r) throw new Error(`No mount for path: ${path4}`);
410
- this.assertWritable(r.fs, path4, "mkdir");
417
+ async mkdir(path6, options) {
418
+ const r = this.resolveMount(path6);
419
+ if (!r) throw new Error(`No mount for path: ${path6}`);
420
+ this.assertWritable(r.fs, path6, "mkdir");
411
421
  return r.fs.mkdir(r.fsPath, options);
412
422
  }
413
- async rmdir(path4, options) {
414
- const r = this.resolveMount(path4);
415
- if (!r) throw new Error(`No mount for path: ${path4}`);
416
- this.assertWritable(r.fs, path4, "rmdir");
423
+ async rmdir(path6, options) {
424
+ const r = this.resolveMount(path6);
425
+ if (!r) throw new Error(`No mount for path: ${path6}`);
426
+ this.assertWritable(r.fs, path6, "rmdir");
417
427
  return r.fs.rmdir(r.fsPath, options);
418
428
  }
419
- async exists(path4) {
420
- if (this.isVirtualPath(path4)) return true;
421
- const r = this.resolveMount(path4);
429
+ async exists(path6) {
430
+ if (this.isVirtualPath(path6)) return true;
431
+ const r = this.resolveMount(path6);
422
432
  if (!r) return false;
423
433
  if (r.fsPath === "/") return true;
424
434
  return r.fs.exists(r.fsPath);
425
435
  }
426
- async stat(path4) {
427
- const normalized = this.normalizePath(path4);
428
- if (this.isVirtualPath(path4)) {
436
+ async stat(path6) {
437
+ const normalized = this.normalizePath(path6);
438
+ if (this.isVirtualPath(path6)) {
429
439
  const parts = normalized.split("/").filter(Boolean);
430
440
  const now = /* @__PURE__ */ new Date();
431
441
  return {
@@ -437,8 +447,8 @@ var CompositeFilesystem = class {
437
447
  modifiedAt: now
438
448
  };
439
449
  }
440
- const r = this.resolveMount(path4);
441
- if (!r) throw new Error(`No mount for path: ${path4}`);
450
+ const r = this.resolveMount(path6);
451
+ if (!r) throw new Error(`No mount for path: ${path6}`);
442
452
  if (r.fsPath === "/") {
443
453
  const parts = normalized.split("/").filter(Boolean);
444
454
  const now = /* @__PURE__ */ new Date();
@@ -453,9 +463,9 @@ var CompositeFilesystem = class {
453
463
  }
454
464
  return r.fs.stat(r.fsPath);
455
465
  }
456
- async isFile(path4) {
457
- if (this.isVirtualPath(path4)) return false;
458
- const r = this.resolveMount(path4);
466
+ async isFile(path6) {
467
+ if (this.isVirtualPath(path6)) return false;
468
+ const r = this.resolveMount(path6);
459
469
  if (!r) return false;
460
470
  try {
461
471
  const stat3 = await r.fs.stat(r.fsPath);
@@ -464,9 +474,9 @@ var CompositeFilesystem = class {
464
474
  return false;
465
475
  }
466
476
  }
467
- async isDirectory(path4) {
468
- if (this.isVirtualPath(path4)) return true;
469
- const r = this.resolveMount(path4);
477
+ async isDirectory(path6) {
478
+ if (this.isVirtualPath(path6)) return true;
479
+ const r = this.resolveMount(path6);
470
480
  if (!r) return false;
471
481
  if (r.fsPath === "/") return true;
472
482
  try {
@@ -769,6 +779,17 @@ function isTextFile(filename) {
769
779
  const ext = nodePath__namespace.extname(filename).toLowerCase();
770
780
  return TEXT_EXTENSIONS.has(ext);
771
781
  }
782
+ function resolveWorkspacePath(basePath, filePath) {
783
+ if (nodePath__namespace.isAbsolute(filePath)) {
784
+ const normalizedBase = nodePath__namespace.normalize(basePath);
785
+ const normalizedFile = nodePath__namespace.normalize(filePath);
786
+ const rel = nodePath__namespace.relative(normalizedBase, normalizedFile);
787
+ if (!rel.startsWith("..") && !nodePath__namespace.isAbsolute(rel)) {
788
+ return normalizedFile;
789
+ }
790
+ }
791
+ return nodePath__namespace.join(basePath, filePath.replace(/^\/+/, ""));
792
+ }
772
793
  async function fsExists(absolutePath) {
773
794
  try {
774
795
  await fs2__namespace.access(absolutePath);
@@ -856,8 +877,8 @@ var LocalFilesystem = class extends MastraFilesystem {
856
877
  _isWithinAnyRoot(absolutePath) {
857
878
  const roots = [this._basePath, ...this._allowedPaths];
858
879
  return roots.some((root) => {
859
- const relative2 = nodePath__namespace.relative(root, absolutePath);
860
- return !relative2.startsWith("..") && !nodePath__namespace.isAbsolute(relative2);
880
+ const relative3 = nodePath__namespace.relative(root, absolutePath);
881
+ return !relative3.startsWith("..") && !nodePath__namespace.isAbsolute(relative3);
861
882
  });
862
883
  }
863
884
  toBuffer(content) {
@@ -874,12 +895,10 @@ var LocalFilesystem = class extends MastraFilesystem {
874
895
  if (this._isWithinAnyRoot(normalized)) {
875
896
  absolutePath = normalized;
876
897
  } else {
877
- const cleanedPath = inputPath.replace(/^\/+/, "");
878
- absolutePath = nodePath__namespace.resolve(this._basePath, nodePath__namespace.normalize(cleanedPath));
898
+ absolutePath = resolveWorkspacePath(this._basePath, inputPath);
879
899
  }
880
900
  } else {
881
- const cleanedPath = inputPath.replace(/^\/+/, "");
882
- absolutePath = nodePath__namespace.resolve(this._basePath, nodePath__namespace.normalize(cleanedPath));
901
+ absolutePath = resolveWorkspacePath(this._basePath, inputPath);
883
902
  }
884
903
  if (this._contained) {
885
904
  if (!this._isWithinAnyRoot(absolutePath)) {
@@ -888,6 +907,18 @@ var LocalFilesystem = class extends MastraFilesystem {
888
907
  }
889
908
  return absolutePath;
890
909
  }
910
+ /**
911
+ * Resolve a workspace-relative path to an absolute disk path.
912
+ * Uses the same resolution logic as internal file operations.
913
+ * Returns `undefined` if the path violates containment.
914
+ */
915
+ resolveAbsolutePath(inputPath) {
916
+ try {
917
+ return this.resolvePath(inputPath);
918
+ } catch {
919
+ return void 0;
920
+ }
921
+ }
891
922
  toRelativePath(absolutePath) {
892
923
  return "/" + nodePath__namespace.relative(this._basePath, absolutePath).replace(/\\/g, "/");
893
924
  }
@@ -1321,35 +1352,35 @@ var LocalFilesystem = class extends MastraFilesystem {
1321
1352
  };
1322
1353
  var InMemoryFileReadTracker = class {
1323
1354
  records = /* @__PURE__ */ new Map();
1324
- recordRead(path4, modifiedAt) {
1325
- const normalizedPath = this.normalizePath(path4);
1355
+ recordRead(path6, modifiedAt) {
1356
+ const normalizedPath = this.normalizePath(path6);
1326
1357
  this.records.set(normalizedPath, {
1327
1358
  path: normalizedPath,
1328
1359
  readAt: /* @__PURE__ */ new Date(),
1329
1360
  modifiedAtRead: modifiedAt
1330
1361
  });
1331
1362
  }
1332
- getReadRecord(path4) {
1333
- return this.records.get(this.normalizePath(path4));
1363
+ getReadRecord(path6) {
1364
+ return this.records.get(this.normalizePath(path6));
1334
1365
  }
1335
- needsReRead(path4, currentModifiedAt) {
1336
- const record = this.getReadRecord(path4);
1366
+ needsReRead(path6, currentModifiedAt) {
1367
+ const record = this.getReadRecord(path6);
1337
1368
  if (!record) {
1338
1369
  return {
1339
1370
  needsReRead: true,
1340
- reason: `File "${path4}" has not been read. You must read a file before writing to it.`
1371
+ reason: `File "${path6}" has not been read. You must read a file before writing to it.`
1341
1372
  };
1342
1373
  }
1343
1374
  if (currentModifiedAt.getTime() > record.modifiedAtRead.getTime()) {
1344
1375
  return {
1345
1376
  needsReRead: true,
1346
- reason: `File "${path4}" was modified since last read (read at: ${record.modifiedAtRead.toISOString()}, current: ${currentModifiedAt.toISOString()}). Please re-read the file to get the latest contents.`
1377
+ reason: `File "${path6}" was modified since last read (read at: ${record.modifiedAtRead.toISOString()}, current: ${currentModifiedAt.toISOString()}). Please re-read the file to get the latest contents.`
1347
1378
  };
1348
1379
  }
1349
1380
  return { needsReRead: false };
1350
1381
  }
1351
- clearReadRecord(path4) {
1352
- this.records.delete(this.normalizePath(path4));
1382
+ clearReadRecord(path6) {
1383
+ this.records.delete(this.normalizePath(path6));
1353
1384
  }
1354
1385
  clear() {
1355
1386
  this.records.clear();
@@ -1437,11 +1468,721 @@ function createGlobMatcher(patterns, options) {
1437
1468
  posix: true,
1438
1469
  dot: options?.dot ?? false
1439
1470
  });
1440
- return (path4) => matcher(normalizeForMatch(path4));
1471
+ return (path6) => matcher(normalizeForMatch(path6));
1472
+ }
1473
+ function matchGlob(path6, pattern, options) {
1474
+ return createGlobMatcher(pattern, options)(path6);
1475
+ }
1476
+
1477
+ // src/workspace/lsp/language.ts
1478
+ var LANGUAGE_EXTENSIONS = {
1479
+ // TypeScript/JavaScript
1480
+ ".ts": "typescript",
1481
+ ".tsx": "typescriptreact",
1482
+ ".js": "javascript",
1483
+ ".jsx": "javascriptreact",
1484
+ ".mjs": "javascript",
1485
+ ".cjs": "javascript",
1486
+ // Python
1487
+ ".py": "python",
1488
+ ".pyi": "python",
1489
+ // Go
1490
+ ".go": "go",
1491
+ // Rust
1492
+ ".rs": "rust",
1493
+ // C/C++
1494
+ ".c": "c",
1495
+ ".cpp": "cpp",
1496
+ ".cc": "cpp",
1497
+ ".cxx": "cpp",
1498
+ ".h": "c",
1499
+ ".hpp": "cpp",
1500
+ // Java
1501
+ ".java": "java",
1502
+ // JSON
1503
+ ".json": "json",
1504
+ ".jsonc": "jsonc",
1505
+ // YAML
1506
+ ".yaml": "yaml",
1507
+ ".yml": "yaml",
1508
+ // Markdown
1509
+ ".md": "markdown",
1510
+ // HTML/CSS
1511
+ ".html": "html",
1512
+ ".css": "css",
1513
+ ".scss": "scss",
1514
+ ".sass": "sass",
1515
+ ".less": "less"
1516
+ };
1517
+ function getLanguageId(filePath) {
1518
+ const dotIndex = filePath.lastIndexOf(".");
1519
+ if (dotIndex === -1) return void 0;
1520
+ const ext = filePath.substring(dotIndex);
1521
+ return LANGUAGE_EXTENSIONS[ext];
1522
+ }
1523
+ var jsonrpcModule;
1524
+ var lspProtocolModule;
1525
+ function isLSPAvailable() {
1526
+ if (jsonrpcModule !== void 0) {
1527
+ return jsonrpcModule !== null;
1528
+ }
1529
+ try {
1530
+ const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-QKQGKEN7.cjs', document.baseURI).href)));
1531
+ req.resolve("vscode-jsonrpc/node");
1532
+ req.resolve("vscode-languageserver-protocol");
1533
+ return true;
1534
+ } catch {
1535
+ return false;
1536
+ }
1537
+ }
1538
+ async function loadLSPDeps() {
1539
+ if (jsonrpcModule !== void 0 && lspProtocolModule !== void 0) {
1540
+ if (jsonrpcModule === null || lspProtocolModule === null) return null;
1541
+ return { ...jsonrpcModule, ...lspProtocolModule };
1542
+ }
1543
+ try {
1544
+ const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-QKQGKEN7.cjs', document.baseURI).href)));
1545
+ const jsonrpc = req("vscode-jsonrpc/node");
1546
+ const protocol = req("vscode-languageserver-protocol");
1547
+ jsonrpcModule = {
1548
+ StreamMessageReader: jsonrpc.StreamMessageReader,
1549
+ StreamMessageWriter: jsonrpc.StreamMessageWriter,
1550
+ createMessageConnection: jsonrpc.createMessageConnection
1551
+ };
1552
+ lspProtocolModule = {
1553
+ TextDocumentIdentifier: protocol.TextDocumentIdentifier,
1554
+ Position: protocol.Position
1555
+ };
1556
+ return { ...jsonrpcModule, ...lspProtocolModule };
1557
+ } catch {
1558
+ jsonrpcModule = null;
1559
+ lspProtocolModule = null;
1560
+ return null;
1561
+ }
1562
+ }
1563
+ function toFileUri(fsPath) {
1564
+ return url.pathToFileURL(fsPath).toString();
1565
+ }
1566
+ var LSPClient = class {
1567
+ connection = null;
1568
+ handle = null;
1569
+ serverDef;
1570
+ workspaceRoot;
1571
+ processManager;
1572
+ diagnostics = /* @__PURE__ */ new Map();
1573
+ initializationOptions = null;
1574
+ constructor(serverDef, workspaceRoot, processManager) {
1575
+ this.serverDef = serverDef;
1576
+ this.workspaceRoot = workspaceRoot;
1577
+ this.processManager = processManager;
1578
+ }
1579
+ /** Whether the underlying server process is still running. */
1580
+ get isAlive() {
1581
+ return this.handle !== null && this.handle.exitCode === void 0;
1582
+ }
1583
+ /**
1584
+ * Initialize the LSP connection — spawns the server and performs the handshake.
1585
+ */
1586
+ async initialize(initTimeout = 1e4) {
1587
+ const deps = await loadLSPDeps();
1588
+ if (!deps) {
1589
+ throw new Error("LSP dependencies (vscode-jsonrpc) are not available");
1590
+ }
1591
+ const { StreamMessageReader, StreamMessageWriter, createMessageConnection } = deps;
1592
+ const command = this.serverDef.command(this.workspaceRoot);
1593
+ if (!command) {
1594
+ throw new Error("Failed to resolve LSP server command");
1595
+ }
1596
+ this.handle = await this.processManager.spawn(command, { cwd: this.workspaceRoot });
1597
+ const initializationOptions = this.serverDef.initialization?.(this.workspaceRoot);
1598
+ const reader = new StreamMessageReader(this.handle.reader);
1599
+ const writer = new StreamMessageWriter(this.handle.writer);
1600
+ this.connection = createMessageConnection(reader, writer);
1601
+ this.connection.onError(() => {
1602
+ });
1603
+ this.connection.onNotification("textDocument/publishDiagnostics", (params) => {
1604
+ this.diagnostics.set(params.uri, params.diagnostics);
1605
+ });
1606
+ this.connection.listen();
1607
+ const initParams = {
1608
+ processId: process.pid,
1609
+ rootUri: toFileUri(this.workspaceRoot),
1610
+ workspaceFolders: [
1611
+ {
1612
+ name: "workspace",
1613
+ uri: toFileUri(this.workspaceRoot)
1614
+ }
1615
+ ],
1616
+ capabilities: {
1617
+ window: { workDoneProgress: true },
1618
+ workspace: { configuration: true },
1619
+ textDocument: {
1620
+ publishDiagnostics: {
1621
+ relatedInformation: true,
1622
+ tagSupport: { valueSet: [1, 2] },
1623
+ versionSupport: false
1624
+ },
1625
+ synchronization: {
1626
+ didOpen: true,
1627
+ didChange: true,
1628
+ dynamicRegistration: false,
1629
+ willSave: false,
1630
+ willSaveWaitUntil: false,
1631
+ didSave: false
1632
+ },
1633
+ completion: {
1634
+ dynamicRegistration: false,
1635
+ completionItem: {
1636
+ snippetSupport: false,
1637
+ commitCharactersSupport: false,
1638
+ documentationFormat: ["markdown", "plaintext"],
1639
+ deprecatedSupport: false,
1640
+ preselectSupport: false
1641
+ }
1642
+ },
1643
+ definition: { dynamicRegistration: false, linkSupport: true },
1644
+ typeDefinition: { dynamicRegistration: false, linkSupport: true },
1645
+ implementation: { dynamicRegistration: false, linkSupport: true },
1646
+ references: { dynamicRegistration: false },
1647
+ documentHighlight: { dynamicRegistration: false },
1648
+ documentSymbol: { dynamicRegistration: false, hierarchicalDocumentSymbolSupport: true },
1649
+ codeAction: {
1650
+ dynamicRegistration: false,
1651
+ codeActionLiteralSupport: {
1652
+ codeActionKind: {
1653
+ valueSet: [
1654
+ "quickfix",
1655
+ "refactor",
1656
+ "refactor.extract",
1657
+ "refactor.inline",
1658
+ "refactor.rewrite",
1659
+ "source",
1660
+ "source.organizeImports"
1661
+ ]
1662
+ }
1663
+ }
1664
+ },
1665
+ hover: { dynamicRegistration: false, contentFormat: ["markdown", "plaintext"] }
1666
+ }
1667
+ }
1668
+ };
1669
+ if (initializationOptions) {
1670
+ initParams.initializationOptions = initializationOptions;
1671
+ this.initializationOptions = initializationOptions;
1672
+ }
1673
+ this.connection.onRequest("workspace/configuration", (params) => {
1674
+ return params.items?.map(() => ({})) || [];
1675
+ });
1676
+ this.connection.onRequest("window/workDoneProgress/create", () => null);
1677
+ let initTimer;
1678
+ await Promise.race([
1679
+ this.connection.sendRequest("initialize", initParams),
1680
+ new Promise((_, reject) => {
1681
+ initTimer = setTimeout(() => reject(new Error("LSP initialize request timed out")), initTimeout);
1682
+ })
1683
+ ]).finally(() => clearTimeout(initTimer));
1684
+ this.connection.sendNotification("initialized", {});
1685
+ this.connection.sendNotification("workspace/didChangeConfiguration", {
1686
+ settings: this.initializationOptions ?? {}
1687
+ });
1688
+ }
1689
+ /**
1690
+ * Notify the server that a document has been opened.
1691
+ */
1692
+ notifyOpen(filePath, content, languageId) {
1693
+ if (!this.connection) return;
1694
+ const uri = toFileUri(filePath);
1695
+ this.diagnostics.delete(uri);
1696
+ this.connection.sendNotification("textDocument/didOpen", {
1697
+ textDocument: { uri, languageId, version: 0, text: content }
1698
+ });
1699
+ }
1700
+ /**
1701
+ * Notify the server that a document has changed.
1702
+ */
1703
+ notifyChange(filePath, content, version) {
1704
+ if (!this.connection) return;
1705
+ this.connection.sendNotification("textDocument/didChange", {
1706
+ textDocument: { uri: toFileUri(filePath), version },
1707
+ contentChanges: [{ text: content }]
1708
+ });
1709
+ }
1710
+ /**
1711
+ * Wait for diagnostics to arrive for a file.
1712
+ *
1713
+ * When `waitForChange` is false (default), returns as soon as diagnostics
1714
+ * are available. To avoid returning a premature empty array (servers may
1715
+ * publish `[]` first while still analysing), empty results trigger a short
1716
+ * settle window: polling continues for up to `settleMs` (default 500ms)
1717
+ * to see if non-empty diagnostics arrive. Non-empty results are returned
1718
+ * immediately.
1719
+ */
1720
+ async waitForDiagnostics(filePath, timeoutMs = 5e3, waitForChange = false, settleMs = 500) {
1721
+ if (!this.connection) return [];
1722
+ const uri = toFileUri(filePath);
1723
+ const startTime = Date.now();
1724
+ const initialDiagnostics = this.diagnostics.get(uri);
1725
+ let emptyReceivedAt;
1726
+ while (Date.now() - startTime < timeoutMs) {
1727
+ const currentDiagnostics = this.diagnostics.get(uri);
1728
+ if (waitForChange) {
1729
+ if (currentDiagnostics !== void 0 && currentDiagnostics !== initialDiagnostics) {
1730
+ return currentDiagnostics;
1731
+ }
1732
+ } else {
1733
+ if (currentDiagnostics !== void 0) {
1734
+ if (currentDiagnostics.length > 0) return currentDiagnostics;
1735
+ if (emptyReceivedAt === void 0) emptyReceivedAt = Date.now();
1736
+ if (Date.now() - emptyReceivedAt >= settleMs) return currentDiagnostics;
1737
+ }
1738
+ }
1739
+ await new Promise((resolve3) => setTimeout(resolve3, 100));
1740
+ }
1741
+ return waitForChange ? initialDiagnostics || [] : this.diagnostics.get(uri) || [];
1742
+ }
1743
+ /**
1744
+ * Notify the server that a document was closed.
1745
+ */
1746
+ notifyClose(filePath) {
1747
+ if (!this.connection) return;
1748
+ const uri = toFileUri(filePath);
1749
+ this.diagnostics.delete(uri);
1750
+ this.connection.sendNotification("textDocument/didClose", {
1751
+ textDocument: { uri }
1752
+ });
1753
+ }
1754
+ /**
1755
+ * Shutdown the connection and kill the process.
1756
+ */
1757
+ async shutdown() {
1758
+ if (this.connection) {
1759
+ try {
1760
+ if (this.handle && this.handle.exitCode === void 0) {
1761
+ let shutdownTimer;
1762
+ await Promise.race([
1763
+ this.connection.sendRequest("shutdown"),
1764
+ new Promise((_, reject) => {
1765
+ shutdownTimer = setTimeout(() => reject(new Error("Shutdown request timed out")), 1e3);
1766
+ })
1767
+ ]).finally(() => clearTimeout(shutdownTimer));
1768
+ this.connection.sendNotification("exit");
1769
+ }
1770
+ } catch {
1771
+ }
1772
+ try {
1773
+ this.connection.dispose();
1774
+ } catch {
1775
+ }
1776
+ this.connection = null;
1777
+ }
1778
+ if (this.handle) {
1779
+ try {
1780
+ await this.handle.kill();
1781
+ } catch {
1782
+ }
1783
+ this.handle = null;
1784
+ }
1785
+ this.diagnostics = /* @__PURE__ */ new Map();
1786
+ }
1787
+ };
1788
+ function whichSync(binary) {
1789
+ try {
1790
+ const cmd = process.platform === "win32" ? "where" : "which";
1791
+ childProcess.execFileSync(cmd, [binary], { stdio: "ignore" });
1792
+ return true;
1793
+ } catch {
1794
+ return false;
1795
+ }
1796
+ }
1797
+ function resolveRequire(root, moduleId) {
1798
+ try {
1799
+ const req = module$1.createRequire(url.pathToFileURL(nodePath.join(root, "package.json")));
1800
+ return { require: req, resolved: req.resolve(moduleId) };
1801
+ } catch {
1802
+ }
1803
+ try {
1804
+ const req = module$1.createRequire(url.pathToFileURL(nodePath.join(process.cwd(), "package.json")));
1805
+ return { require: req, resolved: req.resolve(moduleId) };
1806
+ } catch {
1807
+ return null;
1808
+ }
1809
+ }
1810
+ function walkUp(startDir, markers) {
1811
+ let current = startDir;
1812
+ const fsRoot = nodePath.parse(current).root;
1813
+ while (true) {
1814
+ for (const marker of markers) {
1815
+ if (fs.existsSync(nodePath.join(current, marker))) {
1816
+ return current;
1817
+ }
1818
+ }
1819
+ if (current === fsRoot) break;
1820
+ const parent = nodePath.dirname(current);
1821
+ if (parent === current) break;
1822
+ current = parent;
1823
+ }
1824
+ return null;
1825
+ }
1826
+ async function walkUpAsync(startDir, markers, fs5) {
1827
+ let current = startDir;
1828
+ const fsRoot = nodePath.parse(current).root;
1829
+ while (true) {
1830
+ for (const marker of markers) {
1831
+ if (await fs5.exists(nodePath.join(current, marker))) {
1832
+ return current;
1833
+ }
1834
+ }
1835
+ if (current === fsRoot) break;
1836
+ const parent = nodePath.dirname(current);
1837
+ if (parent === current) break;
1838
+ current = parent;
1839
+ }
1840
+ return null;
1841
+ }
1842
+ var DEFAULT_MARKERS = [
1843
+ "tsconfig.json",
1844
+ "package.json",
1845
+ "pyproject.toml",
1846
+ "go.mod",
1847
+ "Cargo.toml",
1848
+ "composer.json",
1849
+ ".git"
1850
+ ];
1851
+ function findProjectRoot(startDir) {
1852
+ return walkUp(startDir, DEFAULT_MARKERS);
1853
+ }
1854
+ var BUILTIN_SERVERS = {
1855
+ typescript: {
1856
+ id: "typescript",
1857
+ name: "TypeScript Language Server",
1858
+ languageIds: ["typescript", "typescriptreact", "javascript", "javascriptreact"],
1859
+ markers: ["tsconfig.json", "package.json"],
1860
+ command: (root) => {
1861
+ const ts = resolveRequire(root, "typescript/lib/tsserver.js");
1862
+ if (!ts) return void 0;
1863
+ const localBin = nodePath.join(root, "node_modules", ".bin", "typescript-language-server");
1864
+ const cwdBin = nodePath.join(process.cwd(), "node_modules", ".bin", "typescript-language-server");
1865
+ if (fs.existsSync(localBin)) return `${localBin} --stdio`;
1866
+ if (fs.existsSync(cwdBin)) return `${cwdBin} --stdio`;
1867
+ return void 0;
1868
+ },
1869
+ initialization: (root) => {
1870
+ const ts = resolveRequire(root, "typescript/lib/tsserver.js");
1871
+ if (!ts) return void 0;
1872
+ return {
1873
+ tsserver: {
1874
+ path: ts.resolved,
1875
+ logVerbosity: "off"
1876
+ }
1877
+ };
1878
+ }
1879
+ },
1880
+ eslint: {
1881
+ id: "eslint",
1882
+ name: "ESLint Language Server",
1883
+ languageIds: ["typescript", "typescriptreact", "javascript", "javascriptreact"],
1884
+ markers: [
1885
+ "package.json",
1886
+ ".eslintrc.js",
1887
+ ".eslintrc.json",
1888
+ ".eslintrc.yml",
1889
+ ".eslintrc.yaml",
1890
+ "eslint.config.js",
1891
+ "eslint.config.mjs",
1892
+ "eslint.config.ts"
1893
+ ],
1894
+ command: (root) => {
1895
+ const localBin = nodePath.join(root, "node_modules", ".bin", "vscode-eslint-language-server");
1896
+ const cwdBin = nodePath.join(process.cwd(), "node_modules", ".bin", "vscode-eslint-language-server");
1897
+ if (fs.existsSync(localBin)) return `${localBin} --stdio`;
1898
+ if (fs.existsSync(cwdBin)) return `${cwdBin} --stdio`;
1899
+ return void 0;
1900
+ }
1901
+ },
1902
+ python: {
1903
+ id: "python",
1904
+ name: "Python Language Server (Pyright)",
1905
+ languageIds: ["python"],
1906
+ markers: ["pyproject.toml", "setup.py", "requirements.txt", "setup.cfg"],
1907
+ command: (root) => {
1908
+ const localBin = nodePath.join(root, "node_modules", ".bin", "pyright-langserver");
1909
+ const cwdBin = nodePath.join(process.cwd(), "node_modules", ".bin", "pyright-langserver");
1910
+ if (fs.existsSync(localBin)) return `${localBin} --stdio`;
1911
+ if (fs.existsSync(cwdBin)) return `${cwdBin} --stdio`;
1912
+ return whichSync("pyright-langserver") ? "pyright-langserver --stdio" : void 0;
1913
+ }
1914
+ },
1915
+ go: {
1916
+ id: "go",
1917
+ name: "Go Language Server (gopls)",
1918
+ languageIds: ["go"],
1919
+ markers: ["go.mod"],
1920
+ command: () => {
1921
+ return whichSync("gopls") ? "gopls serve" : void 0;
1922
+ }
1923
+ },
1924
+ rust: {
1925
+ id: "rust",
1926
+ name: "Rust Language Server (rust-analyzer)",
1927
+ languageIds: ["rust"],
1928
+ markers: ["Cargo.toml"],
1929
+ command: () => {
1930
+ return whichSync("rust-analyzer") ? "rust-analyzer --stdio" : void 0;
1931
+ }
1932
+ }
1933
+ };
1934
+ function getServersForFile(filePath, disabledServers) {
1935
+ const languageId = getLanguageId(filePath);
1936
+ if (!languageId) return [];
1937
+ const disabled = new Set(disabledServers ?? []);
1938
+ return Object.values(BUILTIN_SERVERS).filter(
1939
+ (server) => !disabled.has(server.id) && server.languageIds.includes(languageId)
1940
+ );
1441
1941
  }
1442
- function matchGlob(path4, pattern, options) {
1443
- return createGlobMatcher(pattern, options)(path4);
1942
+ function mapSeverity(severity) {
1943
+ switch (severity) {
1944
+ case 1:
1945
+ return "error";
1946
+ case 2:
1947
+ return "warning";
1948
+ case 3:
1949
+ return "info";
1950
+ case 4:
1951
+ return "hint";
1952
+ default:
1953
+ return "warning";
1954
+ }
1444
1955
  }
1956
+ var LSPManager = class {
1957
+ clients = /* @__PURE__ */ new Map();
1958
+ initPromises = /* @__PURE__ */ new Map();
1959
+ fileLocks = /* @__PURE__ */ new Map();
1960
+ processManager;
1961
+ _root;
1962
+ config;
1963
+ filesystem;
1964
+ constructor(processManager, root, config = {}, filesystem) {
1965
+ this.processManager = processManager;
1966
+ this._root = root;
1967
+ this.config = config;
1968
+ this.filesystem = filesystem;
1969
+ }
1970
+ /** Default project root (fallback when per-file walkup finds nothing). */
1971
+ get root() {
1972
+ return this._root;
1973
+ }
1974
+ /**
1975
+ * Resolve the project root for a given file path using the server's markers.
1976
+ * Uses the workspace filesystem when available (supports remote filesystems),
1977
+ * falls back to sync walkUp (local disk) otherwise.
1978
+ */
1979
+ async resolveRoot(filePath, markers) {
1980
+ const fileDir = nodePath__namespace.default.dirname(filePath);
1981
+ if (this.filesystem) {
1982
+ return await walkUpAsync(fileDir, markers, this.filesystem) ?? this._root;
1983
+ }
1984
+ return walkUp(fileDir, markers) ?? this._root;
1985
+ }
1986
+ /**
1987
+ * Acquire a per-file lock so that concurrent getDiagnostics calls for the
1988
+ * same file are serialized (preventing interleaved open/change/close).
1989
+ * Different files can run in parallel.
1990
+ */
1991
+ async acquireFileLock(filePath) {
1992
+ while (this.fileLocks.has(filePath)) {
1993
+ await this.fileLocks.get(filePath);
1994
+ }
1995
+ let release;
1996
+ const lockPromise = new Promise((resolve3) => {
1997
+ release = resolve3;
1998
+ });
1999
+ this.fileLocks.set(filePath, lockPromise);
2000
+ return () => {
2001
+ this.fileLocks.delete(filePath);
2002
+ release();
2003
+ };
2004
+ }
2005
+ /**
2006
+ * Initialize an LSP client for the given server definition and project root.
2007
+ * Handles timeout, deduplication of concurrent init calls, and caching.
2008
+ */
2009
+ async initClient(serverDef, projectRoot, key) {
2010
+ if (this.initPromises.has(key)) {
2011
+ await this.initPromises.get(key);
2012
+ return this.clients.get(key) || null;
2013
+ }
2014
+ const initTimeout = this.config.initTimeout ?? 15e3;
2015
+ let timedOut = false;
2016
+ const initPromise = (async () => {
2017
+ const client = new LSPClient(serverDef, projectRoot, this.processManager);
2018
+ await client.initialize(initTimeout);
2019
+ if (timedOut) {
2020
+ await client.shutdown().catch(() => {
2021
+ });
2022
+ return;
2023
+ }
2024
+ this.clients.set(key, client);
2025
+ })();
2026
+ this.initPromises.set(key, initPromise);
2027
+ initPromise.catch(() => {
2028
+ });
2029
+ try {
2030
+ await Promise.race([
2031
+ initPromise,
2032
+ new Promise(
2033
+ (_, reject) => setTimeout(() => reject(new Error("LSP client initialization timed out")), initTimeout + 1e3)
2034
+ )
2035
+ ]);
2036
+ return this.clients.get(key) || null;
2037
+ } catch {
2038
+ timedOut = true;
2039
+ this.clients.delete(key);
2040
+ return null;
2041
+ } finally {
2042
+ this.initPromises.delete(key);
2043
+ }
2044
+ }
2045
+ /**
2046
+ * Get or create an LSP client for a file path.
2047
+ * Resolves the project root per-file using the server's markers.
2048
+ * Returns null if no server is available.
2049
+ */
2050
+ async getClient(filePath) {
2051
+ const servers = getServersForFile(filePath, this.config.disableServers);
2052
+ if (servers.length === 0) return null;
2053
+ const serverDef = servers.find(
2054
+ (s) => s.languageIds.includes("typescript") || s.languageIds.includes("javascript") || s.languageIds.includes("python") || s.languageIds.includes("go")
2055
+ ) ?? servers[0];
2056
+ const projectRoot = await this.resolveRoot(filePath, serverDef.markers);
2057
+ if (serverDef.command(projectRoot) === void 0) return null;
2058
+ const key = `${serverDef.name}:${projectRoot}`;
2059
+ if (this.clients.has(key)) {
2060
+ const existing = this.clients.get(key);
2061
+ if (!existing.isAlive) {
2062
+ this.clients.delete(key);
2063
+ existing.shutdown().catch(() => {
2064
+ });
2065
+ } else {
2066
+ return existing;
2067
+ }
2068
+ }
2069
+ return this.initClient(serverDef, projectRoot, key);
2070
+ }
2071
+ /**
2072
+ * Convenience method: open file, send content, wait for diagnostics, return normalized results.
2073
+ * Returns an empty array on any failure (non-blocking).
2074
+ * Uses a per-file lock to serialize concurrent calls for the same file.
2075
+ */
2076
+ async getDiagnostics(filePath, content) {
2077
+ const release = await this.acquireFileLock(filePath);
2078
+ try {
2079
+ const client = await this.getClient(filePath);
2080
+ if (!client) return [];
2081
+ const languageId = getLanguageId(filePath);
2082
+ if (!languageId) return [];
2083
+ client.notifyOpen(filePath, content, languageId);
2084
+ client.notifyChange(filePath, content, 1);
2085
+ const diagnosticTimeout = this.config.diagnosticTimeout ?? 5e3;
2086
+ let rawDiagnostics;
2087
+ try {
2088
+ rawDiagnostics = await client.waitForDiagnostics(filePath, diagnosticTimeout);
2089
+ } finally {
2090
+ client.notifyClose(filePath);
2091
+ }
2092
+ return rawDiagnostics.map((d) => ({
2093
+ severity: mapSeverity(d.severity),
2094
+ message: d.message,
2095
+ line: (d.range?.start?.line ?? 0) + 1,
2096
+ // LSP is 0-indexed, we report 1-indexed
2097
+ character: (d.range?.start?.character ?? 0) + 1,
2098
+ source: d.source
2099
+ }));
2100
+ } catch {
2101
+ return [];
2102
+ } finally {
2103
+ release();
2104
+ }
2105
+ }
2106
+ /**
2107
+ * Get diagnostics from ALL matching language servers for a file.
2108
+ * Deduplicates results by (line, character, message).
2109
+ * Individual server failures don't block other servers.
2110
+ */
2111
+ async getDiagnosticsMulti(filePath, content) {
2112
+ const servers = getServersForFile(filePath, this.config.disableServers);
2113
+ if (servers.length === 0) return [];
2114
+ const release = await this.acquireFileLock(filePath);
2115
+ try {
2116
+ const languageId = getLanguageId(filePath);
2117
+ if (!languageId) return [];
2118
+ const allDiagnostics = [];
2119
+ const results = await Promise.allSettled(
2120
+ servers.map(async (serverDef) => {
2121
+ const projectRoot = await this.resolveRoot(filePath, serverDef.markers);
2122
+ if (serverDef.command(projectRoot) === void 0) return [];
2123
+ const key = `${serverDef.name}:${projectRoot}`;
2124
+ if (this.clients.has(key)) {
2125
+ const existing = this.clients.get(key);
2126
+ if (!existing.isAlive) {
2127
+ this.clients.delete(key);
2128
+ existing.shutdown().catch(() => {
2129
+ });
2130
+ } else {
2131
+ return this.collectDiagnostics(existing, filePath, content, languageId);
2132
+ }
2133
+ }
2134
+ const client = await this.initClient(serverDef, projectRoot, key);
2135
+ if (!client) return [];
2136
+ return this.collectDiagnostics(client, filePath, content, languageId);
2137
+ })
2138
+ );
2139
+ for (const result of results) {
2140
+ if (result.status === "fulfilled") {
2141
+ allDiagnostics.push(...result.value);
2142
+ }
2143
+ }
2144
+ const seen = /* @__PURE__ */ new Set();
2145
+ return allDiagnostics.filter((d) => {
2146
+ const key = `${d.line}:${d.character}:${d.message}`;
2147
+ if (seen.has(key)) return false;
2148
+ seen.add(key);
2149
+ return true;
2150
+ });
2151
+ } finally {
2152
+ release();
2153
+ }
2154
+ }
2155
+ /**
2156
+ * Collect diagnostics from a single client for a file.
2157
+ */
2158
+ async collectDiagnostics(client, filePath, content, languageId) {
2159
+ client.notifyOpen(filePath, content, languageId);
2160
+ client.notifyChange(filePath, content, 1);
2161
+ const diagnosticTimeout = this.config.diagnosticTimeout ?? 5e3;
2162
+ let rawDiagnostics;
2163
+ try {
2164
+ rawDiagnostics = await client.waitForDiagnostics(filePath, diagnosticTimeout);
2165
+ } finally {
2166
+ client.notifyClose(filePath);
2167
+ }
2168
+ return rawDiagnostics.map((d) => ({
2169
+ severity: mapSeverity(d.severity),
2170
+ message: d.message,
2171
+ line: (d.range?.start?.line ?? 0) + 1,
2172
+ character: (d.range?.start?.character ?? 0) + 1,
2173
+ source: d.source
2174
+ }));
2175
+ }
2176
+ /**
2177
+ * Shutdown all managed LSP clients.
2178
+ */
2179
+ async shutdownAll() {
2180
+ await Promise.allSettled(Array.from(this.clients.values()).map((client) => client.shutdown()));
2181
+ this.clients.clear();
2182
+ this.initPromises.clear();
2183
+ this.fileLocks.clear();
2184
+ }
2185
+ };
1445
2186
 
1446
2187
  // src/workspace/sandbox/errors.ts
1447
2188
  var SandboxError = class extends Error {
@@ -1551,14 +2292,14 @@ var MountManager = class {
1551
2292
  /**
1552
2293
  * Get a mount entry by path.
1553
2294
  */
1554
- get(path4) {
1555
- return this._entries.get(path4);
2295
+ get(path6) {
2296
+ return this._entries.get(path6);
1556
2297
  }
1557
2298
  /**
1558
2299
  * Check if a mount exists at the given path.
1559
2300
  */
1560
- has(path4) {
1561
- return this._entries.has(path4);
2301
+ has(path6) {
2302
+ return this._entries.has(path6);
1562
2303
  }
1563
2304
  // ---------------------------------------------------------------------------
1564
2305
  // Entry Modification
@@ -1570,8 +2311,8 @@ var MountManager = class {
1570
2311
  add(mounts) {
1571
2312
  const paths = Object.keys(mounts);
1572
2313
  this.logger.debug(`Adding ${paths.length} pending mount(s)`, { paths });
1573
- for (const [path4, filesystem] of Object.entries(mounts)) {
1574
- this._entries.set(path4, {
2314
+ for (const [path6, filesystem] of Object.entries(mounts)) {
2315
+ this._entries.set(path6, {
1575
2316
  filesystem,
1576
2317
  state: "pending"
1577
2318
  });
@@ -1581,8 +2322,8 @@ var MountManager = class {
1581
2322
  * Update a mount entry's state.
1582
2323
  * Creates the entry if it doesn't exist.
1583
2324
  */
1584
- set(path4, updates) {
1585
- const existing = this._entries.get(path4);
2325
+ set(path6, updates) {
2326
+ const existing = this._entries.get(path6);
1586
2327
  if (existing) {
1587
2328
  existing.state = updates.state;
1588
2329
  if (updates.config) {
@@ -1593,7 +2334,7 @@ var MountManager = class {
1593
2334
  existing.error = updates.error;
1594
2335
  }
1595
2336
  } else if (updates.filesystem) {
1596
- this._entries.set(path4, {
2337
+ this._entries.set(path6, {
1597
2338
  filesystem: updates.filesystem,
1598
2339
  state: updates.state,
1599
2340
  config: updates.config,
@@ -1601,14 +2342,14 @@ var MountManager = class {
1601
2342
  error: updates.error
1602
2343
  });
1603
2344
  } else {
1604
- this.logger.debug(`set() called for unknown path "${path4}" without filesystem \u2014 no entry created`);
2345
+ this.logger.debug(`set() called for unknown path "${path6}" without filesystem \u2014 no entry created`);
1605
2346
  }
1606
2347
  }
1607
2348
  /**
1608
2349
  * Delete a mount entry.
1609
2350
  */
1610
- delete(path4) {
1611
- return this._entries.delete(path4);
2351
+ delete(path6) {
2352
+ return this._entries.delete(path6);
1612
2353
  }
1613
2354
  /**
1614
2355
  * Clear all mount entries.
@@ -1629,7 +2370,7 @@ var MountManager = class {
1629
2370
  return;
1630
2371
  }
1631
2372
  this.logger.debug(`Processing ${pendingCount} pending mount(s)`);
1632
- for (const [path4, entry] of this._entries) {
2373
+ for (const [path6, entry] of this._entries) {
1633
2374
  if (entry.state !== "pending") {
1634
2375
  continue;
1635
2376
  }
@@ -1639,7 +2380,7 @@ var MountManager = class {
1639
2380
  try {
1640
2381
  const hookResult = await this._onMount({
1641
2382
  filesystem: entry.filesystem,
1642
- mountPath: path4,
2383
+ mountPath: path6,
1643
2384
  config,
1644
2385
  sandbox: this._sandbox,
1645
2386
  workspace: this._workspace
@@ -1647,7 +2388,7 @@ var MountManager = class {
1647
2388
  if (hookResult === false) {
1648
2389
  entry.state = "unsupported";
1649
2390
  entry.error = "Skipped by onMount hook";
1650
- this.logger.debug(`Mount skipped by onMount hook`, { path: path4, provider: fsProvider });
2391
+ this.logger.debug(`Mount skipped by onMount hook`, { path: path6, provider: fsProvider });
1651
2392
  continue;
1652
2393
  }
1653
2394
  if (hookResult && typeof hookResult === "object") {
@@ -1655,45 +2396,45 @@ var MountManager = class {
1655
2396
  entry.state = "mounted";
1656
2397
  entry.config = config;
1657
2398
  entry.configHash = config ? this.hashConfig(config) : void 0;
1658
- this.logger.info(`Mount handled by onMount hook`, { path: path4, provider: fsProvider });
2399
+ this.logger.info(`Mount handled by onMount hook`, { path: path6, provider: fsProvider });
1659
2400
  } else {
1660
2401
  entry.state = "error";
1661
2402
  entry.error = hookResult.error ?? "Mount hook failed";
1662
- this.logger.error(`Mount hook failed`, { path: path4, provider: fsProvider, error: entry.error });
2403
+ this.logger.error(`Mount hook failed`, { path: path6, provider: fsProvider, error: entry.error });
1663
2404
  }
1664
2405
  continue;
1665
2406
  }
1666
2407
  } catch (err) {
1667
2408
  entry.state = "error";
1668
2409
  entry.error = `Mount hook error: ${String(err)}`;
1669
- this.logger.error(`Mount hook threw error`, { path: path4, provider: fsProvider, error: entry.error });
2410
+ this.logger.error(`Mount hook threw error`, { path: path6, provider: fsProvider, error: entry.error });
1670
2411
  continue;
1671
2412
  }
1672
2413
  }
1673
2414
  if (!config) {
1674
2415
  entry.state = "unsupported";
1675
2416
  entry.error = "Filesystem does not support mounting";
1676
- this.logger.debug(`Filesystem does not support mounting`, { path: path4, provider: fsProvider });
2417
+ this.logger.debug(`Filesystem does not support mounting`, { path: path6, provider: fsProvider });
1677
2418
  continue;
1678
2419
  }
1679
2420
  entry.config = config;
1680
2421
  entry.configHash = this.hashConfig(config);
1681
2422
  entry.state = "mounting";
1682
- this.logger.debug(`Mounting filesystem`, { path: path4, provider: fsProvider, type: config.type });
2423
+ this.logger.debug(`Mounting filesystem`, { path: path6, provider: fsProvider, type: config.type });
1683
2424
  try {
1684
- const result = await this._mountFn(entry.filesystem, path4);
2425
+ const result = await this._mountFn(entry.filesystem, path6);
1685
2426
  if (result.success) {
1686
2427
  entry.state = "mounted";
1687
- this.logger.info(`Mount successful`, { path: path4, provider: fsProvider });
2428
+ this.logger.info(`Mount successful`, { path: path6, provider: fsProvider });
1688
2429
  } else {
1689
2430
  entry.state = "error";
1690
2431
  entry.error = result.error ?? "Mount failed";
1691
- this.logger.error(`Mount failed`, { path: path4, provider: fsProvider, error: entry.error });
2432
+ this.logger.error(`Mount failed`, { path: path6, provider: fsProvider, error: entry.error });
1692
2433
  }
1693
2434
  } catch (err) {
1694
2435
  entry.state = "error";
1695
2436
  entry.error = String(err);
1696
- this.logger.error(`Mount threw error`, { path: path4, provider: fsProvider, error: entry.error });
2437
+ this.logger.error(`Mount threw error`, { path: path6, provider: fsProvider, error: entry.error });
1697
2438
  }
1698
2439
  }
1699
2440
  }
@@ -1741,10 +2482,10 @@ var MountManager = class {
1741
2482
  if (separatorIndex <= 0) {
1742
2483
  return null;
1743
2484
  }
1744
- const path4 = content.slice(0, separatorIndex);
2485
+ const path6 = content.slice(0, separatorIndex);
1745
2486
  const configHash = content.slice(separatorIndex + 1);
1746
- if (!path4 || !configHash) return null;
1747
- return { path: path4, configHash };
2487
+ if (!path6 || !configHash) return null;
2488
+ return { path: path6, configHash };
1748
2489
  }
1749
2490
  /**
1750
2491
  * Check if a config hash matches the expected hash for a mount path.
@@ -2966,18 +3707,18 @@ var VersionedSkillSource = class {
2966
3707
  /**
2967
3708
  * Normalize a path by stripping leading/trailing slashes and dots.
2968
3709
  */
2969
- #normalizePath(path4) {
2970
- let normalized = path4.replace(/^[./\\]+|[/\\]+$/g, "");
3710
+ #normalizePath(path6) {
3711
+ let normalized = path6.replace(/^[./\\]+|[/\\]+$/g, "");
2971
3712
  if (normalized === "") return "";
2972
3713
  return normalized;
2973
3714
  }
2974
- async exists(path4) {
2975
- const normalized = this.#normalizePath(path4);
3715
+ async exists(path6) {
3716
+ const normalized = this.#normalizePath(path6);
2976
3717
  if (this.#tree.entries[normalized]) return true;
2977
3718
  return this.#directories.has(normalized);
2978
3719
  }
2979
- async stat(path4) {
2980
- const normalized = this.#normalizePath(path4);
3720
+ async stat(path6) {
3721
+ const normalized = this.#normalizePath(path6);
2981
3722
  const name = normalized.split("/").pop() || normalized || ".";
2982
3723
  const entry = this.#tree.entries[normalized];
2983
3724
  if (entry) {
@@ -2999,27 +3740,27 @@ var VersionedSkillSource = class {
2999
3740
  modifiedAt: this.#versionCreatedAt
3000
3741
  };
3001
3742
  }
3002
- throw new Error(`Path not found in skill version tree: ${path4}`);
3743
+ throw new Error(`Path not found in skill version tree: ${path6}`);
3003
3744
  }
3004
- async readFile(path4) {
3005
- const normalized = this.#normalizePath(path4);
3745
+ async readFile(path6) {
3746
+ const normalized = this.#normalizePath(path6);
3006
3747
  const entry = this.#tree.entries[normalized];
3007
3748
  if (!entry) {
3008
- throw new Error(`File not found in skill version tree: ${path4}`);
3749
+ throw new Error(`File not found in skill version tree: ${path6}`);
3009
3750
  }
3010
3751
  const blob = await this.#blobStore.get(entry.blobHash);
3011
3752
  if (!blob) {
3012
- throw new Error(`Blob not found for hash ${entry.blobHash} (file: ${path4})`);
3753
+ throw new Error(`Blob not found for hash ${entry.blobHash} (file: ${path6})`);
3013
3754
  }
3014
3755
  if (entry.encoding === "base64") {
3015
3756
  return Buffer.from(blob.content, "base64");
3016
3757
  }
3017
3758
  return blob.content;
3018
3759
  }
3019
- async readdir(path4) {
3020
- const normalized = this.#normalizePath(path4);
3760
+ async readdir(path6) {
3761
+ const normalized = this.#normalizePath(path6);
3021
3762
  if (!this.#directories.has(normalized)) {
3022
- throw new Error(`Directory not found in skill version tree: ${path4}`);
3763
+ throw new Error(`Directory not found in skill version tree: ${path6}`);
3023
3764
  }
3024
3765
  const prefix = normalized === "" ? "" : normalized + "/";
3025
3766
  const seen = /* @__PURE__ */ new Set();
@@ -3052,15 +3793,15 @@ var CompositeVersionedSkillSource = class {
3052
3793
  this.#fallback = options?.fallback;
3053
3794
  this.#fallbackSkills = new Set(options?.fallbackSkills ?? []);
3054
3795
  }
3055
- #normalizePath(path4) {
3056
- return path4.replace(/^[./\\]+|[/\\]+$/g, "");
3796
+ #normalizePath(path6) {
3797
+ return path6.replace(/^[./\\]+|[/\\]+$/g, "");
3057
3798
  }
3058
3799
  /**
3059
3800
  * Route a path to the correct source.
3060
3801
  * Returns the source and the remaining path within that source.
3061
3802
  */
3062
- #routePath(path4) {
3063
- const normalized = this.#normalizePath(path4);
3803
+ #routePath(path6) {
3804
+ const normalized = this.#normalizePath(path6);
3064
3805
  if (normalized === "") return null;
3065
3806
  const segments = normalized.split("/");
3066
3807
  const skillDir = segments[0];
@@ -3077,15 +3818,15 @@ var CompositeVersionedSkillSource = class {
3077
3818
  }
3078
3819
  return null;
3079
3820
  }
3080
- async exists(path4) {
3081
- const normalized = this.#normalizePath(path4);
3821
+ async exists(path6) {
3822
+ const normalized = this.#normalizePath(path6);
3082
3823
  if (normalized === "") return true;
3083
- const route = this.#routePath(path4);
3824
+ const route = this.#routePath(path6);
3084
3825
  if (!route) return false;
3085
3826
  return route.source.exists(route.subPath);
3086
3827
  }
3087
- async stat(path4) {
3088
- const normalized = this.#normalizePath(path4);
3828
+ async stat(path6) {
3829
+ const normalized = this.#normalizePath(path6);
3089
3830
  if (normalized === "") {
3090
3831
  return {
3091
3832
  name: ".",
@@ -3095,21 +3836,21 @@ var CompositeVersionedSkillSource = class {
3095
3836
  modifiedAt: /* @__PURE__ */ new Date()
3096
3837
  };
3097
3838
  }
3098
- const route = this.#routePath(path4);
3839
+ const route = this.#routePath(path6);
3099
3840
  if (!route) {
3100
- throw new Error(`Path not found in composite skill source: ${path4}`);
3841
+ throw new Error(`Path not found in composite skill source: ${path6}`);
3101
3842
  }
3102
3843
  return route.source.stat(route.subPath);
3103
3844
  }
3104
- async readFile(path4) {
3105
- const route = this.#routePath(path4);
3845
+ async readFile(path6) {
3846
+ const route = this.#routePath(path6);
3106
3847
  if (!route) {
3107
- throw new Error(`File not found in composite skill source: ${path4}`);
3848
+ throw new Error(`File not found in composite skill source: ${path6}`);
3108
3849
  }
3109
3850
  return route.source.readFile(route.subPath);
3110
3851
  }
3111
- async readdir(path4) {
3112
- const normalized = this.#normalizePath(path4);
3852
+ async readdir(path6) {
3853
+ const normalized = this.#normalizePath(path6);
3113
3854
  if (normalized === "") {
3114
3855
  const entries = [];
3115
3856
  const seen = /* @__PURE__ */ new Set();
@@ -3125,9 +3866,9 @@ var CompositeVersionedSkillSource = class {
3125
3866
  }
3126
3867
  return entries;
3127
3868
  }
3128
- const route = this.#routePath(path4);
3869
+ const route = this.#routePath(path6);
3129
3870
  if (!route) {
3130
- throw new Error(`Directory not found in composite skill source: ${path4}`);
3871
+ throw new Error(`Directory not found in composite skill source: ${path6}`);
3131
3872
  }
3132
3873
  return route.source.readdir(route.subPath);
3133
3874
  }
@@ -3251,7 +3992,7 @@ var WorkspaceSkillsImpl = class _WorkspaceSkillsImpl {
3251
3992
  if (a.length !== b.length) return false;
3252
3993
  const sortedA = [...a].sort();
3253
3994
  const sortedB = [...b].sort();
3254
- return sortedA.every((path4, i) => path4 === sortedB[i]);
3995
+ return sortedA.every((path6, i) => path6 === sortedB[i]);
3255
3996
  }
3256
3997
  // ===========================================================================
3257
3998
  // Search
@@ -3299,7 +4040,7 @@ var WorkspaceSkillsImpl = class _WorkspaceSkillsImpl {
3299
4040
  const skill = this.#skills.get(skillName);
3300
4041
  if (!skill) return null;
3301
4042
  const safeRefPath = this.#assertRelativePath(referencePath, "reference");
3302
- const refFilePath = this.#joinPath(skill.path, "references", safeRefPath);
4043
+ const refFilePath = this.#joinPath(skill.path, safeRefPath);
3303
4044
  if (!await this.#source.exists(refFilePath)) {
3304
4045
  return null;
3305
4046
  }
@@ -3315,7 +4056,7 @@ var WorkspaceSkillsImpl = class _WorkspaceSkillsImpl {
3315
4056
  const skill = this.#skills.get(skillName);
3316
4057
  if (!skill) return null;
3317
4058
  const safeScriptPath = this.#assertRelativePath(scriptPath, "script");
3318
- const scriptFilePath = this.#joinPath(skill.path, "scripts", safeScriptPath);
4059
+ const scriptFilePath = this.#joinPath(skill.path, safeScriptPath);
3319
4060
  if (!await this.#source.exists(scriptFilePath)) {
3320
4061
  return null;
3321
4062
  }
@@ -3331,7 +4072,7 @@ var WorkspaceSkillsImpl = class _WorkspaceSkillsImpl {
3331
4072
  const skill = this.#skills.get(skillName);
3332
4073
  if (!skill) return null;
3333
4074
  const safeAssetPath = this.#assertRelativePath(assetPath, "asset");
3334
- const assetFilePath = this.#joinPath(skill.path, "assets", safeAssetPath);
4075
+ const assetFilePath = this.#joinPath(skill.path, safeAssetPath);
3335
4076
  if (!await this.#source.exists(assetFilePath)) {
3336
4077
  return null;
3337
4078
  }
@@ -3777,7 +4518,7 @@ ${validation.errors.join("\n")}`);
3777
4518
  if (includeReferences) {
3778
4519
  for (const refPath of skill.references) {
3779
4520
  if (results.length >= topK) break;
3780
- const content = await this.getReference(skill.name, refPath);
4521
+ const content = await this.getReference(skill.name, `references/${refPath}`);
3781
4522
  if (content && content.toLowerCase().includes(queryLower)) {
3782
4523
  results.push({
3783
4524
  skillName: skill.name,
@@ -3820,8 +4561,8 @@ ${validation.errors.join("\n")}`);
3820
4561
  */
3821
4562
  #assertRelativePath(input, label) {
3822
4563
  const normalized = input.replace(/\\/g, "/");
3823
- const segments = normalized.split("/").filter(Boolean);
3824
- if (normalized.startsWith("/") || segments.some((seg) => seg === "." || seg === "..")) {
4564
+ const segments = normalized.split("/").filter((seg) => Boolean(seg) && seg !== ".");
4565
+ if (normalized.startsWith("/") || segments.some((seg) => seg === "..")) {
3825
4566
  throw new Error(`Invalid ${label} path: ${input}`);
3826
4567
  }
3827
4568
  return segments.join("/");
@@ -3829,9 +4570,9 @@ ${validation.errors.join("\n")}`);
3829
4570
  /**
3830
4571
  * Get parent path
3831
4572
  */
3832
- #getParentPath(path4) {
3833
- const lastSlash = path4.lastIndexOf("/");
3834
- return lastSlash > 0 ? path4.substring(0, lastSlash) : "/";
4573
+ #getParentPath(path6) {
4574
+ const lastSlash = path6.lastIndexOf("/");
4575
+ return lastSlash > 0 ? path6.substring(0, lastSlash) : "/";
3835
4576
  }
3836
4577
  };
3837
4578
  function hashContent(content) {
@@ -3992,6 +4733,7 @@ var Workspace = class {
3992
4733
  _config;
3993
4734
  _searchEngine;
3994
4735
  _skills;
4736
+ _lsp;
3995
4737
  constructor(config) {
3996
4738
  this.id = config.id ?? this.generateId();
3997
4739
  this.name = config.name ?? `workspace-${this.id.slice(0, 8)}`;
@@ -4048,6 +4790,26 @@ var Workspace = class {
4048
4790
  } : void 0
4049
4791
  });
4050
4792
  }
4793
+ if (config.lsp) {
4794
+ const processes = this._sandbox?.processes;
4795
+ if (!this._sandbox) {
4796
+ console.warn(
4797
+ `[Workspace "${this.name}"] lsp: true requires a sandbox with a process manager. No sandbox configured \u2014 LSP disabled.`
4798
+ );
4799
+ } else if (!processes) {
4800
+ console.warn(
4801
+ `[Workspace "${this.name}"] lsp: true requires a sandbox with a process manager. Sandbox "${this._sandbox.name ?? "unknown"}" does not provide one \u2014 LSP disabled.`
4802
+ );
4803
+ } else if (!isLSPAvailable()) {
4804
+ console.warn(
4805
+ `[Workspace "${this.name}"] lsp: true requires vscode-jsonrpc and vscode-languageserver-protocol packages. Install them to enable LSP diagnostics.`
4806
+ );
4807
+ } else {
4808
+ const lspConfig = config.lsp === true ? {} : config.lsp;
4809
+ const defaultRoot = lspConfig.root ?? findProjectRoot(process.cwd()) ?? process.cwd();
4810
+ this._lsp = new LSPManager(processes, defaultRoot, lspConfig, this._fs);
4811
+ }
4812
+ }
4051
4813
  if (!this._fs && !this._sandbox && !this.hasSkillsConfig()) {
4052
4814
  throw new WorkspaceError("Workspace requires at least a filesystem, sandbox, or skills", "NO_PROVIDERS");
4053
4815
  }
@@ -4086,6 +4848,13 @@ var Workspace = class {
4086
4848
  getToolsConfig() {
4087
4849
  return this._config.tools;
4088
4850
  }
4851
+ /**
4852
+ * The LSP manager (if configured, initialized, and a process manager is available).
4853
+ * Returns undefined if LSP is not configured, deps are missing, or sandbox has no process manager.
4854
+ */
4855
+ get lsp() {
4856
+ return this._lsp;
4857
+ }
4089
4858
  /**
4090
4859
  * Update the per-tool configuration for this workspace.
4091
4860
  * Takes effect on the next `createWorkspaceTools()` call.
@@ -4166,13 +4935,13 @@ var Workspace = class {
4166
4935
  * @param options - Index options (metadata, type hints)
4167
4936
  * @throws {SearchNotAvailableError} if search is not configured
4168
4937
  */
4169
- async index(path4, content, options) {
4938
+ async index(path6, content, options) {
4170
4939
  if (!this._searchEngine) {
4171
4940
  throw new SearchNotAvailableError();
4172
4941
  }
4173
4942
  this.lastAccessedAt = /* @__PURE__ */ new Date();
4174
4943
  const doc = {
4175
- id: path4,
4944
+ id: path6,
4176
4945
  content,
4177
4946
  metadata: {
4178
4947
  type: options?.type,
@@ -4289,6 +5058,13 @@ var Workspace = class {
4289
5058
  async destroy() {
4290
5059
  this._status = "destroying";
4291
5060
  try {
5061
+ if (this._lsp) {
5062
+ try {
5063
+ await this._lsp.shutdownAll();
5064
+ } catch {
5065
+ }
5066
+ this._lsp = void 0;
5067
+ }
4292
5068
  if (this._sandbox) {
4293
5069
  await callLifecycle(this._sandbox, "destroy");
4294
5070
  }
@@ -4879,11 +5655,11 @@ function buildBwrapCommand(command, workspacePath, config) {
4879
5655
  }
4880
5656
  bwrapArgs.push("--proc", "/proc");
4881
5657
  bwrapArgs.push("--tmpfs", "/tmp");
4882
- for (const path4 of DEFAULT_READONLY_BINDS) {
4883
- bwrapArgs.push("--ro-bind-try", path4, path4);
5658
+ for (const path6 of DEFAULT_READONLY_BINDS) {
5659
+ bwrapArgs.push("--ro-bind-try", path6, path6);
4884
5660
  }
4885
- for (const path4 of config.readOnlyPaths ?? []) {
4886
- bwrapArgs.push("--ro-bind", path4, path4);
5661
+ for (const path6 of config.readOnlyPaths ?? []) {
5662
+ bwrapArgs.push("--ro-bind", path6, path6);
4887
5663
  }
4888
5664
  if (config.allowSystemBinaries !== false) {
4889
5665
  const nodePath4 = process.execPath;
@@ -4895,8 +5671,8 @@ function buildBwrapCommand(command, workspacePath, config) {
4895
5671
  bwrapArgs.push("--ro-bind-try", "/snap", "/snap");
4896
5672
  }
4897
5673
  bwrapArgs.push("--bind", workspacePath, workspacePath);
4898
- for (const path4 of config.readWritePaths ?? []) {
4899
- bwrapArgs.push("--bind", path4, path4);
5674
+ for (const path6 of config.readWritePaths ?? []) {
5675
+ bwrapArgs.push("--bind", path6, path6);
4900
5676
  }
4901
5677
  bwrapArgs.push("--chdir", workspacePath);
4902
5678
  bwrapArgs.push("--die-with-parent");
@@ -5141,8 +5917,6 @@ var WORKSPACE_TOOLS = {
5141
5917
  INDEX: `${WORKSPACE_TOOLS_PREFIX}_index`
5142
5918
  }
5143
5919
  };
5144
-
5145
- // src/workspace/tools/helpers.ts
5146
5920
  function requireWorkspace(context) {
5147
5921
  if (!context?.workspace) {
5148
5922
  throw new WorkspaceNotAvailableError();
@@ -5172,6 +5946,63 @@ async function emitWorkspaceMetadata(context, toolName) {
5172
5946
  data: { toolName, toolCallId, ...info }
5173
5947
  });
5174
5948
  }
5949
+ async function getEditDiagnosticsText(workspace, filePath, content) {
5950
+ try {
5951
+ const lspManager = workspace.lsp;
5952
+ if (!lspManager) return "";
5953
+ const absolutePath = workspace.filesystem?.resolveAbsolutePath?.(filePath) ?? nodePath__namespace.default.resolve(lspManager.root, filePath.replace(/^\/+/, ""));
5954
+ const DIAG_TIMEOUT_MS = 1e4;
5955
+ let diagTimer;
5956
+ const diagnostics = await Promise.race([
5957
+ lspManager.getDiagnostics(absolutePath, content),
5958
+ new Promise((_, reject) => {
5959
+ diagTimer = setTimeout(() => reject(new Error("LSP diagnostics timeout")), DIAG_TIMEOUT_MS);
5960
+ })
5961
+ ]).finally(() => clearTimeout(diagTimer));
5962
+ if (diagnostics.length === 0) return "";
5963
+ const seen = /* @__PURE__ */ new Set();
5964
+ const deduped = diagnostics.filter((d) => {
5965
+ const key = `${d.severity}:${d.line}:${d.character}:${d.message}`;
5966
+ if (seen.has(key)) return false;
5967
+ seen.add(key);
5968
+ return true;
5969
+ });
5970
+ const groups = {
5971
+ error: [],
5972
+ warning: [],
5973
+ info: [],
5974
+ hint: []
5975
+ };
5976
+ for (const d of deduped) {
5977
+ groups[d.severity].push(d);
5978
+ }
5979
+ const lines = ["\n\nLSP Diagnostics:"];
5980
+ const severityLabels = [
5981
+ ["error", "Errors"],
5982
+ ["warning", "Warnings"],
5983
+ ["info", "Info"],
5984
+ ["hint", "Hints"]
5985
+ ];
5986
+ for (const [severity, label] of severityLabels) {
5987
+ const items = groups[severity];
5988
+ if (items.length === 0) continue;
5989
+ lines.push(`${label}:`);
5990
+ for (const d of items) {
5991
+ const source = d.source ? ` [${d.source}]` : "";
5992
+ lines.push(` ${d.line}:${d.character} - ${d.message}${source}`);
5993
+ }
5994
+ }
5995
+ let result = lines.join("\n");
5996
+ const maxChars = 2e3;
5997
+ if (result.length > maxChars) {
5998
+ const cutoff = result.lastIndexOf("\n", maxChars);
5999
+ result = result.slice(0, cutoff > 0 ? cutoff : maxChars) + "\n ... (truncated)";
6000
+ }
6001
+ return result;
6002
+ } catch {
6003
+ return "";
6004
+ }
6005
+ }
5175
6006
 
5176
6007
  // src/workspace/tools/ast-edit.ts
5177
6008
  var astGrepModule;
@@ -5203,7 +6034,7 @@ function isAstGrepAvailable() {
5203
6034
  return astGrepModule !== null;
5204
6035
  }
5205
6036
  try {
5206
- const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-7UAJ6LMR.cjs', document.baseURI).href)));
6037
+ const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-QKQGKEN7.cjs', document.baseURI).href)));
5207
6038
  req.resolve("@ast-grep/napi");
5208
6039
  return true;
5209
6040
  } catch {
@@ -5371,7 +6202,7 @@ function patternReplace(content, root, pattern, replacement) {
5371
6202
  }
5372
6203
  return { content: modifiedContent, count };
5373
6204
  }
5374
- var astEditTool = chunkEAZ6YDCQ_cjs.createTool({
6205
+ var astEditTool = chunkU3HBG2GU_cjs.createTool({
5375
6206
  id: WORKSPACE_TOOLS.FILESYSTEM.AST_EDIT,
5376
6207
  description: `Edit code using AST-based analysis for intelligent transformations.
5377
6208
 
@@ -5402,8 +6233,8 @@ Pattern replace (for everything else):
5402
6233
  isDefault: zod.z.boolean().optional().describe("Whether the first name is a default import")
5403
6234
  }).optional().describe("Required for add-import transform. Specifies the module and names to import.")
5404
6235
  }),
5405
- execute: async ({ path: path4, pattern, replacement, transform, targetName, newName, importSpec }, context) => {
5406
- const { filesystem } = requireFilesystem(context);
6236
+ execute: async ({ path: path6, pattern, replacement, transform, targetName, newName, importSpec }, context) => {
6237
+ const { workspace, filesystem } = requireFilesystem(context);
5407
6238
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.AST_EDIT);
5408
6239
  if (filesystem.readOnly) {
5409
6240
  throw new WorkspaceReadOnlyError("ast_edit");
@@ -5412,24 +6243,24 @@ Pattern replace (for everything else):
5412
6243
  if (!astGrep) {
5413
6244
  return "@ast-grep/napi is not available. Install it to use AST editing.";
5414
6245
  }
5415
- const { parse, Lang } = astGrep;
6246
+ const { parse: parse2, Lang } = astGrep;
5416
6247
  let content;
5417
6248
  try {
5418
- content = await filesystem.readFile(path4, { encoding: "utf-8" });
6249
+ content = await filesystem.readFile(path6, { encoding: "utf-8" });
5419
6250
  } catch (error) {
5420
6251
  if (error instanceof FileNotFoundError) {
5421
- return `File not found: ${path4}. Use ${WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE} to create it first.`;
6252
+ return `File not found: ${path6}. Use ${WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE} to create it first.`;
5422
6253
  }
5423
6254
  throw error;
5424
6255
  }
5425
6256
  if (typeof content !== "string") {
5426
6257
  return `Cannot perform AST edits on binary files. Use ${WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE} instead.`;
5427
6258
  }
5428
- const lang = getLanguageFromPath(path4, Lang);
6259
+ const lang = getLanguageFromPath(path6, Lang);
5429
6260
  if (!lang) {
5430
- return `Unsupported file type for AST editing: ${path4}`;
6261
+ return `Unsupported file type for AST editing: ${path6}`;
5431
6262
  }
5432
- const ast = parse(lang, content);
6263
+ const ast = parse2(lang, content);
5433
6264
  const root = ast.root();
5434
6265
  let modifiedContent = content;
5435
6266
  const changes = [];
@@ -5477,37 +6308,39 @@ Pattern replace (for everything else):
5477
6308
  }
5478
6309
  const wasModified = modifiedContent !== content;
5479
6310
  if (wasModified) {
5480
- await filesystem.writeFile(path4, modifiedContent, { overwrite: true });
6311
+ await filesystem.writeFile(path6, modifiedContent, { overwrite: true });
5481
6312
  }
5482
6313
  if (!wasModified) {
5483
- return `No changes made to ${path4} (${changes.join("; ")})`;
6314
+ return `No changes made to ${path6} (${changes.join("; ")})`;
5484
6315
  }
5485
- return `${path4}: ${changes.join("; ")}`;
6316
+ let output = `${path6}: ${changes.join("; ")}`;
6317
+ output += await getEditDiagnosticsText(workspace, path6, modifiedContent);
6318
+ return output;
5486
6319
  }
5487
6320
  });
5488
- var deleteFileTool = chunkEAZ6YDCQ_cjs.createTool({
6321
+ var deleteFileTool = chunkU3HBG2GU_cjs.createTool({
5489
6322
  id: WORKSPACE_TOOLS.FILESYSTEM.DELETE,
5490
6323
  description: "Delete a file or directory from the workspace filesystem",
5491
6324
  inputSchema: zod.z.object({
5492
6325
  path: zod.z.string().describe("The path to the file or directory to delete"),
5493
6326
  recursive: zod.z.boolean().optional().default(false).describe("If true, delete directories and their contents recursively. Required for non-empty directories.")
5494
6327
  }),
5495
- execute: async ({ path: path4, recursive }, context) => {
6328
+ execute: async ({ path: path6, recursive }, context) => {
5496
6329
  const { filesystem } = requireFilesystem(context);
5497
6330
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.DELETE);
5498
6331
  if (filesystem.readOnly) {
5499
6332
  throw new WorkspaceReadOnlyError("delete");
5500
6333
  }
5501
- const stat3 = await filesystem.stat(path4);
6334
+ const stat3 = await filesystem.stat(path6);
5502
6335
  if (stat3.type === "directory") {
5503
- await filesystem.rmdir(path4, { recursive, force: recursive });
6336
+ await filesystem.rmdir(path6, { recursive, force: recursive });
5504
6337
  } else {
5505
- await filesystem.deleteFile(path4);
6338
+ await filesystem.deleteFile(path6);
5506
6339
  }
5507
- return `Deleted ${path4}`;
6340
+ return `Deleted ${path6}`;
5508
6341
  }
5509
6342
  });
5510
- var editFileTool = chunkEAZ6YDCQ_cjs.createTool({
6343
+ var editFileTool = chunkU3HBG2GU_cjs.createTool({
5511
6344
  id: WORKSPACE_TOOLS.FILESYSTEM.EDIT_FILE,
5512
6345
  description: `Edit a file by replacing specific text. The old_string must match exactly and be unique in the file.
5513
6346
 
@@ -5522,20 +6355,22 @@ Usage:
5522
6355
  new_string: zod.z.string().describe("The text to replace old_string with"),
5523
6356
  replace_all: zod.z.boolean().optional().default(false).describe("If true, replace all occurrences. If false (default), old_string must be unique.")
5524
6357
  }),
5525
- execute: async ({ path: path4, old_string, new_string, replace_all }, context) => {
5526
- const { filesystem } = requireFilesystem(context);
6358
+ execute: async ({ path: path6, old_string, new_string, replace_all }, context) => {
6359
+ const { workspace, filesystem } = requireFilesystem(context);
5527
6360
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.EDIT_FILE);
5528
6361
  if (filesystem.readOnly) {
5529
6362
  throw new WorkspaceReadOnlyError("edit_file");
5530
6363
  }
5531
6364
  try {
5532
- const content = await filesystem.readFile(path4, { encoding: "utf-8" });
6365
+ const content = await filesystem.readFile(path6, { encoding: "utf-8" });
5533
6366
  if (typeof content !== "string") {
5534
6367
  return `Cannot edit binary files. Use ${WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE} instead.`;
5535
6368
  }
5536
6369
  const result = replaceString(content, old_string, new_string, replace_all);
5537
- await filesystem.writeFile(path4, result.content, { overwrite: true });
5538
- return `Replaced ${result.replacements} occurrence${result.replacements !== 1 ? "s" : ""} in ${path4}`;
6370
+ await filesystem.writeFile(path6, result.content, { overwrite: true });
6371
+ let output = `Replaced ${result.replacements} occurrence${result.replacements !== 1 ? "s" : ""} in ${path6}`;
6372
+ output += await getEditDiagnosticsText(workspace, path6, result.content);
6373
+ return output;
5539
6374
  } catch (error) {
5540
6375
  if (error instanceof StringNotFoundError) {
5541
6376
  return error.message;
@@ -5672,13 +6507,13 @@ Usage:
5672
6507
  - Always quote file paths that contain spaces (e.g., cd "/path/with spaces").
5673
6508
  - Use the timeout parameter to limit execution time. Behavior when omitted depends on the sandbox provider.
5674
6509
  - Optionally use cwd to override the working directory. Commands run from the sandbox default if omitted.`;
5675
- var executeCommandTool = chunkEAZ6YDCQ_cjs.createTool({
6510
+ var executeCommandTool = chunkU3HBG2GU_cjs.createTool({
5676
6511
  id: WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND,
5677
6512
  description: baseDescription,
5678
6513
  inputSchema: executeCommandInputSchema,
5679
6514
  execute: executeCommand
5680
6515
  });
5681
- var executeCommandWithBackgroundTool = chunkEAZ6YDCQ_cjs.createTool({
6516
+ var executeCommandWithBackgroundTool = chunkU3HBG2GU_cjs.createTool({
5682
6517
  id: WORKSPACE_TOOLS.SANDBOX.EXECUTE_COMMAND,
5683
6518
  description: `${baseDescription}
5684
6519
 
@@ -5686,31 +6521,31 @@ Set background: true to run long-running commands (dev servers, watchers) withou
5686
6521
  inputSchema: executeCommandWithBackgroundSchema,
5687
6522
  execute: executeCommand
5688
6523
  });
5689
- var fileStatTool = chunkEAZ6YDCQ_cjs.createTool({
6524
+ var fileStatTool = chunkU3HBG2GU_cjs.createTool({
5690
6525
  id: WORKSPACE_TOOLS.FILESYSTEM.FILE_STAT,
5691
6526
  description: "Get file or directory metadata from the workspace. Returns existence, type, size, and modification time.",
5692
6527
  inputSchema: zod.z.object({
5693
6528
  path: zod.z.string().describe("The path to check")
5694
6529
  }),
5695
- execute: async ({ path: path4 }, context) => {
6530
+ execute: async ({ path: path6 }, context) => {
5696
6531
  const { filesystem } = requireFilesystem(context);
5697
6532
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.FILE_STAT);
5698
6533
  try {
5699
- const stat3 = await filesystem.stat(path4);
6534
+ const stat3 = await filesystem.stat(path6);
5700
6535
  const modifiedAt = stat3.modifiedAt.toISOString();
5701
- const parts = [`${path4}`, `Type: ${stat3.type}`];
6536
+ const parts = [`${path6}`, `Type: ${stat3.type}`];
5702
6537
  if (stat3.size !== void 0) parts.push(`Size: ${stat3.size} bytes`);
5703
6538
  parts.push(`Modified: ${modifiedAt}`);
5704
6539
  return parts.join(" ");
5705
6540
  } catch (error) {
5706
6541
  if (error instanceof FileNotFoundError) {
5707
- return `${path4}: not found`;
6542
+ return `${path6}: not found`;
5708
6543
  }
5709
6544
  throw error;
5710
6545
  }
5711
6546
  }
5712
6547
  });
5713
- var getProcessOutputTool = chunkEAZ6YDCQ_cjs.createTool({
6548
+ var getProcessOutputTool = chunkU3HBG2GU_cjs.createTool({
5714
6549
  id: WORKSPACE_TOOLS.SANDBOX.GET_PROCESS_OUTPUT,
5715
6550
  description: `Get the current output (stdout, stderr) and status of a background process by its PID.
5716
6551
 
@@ -5786,7 +6621,7 @@ Use this after starting a background command with execute_command (background: t
5786
6621
  return parts.join("\n");
5787
6622
  }
5788
6623
  });
5789
- var grepTool = chunkEAZ6YDCQ_cjs.createTool({
6624
+ var grepTool = chunkU3HBG2GU_cjs.createTool({
5790
6625
  id: WORKSPACE_TOOLS.FILESYSTEM.GREP,
5791
6626
  description: `Search file contents using a regex pattern. Walks the filesystem and returns matching lines with file paths and line numbers.
5792
6627
 
@@ -5927,7 +6762,7 @@ Usage:
5927
6762
  return outputLines.join("\n");
5928
6763
  }
5929
6764
  });
5930
- var indexContentTool = chunkEAZ6YDCQ_cjs.createTool({
6765
+ var indexContentTool = chunkU3HBG2GU_cjs.createTool({
5931
6766
  id: WORKSPACE_TOOLS.SEARCH.INDEX,
5932
6767
  description: "Index content for search. The path becomes the document ID in search results.",
5933
6768
  inputSchema: zod.z.object({
@@ -5935,15 +6770,15 @@ var indexContentTool = chunkEAZ6YDCQ_cjs.createTool({
5935
6770
  content: zod.z.string().describe("The text content to index"),
5936
6771
  metadata: zod.z.record(zod.z.unknown()).optional().describe("Optional metadata to store with the document")
5937
6772
  }),
5938
- execute: async ({ path: path4, content, metadata }, context) => {
6773
+ execute: async ({ path: path6, content, metadata }, context) => {
5939
6774
  const workspace = requireWorkspace(context);
5940
6775
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.SEARCH.INDEX);
5941
- await workspace.index(path4, content, { metadata });
5942
- return `Indexed ${path4}`;
6776
+ await workspace.index(path6, content, { metadata });
6777
+ return `Indexed ${path6}`;
5943
6778
  }
5944
6779
  });
5945
6780
  var KILL_TAIL_LINES = 50;
5946
- var killProcessTool = chunkEAZ6YDCQ_cjs.createTool({
6781
+ var killProcessTool = chunkU3HBG2GU_cjs.createTool({
5947
6782
  id: WORKSPACE_TOOLS.SANDBOX.KILL_PROCESS,
5948
6783
  description: `Kill a background process by its PID.
5949
6784
 
@@ -5997,7 +6832,7 @@ var BRANCH = "\u251C\u2500\u2500 ";
5997
6832
  var LAST_BRANCH = "\u2514\u2500\u2500 ";
5998
6833
  var VERTICAL = "\u2502 ";
5999
6834
  var SPACE = " ";
6000
- async function formatAsTree(fs5, path4, options) {
6835
+ async function formatAsTree(fs5, path6, options) {
6001
6836
  const maxDepth = options?.maxDepth ?? Infinity;
6002
6837
  const showHidden = options?.showHidden ?? false;
6003
6838
  const dirsOnly = options?.dirsOnly ?? false;
@@ -6053,12 +6888,12 @@ async function formatAsTree(fs5, path4, options) {
6053
6888
  if (globMatcher && !dirsOnly) {
6054
6889
  filtered = filtered.filter((e) => {
6055
6890
  if (e.type === "directory") return true;
6056
- const entryPath = currentPath === path4 ? e.name : `${currentPath === "/" ? "" : currentPath}/${e.name}`;
6891
+ const entryPath = currentPath === path6 ? e.name : `${currentPath === "/" ? "" : currentPath}/${e.name}`;
6057
6892
  let relativePath;
6058
- if (path4 === "/" || path4 === "") {
6893
+ if (path6 === "/" || path6 === "") {
6059
6894
  relativePath = entryPath.startsWith("/") ? entryPath.slice(1) : entryPath;
6060
6895
  } else {
6061
- relativePath = entryPath.startsWith(path4 + "/") ? entryPath.slice(path4.length + 1) : entryPath;
6896
+ relativePath = entryPath.startsWith(path6 + "/") ? entryPath.slice(path6.length + 1) : entryPath;
6062
6897
  if (!relativePath) relativePath = entryPath;
6063
6898
  }
6064
6899
  return globMatcher(relativePath);
@@ -6087,7 +6922,7 @@ async function formatAsTree(fs5, path4, options) {
6087
6922
  }
6088
6923
  }
6089
6924
  }
6090
- await buildTree(path4, "", 0);
6925
+ await buildTree(path6, "", 0);
6091
6926
  const dirPart = dirCount === 1 ? "1 directory" : `${dirCount} directories`;
6092
6927
  const filePart = fileCount === 1 ? "1 file" : `${fileCount} files`;
6093
6928
  let summary = `${dirPart}, ${filePart}`;
@@ -6110,7 +6945,7 @@ function joinPath2(base, name) {
6110
6945
  }
6111
6946
 
6112
6947
  // src/workspace/tools/list-files.ts
6113
- var listFilesTool = chunkEAZ6YDCQ_cjs.createTool({
6948
+ var listFilesTool = chunkU3HBG2GU_cjs.createTool({
6114
6949
  id: WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES,
6115
6950
  description: `List files and directories in the workspace filesystem.
6116
6951
  Returns a tree-style view (like the Unix "tree" command) for easy visualization.
@@ -6136,10 +6971,10 @@ Examples:
6136
6971
  'Glob pattern(s) to filter files. Examples: "**/*.ts", "src/**/*.test.ts", "*.config.{js,ts}". Directories always pass through.'
6137
6972
  )
6138
6973
  }),
6139
- execute: async ({ path: path4 = "./", maxDepth = 3, showHidden, dirsOnly, exclude, extension, pattern }, context) => {
6974
+ execute: async ({ path: path6 = "./", maxDepth = 3, showHidden, dirsOnly, exclude, extension, pattern }, context) => {
6140
6975
  const { filesystem } = requireFilesystem(context);
6141
6976
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES);
6142
- const result = await formatAsTree(filesystem, path4, {
6977
+ const result = await formatAsTree(filesystem, path6, {
6143
6978
  maxDepth,
6144
6979
  showHidden,
6145
6980
  dirsOnly,
@@ -6152,24 +6987,24 @@ Examples:
6152
6987
  ${result.summary}`;
6153
6988
  }
6154
6989
  });
6155
- var mkdirTool = chunkEAZ6YDCQ_cjs.createTool({
6990
+ var mkdirTool = chunkU3HBG2GU_cjs.createTool({
6156
6991
  id: WORKSPACE_TOOLS.FILESYSTEM.MKDIR,
6157
6992
  description: "Create a directory in the workspace filesystem",
6158
6993
  inputSchema: zod.z.object({
6159
6994
  path: zod.z.string().describe("The path of the directory to create"),
6160
6995
  recursive: zod.z.boolean().optional().default(true).describe("Whether to create parent directories if they do not exist")
6161
6996
  }),
6162
- execute: async ({ path: path4, recursive }, context) => {
6997
+ execute: async ({ path: path6, recursive }, context) => {
6163
6998
  const { filesystem } = requireFilesystem(context);
6164
6999
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.MKDIR);
6165
7000
  if (filesystem.readOnly) {
6166
7001
  throw new WorkspaceReadOnlyError("mkdir");
6167
7002
  }
6168
- await filesystem.mkdir(path4, { recursive });
6169
- return `Created directory ${path4}`;
7003
+ await filesystem.mkdir(path6, { recursive });
7004
+ return `Created directory ${path6}`;
6170
7005
  }
6171
7006
  });
6172
- var readFileTool = chunkEAZ6YDCQ_cjs.createTool({
7007
+ var readFileTool = chunkU3HBG2GU_cjs.createTool({
6173
7008
  id: WORKSPACE_TOOLS.FILESYSTEM.READ_FILE,
6174
7009
  description: "Read the contents of a file from the workspace filesystem. Use offset/limit parameters to read specific line ranges for large files.",
6175
7010
  inputSchema: zod.z.object({
@@ -6179,12 +7014,12 @@ var readFileTool = chunkEAZ6YDCQ_cjs.createTool({
6179
7014
  limit: zod.z.number().optional().describe("Maximum number of lines to read. If omitted, reads to the end of the file."),
6180
7015
  showLineNumbers: zod.z.boolean().optional().default(true).describe("Whether to prefix each line with its line number (default: true)")
6181
7016
  }),
6182
- execute: async ({ path: path4, encoding, offset, limit, showLineNumbers }, context) => {
7017
+ execute: async ({ path: path6, encoding, offset, limit, showLineNumbers }, context) => {
6183
7018
  const { filesystem } = requireFilesystem(context);
6184
7019
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.READ_FILE);
6185
7020
  const effectiveEncoding = encoding ?? "utf-8";
6186
- const fullContent = await filesystem.readFile(path4, { encoding: effectiveEncoding });
6187
- const stat3 = await filesystem.stat(path4);
7021
+ const fullContent = await filesystem.readFile(path6, { encoding: effectiveEncoding });
7022
+ const stat3 = await filesystem.stat(path6);
6188
7023
  const isTextEncoding = !encoding || encoding === "utf-8" || encoding === "utf8";
6189
7024
  if (!isTextEncoding) {
6190
7025
  return `${stat3.path} (${stat3.size} bytes, ${effectiveEncoding})
@@ -6208,7 +7043,7 @@ ${fullContent.toString("base64")}`;
6208
7043
  ${formattedContent}`;
6209
7044
  }
6210
7045
  });
6211
- var searchTool = chunkEAZ6YDCQ_cjs.createTool({
7046
+ var searchTool = chunkU3HBG2GU_cjs.createTool({
6212
7047
  id: WORKSPACE_TOOLS.SEARCH.SEARCH,
6213
7048
  description: "Search indexed content in the workspace. Supports keyword (BM25), semantic (vector), and hybrid search modes.",
6214
7049
  inputSchema: zod.z.object({
@@ -6235,7 +7070,7 @@ var searchTool = chunkEAZ6YDCQ_cjs.createTool({
6235
7070
  return lines.join("\n");
6236
7071
  }
6237
7072
  });
6238
- var writeFileTool = chunkEAZ6YDCQ_cjs.createTool({
7073
+ var writeFileTool = chunkU3HBG2GU_cjs.createTool({
6239
7074
  id: WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE,
6240
7075
  description: "Write content to a file in the workspace filesystem. Creates parent directories if needed.",
6241
7076
  inputSchema: zod.z.object({
@@ -6243,15 +7078,17 @@ var writeFileTool = chunkEAZ6YDCQ_cjs.createTool({
6243
7078
  content: zod.z.string().describe("The content to write to the file"),
6244
7079
  overwrite: zod.z.boolean().optional().default(true).describe("Whether to overwrite the file if it already exists")
6245
7080
  }),
6246
- execute: async ({ path: path4, content, overwrite }, context) => {
6247
- const { filesystem } = requireFilesystem(context);
7081
+ execute: async ({ path: path6, content, overwrite }, context) => {
7082
+ const { workspace, filesystem } = requireFilesystem(context);
6248
7083
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE);
6249
7084
  if (filesystem.readOnly) {
6250
7085
  throw new WorkspaceReadOnlyError("write_file");
6251
7086
  }
6252
- await filesystem.writeFile(path4, content, { overwrite });
7087
+ await filesystem.writeFile(path6, content, { overwrite });
6253
7088
  const size = Buffer.byteLength(content, "utf-8");
6254
- return `Wrote ${size} bytes to ${path4}`;
7089
+ let output = `Wrote ${size} bytes to ${path6}`;
7090
+ output += await getEditDiagnosticsText(workspace, path6, content);
7091
+ return output;
6255
7092
  }
6256
7093
  });
6257
7094
 
@@ -6473,5 +7310,5 @@ exports.requireWorkspace = requireWorkspace;
6473
7310
  exports.resolveToolConfig = resolveToolConfig;
6474
7311
  exports.searchTool = searchTool;
6475
7312
  exports.writeFileTool = writeFileTool;
6476
- //# sourceMappingURL=chunk-7UAJ6LMR.cjs.map
6477
- //# sourceMappingURL=chunk-7UAJ6LMR.cjs.map
7313
+ //# sourceMappingURL=chunk-QKQGKEN7.cjs.map
7314
+ //# sourceMappingURL=chunk-QKQGKEN7.cjs.map