@shawnstack/quickforge 1.3.14 → 1.3.16

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 (350) hide show
  1. package/README.md +348 -348
  2. package/dist/assets/{anthropic-DGgbbhP2.js → anthropic-CTuvxFTI.js} +1 -1
  3. package/dist/assets/{azure-openai-responses-iVkKls8h.js → azure-openai-responses-Bbdz_9hw.js} +1 -1
  4. package/dist/assets/{google-CfWayb6J.js → google-Dwuw-aUO.js} +1 -1
  5. package/dist/assets/{google-gemini-cli-BKFbEcDj.js → google-gemini-cli-CUAh97VN.js} +1 -1
  6. package/dist/assets/{google-vertex-Di6pCCaT.js → google-vertex-I8vqzEMR.js} +1 -1
  7. package/dist/assets/{index-CgTJgJ5U.js → index-DC0sfTYJ.js} +476 -455
  8. package/dist/assets/{mistral-DGp-bWeK.js → mistral-BFoKj0LS.js} +1 -1
  9. package/dist/assets/{openai-codex-responses-CFSjwMXz.js → openai-codex-responses-BowpWoQz.js} +1 -1
  10. package/dist/assets/{openai-completions-DlNb8Upk.js → openai-completions-DgCq7TXk.js} +1 -1
  11. package/dist/assets/{openai-responses-DulHAAeh.js → openai-responses-Bj3ccKY7.js} +1 -1
  12. package/dist/assets/{openai-responses-shared-BWikZIo_.js → openai-responses-shared-B1BV7Hco.js} +1 -1
  13. package/dist/index.html +1 -1
  14. package/node_modules/@mistralai/mistralai/FUNCTIONS.md +2 -2
  15. package/node_modules/@mistralai/mistralai/README.md +41 -2
  16. package/node_modules/@mistralai/mistralai/esm/extra/structChat.js +30 -9
  17. package/node_modules/@mistralai/mistralai/esm/funcs/agentsComplete.js +1 -1
  18. package/node_modules/@mistralai/mistralai/esm/funcs/agentsStream.js +1 -1
  19. package/node_modules/@mistralai/mistralai/esm/funcs/audioSpeechComplete.js +1 -1
  20. package/node_modules/@mistralai/mistralai/esm/funcs/audioTranscriptionsComplete.js +1 -1
  21. package/node_modules/@mistralai/mistralai/esm/funcs/audioTranscriptionsStream.js +1 -1
  22. package/node_modules/@mistralai/mistralai/esm/funcs/audioVoicesCreate.js +1 -1
  23. package/node_modules/@mistralai/mistralai/esm/funcs/audioVoicesDelete.js +1 -1
  24. package/node_modules/@mistralai/mistralai/esm/funcs/audioVoicesGet.js +1 -1
  25. package/node_modules/@mistralai/mistralai/esm/funcs/audioVoicesGetSampleAudio.js +1 -1
  26. package/node_modules/@mistralai/mistralai/esm/funcs/audioVoicesList.js +1 -1
  27. package/node_modules/@mistralai/mistralai/esm/funcs/audioVoicesUpdate.js +1 -1
  28. package/node_modules/@mistralai/mistralai/esm/funcs/batchJobsCancel.js +1 -1
  29. package/node_modules/@mistralai/mistralai/esm/funcs/batchJobsCreate.js +1 -1
  30. package/node_modules/@mistralai/mistralai/esm/funcs/batchJobsDelete.js +1 -1
  31. package/node_modules/@mistralai/mistralai/esm/funcs/batchJobsGet.js +1 -1
  32. package/node_modules/@mistralai/mistralai/esm/funcs/batchJobsList.js +1 -1
  33. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsCreate.js +1 -1
  34. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsCreateVersionAlias.js +1 -1
  35. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsDelete.js +1 -1
  36. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsDeleteVersionAlias.js +1 -1
  37. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsGet.js +1 -1
  38. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsGetVersion.js +1 -1
  39. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsList.js +1 -1
  40. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsListVersionAliases.js +1 -1
  41. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsListVersions.js +1 -1
  42. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsUpdate.js +1 -1
  43. package/node_modules/@mistralai/mistralai/esm/funcs/betaAgentsUpdateVersion.js +1 -1
  44. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsActivateForOrganization.js +93 -0
  45. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsActivateForUser.js +93 -0
  46. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsActivateForWorkspace.js +93 -0
  47. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsCallTool.js +1 -1
  48. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsCreate.js +1 -1
  49. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsCreateOrUpdateOrganizationCredentials.js +1 -1
  50. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsCreateOrUpdateUserCredentials.js +1 -1
  51. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsCreateOrUpdateWorkspaceCredentials.js +1 -1
  52. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsDeactivateForOrganization.js +91 -0
  53. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsDeactivateForUser.js +90 -0
  54. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsDeactivateForWorkspace.js +90 -0
  55. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsDelete.js +1 -1
  56. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsDeleteOrganizationCredentials.js +1 -1
  57. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsDeleteUserCredentials.js +1 -1
  58. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsDeleteWorkspaceCredentials.js +1 -1
  59. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsGet.js +2 -2
  60. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsGetAuthUrl.js +1 -1
  61. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsGetAuthenticationMethods.js +1 -1
  62. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsList.js +1 -1
  63. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsListOrganizationCredentials.js +1 -1
  64. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsListTools.js +1 -1
  65. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsListUserCredentials.js +1 -1
  66. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsListWorkspaceCredentials.js +1 -1
  67. package/node_modules/@mistralai/mistralai/esm/funcs/betaConnectorsUpdate.js +1 -1
  68. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsAppend.js +1 -1
  69. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsAppendStream.js +1 -1
  70. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsDelete.js +1 -1
  71. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsGet.js +1 -1
  72. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsGetHistory.js +1 -1
  73. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsGetMessages.js +1 -1
  74. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsList.js +1 -1
  75. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsRestart.js +1 -1
  76. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsRestartStream.js +1 -1
  77. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsStart.js +1 -1
  78. package/node_modules/@mistralai/mistralai/esm/funcs/betaConversationsStartStream.js +1 -1
  79. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesAccessesDelete.js +2 -2
  80. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesAccessesList.js +1 -1
  81. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesAccessesUpdateOrCreate.js +1 -1
  82. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesCreate.js +1 -1
  83. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDelete.js +2 -2
  84. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsDelete.js +1 -1
  85. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsExtractedTextSignedUrl.js +1 -1
  86. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsGet.js +1 -1
  87. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsGetSignedUrl.js +1 -1
  88. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsLibrariesDocumentsUpdateV1.js +99 -0
  89. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsList.js +1 -1
  90. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsReprocess.js +1 -1
  91. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsStatus.js +1 -1
  92. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsTextContent.js +1 -1
  93. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsUpdate.js +5 -5
  94. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesDocumentsUpload.js +1 -1
  95. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesGet.js +1 -1
  96. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesLibrariesUpdateV1.js +95 -0
  97. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesList.js +1 -1
  98. package/node_modules/@mistralai/mistralai/esm/funcs/betaLibrariesUpdate.js +4 -4
  99. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityCampaignsCreate.js +1 -1
  100. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityCampaignsDelete.js +1 -1
  101. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityCampaignsFetch.js +1 -1
  102. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityCampaignsFetchStatus.js +1 -1
  103. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityCampaignsList.js +1 -1
  104. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityCampaignsListEvents.js +1 -1
  105. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityChatCompletionEventsFetch.js +1 -1
  106. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityChatCompletionEventsFetchSimilarEvents.js +1 -1
  107. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityChatCompletionEventsFieldsFetchOptionCounts.js +1 -1
  108. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityChatCompletionEventsFieldsFetchOptions.js +1 -1
  109. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityChatCompletionEventsFieldsList.js +1 -1
  110. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityChatCompletionEventsJudge.js +1 -1
  111. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityChatCompletionEventsSearch.js +1 -1
  112. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityChatCompletionEventsSearchIds.js +1 -1
  113. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsCreate.js +1 -1
  114. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsCreateRecord.js +1 -1
  115. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsDelete.js +1 -1
  116. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsExportToJsonl.js +1 -1
  117. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsFetch.js +1 -1
  118. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsFetchTask.js +1 -1
  119. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsImportFromCampaign.js +1 -1
  120. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsImportFromDatasetRecords.js +1 -1
  121. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsImportFromExplorer.js +1 -1
  122. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsImportFromFile.js +1 -1
  123. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsImportFromPlayground.js +1 -1
  124. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsList.js +1 -1
  125. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsListRecords.js +1 -1
  126. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsListTasks.js +1 -1
  127. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsRecordsBulkDelete.js +1 -1
  128. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsRecordsDelete.js +1 -1
  129. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsRecordsFetch.js +1 -1
  130. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsRecordsJudge.js +1 -1
  131. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsRecordsUpdatePayload.js +1 -1
  132. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsRecordsUpdateProperties.js +1 -1
  133. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityDatasetsUpdate.js +1 -1
  134. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityJudgesCreate.js +1 -1
  135. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityJudgesDelete.js +1 -1
  136. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityJudgesFetch.js +1 -1
  137. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityJudgesJudgeConversation.js +1 -1
  138. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityJudgesList.js +1 -1
  139. package/node_modules/@mistralai/mistralai/esm/funcs/betaObservabilityJudgesUpdate.js +1 -1
  140. package/node_modules/@mistralai/mistralai/esm/funcs/betaRagIngestionPipelineConfigurationsList.js +1 -1
  141. package/node_modules/@mistralai/mistralai/esm/funcs/betaRagIngestionPipelineConfigurationsRegister.js +85 -0
  142. package/node_modules/@mistralai/mistralai/esm/funcs/betaRagIngestionPipelineConfigurationsUpdateRunInfo.js +90 -0
  143. package/node_modules/@mistralai/mistralai/esm/funcs/betaRagSearchIndexesList.js +68 -0
  144. package/node_modules/@mistralai/mistralai/esm/funcs/betaRagSearchIndexesRegister.js +81 -0
  145. package/node_modules/@mistralai/mistralai/esm/funcs/chatComplete.js +1 -1
  146. package/node_modules/@mistralai/mistralai/esm/funcs/chatStream.js +1 -1
  147. package/node_modules/@mistralai/mistralai/esm/funcs/classifiersClassify.js +1 -1
  148. package/node_modules/@mistralai/mistralai/esm/funcs/classifiersClassifyChat.js +1 -1
  149. package/node_modules/@mistralai/mistralai/esm/funcs/classifiersModerate.js +1 -1
  150. package/node_modules/@mistralai/mistralai/esm/funcs/classifiersModerateChat.js +1 -1
  151. package/node_modules/@mistralai/mistralai/esm/funcs/embeddingsCreate.js +1 -1
  152. package/node_modules/@mistralai/mistralai/esm/funcs/eventsGetStreamEvents.js +1 -1
  153. package/node_modules/@mistralai/mistralai/esm/funcs/eventsGetWorkflowEvents.js +1 -1
  154. package/node_modules/@mistralai/mistralai/esm/funcs/filesDelete.js +1 -1
  155. package/node_modules/@mistralai/mistralai/esm/funcs/filesDownload.js +1 -1
  156. package/node_modules/@mistralai/mistralai/esm/funcs/filesGetSignedUrl.js +1 -1
  157. package/node_modules/@mistralai/mistralai/esm/funcs/filesList.js +1 -1
  158. package/node_modules/@mistralai/mistralai/esm/funcs/filesRetrieve.js +1 -1
  159. package/node_modules/@mistralai/mistralai/esm/funcs/filesUpload.js +1 -1
  160. package/node_modules/@mistralai/mistralai/esm/funcs/fimComplete.js +1 -1
  161. package/node_modules/@mistralai/mistralai/esm/funcs/fimStream.js +1 -1
  162. package/node_modules/@mistralai/mistralai/esm/funcs/fineTuningJobsCancel.js +1 -1
  163. package/node_modules/@mistralai/mistralai/esm/funcs/fineTuningJobsCreate.js +1 -1
  164. package/node_modules/@mistralai/mistralai/esm/funcs/fineTuningJobsGet.js +1 -1
  165. package/node_modules/@mistralai/mistralai/esm/funcs/fineTuningJobsList.js +1 -1
  166. package/node_modules/@mistralai/mistralai/esm/funcs/fineTuningJobsStart.js +1 -1
  167. package/node_modules/@mistralai/mistralai/esm/funcs/modelsArchive.js +1 -1
  168. package/node_modules/@mistralai/mistralai/esm/funcs/modelsDelete.js +1 -1
  169. package/node_modules/@mistralai/mistralai/esm/funcs/modelsList.js +1 -1
  170. package/node_modules/@mistralai/mistralai/esm/funcs/modelsRetrieve.js +1 -1
  171. package/node_modules/@mistralai/mistralai/esm/funcs/modelsUnarchive.js +1 -1
  172. package/node_modules/@mistralai/mistralai/esm/funcs/modelsUpdate.js +1 -1
  173. package/node_modules/@mistralai/mistralai/esm/funcs/ocrProcess.js +1 -1
  174. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsArchiveWorkflow.js +1 -1
  175. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsBulkArchiveWorkflows.js +81 -0
  176. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsBulkUnarchiveWorkflows.js +81 -0
  177. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsDeploymentsGetDeployment.js +1 -1
  178. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsDeploymentsListDeployments.js +1 -1
  179. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecuteWorkflow.js +1 -1
  180. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecuteWorkflowRegistration.js +1 -1
  181. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsBatchCancelWorkflowExecutions.js +1 -1
  182. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsBatchTerminateWorkflowExecutions.js +1 -1
  183. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsCancelWorkflowExecution.js +1 -1
  184. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsGetWorkflowExecution.js +1 -1
  185. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsGetWorkflowExecutionHistory.js +1 -1
  186. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsGetWorkflowExecutionTraceEvents.js +1 -1
  187. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsGetWorkflowExecutionTraceOtel.js +1 -1
  188. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsGetWorkflowExecutionTraceSummary.js +1 -1
  189. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsQueryWorkflowExecution.js +1 -1
  190. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsResetWorkflow.js +1 -1
  191. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsSignalWorkflowExecution.js +1 -1
  192. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsStream.js +1 -1
  193. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsTerminateWorkflowExecution.js +1 -1
  194. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsExecutionsUpdateWorkflowExecution.js +1 -1
  195. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsGetWorkflow.js +1 -1
  196. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsGetWorkflowRegistration.js +1 -1
  197. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsGetWorkflowRegistrations.js +1 -1
  198. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsGetWorkflows.js +1 -1
  199. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsMetricsGetWorkflowMetrics.js +1 -1
  200. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsRunsGetRun.js +1 -1
  201. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsRunsGetRunHistory.js +1 -1
  202. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsRunsListRuns.js +1 -1
  203. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsSchedulesGetSchedule.js +89 -0
  204. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsSchedulesGetSchedules.js +65 -10
  205. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsSchedulesPauseSchedule.js +92 -0
  206. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsSchedulesResumeSchedule.js +92 -0
  207. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsSchedulesScheduleWorkflow.js +1 -1
  208. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsSchedulesUnscheduleWorkflow.js +1 -1
  209. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsSchedulesUpdateSchedule.js +92 -0
  210. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsUnarchiveWorkflow.js +1 -1
  211. package/node_modules/@mistralai/mistralai/esm/funcs/workflowsUpdateWorkflow.js +1 -1
  212. package/node_modules/@mistralai/mistralai/esm/hooks/deprecation_warning.js +1 -1
  213. package/node_modules/@mistralai/mistralai/esm/lib/config.js +3 -3
  214. package/node_modules/@mistralai/mistralai/esm/models/components/agentscompletionrequest.js +2 -0
  215. package/node_modules/@mistralai/mistralai/esm/models/components/agentscompletionstreamrequest.js +2 -0
  216. package/node_modules/@mistralai/mistralai/esm/models/components/authenticationconfiguration.js +4 -2
  217. package/node_modules/@mistralai/mistralai/esm/models/components/basefielddefinition.js +3 -4
  218. package/node_modules/@mistralai/mistralai/esm/models/components/chatcompletionevent.js +2 -0
  219. package/node_modules/@mistralai/mistralai/esm/models/components/chatcompletioneventpreview.js +2 -0
  220. package/node_modules/@mistralai/mistralai/esm/models/components/chatcompletionrequest.js +2 -0
  221. package/node_modules/@mistralai/mistralai/esm/models/components/chatcompletionstreamrequest.js +2 -0
  222. package/node_modules/@mistralai/mistralai/esm/models/components/classifierfinetuningjobdetails.js +3 -0
  223. package/node_modules/@mistralai/mistralai/esm/models/components/clientcapabilities.js +23 -0
  224. package/node_modules/@mistralai/mistralai/esm/models/components/clienttaskscapability.js +17 -0
  225. package/node_modules/@mistralai/mistralai/esm/models/components/clienttasksrequestscapability.js +17 -0
  226. package/node_modules/@mistralai/mistralai/esm/models/components/completionfinetuningjobdetails.js +3 -0
  227. package/node_modules/@mistralai/mistralai/esm/models/components/connectionconfigtype.js +13 -0
  228. package/node_modules/@mistralai/mistralai/esm/models/components/connectionpreference.js +26 -0
  229. package/node_modules/@mistralai/mistralai/esm/models/components/connector.js +42 -2
  230. package/node_modules/@mistralai/mistralai/esm/models/components/connectorlocale.js +21 -0
  231. package/node_modules/@mistralai/mistralai/esm/models/components/connectorprotocol.js +15 -0
  232. package/node_modules/@mistralai/mistralai/esm/models/components/connectorsqueryfilters.js +0 -6
  233. package/node_modules/@mistralai/mistralai/esm/models/components/consumertype.js +14 -0
  234. package/node_modules/@mistralai/mistralai/esm/models/components/createconnectorrequest.js +2 -0
  235. package/node_modules/@mistralai/mistralai/esm/models/components/createingestionpipelineconfigurationrequest.js +20 -0
  236. package/node_modules/@mistralai/mistralai/esm/models/components/createsearchindexinforequest.js +33 -0
  237. package/node_modules/@mistralai/mistralai/esm/models/components/createvespaschemarequest.js +19 -0
  238. package/node_modules/@mistralai/mistralai/esm/models/components/createvespasearchindexinforequest.js +25 -0
  239. package/node_modules/@mistralai/mistralai/esm/models/components/credentialsresponse.js +2 -2
  240. package/node_modules/@mistralai/mistralai/esm/models/components/document.js +2 -0
  241. package/node_modules/@mistralai/mistralai/esm/models/components/elicitationcapability.js +15 -0
  242. package/node_modules/@mistralai/mistralai/esm/models/components/encodedpayloadoptions.js +4 -2
  243. package/node_modules/@mistralai/mistralai/esm/models/components/encryptedpatchvalue.js +15 -0
  244. package/node_modules/@mistralai/mistralai/esm/models/components/fimcompletionrequest.js +2 -0
  245. package/node_modules/@mistralai/mistralai/esm/models/components/fimcompletionstreamrequest.js +2 -0
  246. package/node_modules/@mistralai/mistralai/esm/models/components/index.js +59 -5
  247. package/node_modules/@mistralai/mistralai/esm/models/components/ingestionpipelineconfiguration.js +10 -0
  248. package/node_modules/@mistralai/mistralai/esm/models/components/jsonpatch.js +21 -0
  249. package/node_modules/@mistralai/mistralai/esm/models/components/jsonpatchappend.js +8 -1
  250. package/node_modules/@mistralai/mistralai/esm/models/components/jsonpatchpayloadresponse.js +10 -21
  251. package/node_modules/@mistralai/mistralai/esm/models/components/jsonpatchpayloadvalueresponse.js +14 -0
  252. package/node_modules/@mistralai/mistralai/esm/models/components/jsonpayloadresponse.js +8 -0
  253. package/node_modules/@mistralai/mistralai/esm/models/components/logicalexpression.js +60 -0
  254. package/node_modules/@mistralai/mistralai/esm/models/components/mcpprompt.js +26 -0
  255. package/node_modules/@mistralai/mistralai/esm/models/components/mcpresource.js +30 -0
  256. package/node_modules/@mistralai/mistralai/esm/models/components/mcpserverauthenticationrequirement.js +15 -0
  257. package/node_modules/@mistralai/mistralai/esm/models/components/mcpservercard.js +66 -0
  258. package/node_modules/@mistralai/mistralai/esm/models/components/mcpservercardmeta.js +20 -0
  259. package/node_modules/@mistralai/mistralai/esm/models/components/mcpserverremote.js +31 -0
  260. package/node_modules/@mistralai/mistralai/esm/models/components/mcpserverremoteheader.js +19 -0
  261. package/node_modules/@mistralai/mistralai/esm/models/components/mcpserverrepository.js +16 -0
  262. package/node_modules/@mistralai/mistralai/esm/models/components/mcptoolmeta.js +13 -5
  263. package/node_modules/@mistralai/mistralai/esm/models/components/ocrrequest.js +0 -1
  264. package/node_modules/@mistralai/mistralai/esm/models/components/outboundauthenticationtype.js +15 -0
  265. package/node_modules/@mistralai/mistralai/esm/models/components/partialscheduledefinition.js +35 -0
  266. package/node_modules/@mistralai/mistralai/esm/models/components/promptargument.js +16 -0
  267. package/node_modules/@mistralai/mistralai/esm/models/components/promptscapability.js +14 -0
  268. package/node_modules/@mistralai/mistralai/esm/models/components/publicauthenticationmethod.js +4 -2
  269. package/node_modules/@mistralai/mistralai/esm/models/components/publicconnectionconfig.js +23 -0
  270. package/node_modules/@mistralai/mistralai/esm/models/components/referencechunk.js +4 -4
  271. package/node_modules/@mistralai/mistralai/esm/models/components/resourcescapability.js +15 -0
  272. package/node_modules/@mistralai/mistralai/esm/models/components/resourcetype.js +14 -0
  273. package/node_modules/@mistralai/mistralai/esm/models/components/rootscapability.js +14 -0
  274. package/node_modules/@mistralai/mistralai/esm/models/components/samplingcapability.js +15 -0
  275. package/node_modules/@mistralai/mistralai/esm/models/components/scheduledefinition.js +2 -0
  276. package/node_modules/@mistralai/mistralai/esm/models/components/scheduledefinitionoutput.js +12 -0
  277. package/node_modules/@mistralai/mistralai/esm/models/components/schedulefutureexecution.js +19 -0
  278. package/node_modules/@mistralai/mistralai/esm/models/components/schedulerecentexecution.js +23 -0
  279. package/node_modules/@mistralai/mistralai/esm/models/components/searchindexresponse.js +42 -0
  280. package/node_modules/@mistralai/mistralai/esm/models/components/servercapabilities.js +25 -0
  281. package/node_modules/@mistralai/mistralai/esm/models/components/{turbinetoollocale.js → serverlocale.js} +8 -6
  282. package/node_modules/@mistralai/mistralai/esm/models/components/servertaskscapability.js +17 -0
  283. package/node_modules/@mistralai/mistralai/esm/models/components/servertasksrequestscapability.js +15 -0
  284. package/node_modules/@mistralai/mistralai/esm/models/components/taskselicitationcapability.js +14 -0
  285. package/node_modules/@mistralai/mistralai/esm/models/components/taskssamplingcapability.js +14 -0
  286. package/node_modules/@mistralai/mistralai/esm/models/components/taskstoolscapability.js +14 -0
  287. package/node_modules/@mistralai/mistralai/esm/models/components/toolexecutionconfiguration.js +93 -0
  288. package/node_modules/@mistralai/mistralai/esm/models/components/toolproperties.js +30 -0
  289. package/node_modules/@mistralai/mistralai/esm/models/components/toolscapability.js +14 -0
  290. package/node_modules/@mistralai/mistralai/esm/models/components/turbinemeta.js +22 -0
  291. package/node_modules/@mistralai/mistralai/esm/models/components/updateconnectorrequest.js +3 -0
  292. package/node_modules/@mistralai/mistralai/esm/models/components/updatedocumentrequest.js +7 -1
  293. package/node_modules/@mistralai/mistralai/esm/models/components/updatelibraryrequest.js +1 -1
  294. package/node_modules/@mistralai/mistralai/esm/models/components/updateruninfo.js +20 -0
  295. package/node_modules/@mistralai/mistralai/esm/models/components/vespaschemaresponse.js +20 -0
  296. package/node_modules/@mistralai/mistralai/esm/models/components/vespasearchindexinforesponse.js +26 -0
  297. package/node_modules/@mistralai/mistralai/esm/models/components/voiceappearance.js +42 -0
  298. package/node_modules/@mistralai/mistralai/esm/models/components/voicecreaterequest.js +3 -0
  299. package/node_modules/@mistralai/mistralai/esm/models/components/voiceresponse.js +3 -0
  300. package/node_modules/@mistralai/mistralai/esm/models/components/voiceupdaterequest.js +3 -0
  301. package/node_modules/@mistralai/mistralai/esm/models/components/workflowbulkarchiverequest.js +18 -0
  302. package/node_modules/@mistralai/mistralai/esm/models/components/workflowbulkarchiveresponse.js +17 -0
  303. package/node_modules/@mistralai/mistralai/esm/models/components/workflowbulkerror.js +22 -0
  304. package/node_modules/@mistralai/mistralai/esm/models/components/workflowbulkunarchiverequest.js +18 -0
  305. package/node_modules/@mistralai/mistralai/esm/models/components/workflowbulkunarchiveresponse.js +17 -0
  306. package/node_modules/@mistralai/mistralai/esm/models/components/workflowexecutionrequest.js +0 -3
  307. package/node_modules/@mistralai/mistralai/esm/models/components/workflowschedulelistresponse.js +6 -0
  308. package/node_modules/@mistralai/mistralai/esm/models/components/workflowschedulepauserequest.js +13 -0
  309. package/node_modules/@mistralai/mistralai/esm/models/components/workflowscheduleupdaterequest.js +14 -0
  310. package/node_modules/@mistralai/mistralai/esm/models/operations/connectoractivatefororganizationv1.js +21 -0
  311. package/node_modules/@mistralai/mistralai/esm/models/operations/connectoractivateforuserv1.js +21 -0
  312. package/node_modules/@mistralai/mistralai/esm/models/operations/connectoractivateforworkspacev1.js +21 -0
  313. package/node_modules/@mistralai/mistralai/esm/models/operations/connectordeactivatefororganizationv1.js +18 -0
  314. package/node_modules/@mistralai/mistralai/esm/models/operations/connectordeactivateforuserv1.js +18 -0
  315. package/node_modules/@mistralai/mistralai/esm/models/operations/connectordeactivateforworkspacev1.js +18 -0
  316. package/node_modules/@mistralai/mistralai/esm/models/operations/connectorgetv1.js +2 -2
  317. package/node_modules/@mistralai/mistralai/esm/models/operations/connectorlistorganizationcredentialsv1.js +1 -1
  318. package/node_modules/@mistralai/mistralai/esm/models/operations/connectorlistusercredentialsv1.js +2 -1
  319. package/node_modules/@mistralai/mistralai/esm/models/operations/connectorlistworkspacecredentialsv1.js +1 -1
  320. package/node_modules/@mistralai/mistralai/esm/models/operations/getschedulesv1workflowsschedulesget.js +48 -0
  321. package/node_modules/@mistralai/mistralai/esm/models/operations/getschedulev1workflowsschedulesscheduleidget.js +18 -0
  322. package/node_modules/@mistralai/mistralai/esm/models/operations/index.js +14 -0
  323. package/node_modules/@mistralai/mistralai/esm/models/operations/librariesdocumentspatchv1.js +23 -0
  324. package/node_modules/@mistralai/mistralai/esm/models/operations/librariespatchv1.js +21 -0
  325. package/node_modules/@mistralai/mistralai/esm/models/operations/pauseschedulev1workflowsschedulesscheduleidpausepost.js +22 -0
  326. package/node_modules/@mistralai/mistralai/esm/models/operations/resumeschedulev1workflowsschedulesscheduleidresumepost.js +22 -0
  327. package/node_modules/@mistralai/mistralai/esm/models/operations/updateruninfov1ragingestionpipelineconfigurationsidruninfoput.js +21 -0
  328. package/node_modules/@mistralai/mistralai/esm/models/operations/updateschedulev1workflowsschedulesscheduleidpatch.js +22 -0
  329. package/node_modules/@mistralai/mistralai/esm/sdk/accesses.js +1 -1
  330. package/node_modules/@mistralai/mistralai/esm/sdk/connectors.js +60 -0
  331. package/node_modules/@mistralai/mistralai/esm/sdk/documents.js +13 -1
  332. package/node_modules/@mistralai/mistralai/esm/sdk/ingestionpipelineconfigurations.js +17 -0
  333. package/node_modules/@mistralai/mistralai/esm/sdk/libraries.js +13 -1
  334. package/node_modules/@mistralai/mistralai/esm/sdk/rag.js +5 -0
  335. package/node_modules/@mistralai/mistralai/esm/sdk/schedules.js +31 -2
  336. package/node_modules/@mistralai/mistralai/esm/sdk/searchindexes.js +23 -0
  337. package/node_modules/@mistralai/mistralai/esm/sdk/workflows.js +14 -0
  338. package/node_modules/@mistralai/mistralai/esm/types/async.js +6 -6
  339. package/node_modules/@mistralai/mistralai/jsr.json +1 -1
  340. package/node_modules/@mistralai/mistralai/package.json +1 -1
  341. package/package.json +1 -1
  342. package/server/agent-manager.mjs +97 -3
  343. package/server/auto-compaction.mjs +21 -1
  344. package/server/routes/agent.mjs +27 -0
  345. package/server/tools/definitions.mjs +0 -1
  346. package/server/tools/index.mjs +747 -712
  347. package/node_modules/@mistralai/mistralai/esm/models/components/authenticationtype.js +0 -15
  348. package/node_modules/@mistralai/mistralai/esm/models/components/mcpuitoolmeta.js +0 -23
  349. package/node_modules/@mistralai/mistralai/esm/models/components/tooltype.js +0 -15
  350. package/node_modules/@mistralai/mistralai/esm/models/components/turbinetoolmeta.js +0 -25
