sensemaking 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/chunk/extract.d.cts +2 -0
  3. package/dist/cjs/chunk/extract.d.ts +2 -0
  4. package/dist/cjs/chunk/extract.js +139 -0
  5. package/dist/cjs/chunk/extract.js.map +1 -0
  6. package/dist/cjs/chunk/group.d.cts +4 -0
  7. package/dist/cjs/chunk/group.d.ts +4 -0
  8. package/dist/cjs/chunk/group.js +489 -0
  9. package/dist/cjs/chunk/group.js.map +1 -0
  10. package/dist/cjs/chunk/index.d.cts +8 -0
  11. package/dist/cjs/chunk/index.d.ts +8 -0
  12. package/dist/cjs/chunk/index.js +44 -0
  13. package/dist/cjs/chunk/index.js.map +1 -0
  14. package/dist/cjs/chunk/parse.d.cts +2 -0
  15. package/dist/cjs/chunk/parse.d.ts +2 -0
  16. package/dist/cjs/chunk/parse.js +71 -0
  17. package/dist/cjs/chunk/parse.js.map +1 -0
  18. package/dist/cjs/chunk/types.d.cts +19 -0
  19. package/dist/cjs/chunk/types.d.ts +19 -0
  20. package/dist/cjs/chunk/types.js +5 -0
  21. package/dist/cjs/chunk/types.js.map +1 -0
  22. package/dist/cjs/chunk/version.d.cts +1 -0
  23. package/dist/cjs/chunk/version.d.ts +1 -0
  24. package/dist/cjs/chunk/version.js +14 -0
  25. package/dist/cjs/chunk/version.js.map +1 -0
  26. package/dist/cjs/cli/map.js +1 -1
  27. package/dist/cjs/cli/map.js.map +1 -1
  28. package/dist/cjs/cli/named.js +1 -1
  29. package/dist/cjs/cli/named.js.map +1 -1
  30. package/dist/cjs/cli/path.js +2 -2
  31. package/dist/cjs/cli/path.js.map +1 -1
  32. package/dist/cjs/cli/peek.js +1 -1
  33. package/dist/cjs/cli/peek.js.map +1 -1
  34. package/dist/cjs/cli/related.js +1 -1
  35. package/dist/cjs/cli/related.js.map +1 -1
  36. package/dist/cjs/cli/search.js +1 -1
  37. package/dist/cjs/cli/search.js.map +1 -1
  38. package/dist/cjs/cli/shared.d.cts +1 -1
  39. package/dist/cjs/cli/shared.d.ts +1 -1
  40. package/dist/cjs/cli/shared.js +3 -3
  41. package/dist/cjs/cli/shared.js.map +1 -1
  42. package/dist/cjs/cli/status.js +1 -1
  43. package/dist/cjs/cli/status.js.map +1 -1
  44. package/dist/cjs/commands/map.d.cts +1 -1
  45. package/dist/cjs/commands/map.d.ts +1 -1
  46. package/dist/cjs/commands/map.js.map +1 -1
  47. package/dist/cjs/commands/peek.d.cts +1 -1
  48. package/dist/cjs/commands/peek.d.ts +1 -1
  49. package/dist/cjs/commands/peek.js +13 -6
  50. package/dist/cjs/commands/peek.js.map +1 -1
  51. package/dist/cjs/commands/scope.js +1 -1
  52. package/dist/cjs/commands/scope.js.map +1 -1
  53. package/dist/cjs/commands/search.d.cts +1 -1
  54. package/dist/cjs/commands/search.d.ts +1 -1
  55. package/dist/cjs/commands/search.js +3 -3
  56. package/dist/cjs/commands/search.js.map +1 -1
  57. package/dist/cjs/commands/signals.js +1 -1
  58. package/dist/cjs/commands/signals.js.map +1 -1
  59. package/dist/cjs/config/access.d.cts +3 -1
  60. package/dist/cjs/config/access.d.ts +3 -1
  61. package/dist/cjs/config/access.js +11 -11
  62. package/dist/cjs/config/access.js.map +1 -1
  63. package/dist/cjs/config/index.d.cts +1 -0
  64. package/dist/cjs/config/index.d.ts +1 -0
  65. package/dist/cjs/config/index.js +4 -0
  66. package/dist/cjs/config/index.js.map +1 -1
  67. package/dist/cjs/config/types.d.cts +1 -0
  68. package/dist/cjs/config/types.d.ts +1 -0
  69. package/dist/cjs/config/types.js.map +1 -1
  70. package/dist/cjs/config/validate.d.cts +1 -0
  71. package/dist/cjs/config/validate.d.ts +1 -0
  72. package/dist/cjs/config/validate.js +8 -1
  73. package/dist/cjs/config/validate.js.map +1 -1
  74. package/dist/cjs/db/open.d.cts +1 -1
  75. package/dist/cjs/db/open.d.ts +1 -1
  76. package/dist/cjs/db/open.js +4 -4
  77. package/dist/cjs/db/open.js.map +1 -1
  78. package/dist/cjs/db/reconcile.js +8 -8
  79. package/dist/cjs/db/reconcile.js.map +1 -1
  80. package/dist/cjs/{sql-functions.js → db/sql-functions.js} +1 -1
  81. package/dist/cjs/db/sql-functions.js.map +1 -0
  82. package/dist/cjs/embed/langfit.js +45 -85
  83. package/dist/cjs/embed/langfit.js.map +1 -1
  84. package/dist/cjs/embed/languages.js.map +1 -1
  85. package/dist/cjs/embed/query.js +6 -6
  86. package/dist/cjs/embed/query.js.map +1 -1
  87. package/dist/cjs/embed/static.js +3 -40
  88. package/dist/cjs/embed/static.js.map +1 -1
  89. package/dist/cjs/features/embed.d.cts +2 -5
  90. package/dist/cjs/features/embed.d.ts +2 -5
  91. package/dist/cjs/features/embed.js +36 -58
  92. package/dist/cjs/features/embed.js.map +1 -1
  93. package/dist/cjs/{fences.js → features/fences.js} +1 -1
  94. package/dist/cjs/features/fences.js.map +1 -0
  95. package/dist/cjs/features/links.js +1 -1
  96. package/dist/cjs/features/links.js.map +1 -1
  97. package/dist/cjs/features/rank.js +1 -1
  98. package/dist/cjs/features/rank.js.map +1 -1
  99. package/dist/cjs/features/sections.js +4 -3
  100. package/dist/cjs/features/sections.js.map +1 -1
  101. package/dist/cjs/features/tags.js +1 -1
  102. package/dist/cjs/features/tags.js.map +1 -1
  103. package/dist/cjs/features/types.d.cts +4 -2
  104. package/dist/cjs/features/types.d.ts +4 -2
  105. package/dist/cjs/graph/graph.js.map +1 -0
  106. package/dist/cjs/graph/traverse.js.map +1 -0
  107. package/dist/cjs/index.d.cts +4 -4
  108. package/dist/cjs/index.d.ts +4 -4
  109. package/dist/cjs/index.js +4 -1
  110. package/dist/cjs/index.js.map +1 -1
  111. package/dist/cjs/output/column-hint.js.map +1 -0
  112. package/dist/cjs/output/output.js.map +1 -0
  113. package/dist/cjs/output/progress.js.map +1 -0
  114. package/dist/cjs/{search-error.js → output/search-error.js} +1 -1
  115. package/dist/cjs/output/search-error.js.map +1 -0
  116. package/dist/cjs/scan/frontmatter.d.cts +13 -0
  117. package/dist/cjs/scan/frontmatter.d.ts +13 -0
  118. package/dist/cjs/scan/frontmatter.js +229 -0
  119. package/dist/cjs/scan/frontmatter.js.map +1 -0
  120. package/dist/cjs/scan/index.d.cts +25 -0
  121. package/dist/cjs/scan/index.d.ts +25 -0
  122. package/dist/cjs/scan/index.js +107 -0
  123. package/dist/cjs/scan/index.js.map +1 -0
  124. package/dist/cjs/scan/list.d.cts +12 -0
  125. package/dist/cjs/scan/list.d.ts +12 -0
  126. package/dist/cjs/scan/list.js +154 -0
  127. package/dist/cjs/scan/list.js.map +1 -0
  128. package/dist/cjs/text/segment.d.cts +3 -0
  129. package/dist/cjs/text/segment.d.ts +3 -0
  130. package/dist/cjs/{segment.js → text/segment.js} +17 -14
  131. package/dist/cjs/text/segment.js.map +1 -0
  132. package/dist/cjs/text/strip.d.cts +3 -0
  133. package/dist/cjs/text/strip.d.ts +3 -0
  134. package/dist/cjs/text/strip.js +32 -0
  135. package/dist/cjs/text/strip.js.map +1 -0
  136. package/dist/esm/chunk/extract.d.ts +2 -0
  137. package/dist/esm/chunk/extract.js +114 -0
  138. package/dist/esm/chunk/extract.js.map +1 -0
  139. package/dist/esm/chunk/group.d.ts +4 -0
  140. package/dist/esm/chunk/group.js +253 -0
  141. package/dist/esm/chunk/group.js.map +1 -0
  142. package/dist/esm/chunk/index.d.ts +8 -0
  143. package/dist/esm/chunk/index.js +16 -0
  144. package/dist/esm/chunk/index.js.map +1 -0
  145. package/dist/esm/chunk/parse.d.ts +2 -0
  146. package/dist/esm/chunk/parse.js +63 -0
  147. package/dist/esm/chunk/parse.js.map +1 -0
  148. package/dist/esm/chunk/types.d.ts +19 -0
  149. package/dist/esm/chunk/types.js +2 -0
  150. package/dist/esm/chunk/types.js.map +1 -0
  151. package/dist/esm/chunk/version.d.ts +1 -0
  152. package/dist/esm/chunk/version.js +3 -0
  153. package/dist/esm/chunk/version.js.map +1 -0
  154. package/dist/esm/cli/map.js +1 -1
  155. package/dist/esm/cli/map.js.map +1 -1
  156. package/dist/esm/cli/named.js +1 -1
  157. package/dist/esm/cli/named.js.map +1 -1
  158. package/dist/esm/cli/path.js +2 -2
  159. package/dist/esm/cli/path.js.map +1 -1
  160. package/dist/esm/cli/peek.js +1 -1
  161. package/dist/esm/cli/peek.js.map +1 -1
  162. package/dist/esm/cli/related.js +1 -1
  163. package/dist/esm/cli/related.js.map +1 -1
  164. package/dist/esm/cli/search.js +1 -1
  165. package/dist/esm/cli/search.js.map +1 -1
  166. package/dist/esm/cli/shared.d.ts +1 -1
  167. package/dist/esm/cli/shared.js +3 -3
  168. package/dist/esm/cli/shared.js.map +1 -1
  169. package/dist/esm/cli/status.js +1 -1
  170. package/dist/esm/cli/status.js.map +1 -1
  171. package/dist/esm/commands/map.d.ts +1 -1
  172. package/dist/esm/commands/map.js.map +1 -1
  173. package/dist/esm/commands/peek.d.ts +1 -1
  174. package/dist/esm/commands/peek.js +8 -1
  175. package/dist/esm/commands/peek.js.map +1 -1
  176. package/dist/esm/commands/scope.js +1 -1
  177. package/dist/esm/commands/scope.js.map +1 -1
  178. package/dist/esm/commands/search.d.ts +1 -1
  179. package/dist/esm/commands/search.js +3 -3
  180. package/dist/esm/commands/search.js.map +1 -1
  181. package/dist/esm/commands/signals.js +1 -1
  182. package/dist/esm/commands/signals.js.map +1 -1
  183. package/dist/esm/config/access.d.ts +3 -1
  184. package/dist/esm/config/access.js +9 -9
  185. package/dist/esm/config/access.js.map +1 -1
  186. package/dist/esm/config/index.d.ts +1 -0
  187. package/dist/esm/config/index.js +1 -0
  188. package/dist/esm/config/index.js.map +1 -1
  189. package/dist/esm/config/types.d.ts +1 -0
  190. package/dist/esm/config/types.js.map +1 -1
  191. package/dist/esm/config/validate.d.ts +1 -0
  192. package/dist/esm/config/validate.js +8 -2
  193. package/dist/esm/config/validate.js.map +1 -1
  194. package/dist/esm/db/open.d.ts +1 -1
  195. package/dist/esm/db/open.js +5 -5
  196. package/dist/esm/db/open.js.map +1 -1
  197. package/dist/esm/db/reconcile.js +4 -4
  198. package/dist/esm/db/reconcile.js.map +1 -1
  199. package/dist/esm/{sql-functions.js → db/sql-functions.js} +1 -1
  200. package/dist/esm/db/sql-functions.js.map +1 -0
  201. package/dist/esm/embed/langfit.js +3 -3
  202. package/dist/esm/embed/langfit.js.map +1 -1
  203. package/dist/esm/embed/languages.js.map +1 -1
  204. package/dist/esm/embed/query.js +5 -5
  205. package/dist/esm/embed/query.js.map +1 -1
  206. package/dist/esm/embed/static.js +1 -2
  207. package/dist/esm/embed/static.js.map +1 -1
  208. package/dist/esm/features/embed.d.ts +2 -5
  209. package/dist/esm/features/embed.js +34 -32
  210. package/dist/esm/features/embed.js.map +1 -1
  211. package/dist/esm/{fences.js → features/fences.js} +1 -1
  212. package/dist/esm/features/fences.js.map +1 -0
  213. package/dist/esm/features/links.js +1 -1
  214. package/dist/esm/features/links.js.map +1 -1
  215. package/dist/esm/features/rank.js +1 -1
  216. package/dist/esm/features/rank.js.map +1 -1
  217. package/dist/esm/features/sections.js +4 -3
  218. package/dist/esm/features/sections.js.map +1 -1
  219. package/dist/esm/features/tags.js +1 -1
  220. package/dist/esm/features/tags.js.map +1 -1
  221. package/dist/esm/features/types.d.ts +4 -2
  222. package/dist/esm/features/types.js.map +1 -1
  223. package/dist/esm/graph/graph.js.map +1 -0
  224. package/dist/esm/graph/traverse.js.map +1 -0
  225. package/dist/esm/index.d.ts +4 -4
  226. package/dist/esm/index.js +2 -2
  227. package/dist/esm/index.js.map +1 -1
  228. package/dist/esm/output/column-hint.js.map +1 -0
  229. package/dist/esm/output/output.js.map +1 -0
  230. package/dist/esm/output/progress.js.map +1 -0
  231. package/dist/esm/{search-error.js → output/search-error.js} +1 -1
  232. package/dist/esm/output/search-error.js.map +1 -0
  233. package/dist/esm/scan/frontmatter.d.ts +13 -0
  234. package/dist/esm/{scan.js → scan/frontmatter.js} +4 -123
  235. package/dist/esm/scan/frontmatter.js.map +1 -0
  236. package/dist/esm/scan/index.d.ts +25 -0
  237. package/dist/esm/scan/index.js +58 -0
  238. package/dist/esm/scan/index.js.map +1 -0
  239. package/dist/esm/scan/list.d.ts +12 -0
  240. package/dist/esm/scan/list.js +58 -0
  241. package/dist/esm/scan/list.js.map +1 -0
  242. package/dist/esm/text/segment.d.ts +3 -0
  243. package/dist/esm/{segment.js → text/segment.js} +3 -3
  244. package/dist/esm/text/segment.js.map +1 -0
  245. package/dist/esm/text/strip.d.ts +3 -0
  246. package/dist/esm/text/strip.js +12 -0
  247. package/dist/esm/text/strip.js.map +1 -0
  248. package/package.json +15 -2
  249. package/schema.json +8 -1
  250. package/skills/sense/SKILL.md +1 -1
  251. package/skills/sense-setup/SKILL.md +3 -3
  252. package/dist/cjs/column-hint.js.map +0 -1
  253. package/dist/cjs/fences.js.map +0 -1
  254. package/dist/cjs/graph.js.map +0 -1
  255. package/dist/cjs/output.js.map +0 -1
  256. package/dist/cjs/progress.js.map +0 -1
  257. package/dist/cjs/scan.d.cts +0 -35
  258. package/dist/cjs/scan.d.ts +0 -35
  259. package/dist/cjs/scan.js +0 -436
  260. package/dist/cjs/scan.js.map +0 -1
  261. package/dist/cjs/search-error.js.map +0 -1
  262. package/dist/cjs/segment.d.cts +0 -2
  263. package/dist/cjs/segment.d.ts +0 -2
  264. package/dist/cjs/segment.js.map +0 -1
  265. package/dist/cjs/sql-functions.js.map +0 -1
  266. package/dist/cjs/traverse.js.map +0 -1
  267. package/dist/esm/column-hint.js.map +0 -1
  268. package/dist/esm/fences.js.map +0 -1
  269. package/dist/esm/graph.js.map +0 -1
  270. package/dist/esm/output.js.map +0 -1
  271. package/dist/esm/progress.js.map +0 -1
  272. package/dist/esm/scan.d.ts +0 -35
  273. package/dist/esm/scan.js.map +0 -1
  274. package/dist/esm/search-error.js.map +0 -1
  275. package/dist/esm/segment.d.ts +0 -2
  276. package/dist/esm/segment.js.map +0 -1
  277. package/dist/esm/sql-functions.js.map +0 -1
  278. package/dist/esm/traverse.js.map +0 -1
  279. /package/dist/cjs/{sql-functions.d.cts → db/sql-functions.d.cts} +0 -0
  280. /package/dist/cjs/{sql-functions.d.ts → db/sql-functions.d.ts} +0 -0
  281. /package/dist/cjs/{fences.d.cts → features/fences.d.cts} +0 -0
  282. /package/dist/cjs/{fences.d.ts → features/fences.d.ts} +0 -0
  283. /package/dist/cjs/{graph.d.cts → graph/graph.d.cts} +0 -0
  284. /package/dist/cjs/{graph.d.ts → graph/graph.d.ts} +0 -0
  285. /package/dist/cjs/{graph.js → graph/graph.js} +0 -0
  286. /package/dist/cjs/{traverse.d.cts → graph/traverse.d.cts} +0 -0
  287. /package/dist/cjs/{traverse.d.ts → graph/traverse.d.ts} +0 -0
  288. /package/dist/cjs/{traverse.js → graph/traverse.js} +0 -0
  289. /package/dist/cjs/{column-hint.d.cts → output/column-hint.d.cts} +0 -0
  290. /package/dist/cjs/{column-hint.d.ts → output/column-hint.d.ts} +0 -0
  291. /package/dist/cjs/{column-hint.js → output/column-hint.js} +0 -0
  292. /package/dist/cjs/{output.d.cts → output/output.d.cts} +0 -0
  293. /package/dist/cjs/{output.d.ts → output/output.d.ts} +0 -0
  294. /package/dist/cjs/{output.js → output/output.js} +0 -0
  295. /package/dist/cjs/{progress.d.cts → output/progress.d.cts} +0 -0
  296. /package/dist/cjs/{progress.d.ts → output/progress.d.ts} +0 -0
  297. /package/dist/cjs/{progress.js → output/progress.js} +0 -0
  298. /package/dist/cjs/{search-error.d.cts → output/search-error.d.cts} +0 -0
  299. /package/dist/cjs/{search-error.d.ts → output/search-error.d.ts} +0 -0
  300. /package/dist/esm/{sql-functions.d.ts → db/sql-functions.d.ts} +0 -0
  301. /package/dist/esm/{fences.d.ts → features/fences.d.ts} +0 -0
  302. /package/dist/esm/{graph.d.ts → graph/graph.d.ts} +0 -0
  303. /package/dist/esm/{graph.js → graph/graph.js} +0 -0
  304. /package/dist/esm/{traverse.d.ts → graph/traverse.d.ts} +0 -0
  305. /package/dist/esm/{traverse.js → graph/traverse.js} +0 -0
  306. /package/dist/esm/{column-hint.d.ts → output/column-hint.d.ts} +0 -0
  307. /package/dist/esm/{column-hint.js → output/column-hint.js} +0 -0
  308. /package/dist/esm/{output.d.ts → output/output.d.ts} +0 -0
  309. /package/dist/esm/{output.js → output/output.js} +0 -0
  310. /package/dist/esm/{progress.d.ts → output/progress.d.ts} +0 -0
  311. /package/dist/esm/{progress.js → output/progress.js} +0 -0
  312. /package/dist/esm/{search-error.d.ts → output/search-error.d.ts} +0 -0
