@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,20 +1,22 @@
1
- import { createTool } from './chunk-BQHWJLXU.js';
1
+ import { createTool } from './chunk-63G75DJE.js';
2
2
  import { MastraBase } from './chunk-WCAFTXGK.js';
3
3
  import { RegisteredLogger } from './chunk-X2WMFSPB.js';
4
4
  import posixPath from 'path/posix';
5
- import { constants } from 'fs';
5
+ import { constants, existsSync } from 'fs';
6
6
  import * as fs2 from 'fs/promises';
7
7
  import * as nodePath from 'path';
8
+ import nodePath__default, { parse, join, dirname } from 'path';
8
9
  import picomatch from 'picomatch';
10
+ import { createRequire } from 'module';
11
+ import { pathToFileURL } from 'url';
12
+ import * as childProcess from 'child_process';
13
+ import { execFileSync } from 'child_process';
9
14
  import * as crypto from 'crypto';
10
15
  import { createHash } from 'crypto';
11
16
  import matter from 'gray-matter';
12
17
  import * as os from 'os';
13
18
  import os__default from 'os';
14
- import * as childProcess from 'child_process';
15
- import { execFileSync } from 'child_process';
16
19
  import { Readable, Writable } from 'stream';
17
- import { createRequire } from 'module';
18
20
  import { z } from 'zod';
19
21
 
20
22
  // src/workspace/errors.ts
@@ -69,59 +71,59 @@ var WorkspaceReadOnlyError = class extends WorkspaceError {
69
71
  }
70
72
  };
