doc2vec 2.9.0 → 2.9.2

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.
@@ -1707,7 +1707,10 @@ class ContentProcessor {
1707
1707
  if (lang) {
1708
1708
  try {
1709
1709
  const codeChunker = await this.getCodeChunker(lang, sourceConfig.chunk_size);
1710
- chunks = await codeChunker.chunk(code);
1710
+ chunks = await Promise.race([
1711
+ codeChunker.chunk(code),
1712
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`CodeChunker timed out after 30s for ${normalizedPath || url}`)), 30000))
1713
+ ]);
1711
1714
  }
1712
1715
  catch (error) {
1713
1716
  logger.warn(`CodeChunker failed for ${normalizedPath || url}, falling back to token chunking:`, error);
@@ -1757,9 +1760,9 @@ class ContentProcessor {
1757
1760
  }
1758
1761
  async chunkMarkdown(markdown, sourceConfig, url) {
1759
1762
  const logger = this.logger.child('chunker');
1760
- // --- Configuration ---
1761
- const MAX_TOKENS = 1000;
1762
- const MIN_TOKENS = 150; // 💡 Merges "OpenAI-compatible" sentence into the next block
1763
+ // --- Configuration (character-based, ~4 chars ≈ 1 token) ---
1764
+ const MAX_CHARS = 4000;
1765
+ const MIN_CHARS = 600; // 💡 Merges short sections into the next block
1763
1766
  const OVERLAP_PERCENT = 0.1; // 10% overlap for large splits
1764
1767
  const chunks = [];
1765
1768
  const lines = markdown.split("\n");
@@ -1821,29 +1824,27 @@ class ContentProcessor {
1821
1824
  };
1822
1825
  /**
1823
1826
  * Flushes the current buffer into the chunks array.
1824
- * Uses sub-splitting logic if the buffer exceeds MAX_TOKENS.
1827
+ * Uses sub-splitting logic if the buffer exceeds MAX_CHARS.
1825
1828
  */
1826
1829
  const flushBuffer = (force = false) => {
1827
1830
  const trimmedBuffer = buffer.trim();
1828
1831
  if (!trimmedBuffer)
1829
1832
  return;
1830
- const tokenCount = utils_1.Utils.tokenize(trimmedBuffer).length;
1833
+ const charCount = trimmedBuffer.length;
1831
1834
  // 💡 SEMANTIC MERGING
1832
1835
  // If the current section is too short (like just a title or a one-liner),
1833
1836
  // we don't flush yet unless it's the end of the file (force=true).
1834
- if (tokenCount < MIN_TOKENS && !force) {
1837
+ if (charCount < MIN_CHARS && !force) {
1835
1838
  return;
1836
1839
  }
1837
1840
  // Compute the appropriate topic hierarchy for merged content
1838
1841
  const topicHierarchy = computeTopicHierarchy();
1839
- if (tokenCount > MAX_TOKENS) {
1840
- // 💡 RECURSIVE OVERLAP SPLITTING
1842
+ if (charCount > MAX_CHARS) {
1843
+ // 💡 OVERLAP SPLITTING
1841
1844
  // If the section is a massive guide, split it but keep headers on every sub-piece.
1842
- const tokens = utils_1.Utils.tokenize(trimmedBuffer);
1843
- const overlapSize = Math.floor(MAX_TOKENS * OVERLAP_PERCENT);
1844
- for (let i = 0; i < tokens.length; i += (MAX_TOKENS - overlapSize)) {
1845
- const subTokens = tokens.slice(i, i + MAX_TOKENS);
1846
- const subContent = subTokens.join("");
1845
+ const overlapSize = Math.floor(MAX_CHARS * OVERLAP_PERCENT);
1846
+ for (let i = 0; i < trimmedBuffer.length; i += (MAX_CHARS - overlapSize)) {
1847
+ const subContent = trimmedBuffer.slice(i, i + MAX_CHARS);
1847
1848
  chunks.push(createDocumentChunk(subContent, topicHierarchy));
1848
1849
  }
1849
1850
  }
@@ -1867,9 +1868,9 @@ class ContentProcessor {
1867
1868
  .replace(/\[\]\(#[^)]*\)/g, "") // Remove [](#anchor) patterns
1868
1869
  .trim();
1869
1870
  // Check if we should merge with previous content
1870
- const currentTokenCount = utils_1.Utils.tokenize(buffer.trim()).length;
1871
- const hasBufferContent = currentTokenCount > 0;
1872
- const bufferIsSmall = currentTokenCount < MIN_TOKENS;
1871
+ const currentCharCount = buffer.trim().length;
1872
+ const hasBufferContent = currentCharCount > 0;
1873
+ const bufferIsSmall = currentCharCount < MIN_CHARS;
1873
1874
  // Only merge if:
1874
1875
  // 1. Buffer has content and is small
1875
1876
  // 2. Buffer has tracked headings (we're merging sections, not just content)
@@ -1895,7 +1896,7 @@ class ContentProcessor {
1895
1896
  else {
1896
1897
  buffer += `${line}\n`;
1897
1898
  // Safety valve: if a single section is huge, flush it periodically
1898
- if (utils_1.Utils.tokenize(buffer).length >= MAX_TOKENS) {
1899
+ if (buffer.length >= MAX_CHARS) {
1899
1900
  flushBuffer();
1900
1901
  }
1901
1902
  }
package/dist/doc2vec.js CHANGED
@@ -1530,7 +1530,7 @@ class Doc2Vec {
1530
1530
  const response = await this.openai.embeddings.create({
1531
1531
  model: this.embeddingModel,
1532
1532
  input: safeTexts,
1533
- });
1533
+ }, { timeout: 60000 });
1534
1534
  logger.debug(`Successfully created ${response.data.length} embeddings`);
1535
1535
  return response.data.map(d => d.embedding);
1536
1536
  }
@@ -1555,5 +1555,7 @@ if (require.main === module) {
1555
1555
  process.exit(1);
1556
1556
  }
1557
1557
  const doc2Vec = new Doc2Vec(configPath);
1558
- doc2Vec.run().catch(console.error);
1558
+ doc2Vec.run()
1559
+ .then(() => process.exit(0))
1560
+ .catch((err) => { console.error(err); process.exit(1); });
1559
1561
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doc2vec",
3
- "version": "2.9.0",
3
+ "version": "2.9.2",
4
4
  "type": "commonjs",
5
5
  "description": "",
6
6
  "main": "dist/doc2vec.js",