@mastra/core 1.31.0-alpha.3 → 1.31.0-alpha.5

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 (144) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/agent/durable/index.cjs +22 -22
  3. package/dist/agent/durable/index.js +4 -4
  4. package/dist/agent/index.cjs +9 -9
  5. package/dist/agent/index.js +1 -1
  6. package/dist/browser/index.cjs +5 -5
  7. package/dist/browser/index.js +2 -2
  8. package/dist/channels/index.cjs +4 -4
  9. package/dist/channels/index.js +1 -1
  10. package/dist/{chunk-LEXSJDD5.cjs → chunk-3CBQ4FAZ.cjs} +215 -18
  11. package/dist/chunk-3CBQ4FAZ.cjs.map +1 -0
  12. package/dist/{chunk-EMLA7DXA.cjs → chunk-4RFGOX6E.cjs} +9 -9
  13. package/dist/{chunk-EMLA7DXA.cjs.map → chunk-4RFGOX6E.cjs.map} +1 -1
  14. package/dist/{chunk-P5XCYDW7.js → chunk-52IAV52S.js} +3 -3
  15. package/dist/{chunk-P5XCYDW7.js.map → chunk-52IAV52S.js.map} +1 -1
  16. package/dist/{chunk-OQ6ORZLY.cjs → chunk-5ANWVE3P.cjs} +216 -35
  17. package/dist/chunk-5ANWVE3P.cjs.map +1 -0
  18. package/dist/{chunk-HBCHXSQT.js → chunk-5AZE6Y7E.js} +6 -6
  19. package/dist/{chunk-HBCHXSQT.js.map → chunk-5AZE6Y7E.js.map} +1 -1
  20. package/dist/{chunk-JXWLABNY.cjs → chunk-ALZAXC3J.cjs} +19 -19
  21. package/dist/{chunk-JXWLABNY.cjs.map → chunk-ALZAXC3J.cjs.map} +1 -1
  22. package/dist/{chunk-IKXZNMTB.cjs → chunk-ATJ2RA5L.cjs} +5 -5
  23. package/dist/{chunk-IKXZNMTB.cjs.map → chunk-ATJ2RA5L.cjs.map} +1 -1
  24. package/dist/{chunk-BEDXCJ3D.js → chunk-D6WNIFWU.js} +4 -4
  25. package/dist/{chunk-BEDXCJ3D.js.map → chunk-D6WNIFWU.js.map} +1 -1
  26. package/dist/{chunk-C6KGFSLD.js → chunk-D7ORPD2O.js} +3 -3
  27. package/dist/{chunk-C6KGFSLD.js.map → chunk-D7ORPD2O.js.map} +1 -1
  28. package/dist/{chunk-WYDQEW3F.cjs → chunk-DZBT3XFM.cjs} +7 -7
  29. package/dist/{chunk-WYDQEW3F.cjs.map → chunk-DZBT3XFM.cjs.map} +1 -1
  30. package/dist/{chunk-3MJ2YZKW.js → chunk-EZANPKCM.js} +3 -3
  31. package/dist/{chunk-3MJ2YZKW.js.map → chunk-EZANPKCM.js.map} +1 -1
  32. package/dist/{chunk-5AFU6MDJ.js → chunk-F4PWGVHW.js} +212 -32
  33. package/dist/chunk-F4PWGVHW.js.map +1 -0
  34. package/dist/{chunk-N3MFQ5IC.cjs → chunk-GYK5WRWE.cjs} +3 -3
  35. package/dist/{chunk-N3MFQ5IC.cjs.map → chunk-GYK5WRWE.cjs.map} +1 -1
  36. package/dist/{chunk-FBSDOK7N.cjs → chunk-HDZV5R52.cjs} +224 -224
  37. package/dist/{chunk-FBSDOK7N.cjs.map → chunk-HDZV5R52.cjs.map} +1 -1
  38. package/dist/{chunk-ORGS37CO.js → chunk-IB3UPSY2.js} +9 -9
  39. package/dist/{chunk-ORGS37CO.js.map → chunk-IB3UPSY2.js.map} +1 -1
  40. package/dist/{chunk-ZTVCTOC4.js → chunk-II2JGWWS.js} +3 -3
  41. package/dist/{chunk-ZTVCTOC4.js.map → chunk-II2JGWWS.js.map} +1 -1
  42. package/dist/{chunk-QYT6OF4I.cjs → chunk-O4NY7VXW.cjs} +17 -17
  43. package/dist/{chunk-QYT6OF4I.cjs.map → chunk-O4NY7VXW.cjs.map} +1 -1
  44. package/dist/{chunk-BICHLSKY.cjs → chunk-PLCMSZZR.cjs} +20 -20
  45. package/dist/{chunk-BICHLSKY.cjs.map → chunk-PLCMSZZR.cjs.map} +1 -1
  46. package/dist/{chunk-U7SCBEKL.js → chunk-PW5TFXZI.js} +3 -3
  47. package/dist/{chunk-U7SCBEKL.js.map → chunk-PW5TFXZI.js.map} +1 -1
  48. package/dist/{chunk-6YTX2D43.cjs → chunk-QB6SFTJF.cjs} +57 -57
  49. package/dist/{chunk-6YTX2D43.cjs.map → chunk-QB6SFTJF.cjs.map} +1 -1
  50. package/dist/{chunk-7CDGKPLZ.cjs → chunk-U7C3WU7B.cjs} +389 -389
  51. package/dist/{chunk-7CDGKPLZ.cjs.map → chunk-U7C3WU7B.cjs.map} +1 -1
  52. package/dist/{chunk-ENFUF5ZE.js → chunk-URCXU22J.js} +8 -8
  53. package/dist/{chunk-ENFUF5ZE.js.map → chunk-URCXU22J.js.map} +1 -1
  54. package/dist/{chunk-SE2NIAOC.js → chunk-X735G7KE.js} +4 -4
  55. package/dist/{chunk-SE2NIAOC.js.map → chunk-X735G7KE.js.map} +1 -1
  56. package/dist/{chunk-6BMV3INL.js → chunk-ZKHNSFUH.js} +213 -16
  57. package/dist/chunk-ZKHNSFUH.js.map +1 -0
  58. package/dist/datasets/experiment/index.d.ts.map +1 -1
  59. package/dist/datasets/experiment/scorer.d.ts +25 -0
  60. package/dist/datasets/experiment/scorer.d.ts.map +1 -1
  61. package/dist/datasets/experiment/types.d.ts +18 -2
  62. package/dist/datasets/experiment/types.d.ts.map +1 -1
  63. package/dist/datasets/index.cjs +11 -11
  64. package/dist/datasets/index.js +1 -1
  65. package/dist/docs/SKILL.md +1 -1
  66. package/dist/docs/assets/SOURCE_MAP.json +140 -140
  67. package/dist/docs/references/docs-agents-adding-voice.md +14 -13
  68. package/dist/docs/references/docs-voice-overview.md +66 -0
  69. package/dist/docs/references/docs-voice-speech-to-speech.md +45 -1
  70. package/dist/docs/references/docs-workspace-search.md +39 -0
  71. package/dist/docs/references/reference-datasets-startExperiment.md +28 -2
  72. package/dist/docs/references/reference-workspace-workspace-class.md +1 -1
  73. package/dist/docs/references/reference.md +2 -0
  74. package/dist/evals/index.cjs +6 -6
  75. package/dist/evals/index.js +2 -2
  76. package/dist/evals/scoreTraces/index.cjs +3 -3
  77. package/dist/evals/scoreTraces/index.js +1 -1
  78. package/dist/harness/index.cjs +11 -11
  79. package/dist/harness/index.js +6 -6
  80. package/dist/index.cjs +2 -2
  81. package/dist/index.js +1 -1
  82. package/dist/llm/index.cjs +20 -20
  83. package/dist/llm/index.js +5 -5
  84. package/dist/loop/index.cjs +14 -14
  85. package/dist/loop/index.js +1 -1
  86. package/dist/mastra/index.cjs +2 -2
  87. package/dist/mastra/index.js +1 -1
  88. package/dist/mastra-OCULSBP5.js +3 -0
  89. package/dist/{mastra-ZMGSDAUN.js.map → mastra-OCULSBP5.js.map} +1 -1
  90. package/dist/mastra-VMPA5UVF.cjs +12 -0
  91. package/dist/{mastra-P7T3UKV5.cjs.map → mastra-VMPA5UVF.cjs.map} +1 -1
  92. package/dist/memory/index.cjs +19 -19
  93. package/dist/memory/index.js +1 -1
  94. package/dist/models-dev-CCJECLMT.cjs +12 -0
  95. package/dist/{models-dev-GJQCRHM3.cjs.map → models-dev-CCJECLMT.cjs.map} +1 -1
  96. package/dist/models-dev-F6OUM7S7.js +3 -0
  97. package/dist/{models-dev-DL6NWDNP.js.map → models-dev-F6OUM7S7.js.map} +1 -1
  98. package/dist/netlify-2YTGXPQW.js +3 -0
  99. package/dist/{netlify-3CKP3DSR.js.map → netlify-2YTGXPQW.js.map} +1 -1
  100. package/dist/netlify-4NR3G6EJ.cjs +12 -0
  101. package/dist/{netlify-O34AZQ5R.cjs.map → netlify-4NR3G6EJ.cjs.map} +1 -1
  102. package/dist/processor-provider/index.cjs +10 -10
  103. package/dist/processor-provider/index.js +1 -1
  104. package/dist/processors/index.cjs +49 -49
  105. package/dist/processors/index.js +1 -1
  106. package/dist/provider-registry-HZHKE2KN.cjs +44 -0
  107. package/dist/{provider-registry-DI3SQCLD.cjs.map → provider-registry-HZHKE2KN.cjs.map} +1 -1
  108. package/dist/provider-registry-QREDL7WJ.js +3 -0
  109. package/dist/{provider-registry-ZTTSZTTB.js.map → provider-registry-QREDL7WJ.js.map} +1 -1
  110. package/dist/relevance/index.cjs +3 -3
  111. package/dist/relevance/index.js +1 -1
  112. package/dist/runner-FOG455RH.js +3 -0
  113. package/dist/{runner-BIOR2SMR.js.map → runner-FOG455RH.js.map} +1 -1
  114. package/dist/runner-PDJYD3PQ.cjs +16 -0
  115. package/dist/{runner-J24LBLPO.cjs.map → runner-PDJYD3PQ.cjs.map} +1 -1
  116. package/dist/stream/index.cjs +11 -11
  117. package/dist/stream/index.js +1 -1
  118. package/dist/tool-loop-agent/index.cjs +4 -4
  119. package/dist/tool-loop-agent/index.js +1 -1
  120. package/dist/workflows/evented/index.cjs +10 -10
  121. package/dist/workflows/evented/index.js +1 -1
  122. package/dist/workflows/index.cjs +24 -24
  123. package/dist/workflows/index.js +1 -1
  124. package/dist/workspace/index.cjs +68 -68
  125. package/dist/workspace/index.js +1 -1
  126. package/dist/workspace/search/search-engine.d.ts +67 -4
  127. package/dist/workspace/search/search-engine.d.ts.map +1 -1
  128. package/dist/workspace/workspace.d.ts +14 -0
  129. package/dist/workspace/workspace.d.ts.map +1 -1
  130. package/package.json +5 -5
  131. package/dist/chunk-5AFU6MDJ.js.map +0 -1
  132. package/dist/chunk-6BMV3INL.js.map +0 -1
  133. package/dist/chunk-LEXSJDD5.cjs.map +0 -1
  134. package/dist/chunk-OQ6ORZLY.cjs.map +0 -1
  135. package/dist/mastra-P7T3UKV5.cjs +0 -12
  136. package/dist/mastra-ZMGSDAUN.js +0 -3
  137. package/dist/models-dev-DL6NWDNP.js +0 -3
  138. package/dist/models-dev-GJQCRHM3.cjs +0 -12
  139. package/dist/netlify-3CKP3DSR.js +0 -3
  140. package/dist/netlify-O34AZQ5R.cjs +0 -12
  141. package/dist/provider-registry-DI3SQCLD.cjs +0 -44
  142. package/dist/provider-registry-ZTTSZTTB.js +0 -3
  143. package/dist/runner-BIOR2SMR.js +0 -3
  144. package/dist/runner-J24LBLPO.cjs +0 -16
