sensemaking 0.22.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -8
- package/dist/cjs/chunk/extract.d.cts +3 -3
- package/dist/cjs/chunk/extract.d.ts +3 -3
- package/dist/cjs/chunk/extract.js +369 -72
- package/dist/cjs/chunk/extract.js.map +1 -1
- package/dist/cjs/chunk/group.js +2 -2
- package/dist/cjs/chunk/group.js.map +1 -1
- package/dist/cjs/chunk/parse.js +63 -67
- package/dist/cjs/chunk/parse.js.map +1 -1
- package/dist/cjs/chunk/parser.d.cts +2 -0
- package/dist/cjs/chunk/parser.d.ts +2 -0
- package/dist/cjs/chunk/parser.js +40 -0
- package/dist/cjs/chunk/parser.js.map +1 -0
- package/dist/cjs/chunk/types.d.cts +2 -2
- package/dist/cjs/chunk/types.d.ts +2 -2
- package/dist/cjs/chunk/version.d.cts +1 -1
- package/dist/cjs/chunk/version.d.ts +1 -1
- package/dist/cjs/chunk/version.js +1 -1
- package/dist/cjs/chunk/version.js.map +1 -1
- package/dist/cjs/features/links.js +67 -71
- package/dist/cjs/features/links.js.map +1 -1
- package/dist/cjs/features/sections.js +1 -1
- package/dist/cjs/features/sections.js.map +1 -1
- package/dist/cjs/scan/pool.js +1 -1
- package/dist/cjs/scan/pool.js.map +1 -1
- package/dist/cjs/store/builder.js +2 -3
- package/dist/cjs/store/builder.js.map +1 -1
- package/dist/cjs/store/duckdb/open.d.cts +1 -1
- package/dist/cjs/store/duckdb/open.d.ts +1 -1
- package/dist/cjs/store/duckdb/open.js +1 -1
- package/dist/cjs/store/duckdb/open.js.map +1 -1
- package/dist/cjs/store/sqlite/open.d.cts +1 -1
- package/dist/cjs/store/sqlite/open.d.ts +1 -1
- package/dist/cjs/store/sqlite/open.js +1 -1
- package/dist/cjs/store/sqlite/open.js.map +1 -1
- package/dist/cjs/store/turso/connection.d.cts +1 -0
- package/dist/cjs/store/turso/connection.d.ts +1 -0
- package/dist/cjs/store/turso/connection.js +134 -13
- package/dist/cjs/store/turso/connection.js.map +1 -1
- package/dist/cjs/store/turso/open.d.cts +1 -1
- package/dist/cjs/store/turso/open.d.ts +1 -1
- package/dist/cjs/store/turso/open.js +8 -2
- package/dist/cjs/store/turso/open.js.map +1 -1
- package/dist/cjs/store/turso/store.js +8 -1
- package/dist/cjs/store/turso/store.js.map +1 -1
- package/dist/cjs/text/strip.js +1 -3
- package/dist/cjs/text/strip.js.map +1 -1
- package/dist/cjs/workers/parse.js.map +1 -1
- package/dist/esm/chunk/extract.d.ts +3 -3
- package/dist/esm/chunk/extract.js +276 -63
- package/dist/esm/chunk/extract.js.map +1 -1
- package/dist/esm/chunk/group.js +2 -2
- package/dist/esm/chunk/group.js.map +1 -1
- package/dist/esm/chunk/parse.js +65 -64
- package/dist/esm/chunk/parse.js.map +1 -1
- package/dist/esm/chunk/parser.d.ts +2 -0
- package/dist/esm/chunk/parser.js +26 -0
- package/dist/esm/chunk/parser.js.map +1 -0
- package/dist/esm/chunk/types.d.ts +2 -2
- package/dist/esm/chunk/types.js.map +1 -1
- package/dist/esm/chunk/version.d.ts +1 -1
- package/dist/esm/chunk/version.js +1 -1
- package/dist/esm/chunk/version.js.map +1 -1
- package/dist/esm/features/links.js +59 -22
- package/dist/esm/features/links.js.map +1 -1
- package/dist/esm/features/sections.js +1 -1
- package/dist/esm/features/sections.js.map +1 -1
- package/dist/esm/scan/pool.js +1 -1
- package/dist/esm/scan/pool.js.map +1 -1
- package/dist/esm/store/builder.js +2 -3
- package/dist/esm/store/builder.js.map +1 -1
- package/dist/esm/store/duckdb/open.d.ts +1 -1
- package/dist/esm/store/duckdb/open.js +1 -1
- package/dist/esm/store/duckdb/open.js.map +1 -1
- package/dist/esm/store/sqlite/open.d.ts +1 -1
- package/dist/esm/store/sqlite/open.js +1 -1
- package/dist/esm/store/sqlite/open.js.map +1 -1
- package/dist/esm/store/turso/connection.d.ts +1 -0
- package/dist/esm/store/turso/connection.js +21 -8
- package/dist/esm/store/turso/connection.js.map +1 -1
- package/dist/esm/store/turso/open.d.ts +1 -1
- package/dist/esm/store/turso/open.js +3 -2
- package/dist/esm/store/turso/open.js.map +1 -1
- package/dist/esm/store/turso/store.js +2 -0
- package/dist/esm/store/turso/store.js.map +1 -1
- package/dist/esm/text/strip.js +1 -1
- package/dist/esm/text/strip.js.map +1 -1
- package/dist/esm/workers/parse.js.map +1 -1
- package/package.json +5 -19
- package/skills/sense-setup/SKILL.md +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/group.ts"],"sourcesContent":["import { extractText } from './extract.ts';\nimport { parse } from './parse.ts';\nimport { DEFAULT_TARGET_TOKENS, estimateTokens } from './tokens.ts';\nimport type { Block, BlockType, Chunk, ChunkOptions } from './types.ts';\n\nconst PGC_GROUP_SIZE = 2;\nconst OVERSIZE_TRIGGER_MULTIPLE = 2;\n\ninterface ResolvedOptions {\n targetTokens: number;\n text: 'extracted' | 'raw';\n}\n\nfunction resolveOptions(opts?: ChunkOptions): ResolvedOptions {\n return {\n targetTokens: opts?.targetTokens ?? DEFAULT_TARGET_TOKENS,\n text: opts?.text ?? 'raw',\n };\n}\n\n// A heading of any depth ends the current scope and starts a new one (D1); the heading block\n// itself is carried into the new scope, where it joins that scope's first group (F7/F10).\nfunction splitScopes(blocks: Block[]): Block[][] {\n const scopes: Block[][] = [];\n let current: Block[] = [];\n for (const block of blocks) {\n if (block.type === 'heading' && current.length > 0) {\n scopes.push(current);\n current = [];\n }\n current.push(block);\n }\n if (current.length > 0) scopes.push(current);\n return scopes;\n}\n\ninterface Part {\n startLine: number;\n endLine: number;\n text: string;\n // True for a sub-line split piece: its text is already the final slice, not the whole line --\n // group()'s extent-based raw re-slice must not touch it (siblings share startLine === endLine).\n final?: boolean;\n}\n\nfunction finalize(parts: Part[]): (Chunk & { final?: boolean }) | undefined {\n if (parts.length === 0) return undefined;\n const first = parts[0];\n const last = parts[parts.length - 1];\n return { startLine: first.startLine, endLine: last.endLine, text: parts.map((p) => p.text).join('\\n'), final: parts.some((p) => p.final) };\n}\n\nconst NEWLINE_TOKENS = estimateTokens('\\n');\n// Built on first use and kept: each construction is ~3.5 ms, and only an oversize block is ever\n// split, so no command pays for a segmenter it never reaches.\nconst SEGMENTERS = new Map<string, Intl.Segmenter>();\n\nfunction segmentsOf(text: string, granularity: 'sentence' | 'word'): string[] {\n let segmenter = SEGMENTERS.get(granularity);\n if (!segmenter) {\n segmenter = new Intl.Segmenter(undefined, { granularity });\n SEGMENTERS.set(granularity, segmenter);\n }\n return Array.from(segmenter.segment(text), (s) => s.segment);\n}\n\n// Greedily packs segments (already contiguous, tiling the source text with no gaps) into groups\n// of at most `working` estimated tokens; a lone segment over `working` still stands alone.\nfunction pack(segments: string[], working: number): string[] {\n const groups: string[] = [];\n let current = '';\n let tokens = 0;\n for (const segment of segments) {\n const segmentTokens = estimateTokens(segment);\n if (current.length > 0 && tokens + segmentTokens > working) {\n groups.push(current);\n current = '';\n tokens = 0;\n }\n current += segment;\n tokens += segmentTokens;\n }\n if (current.length > 0) groups.push(current);\n return groups;\n}\n\n// Line-split alone can't shrink a lone dense line (the CJK case): falls back to sentence then\n// word boundaries (Intl.Segmenter, the same grapheme-safe engine as segment.ts), mode-agnostic on `text`.\nfunction splitLineText(text: string, working: number): string[] {\n const sentences = segmentsOf(text, 'sentence');\n const out: string[] = [];\n let current = '';\n let tokens = 0;\n const flush = () => {\n if (current.length > 0) {\n out.push(current);\n current = '';\n tokens = 0;\n }\n };\n for (const sentence of sentences) {\n const sentenceTokens = estimateTokens(sentence);\n if (sentenceTokens > working) {\n flush();\n out.push(...pack(segmentsOf(sentence, 'word'), working));\n continue;\n }\n if (current.length > 0 && tokens + sentenceTokens > working) flush();\n current += sentence;\n tokens += sentenceTokens;\n }\n flush();\n return out;\n}\n\nconst ATOMIC_TYPES: ReadonlySet<BlockType> = new Set(['code', 'table', 'list']);\n\n// Atomic (code/table/list) pieces are always a raw line slice: re-parsing a table's later pieces\n// without their header/delimiter rows would demote them to paragraph text.\nfunction piece(pieceLines: string[], startLine: number, endLine: number, blockType: BlockType, textMode: 'extracted' | 'raw'): Part {\n const text =\n ATOMIC_TYPES.has(blockType) || textMode === 'raw'\n ? pieceLines.join('\\n')\n : parse(pieceLines.join('\\n'))\n .map((b) => extractText(b.node))\n .join('\\n');\n return { startLine, endLine, text };\n}\n\n// A one-line piece over working can't shrink via another line-boundary pass (rule 5's gap), so it\n// splits at sentence/word boundaries instead; `final` stops group() re-deriving its text by extent (F5).\nfunction finalizePiece(pieceLines: string[], startLine: number, endLine: number, working: number, blockType: BlockType, textMode: 'extracted' | 'raw'): Part[] {\n const p = piece(pieceLines, startLine, endLine, blockType, textMode);\n if (pieceLines.length === 1 && estimateTokens(p.text) > working) {\n return splitLineText(p.text, working).map((text) => ({ startLine, endLine, text, final: true }));\n }\n return [p];\n}\n\n// A block over 2x working size splits at line boundaries into pieces each <= working size, never\n// mid-line. `seed`: pending tokens (e.g. a heading) the first piece must join, checked against the limit.\nfunction splitOversizeBlock(lines: string[], startLine: number, endLine: number, working: number, blockType: BlockType, textMode: 'extracted' | 'raw', seed = 0): Part[] {\n const pieces: Part[] = [];\n let pieceLines: string[] = [];\n let pieceStart = startLine;\n let tokens = seed;\n for (let line = startLine; line <= endLine; line++) {\n const lineText = lines[line - 1];\n const sep = pieceLines.length > 0 || tokens > 0 ? NEWLINE_TOKENS : 0;\n const lineTokens = estimateTokens(lineText);\n if (pieceLines.length > 0 && tokens + sep + lineTokens > working) {\n pieces.push(...finalizePiece(pieceLines, pieceStart, line - 1, working, blockType, textMode));\n pieceLines = [];\n tokens = 0;\n pieceStart = line;\n pieceLines.push(lineText);\n tokens += lineTokens;\n continue;\n }\n pieceLines.push(lineText);\n tokens += sep + lineTokens;\n }\n if (pieceLines.length > 0) pieces.push(...finalizePiece(pieceLines, pieceStart, endLine, working, blockType, textMode));\n return pieces;\n}\n\n// One heading scope's groups (D1): a heading opens the first group, and an oversize block\n// (rule 5, including an oversize heading) splits into pieces that each close their own group.\nfunction groupScope(scopeBlocks: Block[], lines: string[], resolved: ResolvedOptions): (Chunk & { final?: boolean })[] {\n const working = resolved.targetTokens;\n const trigger = working * OVERSIZE_TRIGGER_MULTIPLE;\n const finished: (Chunk & { final?: boolean })[] = [];\n let parts: Part[] = [];\n let paragraphCount = 0;\n let tokens = 0;\n\n function close(): void {\n const group = finalize(parts);\n if (group) finished.push(group);\n parts = [];\n paragraphCount = 0;\n tokens = 0;\n }\n\n // tokens tracks the active text mode's own estimate (a newline between parts costs\n // NEWLINE_TOKENS too), so packing decisions size the text the chunk will actually ship as.\n function addPart(text: string, sizeText: string, startLine: number, endLine: number): void {\n tokens += (parts.length > 0 ? NEWLINE_TOKENS : 0) + estimateTokens(sizeText);\n parts.push({ startLine, endLine, text });\n }\n\n for (const block of scopeBlocks) {\n const raw = lines.slice(block.startLine - 1, block.endLine).join('\\n');\n const blockTokens = estimateTokens(raw);\n\n if (blockTokens > trigger) {\n const seed = parts.length > 0 ? tokens : 0;\n for (const p of splitOversizeBlock(lines, block.startLine, block.endLine, working, block.type, resolved.text, seed)) {\n parts.push(p);\n close();\n }\n continue;\n }\n\n const extracted = extractText(block.node);\n const sizeText = resolved.text === 'raw' ? raw : extracted;\n\n if (block.type === 'heading') {\n addPart(extracted, sizeText, block.startLine, block.endLine);\n continue;\n }\n\n // The 2x-working invariant holds even under pgc's paper-faithful 2-paragraph pairing --\n // close first if the pair about to form would cross it.\n const pairOversize = parts.length > 0 && tokens + NEWLINE_TOKENS + blockTokens > trigger;\n if (pairOversize) close();\n\n addPart(extracted, sizeText, block.startLine, block.endLine);\n paragraphCount++;\n\n if (paragraphCount >= PGC_GROUP_SIZE) close();\n }\n close();\n\n return finished;\n}\n\n// Groups already-parsed blocks per opts (D1/D3), against the same body the blocks were parsed\n// from (line lookups for oversize splitting).\nexport function group(blocks: Block[], body: string, opts?: ChunkOptions): Chunk[] {\n const resolved = resolveOptions(opts);\n const lines = body.split('\\n');\n const chunks: (Chunk & { final?: boolean })[] = [];\n for (const scope of splitScopes(blocks)) chunks.push(...groupScope(scope, lines, resolved));\n // 'raw': the chunk's own source lines verbatim, replacing the flavor-resolved join above (D9).\n // A `final` chunk already carries its own slice's raw text; re-slicing by extent would return the whole shared line.\n const texted =\n resolved.text === 'raw'\n ? chunks.map((c) =>\n c.final\n ? c\n : {\n ...c,\n text: lines\n .slice(c.startLine - 1, c.endLine)\n .join('\\n')\n .trim(),\n }\n )\n : chunks;\n // A group can be all-blank (flavor-stripped to nothing, or a raw slice of pure syntax); it never produces a chunk.\n return texted.filter((c) => c.text.trim().length > 0).map((c) => ({ startLine: c.startLine, endLine: c.endLine, text: c.text }));\n}\n"],"names":["group","PGC_GROUP_SIZE","OVERSIZE_TRIGGER_MULTIPLE","resolveOptions","opts","targetTokens","DEFAULT_TARGET_TOKENS","text","splitScopes","blocks","scopes","current","block","type","length","push","finalize","parts","undefined","first","last","startLine","endLine","map","p","join","final","some","NEWLINE_TOKENS","estimateTokens","SEGMENTERS","Map","segmentsOf","granularity","segmenter","get","Intl","Segmenter","set","Array","from","segment","s","pack","segments","working","groups","tokens","segmentTokens","splitLineText","sentences","out","flush","sentence","sentenceTokens","ATOMIC_TYPES","Set","piece","pieceLines","blockType","textMode","has","parse","b","extractText","node","finalizePiece","splitOversizeBlock","lines","seed","pieces","pieceStart","line","lineText","sep","lineTokens","groupScope","scopeBlocks","resolved","trigger","finished","paragraphCount","close","addPart","sizeText","raw","slice","blockTokens","extracted","pairOversize","body","chunks","split","scope","texted","c","trim","filter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/group.ts"],"sourcesContent":["import { extractText } from './extract.ts';\nimport { parse } from './parse.ts';\nimport { DEFAULT_TARGET_TOKENS, estimateTokens } from './tokens.ts';\nimport type { Block, BlockType, Chunk, ChunkOptions } from './types.ts';\n\nconst PGC_GROUP_SIZE = 2;\nconst OVERSIZE_TRIGGER_MULTIPLE = 2;\n\ninterface ResolvedOptions {\n targetTokens: number;\n text: 'extracted' | 'raw';\n}\n\nfunction resolveOptions(opts?: ChunkOptions): ResolvedOptions {\n return {\n targetTokens: opts?.targetTokens ?? DEFAULT_TARGET_TOKENS,\n text: opts?.text ?? 'raw',\n };\n}\n\n// A heading of any depth ends the current scope and starts a new one (D1); the heading block\n// itself is carried into the new scope, where it joins that scope's first group (F7/F10).\nfunction splitScopes(blocks: Block[]): Block[][] {\n const scopes: Block[][] = [];\n let current: Block[] = [];\n for (const block of blocks) {\n if (block.type === 'heading' && current.length > 0) {\n scopes.push(current);\n current = [];\n }\n current.push(block);\n }\n if (current.length > 0) scopes.push(current);\n return scopes;\n}\n\ninterface Part {\n startLine: number;\n endLine: number;\n text: string;\n // True for a sub-line split piece: its text is already the final slice, not the whole line --\n // group()'s extent-based raw re-slice must not touch it (siblings share startLine === endLine).\n final?: boolean;\n}\n\nfunction finalize(parts: Part[]): (Chunk & { final?: boolean }) | undefined {\n if (parts.length === 0) return undefined;\n const first = parts[0];\n const last = parts[parts.length - 1];\n return { startLine: first.startLine, endLine: last.endLine, text: parts.map((p) => p.text).join('\\n'), final: parts.some((p) => p.final) };\n}\n\nconst NEWLINE_TOKENS = estimateTokens('\\n');\n// Built on first use and kept: each construction is ~3.5 ms, and only an oversize block is ever\n// split, so no command pays for a segmenter it never reaches.\nconst SEGMENTERS = new Map<string, Intl.Segmenter>();\n\nfunction segmentsOf(text: string, granularity: 'sentence' | 'word'): string[] {\n let segmenter = SEGMENTERS.get(granularity);\n if (!segmenter) {\n segmenter = new Intl.Segmenter(undefined, { granularity });\n SEGMENTERS.set(granularity, segmenter);\n }\n return Array.from(segmenter.segment(text), (s) => s.segment);\n}\n\n// Greedily packs segments (already contiguous, tiling the source text with no gaps) into groups\n// of at most `working` estimated tokens; a lone segment over `working` still stands alone.\nfunction pack(segments: string[], working: number): string[] {\n const groups: string[] = [];\n let current = '';\n let tokens = 0;\n for (const segment of segments) {\n const segmentTokens = estimateTokens(segment);\n if (current.length > 0 && tokens + segmentTokens > working) {\n groups.push(current);\n current = '';\n tokens = 0;\n }\n current += segment;\n tokens += segmentTokens;\n }\n if (current.length > 0) groups.push(current);\n return groups;\n}\n\n// Line-split alone can't shrink a lone dense line (the CJK case): falls back to sentence then\n// word boundaries (Intl.Segmenter, the same grapheme-safe engine as segment.ts), mode-agnostic on `text`.\nfunction splitLineText(text: string, working: number): string[] {\n const sentences = segmentsOf(text, 'sentence');\n const out: string[] = [];\n let current = '';\n let tokens = 0;\n const flush = () => {\n if (current.length > 0) {\n out.push(current);\n current = '';\n tokens = 0;\n }\n };\n for (const sentence of sentences) {\n const sentenceTokens = estimateTokens(sentence);\n if (sentenceTokens > working) {\n flush();\n out.push(...pack(segmentsOf(sentence, 'word'), working));\n continue;\n }\n if (current.length > 0 && tokens + sentenceTokens > working) flush();\n current += sentence;\n tokens += sentenceTokens;\n }\n flush();\n return out;\n}\n\nconst ATOMIC_TYPES: ReadonlySet<BlockType> = new Set(['code', 'table', 'list']);\n\n// Atomic (code/table/list) pieces are always a raw line slice: re-parsing a table's later pieces\n// without their header/delimiter rows would demote them to paragraph text.\nfunction piece(pieceLines: string[], startLine: number, endLine: number, blockType: BlockType, textMode: 'extracted' | 'raw'): Part {\n const text =\n ATOMIC_TYPES.has(blockType) || textMode === 'raw'\n ? pieceLines.join('\\n')\n : parse(pieceLines.join('\\n'))\n .map((b) => extractText(b))\n .join('\\n');\n return { startLine, endLine, text };\n}\n\n// A one-line piece over working can't shrink via another line-boundary pass (rule 5's gap), so it\n// splits at sentence/word boundaries instead; `final` stops group() re-deriving its text by extent (F5).\nfunction finalizePiece(pieceLines: string[], startLine: number, endLine: number, working: number, blockType: BlockType, textMode: 'extracted' | 'raw'): Part[] {\n const p = piece(pieceLines, startLine, endLine, blockType, textMode);\n if (pieceLines.length === 1 && estimateTokens(p.text) > working) {\n return splitLineText(p.text, working).map((text) => ({ startLine, endLine, text, final: true }));\n }\n return [p];\n}\n\n// A block over 2x working size splits at line boundaries into pieces each <= working size, never\n// mid-line. `seed`: pending tokens (e.g. a heading) the first piece must join, checked against the limit.\nfunction splitOversizeBlock(lines: string[], startLine: number, endLine: number, working: number, blockType: BlockType, textMode: 'extracted' | 'raw', seed = 0): Part[] {\n const pieces: Part[] = [];\n let pieceLines: string[] = [];\n let pieceStart = startLine;\n let tokens = seed;\n for (let line = startLine; line <= endLine; line++) {\n const lineText = lines[line - 1];\n const sep = pieceLines.length > 0 || tokens > 0 ? NEWLINE_TOKENS : 0;\n const lineTokens = estimateTokens(lineText);\n if (pieceLines.length > 0 && tokens + sep + lineTokens > working) {\n pieces.push(...finalizePiece(pieceLines, pieceStart, line - 1, working, blockType, textMode));\n pieceLines = [];\n tokens = 0;\n pieceStart = line;\n pieceLines.push(lineText);\n tokens += lineTokens;\n continue;\n }\n pieceLines.push(lineText);\n tokens += sep + lineTokens;\n }\n if (pieceLines.length > 0) pieces.push(...finalizePiece(pieceLines, pieceStart, endLine, working, blockType, textMode));\n return pieces;\n}\n\n// One heading scope's groups (D1): a heading opens the first group, and an oversize block\n// (rule 5, including an oversize heading) splits into pieces that each close their own group.\nfunction groupScope(scopeBlocks: Block[], lines: string[], resolved: ResolvedOptions): (Chunk & { final?: boolean })[] {\n const working = resolved.targetTokens;\n const trigger = working * OVERSIZE_TRIGGER_MULTIPLE;\n const finished: (Chunk & { final?: boolean })[] = [];\n let parts: Part[] = [];\n let paragraphCount = 0;\n let tokens = 0;\n\n function close(): void {\n const group = finalize(parts);\n if (group) finished.push(group);\n parts = [];\n paragraphCount = 0;\n tokens = 0;\n }\n\n // tokens tracks the active text mode's own estimate (a newline between parts costs\n // NEWLINE_TOKENS too), so packing decisions size the text the chunk will actually ship as.\n function addPart(text: string, sizeText: string, startLine: number, endLine: number): void {\n tokens += (parts.length > 0 ? NEWLINE_TOKENS : 0) + estimateTokens(sizeText);\n parts.push({ startLine, endLine, text });\n }\n\n for (const block of scopeBlocks) {\n const raw = lines.slice(block.startLine - 1, block.endLine).join('\\n');\n const blockTokens = estimateTokens(raw);\n\n if (blockTokens > trigger) {\n const seed = parts.length > 0 ? tokens : 0;\n for (const p of splitOversizeBlock(lines, block.startLine, block.endLine, working, block.type, resolved.text, seed)) {\n parts.push(p);\n close();\n }\n continue;\n }\n\n const extracted = extractText(block);\n const sizeText = resolved.text === 'raw' ? raw : extracted;\n\n if (block.type === 'heading') {\n addPart(extracted, sizeText, block.startLine, block.endLine);\n continue;\n }\n\n // The 2x-working invariant holds even under pgc's paper-faithful 2-paragraph pairing --\n // close first if the pair about to form would cross it.\n const pairOversize = parts.length > 0 && tokens + NEWLINE_TOKENS + blockTokens > trigger;\n if (pairOversize) close();\n\n addPart(extracted, sizeText, block.startLine, block.endLine);\n paragraphCount++;\n\n if (paragraphCount >= PGC_GROUP_SIZE) close();\n }\n close();\n\n return finished;\n}\n\n// Groups already-parsed blocks per opts (D1/D3), against the same body the blocks were parsed\n// from (line lookups for oversize splitting).\nexport function group(blocks: Block[], body: string, opts?: ChunkOptions): Chunk[] {\n const resolved = resolveOptions(opts);\n const lines = body.split('\\n');\n const chunks: (Chunk & { final?: boolean })[] = [];\n for (const scope of splitScopes(blocks)) chunks.push(...groupScope(scope, lines, resolved));\n // 'raw': the chunk's own source lines verbatim, replacing the flavor-resolved join above (D9).\n // A `final` chunk already carries its own slice's raw text; re-slicing by extent would return the whole shared line.\n const texted =\n resolved.text === 'raw'\n ? chunks.map((c) =>\n c.final\n ? c\n : {\n ...c,\n text: lines\n .slice(c.startLine - 1, c.endLine)\n .join('\\n')\n .trim(),\n }\n )\n : chunks;\n // A group can be all-blank (flavor-stripped to nothing, or a raw slice of pure syntax); it never produces a chunk.\n return texted.filter((c) => c.text.trim().length > 0).map((c) => ({ startLine: c.startLine, endLine: c.endLine, text: c.text }));\n}\n"],"names":["group","PGC_GROUP_SIZE","OVERSIZE_TRIGGER_MULTIPLE","resolveOptions","opts","targetTokens","DEFAULT_TARGET_TOKENS","text","splitScopes","blocks","scopes","current","block","type","length","push","finalize","parts","undefined","first","last","startLine","endLine","map","p","join","final","some","NEWLINE_TOKENS","estimateTokens","SEGMENTERS","Map","segmentsOf","granularity","segmenter","get","Intl","Segmenter","set","Array","from","segment","s","pack","segments","working","groups","tokens","segmentTokens","splitLineText","sentences","out","flush","sentence","sentenceTokens","ATOMIC_TYPES","Set","piece","pieceLines","blockType","textMode","has","parse","b","extractText","finalizePiece","splitOversizeBlock","lines","seed","pieces","pieceStart","line","lineText","sep","lineTokens","groupScope","scopeBlocks","resolved","trigger","finished","paragraphCount","close","addPart","sizeText","raw","slice","blockTokens","extracted","pairOversize","body","chunks","split","scope","texted","c","trim","filter"],"mappings":"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"}
|
package/dist/cjs/chunk/parse.js
CHANGED
|
@@ -8,78 +8,74 @@ Object.defineProperty(exports, "parse", {
|
|
|
8
8
|
return parse;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
var _nodemodule = /*#__PURE__*/ _interop_require_default(require("node:module"));
|
|
12
11
|
var _extractts = require("./extract.js");
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
// Tier-2, as embed/static.ts: the parser's packages cost ~19 ms to load and a warm tree never
|
|
19
|
-
// parses, so every store-opening command paid for them until a file actually changed.
|
|
20
|
-
var _require = typeof require === 'undefined' ? _nodemodule.default.createRequire(require("url").pathToFileURL(__filename).toString()) : require;
|
|
12
|
+
var _parserts = require("./parser.js");
|
|
13
|
+
// Opening token type to Block type. Everything else (rules, raw html, footnote definitions) is
|
|
14
|
+
// 'other', as mdast's BLOCK_TYPES mapped no entry for those nodes.
|
|
21
15
|
var BLOCK_TYPES = {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
16
|
+
heading_open: 'heading',
|
|
17
|
+
paragraph_open: 'paragraph',
|
|
18
|
+
fence: 'code',
|
|
19
|
+
code_block: 'code',
|
|
20
|
+
table_open: 'table',
|
|
21
|
+
ordered_list_open: 'list',
|
|
22
|
+
bullet_list_open: 'list',
|
|
23
|
+
blockquote_open: 'blockquote'
|
|
28
24
|
};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
gfmTaskListItem()
|
|
54
|
-
],
|
|
55
|
-
mdastExtensions: [
|
|
56
|
-
gfmAutolinkLiteralFromMarkdown(),
|
|
57
|
-
gfmFootnoteFromMarkdown(),
|
|
58
|
-
gfmStrikethroughFromMarkdown(),
|
|
59
|
-
gfmTableFromMarkdown(),
|
|
60
|
-
gfmTaskListItemFromMarkdown()
|
|
61
|
-
]
|
|
25
|
+
function parse(body) {
|
|
26
|
+
var tokens = (0, _parserts.parser)().parse(body, {});
|
|
27
|
+
var lines = body.split('\n');
|
|
28
|
+
var blocks = [];
|
|
29
|
+
var i = 0;
|
|
30
|
+
while(i < tokens.length){
|
|
31
|
+
var token = tokens[i];
|
|
32
|
+
if (token.nesting === 0) {
|
|
33
|
+
var _BLOCK_TYPES_token_type;
|
|
34
|
+
blocks.push(makeBlock((_BLOCK_TYPES_token_type = BLOCK_TYPES[token.type]) !== null && _BLOCK_TYPES_token_type !== void 0 ? _BLOCK_TYPES_token_type : 'other', tokens, i, i + 1, lines));
|
|
35
|
+
i += 1;
|
|
36
|
+
} else if (token.nesting === 1) {
|
|
37
|
+
var _BLOCK_TYPES_token_type1;
|
|
38
|
+
var depth = 1;
|
|
39
|
+
var j = i + 1;
|
|
40
|
+
while(j < tokens.length && depth > 0){
|
|
41
|
+
depth += tokens[j].nesting === 1 ? 1 : tokens[j].nesting === -1 ? -1 : 0;
|
|
42
|
+
j += 1;
|
|
43
|
+
}
|
|
44
|
+
blocks.push(makeBlock((_BLOCK_TYPES_token_type1 = BLOCK_TYPES[token.type]) !== null && _BLOCK_TYPES_token_type1 !== void 0 ? _BLOCK_TYPES_token_type1 : 'other', tokens, i, j, lines));
|
|
45
|
+
i = j;
|
|
46
|
+
} else {
|
|
47
|
+
// Defensive: the balanced scan above consumes every close belonging to an open.
|
|
48
|
+
i += 1;
|
|
62
49
|
}
|
|
63
|
-
}
|
|
64
|
-
return
|
|
50
|
+
}
|
|
51
|
+
return blocks;
|
|
65
52
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
};
|
|
78
|
-
if (node.type === 'heading') {
|
|
79
|
-
block.depth = node.depth;
|
|
80
|
-
block.text = (0, _extractts.extractText)(node);
|
|
53
|
+
// 1-based inclusive extent from the min/max of the tokens' maps (0-based half-open); a block
|
|
54
|
+
// whose tokens carry no map (an empty footnote definition) falls back to line 1. Trailing
|
|
55
|
+
// blank lines trim so a list's endLine lands where mdast's position ended it.
|
|
56
|
+
function makeBlock(type, tokens, i, j, lines) {
|
|
57
|
+
var start = Infinity;
|
|
58
|
+
var end = 0;
|
|
59
|
+
for(var k = i; k < j; k++){
|
|
60
|
+
var map = tokens[k].map;
|
|
61
|
+
if (map) {
|
|
62
|
+
start = Math.min(start, map[0]);
|
|
63
|
+
end = Math.max(end, map[1]);
|
|
81
64
|
}
|
|
82
|
-
|
|
83
|
-
|
|
65
|
+
}
|
|
66
|
+
var startLine = Number.isFinite(start) ? start + 1 : 1;
|
|
67
|
+
var endLine = end > start ? end : startLine;
|
|
68
|
+
while(endLine > startLine && lines[endLine - 1].trim() === '')endLine--;
|
|
69
|
+
var block = {
|
|
70
|
+
type: type,
|
|
71
|
+
startLine: startLine,
|
|
72
|
+
endLine: endLine,
|
|
73
|
+
node: tokens.slice(i, j)
|
|
74
|
+
};
|
|
75
|
+
if (type === 'heading') {
|
|
76
|
+
block.depth = Number(tokens[i].tag.slice(1));
|
|
77
|
+
block.text = (0, _extractts.extractText)(block);
|
|
78
|
+
}
|
|
79
|
+
return block;
|
|
84
80
|
}
|
|
85
81
|
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/parse.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/parse.ts"],"sourcesContent":["import type { Token } from 'markdown-it';\nimport { extractText } from './extract.ts';\nimport { parser } from './parser.ts';\nimport type { Block, BlockType } from './types.ts';\n\n// Opening token type to Block type. Everything else (rules, raw html, footnote definitions) is\n// 'other', as mdast's BLOCK_TYPES mapped no entry for those nodes.\nconst BLOCK_TYPES: Record<string, BlockType> = {\n heading_open: 'heading',\n paragraph_open: 'paragraph',\n fence: 'code',\n code_block: 'code',\n table_open: 'table',\n ordered_list_open: 'list',\n bullet_list_open: 'list',\n blockquote_open: 'blockquote',\n};\n\n// Top-level blocks of a markdown body, typed and line-extent bounded from markdown-it's own\n// token maps (never a regex guess). html and linkify on, with the footnote and task-list plugins.\nexport function parse(body: string): Block[] {\n const tokens = parser().parse(body, {});\n const lines = body.split('\\n');\n const blocks: Block[] = [];\n let i = 0;\n while (i < tokens.length) {\n const token = tokens[i];\n if (token.nesting === 0) {\n blocks.push(makeBlock(BLOCK_TYPES[token.type] ?? 'other', tokens, i, i + 1, lines));\n i += 1;\n } else if (token.nesting === 1) {\n let depth = 1;\n let j = i + 1;\n while (j < tokens.length && depth > 0) {\n depth += tokens[j].nesting === 1 ? 1 : tokens[j].nesting === -1 ? -1 : 0;\n j += 1;\n }\n blocks.push(makeBlock(BLOCK_TYPES[token.type] ?? 'other', tokens, i, j, lines));\n i = j;\n } else {\n // Defensive: the balanced scan above consumes every close belonging to an open.\n i += 1;\n }\n }\n return blocks;\n}\n\n// 1-based inclusive extent from the min/max of the tokens' maps (0-based half-open); a block\n// whose tokens carry no map (an empty footnote definition) falls back to line 1. Trailing\n// blank lines trim so a list's endLine lands where mdast's position ended it.\nfunction makeBlock(type: BlockType, tokens: Token[], i: number, j: number, lines: string[]): Block {\n let start = Infinity;\n let end = 0;\n for (let k = i; k < j; k++) {\n const map = tokens[k].map;\n if (map) {\n start = Math.min(start, map[0]);\n end = Math.max(end, map[1]);\n }\n }\n const startLine = Number.isFinite(start) ? start + 1 : 1;\n let endLine = end > start ? end : startLine;\n while (endLine > startLine && lines[endLine - 1].trim() === '') endLine--;\n const block: Block = { type, startLine, endLine, node: tokens.slice(i, j) };\n if (type === 'heading') {\n block.depth = Number(tokens[i].tag.slice(1));\n block.text = extractText(block);\n }\n return block;\n}\n"],"names":["parse","BLOCK_TYPES","heading_open","paragraph_open","fence","code_block","table_open","ordered_list_open","bullet_list_open","blockquote_open","body","tokens","parser","lines","split","blocks","i","length","token","nesting","push","makeBlock","type","depth","j","start","Infinity","end","k","map","Math","min","max","startLine","Number","isFinite","endLine","trim","block","node","slice","tag","text","extractText"],"mappings":";;;;+BAoBgBA;;;eAAAA;;;yBAnBY;wBACL;AAGvB,+FAA+F;AAC/F,mEAAmE;AACnE,IAAMC,cAAyC;IAC7CC,cAAc;IACdC,gBAAgB;IAChBC,OAAO;IACPC,YAAY;IACZC,YAAY;IACZC,mBAAmB;IACnBC,kBAAkB;IAClBC,iBAAiB;AACnB;AAIO,SAAST,MAAMU,IAAY;IAChC,IAAMC,SAASC,IAAAA,gBAAM,IAAGZ,KAAK,CAACU,MAAM,CAAC;IACrC,IAAMG,QAAQH,KAAKI,KAAK,CAAC;IACzB,IAAMC,SAAkB,EAAE;IAC1B,IAAIC,IAAI;IACR,MAAOA,IAAIL,OAAOM,MAAM,CAAE;QACxB,IAAMC,QAAQP,MAAM,CAACK,EAAE;QACvB,IAAIE,MAAMC,OAAO,KAAK,GAAG;gBACDlB;YAAtBc,OAAOK,IAAI,CAACC,WAAUpB,0BAAAA,WAAW,CAACiB,MAAMI,IAAI,CAAC,cAAvBrB,qCAAAA,0BAA2B,SAASU,QAAQK,GAAGA,IAAI,GAAGH;YAC5EG,KAAK;QACP,OAAO,IAAIE,MAAMC,OAAO,KAAK,GAAG;gBAORlB;YANtB,IAAIsB,QAAQ;YACZ,IAAIC,IAAIR,IAAI;YACZ,MAAOQ,IAAIb,OAAOM,MAAM,IAAIM,QAAQ,EAAG;gBACrCA,SAASZ,MAAM,CAACa,EAAE,CAACL,OAAO,KAAK,IAAI,IAAIR,MAAM,CAACa,EAAE,CAACL,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI;gBACvEK,KAAK;YACP;YACAT,OAAOK,IAAI,CAACC,WAAUpB,2BAAAA,WAAW,CAACiB,MAAMI,IAAI,CAAC,cAAvBrB,sCAAAA,2BAA2B,SAASU,QAAQK,GAAGQ,GAAGX;YACxEG,IAAIQ;QACN,OAAO;YACL,gFAAgF;YAChFR,KAAK;QACP;IACF;IACA,OAAOD;AACT;AAEA,6FAA6F;AAC7F,0FAA0F;AAC1F,8EAA8E;AAC9E,SAASM,UAAUC,IAAe,EAAEX,MAAe,EAAEK,CAAS,EAAEQ,CAAS,EAAEX,KAAe;IACxF,IAAIY,QAAQC;IACZ,IAAIC,MAAM;IACV,IAAK,IAAIC,IAAIZ,GAAGY,IAAIJ,GAAGI,IAAK;QAC1B,IAAMC,MAAMlB,MAAM,CAACiB,EAAE,CAACC,GAAG;QACzB,IAAIA,KAAK;YACPJ,QAAQK,KAAKC,GAAG,CAACN,OAAOI,GAAG,CAAC,EAAE;YAC9BF,MAAMG,KAAKE,GAAG,CAACL,KAAKE,GAAG,CAAC,EAAE;QAC5B;IACF;IACA,IAAMI,YAAYC,OAAOC,QAAQ,CAACV,SAASA,QAAQ,IAAI;IACvD,IAAIW,UAAUT,MAAMF,QAAQE,MAAMM;IAClC,MAAOG,UAAUH,aAAapB,KAAK,CAACuB,UAAU,EAAE,CAACC,IAAI,OAAO,GAAID;IAChE,IAAME,QAAe;QAAEhB,MAAAA;QAAMW,WAAAA;QAAWG,SAAAA;QAASG,MAAM5B,OAAO6B,KAAK,CAACxB,GAAGQ;IAAG;IAC1E,IAAIF,SAAS,WAAW;QACtBgB,MAAMf,KAAK,GAAGW,OAAOvB,MAAM,CAACK,EAAE,CAACyB,GAAG,CAACD,KAAK,CAAC;QACzCF,MAAMI,IAAI,GAAGC,IAAAA,sBAAW,EAACL;IAC3B;IACA,OAAOA;AACT"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "parser", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return parser;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
var _nodemodule = /*#__PURE__*/ _interop_require_default(require("node:module"));
|
|
12
|
+
function _interop_require_default(obj) {
|
|
13
|
+
return obj && obj.__esModule ? obj : {
|
|
14
|
+
default: obj
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
// Tier-2, as embed/static.ts: the parser's packages cost ~19 ms to load and a warm tree never
|
|
18
|
+
// parses, so every store-opening command paid for them until a file actually changed.
|
|
19
|
+
var _require = typeof require === 'undefined' ? _nodemodule.default.createRequire(require("url").pathToFileURL(__filename).toString()) : require;
|
|
20
|
+
var cached;
|
|
21
|
+
function parser() {
|
|
22
|
+
if (cached) return cached;
|
|
23
|
+
var Ctor = _require('markdown-it');
|
|
24
|
+
var footnote = _require('markdown-it-footnote');
|
|
25
|
+
var taskLists = _require('markdown-it-task-lists');
|
|
26
|
+
var md = new Ctor({
|
|
27
|
+
html: true,
|
|
28
|
+
linkify: true
|
|
29
|
+
}).use(footnote).use(taskLists);
|
|
30
|
+
// Fuzzy linking is what links www. domains and emails (the scheme matcher does neither); its
|
|
31
|
+
// bare-domain over-matching vs GFM is reined in at extraction, where the text is kept.
|
|
32
|
+
md.linkify.set({
|
|
33
|
+
fuzzyLink: true
|
|
34
|
+
});
|
|
35
|
+
md.core.ruler.disable('footnote_tail');
|
|
36
|
+
md.inline.ruler.disable('footnote_inline');
|
|
37
|
+
cached = md;
|
|
38
|
+
return cached;
|
|
39
|
+
}
|
|
40
|
+
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/parser.ts"],"sourcesContent":["import Module from 'node:module';\nimport type { MarkdownIt } from 'markdown-it';\nimport type footnotePlugin from 'markdown-it-footnote';\nimport type taskListsPlugin from 'markdown-it-task-lists';\n\n// Tier-2, as embed/static.ts: the parser's packages cost ~19 ms to load and a warm tree never\n// parses, so every store-opening command paid for them until a file actually changed.\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\n\n// The CJS build resolves markdown-it's export= types, so the constructor is named locally.\ntype Ctor = new (options?: { html?: boolean; linkify?: boolean }) => MarkdownIt;\n\nlet cached: MarkdownIt | undefined;\n\n// The one shared parser: html and linkify on, fuzzy links, footnotes and task lists, with the\n// footnote rules disabled for GFM parity (definitions stay spans; ^[...] stays inert text).\nexport function parser(): MarkdownIt {\n if (cached) return cached;\n const Ctor = _require('markdown-it') as Ctor;\n const footnote = _require('markdown-it-footnote') as typeof footnotePlugin;\n const taskLists = _require('markdown-it-task-lists') as typeof taskListsPlugin;\n const md = new Ctor({ html: true, linkify: true }).use(footnote).use(taskLists);\n // Fuzzy linking is what links www. domains and emails (the scheme matcher does neither); its\n // bare-domain over-matching vs GFM is reined in at extraction, where the text is kept.\n md.linkify.set({ fuzzyLink: true });\n md.core.ruler.disable('footnote_tail');\n md.inline.ruler.disable('footnote_inline');\n cached = md;\n return cached;\n}\n"],"names":["parser","_require","require","Module","createRequire","cached","Ctor","footnote","taskLists","md","html","linkify","use","set","fuzzyLink","core","ruler","disable","inline"],"mappings":";;;;+BAgBgBA;;;eAAAA;;;iEAhBG;;;;;;AAKnB,8FAA8F;AAC9F,sFAAsF;AACtF,IAAMC,WAAW,OAAOC,YAAY,cAAcC,mBAAM,CAACC,aAAa,CAAC,uDAAmBF;AAK1F,IAAIG;AAIG,SAASL;IACd,IAAIK,QAAQ,OAAOA;IACnB,IAAMC,OAAOL,SAAS;IACtB,IAAMM,WAAWN,SAAS;IAC1B,IAAMO,YAAYP,SAAS;IAC3B,IAAMQ,KAAK,IAAIH,KAAK;QAAEI,MAAM;QAAMC,SAAS;IAAK,GAAGC,GAAG,CAACL,UAAUK,GAAG,CAACJ;IACrE,6FAA6F;IAC7F,uFAAuF;IACvFC,GAAGE,OAAO,CAACE,GAAG,CAAC;QAAEC,WAAW;IAAK;IACjCL,GAAGM,IAAI,CAACC,KAAK,CAACC,OAAO,CAAC;IACtBR,GAAGS,MAAM,CAACF,KAAK,CAACC,OAAO,CAAC;IACxBZ,SAASI;IACT,OAAOJ;AACT"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Token } from 'markdown-it';
|
|
2
2
|
export type BlockType = 'heading' | 'paragraph' | 'code' | 'table' | 'list' | 'blockquote' | 'other';
|
|
3
3
|
export interface Block {
|
|
4
4
|
type: BlockType;
|
|
@@ -6,7 +6,7 @@ export interface Block {
|
|
|
6
6
|
endLine: number;
|
|
7
7
|
depth?: number;
|
|
8
8
|
text?: string;
|
|
9
|
-
node:
|
|
9
|
+
node: Token[];
|
|
10
10
|
}
|
|
11
11
|
export interface ChunkOptions {
|
|
12
12
|
targetTokens?: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Token } from 'markdown-it';
|
|
2
2
|
export type BlockType = 'heading' | 'paragraph' | 'code' | 'table' | 'list' | 'blockquote' | 'other';
|
|
3
3
|
export interface Block {
|
|
4
4
|
type: BlockType;
|
|
@@ -6,7 +6,7 @@ export interface Block {
|
|
|
6
6
|
endLine: number;
|
|
7
7
|
depth?: number;
|
|
8
8
|
text?: string;
|
|
9
|
-
node:
|
|
9
|
+
node: Token[];
|
|
10
10
|
}
|
|
11
11
|
export interface ChunkOptions {
|
|
12
12
|
targetTokens?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CHUNK_VERSION = "chunk:
|
|
1
|
+
export declare const CHUNK_VERSION = "chunk:v6";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CHUNK_VERSION = "chunk:
|
|
1
|
+
export declare const CHUNK_VERSION = "chunk:v6";
|
|
@@ -10,5 +10,5 @@ Object.defineProperty(exports, "CHUNK_VERSION", {
|
|
|
10
10
|
return CHUNK_VERSION;
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
|
-
var CHUNK_VERSION = 'chunk:
|
|
13
|
+
var CHUNK_VERSION = 'chunk:v6';
|
|
14
14
|
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/version.ts"],"sourcesContent":["// D8: bump whenever chunk semantics change (grouping, sizing, splitting); the digest in\n// test/unit/chunk/version.test.ts tracks EXTRACTION changes only, so the two move independently.\nexport const CHUNK_VERSION = 'chunk:
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/version.ts"],"sourcesContent":["// D8: bump whenever chunk semantics change (grouping, sizing, splitting); the digest in\n// test/unit/chunk/version.test.ts tracks EXTRACTION changes only, so the two move independently.\nexport const CHUNK_VERSION = 'chunk:v6';\n"],"names":["CHUNK_VERSION"],"mappings":"AAAA,wFAAwF;AACxF,iGAAiG;;;;;+BACpFA;;;eAAAA;;;AAAN,IAAMA,gBAAgB"}
|
|
@@ -508,45 +508,6 @@ function writeResolved(db, rows) {
|
|
|
508
508
|
});
|
|
509
509
|
})();
|
|
510
510
|
}
|
|
511
|
-
// A new or deleted file can change any note's resolution, so re-resolve the whole table.
|
|
512
|
-
// Fallback for cold builds and large deltas -- see afterReconcile's threshold.
|
|
513
|
-
function resolveAll(db, files) {
|
|
514
|
-
return _async_to_generator(function() {
|
|
515
|
-
var pathSet, byBase, stmt, rows, changed;
|
|
516
|
-
return _ts_generator(this, function(_state) {
|
|
517
|
-
switch(_state.label){
|
|
518
|
-
case 0:
|
|
519
|
-
pathSet = new Set(files.map(function(f) {
|
|
520
|
-
return f.relPath;
|
|
521
|
-
}));
|
|
522
|
-
byBase = buildByBase(files);
|
|
523
|
-
return [
|
|
524
|
-
4,
|
|
525
|
-
db.prepare('SELECT src, target, dst, embed FROM links')
|
|
526
|
-
];
|
|
527
|
-
case 1:
|
|
528
|
-
stmt = _state.sent();
|
|
529
|
-
return [
|
|
530
|
-
4,
|
|
531
|
-
stmt.all()
|
|
532
|
-
];
|
|
533
|
-
case 2:
|
|
534
|
-
rows = _state.sent();
|
|
535
|
-
changed = resolveRows(rows, pathSet, byBase);
|
|
536
|
-
return [
|
|
537
|
-
4,
|
|
538
|
-
writeResolved(db, changed)
|
|
539
|
-
];
|
|
540
|
-
case 3:
|
|
541
|
-
_state.sent();
|
|
542
|
-
return [
|
|
543
|
-
2,
|
|
544
|
-
changed.length > 0
|
|
545
|
-
];
|
|
546
|
-
}
|
|
547
|
-
});
|
|
548
|
-
})();
|
|
549
|
-
}
|
|
550
511
|
// Chunked so a large-but-under-threshold delta never exceeds SQLite's bound-variable limit
|
|
551
512
|
// (SQLITE_MAX_VARIABLE_NUMBER, 32766); harmless headroom on DuckDB, which has no such cap.
|
|
552
513
|
function selectIn(db, column, keys) {
|
|
@@ -757,8 +718,11 @@ function linkEdges(db) {
|
|
|
757
718
|
// Records whether remove()/store() deleted any link row, since afterReconcile runs after both
|
|
758
719
|
// and dstChanged alone misses the reparsed-to-zero-links case. Keyed on delta so state dies with it.
|
|
759
720
|
var removedWithLinks = new WeakMap();
|
|
760
|
-
//
|
|
761
|
-
//
|
|
721
|
+
// Cold build only: whether store() resolved at least one row to a non-null dst, so afterReconcile
|
|
722
|
+
// can report linksChanged without re-reading the table it just wrote.
|
|
723
|
+
var coldResolved = new WeakMap();
|
|
724
|
+
// dst stays NULL here on an incremental store (resolution runs afterward); a cold build resolves
|
|
725
|
+
// it inline in store() instead, through the *_RESOLVED column list and SQL below.
|
|
762
726
|
var LINK_COLUMNS = [
|
|
763
727
|
'src',
|
|
764
728
|
'target',
|
|
@@ -766,6 +730,14 @@ var LINK_COLUMNS = [
|
|
|
766
730
|
'embed'
|
|
767
731
|
];
|
|
768
732
|
var UPSERT_LINK_SQL = 'INSERT INTO links (src, target, target_base, dst, embed) VALUES (?, ?, ?, NULL, ?) ON CONFLICT(src, target, embed) DO UPDATE SET target_base = excluded.target_base';
|
|
733
|
+
var LINK_COLUMNS_RESOLVED = [
|
|
734
|
+
'src',
|
|
735
|
+
'target',
|
|
736
|
+
'target_base',
|
|
737
|
+
'dst',
|
|
738
|
+
'embed'
|
|
739
|
+
];
|
|
740
|
+
var UPSERT_LINK_SQL_RESOLVED = 'INSERT INTO links (src, target, target_base, dst, embed) VALUES (?, ?, ?, ?, ?) ON CONFLICT(src, target, embed) DO UPDATE SET target_base = excluded.target_base';
|
|
769
741
|
var links = {
|
|
770
742
|
name: 'links',
|
|
771
743
|
schema: function schema(db) {
|
|
@@ -840,7 +812,7 @@ var links = {
|
|
|
840
812
|
},
|
|
841
813
|
store: function store(db, docs, delta) {
|
|
842
814
|
return _async_to_generator(function() {
|
|
843
|
-
var byPath, addedSet, reparsedExisting, existingRows, staleRows, appendable, upsertRows, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, path, targets, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, _step_value1, target, embed,
|
|
815
|
+
var byPath, addedSet, reparsedExisting, existingRows, staleRows, cold, resolveNew, pathSet, byBase, resolvedLink, appendable, upsertRows, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, path, targets, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, _step_value1, target, embed, targetBase, dst;
|
|
844
816
|
return _ts_generator(this, function(_state) {
|
|
845
817
|
switch(_state.label){
|
|
846
818
|
case 0:
|
|
@@ -888,8 +860,21 @@ var links = {
|
|
|
888
860
|
removedWithLinks.set(delta, true);
|
|
889
861
|
_state.label = 3;
|
|
890
862
|
case 3:
|
|
891
|
-
//
|
|
892
|
-
//
|
|
863
|
+
// Cold build: every path is in `added`, so pathSet/byBase cover the same complete tree
|
|
864
|
+
// afterReconcile's large branch would otherwise re-derive; resolve dst here instead.
|
|
865
|
+
cold = delta.files.length === 0 || delta.added.length === delta.files.length;
|
|
866
|
+
if (cold) {
|
|
867
|
+
pathSet = new Set(delta.files.map(function(f) {
|
|
868
|
+
return f.relPath;
|
|
869
|
+
}));
|
|
870
|
+
byBase = buildByBase(delta.files);
|
|
871
|
+
resolveNew = function resolveNew(src, target) {
|
|
872
|
+
return resolveTarget(src, target, pathSet, byBase);
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
resolvedLink = false;
|
|
876
|
+
// Upsert preserves dst on surviving rows; a cold build resolves new rows, else they start NULL.
|
|
877
|
+
// A same-note anchor gets no target_base, so SQL's `IN` excludes it from resolveIncremental's lookup.
|
|
893
878
|
// Split, unlike the other features: this hook has no remove() pass behind it (see above), so
|
|
894
879
|
// only a path in `added` is guaranteed to have no row yet. The rest genuinely conflict and the
|
|
895
880
|
// upsert is what preserves their `dst`.
|
|
@@ -903,14 +888,34 @@ var links = {
|
|
|
903
888
|
try {
|
|
904
889
|
for(_iterator1 = targets[Symbol.iterator](); !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
905
890
|
_step_value1 = _step1.value, target = _step_value1.target, embed = _step_value1.embed;
|
|
906
|
-
|
|
891
|
+
targetBase = target.startsWith('#') ? null : baseKey(cleanTarget(target));
|
|
892
|
+
if (!addedSet.has(path)) {
|
|
893
|
+
upsertRows.push([
|
|
894
|
+
path,
|
|
895
|
+
target,
|
|
896
|
+
targetBase,
|
|
897
|
+
embed ? 1 : 0
|
|
898
|
+
]);
|
|
899
|
+
continue;
|
|
900
|
+
}
|
|
901
|
+
if (!resolveNew) {
|
|
902
|
+
appendable.push([
|
|
903
|
+
path,
|
|
904
|
+
target,
|
|
905
|
+
targetBase,
|
|
906
|
+
embed ? 1 : 0
|
|
907
|
+
]);
|
|
908
|
+
continue;
|
|
909
|
+
}
|
|
910
|
+
dst = resolveNew(path, target);
|
|
911
|
+
if (dst !== null) resolvedLink = true;
|
|
912
|
+
appendable.push([
|
|
907
913
|
path,
|
|
908
914
|
target,
|
|
909
|
-
|
|
915
|
+
targetBase,
|
|
916
|
+
dst,
|
|
910
917
|
embed ? 1 : 0
|
|
911
|
-
];
|
|
912
|
-
if (addedSet.has(path)) appendable.push(row);
|
|
913
|
-
else upsertRows.push(row);
|
|
918
|
+
]);
|
|
914
919
|
}
|
|
915
920
|
} catch (err) {
|
|
916
921
|
_didIteratorError1 = true;
|
|
@@ -943,7 +948,7 @@ var links = {
|
|
|
943
948
|
}
|
|
944
949
|
return [
|
|
945
950
|
4,
|
|
946
|
-
(0, _sharedts.appendRows)(db, 'links', LINK_COLUMNS, UPSERT_LINK_SQL, appendable)
|
|
951
|
+
(0, _sharedts.appendRows)(db, 'links', resolveNew ? LINK_COLUMNS_RESOLVED : LINK_COLUMNS, resolveNew ? UPSERT_LINK_SQL_RESOLVED : UPSERT_LINK_SQL, appendable)
|
|
947
952
|
];
|
|
948
953
|
case 4:
|
|
949
954
|
_state.sent();
|
|
@@ -959,6 +964,7 @@ var links = {
|
|
|
959
964
|
_state.sent();
|
|
960
965
|
_state.label = 6;
|
|
961
966
|
case 6:
|
|
967
|
+
if (cold) coldResolved.set(delta, resolvedLink);
|
|
962
968
|
return [
|
|
963
969
|
2
|
|
964
970
|
];
|
|
@@ -968,7 +974,7 @@ var links = {
|
|
|
968
974
|
},
|
|
969
975
|
afterReconcile: function afterReconcile(db, delta) {
|
|
970
976
|
return _async_to_generator(function() {
|
|
971
|
-
var _removedWithLinks_get, removeHadLinks, large,
|
|
977
|
+
var _removedWithLinks_get, removeHadLinks, large, _coldResolved_get, dstChanged;
|
|
972
978
|
return _ts_generator(this, function(_state) {
|
|
973
979
|
switch(_state.label){
|
|
974
980
|
case 0:
|
|
@@ -978,30 +984,20 @@ var links = {
|
|
|
978
984
|
// A cold build is the only case a full pass wins. Measured 2026-09-01 on 6,566 notes, resolve
|
|
979
985
|
// time alone: full is flat near 90ms at any churn, incremental 7ms at 10 files and 30ms at 2,000.
|
|
980
986
|
large = delta.files.length === 0 || delta.added.length === delta.files.length;
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
case 1:
|
|
990
|
-
_tmp = _state.sent();
|
|
991
|
-
return [
|
|
992
|
-
3,
|
|
993
|
-
4
|
|
994
|
-
];
|
|
995
|
-
case 2:
|
|
987
|
+
// store() already resolved dst inline on this cold build (same test), so nothing is left to update.
|
|
988
|
+
if (large) {
|
|
989
|
+
;
|
|
990
|
+
delta.linksChanged = ((_coldResolved_get = coldResolved.get(delta)) !== null && _coldResolved_get !== void 0 ? _coldResolved_get : false) || removeHadLinks;
|
|
991
|
+
return [
|
|
992
|
+
2
|
|
993
|
+
];
|
|
994
|
+
}
|
|
996
995
|
return [
|
|
997
996
|
4,
|
|
998
997
|
resolveIncremental(db, delta)
|
|
999
998
|
];
|
|
1000
|
-
case
|
|
1001
|
-
|
|
1002
|
-
_state.label = 4;
|
|
1003
|
-
case 4:
|
|
1004
|
-
dstChanged = _tmp;
|
|
999
|
+
case 1:
|
|
1000
|
+
dstChanged = _state.sent();
|
|
1005
1001
|
delta.linksChanged = dstChanged || removeHadLinks;
|
|
1006
1002
|
return [
|
|
1007
1003
|
2
|