@@ -0,0 +1,253 @@
1
+ import { UNSPACED_SCRIPTS } from '../text/segment.js';
2
+ import { extractText } from './extract.js';
3
+ import { parse } from './parse.js';
4
+ export const DEFAULT_TARGET_TOKENS = 500;
5
+ const PGC_GROUP_SIZE = 2;
6
+ const OVERSIZE_TRIGGER_MULTIPLE = 2;
7
+ // D5: segment.ts's unspaced-script set packs close to one token per character; Hangul is
8
+ // spaced but still token-dense, added here as a conservative bound (one Unicode set, one home).
9
+ const DENSE_SCRIPT = new RegExp(`[${UNSPACED_SCRIPTS}\\p{scx=Hangul}]`, 'u');
10
+ // D5's size estimate: dense-script graphemes 1:1, everything else at 4 chars/token.
11
+ export function estimateTokens(text) {
12
+ let dense = 0;
13
+ let other = 0;
14
+ for (const ch of text){
15
+ if (DENSE_SCRIPT.test(ch)) dense++;
16
+ else other++;
17
+ }
18
+ return dense + other / 4;
19
+ }
20
+ function resolveOptions(opts) {
21
+ var _ref, _ref1;
22
+ return {
23
+ targetTokens: (_ref = opts === null || opts === void 0 ? void 0 : opts.targetTokens) !== null && _ref !== void 0 ? _ref : DEFAULT_TARGET_TOKENS,
24
+ text: (_ref1 = opts === null || opts === void 0 ? void 0 : opts.text) !== null && _ref1 !== void 0 ? _ref1 : 'raw'
25
+ };
26
+ }
27
+ // A heading of any depth ends the current scope and starts a new one (D1); the heading block
28
+ // itself is carried into the new scope, where it joins that scope's first group (F7/F10).
29
+ function splitScopes(blocks) {
30
+ const scopes = [];
31
+ let current = [];
32
+ for (const block of blocks){
33
+ if (block.type === 'heading' && current.length > 0) {
34
+ scopes.push(current);
35
+ current = [];
36
+ }
37
+ current.push(block);
38
+ }
39
+ if (current.length > 0) scopes.push(current);
40
+ return scopes;
41
+ }
42
+ function finalize(parts) {
43
+ if (parts.length === 0) return undefined;
44
+ const first = parts[0];
45
+ const last = parts[parts.length - 1];
46
+ return {
47
+ startLine: first.startLine,
48
+ endLine: last.endLine,
49
+ text: parts.map((p)=>p.text).join('\n'),
50
+ final: parts.some((p)=>p.final)
51
+ };
52
+ }
53
+ const NEWLINE_TOKENS = estimateTokens('\n');
54
+ const SENTENCE_SEGMENTER = new Intl.Segmenter(undefined, {
55
+ granularity: 'sentence'
56
+ });
57
+ const WORD_SEGMENTER = new Intl.Segmenter(undefined, {
58
+ granularity: 'word'
59
+ });
60
+ function segmentsOf(text, segmenter) {
61
+ return Array.from(segmenter.segment(text), (s)=>s.segment);
62
+ }
63
+ // Greedily packs segments (already contiguous, tiling the source text with no gaps) into groups
64
+ // of at most `working` estimated tokens; a lone segment over `working` still stands alone.
65
+ function pack(segments, working) {
66
+ const groups = [];
67
+ let current = '';
68
+ let tokens = 0;
69
+ for (const segment of segments){
70
+ const segmentTokens = estimateTokens(segment);
71
+ if (current.length > 0 && tokens + segmentTokens > working) {
72
+ groups.push(current);
73
+ current = '';
74
+ tokens = 0;
75
+ }
76
+ current += segment;
77
+ tokens += segmentTokens;
78
+ }
79
+ if (current.length > 0) groups.push(current);
80
+ return groups;
81
+ }
82
+ // A single line's text, still over working after rule 5's line-split can't reduce a lone line
83
+ // (the CJK case, one sentence-dense line with no newlines), falls back to Intl.Segmenter sentence
84
+ // boundaries, then word boundaries for any one sentence still over working. Never splits inside a
85
+ // grapheme either way (both are ECMA-402, the same proven component segment.ts uses for
86
+ // graphemes). Mode-agnostic: the caller decides whether `text` is the raw line or its extracted
87
+ // flavor -- this only packs whatever text it is given.
88
+ function splitLineText(text, working) {
89
+ const sentences = segmentsOf(text, SENTENCE_SEGMENTER);
90
+ const out = [];
91
+ let current = '';
92
+ let tokens = 0;
93
+ const flush = ()=>{
94
+ if (current.length > 0) {
95
+ out.push(current);
96
+ current = '';
97
+ tokens = 0;
98
+ }
99
+ };
100
+ for (const sentence of sentences){
101
+ const sentenceTokens = estimateTokens(sentence);
102
+ if (sentenceTokens > working) {
103
+ flush();
104
+ out.push(...pack(segmentsOf(sentence, WORD_SEGMENTER), working));
105
+ continue;
106
+ }
107
+ if (current.length > 0 && tokens + sentenceTokens > working) flush();
108
+ current += sentence;
109
+ tokens += sentenceTokens;
110
+ }
111
+ flush();
112
+ return out;
113
+ }
114
+ const ATOMIC_TYPES = new Set([
115
+ 'code',
116
+ 'table',
117
+ 'list'
118
+ ]);
119
+ // An atomic block's (code/table/list) piece is always a raw line slice: re-parsing a table's
120
+ // later pieces without their header/delimiter rows demotes them to paragraph text. A non-atomic
121
+ // piece is a raw line slice too when raw mode requested it; extracted mode re-parses and resolves
122
+ // flavor as before.
123
+ function piece(pieceLines, startLine, endLine, blockType, textMode) {
124
+ const text = ATOMIC_TYPES.has(blockType) || textMode === 'raw' ? pieceLines.join('\n') : parse(pieceLines.join('\n')).map((b)=>extractText(b.node)).join('\n');
125
+ return {
126
+ startLine,
127
+ endLine,
128
+ text
129
+ };
130
+ }
131
+ // A piece over working size that came from exactly one source line cannot be reduced by another
132
+ // line-boundary pass (rule 5's gap); it is sliced instead, at sentence then word boundaries, over
133
+ // the mode-resolved text piece() already produced -- so raw mode packs the raw line and extracted
134
+ // mode packs its flavor-resolved text. Extents collapse to that one line for every sub-piece (F5:
135
+ // re-derivation is by index over chunk()'s own deterministic output, not by a unique line range
136
+ // per piece); `final` flags each sub-piece so group() knows not to re-derive its text from that
137
+ // shared extent.
138
+ function finalizePiece(pieceLines, startLine, endLine, working, blockType, textMode) {
139
+ const p = piece(pieceLines, startLine, endLine, blockType, textMode);
140
+ if (pieceLines.length === 1 && estimateTokens(p.text) > working) {
141
+ return splitLineText(p.text, working).map((text)=>({
142
+ startLine,
143
+ endLine,
144
+ text,
145
+ final: true
146
+ }));
147
+ }
148
+ return [
149
+ p
150
+ ];
151
+ }
152
+ // A block over 2x working size splits at line boundaries into pieces each <= working size,
153
+ // never mid-line. `seed`: pending tokens (a heading) the first piece must join, checked against
154
+ // the limit too.
155
+ function splitOversizeBlock(lines, startLine, endLine, working, blockType, textMode, seed = 0) {
156
+ const pieces = [];
157
+ let pieceLines = [];
158
+ let pieceStart = startLine;
159
+ let tokens = seed;
160
+ for(let line = startLine; line <= endLine; line++){
161
+ const lineText = lines[line - 1];
162
+ const sep = pieceLines.length > 0 || tokens > 0 ? NEWLINE_TOKENS : 0;
163
+ const lineTokens = estimateTokens(lineText);
164
+ if (pieceLines.length > 0 && tokens + sep + lineTokens > working) {
165
+ pieces.push(...finalizePiece(pieceLines, pieceStart, line - 1, working, blockType, textMode));
166
+ pieceLines = [];
167
+ tokens = 0;
168
+ pieceStart = line;
169
+ pieceLines.push(lineText);
170
+ tokens += lineTokens;
171
+ continue;
172
+ }
173
+ pieceLines.push(lineText);
174
+ tokens += sep + lineTokens;
175
+ }
176
+ if (pieceLines.length > 0) pieces.push(...finalizePiece(pieceLines, pieceStart, endLine, working, blockType, textMode));
177
+ return pieces;
178
+ }
179
+ // One heading scope's groups (D1): a heading opens the first group, and an oversize block
180
+ // (rule 5, including an oversize heading) splits into pieces that each close their own group.
181
+ function groupScope(scopeBlocks, lines, resolved) {
182
+ const working = resolved.targetTokens;
183
+ const trigger = working * OVERSIZE_TRIGGER_MULTIPLE;
184
+ const finished = [];
185
+ let parts = [];
186
+ let paragraphCount = 0;
187
+ let tokens = 0;
188
+ function close() {
189
+ const group = finalize(parts);
190
+ if (group) finished.push(group);
191
+ parts = [];
192
+ paragraphCount = 0;
193
+ tokens = 0;
194
+ }
195
+ // tokens tracks the active text mode's own estimate (a newline between parts costs
196
+ // NEWLINE_TOKENS too), so packing decisions size the text the chunk will actually ship as.
197
+ function addPart(text, sizeText, startLine, endLine) {
198
+ tokens += (parts.length > 0 ? NEWLINE_TOKENS : 0) + estimateTokens(sizeText);
199
+ parts.push({
200
+ startLine,
201
+ endLine,
202
+ text
203
+ });
204
+ }
205
+ for (const block of scopeBlocks){
206
+ const raw = lines.slice(block.startLine - 1, block.endLine).join('\n');
207
+ const blockTokens = estimateTokens(raw);
208
+ if (blockTokens > trigger) {
209
+ const seed = parts.length > 0 ? tokens : 0;
210
+ for (const p of splitOversizeBlock(lines, block.startLine, block.endLine, working, block.type, resolved.text, seed)){
211
+ parts.push(p);
212
+ close();
213
+ }
214
+ continue;
215
+ }
216
+ const extracted = extractText(block.node);
217
+ const sizeText = resolved.text === 'raw' ? raw : extracted;
218
+ if (block.type === 'heading') {
219
+ addPart(extracted, sizeText, block.startLine, block.endLine);
220
+ continue;
221
+ }
222
+ // The 2x-working invariant holds even under pgc's paper-faithful 2-paragraph pairing --
223
+ // close first if the pair about to form would cross it.
224
+ const pairOversize = parts.length > 0 && tokens + NEWLINE_TOKENS + blockTokens > trigger;
225
+ if (pairOversize) close();
226
+ addPart(extracted, sizeText, block.startLine, block.endLine);
227
+ paragraphCount++;
228
+ if (paragraphCount >= PGC_GROUP_SIZE) close();
229
+ }
230
+ close();
231
+ return finished;
232
+ }
233
+ // Groups already-parsed blocks per opts (D1/D3), against the same body the blocks were parsed
234
+ // from (line lookups for oversize splitting).
235
+ export function group(blocks, body, opts) {
236
+ const resolved = resolveOptions(opts);
237
+ const lines = body.split('\n');
238
+ const chunks = [];
239
+ for (const scope of splitScopes(blocks))chunks.push(...groupScope(scope, lines, resolved));
240
+ // 'raw': the chunk's own source lines verbatim, replacing the flavor-resolved join above (D9).
241
+ // A `final` chunk (a sub-line split) already carries its own slice's raw text -- re-slicing by
242
+ // extent would return the whole shared source line instead, once per sub-piece.
243
+ const texted = resolved.text === 'raw' ? chunks.map((c)=>c.final ? c : {
244
+ ...c,
245
+ text: lines.slice(c.startLine - 1, c.endLine).join('\n').trim()
246
+ }) : chunks;
247
+ // A group can be all-blank (flavor-stripped to nothing, or a raw slice of pure syntax); it never produces a chunk.
248
+ return texted.filter((c)=>c.text.trim().length > 0).map((c)=>({
249
+ startLine: c.startLine,
250
+ endLine: c.endLine,
251
+ text: c.text
252
+ }));
253
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/group.ts"],"sourcesContent":["import { UNSPACED_SCRIPTS } from '../text/segment.ts';\nimport { extractText } from './extract.ts';\nimport { parse } from './parse.ts';\nimport type { Block, BlockType, Chunk, ChunkOptions } from './types.ts';\n\nexport const DEFAULT_TARGET_TOKENS = 500;\nconst PGC_GROUP_SIZE = 2;\nconst OVERSIZE_TRIGGER_MULTIPLE = 2;\n\n// D5: segment.ts's unspaced-script set packs close to one token per character; Hangul is\n// spaced but still token-dense, added here as a conservative bound (one Unicode set, one home).\nconst DENSE_SCRIPT = new RegExp(`[${UNSPACED_SCRIPTS}\\\\p{scx=Hangul}]`, 'u');\n\n// D5's size estimate: dense-script graphemes 1:1, everything else at 4 chars/token.\nexport function estimateTokens(text: string): number {\n let dense = 0;\n let other = 0;\n for (const ch of text) {\n if (DENSE_SCRIPT.test(ch)) dense++;\n else other++;\n }\n return dense + other / 4;\n}\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 (finalizePiece's splitLineText branch): its text is already\n // the active mode's final text for its own slice of the line, not the whole line, so group()'s\n // extent-based raw re-slice (startLine === endLine for every sibling sub-piece) must not touch it.\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');\nconst SENTENCE_SEGMENTER = new Intl.Segmenter(undefined, { granularity: 'sentence' });\nconst WORD_SEGMENTER = new Intl.Segmenter(undefined, { granularity: 'word' });\n\nfunction segmentsOf(text: string, segmenter: Intl.Segmenter): string[] {\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// A single line's text, still over working after rule 5's line-split can't reduce a lone line\n// (the CJK case, one sentence-dense line with no newlines), falls back to Intl.Segmenter sentence\n// boundaries, then word boundaries for any one sentence still over working. Never splits inside a\n// grapheme either way (both are ECMA-402, the same proven component segment.ts uses for\n// graphemes). Mode-agnostic: the caller decides whether `text` is the raw line or its extracted\n// flavor -- this only packs whatever text it is given.\nfunction splitLineText(text: string, working: number): string[] {\n const sentences = segmentsOf(text, SENTENCE_SEGMENTER);\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_SEGMENTER), 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// An atomic block's (code/table/list) piece is always a raw line slice: re-parsing a table's\n// later pieces without their header/delimiter rows demotes them to paragraph text. A non-atomic\n// piece is a raw line slice too when raw mode requested it; extracted mode re-parses and resolves\n// flavor as before.\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 piece over working size that came from exactly one source line cannot be reduced by another\n// line-boundary pass (rule 5's gap); it is sliced instead, at sentence then word boundaries, over\n// the mode-resolved text piece() already produced -- so raw mode packs the raw line and extracted\n// mode packs its flavor-resolved text. Extents collapse to that one line for every sub-piece (F5:\n// re-derivation is by index over chunk()'s own deterministic output, not by a unique line range\n// per piece); `final` flags each sub-piece so group() knows not to re-derive its text from that\n// shared extent.\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,\n// never mid-line. `seed`: pending tokens (a heading) the first piece must join, checked against\n// the limit too.\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 (a sub-line split) already carries its own slice's raw text -- re-slicing by\n // extent would return the whole shared source line instead, once per sub-piece.\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":["UNSPACED_SCRIPTS","extractText","parse","DEFAULT_TARGET_TOKENS","PGC_GROUP_SIZE","OVERSIZE_TRIGGER_MULTIPLE","DENSE_SCRIPT","RegExp","estimateTokens","text","dense","other","ch","test","resolveOptions","opts","targetTokens","splitScopes","blocks","scopes","current","block","type","length","push","finalize","parts","undefined","first","last","startLine","endLine","map","p","join","final","some","NEWLINE_TOKENS","SENTENCE_SEGMENTER","Intl","Segmenter","granularity","WORD_SEGMENTER","segmentsOf","segmenter","Array","from","segment","s","pack","segments","working","groups","tokens","segmentTokens","splitLineText","sentences","out","flush","sentence","sentenceTokens","ATOMIC_TYPES","Set","piece","pieceLines","blockType","textMode","has","b","node","finalizePiece","splitOversizeBlock","lines","seed","pieces","pieceStart","line","lineText","sep","lineTokens","groupScope","scopeBlocks","resolved","trigger","finished","paragraphCount","close","group","addPart","sizeText","raw","slice","blockTokens","extracted","pairOversize","body","split","chunks","scope","texted","c","trim","filter"],"mappings":"AAAA,SAASA,gBAAgB,QAAQ,qBAAqB;AACtD,SAASC,WAAW,QAAQ,eAAe;AAC3C,SAASC,KAAK,QAAQ,aAAa;AAGnC,OAAO,MAAMC,wBAAwB,IAAI;AACzC,MAAMC,iBAAiB;AACvB,MAAMC,4BAA4B;AAElC,yFAAyF;AACzF,gGAAgG;AAChG,MAAMC,eAAe,IAAIC,OAAO,CAAC,CAAC,EAAEP,iBAAiB,gBAAgB,CAAC,EAAE;AAExE,oFAAoF;AACpF,OAAO,SAASQ,eAAeC,IAAY;IACzC,IAAIC,QAAQ;IACZ,IAAIC,QAAQ;IACZ,KAAK,MAAMC,MAAMH,KAAM;QACrB,IAAIH,aAAaO,IAAI,CAACD,KAAKF;aACtBC;IACP;IACA,OAAOD,QAAQC,QAAQ;AACzB;AAOA,SAASG,eAAeC,IAAmB;;IACzC,OAAO;QACLC,YAAY,UAAED,iBAAAA,2BAAAA,KAAMC,YAAY,uCAAIb;QACpCM,IAAI,WAAEM,iBAAAA,2BAAAA,KAAMN,IAAI,yCAAI;IACtB;AACF;AAEA,6FAA6F;AAC7F,0FAA0F;AAC1F,SAASQ,YAAYC,MAAe;IAClC,MAAMC,SAAoB,EAAE;IAC5B,IAAIC,UAAmB,EAAE;IACzB,KAAK,MAAMC,SAASH,OAAQ;QAC1B,IAAIG,MAAMC,IAAI,KAAK,aAAaF,QAAQG,MAAM,GAAG,GAAG;YAClDJ,OAAOK,IAAI,CAACJ;YACZA,UAAU,EAAE;QACd;QACAA,QAAQI,IAAI,CAACH;IACf;IACA,IAAID,QAAQG,MAAM,GAAG,GAAGJ,OAAOK,IAAI,CAACJ;IACpC,OAAOD;AACT;AAYA,SAASM,SAASC,KAAa;IAC7B,IAAIA,MAAMH,MAAM,KAAK,GAAG,OAAOI;IAC/B,MAAMC,QAAQF,KAAK,CAAC,EAAE;IACtB,MAAMG,OAAOH,KAAK,CAACA,MAAMH,MAAM,GAAG,EAAE;IACpC,OAAO;QAAEO,WAAWF,MAAME,SAAS;QAAEC,SAASF,KAAKE,OAAO;QAAEtB,MAAMiB,MAAMM,GAAG,CAAC,CAACC,IAAMA,EAAExB,IAAI,EAAEyB,IAAI,CAAC;QAAOC,OAAOT,MAAMU,IAAI,CAAC,CAACH,IAAMA,EAAEE,KAAK;IAAE;AAC3I;AAEA,MAAME,iBAAiB7B,eAAe;AACtC,MAAM8B,qBAAqB,IAAIC,KAAKC,SAAS,CAACb,WAAW;IAAEc,aAAa;AAAW;AACnF,MAAMC,iBAAiB,IAAIH,KAAKC,SAAS,CAACb,WAAW;IAAEc,aAAa;AAAO;AAE3E,SAASE,WAAWlC,IAAY,EAAEmC,SAAyB;IACzD,OAAOC,MAAMC,IAAI,CAACF,UAAUG,OAAO,CAACtC,OAAO,CAACuC,IAAMA,EAAED,OAAO;AAC7D;AAEA,gGAAgG;AAChG,2FAA2F;AAC3F,SAASE,KAAKC,QAAkB,EAAEC,OAAe;IAC/C,MAAMC,SAAmB,EAAE;IAC3B,IAAIhC,UAAU;IACd,IAAIiC,SAAS;IACb,KAAK,MAAMN,WAAWG,SAAU;QAC9B,MAAMI,gBAAgB9C,eAAeuC;QACrC,IAAI3B,QAAQG,MAAM,GAAG,KAAK8B,SAASC,gBAAgBH,SAAS;YAC1DC,OAAO5B,IAAI,CAACJ;YACZA,UAAU;YACViC,SAAS;QACX;QACAjC,WAAW2B;QACXM,UAAUC;IACZ;IACA,IAAIlC,QAAQG,MAAM,GAAG,GAAG6B,OAAO5B,IAAI,CAACJ;IACpC,OAAOgC;AACT;AAEA,8FAA8F;AAC9F,kGAAkG;AAClG,kGAAkG;AAClG,wFAAwF;AACxF,gGAAgG;AAChG,uDAAuD;AACvD,SAASG,cAAc9C,IAAY,EAAE0C,OAAe;IAClD,MAAMK,YAAYb,WAAWlC,MAAM6B;IACnC,MAAMmB,MAAgB,EAAE;IACxB,IAAIrC,UAAU;IACd,IAAIiC,SAAS;IACb,MAAMK,QAAQ;QACZ,IAAItC,QAAQG,MAAM,GAAG,GAAG;YACtBkC,IAAIjC,IAAI,CAACJ;YACTA,UAAU;YACViC,SAAS;QACX;IACF;IACA,KAAK,MAAMM,YAAYH,UAAW;QAChC,MAAMI,iBAAiBpD,eAAemD;QACtC,IAAIC,iBAAiBT,SAAS;YAC5BO;YACAD,IAAIjC,IAAI,IAAIyB,KAAKN,WAAWgB,UAAUjB,iBAAiBS;YACvD;QACF;QACA,IAAI/B,QAAQG,MAAM,GAAG,KAAK8B,SAASO,iBAAiBT,SAASO;QAC7DtC,WAAWuC;QACXN,UAAUO;IACZ;IACAF;IACA,OAAOD;AACT;AAEA,MAAMI,eAAuC,IAAIC,IAAI;IAAC;IAAQ;IAAS;CAAO;AAE9E,6FAA6F;AAC7F,gGAAgG;AAChG,kGAAkG;AAClG,oBAAoB;AACpB,SAASC,MAAMC,UAAoB,EAAElC,SAAiB,EAAEC,OAAe,EAAEkC,SAAoB,EAAEC,QAA6B;IAC1H,MAAMzD,OACJoD,aAAaM,GAAG,CAACF,cAAcC,aAAa,QACxCF,WAAW9B,IAAI,CAAC,QAChBhC,MAAM8D,WAAW9B,IAAI,CAAC,OACnBF,GAAG,CAAC,CAACoC,IAAMnE,YAAYmE,EAAEC,IAAI,GAC7BnC,IAAI,CAAC;IACd,OAAO;QAAEJ;QAAWC;QAAStB;IAAK;AACpC;AAEA,gGAAgG;AAChG,kGAAkG;AAClG,kGAAkG;AAClG,kGAAkG;AAClG,gGAAgG;AAChG,gGAAgG;AAChG,iBAAiB;AACjB,SAAS6D,cAAcN,UAAoB,EAAElC,SAAiB,EAAEC,OAAe,EAAEoB,OAAe,EAAEc,SAAoB,EAAEC,QAA6B;IACnJ,MAAMjC,IAAI8B,MAAMC,YAAYlC,WAAWC,SAASkC,WAAWC;IAC3D,IAAIF,WAAWzC,MAAM,KAAK,KAAKf,eAAeyB,EAAExB,IAAI,IAAI0C,SAAS;QAC/D,OAAOI,cAActB,EAAExB,IAAI,EAAE0C,SAASnB,GAAG,CAAC,CAACvB,OAAU,CAAA;gBAAEqB;gBAAWC;gBAAStB;gBAAM0B,OAAO;YAAK,CAAA;IAC/F;IACA,OAAO;QAACF;KAAE;AACZ;AAEA,2FAA2F;AAC3F,gGAAgG;AAChG,iBAAiB;AACjB,SAASsC,mBAAmBC,KAAe,EAAE1C,SAAiB,EAAEC,OAAe,EAAEoB,OAAe,EAAEc,SAAoB,EAAEC,QAA6B,EAAEO,OAAO,CAAC;IAC7J,MAAMC,SAAiB,EAAE;IACzB,IAAIV,aAAuB,EAAE;IAC7B,IAAIW,aAAa7C;IACjB,IAAIuB,SAASoB;IACb,IAAK,IAAIG,OAAO9C,WAAW8C,QAAQ7C,SAAS6C,OAAQ;QAClD,MAAMC,WAAWL,KAAK,CAACI,OAAO,EAAE;QAChC,MAAME,MAAMd,WAAWzC,MAAM,GAAG,KAAK8B,SAAS,IAAIhB,iBAAiB;QACnE,MAAM0C,aAAavE,eAAeqE;QAClC,IAAIb,WAAWzC,MAAM,GAAG,KAAK8B,SAASyB,MAAMC,aAAa5B,SAAS;YAChEuB,OAAOlD,IAAI,IAAI8C,cAAcN,YAAYW,YAAYC,OAAO,GAAGzB,SAASc,WAAWC;YACnFF,aAAa,EAAE;YACfX,SAAS;YACTsB,aAAaC;YACbZ,WAAWxC,IAAI,CAACqD;YAChBxB,UAAU0B;YACV;QACF;QACAf,WAAWxC,IAAI,CAACqD;QAChBxB,UAAUyB,MAAMC;IAClB;IACA,IAAIf,WAAWzC,MAAM,GAAG,GAAGmD,OAAOlD,IAAI,IAAI8C,cAAcN,YAAYW,YAAY5C,SAASoB,SAASc,WAAWC;IAC7G,OAAOQ;AACT;AAEA,0FAA0F;AAC1F,8FAA8F;AAC9F,SAASM,WAAWC,WAAoB,EAAET,KAAe,EAAEU,QAAyB;IAClF,MAAM/B,UAAU+B,SAASlE,YAAY;IACrC,MAAMmE,UAAUhC,UAAU9C;IAC1B,MAAM+E,WAA4C,EAAE;IACpD,IAAI1D,QAAgB,EAAE;IACtB,IAAI2D,iBAAiB;IACrB,IAAIhC,SAAS;IAEb,SAASiC;QACP,MAAMC,QAAQ9D,SAASC;QACvB,IAAI6D,OAAOH,SAAS5D,IAAI,CAAC+D;QACzB7D,QAAQ,EAAE;QACV2D,iBAAiB;QACjBhC,SAAS;IACX;IAEA,mFAAmF;IACnF,2FAA2F;IAC3F,SAASmC,QAAQ/E,IAAY,EAAEgF,QAAgB,EAAE3D,SAAiB,EAAEC,OAAe;QACjFsB,UAAU,AAAC3B,CAAAA,MAAMH,MAAM,GAAG,IAAIc,iBAAiB,CAAA,IAAK7B,eAAeiF;QACnE/D,MAAMF,IAAI,CAAC;YAAEM;YAAWC;YAAStB;QAAK;IACxC;IAEA,KAAK,MAAMY,SAAS4D,YAAa;QAC/B,MAAMS,MAAMlB,MAAMmB,KAAK,CAACtE,MAAMS,SAAS,GAAG,GAAGT,MAAMU,OAAO,EAAEG,IAAI,CAAC;QACjE,MAAM0D,cAAcpF,eAAekF;QAEnC,IAAIE,cAAcT,SAAS;YACzB,MAAMV,OAAO/C,MAAMH,MAAM,GAAG,IAAI8B,SAAS;YACzC,KAAK,MAAMpB,KAAKsC,mBAAmBC,OAAOnD,MAAMS,SAAS,EAAET,MAAMU,OAAO,EAAEoB,SAAS9B,MAAMC,IAAI,EAAE4D,SAASzE,IAAI,EAAEgE,MAAO;gBACnH/C,MAAMF,IAAI,CAACS;gBACXqD;YACF;YACA;QACF;QAEA,MAAMO,YAAY5F,YAAYoB,MAAMgD,IAAI;QACxC,MAAMoB,WAAWP,SAASzE,IAAI,KAAK,QAAQiF,MAAMG;QAEjD,IAAIxE,MAAMC,IAAI,KAAK,WAAW;YAC5BkE,QAAQK,WAAWJ,UAAUpE,MAAMS,SAAS,EAAET,MAAMU,OAAO;YAC3D;QACF;QAEA,wFAAwF;QACxF,wDAAwD;QACxD,MAAM+D,eAAepE,MAAMH,MAAM,GAAG,KAAK8B,SAAShB,iBAAiBuD,cAAcT;QACjF,IAAIW,cAAcR;QAElBE,QAAQK,WAAWJ,UAAUpE,MAAMS,SAAS,EAAET,MAAMU,OAAO;QAC3DsD;QAEA,IAAIA,kBAAkBjF,gBAAgBkF;IACxC;IACAA;IAEA,OAAOF;AACT;AAEA,8FAA8F;AAC9F,8CAA8C;AAC9C,OAAO,SAASG,MAAMrE,MAAe,EAAE6E,IAAY,EAAEhF,IAAmB;IACtE,MAAMmE,WAAWpE,eAAeC;IAChC,MAAMyD,QAAQuB,KAAKC,KAAK,CAAC;IACzB,MAAMC,SAA0C,EAAE;IAClD,KAAK,MAAMC,SAASjF,YAAYC,QAAS+E,OAAOzE,IAAI,IAAIwD,WAAWkB,OAAO1B,OAAOU;IACjF,+FAA+F;IAC/F,+FAA+F;IAC/F,gFAAgF;IAChF,MAAMiB,SACJjB,SAASzE,IAAI,KAAK,QACdwF,OAAOjE,GAAG,CAAC,CAACoE,IACVA,EAAEjE,KAAK,GACHiE,IACA;YACE,GAAGA,CAAC;YACJ3F,MAAM+D,MACHmB,KAAK,CAACS,EAAEtE,SAAS,GAAG,GAAGsE,EAAErE,OAAO,EAChCG,IAAI,CAAC,MACLmE,IAAI;QACT,KAENJ;IACN,mHAAmH;IACnH,OAAOE,OAAOG,MAAM,CAAC,CAACF,IAAMA,EAAE3F,IAAI,CAAC4F,IAAI,GAAG9E,MAAM,GAAG,GAAGS,GAAG,CAAC,CAACoE,IAAO,CAAA;YAAEtE,WAAWsE,EAAEtE,SAAS;YAAEC,SAASqE,EAAErE,OAAO;YAAEtB,MAAM2F,EAAE3F,IAAI;QAAC,CAAA;AAC/H"}
@@ -0,0 +1,8 @@
1
+ import type { Block, Chunk, ChunkOptions } from './types.js';
2
+ export declare function chunkFromBlocks(blocks: Block[], body: string, opts?: ChunkOptions): Chunk[];
3
+ export declare function chunk(body: string, opts?: ChunkOptions): Chunk[];
4
+ export { extractText } from './extract.js';
5
+ export { DEFAULT_TARGET_TOKENS, estimateTokens } from './group.js';
6
+ export { parse } from './parse.js';
7
+ export type { Block, BlockType, Chunk, ChunkOptions } from './types.js';
8
+ export { CHUNK_VERSION } from './version.js';
@@ -0,0 +1,16 @@
1
+ import { group } from './group.js';
2
+ import { parse } from './parse.js';
3
+ // Groups blocks a caller already parsed (e.g. scan/index.ts, sharing one parse with the FTS
4
+ // text path) against the same body they came from, per opts (D1/D3).
5
+ export function chunkFromBlocks(blocks, body, opts) {
6
+ return group(blocks, body, opts);
7
+ }
8
+ // Pure, deterministic function of file content; chunk semantics are version-stamped via
9
+ // CHUNK_VERSION (./version.ts). Algorithm and evidence: BENCHMARKING.md, "The chunking algorithm".
10
+ export function chunk(body, opts) {
11
+ return chunkFromBlocks(parse(body), body, opts);
12
+ }
13
+ export { extractText } from './extract.js';
14
+ export { DEFAULT_TARGET_TOKENS, estimateTokens } from './group.js';
15
+ export { parse } from './parse.js';
16
+ export { CHUNK_VERSION } from './version.js';
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/index.ts"],"sourcesContent":["import { group } from './group.ts';\nimport { parse } from './parse.ts';\nimport type { Block, Chunk, ChunkOptions } from './types.ts';\n\n// Groups blocks a caller already parsed (e.g. scan/index.ts, sharing one parse with the FTS\n// text path) against the same body they came from, per opts (D1/D3).\nexport function chunkFromBlocks(blocks: Block[], body: string, opts?: ChunkOptions): Chunk[] {\n return group(blocks, body, opts);\n}\n\n// Pure, deterministic function of file content; chunk semantics are version-stamped via\n// CHUNK_VERSION (./version.ts). Algorithm and evidence: BENCHMARKING.md, \"The chunking algorithm\".\nexport function chunk(body: string, opts?: ChunkOptions): Chunk[] {\n return chunkFromBlocks(parse(body), body, opts);\n}\n\nexport { extractText } from './extract.ts';\nexport { DEFAULT_TARGET_TOKENS, estimateTokens } from './group.ts';\nexport { parse } from './parse.ts';\nexport type { Block, BlockType, Chunk, ChunkOptions } from './types.ts';\nexport { CHUNK_VERSION } from './version.ts';\n"],"names":["group","parse","chunkFromBlocks","blocks","body","opts","chunk","extractText","DEFAULT_TARGET_TOKENS","estimateTokens","CHUNK_VERSION"],"mappings":"AAAA,SAASA,KAAK,QAAQ,aAAa;AACnC,SAASC,KAAK,QAAQ,aAAa;AAGnC,4FAA4F;AAC5F,qEAAqE;AACrE,OAAO,SAASC,gBAAgBC,MAAe,EAAEC,IAAY,EAAEC,IAAmB;IAChF,OAAOL,MAAMG,QAAQC,MAAMC;AAC7B;AAEA,wFAAwF;AACxF,mGAAmG;AACnG,OAAO,SAASC,MAAMF,IAAY,EAAEC,IAAmB;IACrD,OAAOH,gBAAgBD,MAAMG,OAAOA,MAAMC;AAC5C;AAEA,SAASE,WAAW,QAAQ,eAAe;AAC3C,SAASC,qBAAqB,EAAEC,cAAc,QAAQ,aAAa;AACnE,SAASR,KAAK,QAAQ,aAAa;AAEnC,SAASS,aAAa,QAAQ,eAAe"}
@@ -0,0 +1,2 @@
1
+ import type { Block } from './types.js';
2
+ export declare function parse(body: string): Block[];
@@ -0,0 +1,63 @@
1
+ import { fromMarkdown } from 'mdast-util-from-markdown';
2
+ import { gfmAutolinkLiteralFromMarkdown } from 'mdast-util-gfm-autolink-literal';
3
+ import { gfmFootnoteFromMarkdown } from 'mdast-util-gfm-footnote';
4
+ import { gfmStrikethroughFromMarkdown } from 'mdast-util-gfm-strikethrough';
5
+ import { gfmTableFromMarkdown } from 'mdast-util-gfm-table';
6
+ import { gfmTaskListItemFromMarkdown } from 'mdast-util-gfm-task-list-item';
7
+ import { gfmAutolinkLiteral } from 'micromark-extension-gfm-autolink-literal';
8
+ import { gfmFootnote } from 'micromark-extension-gfm-footnote';
9
+ import { gfmStrikethrough } from 'micromark-extension-gfm-strikethrough';
10
+ import { gfmTable } from 'micromark-extension-gfm-table';
11
+ import { gfmTaskListItem } from 'micromark-extension-gfm-task-list-item';
12
+ import { extractText } from './extract.js';
13
+ const BLOCK_TYPES = {
14
+ heading: 'heading',
15
+ paragraph: 'paragraph',
16
+ code: 'code',
17
+ table: 'table',
18
+ list: 'list',
19
+ blockquote: 'blockquote'
20
+ };
21
+ // The five extensions extract.ts/group.ts actually consume, imported individually rather than
22
+ // through micromark-extension-gfm/mdast-util-gfm: those bundles also pull in gfm-tagfilter,
23
+ // an HTML-serialization sanitizer this library never uses (no htmlExtensions call anywhere).
24
+ // micromark and mdast-util-from-markdown each already flatten an extensions array themselves,
25
+ // so no combine-extensions helper is needed here.
26
+ const EXTENSIONS = [
27
+ gfmAutolinkLiteral(),
28
+ gfmFootnote(),
29
+ gfmStrikethrough(),
30
+ gfmTable(),
31
+ gfmTaskListItem()
32
+ ];
33
+ const MDAST_EXTENSIONS = [
34
+ gfmAutolinkLiteralFromMarkdown(),
35
+ gfmFootnoteFromMarkdown(),
36
+ gfmStrikethroughFromMarkdown(),
37
+ gfmTableFromMarkdown(),
38
+ gfmTaskListItemFromMarkdown()
39
+ ];
40
+ // Top-level blocks of a markdown body, typed and line-extent bounded. Extents come from
41
+ // mdast's own node.position, never a regex guess at where a block starts or ends; GFM adds
42
+ // tables, task lists, footnotes and strikethrough to the CommonMark set fromMarkdown parses.
43
+ export function parse(body) {
44
+ const tree = fromMarkdown(body, {
45
+ extensions: EXTENSIONS,
46
+ mdastExtensions: MDAST_EXTENSIONS
47
+ });
48
+ return tree.children.map((node)=>{
49
+ var _BLOCK_TYPES_node_type;
50
+ const position = node.position;
51
+ const block = {
52
+ type: (_BLOCK_TYPES_node_type = BLOCK_TYPES[node.type]) !== null && _BLOCK_TYPES_node_type !== void 0 ? _BLOCK_TYPES_node_type : 'other',
53
+ startLine: position ? position.start.line : 1,
54
+ endLine: position ? position.end.line : 1,
55
+ node
56
+ };
57
+ if (node.type === 'heading') {
58
+ block.depth = node.depth;
59
+ block.text = extractText(node);
60
+ }
61
+ return block;
62
+ });
63
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/parse.ts"],"sourcesContent":["import type { RootContent } from 'mdast';\nimport { fromMarkdown } from 'mdast-util-from-markdown';\nimport { gfmAutolinkLiteralFromMarkdown } from 'mdast-util-gfm-autolink-literal';\nimport { gfmFootnoteFromMarkdown } from 'mdast-util-gfm-footnote';\nimport { gfmStrikethroughFromMarkdown } from 'mdast-util-gfm-strikethrough';\nimport { gfmTableFromMarkdown } from 'mdast-util-gfm-table';\nimport { gfmTaskListItemFromMarkdown } from 'mdast-util-gfm-task-list-item';\nimport { gfmAutolinkLiteral } from 'micromark-extension-gfm-autolink-literal';\nimport { gfmFootnote } from 'micromark-extension-gfm-footnote';\nimport { gfmStrikethrough } from 'micromark-extension-gfm-strikethrough';\nimport { gfmTable } from 'micromark-extension-gfm-table';\nimport { gfmTaskListItem } from 'micromark-extension-gfm-task-list-item';\nimport { extractText } from './extract.ts';\nimport type { Block, BlockType } from './types.ts';\n\nconst BLOCK_TYPES: Partial<Record<RootContent['type'], BlockType>> = {\n heading: 'heading',\n paragraph: 'paragraph',\n code: 'code',\n table: 'table',\n list: 'list',\n blockquote: 'blockquote',\n};\n\n// The five extensions extract.ts/group.ts actually consume, imported individually rather than\n// through micromark-extension-gfm/mdast-util-gfm: those bundles also pull in gfm-tagfilter,\n// an HTML-serialization sanitizer this library never uses (no htmlExtensions call anywhere).\n// micromark and mdast-util-from-markdown each already flatten an extensions array themselves,\n// so no combine-extensions helper is needed here.\nconst EXTENSIONS = [gfmAutolinkLiteral(), gfmFootnote(), gfmStrikethrough(), gfmTable(), gfmTaskListItem()];\nconst MDAST_EXTENSIONS = [gfmAutolinkLiteralFromMarkdown(), gfmFootnoteFromMarkdown(), gfmStrikethroughFromMarkdown(), gfmTableFromMarkdown(), gfmTaskListItemFromMarkdown()];\n\n// Top-level blocks of a markdown body, typed and line-extent bounded. Extents come from\n// mdast's own node.position, never a regex guess at where a block starts or ends; GFM adds\n// tables, task lists, footnotes and strikethrough to the CommonMark set fromMarkdown parses.\nexport function parse(body: string): Block[] {\n const tree = fromMarkdown(body, { extensions: EXTENSIONS, mdastExtensions: MDAST_EXTENSIONS });\n return tree.children.map((node) => {\n const position = node.position;\n const block: Block = {\n type: BLOCK_TYPES[node.type] ?? 'other',\n startLine: position ? position.start.line : 1,\n endLine: position ? position.end.line : 1,\n node,\n };\n if (node.type === 'heading') {\n block.depth = node.depth;\n block.text = extractText(node);\n }\n return block;\n });\n}\n"],"names":["fromMarkdown","gfmAutolinkLiteralFromMarkdown","gfmFootnoteFromMarkdown","gfmStrikethroughFromMarkdown","gfmTableFromMarkdown","gfmTaskListItemFromMarkdown","gfmAutolinkLiteral","gfmFootnote","gfmStrikethrough","gfmTable","gfmTaskListItem","extractText","BLOCK_TYPES","heading","paragraph","code","table","list","blockquote","EXTENSIONS","MDAST_EXTENSIONS","parse","body","tree","extensions","mdastExtensions","children","map","node","position","block","type","startLine","start","line","endLine","end","depth","text"],"mappings":"AACA,SAASA,YAAY,QAAQ,2BAA2B;AACxD,SAASC,8BAA8B,QAAQ,kCAAkC;AACjF,SAASC,uBAAuB,QAAQ,0BAA0B;AAClE,SAASC,4BAA4B,QAAQ,+BAA+B;AAC5E,SAASC,oBAAoB,QAAQ,uBAAuB;AAC5D,SAASC,2BAA2B,QAAQ,gCAAgC;AAC5E,SAASC,kBAAkB,QAAQ,2CAA2C;AAC9E,SAASC,WAAW,QAAQ,mCAAmC;AAC/D,SAASC,gBAAgB,QAAQ,wCAAwC;AACzE,SAASC,QAAQ,QAAQ,gCAAgC;AACzD,SAASC,eAAe,QAAQ,yCAAyC;AACzE,SAASC,WAAW,QAAQ,eAAe;AAG3C,MAAMC,cAA+D;IACnEC,SAAS;IACTC,WAAW;IACXC,MAAM;IACNC,OAAO;IACPC,MAAM;IACNC,YAAY;AACd;AAEA,8FAA8F;AAC9F,4FAA4F;AAC5F,6FAA6F;AAC7F,8FAA8F;AAC9F,kDAAkD;AAClD,MAAMC,aAAa;IAACb;IAAsBC;IAAeC;IAAoBC;IAAYC;CAAkB;AAC3G,MAAMU,mBAAmB;IAACnB;IAAkCC;IAA2BC;IAAgCC;IAAwBC;CAA8B;AAE7K,wFAAwF;AACxF,2FAA2F;AAC3F,6FAA6F;AAC7F,OAAO,SAASgB,MAAMC,IAAY;IAChC,MAAMC,OAAOvB,aAAasB,MAAM;QAAEE,YAAYL;QAAYM,iBAAiBL;IAAiB;IAC5F,OAAOG,KAAKG,QAAQ,CAACC,GAAG,CAAC,CAACC;YAGhBhB;QAFR,MAAMiB,WAAWD,KAAKC,QAAQ;QAC9B,MAAMC,QAAe;YACnBC,IAAI,GAAEnB,yBAAAA,WAAW,CAACgB,KAAKG,IAAI,CAAC,cAAtBnB,oCAAAA,yBAA0B;YAChCoB,WAAWH,WAAWA,SAASI,KAAK,CAACC,IAAI,GAAG;YAC5CC,SAASN,WAAWA,SAASO,GAAG,CAACF,IAAI,GAAG;YACxCN;QACF;QACA,IAAIA,KAAKG,IAAI,KAAK,WAAW;YAC3BD,MAAMO,KAAK,GAAGT,KAAKS,KAAK;YACxBP,MAAMQ,IAAI,GAAG3B,YAAYiB;QAC3B;QACA,OAAOE;IACT;AACF"}
@@ -0,0 +1,19 @@
1
+ import type { RootContent } from 'mdast';
2
+ export type BlockType = 'heading' | 'paragraph' | 'code' | 'table' | 'list' | 'blockquote' | 'other';
3
+ export interface Block {
4
+ type: BlockType;
5
+ startLine: number;
6
+ endLine: number;
7
+ depth?: number;
8
+ text?: string;
9
+ node: RootContent;
10
+ }
11
+ export interface ChunkOptions {
12
+ targetTokens?: number;
13
+ text?: 'extracted' | 'raw';
14
+ }
15
+ export interface Chunk {
16
+ startLine: number;
17
+ endLine: number;
18
+ text: string;
19
+ }
@@ -0,0 +1,2 @@
1
+ // One grouped, extracted unit: 1-indexed line extent over the body, flavor-resolved text.
2
+ export { };
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/types.ts"],"sourcesContent":["import type { RootContent } from 'mdast';\n\nexport type BlockType = 'heading' | 'paragraph' | 'code' | 'table' | 'list' | 'blockquote' | 'other';\n\n// One top-level mdast node plus its 1-indexed source line extent, heading depth/text if any.\n// `node` is the mdast node itself, so extract.ts and group.ts (W2) read the same parse.\nexport interface Block {\n type: BlockType;\n startLine: number;\n endLine: number;\n depth?: number;\n text?: string;\n node: RootContent;\n}\n\nexport interface ChunkOptions {\n // D3/W3b: the pgc pairing cap and the sole owner lever (embed.chunkTokens); default 500.\n targetTokens?: number;\n // D9: 'raw' (source lines verbatim) is the shipped default; 'extracted' (flavor-resolved)\n // stays available for a future measured revisit, not currently shipped.\n text?: 'extracted' | 'raw';\n}\n\n// One grouped, extracted unit: 1-indexed line extent over the body, flavor-resolved text.\nexport interface Chunk {\n startLine: number;\n endLine: number;\n text: string;\n}\n"],"names":[],"mappings":"AAuBA,0FAA0F;AAC1F,WAIC"}
@@ -0,0 +1 @@
1
+ export declare const CHUNK_VERSION = "chunk:v5";
@@ -0,0 +1,3 @@
1
+ // D8: bump whenever chunk semantics change (grouping, sizing, splitting); the digest in
2
+ // test/unit/chunk/version.test.ts tracks EXTRACTION changes only, so the two move independently.
3
+ export const CHUNK_VERSION = 'chunk:v5';
@@ -0,0 +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:v5';\n"],"names":["CHUNK_VERSION"],"mappings":"AAAA,wFAAwF;AACxF,iGAAiG;AACjG,OAAO,MAAMA,gBAAgB,WAAW"}
@@ -1,5 +1,5 @@
1
1
  import { mapTree } from '../commands/index.js';
2
- import { renderMap } from '../output.js';
2
+ import { renderMap } from '../output/output.js';
3
3
  import { USAGE } from './index.js';
4
4
  import { CONFIG, FORMAT, formatOf, parse, SCOPE, scopeOf, withDb } from './shared.js';
5
5
  const map = (ctx)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/map.ts"],"sourcesContent":["import { mapTree } from '../commands/index.ts';\nimport { renderMap } from '../output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, parse, SCOPE, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst map: Command = (ctx) => {\n const { values } = parse(ctx.argv, `usage: ${ctx.name} ${USAGE.map}`, { ...SCOPE, ...FORMAT, ...CONFIG });\n const format = formatOf(values);\n return withDb(ctx, values.config as string | undefined, (db, cfg) => {\n const result = mapTree(db, cfg, scopeOf(values));\n console.log(format === 'json' ? JSON.stringify(result, null, 2) : renderMap(result));\n });\n};\nexport default map;\n"],"names":["mapTree","renderMap","USAGE","CONFIG","FORMAT","formatOf","parse","SCOPE","scopeOf","withDb","map","ctx","values","argv","name","format","config","db","cfg","result","console","log","JSON","stringify"],"mappings":"AAAA,SAASA,OAAO,QAAQ,uBAAuB;AAC/C,SAASC,SAAS,QAAQ,eAAe;AACzC,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,KAAK,EAAEC,KAAK,EAAEC,OAAO,EAAEC,MAAM,QAAQ,cAAc;AAGtF,MAAMC,MAAe,CAACC;IACpB,MAAM,EAAEC,MAAM,EAAE,GAAGN,MAAMK,IAAIE,IAAI,EAAE,CAAC,OAAO,EAAEF,IAAIG,IAAI,CAAC,CAAC,EAAEZ,MAAMQ,GAAG,EAAE,EAAE;QAAE,GAAGH,KAAK;QAAE,GAAGH,MAAM;QAAE,GAAGD,MAAM;IAAC;IACvG,MAAMY,SAASV,SAASO;IACxB,OAAOH,OAAOE,KAAKC,OAAOI,MAAM,EAAwB,CAACC,IAAIC;QAC3D,MAAMC,SAASnB,QAAQiB,IAAIC,KAAKV,QAAQI;QACxCQ,QAAQC,GAAG,CAACN,WAAW,SAASO,KAAKC,SAAS,CAACJ,QAAQ,MAAM,KAAKlB,UAAUkB;IAC9E;AACF;AACA,eAAeT,IAAI"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/map.ts"],"sourcesContent":["import { mapTree } from '../commands/index.ts';\nimport { renderMap } from '../output/output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, parse, SCOPE, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst map: Command = (ctx) => {\n const { values } = parse(ctx.argv, `usage: ${ctx.name} ${USAGE.map}`, { ...SCOPE, ...FORMAT, ...CONFIG });\n const format = formatOf(values);\n return withDb(ctx, values.config as string | undefined, (db, cfg) => {\n const result = mapTree(db, cfg, scopeOf(values));\n console.log(format === 'json' ? JSON.stringify(result, null, 2) : renderMap(result));\n });\n};\nexport default map;\n"],"names":["mapTree","renderMap","USAGE","CONFIG","FORMAT","formatOf","parse","SCOPE","scopeOf","withDb","map","ctx","values","argv","name","format","config","db","cfg","result","console","log","JSON","stringify"],"mappings":"AAAA,SAASA,OAAO,QAAQ,uBAAuB;AAC/C,SAASC,SAAS,QAAQ,sBAAsB;AAChD,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,KAAK,EAAEC,KAAK,EAAEC,OAAO,EAAEC,MAAM,QAAQ,cAAc;AAGtF,MAAMC,MAAe,CAACC;IACpB,MAAM,EAAEC,MAAM,EAAE,GAAGN,MAAMK,IAAIE,IAAI,EAAE,CAAC,OAAO,EAAEF,IAAIG,IAAI,CAAC,CAAC,EAAEZ,MAAMQ,GAAG,EAAE,EAAE;QAAE,GAAGH,KAAK;QAAE,GAAGH,MAAM;QAAE,GAAGD,MAAM;IAAC;IACvG,MAAMY,SAASV,SAASO;IACxB,OAAOH,OAAOE,KAAKC,OAAOI,MAAM,EAAwB,CAACC,IAAIC;QAC3D,MAAMC,SAASnB,QAAQiB,IAAIC,KAAKV,QAAQI;QACxCQ,QAAQC,GAAG,CAACN,WAAW,SAASO,KAAKC,SAAS,CAACJ,QAAQ,MAAM,KAAKlB,UAAUkB;IAC9E;AACF;AACA,eAAeT,IAAI"}
@@ -1,5 +1,5 @@
1
1
  import { search } from '../commands/index.js';
2
- import { printRows } from '../output.js';
2
+ import { printRows } from '../output/output.js';
3
3
  import { CONFIG, FORMAT, parse, parseK, rowFormatOf, runSql, SEARCH_FLAGS, withDb } from './shared.js';
4
4
  // Fallback when the first positional is not a command: a saved query, { sql } or { search }.
5
5
  // SEARCH_FLAGS override a saved search's fields the same way they override a preset's.
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/named.ts"],"sourcesContent":["import { search } from '../commands/index.ts';\nimport { printRows } from '../output.ts';\nimport { CONFIG, FORMAT, parse, parseK, rowFormatOf, runSql, SEARCH_FLAGS, withDb } from './shared.ts';\nimport type { Ctx } from './types.ts';\n\n// Fallback when the first positional is not a command: a saved query, { sql } or { search }.\n// SEARCH_FLAGS override a saved search's fields the same way they override a preset's.\nexport default async function named(ctx: Ctx, queryName: string): Promise<void> {\n const usage = `usage: ${ctx.name} ${queryName} [params...] [--format table|json|csv] [--config path] [--where \"<sql>\"] [--k n] [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude]`;\n const { values, positionals: params } = parse(ctx.argv, usage, { ...SEARCH_FLAGS, ...FORMAT, ...CONFIG });\n const format = rowFormatOf(values);\n const configPath = values.config as string | undefined;\n\n const cfg = ctx.resolveConfig(configPath);\n const entry = cfg.queries[queryName];\n if (entry === undefined) {\n console.error(`unknown command or saved entry: \"${queryName}\"`);\n console.error(`saved queries: ${Object.keys(cfg.queries).sort().join(', ')}`);\n process.exit(2);\n }\n\n if ('sql' in entry) {\n // A saved statement written against `scope` is preset-agnostic, so the same entry can be\n // re-pointed at another layer from the command line instead of being copied per preset.\n runSql(cfg, entry.sql, params, format, `query \"${queryName}\"`, values.preset as string | undefined);\n return;\n }\n\n // A saved search's text is fixed in config; there is nowhere for a positional to bind.\n if (params.length > 0) {\n ctx.usageError(`\"${queryName}\" is a saved search and takes no positional parameters; edit its \"search\" in sense.config.json, or use \"${ctx.name} search\" directly`);\n }\n const k = parseK(values.k as string | undefined, ctx.usageError) ?? entry.k;\n const where = (values.where as string | undefined) ?? entry.where;\n const preset = (values.preset as string | undefined) ?? entry.preset;\n const include = (values.include as string[] | undefined) ?? entry.include;\n const exclude = (values.exclude as string[] | undefined) ?? entry.exclude;\n const noExclude = values['no-exclude'] === true;\n await withDb(ctx, configPath, async (db, resolvedCfg) => printRows(await search(db, resolvedCfg, entry.search, { k, where, preset, include, exclude, noExclude }), format));\n}\n"],"names":["search","printRows","CONFIG","FORMAT","parse","parseK","rowFormatOf","runSql","SEARCH_FLAGS","withDb","named","ctx","queryName","values","usage","name","positionals","params","argv","format","configPath","config","cfg","resolveConfig","entry","queries","undefined","console","error","Object","keys","sort","join","process","exit","sql","preset","length","usageError","k","where","include","exclude","noExclude","db","resolvedCfg"],"mappings":"AAAA,SAASA,MAAM,QAAQ,uBAAuB;AAC9C,SAASC,SAAS,QAAQ,eAAe;AACzC,SAASC,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAEC,WAAW,EAAEC,MAAM,EAAEC,YAAY,EAAEC,MAAM,QAAQ,cAAc;AAGvG,6FAA6F;AAC7F,uFAAuF;AACvF,eAAe,eAAeC,MAAMC,GAAQ,EAAEC,SAAiB;QAyBnDP,SACKQ,eACCA,gBACCA,iBACAA;IA5BjB,MAAMC,QAAQ,CAAC,OAAO,EAAEH,IAAII,IAAI,CAAC,CAAC,EAAEH,UAAU,yJAAyJ,CAAC;IACxM,MAAM,EAAEC,MAAM,EAAEG,aAAaC,MAAM,EAAE,GAAGb,MAAMO,IAAIO,IAAI,EAAEJ,OAAO;QAAE,GAAGN,YAAY;QAAE,GAAGL,MAAM;QAAE,GAAGD,MAAM;IAAC;IACvG,MAAMiB,SAASb,YAAYO;IAC3B,MAAMO,aAAaP,OAAOQ,MAAM;IAEhC,MAAMC,MAAMX,IAAIY,aAAa,CAACH;IAC9B,MAAMI,QAAQF,IAAIG,OAAO,CAACb,UAAU;IACpC,IAAIY,UAAUE,WAAW;QACvBC,QAAQC,KAAK,CAAC,CAAC,iCAAiC,EAAEhB,UAAU,CAAC,CAAC;QAC9De,QAAQC,KAAK,CAAC,CAAC,eAAe,EAAEC,OAAOC,IAAI,CAACR,IAAIG,OAAO,EAAEM,IAAI,GAAGC,IAAI,CAAC,OAAO;QAC5EC,QAAQC,IAAI,CAAC;IACf;IAEA,IAAI,SAASV,OAAO;QAClB,yFAAyF;QACzF,wFAAwF;QACxFjB,OAAOe,KAAKE,MAAMW,GAAG,EAAElB,QAAQE,QAAQ,CAAC,OAAO,EAAEP,UAAU,CAAC,CAAC,EAAEC,OAAOuB,MAAM;QAC5E;IACF;IAEA,uFAAuF;IACvF,IAAInB,OAAOoB,MAAM,GAAG,GAAG;QACrB1B,IAAI2B,UAAU,CAAC,CAAC,CAAC,EAAE1B,UAAU,wGAAwG,EAAED,IAAII,IAAI,CAAC,iBAAiB,CAAC;IACpK;IACA,MAAMwB,KAAIlC,UAAAA,OAAOQ,OAAO0B,CAAC,EAAwB5B,IAAI2B,UAAU,eAArDjC,qBAAAA,UAA0DmB,MAAMe,CAAC;IAC3E,MAAMC,SAAS3B,gBAAAA,OAAO2B,KAAK,cAAZ3B,2BAAAA,gBAAuCW,MAAMgB,KAAK;IACjE,MAAMJ,UAAUvB,iBAAAA,OAAOuB,MAAM,cAAbvB,4BAAAA,iBAAwCW,MAAMY,MAAM;IACpE,MAAMK,WAAW5B,kBAAAA,OAAO4B,OAAO,cAAd5B,6BAAAA,kBAA2CW,MAAMiB,OAAO;IACzE,MAAMC,WAAW7B,kBAAAA,OAAO6B,OAAO,cAAd7B,6BAAAA,kBAA2CW,MAAMkB,OAAO;IACzE,MAAMC,YAAY9B,MAAM,CAAC,aAAa,KAAK;IAC3C,MAAMJ,OAAOE,KAAKS,YAAY,OAAOwB,IAAIC,cAAgB5C,UAAU,MAAMD,OAAO4C,IAAIC,aAAarB,MAAMxB,MAAM,EAAE;YAAEuC;YAAGC;YAAOJ;YAAQK;YAASC;YAASC;QAAU,IAAIxB;AACrK"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/named.ts"],"sourcesContent":["import { search } from '../commands/index.ts';\nimport { printRows } from '../output/output.ts';\nimport { CONFIG, FORMAT, parse, parseK, rowFormatOf, runSql, SEARCH_FLAGS, withDb } from './shared.ts';\nimport type { Ctx } from './types.ts';\n\n// Fallback when the first positional is not a command: a saved query, { sql } or { search }.\n// SEARCH_FLAGS override a saved search's fields the same way they override a preset's.\nexport default async function named(ctx: Ctx, queryName: string): Promise<void> {\n const usage = `usage: ${ctx.name} ${queryName} [params...] [--format table|json|csv] [--config path] [--where \"<sql>\"] [--k n] [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude]`;\n const { values, positionals: params } = parse(ctx.argv, usage, { ...SEARCH_FLAGS, ...FORMAT, ...CONFIG });\n const format = rowFormatOf(values);\n const configPath = values.config as string | undefined;\n\n const cfg = ctx.resolveConfig(configPath);\n const entry = cfg.queries[queryName];\n if (entry === undefined) {\n console.error(`unknown command or saved entry: \"${queryName}\"`);\n console.error(`saved queries: ${Object.keys(cfg.queries).sort().join(', ')}`);\n process.exit(2);\n }\n\n if ('sql' in entry) {\n // A saved statement written against `scope` is preset-agnostic, so the same entry can be\n // re-pointed at another layer from the command line instead of being copied per preset.\n runSql(cfg, entry.sql, params, format, `query \"${queryName}\"`, values.preset as string | undefined);\n return;\n }\n\n // A saved search's text is fixed in config; there is nowhere for a positional to bind.\n if (params.length > 0) {\n ctx.usageError(`\"${queryName}\" is a saved search and takes no positional parameters; edit its \"search\" in sense.config.json, or use \"${ctx.name} search\" directly`);\n }\n const k = parseK(values.k as string | undefined, ctx.usageError) ?? entry.k;\n const where = (values.where as string | undefined) ?? entry.where;\n const preset = (values.preset as string | undefined) ?? entry.preset;\n const include = (values.include as string[] | undefined) ?? entry.include;\n const exclude = (values.exclude as string[] | undefined) ?? entry.exclude;\n const noExclude = values['no-exclude'] === true;\n await withDb(ctx, configPath, async (db, resolvedCfg) => printRows(await search(db, resolvedCfg, entry.search, { k, where, preset, include, exclude, noExclude }), format));\n}\n"],"names":["search","printRows","CONFIG","FORMAT","parse","parseK","rowFormatOf","runSql","SEARCH_FLAGS","withDb","named","ctx","queryName","values","usage","name","positionals","params","argv","format","configPath","config","cfg","resolveConfig","entry","queries","undefined","console","error","Object","keys","sort","join","process","exit","sql","preset","length","usageError","k","where","include","exclude","noExclude","db","resolvedCfg"],"mappings":"AAAA,SAASA,MAAM,QAAQ,uBAAuB;AAC9C,SAASC,SAAS,QAAQ,sBAAsB;AAChD,SAASC,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAEC,WAAW,EAAEC,MAAM,EAAEC,YAAY,EAAEC,MAAM,QAAQ,cAAc;AAGvG,6FAA6F;AAC7F,uFAAuF;AACvF,eAAe,eAAeC,MAAMC,GAAQ,EAAEC,SAAiB;QAyBnDP,SACKQ,eACCA,gBACCA,iBACAA;IA5BjB,MAAMC,QAAQ,CAAC,OAAO,EAAEH,IAAII,IAAI,CAAC,CAAC,EAAEH,UAAU,yJAAyJ,CAAC;IACxM,MAAM,EAAEC,MAAM,EAAEG,aAAaC,MAAM,EAAE,GAAGb,MAAMO,IAAIO,IAAI,EAAEJ,OAAO;QAAE,GAAGN,YAAY;QAAE,GAAGL,MAAM;QAAE,GAAGD,MAAM;IAAC;IACvG,MAAMiB,SAASb,YAAYO;IAC3B,MAAMO,aAAaP,OAAOQ,MAAM;IAEhC,MAAMC,MAAMX,IAAIY,aAAa,CAACH;IAC9B,MAAMI,QAAQF,IAAIG,OAAO,CAACb,UAAU;IACpC,IAAIY,UAAUE,WAAW;QACvBC,QAAQC,KAAK,CAAC,CAAC,iCAAiC,EAAEhB,UAAU,CAAC,CAAC;QAC9De,QAAQC,KAAK,CAAC,CAAC,eAAe,EAAEC,OAAOC,IAAI,CAACR,IAAIG,OAAO,EAAEM,IAAI,GAAGC,IAAI,CAAC,OAAO;QAC5EC,QAAQC,IAAI,CAAC;IACf;IAEA,IAAI,SAASV,OAAO;QAClB,yFAAyF;QACzF,wFAAwF;QACxFjB,OAAOe,KAAKE,MAAMW,GAAG,EAAElB,QAAQE,QAAQ,CAAC,OAAO,EAAEP,UAAU,CAAC,CAAC,EAAEC,OAAOuB,MAAM;QAC5E;IACF;IAEA,uFAAuF;IACvF,IAAInB,OAAOoB,MAAM,GAAG,GAAG;QACrB1B,IAAI2B,UAAU,CAAC,CAAC,CAAC,EAAE1B,UAAU,wGAAwG,EAAED,IAAII,IAAI,CAAC,iBAAiB,CAAC;IACpK;IACA,MAAMwB,KAAIlC,UAAAA,OAAOQ,OAAO0B,CAAC,EAAwB5B,IAAI2B,UAAU,eAArDjC,qBAAAA,UAA0DmB,MAAMe,CAAC;IAC3E,MAAMC,SAAS3B,gBAAAA,OAAO2B,KAAK,cAAZ3B,2BAAAA,gBAAuCW,MAAMgB,KAAK;IACjE,MAAMJ,UAAUvB,iBAAAA,OAAOuB,MAAM,cAAbvB,4BAAAA,iBAAwCW,MAAMY,MAAM;IACpE,MAAMK,WAAW5B,kBAAAA,OAAO4B,OAAO,cAAd5B,6BAAAA,kBAA2CW,MAAMiB,OAAO;IACzE,MAAMC,WAAW7B,kBAAAA,OAAO6B,OAAO,cAAd7B,6BAAAA,kBAA2CW,MAAMkB,OAAO;IACzE,MAAMC,YAAY9B,MAAM,CAAC,aAAa,KAAK;IAC3C,MAAMJ,OAAOE,KAAKS,YAAY,OAAOwB,IAAIC,cAAgB5C,UAAU,MAAMD,OAAO4C,IAAIC,aAAarB,MAAMxB,MAAM,EAAE;YAAEuC;YAAGC;YAAOJ;YAAQK;YAASC;YAASC;QAAU,IAAIxB;AACrK"}
@@ -1,6 +1,6 @@
1
1
  import { resolveNote, scopedPaths } from '../commands/index.js';
2
- import { printRows } from '../output.js';
3
- import { findPath } from '../traverse.js';
2
+ import { findPath } from '../graph/traverse.js';
3
+ import { printRows } from '../output/output.js';
4
4
  import { USAGE } from './index.js';
5
5
  import { CONFIG, FORMAT, formatOf, parse, SCOPE, scopeOf, withDb } from './shared.js';
6
6
  // --max-depth must be a positive integer, mirroring shared.ts's parseK.
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/path.ts"],"sourcesContent":["import { resolveNote, scopedPaths } from '../commands/index.ts';\nimport type { Row } from '../output.ts';\nimport { printRows } from '../output.ts';\nimport { findPath } from '../traverse.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, parse, SCOPE, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\n// --max-depth must be a positive integer, mirroring shared.ts's parseK.\nfunction parseMaxDepth(depth: string | undefined, usageError: (message: string) => never): number | undefined {\n if (depth === undefined) return undefined;\n const parsed = Number(depth);\n if (!Number.isInteger(parsed) || parsed <= 0) usageError(`--max-depth expects a positive integer, got \"${depth}\"`);\n return parsed;\n}\n\nconst pathCmd: Command = (ctx) => {\n const usage = `usage: ${ctx.name} ${USAGE.path}`;\n const { values, positionals } = parse(ctx.argv, usage, { ...SCOPE, ...FORMAT, ...CONFIG, 'max-depth': { type: 'string' } });\n const [a, b] = positionals;\n if (!a || !b) ctx.usageError(usage);\n const maxDepth = parseMaxDepth(values['max-depth'] as string | undefined, ctx.usageError);\n const format = formatOf(values);\n return withDb(ctx, values.config as string | undefined, (db, cfg) => {\n const paths = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n const from = resolveNote(paths, a);\n const to = resolveNote(paths, b);\n const allowed = scopedPaths(db, cfg, scopeOf(values));\n const hops = findPath(db, from, to, { maxDepth, allowed });\n\n if (format === 'json') {\n console.log(JSON.stringify(hops));\n return;\n }\n if (hops === null) {\n console.log(maxDepth ? `no path within ${maxDepth} hops` : 'no path');\n return;\n }\n const rows: Row[] = hops.map((p, step) => ({ step, path: p }));\n printRows(rows, format);\n });\n};\nexport default pathCmd;\n"],"names":["resolveNote","scopedPaths","printRows","findPath","USAGE","CONFIG","FORMAT","formatOf","parse","SCOPE","scopeOf","withDb","parseMaxDepth","depth","usageError","undefined","parsed","Number","isInteger","pathCmd","ctx","usage","name","path","values","positionals","argv","type","a","b","maxDepth","format","config","db","cfg","paths","prepare","all","map","r","from","to","allowed","hops","console","log","JSON","stringify","rows","p","step"],"mappings":"AAAA,SAASA,WAAW,EAAEC,WAAW,QAAQ,uBAAuB;AAEhE,SAASC,SAAS,QAAQ,eAAe;AACzC,SAASC,QAAQ,QAAQ,iBAAiB;AAC1C,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,KAAK,EAAEC,KAAK,EAAEC,OAAO,EAAEC,MAAM,QAAQ,cAAc;AAGtF,wEAAwE;AACxE,SAASC,cAAcC,KAAyB,EAAEC,UAAsC;IACtF,IAAID,UAAUE,WAAW,OAAOA;IAChC,MAAMC,SAASC,OAAOJ;IACtB,IAAI,CAACI,OAAOC,SAAS,CAACF,WAAWA,UAAU,GAAGF,WAAW,CAAC,6CAA6C,EAAED,MAAM,CAAC,CAAC;IACjH,OAAOG;AACT;AAEA,MAAMG,UAAmB,CAACC;IACxB,MAAMC,QAAQ,CAAC,OAAO,EAAED,IAAIE,IAAI,CAAC,CAAC,EAAElB,MAAMmB,IAAI,EAAE;IAChD,MAAM,EAAEC,MAAM,EAAEC,WAAW,EAAE,GAAGjB,MAAMY,IAAIM,IAAI,EAAEL,OAAO;QAAE,GAAGZ,KAAK;QAAE,GAAGH,MAAM;QAAE,GAAGD,MAAM;QAAE,aAAa;YAAEsB,MAAM;QAAS;IAAE;IACzH,MAAM,CAACC,GAAGC,EAAE,GAAGJ;IACf,IAAI,CAACG,KAAK,CAACC,GAAGT,IAAIN,UAAU,CAACO;IAC7B,MAAMS,WAAWlB,cAAcY,MAAM,CAAC,YAAY,EAAwBJ,IAAIN,UAAU;IACxF,MAAMiB,SAASxB,SAASiB;IACxB,OAAOb,OAAOS,KAAKI,OAAOQ,MAAM,EAAwB,CAACC,IAAIC;QAC3D,MAAMC,QAAQ,AAACF,GAAGG,OAAO,CAAC,kCAAkCC,GAAG,GAA+BC,GAAG,CAAC,CAACC,IAAMA,EAAEhB,IAAI;QAC/G,MAAMiB,OAAOxC,YAAYmC,OAAOP;QAChC,MAAMa,KAAKzC,YAAYmC,OAAON;QAC9B,MAAMa,UAAUzC,YAAYgC,IAAIC,KAAKxB,QAAQc;QAC7C,MAAMmB,OAAOxC,SAAS8B,IAAIO,MAAMC,IAAI;YAAEX;YAAUY;QAAQ;QAExD,IAAIX,WAAW,QAAQ;YACrBa,QAAQC,GAAG,CAACC,KAAKC,SAAS,CAACJ;YAC3B;QACF;QACA,IAAIA,SAAS,MAAM;YACjBC,QAAQC,GAAG,CAACf,WAAW,CAAC,eAAe,EAAEA,SAAS,KAAK,CAAC,GAAG;YAC3D;QACF;QACA,MAAMkB,OAAcL,KAAKL,GAAG,CAAC,CAACW,GAAGC,OAAU,CAAA;gBAAEA;gBAAM3B,MAAM0B;YAAE,CAAA;QAC3D/C,UAAU8C,MAAMjB;IAClB;AACF;AACA,eAAeZ,QAAQ"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/path.ts"],"sourcesContent":["import { resolveNote, scopedPaths } from '../commands/index.ts';\nimport { findPath } from '../graph/traverse.ts';\nimport type { Row } from '../output/output.ts';\nimport { printRows } from '../output/output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, parse, SCOPE, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\n// --max-depth must be a positive integer, mirroring shared.ts's parseK.\nfunction parseMaxDepth(depth: string | undefined, usageError: (message: string) => never): number | undefined {\n if (depth === undefined) return undefined;\n const parsed = Number(depth);\n if (!Number.isInteger(parsed) || parsed <= 0) usageError(`--max-depth expects a positive integer, got \"${depth}\"`);\n return parsed;\n}\n\nconst pathCmd: Command = (ctx) => {\n const usage = `usage: ${ctx.name} ${USAGE.path}`;\n const { values, positionals } = parse(ctx.argv, usage, { ...SCOPE, ...FORMAT, ...CONFIG, 'max-depth': { type: 'string' } });\n const [a, b] = positionals;\n if (!a || !b) ctx.usageError(usage);\n const maxDepth = parseMaxDepth(values['max-depth'] as string | undefined, ctx.usageError);\n const format = formatOf(values);\n return withDb(ctx, values.config as string | undefined, (db, cfg) => {\n const paths = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n const from = resolveNote(paths, a);\n const to = resolveNote(paths, b);\n const allowed = scopedPaths(db, cfg, scopeOf(values));\n const hops = findPath(db, from, to, { maxDepth, allowed });\n\n if (format === 'json') {\n console.log(JSON.stringify(hops));\n return;\n }\n if (hops === null) {\n console.log(maxDepth ? `no path within ${maxDepth} hops` : 'no path');\n return;\n }\n const rows: Row[] = hops.map((p, step) => ({ step, path: p }));\n printRows(rows, format);\n });\n};\nexport default pathCmd;\n"],"names":["resolveNote","scopedPaths","findPath","printRows","USAGE","CONFIG","FORMAT","formatOf","parse","SCOPE","scopeOf","withDb","parseMaxDepth","depth","usageError","undefined","parsed","Number","isInteger","pathCmd","ctx","usage","name","path","values","positionals","argv","type","a","b","maxDepth","format","config","db","cfg","paths","prepare","all","map","r","from","to","allowed","hops","console","log","JSON","stringify","rows","p","step"],"mappings":"AAAA,SAASA,WAAW,EAAEC,WAAW,QAAQ,uBAAuB;AAChE,SAASC,QAAQ,QAAQ,uBAAuB;AAEhD,SAASC,SAAS,QAAQ,sBAAsB;AAChD,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,KAAK,EAAEC,KAAK,EAAEC,OAAO,EAAEC,MAAM,QAAQ,cAAc;AAGtF,wEAAwE;AACxE,SAASC,cAAcC,KAAyB,EAAEC,UAAsC;IACtF,IAAID,UAAUE,WAAW,OAAOA;IAChC,MAAMC,SAASC,OAAOJ;IACtB,IAAI,CAACI,OAAOC,SAAS,CAACF,WAAWA,UAAU,GAAGF,WAAW,CAAC,6CAA6C,EAAED,MAAM,CAAC,CAAC;IACjH,OAAOG;AACT;AAEA,MAAMG,UAAmB,CAACC;IACxB,MAAMC,QAAQ,CAAC,OAAO,EAAED,IAAIE,IAAI,CAAC,CAAC,EAAElB,MAAMmB,IAAI,EAAE;IAChD,MAAM,EAAEC,MAAM,EAAEC,WAAW,EAAE,GAAGjB,MAAMY,IAAIM,IAAI,EAAEL,OAAO;QAAE,GAAGZ,KAAK;QAAE,GAAGH,MAAM;QAAE,GAAGD,MAAM;QAAE,aAAa;YAAEsB,MAAM;QAAS;IAAE;IACzH,MAAM,CAACC,GAAGC,EAAE,GAAGJ;IACf,IAAI,CAACG,KAAK,CAACC,GAAGT,IAAIN,UAAU,CAACO;IAC7B,MAAMS,WAAWlB,cAAcY,MAAM,CAAC,YAAY,EAAwBJ,IAAIN,UAAU;IACxF,MAAMiB,SAASxB,SAASiB;IACxB,OAAOb,OAAOS,KAAKI,OAAOQ,MAAM,EAAwB,CAACC,IAAIC;QAC3D,MAAMC,QAAQ,AAACF,GAAGG,OAAO,CAAC,kCAAkCC,GAAG,GAA+BC,GAAG,CAAC,CAACC,IAAMA,EAAEhB,IAAI;QAC/G,MAAMiB,OAAOxC,YAAYmC,OAAOP;QAChC,MAAMa,KAAKzC,YAAYmC,OAAON;QAC9B,MAAMa,UAAUzC,YAAYgC,IAAIC,KAAKxB,QAAQc;QAC7C,MAAMmB,OAAOzC,SAAS+B,IAAIO,MAAMC,IAAI;YAAEX;YAAUY;QAAQ;QAExD,IAAIX,WAAW,QAAQ;YACrBa,QAAQC,GAAG,CAACC,KAAKC,SAAS,CAACJ;YAC3B;QACF;QACA,IAAIA,SAAS,MAAM;YACjBC,QAAQC,GAAG,CAACf,WAAW,CAAC,eAAe,EAAEA,SAAS,KAAK,CAAC,GAAG;YAC3D;QACF;QACA,MAAMkB,OAAcL,KAAKL,GAAG,CAAC,CAACW,GAAGC,OAAU,CAAA;gBAAEA;gBAAM3B,MAAM0B;YAAE,CAAA;QAC3D9C,UAAU6C,MAAMjB;IAClB;AACF;AACA,eAAeZ,QAAQ"}
@@ -1,5 +1,5 @@
1
1
  import { peek } from '../commands/index.js';