@@ -4,6 +4,7 @@ import { MastraBase } from './chunk-WENZPAHS.js';
4
4
  import { RegisteredLogger } from './chunk-DBBWTK24.js';
5
5
  import * as nodePath from 'path';
6
6
  import nodePath__default, { parse, join, dirname } from 'path';
7
+ import pMap, { pMapSkip } from 'p-map';
7
8
  import posixPath from 'path/posix';
8
9
  import { realpathSync, constants, existsSync } from 'fs';
9
10
  import * as fs2 from 'fs/promises';
@@ -4638,8 +4639,10 @@ var BM25Index = class _BM25Index {
4638
4639
  return idf * (numerator / denominator);
4639
4640
  }
4640
4641
  };
4641
-
4642
- // src/workspace/search/search-engine.ts
4642
+ function isBatchEmbedder(embedder) {
4643
+ return typeof embedder === "function" && embedder.batch === true;
4644
+ }
4645
+ var DEFAULT_INDEX_MANY_CONCURRENCY = 8;
4643
4646
  var DEFAULT_MAX_CHUNK_CHARS = 4e3;
4644
4647
  var DEFAULT_OVERLAP_LINES = 3;
4645
4648
  function splitIntoChunks(text, options = {}) {
@@ -4731,12 +4734,15 @@ var SearchEngine = class {
4731
4734
  }
4732
4735
  }