@@ -1,481 +1,481 @@
1
- import { promises as fs } from 'node:fs'
2
- import path from 'node:path'
3
- import { spawn } from 'node:child_process'
4
- import { createRequire } from 'node:module'
5
- import { resolveWorkspacePath, toWorkspaceRelative, assertSafeWorkspacePath, truncateText, splitLines, walkFiles } from '../utils/workspace.mjs'
6
- import { createTextDiff } from '../utils/text-diff.mjs'
7
- import {
8
- formatSkillActivation,
9
- loadSelectedGlobalSkills,
10
- loadSelectedProjectSkills,
11
- mergeSkills,
12
- readSkillResource,
13
- } from '../skills.mjs'
14
- import { getToolWorkspaceRoot } from '../utils/workspace.mjs'
15
-
16
- const require = createRequire(import.meta.url)
17
-
18
- // --- read_file ---
19
- export async function toolReadFile(params, context) {
20
- const file = resolveWorkspacePath(params?.path, context)
21
- await assertSafeWorkspacePath(file, context)
22
-
23
- const text = await fs.readFile(file, 'utf8')
24
- const lines = splitLines(text)
25
- const offset = Math.max(1, Number(params?.offset || 1))
26
- const limit = Math.min(2000, Math.max(1, Number(params?.limit || 200)))
27
- const selected = lines.slice(offset - 1, offset - 1 + limit)
28
- const content = selected.map((line, index) => `${offset + index}: ${line}`).join('\n')
29
- const suffix = offset - 1 + limit < lines.length ? `\n\n[showing ${selected.length} of ${lines.length} lines]` : ''
30
-
31
- return {
32
- content: truncateText(`${content}${suffix}`),
33
- details: { path: toWorkspaceRelative(file, context), project: context?.project, totalLines: lines.length, offset, limit },
34
- }
35
- }
36
-
37
- // --- grep_files ---
38
-
39
- const RIPGREP_MAX_FILESIZE = '1M'
40
- const RIPGREP_TIMEOUT_MS = 60 * 1000
41
- const DEFAULT_EXCLUDE_GLOBS = [
42
- '!.git/**',
43
- '!node_modules/**',
44
- '!dist/**',
45
- '!dist-ssr/**',
46
- '!.vite/**',
47
- '!**/*.png',
48
- '!**/*.jpg',
49
- '!**/*.jpeg',
50
- '!**/*.gif',
51
- '!**/*.webp',
52
- '!**/*.ico',
53
- '!**/*.pdf',
54
- '!**/*.zip',
55
- '!**/*.gz',
56
- '!**/*.7z',
57
- '!**/*.exe',
58
- '!**/*.dll',
59
- '!**/*.woff',
60
- '!**/*.woff2',
61
- '!**/*.ttf',
62
- ]
63
- const SENSITIVE_EXCLUDE_GLOBS = [
64
- '!.env',
65
- '!**/.env',
66
- '!.env.*',
67
- '!**/.env.*',
68
- '!**/*.pem',
69
- '!**/*.key',
70
- '!**/*.p12',
71
- '!**/*.pfx',
72
- '!**/*.crt',
73
- '!**/*.cer',
74
- '!**/*.token',
75
- '!credentials.json',
76
- '!**/credentials.json',
77
- '!secrets.json',
78
- '!**/secrets.json',
79
- '!id_rsa',
80
- '!**/id_rsa',
81
- '!id_ed25519',
82
- '!**/id_ed25519',
83
- ]
84
-
85
- let cachedRipgrepExecutable
86
-
87
- /**
88
- * Process items with bounded concurrency. Returns results in input order.
89
- * @template T, R
90
- * @param {T[]} items
91
- * @param {(item: T, index: number) => Promise<R>} fn
92
- * @param {number} concurrency
93
- * @returns {Promise<R[]>}
94
- */
95
- async function poolMap(items, fn, concurrency = 20) {
96
- const results = new Array(items.length)
97
- let cursor = 0
98
-
99
- async function worker() {
100
- while (cursor < items.length) {
101
- const index = cursor++
102
- results[index] = await fn(items[index], index)
103
- }
104
- }
105
-
106
- const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker())
107
- await Promise.all(workers)
108
- return results
109
- }
110
-
111
- function clampNumber(value, defaultValue, min, max) {
112
- const number = Number(value)
113
- if (!Number.isFinite(number)) return defaultValue
114
- return Math.min(max, Math.max(min, Math.trunc(number)))
115
- }
116
-
117
- function escapeRegExp(value) {
118
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
119
- }
120
-
121
- function normalizeGlobList(value) {
122
- const values = Array.isArray(value) ? value : typeof value === 'string' ? [value] : []
123
- return values
124
- .map((item) => String(item || '').trim())
125
- .filter(Boolean)
126
- .slice(0, 50)
127
- }
128
-
129
- function normalizeGrepParams(params, context) {
130
- const root = resolveWorkspacePath(params?.path || '.', context)
131
- const query = String(params?.query || '')
132
- if (!query) {
133
- const error = new Error('query is required')
134
- error.statusCode = 400
135
- throw error
136
- }
137
-
138
- const flags = params?.caseSensitive ? 'g' : 'gi'
139
- try {
140
- params?.regex
141
- ? new RegExp(query, flags)
142
- : new RegExp(escapeRegExp(query), flags)
143
- } catch {
144
- const error = new Error('Invalid regular expression')
145
- error.statusCode = 400
146
- throw error
147
- }
148
-
149
- return {
150
- root,
151
- query,
152
- regex: Boolean(params?.regex),
153
- caseSensitive: Boolean(params?.caseSensitive),
154
- limit: clampNumber(params?.limit, 200, 1, 1000),
155
- glob: normalizeGlobList(params?.glob),
156
- context: clampNumber(params?.context, 0, 0, 20),
157
- beforeContext: clampNumber(params?.beforeContext, 0, 0, 20),
158
- afterContext: clampNumber(params?.afterContext, 0, 0, 20),
159
- filesWithMatches: Boolean(params?.filesWithMatches),
160
- respectGitIgnore: Boolean(params?.respectGitIgnore),
161
- }
162
- }
163
-
164
- function isRegexLikelyRipgrepCompatible(query) {
165
- return !(/\(\?[=!<]/.test(query) || /\\[1-9]/.test(query))
166
- }
167
-
168
- function ripgrepCandidatePath() {
169
- try {
170
- return require('@vscode/ripgrep').rgPath || null
171
- } catch {
172
- return null
173
- }
174
- }
175
-
176
- async function verifyRipgrepExecutable(command) {
177
- return new Promise((resolve) => {
178
- const child = spawn(command, ['--version'], { shell: false, windowsHide: true })
179
- child.once('error', () => resolve(false))
180
- child.once('close', (code) => resolve(code === 0))
181
- })
182
- }
183
-
184
- async function resolveRipgrepExecutable() {
185
- if (cachedRipgrepExecutable !== undefined) return cachedRipgrepExecutable
186
-
187
- const bundled = ripgrepCandidatePath()
188
- if (bundled && await verifyRipgrepExecutable(bundled)) {
189
- cachedRipgrepExecutable = { command: bundled, source: 'bundled' }
190
- return cachedRipgrepExecutable
191
- }
192
-
193
- if (await verifyRipgrepExecutable('rg')) {
194
- cachedRipgrepExecutable = { command: 'rg', source: 'system' }
195
- return cachedRipgrepExecutable
196
- }
197
-
198
- cachedRipgrepExecutable = null
199
- return cachedRipgrepExecutable
200
- }
201
-
202
- function buildRipgrepArgs(options, context) {
203
- const args = [
204
- '--line-number',
205
- '--color=never',
206
- '--max-filesize',
207
- RIPGREP_MAX_FILESIZE,
208
- ]
209
-
210
- if (options.filesWithMatches) {
211
- args.push('--files-with-matches')
212
- } else {
213
- args.push('--json')
214
- }
215
- if (!options.regex) args.push('--fixed-strings')
216
- if (!options.caseSensitive) args.push('--ignore-case')
217
- if (!options.respectGitIgnore) args.push('--hidden', '--no-ignore')
218
- if (options.context > 0) args.push('-C', String(options.context))
219
- if (options.beforeContext > 0) args.push('-B', String(options.beforeContext))
220
- if (options.afterContext > 0) args.push('-A', String(options.afterContext))
221
-
222
- for (const pattern of options.glob) args.push('--glob', pattern)
223
- for (const pattern of DEFAULT_EXCLUDE_GLOBS) args.push('--glob', pattern)
224
- for (const pattern of SENSITIVE_EXCLUDE_GLOBS) args.push('--glob', pattern)
225
-
226
- args.push('--', options.query, toWorkspaceRelative(options.root, context) || '.')
227
- return args
228
- }
229
-
230
- function cleanRipgrepLine(value) {
231
- return String(value || '').replace(/[\r\n]+$/, '')
232
- }
233
-
234
- function ripgrepRelativePath(value) {
235
- return String(value || '').replace(/\\/g, '/')
236
- }
237
-
238
- function formatRipgrepJsonEvent(event) {
239
- if (event?.type !== 'match' && event?.type !== 'context') return null
240
- const data = event.data || {}
241
- const file = ripgrepRelativePath(data.path?.text)
242
- const lineNumber = data.line_number
243
- const line = cleanRipgrepLine(data.lines?.text)
244
- if (!file || !lineNumber) return null
245
- const separator = event.type === 'match' ? ':' : '-'
246
- return `${file}:${lineNumber}${separator} ${line}`
247
- }
248
-
249
- function fallbackDetails(extra = {}) {
250
- return Object.fromEntries(Object.entries(extra).filter(([, value]) => value !== undefined && value !== null && value !== ''))
251
- }
252
-
253
- async function grepFilesWithRipgrep(executable, options, context, runtime = {}) {
254
- if (options.regex && !isRegexLikelyRipgrepCompatible(options.query)) {
255
- throw new Error('regex uses JavaScript-only features that ripgrep does not support')
256
- }
257
-
258
- const cwd = getToolWorkspaceRoot(context)
259
- const args = buildRipgrepArgs(options, context)
260
- const matches = []
261
- let stderr = ''
262
- let buffer = ''
263
- let killedForLimit = false
264
- let settled = false
265
-
266
- await new Promise((resolve, reject) => {
267
- if (runtime.signal?.aborted) {
268
- reject(new Error('Search aborted'))
269
- return
270
- }
271
-
272
- const child = spawn(executable.command, args, {
273
- cwd,
274
- shell: false,
275
- stdio: ['ignore', 'pipe', 'pipe'],
276
- windowsHide: true,
277
- })
278
-
279
- const cleanup = () => {
280
- clearTimeout(timer)
281
- runtime.signal?.removeEventListener?.('abort', onAbort)
282
- }
283
- const finish = (error) => {
284
- if (settled) return
285
- settled = true
286
- cleanup()
287
- if (error) reject(error)
288
- else resolve()
289
- }
290
- const stopForLimit = () => {
291
- if (killedForLimit) return
292
- killedForLimit = true
293
- killProcessTree(child, 'SIGTERM')
294
- }
295
- const processLine = (line) => {
296
- if (!line || matches.length >= options.limit) return
297
- if (options.filesWithMatches) {
298
- matches.push(ripgrepRelativePath(line))
299
- } else {
300
- try {
301
- const formatted = formatRipgrepJsonEvent(JSON.parse(line))
302
- if (formatted) matches.push(formatted)
303
- } catch {
304
- // Ignore malformed partial output and let process exit handling decide fallback.
305
- }
306
- }
307
- if (matches.length >= options.limit) stopForLimit()
308
- }
309
- const flushLines = (chunk) => {
310
- buffer += chunk.toString()
311
- const lines = buffer.split(/\r?\n/)
312
- buffer = lines.pop() || ''
313
- for (const line of lines) processLine(line)
314
- }
315
- function onAbort() {
316
- killProcessTree(child, 'SIGTERM')
317
- finish(new Error('Search aborted'))
318
- }
319
-
320
- const timer = setTimeout(() => {
321
- killProcessTree(child, 'SIGTERM')
322
- finish(new Error('ripgrep search timed out'))
323
- }, RIPGREP_TIMEOUT_MS)
324
-
325
- runtime.signal?.addEventListener?.('abort', onAbort, { once: true })
326
- child.stdout.on('data', flushLines)
327
- child.stderr.on('data', (chunk) => {
328
- stderr = truncateText(stderr + chunk.toString(), 2000)
329
- })
330
- child.once('error', finish)
331
- child.once('close', (code) => {
332
- if (buffer) processLine(buffer)
333
- if (killedForLimit || code === 0 || code === 1) {
334
- finish()
335
- } else {
336
- finish(new Error(stderr.trim() || `ripgrep exited with code ${code}`))
337
- }
338
- })
339
- })
340
-
341
- return {
342
- content: matches.length ? truncateText(matches.slice(0, options.limit).join('\n')) : 'No matches found.',
343
- details: {
344
- path: toWorkspaceRelative(options.root, context),
345
- project: context?.project,
346
- query: options.query,
347
- count: matches.length,
348
- limit: options.limit,
349
- backend: 'ripgrep',
350
- ripgrepSource: executable.source,
351
- },
352
- }
353
- }
354
-
355
- async function grepFilesWithNode(options, context, extraDetails = {}) {
356
- const flags = options.caseSensitive ? 'g' : 'gi'
357
- const matcher = options.regex
358
- ? new RegExp(options.query, flags)
359
- : new RegExp(escapeRegExp(options.query), flags)
360
-
361
- const files = await walkFiles(options.root, [], context)
362
- const matches = []
363
-
364
- // Stat and filter files in parallel, then grep in parallel batches.
365
- const candidateResults = await poolMap(files, async (file) => {
366
- try {
367
- const stat = await fs.stat(file)
368
- if (stat.size > 1024 * 1024) return { file, skip: true }
369
- return { file, skip: false }
370
- } catch {
371
- return { file, skip: true }
372
- }
373
- })
374
-
375
- const candidates = candidateResults.filter((r) => !r.skip).map((r) => r.file)
376
-
377
- // Grep with bounded concurrency — short-circuit when limit reached.
378
- let matchCount = 0
379
- const filesWithMatches = new Set()
380
- for (let batchStart = 0; batchStart < candidates.length && matchCount < options.limit; batchStart += 20) {
381
- const batch = candidates.slice(batchStart, batchStart + 20)
382
- const batchMatches = await Promise.all(
383
- batch.map(async (file) => {
384
- if (matchCount >= options.limit) return []
385
- try {
386
- const text = await fs.readFile(file, 'utf8')
387
- const lines = splitLines(text)
388
- const fileMatches = []
389
- for (let index = 0; index < lines.length && (matchCount + fileMatches.length) < options.limit; index++) {
390
- matcher.lastIndex = 0
391
- if (matcher.test(lines[index])) {
392
- const relative = toWorkspaceRelative(file, context)
393
- if (options.filesWithMatches) {
394
- if (!filesWithMatches.has(relative)) {
395
- filesWithMatches.add(relative)
396
- fileMatches.push(relative)
397
- }
398
- } else {
399
- fileMatches.push(`${relative}:${index + 1}: ${lines[index]}`)
400
- }
401
- }
402
- }
403
- return fileMatches
404
- } catch {
405
- return []
406
- }
407
- }),
408
- )
409
- for (const fm of batchMatches) {
410
- if (matchCount >= options.limit) break
411
- for (const m of fm) {
412
- if (matchCount >= options.limit) break
413
- matches.push(m)
414
- matchCount++
415
- }
416
- }
417
- }
418
-
419
- return {
420
- content: matches.length ? truncateText(matches.join('\n')) : 'No matches found.',
421
- details: {
422
- path: toWorkspaceRelative(options.root, context),
423
- project: context?.project,
424
- query: options.query,
425
- count: matches.length,
426
- limit: options.limit,
427
- backend: 'node',
428
- ...fallbackDetails(extraDetails),
429
- },
430
- }
431
- }
432
-
433
- export async function toolGrepFiles(params, context, runtime = {}) {
434
- const options = normalizeGrepParams(params, context)
435
- await assertSafeWorkspacePath(options.root, context)
436
-
437
- const executable = await resolveRipgrepExecutable()
438
- if (executable) {
439
- try {
440
- return await grepFilesWithRipgrep(executable, options, context, runtime)
441
- } catch (error) {
442
- if (runtime.signal?.aborted) throw error
443
- return grepFilesWithNode(options, context, {
444
- fallbackFrom: 'ripgrep',
445
- fallbackReason: error?.message || 'ripgrep unavailable',
446
- })
447
- }
448
- }
449
-
450
- return grepFilesWithNode(options, context, { fallbackReason: 'ripgrep unavailable' })
451
- }
452
-
453
- // --- write_file ---
454
- export async function toolWriteFile(params, context) {
455
- const file = resolveWorkspacePath(params?.path, context)
456
- await assertSafeWorkspacePath(file, context, { forWrite: true })
457
-
458
- const content = String(params?.content ?? '')
459
- const relativePath = toWorkspaceRelative(file, context)
460
- let oldText = ''
461
- let existed = true
462
- try {
463
- oldText = await fs.readFile(file, 'utf8')
464
- } catch (error) {
465
- if (error?.code !== 'ENOENT') throw error
466
- existed = false
467
- }
468
- const diff = createTextDiff(oldText, content, relativePath, { oldExists: existed })
469
-
470
- await fs.mkdir(path.dirname(file), { recursive: true })
471
- await fs.writeFile(file, content, 'utf8')
472
-
473
- return {
474
- content: `${existed ? 'Wrote' : 'Created'} ${relativePath} (+${diff.addedLines} -${diff.removedLines})`,
475
- details: { path: relativePath, project: context?.project, bytes: Buffer.byteLength(content, 'utf8'), created: !existed, diff },
476
- }
477
- }
478
-
1
+ import { promises as fs } from 'node:fs'
2
+ import path from 'node:path'
3
+ import { spawn } from 'node:child_process'
4
+ import { createRequire } from 'node:module'
5
+ import { resolveWorkspacePath, toWorkspaceRelative, assertSafeWorkspacePath, truncateText, splitLines, walkFiles } from '../utils/workspace.mjs'
6
+ import { createTextDiff } from '../utils/text-diff.mjs'
7
+ import {
8
+ formatSkillActivation,
9
+ loadSelectedGlobalSkills,
10
+ loadSelectedProjectSkills,
11
+ mergeSkills,
12
+ readSkillResource,
13
+ } from '../skills.mjs'
14
+ import { getToolWorkspaceRoot } from '../utils/workspace.mjs'
15
+
16
+ const require = createRequire(import.meta.url)
17
+
18
+ // --- read_file ---
19
+ export async function toolReadFile(params, context) {
20
+ const file = resolveWorkspacePath(params?.path, context)
21
+ await assertSafeWorkspacePath(file, context)
22
+
23
+ const text = await fs.readFile(file, 'utf8')
24
+ const lines = splitLines(text)
25
+ const offset = Math.max(1, Number(params?.offset || 1))
26
+ const limit = Math.min(2000, Math.max(1, Number(params?.limit || 200)))
27
+ const selected = lines.slice(offset - 1, offset - 1 + limit)
28
+ const content = selected.map((line, index) => `${offset + index}: ${line}`).join('\n')
29
+ const suffix = offset - 1 + limit < lines.length ? `\n\n[showing ${selected.length} of ${lines.length} lines]` : ''
30
+
31
+ return {
32
+ content: truncateText(`${content}${suffix}`),
33
+ details: { path: toWorkspaceRelative(file, context), project: context?.project, totalLines: lines.length, offset, limit },
34
+ }
35
+ }
36
+
37
+ // --- grep_files ---
38
+
39
+ const RIPGREP_MAX_FILESIZE = '1M'
40
+ const RIPGREP_TIMEOUT_MS = 60 * 1000
41
+ const DEFAULT_EXCLUDE_GLOBS = [
42
+ '!.git/**',
43
+ '!node_modules/**',
44
+ '!dist/**',
45
+ '!dist-ssr/**',
46
+ '!.vite/**',
47
+ '!**/*.png',
48
+ '!**/*.jpg',
49
+ '!**/*.jpeg',
50
+ '!**/*.gif',
51
+ '!**/*.webp',
52
+ '!**/*.ico',
53
+ '!**/*.pdf',
54
+ '!**/*.zip',
55
+ '!**/*.gz',
56
+ '!**/*.7z',
57
+ '!**/*.exe',
58
+ '!**/*.dll',
59
+ '!**/*.woff',
60
+ '!**/*.woff2',
61
+ '!**/*.ttf',
62
+ ]
63
+ const SENSITIVE_EXCLUDE_GLOBS = [
64
+ '!.env',
65
+ '!**/.env',
66
+ '!.env.*',
67
+ '!**/.env.*',
68
+ '!**/*.pem',
69
+ '!**/*.key',
70
+ '!**/*.p12',
71
+ '!**/*.pfx',
72
+ '!**/*.crt',
73
+ '!**/*.cer',
74
+ '!**/*.token',
75
+ '!credentials.json',
76
+ '!**/credentials.json',
77
+ '!secrets.json',
78
+ '!**/secrets.json',
79
+ '!id_rsa',
80
+ '!**/id_rsa',
81
+ '!id_ed25519',
82
+ '!**/id_ed25519',
83
+ ]
84
+
85
+ let cachedRipgrepExecutable
86
+
87
+ /**
88
+ * Process items with bounded concurrency. Returns results in input order.
89
+ * @template T, R
90
+ * @param {T[]} items
91
+ * @param {(item: T, index: number) => Promise<R>} fn
92
+ * @param {number} concurrency
93
+ * @returns {Promise<R[]>}
94
+ */
95
+ async function poolMap(items, fn, concurrency = 20) {
96
+ const results = new Array(items.length)
97
+ let cursor = 0
98
+
99
+ async function worker() {
100
+ while (cursor < items.length) {
101
+ const index = cursor++
102
+ results[index] = await fn(items[index], index)
103
+ }
104
+ }
105
+
106
+ const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker())
107
+ await Promise.all(workers)
108
+ return results
109
+ }
110
+
111
+ function clampNumber(value, defaultValue, min, max) {
112
+ const number = Number(value)
113
+ if (!Number.isFinite(number)) return defaultValue
114
+ return Math.min(max, Math.max(min, Math.trunc(number)))
115
+ }
116
+
117
+ function escapeRegExp(value) {
118
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
119
+ }
120
+
121
+ function normalizeGlobList(value) {
122
+ const values = Array.isArray(value) ? value : typeof value === 'string' ? [value] : []
123
+ return values
124
+ .map((item) => String(item || '').trim())
125
+ .filter(Boolean)
126
+ .slice(0, 50)
127
+ }
128
+
129
+ function normalizeGrepParams(params, context) {
130
+ const root = resolveWorkspacePath(params?.path || '.', context)
131
+ const query = String(params?.query || '')
132
+ if (!query) {
133
+ const error = new Error('query is required')
134
+ error.statusCode = 400
135
+ throw error
136
+ }
137
+
138
+ const flags = params?.caseSensitive ? 'g' : 'gi'
139
+ try {
140
+ params?.regex
141
+ ? new RegExp(query, flags)
142
+ : new RegExp(escapeRegExp(query), flags)
143
+ } catch {
144
+ const error = new Error('Invalid regular expression')
145
+ error.statusCode = 400
146
+ throw error
147
+ }
148
+
149
+ return {
150
+ root,
151
+ query,
152
+ regex: Boolean(params?.regex),
153
+ caseSensitive: Boolean(params?.caseSensitive),
154
+ limit: clampNumber(params?.limit, 200, 1, 1000),
155
+ glob: normalizeGlobList(params?.glob),
156
+ context: clampNumber(params?.context, 0, 0, 20),
157
+ beforeContext: clampNumber(params?.beforeContext, 0, 0, 20),
158
+ afterContext: clampNumber(params?.afterContext, 0, 0, 20),
159
+ filesWithMatches: Boolean(params?.filesWithMatches),
160
+ respectGitIgnore: Boolean(params?.respectGitIgnore),
161
+ }
162
+ }
163
+
164
+ function isRegexLikelyRipgrepCompatible(query) {
165
+ return !(/\(\?[=!<]/.test(query) || /\\[1-9]/.test(query))
166
+ }
167
+
168
+ function ripgrepCandidatePath() {
169
+ try {
170
+ return require('@vscode/ripgrep').rgPath || null
171
+ } catch {
172
+ return null
173
+ }
174
+ }
175
+
176
+ async function verifyRipgrepExecutable(command) {
177
+ return new Promise((resolve) => {
178
+ const child = spawn(command, ['--version'], { shell: false, windowsHide: true })
179
+ child.once('error', () => resolve(false))
180
+ child.once('close', (code) => resolve(code === 0))
181
+ })
182
+ }
183
+
184
+ async function resolveRipgrepExecutable() {
185
+ if (cachedRipgrepExecutable !== undefined) return cachedRipgrepExecutable
186
+
187
+ const bundled = ripgrepCandidatePath()
188
+ if (bundled && await verifyRipgrepExecutable(bundled)) {
189
+ cachedRipgrepExecutable = { command: bundled, source: 'bundled' }
190
+ return cachedRipgrepExecutable
191
+ }
192
+
193
+ if (await verifyRipgrepExecutable('rg')) {
194
+ cachedRipgrepExecutable = { command: 'rg', source: 'system' }
195
+ return cachedRipgrepExecutable
196
+ }
197
+
198
+ cachedRipgrepExecutable = null
199
+ return cachedRipgrepExecutable
200
+ }
201
+
202
+ function buildRipgrepArgs(options, context) {
203
+ const args = [
204
+ '--line-number',
205
+ '--color=never',
206
+ '--max-filesize',
207
+ RIPGREP_MAX_FILESIZE,
208
+ ]
209
+
210
+ if (options.filesWithMatches) {
211
+ args.push('--files-with-matches')
212
+ } else {
213
+ args.push('--json')
214
+ }
215
+ if (!options.regex) args.push('--fixed-strings')
216
+ if (!options.caseSensitive) args.push('--ignore-case')
217
+ if (!options.respectGitIgnore) args.push('--hidden', '--no-ignore')
218
+ if (options.context > 0) args.push('-C', String(options.context))
219
+ if (options.beforeContext > 0) args.push('-B', String(options.beforeContext))
220
+ if (options.afterContext > 0) args.push('-A', String(options.afterContext))
221
+
222
+ for (const pattern of options.glob) args.push('--glob', pattern)
223
+ for (const pattern of DEFAULT_EXCLUDE_GLOBS) args.push('--glob', pattern)
224
+ for (const pattern of SENSITIVE_EXCLUDE_GLOBS) args.push('--glob', pattern)
225
+
226
+ args.push('--', options.query, toWorkspaceRelative(options.root, context) || '.')
227
+ return args
228
+ }
229
+
230
+ function cleanRipgrepLine(value) {
231
+ return String(value || '').replace(/[\r\n]+$/, '')
232
+ }
233
+
234
+ function ripgrepRelativePath(value) {
235
+ return String(value || '').replace(/\\/g, '/')
236
+ }
237
+
238
+ function formatRipgrepJsonEvent(event) {
239
+ if (event?.type !== 'match' && event?.type !== 'context') return null
240
+ const data = event.data || {}
241
+ const file = ripgrepRelativePath(data.path?.text)
242
+ const lineNumber = data.line_number
243
+ const line = cleanRipgrepLine(data.lines?.text)
244
+ if (!file || !lineNumber) return null
245
+ const separator = event.type === 'match' ? ':' : '-'
246
+ return `${file}:${lineNumber}${separator} ${line}`
247
+ }
248
+
249
+ function fallbackDetails(extra = {}) {
250
+ return Object.fromEntries(Object.entries(extra).filter(([, value]) => value !== undefined && value !== null && value !== ''))
251
+ }
252
+
253
+ async function grepFilesWithRipgrep(executable, options, context, runtime = {}) {
254
+ if (options.regex && !isRegexLikelyRipgrepCompatible(options.query)) {
255
+ throw new Error('regex uses JavaScript-only features that ripgrep does not support')
256
+ }
257
+
258
+ const cwd = getToolWorkspaceRoot(context)
259
+ const args = buildRipgrepArgs(options, context)
260
+ const matches = []
261
+ let stderr = ''
262
+ let buffer = ''
263
+ let killedForLimit = false
264
+ let settled = false
265
+
266
+ await new Promise((resolve, reject) => {
267
+ if (runtime.signal?.aborted) {
268
+ reject(new Error('Search aborted'))
269
+ return
270
+ }
271
+
272
+ const child = spawn(executable.command, args, {
273
+ cwd,
274
+ shell: false,
275
+ stdio: ['ignore', 'pipe', 'pipe'],
276
+ windowsHide: true,
277
+ })
278
+
279
+ const cleanup = () => {
280
+ clearTimeout(timer)
281
+ runtime.signal?.removeEventListener?.('abort', onAbort)
282
+ }
283
+ const finish = (error) => {
284
+ if (settled) return
285
+ settled = true
286
+ cleanup()
287
+ if (error) reject(error)
288
+ else resolve()
289
+ }
290
+ const stopForLimit = () => {
291
+ if (killedForLimit) return
292
+ killedForLimit = true
293
+ killProcessTree(child, 'SIGTERM')
294
+ }
295
+ const processLine = (line) => {
296
+ if (!line || matches.length >= options.limit) return
297
+ if (options.filesWithMatches) {
298
+ matches.push(ripgrepRelativePath(line))
299
+ } else {
300
+ try {
301
+ const formatted = formatRipgrepJsonEvent(JSON.parse(line))
302
+ if (formatted) matches.push(formatted)
303
+ } catch {
304
+ // Ignore malformed partial output and let process exit handling decide fallback.
305
+ }
306
+ }
307
+ if (matches.length >= options.limit) stopForLimit()
308
+ }
309
+ const flushLines = (chunk) => {
310
+ buffer += chunk.toString()
311
+ const lines = buffer.split(/\r?\n/)
312
+ buffer = lines.pop() || ''
313
+ for (const line of lines) processLine(line)
314
+ }
315
+ function onAbort() {
316
+ killProcessTree(child, 'SIGTERM')
317
+ finish(new Error('Search aborted'))
318
+ }
319
+
320
+ const timer = setTimeout(() => {
321
+ killProcessTree(child, 'SIGTERM')
322
+ finish(new Error('ripgrep search timed out'))
323
+ }, RIPGREP_TIMEOUT_MS)
324
+
325
+ runtime.signal?.addEventListener?.('abort', onAbort, { once: true })
326
+ child.stdout.on('data', flushLines)
327
+ child.stderr.on('data', (chunk) => {
328
+ stderr = truncateText(stderr + chunk.toString(), 2000)
329
+ })
330
+ child.once('error', finish)
331
+ child.once('close', (code) => {
332
+ if (buffer) processLine(buffer)
333
+ if (killedForLimit || code === 0 || code === 1) {
334
+ finish()
335
+ } else {
336
+ finish(new Error(stderr.trim() || `ripgrep exited with code ${code}`))
337
+ }
338
+ })
339
+ })
340
+
341
+ return {
342
+ content: matches.length ? truncateText(matches.slice(0, options.limit).join('\n')) : 'No matches found.',
343
+ details: {
344
+ path: toWorkspaceRelative(options.root, context),
345
+ project: context?.project,
346
+ query: options.query,
347
+ count: matches.length,
348
+ limit: options.limit,
349
+ backend: 'ripgrep',
350
+ ripgrepSource: executable.source,
351
+ },
352
+ }
353
+ }
354
+
355
+ async function grepFilesWithNode(options, context, extraDetails = {}) {
356
+ const flags = options.caseSensitive ? 'g' : 'gi'
357
+ const matcher = options.regex
358
+ ? new RegExp(options.query, flags)
359
+ : new RegExp(escapeRegExp(options.query), flags)
360
+
361
+ const files = await walkFiles(options.root, [], context)
362
+ const matches = []
363
+
364
+ // Stat and filter files in parallel, then grep in parallel batches.
365
+ const candidateResults = await poolMap(files, async (file) => {
366
+ try {
367
+ const stat = await fs.stat(file)
368
+ if (stat.size > 1024 * 1024) return { file, skip: true }
369
+ return { file, skip: false }
370
+ } catch {
371
+ return { file, skip: true }
372
+ }
373
+ })
374
+
375
+ const candidates = candidateResults.filter((r) => !r.skip).map((r) => r.file)
376
+
377
+ // Grep with bounded concurrency — short-circuit when limit reached.
378
+ let matchCount = 0
379
+ const filesWithMatches = new Set()
380
+ for (let batchStart = 0; batchStart < candidates.length && matchCount < options.limit; batchStart += 20) {
381
+ const batch = candidates.slice(batchStart, batchStart + 20)
382
+ const batchMatches = await Promise.all(
383
+ batch.map(async (file) => {
384
+ if (matchCount >= options.limit) return []
385
+ try {
386
+ const text = await fs.readFile(file, 'utf8')
387
+ const lines = splitLines(text)
388
+ const fileMatches = []
389
+ for (let index = 0; index < lines.length && (matchCount + fileMatches.length) < options.limit; index++) {
390
+ matcher.lastIndex = 0
391
+ if (matcher.test(lines[index])) {
392
+ const relative = toWorkspaceRelative(file, context)
393
+ if (options.filesWithMatches) {
394
+ if (!filesWithMatches.has(relative)) {
395
+ filesWithMatches.add(relative)
396
+ fileMatches.push(relative)
397
+ }
398
+ } else {
399
+ fileMatches.push(`${relative}:${index + 1}: ${lines[index]}`)
400
+ }
401
+ }
402
+ }
403
+ return fileMatches
404
+ } catch {
405
+ return []
406
+ }
407
+ }),
408
+ )
409
+ for (const fm of batchMatches) {
410
+ if (matchCount >= options.limit) break
411
+ for (const m of fm) {
412
+ if (matchCount >= options.limit) break
413
+ matches.push(m)
414
+ matchCount++
415
+ }
416
+ }
417
+ }
418
+
419
+ return {
420
+ content: matches.length ? truncateText(matches.join('\n')) : 'No matches found.',
421
+ details: {
422
+ path: toWorkspaceRelative(options.root, context),
423
+ project: context?.project,
424
+ query: options.query,
425
+ count: matches.length,
426
+ limit: options.limit,
427
+ backend: 'node',
428
+ ...fallbackDetails(extraDetails),
429
+ },
430
+ }
431
+ }
432
+
433
+ export async function toolGrepFiles(params, context, runtime = {}) {
434
+ const options = normalizeGrepParams(params, context)
435
+ await assertSafeWorkspacePath(options.root, context)
436
+
437
+ const executable = await resolveRipgrepExecutable()
438
+ if (executable) {
439
+ try {
440
+ return await grepFilesWithRipgrep(executable, options, context, runtime)
441
+ } catch (error) {
442
+ if (runtime.signal?.aborted) throw error
443
+ return grepFilesWithNode(options, context, {
444
+ fallbackFrom: 'ripgrep',
445
+ fallbackReason: error?.message || 'ripgrep unavailable',
446
+ })
447
+ }
448
+ }
449
+
450
+ return grepFilesWithNode(options, context, { fallbackReason: 'ripgrep unavailable' })
451
+ }
452
+
453
+ // --- write_file ---
454
+ export async function toolWriteFile(params, context) {
455
+ const file = resolveWorkspacePath(params?.path, context)
456
+ await assertSafeWorkspacePath(file, context, { forWrite: true })
457
+
458
+ const content = String(params?.content ?? '')
459
+ const relativePath = toWorkspaceRelative(file, context)
460
+ let oldText = ''
461
+ let existed = true
462
+ try {
463
+ oldText = await fs.readFile(file, 'utf8')
464
+ } catch (error) {
465
+ if (error?.code !== 'ENOENT') throw error
466
+ existed = false
467
+ }
468
+ const diff = createTextDiff(oldText, content, relativePath, { oldExists: existed })
469
+
470
+ await fs.mkdir(path.dirname(file), { recursive: true })
471
+ await fs.writeFile(file, content, 'utf8')
472
+
473
+ return {
474
+ content: `${existed ? 'Wrote' : 'Created'} ${relativePath} (+${diff.addedLines} -${diff.removedLines})`,
475
+ details: { path: relativePath, project: context?.project, bytes: Buffer.byteLength(content, 'utf8'), created: !existed, diff },
476
+ }
477
+ }
478
+
479
479
  // --- edit_file ---
480
480
  function countOccurrences(text, needle) {
481
481
  if (!needle) return 0
@@ -488,17 +488,35 @@ function countOccurrences(text, needle) {
488
488
  return count
489
489
  }
490
490
 
491
+ function detectLineEnding(text) {
492
+ return text.includes('\r\n') ? '\r\n' : '\n'
493
+ }
494
+
495
+ function normalizeLineEndings(text) {
496
+ return text.replaceAll('\r\n', '\n').replaceAll('\r', '\n')
497
+ }
498
+
499
+ function convertToLineEnding(text, ending) {
500
+ const normalized = normalizeLineEndings(text)
501
+ return ending === '\r\n' ? normalized.replaceAll('\n', '\r\n') : normalized
502
+ }
503
+
491
504
  export async function toolEditFile(params, context) {
492
505
  const file = resolveWorkspacePath(params?.path, context)
493
506
  await assertSafeWorkspacePath(file, context)
494
507
 
495
- const oldText = String(params?.oldText ?? '')
496
- const newText = String(params?.newText ?? '')
508
+ const rawOldText = String(params?.oldText ?? '')
509
+ const rawNewText = String(params?.newText ?? '')
497
510
  const text = await fs.readFile(file, 'utf8')
511
+ const lineEnding = detectLineEnding(text)
512
+ const oldText = convertToLineEnding(rawOldText, lineEnding)
513
+ const newText = convertToLineEnding(rawNewText, lineEnding)
498
514
  const count = countOccurrences(text, oldText)
499
515
 
500
516
  if (count !== 1) {
501
- const error = new Error(`oldText must match exactly once; found ${count} matches`)
517
+ const rawCount = oldText === rawOldText ? count : countOccurrences(text, rawOldText)
518
+ const suffix = rawCount !== count ? ` after normalizing line endings; raw match count was ${rawCount}` : ''
519
+ const error = new Error(`oldText must match exactly once; found ${count} matches${suffix}`)
502
520
  error.statusCode = 400
503
521
  throw error
504
522
  }
@@ -515,234 +533,251 @@ export async function toolEditFile(params, context) {
515
533
  }
516
534
  }
517
535
 
518
- // --- run_command ---
519
- function activeSkillsForContext(context) {
520
- return mergeSkills(context?.globalSkills, context?.projectSkills)
521
- }
522
-
523
- function activeSkillByName(context, name) {
524
- const skillName = String(name || '')
525
- return activeSkillsForContext(context).find((skill) => skill.name === skillName)
526
- }
527
-
528
- export async function loadSkillToolContext(config = {}) {
529
- const globalSkills = await loadSelectedGlobalSkills(config.globalSkillNames)
530
- const projectSkills = config.workspaceRoot
531
- ? await loadSelectedProjectSkills(config.projectSkillNames, config.workspaceRoot)
532
- : []
533
- return { globalSkills, projectSkills }
534
- }
535
-
536
- // --- activate_skill ---
537
- export async function toolActivateSkill(params, context) {
538
- const skill = activeSkillByName(context, params?.name)
539
- if (!skill) {
540
- const error = new Error(`Unknown or disabled skill: ${params?.name || ''}`)
541
- error.statusCode = 404
542
- throw error
543
- }
544
-
545
- return {
546
- content: truncateText(await formatSkillActivation(skill)),
547
- details: {
548
- skill: skill.name,
549
- source: skill.source,
550
- directory: skill.rootDir,
551
- },
552
- }
553
- }
554
-
555
- // --- read_skill_resource ---
556
- export async function toolReadSkillResource(params, context) {
557
- const skill = activeSkillByName(context, params?.skill)
558
- if (!skill) {
559
- const error = new Error(`Unknown or disabled skill: ${params?.skill || ''}`)
560
- error.statusCode = 404
561
- throw error
562
- }
563
-
564
- const result = await readSkillResource(skill, params?.path, params)
565
- return {
566
- content: truncateText(result.content),
567
- details: result.details,
568
- }
569
- }
570
-
571
- // --- run_command ---
572
- function commandStatus(meta = {}) {
573
- if (meta.running) return 'Status: running'
574
- const flags = [
575
- meta.timedOut ? 'timed out' : null,
576
- meta.aborted ? 'aborted' : null,
577
- ].filter(Boolean)
578
- const suffix = flags.length ? ` (${flags.join(', ')})` : ''
579
- return `Exit code: ${meta.code ?? 'unknown'}${meta.signal ? `, signal: ${meta.signal}` : ''}${suffix}`
580
- }
581
-
582
- function formatCommandOutput(command, stdout, stderr, meta = {}) {
583
- return [
584
- `Command: ${command}`,
585
- commandStatus(meta),
586
- '',
587
- 'STDOUT:',
588
- stdout || '(empty)',
589
- '',
590
- 'STDERR:',
591
- stderr || '(empty)',
592
- ].join('\n')
593
- }
594
-
595
- function killProcessTree(child, signal = 'SIGTERM') {
596
- if (!child?.pid) return
597
-
598
- if (process.platform === 'win32') {
599
- const killer = spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], {
600
- stdio: 'ignore',
601
- windowsHide: true,
602
- })
603
- killer.on('error', () => {
604
- try { child.kill(signal) } catch { /* ignore */ }
605
- })
606
- return
607
- }
608
-
609
- try {
610
- process.kill(-child.pid, signal)
611
- } catch {
612
- try { child.kill(signal) } catch { /* ignore */ }
613
- }
614
- }
615
-
616
- export async function toolRunCommand(params, context, runtime = {}) {
617
- const command = String(params?.command || '')
618
- if (!command.trim()) {
619
- const error = new Error('command is required')
620
- error.statusCode = 400
621
- throw error
622
- }
623
-
624
- const timeoutMs = Math.min(10 * 60, Math.max(1, Number(params?.timeoutSeconds || 60))) * 1000
625
- const cwd = getToolWorkspaceRoot(context)
626
-
627
- if (runtime.signal?.aborted) {
628
- const content = formatCommandOutput(command, '', 'Command aborted before start.', { aborted: true })
629
- return { content: truncateText(content), details: { command, project: context?.project, cwd, aborted: true } }
630
- }
631
-
632
- return new Promise((resolve) => {
633
- const child = spawn(command, {
634
- cwd,
635
- shell: true,
636
- stdio: ['ignore', 'pipe', 'pipe'],
637
- windowsHide: true,
638
- detached: process.platform !== 'win32',
639
- })
640
-
641
- let stdout = ''
642
- let stderr = ''
643
- let timedOut = false
644
- let aborted = false
645
- let settled = false
646
- let updateTimer = null
647
- let updatePending = false
648
- let forceKillTimer = null
649
-
650
- const cleanup = () => {
651
- clearTimeout(timer)
652
- if (forceKillTimer) clearTimeout(forceKillTimer)
653
- if (updateTimer) clearTimeout(updateTimer)
654
- runtime.signal?.removeEventListener?.('abort', onAbort)
655
- }
656
-
657
- const finish = ({ code = null, signal = null, error = null } = {}) => {
658
- if (settled) return
659
- flushUpdate()
660
- settled = true
661
- cleanup()
662
- if (error) {
663
- resolve({
664
- isError: true,
665
- content: truncateText(`Error running command: ${error.message}`),
666
- details: { command, project: context?.project, cwd, error: error.message, aborted, timedOut },
667
- })
668
- return
669
- }
670
- const content = formatCommandOutput(command, stdout, stderr, { code, signal, timedOut, aborted })
671
- resolve({ content: truncateText(content), details: { command, project: context?.project, cwd, code, signal, timedOut, aborted } })
672
- }
673
-
674
- const stopChild = (reason) => {
675
- if (reason === 'timeout') timedOut = true
676
- if (reason === 'abort') aborted = true
677
- killProcessTree(child, 'SIGTERM')
678
- forceKillTimer = setTimeout(() => {
679
- killProcessTree(child, 'SIGKILL')
680
- }, 1500)
681
- }
682
-
683
- function onAbort() {
684
- stopChild('abort')
685
- finish({ signal: 'SIGTERM' })
686
- }
687
-
688
- const emitUpdate = () => {
689
- updateTimer = null
690
- if (settled || !updatePending) return
691
- updatePending = false
692
- runtime.onUpdate?.({
693
- content: [{ type: 'text', text: truncateText(formatCommandOutput(command, stdout, stderr, { running: true })) }],
694
- details: { command, project: context?.project, cwd, running: true, stdout, stderr },
695
- })
696
- }
697
- const flushUpdate = () => {
698
- if (updateTimer) {
699
- clearTimeout(updateTimer)
700
- updateTimer = null
701
- }
702
- if (!updatePending) return
703
- updatePending = false
704
- runtime.onUpdate?.({
705
- content: [{ type: 'text', text: truncateText(formatCommandOutput(command, stdout, stderr, { running: true })) }],
706
- details: { command, project: context?.project, cwd, running: true, stdout, stderr },
707
- })
708
- }
709
- const scheduleUpdate = () => {
710
- if (settled) return
711
- updatePending = true
712
- if (!updateTimer) updateTimer = setTimeout(emitUpdate, 150)
713
- }
714
- const timer = setTimeout(() => {
715
- stopChild('timeout')
716
- finish({ signal: 'SIGTERM' })
717
- }, timeoutMs)
718
-
719
- runtime.signal?.addEventListener?.('abort', onAbort, { once: true })
720
-
721
- child.stdout.on('data', (chunk) => {
722
- if (settled) return
723
- stdout = truncateText(stdout + chunk.toString())
724
- scheduleUpdate()
725
- })
726
- child.stderr.on('data', (chunk) => {
727
- if (settled) return
728
- stderr = truncateText(stderr + chunk.toString())
729
- scheduleUpdate()
730
- })
731
- child.on('close', (code, signal) => {
732
- finish({ code, signal })
733
- })
734
- child.on('error', (err) => {
735
- finish({ error: err })
736
- })
737
- })
738
- }
739
-
740
- export const toolHandlers = {
741
- read_file: toolReadFile,
742
- grep_files: toolGrepFiles,
743
- write_file: toolWriteFile,
744
- edit_file: toolEditFile,
745
- run_command: toolRunCommand,
746
- activate_skill: toolActivateSkill,
747
- read_skill_resource: toolReadSkillResource,
748
- }
536
+ // --- run_command ---
537
+ function activeSkillsForContext(context) {
538
+ return mergeSkills(context?.globalSkills, context?.projectSkills)
539
+ }
540
+
541
+ function activeSkillByName(context, name) {
542
+ const skillName = String(name || '')
543
+ return activeSkillsForContext(context).find((skill) => skill.name === skillName)
544
+ }
545
+
546
+ export async function loadSkillToolContext(config = {}) {
547
+ const globalSkills = await loadSelectedGlobalSkills(config.globalSkillNames)
548
+ const projectSkills = config.workspaceRoot
549
+ ? await loadSelectedProjectSkills(config.projectSkillNames, config.workspaceRoot)
550
+ : []
551
+ return { globalSkills, projectSkills }
552
+ }
553
+
554
+ // --- activate_skill ---
555
+ export async function toolActivateSkill(params, context) {
556
+ const skill = activeSkillByName(context, params?.name)
557
+ if (!skill) {
558
+ const error = new Error(`Unknown or disabled skill: ${params?.name || ''}`)
559
+ error.statusCode = 404
560
+ throw error
561
+ }
562
+
563
+ return {
564
+ content: truncateText(await formatSkillActivation(skill)),
565
+ details: {
566
+ skill: skill.name,
567
+ source: skill.source,
568
+ directory: skill.rootDir,
569
+ },
570
+ }
571
+ }
572
+
573
+ // --- read_skill_resource ---
574
+ export async function toolReadSkillResource(params, context) {
575
+ const skill = activeSkillByName(context, params?.skill)
576
+ if (!skill) {
577
+ const error = new Error(`Unknown or disabled skill: ${params?.skill || ''}`)
578
+ error.statusCode = 404
579
+ throw error
580
+ }
581
+
582
+ const result = await readSkillResource(skill, params?.path, params)
583
+ return {
584
+ content: truncateText(result.content),
585
+ details: result.details,
586
+ }
587
+ }
588
+
589
+ // --- run_command ---
590
+ function commandStatus(meta = {}) {
591
+ if (meta.running) return 'Status: running'
592
+ const flags = [
593
+ meta.timedOut ? 'timed out' : null,
594
+ meta.aborted ? 'aborted' : null,
595
+ ].filter(Boolean)
596
+ const suffix = flags.length ? ` (${flags.join(', ')})` : ''
597
+ return `Exit code: ${meta.code ?? 'unknown'}${meta.signal ? `, signal: ${meta.signal}` : ''}${suffix}`
598
+ }
599
+
600
+ function formatCommandOutput(command, stdout, stderr, meta = {}) {
601
+ return [
602
+ `Command: ${command}`,
603
+ commandStatus(meta),
604
+ '',
605
+ 'STDOUT:',
606
+ stdout || '(empty)',
607
+ '',
608
+ 'STDERR:',
609
+ stderr || '(empty)',
610
+ ].join('\n')
611
+ }
612
+
613
+ function killProcessTree(child, signal = 'SIGTERM') {
614
+ if (!child?.pid) return
615
+
616
+ if (process.platform === 'win32') {
617
+ const killer = spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], {
618
+ stdio: 'ignore',
619
+ windowsHide: true,
620
+ })
621
+ killer.on('error', () => {
622
+ try { child.kill(signal) } catch { /* ignore */ }
623
+ })
624
+ return
625
+ }
626
+
627
+ try {
628
+ process.kill(-child.pid, signal)
629
+ } catch {
630
+ try { child.kill(signal) } catch { /* ignore */ }
631
+ }
632
+ }
633
+
634
+ const runningCommands = new Map()
635
+
636
+ export function abortRunningCommand(toolCallId) {
637
+ if (!toolCallId) return false
638
+ const stop = runningCommands.get(toolCallId)
639
+ if (!stop) return false
640
+ stop('abort')
641
+ return true
642
+ }
643
+
644
+ const RUN_COMMAND_TIMEOUT_MS = 30 * 60 * 1000
645
+
646
+ export async function toolRunCommand(params, context, runtime = {}) {
647
+ const command = String(params?.command || '')
648
+ if (!command.trim()) {
649
+ const error = new Error('command is required')
650
+ error.statusCode = 400
651
+ throw error
652
+ }
653
+
654
+ const timeoutMs = RUN_COMMAND_TIMEOUT_MS
655
+ const cwd = getToolWorkspaceRoot(context)
656
+
657
+ if (runtime.signal?.aborted) {
658
+ const content = formatCommandOutput(command, '', 'Command aborted before start.', { aborted: true })
659
+ return { content: truncateText(content), details: { command, project: context?.project, cwd, aborted: true } }
660
+ }
661
+
662
+ return new Promise((resolve) => {
663
+ const child = spawn(command, {
664
+ cwd,
665
+ shell: true,
666
+ stdio: ['ignore', 'pipe', 'pipe'],
667
+ windowsHide: true,
668
+ detached: process.platform !== 'win32',
669
+ })
670
+
671
+ let stdout = ''
672
+ let stderr = ''
673
+ let timedOut = false
674
+ let aborted = false
675
+ let settled = false
676
+ let updateTimer = null
677
+ let updatePending = false
678
+ let forceKillTimer = null
679
+
680
+ const cleanup = () => {
681
+ clearTimeout(timer)
682
+ if (forceKillTimer) clearTimeout(forceKillTimer)
683
+ if (updateTimer) clearTimeout(updateTimer)
684
+ if (runtime.toolCallId) runningCommands.delete(runtime.toolCallId)
685
+ runtime.signal?.removeEventListener?.('abort', onAbort)
686
+ }
687
+
688
+ const finish = ({ code = null, signal = null, error = null } = {}) => {
689
+ if (settled) return
690
+ flushUpdate()
691
+ settled = true
692
+ cleanup()
693
+ if (error) {
694
+ resolve({
695
+ isError: true,
696
+ content: truncateText(`Error running command: ${error.message}`),
697
+ details: { command, project: context?.project, cwd, error: error.message, aborted, timedOut },
698
+ })
699
+ return
700
+ }
701
+ const content = formatCommandOutput(command, stdout, stderr, { code, signal, timedOut, aborted })
702
+ resolve({ content: truncateText(content), details: { command, project: context?.project, cwd, code, signal, timedOut, aborted } })
703
+ }
704
+
705
+ const stopChild = (reason) => {
706
+ if (reason === 'timeout') timedOut = true
707
+ if (reason === 'abort') aborted = true
708
+ killProcessTree(child, 'SIGTERM')
709
+ forceKillTimer = setTimeout(() => {
710
+ killProcessTree(child, 'SIGKILL')
711
+ }, 1500)
712
+ }
713
+
714
+ if (runtime.toolCallId) runningCommands.set(runtime.toolCallId, stopChild)
715
+
716
+ function onAbort() {
717
+ stopChild('abort')
718
+ finish({ signal: 'SIGTERM' })
719
+ }
720
+
721
+ const runningDetails = () => ({ command, project: context?.project, cwd, running: true, stdout, stderr, toolCallId: runtime.toolCallId })
722
+
723
+ const emitUpdate = () => {
724
+ updateTimer = null
725
+ if (settled || !updatePending) return
726
+ updatePending = false
727
+ runtime.onUpdate?.({
728
+ content: [{ type: 'text', text: truncateText(formatCommandOutput(command, stdout, stderr, { running: true })) }],
729
+ details: runningDetails(),
730
+ })
731
+ }
732
+ const flushUpdate = () => {
733
+ if (updateTimer) {
734
+ clearTimeout(updateTimer)
735
+ updateTimer = null
736
+ }
737
+ if (!updatePending) return
738
+ updatePending = false
739
+ runtime.onUpdate?.({
740
+ content: [{ type: 'text', text: truncateText(formatCommandOutput(command, stdout, stderr, { running: true })) }],
741
+ details: runningDetails(),
742
+ })
743
+ }
744
+ const scheduleUpdate = () => {
745
+ if (settled) return
746
+ updatePending = true
747
+ if (!updateTimer) updateTimer = setTimeout(emitUpdate, 150)
748
+ }
749
+ const timer = setTimeout(() => {
750
+ stopChild('timeout')
751
+ finish({ signal: 'SIGTERM' })
752
+ }, timeoutMs)
753
+
754
+ runtime.signal?.addEventListener?.('abort', onAbort, { once: true })
755
+
756
+ child.stdout.on('data', (chunk) => {
757
+ if (settled) return
758
+ stdout = truncateText(stdout + chunk.toString())
759
+ scheduleUpdate()
760
+ })
761
+ child.stderr.on('data', (chunk) => {
762
+ if (settled) return
763
+ stderr = truncateText(stderr + chunk.toString())
764
+ scheduleUpdate()
765
+ })
766
+ child.on('close', (code, signal) => {
767
+ finish({ code, signal })
768
+ })
769
+ child.on('error', (err) => {
770
+ finish({ error: err })
771
+ })
772
+ })
773
+ }
774
+
775
+ export const toolHandlers = {
776
+ read_file: toolReadFile,
777
+ grep_files: toolGrepFiles,
778
+ write_file: toolWriteFile,
779
+ edit_file: toolEditFile,
780
+ run_command: toolRunCommand,
781
+ activate_skill: toolActivateSkill,
782
+ read_skill_resource: toolReadSkillResource,
783
+ }