2
- import { renderPeek } from '../output.js';
2
+ import { renderPeek } from '../output/output.js';
3
3
  import { USAGE } from './index.js';
4
4
  import { CONFIG, FORMAT, formatOf, parse, SCOPE, scopeOf, withDb } from './shared.js';
5
5
  const peekCmd = (ctx)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/peek.ts"],"sourcesContent":["import { peek } from '../commands/index.ts';\nimport { renderPeek } from '../output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, parse, SCOPE, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst peekCmd: Command = (ctx) => {\n const usage = `usage: ${ctx.name} ${USAGE.peek}`;\n const { values, positionals } = parse(ctx.argv, usage, { ...SCOPE, ...FORMAT, ...CONFIG });\n const [pathArg] = positionals;\n if (!pathArg) ctx.usageError(usage);\n const format = formatOf(values);\n return withDb(ctx, values.config as string | undefined, (db, cfg) => {\n const overrides = scopeOf(values);\n const result = peek(db, cfg, pathArg, overrides);\n console.log(format === 'json' ? JSON.stringify(result, null, 2) : renderPeek(result));\n });\n};\nexport default peekCmd;\n"],"names":["peek","renderPeek","USAGE","CONFIG","FORMAT","formatOf","parse","SCOPE","scopeOf","withDb","peekCmd","ctx","usage","name","values","positionals","argv","pathArg","usageError","format","config","db","cfg","overrides","result","console","log","JSON","stringify"],"mappings":"AAAA,SAASA,IAAI,QAAQ,uBAAuB;AAC5C,SAASC,UAAU,QAAQ,eAAe;AAC1C,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,KAAK,EAAEC,KAAK,EAAEC,OAAO,EAAEC,MAAM,QAAQ,cAAc;AAGtF,MAAMC,UAAmB,CAACC;IACxB,MAAMC,QAAQ,CAAC,OAAO,EAAED,IAAIE,IAAI,CAAC,CAAC,EAAEX,MAAMF,IAAI,EAAE;IAChD,MAAM,EAAEc,MAAM,EAAEC,WAAW,EAAE,GAAGT,MAAMK,IAAIK,IAAI,EAAEJ,OAAO;QAAE,GAAGL,KAAK;QAAE,GAAGH,MAAM;QAAE,GAAGD,MAAM;IAAC;IACxF,MAAM,CAACc,QAAQ,GAAGF;IAClB,IAAI,CAACE,SAASN,IAAIO,UAAU,CAACN;IAC7B,MAAMO,SAASd,SAASS;IACxB,OAAOL,OAAOE,KAAKG,OAAOM,MAAM,EAAwB,CAACC,IAAIC;QAC3D,MAAMC,YAAYf,QAAQM;QAC1B,MAAMU,SAASxB,KAAKqB,IAAIC,KAAKL,SAASM;QACtCE,QAAQC,GAAG,CAACP,WAAW,SAASQ,KAAKC,SAAS,CAACJ,QAAQ,MAAM,KAAKvB,WAAWuB;IAC/E;AACF;AACA,eAAed,QAAQ"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/peek.ts"],"sourcesContent":["import { peek } from '../commands/index.ts';\nimport { renderPeek } from '../output/output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, parse, SCOPE, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst peekCmd: Command = (ctx) => {\n const usage = `usage: ${ctx.name} ${USAGE.peek}`;\n const { values, positionals } = parse(ctx.argv, usage, { ...SCOPE, ...FORMAT, ...CONFIG });\n const [pathArg] = positionals;\n if (!pathArg) ctx.usageError(usage);\n const format = formatOf(values);\n return withDb(ctx, values.config as string | undefined, (db, cfg) => {\n const overrides = scopeOf(values);\n const result = peek(db, cfg, pathArg, overrides);\n console.log(format === 'json' ? JSON.stringify(result, null, 2) : renderPeek(result));\n });\n};\nexport default peekCmd;\n"],"names":["peek","renderPeek","USAGE","CONFIG","FORMAT","formatOf","parse","SCOPE","scopeOf","withDb","peekCmd","ctx","usage","name","values","positionals","argv","pathArg","usageError","format","config","db","cfg","overrides","result","console","log","JSON","stringify"],"mappings":"AAAA,SAASA,IAAI,QAAQ,uBAAuB;AAC5C,SAASC,UAAU,QAAQ,sBAAsB;AACjD,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,KAAK,EAAEC,KAAK,EAAEC,OAAO,EAAEC,MAAM,QAAQ,cAAc;AAGtF,MAAMC,UAAmB,CAACC;IACxB,MAAMC,QAAQ,CAAC,OAAO,EAAED,IAAIE,IAAI,CAAC,CAAC,EAAEX,MAAMF,IAAI,EAAE;IAChD,MAAM,EAAEc,MAAM,EAAEC,WAAW,EAAE,GAAGT,MAAMK,IAAIK,IAAI,EAAEJ,OAAO;QAAE,GAAGL,KAAK;QAAE,GAAGH,MAAM;QAAE,GAAGD,MAAM;IAAC;IACxF,MAAM,CAACc,QAAQ,GAAGF;IAClB,IAAI,CAACE,SAASN,IAAIO,UAAU,CAACN;IAC7B,MAAMO,SAASd,SAASS;IACxB,OAAOL,OAAOE,KAAKG,OAAOM,MAAM,EAAwB,CAACC,IAAIC;QAC3D,MAAMC,YAAYf,QAAQM;QAC1B,MAAMU,SAASxB,KAAKqB,IAAIC,KAAKL,SAASM;QACtCE,QAAQC,GAAG,CAACP,WAAW,SAASQ,KAAKC,SAAS,CAACJ,QAAQ,MAAM,KAAKvB,WAAWuB;IAC/E;AACF;AACA,eAAed,QAAQ"}