4733
4736
  /**
4734
- * Index multiple documents
4737
+ * Index multiple documents (up to `concurrency` at a time when async vector work runs).
4738
+ *
4739
+ * @param docs - Documents to index
4740
+ * @param options - `p-map` options; `concurrency` defaults to 8
4735
4741
  */
4736
- async indexMany(docs) {
4737
- for (const doc of docs) {
4738
- await this.index(doc);
4739
- }
4742
+ async indexMany(docs, options) {
4743
+ const stopOnError = options?.stopOnError;
4744
+ const concurrency = options?.concurrency ?? DEFAULT_INDEX_MANY_CONCURRENCY;
4745
+ await pMap(docs, (doc) => this.index(doc), { stopOnError, concurrency });
4740
4746
  }
4741
4747
  /**
4742
4748
  * Remove a document from the index
@@ -4887,12 +4893,63 @@ var SearchEngine = class {
4887
4893
  throw new Error("No search configuration available. Provide bm25 or vector config.");
4888
4894
  }
4889
4895
  /**
4890
- * Index a single document in the vector store
4896
+ * Embed a single text, dispatching to the batch path with a one-element array
4897
+ * when the configured embedder is batch-capable.
4898
+ */
4899
+ async #embedOne(text) {
4900
+ if (!this.#vectorConfig) {
4901
+ throw new Error("Vector configuration is required to embed text.");
4902
+ }
4903
+ const { embedder } = this.#vectorConfig;
4904
+ if (isBatchEmbedder(embedder)) {
4905
+ const [embedding] = await embedder([text]);
4906
+ if (!embedding) {
4907
+ throw new Error("Batch embedder returned no embedding for input text.");
4908
+ }
4909
+ return embedding;
4910
+ }
4911
+ return embedder(text);
4912
+ }
4913
+ /**
4914
+ * Embed many texts. Uses a single batched call (chunked by `maxBatchSize`)
4915
+ * when the embedder is batch-capable; otherwise falls back to parallel
4916
+ * single-text calls.
4917
+ */
4918
+ async #embedAll(texts) {
4919
+ if (!this.#vectorConfig) {
4920
+ throw new Error("Vector configuration is required to embed texts.");
4921
+ }
4922
+ if (texts.length === 0) return [];
4923
+ const { embedder } = this.#vectorConfig;
4924
+ if (isBatchEmbedder(embedder)) {
4925
+ const max = embedder.maxBatchSize;
4926
+ if (max === void 0 || texts.length <= max) {
4927
+ return embedder(texts);
4928
+ }
4929
+ const chunks = [];
4930
+ for (let i = 0; i < texts.length; i += max) {
4931
+ chunks.push(texts.slice(i, i + max));
4932
+ }
4933
+ const results = await pMap(chunks, (chunk) => embedder(chunk), {
4934
+ concurrency: DEFAULT_INDEX_MANY_CONCURRENCY
4935
+ });
4936
+ return results.flat();
4937
+ }
4938
+ return pMap(texts, (text) => embedder(text), {
4939
+ concurrency: DEFAULT_INDEX_MANY_CONCURRENCY
4940
+ });
4941
+ }
4942
+ /**
4943
+ * Index a single document in the vector store.
4944
+ *
4945
+ * Used by the eager (non-lazy) write path. The lazy flush path embeds all
4946
+ * pending docs together via {@link SearchEngine.#flushVectorBatch} for true
4947
+ * batch embedding when supported.
4891
4948
  */