71
73
  var FilesystemError = class extends Error {
72
- constructor(message, code, path4) {
74
+ constructor(message, code, path6) {
73
75
  super(message);
74
76
  this.code = code;
75
- this.path = path4;
77
+ this.path = path6;
76
78
  this.name = "FilesystemError";
77
79
  }
78
80
  };
79
81
  var FileNotFoundError = class extends FilesystemError {
80
- constructor(path4) {
81
- super(`File not found: ${path4}`, "ENOENT", path4);
82
+ constructor(path6) {
83
+ super(`File not found: ${path6}`, "ENOENT", path6);
82
84
  this.name = "FileNotFoundError";
83
85
  }
84
86
  };
85
87
  var DirectoryNotFoundError = class extends FilesystemError {
86
- constructor(path4) {
87
- super(`Directory not found: ${path4}`, "ENOENT", path4);
88
+ constructor(path6) {
89
+ super(`Directory not found: ${path6}`, "ENOENT", path6);
88
90
  this.name = "DirectoryNotFoundError";
89
91
  }
90
92
  };
91
93
  var FileExistsError = class extends FilesystemError {
92
- constructor(path4) {
93
- super(`File already exists: ${path4}`, "EEXIST", path4);
94
+ constructor(path6) {
95
+ super(`File already exists: ${path6}`, "EEXIST", path6);
94
96
  this.name = "FileExistsError";
95
97
  }
96
98
  };
97
99
  var IsDirectoryError = class extends FilesystemError {
98
- constructor(path4) {
99
- super(`Path is a directory: ${path4}`, "EISDIR", path4);
100
+ constructor(path6) {
101
+ super(`Path is a directory: ${path6}`, "EISDIR", path6);
100
102
  this.name = "IsDirectoryError";
101
103
  }
102
104
  };
103
105
  var NotDirectoryError = class extends FilesystemError {
104
- constructor(path4) {
105
- super(`Path is not a directory: ${path4}`, "ENOTDIR", path4);
106
+ constructor(path6) {
107
+ super(`Path is not a directory: ${path6}`, "ENOTDIR", path6);
106
108
  this.name = "NotDirectoryError";
107
109
  }
108
110
  };
109
111
  var DirectoryNotEmptyError = class extends FilesystemError {
110
- constructor(path4) {
111
- super(`Directory not empty: ${path4}`, "ENOTEMPTY", path4);
112
+ constructor(path6) {
113
+ super(`Directory not empty: ${path6}`, "ENOTEMPTY", path6);
112
114
  this.name = "DirectoryNotEmptyError";
113
115
  }
114
116
  };
115
117
  var PermissionError = class extends FilesystemError {
116
- constructor(path4, operation) {
117
- super(`Permission denied: ${operation} on ${path4}`, "EACCES", path4);
118
+ constructor(path6, operation) {
119
+ super(`Permission denied: ${operation} on ${path6}`, "EACCES", path6);
118
120
  this.operation = operation;
119
121
  this.name = "PermissionError";
120
122
  }
121
123
  };
122
124
  var FileReadRequiredError = class extends FilesystemError {
123
- constructor(path4, reason) {
124
- super(reason, "EREAD_REQUIRED", path4);
125
+ constructor(path6, reason) {
126
+ super(reason, "EREAD_REQUIRED", path6);
125
127
  this.name = "FileReadRequiredError";
126
128
  }
127
129
  };
@@ -157,8 +159,8 @@ var CompositeFilesystem = class {
157
159
  constructor(config) {
158
160
  this.id = `cfs-${Date.now().toString(36)}`;
159
161
  this._mounts = /* @__PURE__ */ new Map();
160
- for (const [path4, fs5] of Object.entries(config.mounts)) {
161
- const normalized = this.normalizePath(path4);
162
+ for (const [path6, fs5] of Object.entries(config.mounts)) {
163
+ const normalized = this.normalizePath(path6);
162
164
  this._mounts.set(normalized, fs5);
163
165
  }
164
166
  if (this._mounts.size === 0) {
@@ -209,27 +211,36 @@ var CompositeFilesystem = class {
209
211
  * Get the underlying filesystem for a given path.
210
212
  * Returns undefined if the path doesn't resolve to any mount.
211
213
  */
212
- getFilesystemForPath(path4) {
213
- const resolved = this.resolveMount(path4);
214
+ getFilesystemForPath(path6) {
215
+ const resolved = this.resolveMount(path6);
214
216
  return resolved?.fs;
215
217
  }
216
218
  /**
217
219
  * Get the mount path for a given path.
218
220
  * Returns undefined if the path doesn't resolve to any mount.
219
221
  */
220
- getMountPathForPath(path4) {
221
- const resolved = this.resolveMount(path4);
222
+ getMountPathForPath(path6) {
223
+ const resolved = this.resolveMount(path6);
222
224
  return resolved?.mountPath;
223
225
  }
224
- normalizePath(path4) {
225
- if (!path4 || path4 === "/") return "/";
226
- let n = posixPath.normalize(path4);
226
+ /**
227
+ * Resolve a workspace-relative path to an absolute disk path.
228
+ * Strips the mount prefix and delegates to the underlying filesystem.
229
+ */
230
+ resolveAbsolutePath(path6) {
231
+ const r = this.resolveMount(path6);
232
+ if (!r) return void 0;
233
+ return r.fs.resolveAbsolutePath?.(r.fsPath);
234
+ }
235
+ normalizePath(path6) {
236
+ if (!path6 || path6 === "/") return "/";
237
+ let n = posixPath.normalize(path6);
227
238
  if (!n.startsWith("/")) n = `/${n}`;
228
239
  if (n.length > 1 && n.endsWith("/")) n = n.slice(0, -1);
229
240
  return n;
230
241
  }
231
- resolveMount(path4) {
232
- const normalized = this.normalizePath(path4);
242
+ resolveMount(path6) {
243
+ const normalized = this.normalizePath(path6);
233
244
  let best = null;
234
245
  for (const [mountPath, fs5] of this._mounts) {
235
246
  if (normalized === mountPath || normalized.startsWith(mountPath + "/")) {
@@ -244,8 +255,8 @@ var CompositeFilesystem = class {
244
255
  if (!fsPath.startsWith("/")) fsPath = "/" + fsPath;
245
256
  return { fs: best.fs, fsPath, mountPath: best.mountPath };
246
257
  }
247
- getVirtualEntries(path4) {
248
- const normalized = this.normalizePath(path4);
258
+ getVirtualEntries(path6) {
259
+ const normalized = this.normalizePath(path6);
249
260
  if (this.resolveMount(normalized)) return null;
250
261
  const entriesMap = /* @__PURE__ */ new Map();
251
262
  for (const [mountPath, fs5] of this._mounts.entries()) {
@@ -272,8 +283,8 @@ var CompositeFilesystem = class {
272
283
  }
273
284
  return entriesMap.size > 0 ? Array.from(entriesMap.values()) : null;
274
285
  }
275
- isVirtualPath(path4) {
276
- const normalized = this.normalizePath(path4);
286
+ isVirtualPath(path6) {
287
+ const normalized = this.normalizePath(path6);
277
288
  if (normalized === "/" && !this._mounts.has("/")) return true;
278
289
  for (const mountPath of this._mounts.keys()) {
279
290
  if (mountPath.startsWith(normalized + "/")) return true;
@@ -284,9 +295,9 @@ var CompositeFilesystem = class {
284
295
  * Assert that a filesystem is writable (not read-only).
285
296
  * @throws {PermissionError} if the filesystem is read-only
286
297
  */
287
- assertWritable(fs5, path4, operation) {
298
+ assertWritable(fs5, path6, operation) {
288
299
  if (fs5.readOnly) {
289
- throw new PermissionError(path4, `${operation} (filesystem is read-only)`);
300
+ throw new PermissionError(path6, `${operation} (filesystem is read-only)`);
290
301
  }
291
302
  }
292
303
  // ===========================================================================
@@ -320,27 +331,27 @@ var CompositeFilesystem = class {
320
331
  }
321
332
  this.status = "destroyed";
322
333
  }
323
- async readFile(path4, options) {
324
- const r = this.resolveMount(path4);
325
- if (!r) throw new Error(`No mount for path: ${path4}`);
334
+ async readFile(path6, options) {
335
+ const r = this.resolveMount(path6);
336
+ if (!r) throw new Error(`No mount for path: ${path6}`);
326
337
  return r.fs.readFile(r.fsPath, options);
327
338
  }
328
- async writeFile(path4, content, options) {
329
- const r = this.resolveMount(path4);
330
- if (!r) throw new Error(`No mount for path: ${path4}`);
331
- this.assertWritable(r.fs, path4, "writeFile");
339
+ async writeFile(path6, content, options) {
340
+ const r = this.resolveMount(path6);
341
+ if (!r) throw new Error(`No mount for path: ${path6}`);
342
+ this.assertWritable(r.fs, path6, "writeFile");
332
343
  return r.fs.writeFile(r.fsPath, content, options);
333
344
  }
334
- async appendFile(path4, content) {
335
- const r = this.resolveMount(path4);
336
- if (!r) throw new Error(`No mount for path: ${path4}`);
337
- this.assertWritable(r.fs, path4, "appendFile");
345
+ async appendFile(path6, content) {
346
+ const r = this.resolveMount(path6);
347
+ if (!r) throw new Error(`No mount for path: ${path6}`);
348
+ this.assertWritable(r.fs, path6, "appendFile");
338
349
  return r.fs.appendFile(r.fsPath, content);
339
350
  }
340
- async deleteFile(path4, options) {
341
- const r = this.resolveMount(path4);
342
- if (!r) throw new Error(`No mount for path: ${path4}`);
343
- this.assertWritable(r.fs, path4, "deleteFile");
351
+ async deleteFile(path6, options) {
352
+ const r = this.resolveMount(path6);
353
+ if (!r) throw new Error(`No mount for path: ${path6}`);
354
+ this.assertWritable(r.fs, path6, "deleteFile");
344
355
  return r.fs.deleteFile(r.fsPath, options);
345
356
  }
346
357
  async copyFile(src, dest, options) {
@@ -368,35 +379,35 @@ var CompositeFilesystem = class {
368
379
  await this.copyFile(src, dest, options);
369
380
  await srcR.fs.deleteFile(srcR.fsPath);
370
381
  }
371
- async readdir(path4, options) {
372
- const virtual = this.getVirtualEntries(path4);
382
+ async readdir(path6, options) {
383
+ const virtual = this.getVirtualEntries(path6);
373
384
  if (virtual) return virtual;
374
- const r = this.resolveMount(path4);
375
- if (!r) throw new Error(`No mount for path: ${path4}`);
385
+ const r = this.resolveMount(path6);
386
+ if (!r) throw new Error(`No mount for path: ${path6}`);
376
387
  return r.fs.readdir(r.fsPath, options);
377
388
  }
378
- async mkdir(path4, options) {
379
- const r = this.resolveMount(path4);
380
- if (!r) throw new Error(`No mount for path: ${path4}`);
381
- this.assertWritable(r.fs, path4, "mkdir");
389
+ async mkdir(path6, options) {
390
+ const r = this.resolveMount(path6);
391
+ if (!r) throw new Error(`No mount for path: ${path6}`);
392
+ this.assertWritable(r.fs, path6, "mkdir");
382
393
  return r.fs.mkdir(r.fsPath, options);
383
394
  }
384
- async rmdir(path4, options) {
385
- const r = this.resolveMount(path4);
386
- if (!r) throw new Error(`No mount for path: ${path4}`);
387
- this.assertWritable(r.fs, path4, "rmdir");
395
+ async rmdir(path6, options) {
396
+ const r = this.resolveMount(path6);
397
+ if (!r) throw new Error(`No mount for path: ${path6}`);
398
+ this.assertWritable(r.fs, path6, "rmdir");
388
399
  return r.fs.rmdir(r.fsPath, options);
389
400
  }
390
- async exists(path4) {
391
- if (this.isVirtualPath(path4)) return true;
392
- const r = this.resolveMount(path4);
401
+ async exists(path6) {
402
+ if (this.isVirtualPath(path6)) return true;
403
+ const r = this.resolveMount(path6);
393
404
  if (!r) return false;
394
405
  if (r.fsPath === "/") return true;
395
406
  return r.fs.exists(r.fsPath);
396
407
  }
397
- async stat(path4) {
398
- const normalized = this.normalizePath(path4);
399
- if (this.isVirtualPath(path4)) {
408
+ async stat(path6) {
409
+ const normalized = this.normalizePath(path6);
410
+ if (this.isVirtualPath(path6)) {
400
411
  const parts = normalized.split("/").filter(Boolean);
401
412
  const now = /* @__PURE__ */ new Date();
402
413
  return {
@@ -408,8 +419,8 @@ var CompositeFilesystem = class {
408
419
  modifiedAt: now
409
420
  };
410
421
  }
411
- const r = this.resolveMount(path4);
412
- if (!r) throw new Error(`No mount for path: ${path4}`);
422
+ const r = this.resolveMount(path6);
423
+ if (!r) throw new Error(`No mount for path: ${path6}`);
413
424
  if (r.fsPath === "/") {
414
425
  const parts = normalized.split("/").filter(Boolean);
415
426
  const now = /* @__PURE__ */ new Date();
@@ -424,9 +435,9 @@ var CompositeFilesystem = class {
424
435
  }
425
436
  return r.fs.stat(r.fsPath);
426
437
  }
427
- async isFile(path4) {
428
- if (this.isVirtualPath(path4)) return false;
429
- const r = this.resolveMount(path4);
438
+ async isFile(path6) {
439
+ if (this.isVirtualPath(path6)) return false;
440
+ const r = this.resolveMount(path6);
430
441
  if (!r) return false;
431
442
  try {
432
443
  const stat3 = await r.fs.stat(r.fsPath);
@@ -435,9 +446,9 @@ var CompositeFilesystem = class {
435
446
  return false;
436
447
  }
437
448
  }
438
- async isDirectory(path4) {
439
- if (this.isVirtualPath(path4)) return true;
440
- const r = this.resolveMount(path4);
449
+ async isDirectory(path6) {
450
+ if (this.isVirtualPath(path6)) return true;
451
+ const r = this.resolveMount(path6);
441
452
  if (!r) return false;
442
453
  if (r.fsPath === "/") return true;
443
454
  try {
@@ -740,6 +751,17 @@ function isTextFile(filename) {
740
751
  const ext = nodePath.extname(filename).toLowerCase();
741
752
  return TEXT_EXTENSIONS.has(ext);
742
753
  }
754
+ function resolveWorkspacePath(basePath, filePath) {
755
+ if (nodePath.isAbsolute(filePath)) {
756
+ const normalizedBase = nodePath.normalize(basePath);
757
+ const normalizedFile = nodePath.normalize(filePath);
758
+ const rel = nodePath.relative(normalizedBase, normalizedFile);
759
+ if (!rel.startsWith("..") && !nodePath.isAbsolute(rel)) {
760
+ return normalizedFile;
761
+ }
762
+ }
763
+ return nodePath.join(basePath, filePath.replace(/^\/+/, ""));
764
+ }
743
765
  async function fsExists(absolutePath) {
744
766
  try {
745
767
  await fs2.access(absolutePath);
@@ -827,8 +849,8 @@ var LocalFilesystem = class extends MastraFilesystem {
827
849
  _isWithinAnyRoot(absolutePath) {
828
850
  const roots = [this._basePath, ...this._allowedPaths];
829
851
  return roots.some((root) => {
830
- const relative2 = nodePath.relative(root, absolutePath);
831
- return !relative2.startsWith("..") && !nodePath.isAbsolute(relative2);
852
+ const relative3 = nodePath.relative(root, absolutePath);
853
+ return !relative3.startsWith("..") && !nodePath.isAbsolute(relative3);
832
854
  });
833
855
  }
834
856
  toBuffer(content) {
@@ -845,12 +867,10 @@ var LocalFilesystem = class extends MastraFilesystem {
845
867
  if (this._isWithinAnyRoot(normalized)) {
846
868
  absolutePath = normalized;
847
869
  } else {
848
- const cleanedPath = inputPath.replace(/^\/+/, "");
849
- absolutePath = nodePath.resolve(this._basePath, nodePath.normalize(cleanedPath));
870
+ absolutePath = resolveWorkspacePath(this._basePath, inputPath);
850
871
  }
851
872
  } else {
852
- const cleanedPath = inputPath.replace(/^\/+/, "");
853
- absolutePath = nodePath.resolve(this._basePath, nodePath.normalize(cleanedPath));
873
+ absolutePath = resolveWorkspacePath(this._basePath, inputPath);
854
874
  }
855
875
  if (this._contained) {
856
876
  if (!this._isWithinAnyRoot(absolutePath)) {
@@ -859,6 +879,18 @@ var LocalFilesystem = class extends MastraFilesystem {
859
879
  }
860
880
  return absolutePath;
861
881
  }
882
+ /**
883
+ * Resolve a workspace-relative path to an absolute disk path.
884
+ * Uses the same resolution logic as internal file operations.
885
+ * Returns `undefined` if the path violates containment.
886
+ */
887
+ resolveAbsolutePath(inputPath) {
888
+ try {
889
+ return this.resolvePath(inputPath);
890
+ } catch {
891
+ return void 0;
892
+ }
893
+ }
862
894
  toRelativePath(absolutePath) {
863
895
  return "/" + nodePath.relative(this._basePath, absolutePath).replace(/\\/g, "/");
864
896
  }
@@ -1292,35 +1324,35 @@ var LocalFilesystem = class extends MastraFilesystem {
1292
1324
  };
1293
1325
  var InMemoryFileReadTracker = class {
1294
1326
  records = /* @__PURE__ */ new Map();
1295
- recordRead(path4, modifiedAt) {
1296
- const normalizedPath = this.normalizePath(path4);
1327
+ recordRead(path6, modifiedAt) {
1328
+ const normalizedPath = this.normalizePath(path6);
1297
1329
  this.records.set(normalizedPath, {
1298
1330
  path: normalizedPath,
1299
1331
  readAt: /* @__PURE__ */ new Date(),
1300
1332
  modifiedAtRead: modifiedAt
1301
1333
  });
1302
1334
  }
1303
- getReadRecord(path4) {
1304
- return this.records.get(this.normalizePath(path4));
1335
+ getReadRecord(path6) {
1336
+ return this.records.get(this.normalizePath(path6));
1305
1337
  }
1306
- needsReRead(path4, currentModifiedAt) {
1307
- const record = this.getReadRecord(path4);
1338
+ needsReRead(path6, currentModifiedAt) {
1339
+ const record = this.getReadRecord(path6);
1308
1340
  if (!record) {
1309
1341
  return {
1310
1342
  needsReRead: true,
1311
- reason: `File "${path4}" has not been read. You must read a file before writing to it.`
1343
+ reason: `File "${path6}" has not been read. You must read a file before writing to it.`
1312
1344
  };
1313
1345
  }
1314
1346
  if (currentModifiedAt.getTime() > record.modifiedAtRead.getTime()) {
1315
1347
  return {
1316
1348
  needsReRead: true,
1317
- 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.`
1349
+ 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.`
1318
1350
  };
1319
1351
  }
1320
1352
  return { needsReRead: false };
1321
1353
  }
1322
- clearReadRecord(path4) {
1323
- this.records.delete(this.normalizePath(path4));
1354
+ clearReadRecord(path6) {
1355
+ this.records.delete(this.normalizePath(path6));
1324
1356
  }
1325
1357
  clear() {
1326
1358
  this.records.clear();
@@ -1408,11 +1440,721 @@ function createGlobMatcher(patterns, options) {
1408
1440
  posix: true,
1409
1441
  dot: options?.dot ?? false
1410
1442
  });
1411
- return (path4) => matcher(normalizeForMatch(path4));
1443
+ return (path6) => matcher(normalizeForMatch(path6));
1444
+ }
1445
+ function matchGlob(path6, pattern, options) {
1446
+ return createGlobMatcher(pattern, options)(path6);
1447
+ }
1448
+
1449
+ // src/workspace/lsp/language.ts
1450
+ var LANGUAGE_EXTENSIONS = {
1451
+ // TypeScript/JavaScript
1452
+ ".ts": "typescript",
1453
+ ".tsx": "typescriptreact",
1454
+ ".js": "javascript",
1455
+ ".jsx": "javascriptreact",
1456
+ ".mjs": "javascript",
1457
+ ".cjs": "javascript",
1458
+ // Python
1459
+ ".py": "python",
1460
+ ".pyi": "python",
1461
+ // Go
1462
+ ".go": "go",
1463
+ // Rust
1464
+ ".rs": "rust",
1465
+ // C/C++
1466
+ ".c": "c",
1467
+ ".cpp": "cpp",
1468
+ ".cc": "cpp",
1469
+ ".cxx": "cpp",
1470
+ ".h": "c",
1471
+ ".hpp": "cpp",
1472
+ // Java
1473
+ ".java": "java",
1474
+ // JSON
1475
+ ".json": "json",
1476
+ ".jsonc": "jsonc",
1477
+ // YAML
1478
+ ".yaml": "yaml",
1479
+ ".yml": "yaml",
1480
+ // Markdown
1481
+ ".md": "markdown",
1482
+ // HTML/CSS
1483
+ ".html": "html",
1484
+ ".css": "css",
1485
+ ".scss": "scss",
1486
+ ".sass": "sass",
1487
+ ".less": "less"
1488
+ };
1489
+ function getLanguageId(filePath) {
1490
+ const dotIndex = filePath.lastIndexOf(".");
1491
+ if (dotIndex === -1) return void 0;
1492
+ const ext = filePath.substring(dotIndex);
1493
+ return LANGUAGE_EXTENSIONS[ext];
1494
+ }
1495
+ var jsonrpcModule;
1496
+ var lspProtocolModule;
1497
+ function isLSPAvailable() {
1498
+ if (jsonrpcModule !== void 0) {
1499
+ return jsonrpcModule !== null;
1500
+ }
1501
+ try {
1502
+ const req = createRequire(import.meta.url);
1503
+ req.resolve("vscode-jsonrpc/node");
1504
+ req.resolve("vscode-languageserver-protocol");
1505
+ return true;
1506
+ } catch {
1507
+ return false;
1508
+ }
1509
+ }
1510
+ async function loadLSPDeps() {
1511
+ if (jsonrpcModule !== void 0 && lspProtocolModule !== void 0) {
1512
+ if (jsonrpcModule === null || lspProtocolModule === null) return null;
1513
+ return { ...jsonrpcModule, ...lspProtocolModule };
1514
+ }
1515
+ try {
1516
+ const req = createRequire(import.meta.url);
1517
+ const jsonrpc = req("vscode-jsonrpc/node");
1518
+ const protocol = req("vscode-languageserver-protocol");
1519
+ jsonrpcModule = {
1520
+ StreamMessageReader: jsonrpc.StreamMessageReader,
1521
+ StreamMessageWriter: jsonrpc.StreamMessageWriter,
1522
+ createMessageConnection: jsonrpc.createMessageConnection
1523
+ };
1524
+ lspProtocolModule = {
1525
+ TextDocumentIdentifier: protocol.TextDocumentIdentifier,
1526
+ Position: protocol.Position
1527
+ };
1528
+ return { ...jsonrpcModule, ...lspProtocolModule };
1529
+ } catch {
1530
+ jsonrpcModule = null;
1531
+ lspProtocolModule = null;
1532
+ return null;
1533
+ }
1534
+ }
1535
+ function toFileUri(fsPath) {
1536
+ return pathToFileURL(fsPath).toString();
1537
+ }
1538
+ var LSPClient = class {
1539
+ connection = null;
1540
+ handle = null;
1541
+ serverDef;
1542
+ workspaceRoot;
1543
+ processManager;
1544
+ diagnostics = /* @__PURE__ */ new Map();
1545
+ initializationOptions = null;
1546
+ constructor(serverDef, workspaceRoot, processManager) {
1547
+ this.serverDef = serverDef;
1548
+ this.workspaceRoot = workspaceRoot;
1549
+ this.processManager = processManager;
1550
+ }
1551
+ /** Whether the underlying server process is still running. */
1552
+ get isAlive() {
1553
+ return this.handle !== null && this.handle.exitCode === void 0;
1554
+ }
1555
+ /**
1556
+ * Initialize the LSP connection — spawns the server and performs the handshake.
1557
+ */
1558
+ async initialize(initTimeout = 1e4) {
1559
+ const deps = await loadLSPDeps();
1560
+ if (!deps) {
1561
+ throw new Error("LSP dependencies (vscode-jsonrpc) are not available");
1562
+ }
1563
+ const { StreamMessageReader, StreamMessageWriter, createMessageConnection } = deps;
1564
+ const command = this.serverDef.command(this.workspaceRoot);
1565
+ if (!command) {
1566
+ throw new Error("Failed to resolve LSP server command");
1567
+ }
1568
+ this.handle = await this.processManager.spawn(command, { cwd: this.workspaceRoot });
1569
+ const initializationOptions = this.serverDef.initialization?.(this.workspaceRoot);
1570
+ const reader = new StreamMessageReader(this.handle.reader);
1571
+ const writer = new StreamMessageWriter(this.handle.writer);
1572
+ this.connection = createMessageConnection(reader, writer);
1573
+ this.connection.onError(() => {
1574
+ });
1575
+ this.connection.onNotification("textDocument/publishDiagnostics", (params) => {
1576
+ this.diagnostics.set(params.uri, params.diagnostics);
1577
+ });
1578
+ this.connection.listen();
1579
+ const initParams = {
1580
+ processId: process.pid,
1581
+ rootUri: toFileUri(this.workspaceRoot),
1582
+ workspaceFolders: [
1583
+ {
1584
+ name: "workspace",
1585
+ uri: toFileUri(this.workspaceRoot)
1586
+ }
1587
+ ],
1588
+ capabilities: {
1589
+ window: { workDoneProgress: true },
1590
+ workspace: { configuration: true },
1591
+ textDocument: {
1592
+ publishDiagnostics: {
1593
+ relatedInformation: true,
1594
+ tagSupport: { valueSet: [1, 2] },
1595
+ versionSupport: false
1596
+ },
1597
+ synchronization: {
1598
+ didOpen: true,
1599
+ didChange: true,
1600
+ dynamicRegistration: false,
1601
+ willSave: false,
1602
+ willSaveWaitUntil: false,
1603
+ didSave: false
1604
+ },
1605
+ completion: {
1606
+ dynamicRegistration: false,
1607
+ completionItem: {
1608
+ snippetSupport: false,
1609
+ commitCharactersSupport: false,
1610
+ documentationFormat: ["markdown", "plaintext"],
1611
+ deprecatedSupport: false,
1612
+ preselectSupport: false
1613
+ }
1614
+ },
1615
+ definition: { dynamicRegistration: false, linkSupport: true },
1616
+ typeDefinition: { dynamicRegistration: false, linkSupport: true },
1617
+ implementation: { dynamicRegistration: false, linkSupport: true },
1618
+ references: { dynamicRegistration: false },
1619
+ documentHighlight: { dynamicRegistration: false },
1620
+ documentSymbol: { dynamicRegistration: false, hierarchicalDocumentSymbolSupport: true },
1621
+ codeAction: {
1622
+ dynamicRegistration: false,
1623
+ codeActionLiteralSupport: {
1624
+ codeActionKind: {
1625
+ valueSet: [
1626
+ "quickfix",
1627
+ "refactor",
1628
+ "refactor.extract",
1629
+ "refactor.inline",
1630
+ "refactor.rewrite",
1631
+ "source",
1632
+ "source.organizeImports"
1633
+ ]
1634
+ }
1635
+ }
1636
+ },
1637
+ hover: { dynamicRegistration: false, contentFormat: ["markdown", "plaintext"] }
1638
+ }
1639
+ }
1640
+ };
1641
+ if (initializationOptions) {
1642
+ initParams.initializationOptions = initializationOptions;
1643
+ this.initializationOptions = initializationOptions;
1644
+ }
1645
+ this.connection.onRequest("workspace/configuration", (params) => {
1646
+ return params.items?.map(() => ({})) || [];
1647
+ });
1648
+ this.connection.onRequest("window/workDoneProgress/create", () => null);
1649
+ let initTimer;
1650
+ await Promise.race([
1651
+ this.connection.sendRequest("initialize", initParams),
1652
+ new Promise((_, reject) => {
1653
+ initTimer = setTimeout(() => reject(new Error("LSP initialize request timed out")), initTimeout);
1654
+ })
1655
+ ]).finally(() => clearTimeout(initTimer));
1656
+ this.connection.sendNotification("initialized", {});
1657
+ this.connection.sendNotification("workspace/didChangeConfiguration", {
1658
+ settings: this.initializationOptions ?? {}
1659
+ });
1660
+ }
1661
+ /**
1662
+ * Notify the server that a document has been opened.
1663
+ */
1664
+ notifyOpen(filePath, content, languageId) {
1665
+ if (!this.connection) return;
1666
+ const uri = toFileUri(filePath);
1667
+ this.diagnostics.delete(uri);
1668
+ this.connection.sendNotification("textDocument/didOpen", {
1669
+ textDocument: { uri, languageId, version: 0, text: content }
1670
+ });
1671
+ }
1672
+ /**
1673
+ * Notify the server that a document has changed.
1674
+ */
1675
+ notifyChange(filePath, content, version) {
1676
+ if (!this.connection) return;
1677
+ this.connection.sendNotification("textDocument/didChange", {
1678
+ textDocument: { uri: toFileUri(filePath), version },
1679
+ contentChanges: [{ text: content }]
1680
+ });
1681
+ }
1682
+ /**
1683
+ * Wait for diagnostics to arrive for a file.
1684
+ *
1685
+ * When `waitForChange` is false (default), returns as soon as diagnostics
1686
+ * are available. To avoid returning a premature empty array (servers may
1687
+ * publish `[]` first while still analysing), empty results trigger a short
1688
+ * settle window: polling continues for up to `settleMs` (default 500ms)
1689
+ * to see if non-empty diagnostics arrive. Non-empty results are returned
1690
+ * immediately.
1691
+ */
1692
+ async waitForDiagnostics(filePath, timeoutMs = 5e3, waitForChange = false, settleMs = 500) {
1693
+ if (!this.connection) return [];
1694
+ const uri = toFileUri(filePath);
1695
+ const startTime = Date.now();
1696
+ const initialDiagnostics = this.diagnostics.get(uri);
1697
+ let emptyReceivedAt;
1698
+ while (Date.now() - startTime < timeoutMs) {
1699
+ const currentDiagnostics = this.diagnostics.get(uri);
1700
+ if (waitForChange) {
1701
+ if (currentDiagnostics !== void 0 && currentDiagnostics !== initialDiagnostics) {
1702
+ return currentDiagnostics;
1703
+ }
1704
+ } else {
1705
+ if (currentDiagnostics !== void 0) {
1706
+ if (currentDiagnostics.length > 0) return currentDiagnostics;
1707
+ if (emptyReceivedAt === void 0) emptyReceivedAt = Date.now();
1708
+ if (Date.now() - emptyReceivedAt >= settleMs) return currentDiagnostics;
1709
+ }
1710
+ }
1711
+ await new Promise((resolve3) => setTimeout(resolve3, 100));
1712
+ }
1713
+ return waitForChange ? initialDiagnostics || [] : this.diagnostics.get(uri) || [];
1714
+ }
1715
+ /**
1716
+ * Notify the server that a document was closed.
1717
+ */
1718
+ notifyClose(filePath) {
1719
+ if (!this.connection) return;
1720
+ const uri = toFileUri(filePath);
1721
+ this.diagnostics.delete(uri);
1722
+ this.connection.sendNotification("textDocument/didClose", {
1723
+ textDocument: { uri }
1724
+ });
1725
+ }
1726
+ /**
1727
+ * Shutdown the connection and kill the process.
1728
+ */
1729
+ async shutdown() {
1730
+ if (this.connection) {
1731
+ try {
1732
+ if (this.handle && this.handle.exitCode === void 0) {
1733
+ let shutdownTimer;
1734
+ await Promise.race([
1735
+ this.connection.sendRequest("shutdown"),
1736
+ new Promise((_, reject) => {
1737
+ shutdownTimer = setTimeout(() => reject(new Error("Shutdown request timed out")), 1e3);
1738
+ })
1739
+ ]).finally(() => clearTimeout(shutdownTimer));
1740
+ this.connection.sendNotification("exit");
1741
+ }
1742
+ } catch {
1743
+ }
1744
+ try {
1745
+ this.connection.dispose();
1746
+ } catch {
1747
+ }
1748
+ this.connection = null;
1749
+ }
1750
+ if (this.handle) {
1751
+ try {
1752
+ await this.handle.kill();
1753
+ } catch {
1754
+ }
1755
+ this.handle = null;
1756
+ }
1757
+ this.diagnostics = /* @__PURE__ */ new Map();
1758
+ }
1759
+ };
1760
+ function whichSync(binary) {
1761
+ try {
1762
+ const cmd = process.platform === "win32" ? "where" : "which";
1763
+ execFileSync(cmd, [binary], { stdio: "ignore" });
1764
+ return true;
1765
+ } catch {
1766
+ return false;
1767
+ }
1768
+ }
1769
+ function resolveRequire(root, moduleId) {
1770
+ try {
1771
+ const req = createRequire(pathToFileURL(join(root, "package.json")));
1772
+ return { require: req, resolved: req.resolve(moduleId) };
1773
+ } catch {
1774
+ }
1775
+ try {
1776
+ const req = createRequire(pathToFileURL(join(process.cwd(), "package.json")));
1777
+ return { require: req, resolved: req.resolve(moduleId) };
1778
+ } catch {
1779
+ return null;
1780
+ }
1781
+ }
1782
+ function walkUp(startDir, markers) {
1783
+ let current = startDir;
1784
+ const fsRoot = parse(current).root;
1785
+ while (true) {
1786
+ for (const marker of markers) {
1787
+ if (existsSync(join(current, marker))) {
1788
+ return current;
1789
+ }
1790
+ }
1791
+ if (current === fsRoot) break;
1792
+ const parent = dirname(current);
1793
+ if (parent === current) break;
1794
+ current = parent;
1795
+ }
1796
+ return null;
1412
1797
  }
1413
- function matchGlob(path4, pattern, options) {
1414
- return createGlobMatcher(pattern, options)(path4);
1798
+ async function walkUpAsync(startDir, markers, fs5) {
1799
+ let current = startDir;
1800
+ const fsRoot = parse(current).root;
1801
+ while (true) {
1802
+ for (const marker of markers) {
1803
+ if (await fs5.exists(join(current, marker))) {
1804
+ return current;
1805
+ }
1806
+ }
1807
+ if (current === fsRoot) break;
1808
+ const parent = dirname(current);
1809
+ if (parent === current) break;
1810
+ current = parent;
1811
+ }
1812
+ return null;
1813
+ }
1814
+ var DEFAULT_MARKERS = [
1815
+ "tsconfig.json",
1816
+ "package.json",
1817
+ "pyproject.toml",
1818
+ "go.mod",
1819
+ "Cargo.toml",
1820
+ "composer.json",
1821
+ ".git"
1822
+ ];
1823
+ function findProjectRoot(startDir) {
1824
+ return walkUp(startDir, DEFAULT_MARKERS);
1825
+ }
1826
+ var BUILTIN_SERVERS = {
1827
+ typescript: {
1828
+ id: "typescript",
1829
+ name: "TypeScript Language Server",
1830
+ languageIds: ["typescript", "typescriptreact", "javascript", "javascriptreact"],
1831
+ markers: ["tsconfig.json", "package.json"],
1832
+ command: (root) => {
1833
+ const ts = resolveRequire(root, "typescript/lib/tsserver.js");
1834
+ if (!ts) return void 0;
1835
+ const localBin = join(root, "node_modules", ".bin", "typescript-language-server");
1836
+ const cwdBin = join(process.cwd(), "node_modules", ".bin", "typescript-language-server");
1837
+ if (existsSync(localBin)) return `${localBin} --stdio`;
1838
+ if (existsSync(cwdBin)) return `${cwdBin} --stdio`;
1839
+ return void 0;
1840
+ },
1841
+ initialization: (root) => {
1842
+ const ts = resolveRequire(root, "typescript/lib/tsserver.js");
1843
+ if (!ts) return void 0;
1844
+ return {
1845
+ tsserver: {
1846
+ path: ts.resolved,
1847
+ logVerbosity: "off"
1848
+ }
1849
+ };
1850
+ }
1851
+ },
1852
+ eslint: {
1853
+ id: "eslint",
1854
+ name: "ESLint Language Server",
1855
+ languageIds: ["typescript", "typescriptreact", "javascript", "javascriptreact"],
1856
+ markers: [
1857
+ "package.json",
1858
+ ".eslintrc.js",
1859
+ ".eslintrc.json",
1860
+ ".eslintrc.yml",
1861
+ ".eslintrc.yaml",
1862
+ "eslint.config.js",
1863
+ "eslint.config.mjs",
1864
+ "eslint.config.ts"
1865
+ ],
1866
+ command: (root) => {
1867
+ const localBin = join(root, "node_modules", ".bin", "vscode-eslint-language-server");
1868
+ const cwdBin = join(process.cwd(), "node_modules", ".bin", "vscode-eslint-language-server");
1869
+ if (existsSync(localBin)) return `${localBin} --stdio`;
1870
+ if (existsSync(cwdBin)) return `${cwdBin} --stdio`;
1871
+ return void 0;
1872
+ }
1873
+ },
1874
+ python: {
1875
+ id: "python",
1876
+ name: "Python Language Server (Pyright)",
1877
+ languageIds: ["python"],
1878
+ markers: ["pyproject.toml", "setup.py", "requirements.txt", "setup.cfg"],
1879
+ command: (root) => {
1880
+ const localBin = join(root, "node_modules", ".bin", "pyright-langserver");
1881
+ const cwdBin = join(process.cwd(), "node_modules", ".bin", "pyright-langserver");
1882
+ if (existsSync(localBin)) return `${localBin} --stdio`;
1883
+ if (existsSync(cwdBin)) return `${cwdBin} --stdio`;
1884
+ return whichSync("pyright-langserver") ? "pyright-langserver --stdio" : void 0;
1885
+ }
1886
+ },
1887
+ go: {
1888
+ id: "go",
1889
+ name: "Go Language Server (gopls)",
1890
+ languageIds: ["go"],
1891
+ markers: ["go.mod"],
1892
+ command: () => {
1893
+ return whichSync("gopls") ? "gopls serve" : void 0;
1894
+ }
1895
+ },
1896
+ rust: {
1897
+ id: "rust",
1898
+ name: "Rust Language Server (rust-analyzer)",
1899
+ languageIds: ["rust"],
1900
+ markers: ["Cargo.toml"],
1901
+ command: () => {
1902
+ return whichSync("rust-analyzer") ? "rust-analyzer --stdio" : void 0;
1903
+ }
1904
+ }
1905
+ };
1906
+ function getServersForFile(filePath, disabledServers) {
1907
+ const languageId = getLanguageId(filePath);
1908
+ if (!languageId) return [];
1909
+ const disabled = new Set(disabledServers ?? []);
1910
+ return Object.values(BUILTIN_SERVERS).filter(
1911
+ (server) => !disabled.has(server.id) && server.languageIds.includes(languageId)
1912
+ );
1415
1913
  }
1914
+ function mapSeverity(severity) {
1915
+ switch (severity) {
1916
+ case 1:
1917
+ return "error";
1918
+ case 2:
1919
+ return "warning";
1920
+ case 3:
1921
+ return "info";
1922
+ case 4:
1923
+ return "hint";
1924
+ default:
1925
+ return "warning";
1926
+ }
1927
+ }
1928
+ var LSPManager = class {
1929
+ clients = /* @__PURE__ */ new Map();
1930
+ initPromises = /* @__PURE__ */ new Map();
1931
+ fileLocks = /* @__PURE__ */ new Map();
1932
+ processManager;
1933
+ _root;
1934
+ config;
1935
+ filesystem;
1936
+ constructor(processManager, root, config = {}, filesystem) {
1937
+ this.processManager = processManager;
1938
+ this._root = root;
1939
+ this.config = config;
1940
+ this.filesystem = filesystem;
1941
+ }
1942
+ /** Default project root (fallback when per-file walkup finds nothing). */
1943
+ get root() {
1944
+ return this._root;
1945
+ }
1946
+ /**
1947
+ * Resolve the project root for a given file path using the server's markers.
1948
+ * Uses the workspace filesystem when available (supports remote filesystems),
1949
+ * falls back to sync walkUp (local disk) otherwise.
1950
+ */
1951
+ async resolveRoot(filePath, markers) {
1952
+ const fileDir = nodePath__default.dirname(filePath);
1953
+ if (this.filesystem) {
1954
+ return await walkUpAsync(fileDir, markers, this.filesystem) ?? this._root;
1955
+ }
1956
+ return walkUp(fileDir, markers) ?? this._root;
1957
+ }
1958
+ /**
1959
+ * Acquire a per-file lock so that concurrent getDiagnostics calls for the
1960
+ * same file are serialized (preventing interleaved open/change/close).
1961
+ * Different files can run in parallel.
1962
+ */
1963
+ async acquireFileLock(filePath) {
1964
+ while (this.fileLocks.has(filePath)) {
1965
+ await this.fileLocks.get(filePath);
1966
+ }
1967
+ let release;
1968
+ const lockPromise = new Promise((resolve3) => {
1969
+ release = resolve3;
1970
+ });
1971
+ this.fileLocks.set(filePath, lockPromise);
1972
+ return () => {
1973
+ this.fileLocks.delete(filePath);
1974
+ release();
1975
+ };
1976
+ }
1977
+ /**
1978
+ * Initialize an LSP client for the given server definition and project root.
1979
+ * Handles timeout, deduplication of concurrent init calls, and caching.
1980
+ */
1981
+ async initClient(serverDef, projectRoot, key) {
1982
+ if (this.initPromises.has(key)) {
1983
+ await this.initPromises.get(key);
1984
+ return this.clients.get(key) || null;
1985
+ }
1986
+ const initTimeout = this.config.initTimeout ?? 15e3;
1987
+ let timedOut = false;
1988
+ const initPromise = (async () => {
1989
+ const client = new LSPClient(serverDef, projectRoot, this.processManager);
1990
+ await client.initialize(initTimeout);
1991
+ if (timedOut) {
1992
+ await client.shutdown().catch(() => {
1993
+ });
1994
+ return;
1995
+ }
1996
+ this.clients.set(key, client);
1997
+ })();
1998
+ this.initPromises.set(key, initPromise);
1999
+ initPromise.catch(() => {
2000
+ });
2001
+ try {
2002
+ await Promise.race([
2003
+ initPromise,
2004
+ new Promise(
2005
+ (_, reject) => setTimeout(() => reject(new Error("LSP client initialization timed out")), initTimeout + 1e3)
2006
+ )
2007
+ ]);
2008
+ return this.clients.get(key) || null;
2009
+ } catch {
2010
+ timedOut = true;
2011
+ this.clients.delete(key);
2012
+ return null;
2013
+ } finally {
2014
+ this.initPromises.delete(key);
2015
+ }
2016
+ }
2017
+ /**
2018
+ * Get or create an LSP client for a file path.
2019
+ * Resolves the project root per-file using the server's markers.
2020
+ * Returns null if no server is available.
2021
+ */
2022
+ async getClient(filePath) {
2023
+ const servers = getServersForFile(filePath, this.config.disableServers);
2024
+ if (servers.length === 0) return null;
2025
+ const serverDef = servers.find(
2026
+ (s) => s.languageIds.includes("typescript") || s.languageIds.includes("javascript") || s.languageIds.includes("python") || s.languageIds.includes("go")
2027
+ ) ?? servers[0];
2028
+ const projectRoot = await this.resolveRoot(filePath, serverDef.markers);
2029
+ if (serverDef.command(projectRoot) === void 0) return null;
2030
+ const key = `${serverDef.name}:${projectRoot}`;
2031
+ if (this.clients.has(key)) {
2032
+ const existing = this.clients.get(key);
2033
+ if (!existing.isAlive) {
2034
+ this.clients.delete(key);
2035
+ existing.shutdown().catch(() => {
2036
+ });
2037
+ } else {
2038
+ return existing;
2039
+ }
2040
+ }
2041
+ return this.initClient(serverDef, projectRoot, key);
2042
+ }
2043
+ /**
2044
+ * Convenience method: open file, send content, wait for diagnostics, return normalized results.
2045
+ * Returns an empty array on any failure (non-blocking).
2046
+ * Uses a per-file lock to serialize concurrent calls for the same file.
2047
+ */
2048
+ async getDiagnostics(filePath, content) {
2049
+ const release = await this.acquireFileLock(filePath);
2050
+ try {
2051
+ const client = await this.getClient(filePath);
2052
+ if (!client) return [];
2053
+ const languageId = getLanguageId(filePath);
2054
+ if (!languageId) return [];
2055
+ client.notifyOpen(filePath, content, languageId);
2056
+ client.notifyChange(filePath, content, 1);
2057
+ const diagnosticTimeout = this.config.diagnosticTimeout ?? 5e3;
2058
+ let rawDiagnostics;
2059
+ try {
2060
+ rawDiagnostics = await client.waitForDiagnostics(filePath, diagnosticTimeout);
2061
+ } finally {
2062
+ client.notifyClose(filePath);
2063
+ }
2064
+ return rawDiagnostics.map((d) => ({
2065
+ severity: mapSeverity(d.severity),
2066
+ message: d.message,
2067
+ line: (d.range?.start?.line ?? 0) + 1,
2068
+ // LSP is 0-indexed, we report 1-indexed
2069
+ character: (d.range?.start?.character ?? 0) + 1,
2070
+ source: d.source
2071
+ }));
2072
+ } catch {
2073
+ return [];
2074
+ } finally {
2075
+ release();
2076
+ }
2077
+ }
2078
+ /**
2079
+ * Get diagnostics from ALL matching language servers for a file.
2080
+ * Deduplicates results by (line, character, message).
2081
+ * Individual server failures don't block other servers.
2082
+ */
2083
+ async getDiagnosticsMulti(filePath, content) {
2084
+ const servers = getServersForFile(filePath, this.config.disableServers);
2085
+ if (servers.length === 0) return [];
2086
+ const release = await this.acquireFileLock(filePath);
2087
+ try {
2088
+ const languageId = getLanguageId(filePath);
2089
+ if (!languageId) return [];
2090
+ const allDiagnostics = [];
2091
+ const results = await Promise.allSettled(
2092
+ servers.map(async (serverDef) => {
2093
+ const projectRoot = await this.resolveRoot(filePath, serverDef.markers);
2094
+ if (serverDef.command(projectRoot) === void 0) return [];
2095
+ const key = `${serverDef.name}:${projectRoot}`;
2096
+ if (this.clients.has(key)) {
2097
+ const existing = this.clients.get(key);
2098
+ if (!existing.isAlive) {
2099
+ this.clients.delete(key);
2100
+ existing.shutdown().catch(() => {
2101
+ });
2102
+ } else {
2103
+ return this.collectDiagnostics(existing, filePath, content, languageId);
2104
+ }
2105
+ }
2106
+ const client = await this.initClient(serverDef, projectRoot, key);
2107
+ if (!client) return [];
2108
+ return this.collectDiagnostics(client, filePath, content, languageId);
2109
+ })
2110
+ );
2111
+ for (const result of results) {
2112
+ if (result.status === "fulfilled") {
2113
+ allDiagnostics.push(...result.value);
2114
+ }
2115
+ }
2116
+ const seen = /* @__PURE__ */ new Set();
2117
+ return allDiagnostics.filter((d) => {
2118
+ const key = `${d.line}:${d.character}:${d.message}`;
2119
+ if (seen.has(key)) return false;
2120
+ seen.add(key);
2121
+ return true;
2122
+ });
2123
+ } finally {
2124
+ release();
2125
+ }
2126
+ }
2127
+ /**
2128
+ * Collect diagnostics from a single client for a file.
2129
+ */
2130
+ async collectDiagnostics(client, filePath, content, languageId) {
2131
+ client.notifyOpen(filePath, content, languageId);
2132
+ client.notifyChange(filePath, content, 1);
2133
+ const diagnosticTimeout = this.config.diagnosticTimeout ?? 5e3;
2134
+ let rawDiagnostics;
2135
+ try {
2136
+ rawDiagnostics = await client.waitForDiagnostics(filePath, diagnosticTimeout);
2137
+ } finally {
2138
+ client.notifyClose(filePath);
2139
+ }
2140
+ return rawDiagnostics.map((d) => ({
2141
+ severity: mapSeverity(d.severity),
2142
+ message: d.message,
2143
+ line: (d.range?.start?.line ?? 0) + 1,
2144
+ character: (d.range?.start?.character ?? 0) + 1,
2145
+ source: d.source
2146
+ }));
2147
+ }
2148
+ /**
2149
+ * Shutdown all managed LSP clients.
2150
+ */
2151
+ async shutdownAll() {
2152
+ await Promise.allSettled(Array.from(this.clients.values()).map((client) => client.shutdown()));
2153
+ this.clients.clear();
2154
+ this.initPromises.clear();
2155
+ this.fileLocks.clear();
2156
+ }
2157
+ };
1416
2158
 
1417
2159
  // src/workspace/sandbox/errors.ts
1418
2160
  var SandboxError = class extends Error {
@@ -1522,14 +2264,14 @@ var MountManager = class {
1522
2264
  /**
1523
2265
  * Get a mount entry by path.
1524
2266
  */
1525
- get(path4) {
1526
- return this._entries.get(path4);
2267
+ get(path6) {
2268
+ return this._entries.get(path6);
1527
2269
  }
1528
2270
  /**
1529
2271
  * Check if a mount exists at the given path.
1530
2272
  */
1531
- has(path4) {
1532
- return this._entries.has(path4);
2273
+ has(path6) {
2274
+ return this._entries.has(path6);
1533
2275
  }
1534
2276
  // ---------------------------------------------------------------------------
1535
2277
  // Entry Modification
@@ -1541,8 +2283,8 @@ var MountManager = class {
1541
2283
  add(mounts) {
1542
2284
  const paths = Object.keys(mounts);
1543
2285
  this.logger.debug(`Adding ${paths.length} pending mount(s)`, { paths });
1544
- for (const [path4, filesystem] of Object.entries(mounts)) {
1545
- this._entries.set(path4, {
2286
+ for (const [path6, filesystem] of Object.entries(mounts)) {
2287
+ this._entries.set(path6, {
1546
2288
  filesystem,
1547
2289
  state: "pending"
1548
2290
  });
@@ -1552,8 +2294,8 @@ var MountManager = class {
1552
2294
  * Update a mount entry's state.
1553
2295
  * Creates the entry if it doesn't exist.
1554
2296
  */
1555
- set(path4, updates) {
1556
- const existing = this._entries.get(path4);
2297
+ set(path6, updates) {
2298
+ const existing = this._entries.get(path6);
1557
2299
  if (existing) {
1558
2300
  existing.state = updates.state;
1559
2301
  if (updates.config) {
@@ -1564,7 +2306,7 @@ var MountManager = class {
1564
2306
  existing.error = updates.error;
1565
2307
  }
1566
2308
  } else if (updates.filesystem) {
1567
- this._entries.set(path4, {
2309
+ this._entries.set(path6, {
1568
2310
  filesystem: updates.filesystem,
1569
2311
  state: updates.state,
1570
2312
  config: updates.config,
@@ -1572,14 +2314,14 @@ var MountManager = class {
1572
2314
  error: updates.error
1573
2315
  });
1574
2316
  } else {
1575
- this.logger.debug(`set() called for unknown path "${path4}" without filesystem \u2014 no entry created`);
2317
+ this.logger.debug(`set() called for unknown path "${path6}" without filesystem \u2014 no entry created`);
1576
2318
  }
1577
2319
  }
1578
2320
  /**
1579
2321
  * Delete a mount entry.
1580
2322
  */
1581
- delete(path4) {
1582
- return this._entries.delete(path4);
2323
+ delete(path6) {
2324
+ return this._entries.delete(path6);
1583
2325
  }
1584
2326
  /**
1585
2327
  * Clear all mount entries.
@@ -1600,7 +2342,7 @@ var MountManager = class {
1600
2342
  return;
1601
2343
  }
1602
2344
  this.logger.debug(`Processing ${pendingCount} pending mount(s)`);
1603
- for (const [path4, entry] of this._entries) {
2345
+ for (const [path6, entry] of this._entries) {
1604
2346
  if (entry.state !== "pending") {
1605
2347
  continue;
1606
2348
  }
@@ -1610,7 +2352,7 @@ var MountManager = class {
1610
2352
  try {
1611
2353
  const hookResult = await this._onMount({
1612
2354
  filesystem: entry.filesystem,
1613
- mountPath: path4,
2355
+ mountPath: path6,
1614
2356
  config,
1615
2357
  sandbox: this._sandbox,
1616
2358
  workspace: this._workspace
@@ -1618,7 +2360,7 @@ var MountManager = class {
1618
2360
  if (hookResult === false) {
1619
2361
  entry.state = "unsupported";
1620
2362
  entry.error = "Skipped by onMount hook";
1621
- this.logger.debug(`Mount skipped by onMount hook`, { path: path4, provider: fsProvider });
2363
+ this.logger.debug(`Mount skipped by onMount hook`, { path: path6, provider: fsProvider });
1622
2364
  continue;
1623
2365
  }
1624
2366
  if (hookResult && typeof hookResult === "object") {
@@ -1626,45 +2368,45 @@ var MountManager = class {
1626
2368
  entry.state = "mounted";
1627
2369
  entry.config = config;
1628
2370
  entry.configHash = config ? this.hashConfig(config) : void 0;
1629
- this.logger.info(`Mount handled by onMount hook`, { path: path4, provider: fsProvider });
2371
+ this.logger.info(`Mount handled by onMount hook`, { path: path6, provider: fsProvider });
1630
2372
  } else {
1631
2373
  entry.state = "error";
1632
2374
  entry.error = hookResult.error ?? "Mount hook failed";
1633
- this.logger.error(`Mount hook failed`, { path: path4, provider: fsProvider, error: entry.error });
2375
+ this.logger.error(`Mount hook failed`, { path: path6, provider: fsProvider, error: entry.error });
1634
2376
  }
1635
2377
  continue;
1636
2378
  }
1637
2379
  } catch (err) {
1638
2380
  entry.state = "error";
1639
2381
  entry.error = `Mount hook error: ${String(err)}`;
1640
- this.logger.error(`Mount hook threw error`, { path: path4, provider: fsProvider, error: entry.error });
2382
+ this.logger.error(`Mount hook threw error`, { path: path6, provider: fsProvider, error: entry.error });
1641
2383
  continue;
1642
2384
  }
1643
2385
  }
1644
2386
  if (!config) {
1645
2387
  entry.state = "unsupported";
1646
2388
  entry.error = "Filesystem does not support mounting";
1647
- this.logger.debug(`Filesystem does not support mounting`, { path: path4, provider: fsProvider });
2389
+ this.logger.debug(`Filesystem does not support mounting`, { path: path6, provider: fsProvider });
1648
2390
  continue;
1649
2391
  }
1650
2392
  entry.config = config;
1651
2393
  entry.configHash = this.hashConfig(config);
1652
2394
  entry.state = "mounting";
1653
- this.logger.debug(`Mounting filesystem`, { path: path4, provider: fsProvider, type: config.type });
2395
+ this.logger.debug(`Mounting filesystem`, { path: path6, provider: fsProvider, type: config.type });
1654
2396
  try {
1655
- const result = await this._mountFn(entry.filesystem, path4);
2397
+ const result = await this._mountFn(entry.filesystem, path6);
1656
2398
  if (result.success) {
1657
2399
  entry.state = "mounted";
1658
- this.logger.info(`Mount successful`, { path: path4, provider: fsProvider });
2400
+ this.logger.info(`Mount successful`, { path: path6, provider: fsProvider });
1659
2401
  } else {
1660
2402
  entry.state = "error";
1661
2403
  entry.error = result.error ?? "Mount failed";
1662
- this.logger.error(`Mount failed`, { path: path4, provider: fsProvider, error: entry.error });
2404
+ this.logger.error(`Mount failed`, { path: path6, provider: fsProvider, error: entry.error });
1663
2405
  }
1664
2406
  } catch (err) {
1665
2407
  entry.state = "error";
1666
2408
  entry.error = String(err);
1667
- this.logger.error(`Mount threw error`, { path: path4, provider: fsProvider, error: entry.error });
2409
+ this.logger.error(`Mount threw error`, { path: path6, provider: fsProvider, error: entry.error });
1668
2410
  }
1669
2411
  }
1670
2412
  }
@@ -1712,10 +2454,10 @@ var MountManager = class {
1712
2454
  if (separatorIndex <= 0) {
1713
2455
  return null;
1714
2456
  }
1715
- const path4 = content.slice(0, separatorIndex);
2457
+ const path6 = content.slice(0, separatorIndex);
1716
2458
  const configHash = content.slice(separatorIndex + 1);
1717
- if (!path4 || !configHash) return null;
1718
- return { path: path4, configHash };
2459
+ if (!path6 || !configHash) return null;
2460
+ return { path: path6, configHash };
1719
2461
  }
1720
2462
  /**
1721
2463
  * Check if a config hash matches the expected hash for a mount path.
@@ -2937,18 +3679,18 @@ var VersionedSkillSource = class {
2937
3679
  /**
2938
3680
  * Normalize a path by stripping leading/trailing slashes and dots.
2939
3681
  */
2940
- #normalizePath(path4) {
2941
- let normalized = path4.replace(/^[./\\]+|[/\\]+$/g, "");
3682
+ #normalizePath(path6) {
3683
+ let normalized = path6.replace(/^[./\\]+|[/\\]+$/g, "");
2942
3684
  if (normalized === "") return "";
2943
3685
  return normalized;
2944
3686
  }
2945
- async exists(path4) {
2946
- const normalized = this.#normalizePath(path4);
3687
+ async exists(path6) {
3688
+ const normalized = this.#normalizePath(path6);
2947
3689
  if (this.#tree.entries[normalized]) return true;
2948
3690
  return this.#directories.has(normalized);
2949
3691
  }
2950
- async stat(path4) {
2951
- const normalized = this.#normalizePath(path4);
3692
+ async stat(path6) {
3693
+ const normalized = this.#normalizePath(path6);
2952
3694
  const name = normalized.split("/").pop() || normalized || ".";
2953
3695
  const entry = this.#tree.entries[normalized];
2954
3696
  if (entry) {
@@ -2970,27 +3712,27 @@ var VersionedSkillSource = class {
2970
3712
  modifiedAt: this.#versionCreatedAt
2971
3713
  };
2972
3714
  }
2973
- throw new Error(`Path not found in skill version tree: ${path4}`);
3715
+ throw new Error(`Path not found in skill version tree: ${path6}`);
2974
3716
  }
2975
- async readFile(path4) {
2976
- const normalized = this.#normalizePath(path4);
3717
+ async readFile(path6) {
3718
+ const normalized = this.#normalizePath(path6);
2977
3719
  const entry = this.#tree.entries[normalized];
2978
3720
  if (!entry) {
2979
- throw new Error(`File not found in skill version tree: ${path4}`);
3721
+ throw new Error(`File not found in skill version tree: ${path6}`);
2980
3722
  }
2981
3723
  const blob = await this.#blobStore.get(entry.blobHash);
2982
3724
  if (!blob) {
2983
- throw new Error(`Blob not found for hash ${entry.blobHash} (file: ${path4})`);
3725
+ throw new Error(`Blob not found for hash ${entry.blobHash} (file: ${path6})`);
2984
3726
  }
2985
3727
  if (entry.encoding === "base64") {
2986
3728
  return Buffer.from(blob.content, "base64");
2987
3729
  }
2988
3730
  return blob.content;
2989
3731
  }
2990
- async readdir(path4) {
2991
- const normalized = this.#normalizePath(path4);
3732
+ async readdir(path6) {
3733
+ const normalized = this.#normalizePath(path6);
2992
3734
  if (!this.#directories.has(normalized)) {
2993
- throw new Error(`Directory not found in skill version tree: ${path4}`);
3735
+ throw new Error(`Directory not found in skill version tree: ${path6}`);
2994
3736
  }
2995
3737
  const prefix = normalized === "" ? "" : normalized + "/";
2996
3738
  const seen = /* @__PURE__ */ new Set();
@@ -3023,15 +3765,15 @@ var CompositeVersionedSkillSource = class {
3023
3765
  this.#fallback = options?.fallback;
3024
3766
  this.#fallbackSkills = new Set(options?.fallbackSkills ?? []);
3025
3767
  }
3026
- #normalizePath(path4) {
3027
- return path4.replace(/^[./\\]+|[/\\]+$/g, "");
3768
+ #normalizePath(path6) {
3769
+ return path6.replace(/^[./\\]+|[/\\]+$/g, "");
3028
3770
  }
3029
3771
  /**
3030
3772
  * Route a path to the correct source.
3031
3773
  * Returns the source and the remaining path within that source.
3032
3774
  */
3033
- #routePath(path4) {
3034
- const normalized = this.#normalizePath(path4);
3775
+ #routePath(path6) {
3776
+ const normalized = this.#normalizePath(path6);
3035
3777
  if (normalized === "") return null;
3036
3778
  const segments = normalized.split("/");
3037
3779
  const skillDir = segments[0];
@@ -3048,15 +3790,15 @@ var CompositeVersionedSkillSource = class {
3048
3790
  }
3049
3791
  return null;
3050
3792
  }
3051
- async exists(path4) {
3052
- const normalized = this.#normalizePath(path4);
3793
+ async exists(path6) {
3794
+ const normalized = this.#normalizePath(path6);
3053
3795
  if (normalized === "") return true;
3054
- const route = this.#routePath(path4);
3796
+ const route = this.#routePath(path6);
3055
3797
  if (!route) return false;
3056
3798
  return route.source.exists(route.subPath);
3057
3799
  }
3058
- async stat(path4) {
3059
- const normalized = this.#normalizePath(path4);
3800
+ async stat(path6) {
3801
+ const normalized = this.#normalizePath(path6);
3060
3802
  if (normalized === "") {
3061
3803
  return {
3062
3804
  name: ".",
@@ -3066,21 +3808,21 @@ var CompositeVersionedSkillSource = class {
3066
3808
  modifiedAt: /* @__PURE__ */ new Date()
3067
3809
  };
3068
3810
  }
3069
- const route = this.#routePath(path4);
3811
+ const route = this.#routePath(path6);
3070
3812
  if (!route) {
3071
- throw new Error(`Path not found in composite skill source: ${path4}`);
3813
+ throw new Error(`Path not found in composite skill source: ${path6}`);
3072
3814
  }
3073
3815
  return route.source.stat(route.subPath);
3074
3816
  }
3075
- async readFile(path4) {
3076
- const route = this.#routePath(path4);
3817
+ async readFile(path6) {
3818
+ const route = this.#routePath(path6);
3077
3819
  if (!route) {
3078
- throw new Error(`File not found in composite skill source: ${path4}`);
3820
+ throw new Error(`File not found in composite skill source: ${path6}`);
3079
3821
  }
3080
3822
  return route.source.readFile(route.subPath);
3081
3823
  }
3082
- async readdir(path4) {
3083
- const normalized = this.#normalizePath(path4);
3824
+ async readdir(path6) {
3825
+ const normalized = this.#normalizePath(path6);
3084
3826
  if (normalized === "") {
3085
3827
  const entries = [];
3086
3828
  const seen = /* @__PURE__ */ new Set();
@@ -3096,9 +3838,9 @@ var CompositeVersionedSkillSource = class {
3096
3838
  }
3097
3839
  return entries;
3098
3840
  }
3099
- const route = this.#routePath(path4);
3841
+ const route = this.#routePath(path6);
3100
3842
  if (!route) {
3101
- throw new Error(`Directory not found in composite skill source: ${path4}`);
3843
+ throw new Error(`Directory not found in composite skill source: ${path6}`);
3102
3844
  }
3103
3845
  return route.source.readdir(route.subPath);
3104
3846
  }
@@ -3222,7 +3964,7 @@ var WorkspaceSkillsImpl = class _WorkspaceSkillsImpl {
3222
3964
  if (a.length !== b.length) return false;
3223
3965
  const sortedA = [...a].sort();
3224
3966
  const sortedB = [...b].sort();
3225
- return sortedA.every((path4, i) => path4 === sortedB[i]);
3967
+ return sortedA.every((path6, i) => path6 === sortedB[i]);
3226
3968
  }
3227
3969
  // ===========================================================================
3228
3970
  // Search
@@ -3270,7 +4012,7 @@ var WorkspaceSkillsImpl = class _WorkspaceSkillsImpl {
3270
4012
  const skill = this.#skills.get(skillName);
3271
4013
  if (!skill) return null;
3272
4014
  const safeRefPath = this.#assertRelativePath(referencePath, "reference");
3273
- const refFilePath = this.#joinPath(skill.path, "references", safeRefPath);
4015
+ const refFilePath = this.#joinPath(skill.path, safeRefPath);
3274
4016
  if (!await this.#source.exists(refFilePath)) {
3275
4017
  return null;
3276
4018
  }
@@ -3286,7 +4028,7 @@ var WorkspaceSkillsImpl = class _WorkspaceSkillsImpl {
3286
4028
  const skill = this.#skills.get(skillName);
3287
4029
  if (!skill) return null;
3288
4030
  const safeScriptPath = this.#assertRelativePath(scriptPath, "script");
3289
- const scriptFilePath = this.#joinPath(skill.path, "scripts", safeScriptPath);
4031
+ const scriptFilePath = this.#joinPath(skill.path, safeScriptPath);
3290
4032
  if (!await this.#source.exists(scriptFilePath)) {
3291
4033
  return null;
3292
4034
  }
@@ -3302,7 +4044,7 @@ var WorkspaceSkillsImpl = class _WorkspaceSkillsImpl {
3302
4044
  const skill = this.#skills.get(skillName);
3303
4045
  if (!skill) return null;
3304
4046
  const safeAssetPath = this.#assertRelativePath(assetPath, "asset");
3305
- const assetFilePath = this.#joinPath(skill.path, "assets", safeAssetPath);
4047
+ const assetFilePath = this.#joinPath(skill.path, safeAssetPath);
3306
4048
  if (!await this.#source.exists(assetFilePath)) {
3307
4049
  return null;
3308
4050
  }
@@ -3748,7 +4490,7 @@ ${validation.errors.join("\n")}`);
3748
4490
  if (includeReferences) {
3749
4491
  for (const refPath of skill.references) {
3750
4492
  if (results.length >= topK) break;
3751
- const content = await this.getReference(skill.name, refPath);
4493
+ const content = await this.getReference(skill.name, `references/${refPath}`);
3752
4494
  if (content && content.toLowerCase().includes(queryLower)) {
3753
4495
  results.push({
3754
4496
  skillName: skill.name,
@@ -3791,8 +4533,8 @@ ${validation.errors.join("\n")}`);
3791
4533
  */
3792
4534
  #assertRelativePath(input, label) {
3793
4535
  const normalized = input.replace(/\\/g, "/");
3794
- const segments = normalized.split("/").filter(Boolean);
3795
- if (normalized.startsWith("/") || segments.some((seg) => seg === "." || seg === "..")) {
4536
+ const segments = normalized.split("/").filter((seg) => Boolean(seg) && seg !== ".");
4537
+ if (normalized.startsWith("/") || segments.some((seg) => seg === "..")) {
3796
4538
  throw new Error(`Invalid ${label} path: ${input}`);
3797
4539
  }
3798
4540
  return segments.join("/");
@@ -3800,9 +4542,9 @@ ${validation.errors.join("\n")}`);
3800
4542
  /**
3801
4543
  * Get parent path
3802
4544
  */
3803
- #getParentPath(path4) {
3804
- const lastSlash = path4.lastIndexOf("/");
3805
- return lastSlash > 0 ? path4.substring(0, lastSlash) : "/";
4545
+ #getParentPath(path6) {
4546
+ const lastSlash = path6.lastIndexOf("/");
4547
+ return lastSlash > 0 ? path6.substring(0, lastSlash) : "/";
3806
4548
  }
3807
4549
  };
3808
4550
  function hashContent(content) {
@@ -3963,6 +4705,7 @@ var Workspace = class {
3963
4705
  _config;
3964
4706
  _searchEngine;
3965
4707
  _skills;
4708
+ _lsp;
3966
4709
  constructor(config) {
3967
4710
  this.id = config.id ?? this.generateId();
3968
4711
  this.name = config.name ?? `workspace-${this.id.slice(0, 8)}`;
@@ -4019,6 +4762,26 @@ var Workspace = class {
4019
4762
  } : void 0
4020
4763
  });
4021
4764
  }
4765
+ if (config.lsp) {
4766
+ const processes = this._sandbox?.processes;
4767
+ if (!this._sandbox) {
4768
+ console.warn(
4769
+ `[Workspace "${this.name}"] lsp: true requires a sandbox with a process manager. No sandbox configured \u2014 LSP disabled.`
4770
+ );
4771
+ } else if (!processes) {
4772
+ console.warn(
4773
+ `[Workspace "${this.name}"] lsp: true requires a sandbox with a process manager. Sandbox "${this._sandbox.name ?? "unknown"}" does not provide one \u2014 LSP disabled.`
4774
+ );
4775
+ } else if (!isLSPAvailable()) {
4776
+ console.warn(
4777
+ `[Workspace "${this.name}"] lsp: true requires vscode-jsonrpc and vscode-languageserver-protocol packages. Install them to enable LSP diagnostics.`
4778
+ );
4779
+ } else {
4780
+ const lspConfig = config.lsp === true ? {} : config.lsp;
4781
+ const defaultRoot = lspConfig.root ?? findProjectRoot(process.cwd()) ?? process.cwd();
4782
+ this._lsp = new LSPManager(processes, defaultRoot, lspConfig, this._fs);
4783
+ }
4784
+ }
4022
4785
  if (!this._fs && !this._sandbox && !this.hasSkillsConfig()) {
4023
4786
  throw new WorkspaceError("Workspace requires at least a filesystem, sandbox, or skills", "NO_PROVIDERS");
4024
4787
  }
@@ -4057,6 +4820,13 @@ var Workspace = class {
4057
4820
  getToolsConfig() {
4058
4821
  return this._config.tools;
4059
4822
  }
4823
+ /**
4824
+ * The LSP manager (if configured, initialized, and a process manager is available).
4825
+ * Returns undefined if LSP is not configured, deps are missing, or sandbox has no process manager.
4826
+ */
4827
+ get lsp() {
4828
+ return this._lsp;
4829
+ }
4060
4830
  /**
4061
4831
  * Update the per-tool configuration for this workspace.
4062
4832
  * Takes effect on the next `createWorkspaceTools()` call.
@@ -4137,13 +4907,13 @@ var Workspace = class {
4137
4907
  * @param options - Index options (metadata, type hints)
4138
4908
  * @throws {SearchNotAvailableError} if search is not configured
4139
4909
  */
4140
- async index(path4, content, options) {
4910
+ async index(path6, content, options) {
4141
4911
  if (!this._searchEngine) {
4142
4912
  throw new SearchNotAvailableError();
4143
4913
  }
4144
4914
  this.lastAccessedAt = /* @__PURE__ */ new Date();
4145
4915
  const doc = {
4146
- id: path4,
4916
+ id: path6,
4147
4917
  content,
4148
4918
  metadata: {
4149
4919
  type: options?.type,
@@ -4260,6 +5030,13 @@ var Workspace = class {
4260
5030
  async destroy() {
4261
5031
  this._status = "destroying";
4262
5032
  try {
5033
+ if (this._lsp) {
5034
+ try {
5035
+ await this._lsp.shutdownAll();
5036
+ } catch {
5037
+ }
5038
+ this._lsp = void 0;
5039
+ }
4263
5040
  if (this._sandbox) {
4264
5041
  await callLifecycle(this._sandbox, "destroy");
4265
5042
  }
@@ -4850,11 +5627,11 @@ function buildBwrapCommand(command, workspacePath, config) {
4850
5627
  }
4851
5628
  bwrapArgs.push("--proc", "/proc");
4852
5629
  bwrapArgs.push("--tmpfs", "/tmp");
4853
- for (const path4 of DEFAULT_READONLY_BINDS) {
4854
- bwrapArgs.push("--ro-bind-try", path4, path4);
5630
+ for (const path6 of DEFAULT_READONLY_BINDS) {
5631
+ bwrapArgs.push("--ro-bind-try", path6, path6);
4855
5632
  }
4856
- for (const path4 of config.readOnlyPaths ?? []) {
4857
- bwrapArgs.push("--ro-bind", path4, path4);
5633
+ for (const path6 of config.readOnlyPaths ?? []) {
5634
+ bwrapArgs.push("--ro-bind", path6, path6);
4858
5635
  }
4859
5636
  if (config.allowSystemBinaries !== false) {
4860
5637
  const nodePath4 = process.execPath;
@@ -4866,8 +5643,8 @@ function buildBwrapCommand(command, workspacePath, config) {
4866
5643
  bwrapArgs.push("--ro-bind-try", "/snap", "/snap");
4867
5644
  }
4868
5645
  bwrapArgs.push("--bind", workspacePath, workspacePath);
4869
- for (const path4 of config.readWritePaths ?? []) {
4870
- bwrapArgs.push("--bind", path4, path4);
5646
+ for (const path6 of config.readWritePaths ?? []) {
5647
+ bwrapArgs.push("--bind", path6, path6);
4871
5648
  }
4872
5649
  bwrapArgs.push("--chdir", workspacePath);
4873
5650
  bwrapArgs.push("--die-with-parent");
@@ -5112,8 +5889,6 @@ var WORKSPACE_TOOLS = {
5112
5889
  INDEX: `${WORKSPACE_TOOLS_PREFIX}_index`
5113
5890
  }
5114
5891
  };
5115
-
5116
- // src/workspace/tools/helpers.ts
5117
5892
  function requireWorkspace(context) {
5118
5893
  if (!context?.workspace) {
5119
5894
  throw new WorkspaceNotAvailableError();
@@ -5143,6 +5918,63 @@ async function emitWorkspaceMetadata(context, toolName) {
5143
5918
  data: { toolName, toolCallId, ...info }
5144
5919
  });
5145
5920
  }
5921
+ async function getEditDiagnosticsText(workspace, filePath, content) {
5922
+ try {
5923
+ const lspManager = workspace.lsp;
5924
+ if (!lspManager) return "";
5925
+ const absolutePath = workspace.filesystem?.resolveAbsolutePath?.(filePath) ?? nodePath__default.resolve(lspManager.root, filePath.replace(/^\/+/, ""));
5926
+ const DIAG_TIMEOUT_MS = 1e4;
5927
+ let diagTimer;
5928
+ const diagnostics = await Promise.race([
5929
+ lspManager.getDiagnostics(absolutePath, content),
5930
+ new Promise((_, reject) => {
5931
+ diagTimer = setTimeout(() => reject(new Error("LSP diagnostics timeout")), DIAG_TIMEOUT_MS);
5932
+ })
5933
+ ]).finally(() => clearTimeout(diagTimer));
5934
+ if (diagnostics.length === 0) return "";
5935
+ const seen = /* @__PURE__ */ new Set();
5936
+ const deduped = diagnostics.filter((d) => {
5937
+ const key = `${d.severity}:${d.line}:${d.character}:${d.message}`;
5938
+ if (seen.has(key)) return false;
5939
+ seen.add(key);
5940
+ return true;
5941
+ });
5942
+ const groups = {
5943
+ error: [],
5944
+ warning: [],
5945
+ info: [],
5946
+ hint: []
5947
+ };
5948
+ for (const d of deduped) {
5949
+ groups[d.severity].push(d);
5950
+ }
5951
+ const lines = ["\n\nLSP Diagnostics:"];
5952
+ const severityLabels = [
5953
+ ["error", "Errors"],
5954
+ ["warning", "Warnings"],
5955
+ ["info", "Info"],
5956
+ ["hint", "Hints"]
5957
+ ];
5958
+ for (const [severity, label] of severityLabels) {
5959
+ const items = groups[severity];
5960
+ if (items.length === 0) continue;
5961
+ lines.push(`${label}:`);
5962
+ for (const d of items) {
5963
+ const source = d.source ? ` [${d.source}]` : "";
5964
+ lines.push(` ${d.line}:${d.character} - ${d.message}${source}`);
5965
+ }
5966
+ }
5967
+ let result = lines.join("\n");
5968
+ const maxChars = 2e3;
5969
+ if (result.length > maxChars) {
5970
+ const cutoff = result.lastIndexOf("\n", maxChars);
5971
+ result = result.slice(0, cutoff > 0 ? cutoff : maxChars) + "\n ... (truncated)";
5972
+ }
5973
+ return result;
5974
+ } catch {
5975
+ return "";
5976
+ }
5977
+ }
5146
5978
 
5147
5979
  // src/workspace/tools/ast-edit.ts
5148
5980
  var astGrepModule;
@@ -5373,8 +6205,8 @@ Pattern replace (for everything else):
5373
6205
  isDefault: z.boolean().optional().describe("Whether the first name is a default import")
5374
6206
  }).optional().describe("Required for add-import transform. Specifies the module and names to import.")
5375
6207
  }),
5376
- execute: async ({ path: path4, pattern, replacement, transform, targetName, newName, importSpec }, context) => {
5377
- const { filesystem } = requireFilesystem(context);
6208
+ execute: async ({ path: path6, pattern, replacement, transform, targetName, newName, importSpec }, context) => {
6209
+ const { workspace, filesystem } = requireFilesystem(context);
5378
6210
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.AST_EDIT);
5379
6211
  if (filesystem.readOnly) {
5380
6212
  throw new WorkspaceReadOnlyError("ast_edit");
@@ -5383,24 +6215,24 @@ Pattern replace (for everything else):
5383
6215
  if (!astGrep) {
5384
6216
  return "@ast-grep/napi is not available. Install it to use AST editing.";
5385
6217
  }
5386
- const { parse, Lang } = astGrep;
6218
+ const { parse: parse2, Lang } = astGrep;
5387
6219
  let content;
5388
6220
  try {
5389
- content = await filesystem.readFile(path4, { encoding: "utf-8" });
6221
+ content = await filesystem.readFile(path6, { encoding: "utf-8" });
5390
6222
  } catch (error) {
5391
6223
  if (error instanceof FileNotFoundError) {
5392
- return `File not found: ${path4}. Use ${WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE} to create it first.`;
6224
+ return `File not found: ${path6}. Use ${WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE} to create it first.`;
5393
6225
  }
5394
6226
  throw error;
5395
6227
  }
5396
6228
  if (typeof content !== "string") {
5397
6229
  return `Cannot perform AST edits on binary files. Use ${WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE} instead.`;
5398
6230
  }
5399
- const lang = getLanguageFromPath(path4, Lang);
6231
+ const lang = getLanguageFromPath(path6, Lang);
5400
6232
  if (!lang) {
5401
- return `Unsupported file type for AST editing: ${path4}`;
6233
+ return `Unsupported file type for AST editing: ${path6}`;
5402
6234
  }
5403
- const ast = parse(lang, content);
6235
+ const ast = parse2(lang, content);
5404
6236
  const root = ast.root();
5405
6237
  let modifiedContent = content;
5406
6238
  const changes = [];
@@ -5448,12 +6280,14 @@ Pattern replace (for everything else):
5448
6280
  }
5449
6281
  const wasModified = modifiedContent !== content;
5450
6282
  if (wasModified) {
5451
- await filesystem.writeFile(path4, modifiedContent, { overwrite: true });
6283
+ await filesystem.writeFile(path6, modifiedContent, { overwrite: true });
5452
6284
  }
5453
6285
  if (!wasModified) {
5454
- return `No changes made to ${path4} (${changes.join("; ")})`;
6286
+ return `No changes made to ${path6} (${changes.join("; ")})`;
5455
6287
  }
5456
- return `${path4}: ${changes.join("; ")}`;
6288
+ let output = `${path6}: ${changes.join("; ")}`;
6289
+ output += await getEditDiagnosticsText(workspace, path6, modifiedContent);
6290
+ return output;
5457
6291
  }
5458
6292
  });
5459
6293
  var deleteFileTool = createTool({
@@ -5463,19 +6297,19 @@ var deleteFileTool = createTool({
5463
6297
  path: z.string().describe("The path to the file or directory to delete"),
5464
6298
  recursive: z.boolean().optional().default(false).describe("If true, delete directories and their contents recursively. Required for non-empty directories.")
5465
6299
  }),
5466
- execute: async ({ path: path4, recursive }, context) => {
6300
+ execute: async ({ path: path6, recursive }, context) => {
5467
6301
  const { filesystem } = requireFilesystem(context);
5468
6302
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.DELETE);
5469
6303
  if (filesystem.readOnly) {
5470
6304
  throw new WorkspaceReadOnlyError("delete");
5471
6305
  }
5472
- const stat3 = await filesystem.stat(path4);
6306
+ const stat3 = await filesystem.stat(path6);
5473
6307
  if (stat3.type === "directory") {
5474
- await filesystem.rmdir(path4, { recursive, force: recursive });
6308
+ await filesystem.rmdir(path6, { recursive, force: recursive });
5475
6309
  } else {
5476
- await filesystem.deleteFile(path4);
6310
+ await filesystem.deleteFile(path6);
5477
6311
  }
5478
- return `Deleted ${path4}`;
6312
+ return `Deleted ${path6}`;
5479
6313
  }
5480
6314
  });
5481
6315
  var editFileTool = createTool({
@@ -5493,20 +6327,22 @@ Usage:
5493
6327
  new_string: z.string().describe("The text to replace old_string with"),
5494
6328
  replace_all: z.boolean().optional().default(false).describe("If true, replace all occurrences. If false (default), old_string must be unique.")
5495
6329
  }),
5496
- execute: async ({ path: path4, old_string, new_string, replace_all }, context) => {
5497
- const { filesystem } = requireFilesystem(context);
6330
+ execute: async ({ path: path6, old_string, new_string, replace_all }, context) => {
6331
+ const { workspace, filesystem } = requireFilesystem(context);
5498
6332
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.EDIT_FILE);
5499
6333
  if (filesystem.readOnly) {
5500
6334
  throw new WorkspaceReadOnlyError("edit_file");
5501
6335
  }
5502
6336
  try {
5503
- const content = await filesystem.readFile(path4, { encoding: "utf-8" });
6337
+ const content = await filesystem.readFile(path6, { encoding: "utf-8" });
5504
6338
  if (typeof content !== "string") {
5505
6339
  return `Cannot edit binary files. Use ${WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE} instead.`;
5506
6340
  }
5507
6341
  const result = replaceString(content, old_string, new_string, replace_all);
5508
- await filesystem.writeFile(path4, result.content, { overwrite: true });
5509
- return `Replaced ${result.replacements} occurrence${result.replacements !== 1 ? "s" : ""} in ${path4}`;
6342
+ await filesystem.writeFile(path6, result.content, { overwrite: true });
6343
+ let output = `Replaced ${result.replacements} occurrence${result.replacements !== 1 ? "s" : ""} in ${path6}`;
6344
+ output += await getEditDiagnosticsText(workspace, path6, result.content);
6345
+ return output;
5510
6346
  } catch (error) {
5511
6347
  if (error instanceof StringNotFoundError) {
5512
6348
  return error.message;
@@ -5663,19 +6499,19 @@ var fileStatTool = createTool({
5663
6499
  inputSchema: z.object({
5664
6500
  path: z.string().describe("The path to check")
5665
6501
  }),
5666
- execute: async ({ path: path4 }, context) => {
6502
+ execute: async ({ path: path6 }, context) => {
5667
6503
  const { filesystem } = requireFilesystem(context);
5668
6504
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.FILE_STAT);
5669
6505
  try {
5670
- const stat3 = await filesystem.stat(path4);
6506
+ const stat3 = await filesystem.stat(path6);
5671
6507
  const modifiedAt = stat3.modifiedAt.toISOString();
5672
- const parts = [`${path4}`, `Type: ${stat3.type}`];
6508
+ const parts = [`${path6}`, `Type: ${stat3.type}`];
5673
6509
  if (stat3.size !== void 0) parts.push(`Size: ${stat3.size} bytes`);
5674
6510
  parts.push(`Modified: ${modifiedAt}`);
5675
6511
  return parts.join(" ");
5676
6512
  } catch (error) {
5677
6513
  if (error instanceof FileNotFoundError) {
5678
- return `${path4}: not found`;
6514
+ return `${path6}: not found`;
5679
6515
  }
5680
6516
  throw error;
5681
6517
  }
@@ -5906,11 +6742,11 @@ var indexContentTool = createTool({
5906
6742
  content: z.string().describe("The text content to index"),
5907
6743
  metadata: z.record(z.unknown()).optional().describe("Optional metadata to store with the document")
5908
6744
  }),
5909
- execute: async ({ path: path4, content, metadata }, context) => {
6745
+ execute: async ({ path: path6, content, metadata }, context) => {
5910
6746
  const workspace = requireWorkspace(context);
5911
6747
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.SEARCH.INDEX);
5912
- await workspace.index(path4, content, { metadata });
5913
- return `Indexed ${path4}`;
6748
+ await workspace.index(path6, content, { metadata });
6749
+ return `Indexed ${path6}`;
5914
6750
  }
5915
6751
  });
5916
6752
  var KILL_TAIL_LINES = 50;
@@ -5968,7 +6804,7 @@ var BRANCH = "\u251C\u2500\u2500 ";
5968
6804
  var LAST_BRANCH = "\u2514\u2500\u2500 ";
5969
6805
  var VERTICAL = "\u2502 ";
5970
6806
  var SPACE = " ";
5971
- async function formatAsTree(fs5, path4, options) {
6807
+ async function formatAsTree(fs5, path6, options) {
5972
6808
  const maxDepth = options?.maxDepth ?? Infinity;
5973
6809
  const showHidden = options?.showHidden ?? false;
5974
6810
  const dirsOnly = options?.dirsOnly ?? false;
@@ -6024,12 +6860,12 @@ async function formatAsTree(fs5, path4, options) {
6024
6860
  if (globMatcher && !dirsOnly) {
6025
6861
  filtered = filtered.filter((e) => {
6026
6862
  if (e.type === "directory") return true;
6027
- const entryPath = currentPath === path4 ? e.name : `${currentPath === "/" ? "" : currentPath}/${e.name}`;
6863
+ const entryPath = currentPath === path6 ? e.name : `${currentPath === "/" ? "" : currentPath}/${e.name}`;
6028
6864
  let relativePath;
6029
- if (path4 === "/" || path4 === "") {
6865
+ if (path6 === "/" || path6 === "") {
6030
6866
  relativePath = entryPath.startsWith("/") ? entryPath.slice(1) : entryPath;
6031
6867
  } else {
6032
- relativePath = entryPath.startsWith(path4 + "/") ? entryPath.slice(path4.length + 1) : entryPath;
6868
+ relativePath = entryPath.startsWith(path6 + "/") ? entryPath.slice(path6.length + 1) : entryPath;
6033
6869
  if (!relativePath) relativePath = entryPath;
6034
6870
  }
6035
6871
  return globMatcher(relativePath);
@@ -6058,7 +6894,7 @@ async function formatAsTree(fs5, path4, options) {
6058
6894
  }
6059
6895
  }
6060
6896
  }
6061
- await buildTree(path4, "", 0);
6897
+ await buildTree(path6, "", 0);
6062
6898
  const dirPart = dirCount === 1 ? "1 directory" : `${dirCount} directories`;
6063
6899
  const filePart = fileCount === 1 ? "1 file" : `${fileCount} files`;
6064
6900
  let summary = `${dirPart}, ${filePart}`;
@@ -6107,10 +6943,10 @@ Examples:
6107
6943
  'Glob pattern(s) to filter files. Examples: "**/*.ts", "src/**/*.test.ts", "*.config.{js,ts}". Directories always pass through.'
6108
6944
  )
6109
6945
  }),
6110
- execute: async ({ path: path4 = "./", maxDepth = 3, showHidden, dirsOnly, exclude, extension, pattern }, context) => {
6946
+ execute: async ({ path: path6 = "./", maxDepth = 3, showHidden, dirsOnly, exclude, extension, pattern }, context) => {
6111
6947
  const { filesystem } = requireFilesystem(context);
6112
6948
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES);
6113
- const result = await formatAsTree(filesystem, path4, {
6949
+ const result = await formatAsTree(filesystem, path6, {
6114
6950
  maxDepth,
6115
6951
  showHidden,
6116
6952
  dirsOnly,
@@ -6130,14 +6966,14 @@ var mkdirTool = createTool({
6130
6966
  path: z.string().describe("The path of the directory to create"),
6131
6967
  recursive: z.boolean().optional().default(true).describe("Whether to create parent directories if they do not exist")
6132
6968
  }),
6133
- execute: async ({ path: path4, recursive }, context) => {
6969
+ execute: async ({ path: path6, recursive }, context) => {
6134
6970
  const { filesystem } = requireFilesystem(context);
6135
6971
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.MKDIR);
6136
6972
  if (filesystem.readOnly) {
6137
6973
  throw new WorkspaceReadOnlyError("mkdir");
6138
6974
  }
6139
- await filesystem.mkdir(path4, { recursive });
6140
- return `Created directory ${path4}`;
6975
+ await filesystem.mkdir(path6, { recursive });
6976
+ return `Created directory ${path6}`;
6141
6977
  }
6142
6978
  });
6143
6979
  var readFileTool = createTool({
@@ -6150,12 +6986,12 @@ var readFileTool = createTool({
6150
6986
  limit: z.number().optional().describe("Maximum number of lines to read. If omitted, reads to the end of the file."),
6151
6987
  showLineNumbers: z.boolean().optional().default(true).describe("Whether to prefix each line with its line number (default: true)")
6152
6988
  }),
6153
- execute: async ({ path: path4, encoding, offset, limit, showLineNumbers }, context) => {
6989
+ execute: async ({ path: path6, encoding, offset, limit, showLineNumbers }, context) => {
6154
6990
  const { filesystem } = requireFilesystem(context);
6155
6991
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.READ_FILE);
6156
6992
  const effectiveEncoding = encoding ?? "utf-8";
6157
- const fullContent = await filesystem.readFile(path4, { encoding: effectiveEncoding });
6158
- const stat3 = await filesystem.stat(path4);
6993
+ const fullContent = await filesystem.readFile(path6, { encoding: effectiveEncoding });
6994
+ const stat3 = await filesystem.stat(path6);
6159
6995
  const isTextEncoding = !encoding || encoding === "utf-8" || encoding === "utf8";
6160
6996
  if (!isTextEncoding) {
6161
6997
  return `${stat3.path} (${stat3.size} bytes, ${effectiveEncoding})
@@ -6214,15 +7050,17 @@ var writeFileTool = createTool({
6214
7050
  content: z.string().describe("The content to write to the file"),
6215
7051
  overwrite: z.boolean().optional().default(true).describe("Whether to overwrite the file if it already exists")
6216
7052
  }),
6217
- execute: async ({ path: path4, content, overwrite }, context) => {
6218
- const { filesystem } = requireFilesystem(context);
7053
+ execute: async ({ path: path6, content, overwrite }, context) => {
7054
+ const { workspace, filesystem } = requireFilesystem(context);
6219
7055
  await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE);
6220
7056
  if (filesystem.readOnly) {
6221
7057
  throw new WorkspaceReadOnlyError("write_file");
6222
7058
  }
6223
- await filesystem.writeFile(path4, content, { overwrite });
7059
+ await filesystem.writeFile(path6, content, { overwrite });
6224
7060
  const size = Buffer.byteLength(content, "utf-8");
6225
- return `Wrote ${size} bytes to ${path4}`;
7061
+ let output = `Wrote ${size} bytes to ${path6}`;
7062
+ output += await getEditDiagnosticsText(workspace, path6, content);
7063
+ return output;
6226
7064
  }
6227
7065
  });
6228
7066
 
@@ -6378,5 +7216,5 @@ function createWorkspaceTools(workspace) {
6378
7216
  }
6379
7217
 
6380
7218
  export { BM25Index, CompositeFilesystem, CompositeVersionedSkillSource, DirectoryNotEmptyError, DirectoryNotFoundError, FileExistsError, FileNotFoundError, FileReadRequiredError, FilesystemError, FilesystemNotAvailableError, FilesystemNotMountableError, FilesystemNotReadyError, IsDirectoryError, IsolationUnavailableError, LocalFilesystem, LocalSandbox, LocalSkillSource, MastraFilesystem, MastraSandbox, MountError, MountManager, MountNotSupportedError, NotDirectoryError, PermissionError, ProcessHandle, SandboxError, SandboxExecutionError, SandboxFeatureNotSupportedError, SandboxNotAvailableError, SandboxNotReadyError, SandboxProcessManager, SandboxTimeoutError, SearchNotAvailableError, VersionedSkillSource, WORKSPACE_TOOLS, WORKSPACE_TOOLS_PREFIX, Workspace, WorkspaceError, WorkspaceNotAvailableError, WorkspaceNotReadyError, WorkspaceReadOnlyError, callLifecycle, collectSkillForPublish, createGlobMatcher, createWorkspaceTools, deleteFileTool, detectIsolation, editFileTool, executeCommandTool, extractGlobBase, extractLines, fileStatTool, getRecommendedIsolation, indexContentTool, isGlobPattern, isIsolationAvailable, listFilesTool, matchGlob, mkdirTool, publishSkillFromSource, readFileTool, requireFilesystem, requireSandbox, requireWorkspace, resolveToolConfig, searchTool, writeFileTool };
6381
- //# sourceMappingURL=chunk-ZSBM2SVU.js.map
6382
- //# sourceMappingURL=chunk-ZSBM2SVU.js.map
7219
+ //# sourceMappingURL=chunk-4H5F6AFP.js.map
7220
+ //# sourceMappingURL=chunk-4H5F6AFP.js.map