@@ -1,5 +1,5 @@
1
1
  import { relatedNotes } from '../commands/index.js';
2
- import { printRows } from '../output.js';
2
+ import { printRows } from '../output/output.js';
3
3
  import { USAGE } from './index.js';
4
4
  import { CONFIG, FORMAT, parse, parseK, rowFormatOf, SCOPE, scopeOf, withDb } from './shared.js';
5
5
  const RELATED_DEFAULT_K = 5;
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/related.ts"],"sourcesContent":["import { relatedNotes } from '../commands/index.ts';\nimport type { Row } from '../output.ts';\nimport { printRows } from '../output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, parse, parseK, rowFormatOf, SCOPE, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst RELATED_DEFAULT_K = 5;\n\nconst relatedCmd: Command = (ctx) => {\n const usage = `usage: ${ctx.name} ${USAGE.related}`;\n const { values, positionals } = parse(ctx.argv, usage, { ...SCOPE, ...FORMAT, ...CONFIG, k: { type: 'string' } });\n const [pathArg] = positionals;\n if (!pathArg) ctx.usageError(usage);\n const k = parseK(values.k as string | undefined, ctx.usageError) ?? RELATED_DEFAULT_K;\n const format = rowFormatOf(values);\n return withDb(ctx, values.config as string | undefined, async (db, cfg) => {\n const overrides = scopeOf(values);\n printRows((await relatedNotes(db, cfg, pathArg, overrides, k)) as Row[], format);\n });\n};\nexport default relatedCmd;\n"],"names":["relatedNotes","printRows","USAGE","CONFIG","FORMAT","parse","parseK","rowFormatOf","SCOPE","scopeOf","withDb","RELATED_DEFAULT_K","relatedCmd","ctx","usage","name","related","values","positionals","argv","k","type","pathArg","usageError","format","config","db","cfg","overrides"],"mappings":"AAAA,SAASA,YAAY,QAAQ,uBAAuB;AAEpD,SAASC,SAAS,QAAQ,eAAe;AACzC,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAEC,WAAW,EAAEC,KAAK,EAAEC,OAAO,EAAEC,MAAM,QAAQ,cAAc;AAGjG,MAAMC,oBAAoB;AAE1B,MAAMC,aAAsB,CAACC;QAKjBP;IAJV,MAAMQ,QAAQ,CAAC,OAAO,EAAED,IAAIE,IAAI,CAAC,CAAC,EAAEb,MAAMc,OAAO,EAAE;IACnD,MAAM,EAAEC,MAAM,EAAEC,WAAW,EAAE,GAAGb,MAAMQ,IAAIM,IAAI,EAAEL,OAAO;QAAE,GAAGN,KAAK;QAAE,GAAGJ,MAAM;QAAE,GAAGD,MAAM;QAAEiB,GAAG;YAAEC,MAAM;QAAS;IAAE;IAC/G,MAAM,CAACC,QAAQ,GAAGJ;IAClB,IAAI,CAACI,SAAST,IAAIU,UAAU,CAACT;IAC7B,MAAMM,KAAId,UAAAA,OAAOW,OAAOG,CAAC,EAAwBP,IAAIU,UAAU,eAArDjB,qBAAAA,UAA0DK;IACpE,MAAMa,SAASjB,YAAYU;IAC3B,OAAOP,OAAOG,KAAKI,OAAOQ,MAAM,EAAwB,OAAOC,IAAIC;QACjE,MAAMC,YAAYnB,QAAQQ;QAC1BhB,UAAW,MAAMD,aAAa0B,IAAIC,KAAKL,SAASM,WAAWR,IAAcI;IAC3E;AACF;AACA,eAAeZ,WAAW"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/related.ts"],"sourcesContent":["import { relatedNotes } from '../commands/index.ts';\nimport type { Row } from '../output/output.ts';\nimport { printRows } from '../output/output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, parse, parseK, rowFormatOf, SCOPE, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst RELATED_DEFAULT_K = 5;\n\nconst relatedCmd: Command = (ctx) => {\n const usage = `usage: ${ctx.name} ${USAGE.related}`;\n const { values, positionals } = parse(ctx.argv, usage, { ...SCOPE, ...FORMAT, ...CONFIG, k: { type: 'string' } });\n const [pathArg] = positionals;\n if (!pathArg) ctx.usageError(usage);\n const k = parseK(values.k as string | undefined, ctx.usageError) ?? RELATED_DEFAULT_K;\n const format = rowFormatOf(values);\n return withDb(ctx, values.config as string | undefined, async (db, cfg) => {\n const overrides = scopeOf(values);\n printRows((await relatedNotes(db, cfg, pathArg, overrides, k)) as Row[], format);\n });\n};\nexport default relatedCmd;\n"],"names":["relatedNotes","printRows","USAGE","CONFIG","FORMAT","parse","parseK","rowFormatOf","SCOPE","scopeOf","withDb","RELATED_DEFAULT_K","relatedCmd","ctx","usage","name","related","values","positionals","argv","k","type","pathArg","usageError","format","config","db","cfg","overrides"],"mappings":"AAAA,SAASA,YAAY,QAAQ,uBAAuB;AAEpD,SAASC,SAAS,QAAQ,sBAAsB;AAChD,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAEC,WAAW,EAAEC,KAAK,EAAEC,OAAO,EAAEC,MAAM,QAAQ,cAAc;AAGjG,MAAMC,oBAAoB;AAE1B,MAAMC,aAAsB,CAACC;QAKjBP;IAJV,MAAMQ,QAAQ,CAAC,OAAO,EAAED,IAAIE,IAAI,CAAC,CAAC,EAAEb,MAAMc,OAAO,EAAE;IACnD,MAAM,EAAEC,MAAM,EAAEC,WAAW,EAAE,GAAGb,MAAMQ,IAAIM,IAAI,EAAEL,OAAO;QAAE,GAAGN,KAAK;QAAE,GAAGJ,MAAM;QAAE,GAAGD,MAAM;QAAEiB,GAAG;YAAEC,MAAM;QAAS;IAAE;IAC/G,MAAM,CAACC,QAAQ,GAAGJ;IAClB,IAAI,CAACI,SAAST,IAAIU,UAAU,CAACT;IAC7B,MAAMM,KAAId,UAAAA,OAAOW,OAAOG,CAAC,EAAwBP,IAAIU,UAAU,eAArDjB,qBAAAA,UAA0DK;IACpE,MAAMa,SAASjB,YAAYU;IAC3B,OAAOP,OAAOG,KAAKI,OAAOQ,MAAM,EAAwB,OAAOC,IAAIC;QACjE,MAAMC,YAAYnB,QAAQQ;QAC1BhB,UAAW,MAAMD,aAAa0B,IAAIC,KAAKL,SAASM,WAAWR,IAAcI;IAC3E;AACF;AACA,eAAeZ,WAAW"}
@@ -1,5 +1,5 @@
1
1
  import { search } from '../commands/index.js';