4892
4949
  async #indexVector(doc) {
4893
4950
  if (!this.#vectorConfig) return;
4894
- const { vectorStore, embedder, indexName } = this.#vectorConfig;
4895
- const embedding = await embedder(doc.content);
4951
+ const { vectorStore, indexName } = this.#vectorConfig;
4952
+ const embedding = await this.#embedOne(doc.content);
4896
4953
  if (!this.#vectorIndexReady) {
4897
4954
  try {
4898
4955
  await vectorStore.createIndex({ indexName, dimension: embedding.length });
@@ -4914,16 +4971,80 @@ var SearchEngine = class {
4914
4971
  this.#vectorIndexReady = true;
4915
4972
  }
4916
4973
  /**
4917
- * Ensure vector index is built (for lazy mode)
4974
+ * Embed and upsert a batch of documents in as few provider calls as possible.
4975
+ *
4976
+ * - If the embedder is batch-capable, all texts go through a single embedder
4977
+ * call (chunked by `maxBatchSize`), then a single `upsert` with all vectors.
4978
+ * - Otherwise falls back to per-doc embedding via {@link SearchEngine.#indexVector}.
4979
+ */
4980
+ async #flushVectorBatch(docs) {
4981
+ if (!this.#vectorConfig || docs.length === 0) return;
4982
+ const { vectorStore, embedder, indexName } = this.#vectorConfig;
4983
+ if (!isBatchEmbedder(embedder)) {
4984
+ await pMap(docs, (doc) => this.#indexVector(doc), {
4985
+ concurrency: DEFAULT_INDEX_MANY_CONCURRENCY
4986
+ });
4987
+ return;
4988
+ }
4989
+ const embeddings = await this.#embedAll(docs.map((d) => d.content));
4990
+ if (embeddings.length !== docs.length) {
4991
+ throw new Error(`Batch embedder returned ${embeddings.length} embeddings for ${docs.length} inputs.`);
4992
+ }
4993
+ if (!this.#vectorIndexReady) {
4994
+ const dim = embeddings[0].length;
4995
+ try {
4996
+ await vectorStore.createIndex({ indexName, dimension: dim });
4997
+ } catch {
4998
+ }
4999
+ }
5000
+ await vectorStore.upsert({
5001
+ indexName,
5002
+ vectors: embeddings,
5003
+ metadata: docs.map((doc) => ({
5004
+ id: doc.id,
5005
+ text: doc.content,
5006
+ ...doc.metadata
5007
+ })),
5008
+ ids: docs.map((d) => d.id)
5009
+ });
5010
+ this.#vectorIndexReady = true;
5011
+ }
5012
+ /**
5013
+ * Collapse duplicate document ids so a single deterministic upsert runs per id (last queue entry wins).
5014
+ */
5015
+ #dedupePendingVectorDocsLastWins(docs) {
5016
+ const byId = /* @__PURE__ */ new Map();
5017
+ for (const doc of docs) {
5018
+ byId.set(doc.id, doc);
5019
+ }
5020
+ return [...byId.values()];
5021
+ }
5022
+ /**
5023
+ * Ensure vector index is built (for lazy mode).
5024
+ *
5025
+ * Drains the pending queue into a local batch before awaiting upserts so concurrent `index()` calls
5026
+ * append to a fresh queue and are not wiped by a blanket clear. Loops until the queue is empty so
5027
+ * documents added mid-flush are indexed before search runs. Re-queues the batch on flush failure.
4918
5028
  */
4919
5029
  async #ensureVectorIndex() {
4920
- if (!this.#lazyVectorIndex || this.#vectorIndexBuilt || this.#pendingVectorDocs.length === 0) {
5030
+ if (!this.#lazyVectorIndex) {
4921
5031
  return;
4922
5032
  }
4923
- for (const doc of this.#pendingVectorDocs) {
4924
- await this.#indexVector(doc);
5033
+ if (this.#pendingVectorDocs.length === 0) {
5034
+ this.#vectorIndexBuilt = true;
5035
+ return;
5036
+ }
5037
+ while (this.#pendingVectorDocs.length > 0) {
5038
+ const batch = this.#pendingVectorDocs;
5039
+ this.#pendingVectorDocs = [];
5040
+ const uniqueDocs = this.#dedupePendingVectorDocsLastWins(batch);
5041
+ try {
5042
+ await this.#flushVectorBatch(uniqueDocs);
5043
+ } catch (error) {
5044
+ this.#pendingVectorDocs = [...uniqueDocs, ...this.#pendingVectorDocs];
5045
+ throw error;
5046
+ }
4925
5047
  }
4926
- this.#pendingVectorDocs = [];
4927
5048
  this.#vectorIndexBuilt = true;
4928
5049
  }
4929
5050
  /**
@@ -4957,8 +5078,8 @@ var SearchEngine = class {
4957
5078
  throw new Error("Vector search requires vector configuration.");
4958
5079
  }
4959
5080
  await this.#ensureVectorIndex();
4960
- const { vectorStore, embedder, indexName } = this.#vectorConfig;
4961
- const queryEmbedding = await embedder(query);
5081
+ const { vectorStore, indexName } = this.#vectorConfig;
5082
+ const queryEmbedding = await this.#embedOne(query);
4962
5083
  const vectorResults = await vectorStore.query({
4963
5084
  indexName,
4964
5085
  queryVector: queryEmbedding,
@@ -6759,6 +6880,7 @@ Available files: ${allFiles.join(", ")}` : "";
6759
6880
  }
6760
6881
 
6761
6882
  // src/workspace/workspace.ts
6883
+ var FS_READ_CONCURRENCY = 8;
6762
6884
  var Workspace = class {
6763
6885
  id;
6764
6886
  name;
@@ -7092,20 +7214,15 @@ var Workspace = class {
7092
7214
  const alreadyCovered = directoryRoots.some((root) => entry.path === root || entry.path.startsWith(`${root}/`));
7093
7215
  if (!alreadyCovered) directoryRoots.push(entry.path);
7094
7216
  }
7095
- for (const filePath of filesToIndex) {
7096
- if (indexedPaths.has(filePath)) continue;
7097
- await this.indexFileForSearch(filePath);
7098
- indexedPaths.add(filePath);
7099
- }
7217
+ const indexed = await this.indexFilesForSearch(
7218
+ Array.from(filesToIndex).filter((filePath) => !indexedPaths.has(filePath))
7219
+ );
7220
+ for (const filePath of indexed) indexedPaths.add(filePath);
7100
7221
  for (const dir of directoryRoots) {
7101
7222
  try {
7102
- const files = await this.getAllFiles(dir);
7103
- for (const filePath of files) {
7104
- if (!indexedPaths.has(filePath)) {
7105
- await this.indexFileForSearch(filePath);
7106
- indexedPaths.add(filePath);
7107
- }
7108
- }
7223
+ const files = (await this.getAllFiles(dir)).filter((filePath) => !indexedPaths.has(filePath));
7224
+ const indexed2 = await this.indexFilesForSearch(files);
7225
+ for (const filePath of indexed2) indexedPaths.add(filePath);
7109
7226
  } catch {
7110
7227
  }
7111
7228
  }
@@ -7113,10 +7230,69 @@ var Workspace = class {
7113
7230
  }
7114
7231
  }
7115
7232
  }
7233
+ /**
7234
+ * Load file contents for search indexing in parallel (bounded by {@link FS_READ_CONCURRENCY}).
7235
+ * Paths that cannot be read as UTF-8 text are omitted (same behavior as {@link indexFileForSearch}).
7236
+ */
7237
+ async batchReadFiles(files) {
7238
+ if (!this._fs || files.length === 0) {
7239
+ return [];
7240
+ }
7241
+ const fs6 = this._fs;
7242
+ return pMap(
7243
+ files,
7244
+ async (filePath) => {
7245
+ try {
7246
+ const content = await fs6.readFile(filePath, { encoding: "utf-8" });
7247
+ const chunks = splitIntoChunks(content);
7248
+ const docs = chunks.length === 1 ? [{ id: filePath, content }] : chunks.map((chunk, i) => ({
7249
+ id: `${filePath}#chunk-${i}`,
7250
+ content: chunk.content,
7251
+ startLineOffset: chunk.startLine,
7252
+ metadata: { sourceFile: filePath }
7253
+ }));
7254
+ return { filePath, docs };
7255
+ } catch {
7256
+ return pMapSkip;
7257
+ }
7258
+ },
7259
+ { stopOnError: false, concurrency: FS_READ_CONCURRENCY }
7260
+ );
7261
+ }
7262
+ /**
7263
+ * Batch-read paths and {@link SearchEngine.indexMany}
7264
+ *
7265
+ * @returns paths that were indexed successfully.
7266
+ * @remarks Falls back to one-at-a-time indexing on failure of {@link SearchEngine.indexMany}
7267
+ */
7268
+ async indexFilesForSearch(paths) {
7269
+ const engine = this._searchEngine;
7270
+ if (!engine) return [];
7271
+ try {
7272
+ const entries = await this.batchReadFiles(paths);
7273
+ await pMap(entries, ({ filePath }) => engine.removeSource(filePath), {
7274
+ concurrency: FS_READ_CONCURRENCY
7275
+ });
7276
+ const docs = entries.flatMap(({ docs: docs2 }) => docs2);
7277
+ await engine.indexMany(docs);
7278
+ return entries.map(({ filePath }) => filePath);
7279
+ } catch {
7280
+ const indexed = [];
7281
+ for (const filePath of paths) {
7282
+ const id = await this.indexFileForSearch(filePath);
7283
+ if (id !== void 0) {
7284
+ indexed.push(id);
7285
+ }
7286
+ }
7287
+ return indexed;
7288
+ }
7289
+ }
7116
7290
  /**
7117
7291
  * Index a single file for search. Skips files that can't be read as text.
7118
7292
  * Large files are automatically split into chunks to stay within embedding
7119
7293
  * model token limits.
7294
+ *
7295
+ * @returns `filePath` when indexed, or `undefined` if read/index failed.
7120
7296
  */
7121
7297
  async indexFileForSearch(filePath) {
7122
7298
  let content;
@@ -7130,11 +7306,13 @@ var Workspace = class {
7130
7306
  if (chunks.length === 1) {
7131
7307
  try {
7132
7308
  await this._searchEngine.index({ id: filePath, content });
7309
+ return filePath;
7133
7310
  } catch (error) {
7134
7311
  this._logger?.warn(`Failed to index file "${filePath}" for search`, { error });
7312
+ return;
7135
7313
  }
7136
- return;
7137
7314
  }
7315
+ let anyIndexed = false;
7138
7316
  for (let i = 0; i < chunks.length; i++) {
7139
7317
  const chunk = chunks[i];
7140
7318
  try {
@@ -7144,10 +7322,12 @@ var Workspace = class {
7144
7322
  startLineOffset: chunk.startLine,
7145
7323
  metadata: { sourceFile: filePath }
7146
7324
  });
7325
+ anyIndexed = true;
7147
7326
  } catch (error) {
7148
7327
  this._logger?.warn(`Failed to index chunk ${i} of file "${filePath}" for search`, { error });
7149
7328
  }
7150
7329
  }
7330
+ return anyIndexed ? filePath : void 0;
7151
7331
  }
7152
7332
  async getAllFiles(dir, depth = 0, maxDepth = 10, filesystem = this._fs) {
7153
7333
  if (!filesystem || depth >= maxDepth) return [];
@@ -9623,5 +9803,5 @@ async function createWorkspaceTools(workspace, configContext) {
9623
9803
  }
9624
9804
 
9625
9805
  export { BM25Index, BrowserCliHandler, 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, StaleFileError, VersionedSkillSource, WORKSPACE_TOOLS, WORKSPACE_TOOLS_PREFIX, Workspace, WorkspaceError, WorkspaceNotAvailableError, WorkspaceNotReadyError, WorkspaceReadOnlyError, browserCliHandler, callLifecycle, collectSkillForPublish, createGlobMatcher, createSkillTools, createWorkspaceTools, deleteFileTool, detectIsolation, editFileTool, executeCommandTool, extractGlobBase, fileStatTool, getRecommendedIsolation, getTiktoken, indexContentTool, isGlobPattern, isIsolationAvailable, listFilesTool, matchGlob, mkdirTool, publishSkillFromSource, readFileTool, requireFilesystem, requireSandbox, requireWorkspace, resolveToolConfig, searchTool, writeFileTool };
9626
- //# sourceMappingURL=chunk-5AFU6MDJ.js.map
9627
- //# sourceMappingURL=chunk-5AFU6MDJ.js.map
9806
+ //# sourceMappingURL=chunk-F4PWGVHW.js.map
9807
+ //# sourceMappingURL=chunk-F4PWGVHW.js.map