2
- import { printRows } from '../output.js';
2
+ import { printRows } from '../output/output.js';
3
3
  import { USAGE } from './index.js';
4
4
  import { CONFIG, FORMAT, parse, parseK, rowFormatOf, SEARCH_FLAGS, scopeOf, withDb } from './shared.js';
5
5
  const searchCmd = async (ctx)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/search.ts"],"sourcesContent":["import { search } from '../commands/index.ts';\nimport { printRows } from '../output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, parse, parseK, rowFormatOf, SEARCH_FLAGS, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst searchCmd: Command = async (ctx) => {\n const usage = `usage: ${ctx.name} ${USAGE.search}`;\n const { values, positionals } = parse(ctx.argv, usage, { ...SEARCH_FLAGS, ...FORMAT, ...CONFIG });\n const [terms] = positionals;\n if (!terms) ctx.usageError(usage);\n const k = parseK(values.k as string | undefined, ctx.usageError);\n const format = rowFormatOf(values);\n await withDb(ctx, values.config as string | undefined, async (db, cfg) => printRows(await search(db, cfg, terms, { k, ...scopeOf(values) }), format));\n};\nexport default searchCmd;\n"],"names":["search","printRows","USAGE","CONFIG","FORMAT","parse","parseK","rowFormatOf","SEARCH_FLAGS","scopeOf","withDb","searchCmd","ctx","usage","name","values","positionals","argv","terms","usageError","k","format","config","db","cfg"],"mappings":"AAAA,SAASA,MAAM,QAAQ,uBAAuB;AAC9C,SAASC,SAAS,QAAQ,eAAe;AACzC,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAEC,WAAW,EAAEC,YAAY,EAAEC,OAAO,EAAEC,MAAM,QAAQ,cAAc;AAGxG,MAAMC,YAAqB,OAAOC;IAChC,MAAMC,QAAQ,CAAC,OAAO,EAAED,IAAIE,IAAI,CAAC,CAAC,EAAEZ,MAAMF,MAAM,EAAE;IAClD,MAAM,EAAEe,MAAM,EAAEC,WAAW,EAAE,GAAGX,MAAMO,IAAIK,IAAI,EAAEJ,OAAO;QAAE,GAAGL,YAAY;QAAE,GAAGJ,MAAM;QAAE,GAAGD,MAAM;IAAC;IAC/F,MAAM,CAACe,MAAM,GAAGF;IAChB,IAAI,CAACE,OAAON,IAAIO,UAAU,CAACN;IAC3B,MAAMO,IAAId,OAAOS,OAAOK,CAAC,EAAwBR,IAAIO,UAAU;IAC/D,MAAME,SAASd,YAAYQ;IAC3B,MAAML,OAAOE,KAAKG,OAAOO,MAAM,EAAwB,OAAOC,IAAIC,MAAQvB,UAAU,MAAMD,OAAOuB,IAAIC,KAAKN,OAAO;YAAEE;YAAG,GAAGX,QAAQM,OAAO;QAAC,IAAIM;AAC/I;AACA,eAAeV,UAAU"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/search.ts"],"sourcesContent":["import { search } from '../commands/index.ts';\nimport { printRows } from '../output/output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, parse, parseK, rowFormatOf, SEARCH_FLAGS, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst searchCmd: Command = async (ctx) => {\n const usage = `usage: ${ctx.name} ${USAGE.search}`;\n const { values, positionals } = parse(ctx.argv, usage, { ...SEARCH_FLAGS, ...FORMAT, ...CONFIG });\n const [terms] = positionals;\n if (!terms) ctx.usageError(usage);\n const k = parseK(values.k as string | undefined, ctx.usageError);\n const format = rowFormatOf(values);\n await withDb(ctx, values.config as string | undefined, async (db, cfg) => printRows(await search(db, cfg, terms, { k, ...scopeOf(values) }), format));\n};\nexport default searchCmd;\n"],"names":["search","printRows","USAGE","CONFIG","FORMAT","parse","parseK","rowFormatOf","SEARCH_FLAGS","scopeOf","withDb","searchCmd","ctx","usage","name","values","positionals","argv","terms","usageError","k","format","config","db","cfg"],"mappings":"AAAA,SAASA,MAAM,QAAQ,uBAAuB;AAC9C,SAASC,SAAS,QAAQ,sBAAsB;AAChD,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAEC,WAAW,EAAEC,YAAY,EAAEC,OAAO,EAAEC,MAAM,QAAQ,cAAc;AAGxG,MAAMC,YAAqB,OAAOC;IAChC,MAAMC,QAAQ,CAAC,OAAO,EAAED,IAAIE,IAAI,CAAC,CAAC,EAAEZ,MAAMF,MAAM,EAAE;IAClD,MAAM,EAAEe,MAAM,EAAEC,WAAW,EAAE,GAAGX,MAAMO,IAAIK,IAAI,EAAEJ,OAAO;QAAE,GAAGL,YAAY;QAAE,GAAGJ,MAAM;QAAE,GAAGD,MAAM;IAAC;IAC/F,MAAM,CAACe,MAAM,GAAGF;IAChB,IAAI,CAACE,OAAON,IAAIO,UAAU,CAACN;IAC3B,MAAMO,IAAId,OAAOS,OAAOK,CAAC,EAAwBR,IAAIO,UAAU;IAC/D,MAAME,SAASd,YAAYQ;IAC3B,MAAML,OAAOE,KAAKG,OAAOO,MAAM,EAAwB,OAAOC,IAAIC,MAAQvB,UAAU,MAAMD,OAAOuB,IAAIC,KAAKN,OAAO;YAAEE;YAAG,GAAGX,QAAQM,OAAO;QAAC,IAAIM;AAC/I;AACA,eAAeV,UAAU"}