sensemaking 0.9.5 → 0.11.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 (177) hide show
  1. package/README.md +27 -22
  2. package/dist/cjs/cli/download.d.cts +3 -0
  3. package/dist/cjs/cli/download.d.ts +3 -0
  4. package/dist/cjs/cli/download.js +214 -0
  5. package/dist/cjs/cli/download.js.map +1 -0
  6. package/dist/cjs/cli/index.d.cts +6 -5
  7. package/dist/cjs/cli/index.d.ts +6 -5
  8. package/dist/cjs/cli/index.js +20 -14
  9. package/dist/cjs/cli/index.js.map +1 -1
  10. package/dist/cjs/cli/init.js +4 -1
  11. package/dist/cjs/cli/init.js.map +1 -1
  12. package/dist/cjs/cli/map.js +2 -2
  13. package/dist/cjs/cli/map.js.map +1 -1
  14. package/dist/cjs/cli/named.js +13 -19
  15. package/dist/cjs/cli/named.js.map +1 -1
  16. package/dist/cjs/cli/path.d.cts +3 -0
  17. package/dist/cjs/cli/path.d.ts +3 -0
  18. package/dist/cjs/cli/path.js +161 -0
  19. package/dist/cjs/cli/path.js.map +1 -0
  20. package/dist/cjs/cli/peek.js +3 -2
  21. package/dist/cjs/cli/peek.js.map +1 -1
  22. package/dist/cjs/cli/related.d.cts +3 -0
  23. package/dist/cjs/cli/related.d.ts +3 -0
  24. package/dist/cjs/cli/related.js +279 -0
  25. package/dist/cjs/cli/related.js.map +1 -0
  26. package/dist/cjs/cli/search.js +3 -7
  27. package/dist/cjs/cli/search.js.map +1 -1
  28. package/dist/cjs/cli/shared.d.cts +4 -2
  29. package/dist/cjs/cli/shared.d.ts +4 -2
  30. package/dist/cjs/cli/shared.js +49 -6
  31. package/dist/cjs/cli/shared.js.map +1 -1
  32. package/dist/cjs/cli/sql.d.cts +3 -0
  33. package/dist/cjs/cli/sql.d.ts +3 -0
  34. package/dist/cjs/cli/{query.js → sql.js} +33 -5
  35. package/dist/cjs/cli/sql.js.map +1 -0
  36. package/dist/cjs/cli/status.d.cts +1 -0
  37. package/dist/cjs/cli/status.d.ts +1 -0
  38. package/dist/cjs/cli/status.js +80 -10
  39. package/dist/cjs/cli/status.js.map +1 -1
  40. package/dist/cjs/cli.js +14 -15
  41. package/dist/cjs/cli.js.map +1 -1
  42. package/dist/cjs/commands.d.cts +13 -4
  43. package/dist/cjs/commands.d.ts +13 -4
  44. package/dist/cjs/commands.js +161 -61
  45. package/dist/cjs/commands.js.map +1 -1
  46. package/dist/cjs/config.d.cts +6 -4
  47. package/dist/cjs/config.d.ts +6 -4
  48. package/dist/cjs/config.js +137 -58
  49. package/dist/cjs/config.js.map +1 -1
  50. package/dist/cjs/db.d.cts +2 -2
  51. package/dist/cjs/db.d.ts +2 -2
  52. package/dist/cjs/db.js +25 -46
  53. package/dist/cjs/db.js.map +1 -1
  54. package/dist/cjs/errors.d.cts +1 -1
  55. package/dist/cjs/errors.d.ts +1 -1
  56. package/dist/cjs/errors.js.map +1 -1
  57. package/dist/cjs/features/embed.d.cts +15 -0
  58. package/dist/cjs/features/embed.d.ts +15 -0
  59. package/dist/cjs/features/embed.js +277 -61
  60. package/dist/cjs/features/embed.js.map +1 -1
  61. package/dist/cjs/features/links.js +7 -16
  62. package/dist/cjs/features/links.js.map +1 -1
  63. package/dist/cjs/features/rank.js +2 -6
  64. package/dist/cjs/features/rank.js.map +1 -1
  65. package/dist/cjs/index.d.cts +2 -2
  66. package/dist/cjs/index.d.ts +2 -2
  67. package/dist/cjs/index.js +3 -3
  68. package/dist/cjs/index.js.map +1 -1
  69. package/dist/cjs/output.d.cts +3 -0
  70. package/dist/cjs/output.d.ts +3 -0
  71. package/dist/cjs/output.js +17 -15
  72. package/dist/cjs/output.js.map +1 -1
  73. package/dist/cjs/progress.js +2 -4
  74. package/dist/cjs/progress.js.map +1 -1
  75. package/dist/cjs/scan.d.cts +2 -0
  76. package/dist/cjs/scan.d.ts +2 -0
  77. package/dist/cjs/scan.js +150 -44
  78. package/dist/cjs/scan.js.map +1 -1
  79. package/dist/cjs/search-error.js +4 -6
  80. package/dist/cjs/search-error.js.map +1 -1
  81. package/dist/cjs/traverse.d.cts +8 -0
  82. package/dist/cjs/traverse.d.ts +8 -0
  83. package/dist/cjs/traverse.js +97 -0
  84. package/dist/cjs/traverse.js.map +1 -0
  85. package/dist/esm/cli/download.d.ts +3 -0
  86. package/dist/esm/cli/download.js +27 -0
  87. package/dist/esm/cli/download.js.map +1 -0
  88. package/dist/esm/cli/index.d.ts +6 -5
  89. package/dist/esm/cli/index.js +13 -11
  90. package/dist/esm/cli/index.js.map +1 -1
  91. package/dist/esm/cli/init.js +4 -1
  92. package/dist/esm/cli/init.js.map +1 -1
  93. package/dist/esm/cli/map.js +3 -2
  94. package/dist/esm/cli/map.js.map +1 -1
  95. package/dist/esm/cli/named.js +13 -17
  96. package/dist/esm/cli/named.js.map +1 -1
  97. package/dist/esm/cli/path.d.ts +3 -0
  98. package/dist/esm/cli/path.js +51 -0
  99. package/dist/esm/cli/path.js.map +1 -0
  100. package/dist/esm/cli/peek.js +4 -2
  101. package/dist/esm/cli/peek.js.map +1 -1
  102. package/dist/esm/cli/related.d.ts +3 -0
  103. package/dist/esm/cli/related.js +26 -0
  104. package/dist/esm/cli/related.js.map +1 -0
  105. package/dist/esm/cli/search.js +2 -5
  106. package/dist/esm/cli/search.js.map +1 -1
  107. package/dist/esm/cli/shared.d.ts +4 -2
  108. package/dist/esm/cli/shared.js +49 -6
  109. package/dist/esm/cli/shared.js.map +1 -1
  110. package/dist/esm/cli/sql.d.ts +3 -0
  111. package/dist/esm/cli/{query.js → sql.js} +8 -5
  112. package/dist/esm/cli/sql.js.map +1 -0
  113. package/dist/esm/cli/status.d.ts +1 -0
  114. package/dist/esm/cli/status.js +72 -8
  115. package/dist/esm/cli/status.js.map +1 -1
  116. package/dist/esm/cli.js +13 -10
  117. package/dist/esm/cli.js.map +1 -1
  118. package/dist/esm/commands.d.ts +13 -4
  119. package/dist/esm/commands.js +135 -72
  120. package/dist/esm/commands.js.map +1 -1
  121. package/dist/esm/config.d.ts +6 -4
  122. package/dist/esm/config.js +126 -75
  123. package/dist/esm/config.js.map +1 -1
  124. package/dist/esm/db.d.ts +2 -2
  125. package/dist/esm/db.js +28 -48
  126. package/dist/esm/db.js.map +1 -1
  127. package/dist/esm/errors.d.ts +1 -1
  128. package/dist/esm/errors.js.map +1 -1
  129. package/dist/esm/features/embed.d.ts +15 -0
  130. package/dist/esm/features/embed.js +137 -42
  131. package/dist/esm/features/embed.js.map +1 -1
  132. package/dist/esm/features/links.js +8 -17
  133. package/dist/esm/features/links.js.map +1 -1
  134. package/dist/esm/features/rank.js +2 -6
  135. package/dist/esm/features/rank.js.map +1 -1
  136. package/dist/esm/features/types.js.map +1 -1
  137. package/dist/esm/index.d.ts +2 -2
  138. package/dist/esm/index.js +1 -1
  139. package/dist/esm/index.js.map +1 -1
  140. package/dist/esm/output.d.ts +3 -0
  141. package/dist/esm/output.js +19 -17
  142. package/dist/esm/output.js.map +1 -1
  143. package/dist/esm/progress.js +2 -4
  144. package/dist/esm/progress.js.map +1 -1
  145. package/dist/esm/scan.d.ts +2 -0
  146. package/dist/esm/scan.js +123 -47
  147. package/dist/esm/scan.js.map +1 -1
  148. package/dist/esm/search-error.js +4 -6
  149. package/dist/esm/search-error.js.map +1 -1
  150. package/dist/esm/traverse.d.ts +8 -0
  151. package/dist/esm/traverse.js +71 -0
  152. package/dist/esm/traverse.js.map +1 -0
  153. package/package.json +7 -3
  154. package/schema.json +12 -16
  155. package/skills/sense/EXAMPLES.md +8 -8
  156. package/skills/sense/SKILL.md +51 -23
  157. package/skills/sense-setup/EXAMPLES.md +24 -21
  158. package/skills/sense-setup/SKILL.md +9 -9
  159. package/dist/cjs/cli/check.d.cts +0 -3
  160. package/dist/cjs/cli/check.d.ts +0 -3
  161. package/dist/cjs/cli/check.js +0 -398
  162. package/dist/cjs/cli/check.js.map +0 -1
  163. package/dist/cjs/cli/query.d.cts +0 -3
  164. package/dist/cjs/cli/query.d.ts +0 -3
  165. package/dist/cjs/cli/query.js.map +0 -1
  166. package/dist/cjs/cli/rebuild.d.cts +0 -3
  167. package/dist/cjs/cli/rebuild.d.ts +0 -3
  168. package/dist/cjs/cli/rebuild.js +0 -50
  169. package/dist/cjs/cli/rebuild.js.map +0 -1
  170. package/dist/esm/cli/check.d.ts +0 -3
  171. package/dist/esm/cli/check.js +0 -94
  172. package/dist/esm/cli/check.js.map +0 -1
  173. package/dist/esm/cli/query.d.ts +0 -3
  174. package/dist/esm/cli/query.js.map +0 -1
  175. package/dist/esm/cli/rebuild.d.ts +0 -3
  176. package/dist/esm/cli/rebuild.js +0 -13
  177. package/dist/esm/cli/rebuild.js.map +0 -1
package/README.md CHANGED
@@ -13,15 +13,16 @@ Markdown notes accumulate: research, decisions, meeting notes, agent output. Pas
13
13
  ```bash
14
14
  npm install -g sensemaking
15
15
  cd your-notes && sense init
16
+ sense download # the embedding model, once per machine; nothing fetches it implicitly
16
17
  ```
17
18
 
18
- Needs Node 22.16 or newer: that is the first release whose built-in SQLite carries FTS5, which `sense search` indexes prose with.
19
+ Needs Node 22.20 or newer: the first release whose built-in SQLite has both FTS5, which `sense search` indexes prose with, and row-returning `INSERT ... RETURNING`, which `sense path` and `peek` walk the link graph with.
19
20
 
20
21
  ```bash
21
22
  sense map # orient: fields, hub notes, recent changes
22
23
  sense search "revenue OR earnings" --k 10 # locate: words + links + meaning, one ranked list
23
24
  sense peek notes/q3-report.md # structure: outline + links, before reading
24
- sense query "SELECT path FROM frontmatter WHERE has(tags, ?)" urgent
25
+ sense sql "SELECT path FROM frontmatter WHERE has(tags, ?)" urgent
25
26
  ```
26
27
 
27
28
  ## Model
@@ -30,14 +31,15 @@ Every file becomes rows in these tables, plus whatever an enabled feature adds o
30
31
 
31
32
  | table | holds | for |
32
33
  |---|---|---|
33
- | `frontmatter` | one column per key, plus `path`, `_mtime`, `_size`, `_rank` | filtering |
34
+ | `frontmatter` | one column per key, plus `path`, `_mtime`, `_size`, `_rank`, `_parse_error` | filtering |
34
35
  | `content` | FTS5 index: `title`, `summary`, `text` | search and ranking |
35
- | `links` | `src`, `target` as written, `dst` resolved (`NULL` = dead link) | graph |
36
+ | `links` | `src`, `target` as written, `dst` resolved (`NULL` = dead link, but see the skill: a link to an attachment can never resolve) | graph |
36
37
  | `sections` | heading, `level`, `start_line`, `end_line`, `tokens` estimate | structure |
38
+ | `preset_files` | `path`, `preset` | which presets cover which files; `sql --preset` binds these as a `scope` table to join, since `sql` is otherwise index-wide |
37
39
 
38
40
  Results are references (path, title, summary, excerpt), never file contents. Reading happens afterward through the filesystem, scoped to the line ranges `peek` returns. This is the [just-in-time context pattern](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents): the agent holds lightweight identifiers and loads payloads only when needed.
39
41
 
40
- Output size is a contract, measured per release ([BENCHMARKING.md](BENCHMARKING.md)): `map` is fixed-size, a `find` row is tens of tokens, and a `peek` stays flat however large the note is. What it saves over reading grows with the file; a small note is cheaper to read whole.
42
+ Output size is a contract, measured per release ([BENCHMARKING.md](BENCHMARKING.md)): `map` is fixed-size, a `search` row is tens of tokens, and a `peek` stays flat however large the note is. What it saves over reading grows with the file; a small note is cheaper to read whole.
41
43
 
42
44
  ```sql
43
45
  -- filter and search compose in one query
@@ -52,17 +54,18 @@ ORDER BY bm25(content, 10.0, 5.0, 1.0) LIMIT 10
52
54
  | command | does |
53
55
  |---|---|
54
56
  | `map` | doc count, frontmatter field coverage, top hubs by link rank, recent changes |
55
- | `search "<text>" [--preset name] [--include glob] [--where "<sql>"] [--k n] [--lexical]` | words + links + vectors, one fused ranked list; `via` labels each row's evidence |
56
- | `peek <path>` | frontmatter + heading outline (`[L143-162, ~380t]`) + links both ways: first 20 per list, each with its total; the `links` table has the rest |
57
- | `query "<sql>" [params...]` | ad-hoc SQL over all the tables; `?` binds positional args |
57
+ | `search "<text>" [--preset name] [--include glob] [--exclude glob] [--no-exclude] [--where "<sql>"] [--k n]` | words + links + vectors, one fused ranked list; `via` labels each row's evidence |
58
+ | `peek <path> [--preset name] [--where "<sql>"]` | frontmatter + heading outline (`[L143-162, ~380t]`) + links both ways (first 20 per list, each with its total) |
59
+ | `path <a> <b> [--max-depth n] [--preset name] [--where "<sql>"]` | shortest link chain between two notes, or none within the bound |
60
+ | `related <note> [--k n] [--preset name] [--where "<sql>"]` | notes similar in meaning that `<note>` does not yet link to; reads vectors, so semantic-search cost |
61
+ | `sql "<statement>" [params...] [--preset name]` | ad-hoc SQL over all the tables; `?` binds positional args. Index-wide by default; `--preset` binds the preset's paths as a `scope` table the statement joins |
58
62
  | `<name> [params...]` | run a query saved in the config; `--list` names them |
59
63
  | `init` | write a starter `sense.config.json` |
60
64
  | `status` | index location, doc count, per-preset coverage, watcher heartbeat |
61
- | `check` | run every saved query and search, so a broken one fails here instead of mid-task |
62
- | `rebuild` | delete the cache and re-crawl |
65
+ | `download` | fetch the embedding model named in the config (once per machine; nothing else downloads it) |
63
66
  | `watch` | keep the index warm in the background (optional; see [WATCH.md](WATCH.md)) |
64
67
 
65
- `search` runs one text through every engine its scope has: FTS5 word match (BM25-ranked, bare words AND-join, operators are yours), a personalized-PageRank walk over the link graph, and vector similarity, fused into one list. `via` labels each row's evidence (`match`, `link`, `vector`, combinations); `similarity` is the cosine against the best-matching chunk; `lines` points at the section that earned the row (a direct read range). A `vector`-only row means the search words don't appear in that note; it showed up because the model judged it semantically related. `--preset` picks a named settings bundle from the config, `--lexical` skips vectors for one command, `--where` filters on frontmatter. `--format json` on any reporting command returns structured output; `--version` and `--help` do what they say.
68
+ `search` runs one text through every engine its scope has: FTS5 word match (BM25-ranked, bare words AND-join, operators are yours), a personalized-PageRank walk over the link graph, and vector similarity, fused into one list. `via` labels each row's evidence (`match`, `link`, `vector`, combinations); `similarity` is the cosine against the best-matching chunk; `lines` points at the section that earned the row (a direct read range). A `vector`-only row means the search words don't appear in that note; it showed up because the model judged it semantically related. `--preset` picks a named settings bundle from the config, `--where` filters on frontmatter. `--format json` on any reporting command returns structured output; `--version` and `--help` do what they say.
66
69
 
67
70
  ## Config
68
71
 
@@ -71,28 +74,30 @@ ORDER BY bm25(content, 10.0, 5.0, 1.0) LIMIT 10
71
74
  ```json
72
75
  {
73
76
  "$schema": "https://unpkg.com/sensemaking/schema.json",
74
- "version": 3,
77
+ "version": 4,
75
78
  "presets": {
76
79
  "default": { "include": ["**/*.md"], "k": 10 },
77
- "raw": { "include": ["raw/**/*.md"], "k": 5, "semantic": false }
80
+ "raw": { "include": ["raw/**/*.md"], "k": 5 }
78
81
  },
82
+ "embed": { "model": "minishlab/potion-retrieval-32M", "type": "static" },
79
83
  "queries": {
80
- "dead-links": "SELECT src, target FROM links WHERE dst IS NULL",
81
- "by-tag": "SELECT path, title FROM frontmatter WHERE has(tags, ?) ORDER BY path",
82
- "hot": { "search": "pricing OR billing", "preset": "raw" }
84
+ "dead-links": { "sql": "SELECT src, target FROM links WHERE dst IS NULL" },
85
+ "by-tag": { "sql": "SELECT path, title FROM frontmatter WHERE has(tags, ?) ORDER BY path" },
86
+ "hot": { "search": "pricing OR billing", "preset": "raw" }
83
87
  }
84
88
  }
85
89
  ```
86
90
 
87
91
  | key | holds |
88
92
  |---|---|
89
- | `presets` | named bundles of `include`/`exclude` globs, `k` (result count), `semantic` (vectors, on unless `false`), `where` (a standing SQL filter). A file is indexed if any preset includes it, embedded if any covering preset has `semantic` on. A `semantic: false` preset's files cost no vectors, and `status` shows each preset's coverage. |
90
- | `queries` | a SQL string (`?` binds positional args) or a saved search with its settings baked in: `sense hot` needs no flags. `sense check` runs them all, so a typo'd column fails at check time instead of mid-task. |
93
+ | `presets` | named bundles of `include`/`exclude` globs, `k` (result count), `semantic` (vectors for this scope, on unless `false`), `where` (a standing SQL filter). A file is indexed if any preset includes it, embedded if a model is named and some covering preset has `semantic` on; `status` shows each preset's coverage. |
94
+ | `embed` | the model vectors are built with. Naming one gives the tree vectors; omitting the block means none at all, whatever the presets say. `sense download` fetches it. |
95
+ | `queries` | entries runnable as `sense <name>`, each naming the verb it runs: `{ sql }` for SQL (`?` binds positional args) or `{ search }` for a ranked search with its settings baked in, so `sense hot` needs no flags. Running an entry validates it: a typo'd column errors and exits nonzero, and a parameterised entry validates with any argument, since preparing precedes binding. |
91
96
  | `version` | schema version; older configs auto-migrate on load, noted on stderr. |
92
97
 
93
98
  Bare commands use the `default` preset; `--preset` names another; flags override single fields. Editing a preset rebuilds the cache and says which preset caused it.
94
99
 
95
- Vectors use the built-in static model (downloaded to `~/.cache/sensemaking` on first use, never in the package); an optional top-level `"embed": { "model", "type", "url", "key" }` block points at any Model2Vec model, local path, or OpenAI-compatible endpoint (Ollama, LM Studio, hosted). Embedding happens on the first semantic search, with progress.
100
+ Vectors need a model, and nothing downloads it implicitly: `sense download` fetches it once per machine into `$XDG_CACHE_HOME/sensemaking/models` (or `~/.cache/...`), one directory per model, shared by every tree (124 MB, never in the package). `embed.model` is a Hugging Face id, or a path to a directory holding `model.safetensors` and `tokenizer.json`, which `sense download` leaves to you to populate. A preset that asks for vectors without the model is an error naming `sense download`, rather than a quieter result that would make the same search answer differently before and after; a `semantic: false` preset never asks, so it is unaffected. An optional top-level `"embed": { "model", "type", "url", "key" }` block points at any Model2Vec model, local path, or OpenAI-compatible endpoint (Ollama, LM Studio, hosted). Embedding the notes themselves happens on the first semantic search, with progress.
96
101
 
97
102
  `has(field, value)` is the one custom SQL function: array membership on JSON-array fields, substring on strings, false on missing keys. Frontmatter parsing is lenient: syntax errors are per-file warnings, and the values are still indexed, so one bad note never costs you the crawl.
98
103
 
@@ -102,7 +107,7 @@ Every query starts with a freshness check against the cache in `.sense/`; only c
102
107
 
103
108
  - **Work is linear in note count.** Crawl, reconcile, and the freshness check are what every invocation pays; that check is the floor cost of a query and the first thing to watch on a large tree.
104
109
  - **Output is flat.** `map`, `peek`, and a search row cost the same on a small tree as a large one: context cost is bounded by what you ask for, not by how much there is.
105
- - **Bulk changes are paid by whoever queries next.** `sense watch` moves that re-parse into the background ([WATCH.md](WATCH.md)): it changes latency, never answers, since every query reconciles for itself. `sense rebuild` starts the cache over.
110
+ - **Bulk changes are paid by whoever queries next.** `sense watch` moves that re-parse into the background ([WATCH.md](WATCH.md)): it changes latency, never answers, since every query reconciles for itself. To start the cache over, delete the directory `sense status` prints.
106
111
 
107
112
  These are release gates rather than hopes: every release regenerates the numbers on pinned corpora spanning a 4x range in note count plus a stress tree that packs the worst measured shapes into one place: a megabyte-scale note, heading-dense outlines, dense link graphs, hundreds of frontmatter fields. A row that grows faster than linearly, or a token count that grows at all, blocks the release. Current figures: [BENCHMARKING.md](BENCHMARKING.md).
108
113
 
@@ -117,7 +122,7 @@ Two skills: `sense` for querying a tree (what each command is for, FTS5 syntax,
117
122
  ## Prior art
118
123
 
119
124
  - [Effective context engineering for AI agents](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents) (Anthropic): agents should hold lightweight identifiers (file paths, links) and load payloads just in time, because context is a finite resource. The commands implement that pattern as a CLI.
120
- - [llm-wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) (Karpathy): an agent-maintained wiki navigated by an `index.md` and links, which he notes needs real search infrastructure past a few hundred pages. `sense map` derives that index from the notes instead of maintaining it; `find` is the hybrid local search it calls for.
125
+ - [llm-wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) (Karpathy): an agent-maintained wiki navigated by an `index.md` and links, which he notes needs real search infrastructure past a few hundred pages. `sense map` derives that index from the notes instead of maintaining it; `sense search` is the hybrid local search it calls for.
121
126
  - Agent memory patterns (llm-wiki's raw/wiki split, Claude Code's dreaming-style nightly consolidation) are trees of small notes with metadata, links, and layers of differing authority. sense is the query layer such patterns need: filter by metadata and age, scope by layer, surface near-duplicates semantically. It isn't an implementation of any one of them.
122
127
 
123
128
  ## Alternatives
@@ -130,7 +135,7 @@ Two skills: `sense` for querying a tree (what each command is for, FTS5 syntax,
130
135
  - **RAG / vector stores:** similarity can't express `WHERE status = 'active'`. Here vectors are one signal inside `search`: same SQLite file, filters compose, every row labels its evidence (`via`), and a preset turns vectors off per layer of the tree. No second store, no daemon, no native builds.
131
136
  - **Document-OS apps (Anytype, Logseq, SilverBullet, Capacities):** full applications with their own UI and storage. `sense` is headless: your files stay files, there's no app to run.
132
137
 
133
- Dependencies: [yaml](https://github.com/eemeli/yaml), [remove-markdown](https://github.com/zuchka/remove-markdown), [fast-glob](https://github.com/mrmlnc/fast-glob), [@huggingface/tokenizers](https://github.com/huggingface/tokenizers.js) (pure JS), and Node's built-in SQLite. No native builds.
138
+ Dependencies: [yaml](https://github.com/eemeli/yaml), [remove-markdown](https://github.com/zuchka/remove-markdown), [@huggingface/tokenizers](https://github.com/huggingface/tokenizers.js) (pure JS), and Node's built-in SQLite. No native builds.
134
139
 
135
140
  ## License
136
141
 
@@ -0,0 +1,3 @@
1
+ import type { Command } from './types.js';
2
+ declare const download: Command;
3
+ export default download;
@@ -0,0 +1,3 @@
1
+ import type { Command } from './types.js';
2
+ declare const download: Command;
3
+ export default download;
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return _default;
9
+ }
10
+ });
11
+ var _configts = require("../config.js");
12
+ var _errorsts = require("../errors.js");
13
+ var _embedts = require("../features/embed.js");
14
+ var _indexts = require("./index.js");
15
+ var _sharedts = require("./shared.js");
16
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
17
+ try {
18
+ var info = gen[key](arg);
19
+ var value = info.value;
20
+ } catch (error) {
21
+ reject(error);
22
+ return;
23
+ }
24
+ if (info.done) {
25
+ resolve(value);
26
+ } else {
27
+ Promise.resolve(value).then(_next, _throw);
28
+ }
29
+ }
30
+ function _async_to_generator(fn) {
31
+ return function() {
32
+ var self = this, args = arguments;
33
+ return new Promise(function(resolve, reject) {
34
+ var gen = fn.apply(self, args);
35
+ function _next(value) {
36
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
37
+ }
38
+ function _throw(err) {
39
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
40
+ }
41
+ _next(undefined);
42
+ });
43
+ };
44
+ }
45
+ function _define_property(obj, key, value) {
46
+ if (key in obj) {
47
+ Object.defineProperty(obj, key, {
48
+ value: value,
49
+ enumerable: true,
50
+ configurable: true,
51
+ writable: true
52
+ });
53
+ } else {
54
+ obj[key] = value;
55
+ }
56
+ return obj;
57
+ }
58
+ function _object_spread(target) {
59
+ for(var i = 1; i < arguments.length; i++){
60
+ var source = arguments[i] != null ? arguments[i] : {};
61
+ var ownKeys = Object.keys(source);
62
+ if (typeof Object.getOwnPropertySymbols === "function") {
63
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
64
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
65
+ }));
66
+ }
67
+ ownKeys.forEach(function(key) {
68
+ _define_property(target, key, source[key]);
69
+ });
70
+ }
71
+ return target;
72
+ }
73
+ function _ts_generator(thisArg, body) {
74
+ var f, y, t, _ = {
75
+ label: 0,
76
+ sent: function() {
77
+ if (t[0] & 1) throw t[1];
78
+ return t[1];
79
+ },
80
+ trys: [],
81
+ ops: []
82
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
83
+ return d(g, "next", {
84
+ value: verb(0)
85
+ }), d(g, "throw", {
86
+ value: verb(1)
87
+ }), d(g, "return", {
88
+ value: verb(2)
89
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
90
+ value: function() {
91
+ return this;
92
+ }
93
+ }), g;
94
+ function verb(n) {
95
+ return function(v) {
96
+ return step([
97
+ n,
98
+ v
99
+ ]);
100
+ };
101
+ }
102
+ function step(op) {
103
+ if (f) throw new TypeError("Generator is already executing.");
104
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
105
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
106
+ if (y = 0, t) op = [
107
+ op[0] & 2,
108
+ t.value
109
+ ];
110
+ switch(op[0]){
111
+ case 0:
112
+ case 1:
113
+ t = op;
114
+ break;
115
+ case 4:
116
+ _.label++;
117
+ return {
118
+ value: op[1],
119
+ done: false
120
+ };
121
+ case 5:
122
+ _.label++;
123
+ y = op[1];
124
+ op = [
125
+ 0
126
+ ];
127
+ continue;
128
+ case 7:
129
+ op = _.ops.pop();
130
+ _.trys.pop();
131
+ continue;
132
+ default:
133
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
134
+ _ = 0;
135
+ continue;
136
+ }
137
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
138
+ _.label = op[1];
139
+ break;
140
+ }
141
+ if (op[0] === 6 && _.label < t[1]) {
142
+ _.label = t[1];
143
+ t = op;
144
+ break;
145
+ }
146
+ if (t && _.label < t[2]) {
147
+ _.label = t[2];
148
+ _.ops.push(op);
149
+ break;
150
+ }
151
+ if (t[2]) _.ops.pop();
152
+ _.trys.pop();
153
+ continue;
154
+ }
155
+ op = body.call(thisArg, _);
156
+ } catch (e) {
157
+ op = [
158
+ 6,
159
+ e
160
+ ];
161
+ y = 0;
162
+ } finally{
163
+ f = t = 0;
164
+ }
165
+ if (op[0] & 5) throw op[1];
166
+ return {
167
+ value: op[0] ? op[1] : void 0,
168
+ done: true
169
+ };
170
+ }
171
+ }
172
+ // The one command that fetches weights. Nothing else touches the network for them, so a
173
+ // query that reads like a query never spends minutes pulling 124 MB. Asks nothing, so there
174
+ // is no prompt for CI to bypass; running it twice is a no-op.
175
+ var download = function download(ctx) {
176
+ return _async_to_generator(function() {
177
+ var values, cfg, e, dir;
178
+ return _ts_generator(this, function(_state) {
179
+ switch(_state.label){
180
+ case 0:
181
+ values = (0, _sharedts.parse)(ctx.argv, "usage: ".concat(ctx.name, " ").concat(_indexts.USAGE.download), _object_spread({}, _sharedts.CONFIG)).values;
182
+ cfg = ctx.resolveConfig(values.config);
183
+ e = (0, _configts.embedConfig)(cfg);
184
+ if (!e) throw new _errorsts.SenseError('EMBED_DISABLED', 'no preset asks for vectors, so there is no model to download');
185
+ if (e.type === 'api') {
186
+ console.log('embed type is "api" ('.concat(e.url, "), so there is nothing to download; ").concat(ctx.name, " search reaches it over the network"));
187
+ return [
188
+ 2
189
+ ];
190
+ }
191
+ if ((0, _embedts.modelPresent)(cfg)) {
192
+ console.log("".concat(e.model, " is already available in ").concat((0, _embedts.modelDir)(e.model)));
193
+ return [
194
+ 2
195
+ ];
196
+ }
197
+ return [
198
+ 4,
199
+ (0, _embedts.downloadModel)(e.model, function(file, into) {
200
+ return console.error("fetching ".concat(e.model, "/").concat(file, " into ").concat(into));
201
+ })
202
+ ];
203
+ case 1:
204
+ dir = _state.sent();
205
+ console.log("downloaded ".concat(e.model, " into ").concat(dir));
206
+ return [
207
+ 2
208
+ ];
209
+ }
210
+ });
211
+ })();
212
+ };
213
+ var _default = download;
214
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/download.ts"],"sourcesContent":["import { embedConfig } from '../config.ts';\nimport { SenseError } from '../errors.ts';\nimport { downloadModel, modelDir, modelPresent } from '../features/embed.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, parse } from './shared.ts';\nimport type { Command } from './types.ts';\n\n// The one command that fetches weights. Nothing else touches the network for them, so a\n// query that reads like a query never spends minutes pulling 124 MB. Asks nothing, so there\n// is no prompt for CI to bypass; running it twice is a no-op.\nconst download: Command = async (ctx) => {\n const { values } = parse(ctx.argv, `usage: ${ctx.name} ${USAGE.download}`, { ...CONFIG });\n const cfg = ctx.resolveConfig(values.config as string | undefined);\n const e = embedConfig(cfg);\n if (!e) throw new SenseError('EMBED_DISABLED', 'no preset asks for vectors, so there is no model to download');\n\n if (e.type === 'api') {\n console.log(`embed type is \"api\" (${e.url}), so there is nothing to download; ${ctx.name} search reaches it over the network`);\n return;\n }\n if (modelPresent(cfg)) {\n console.log(`${e.model} is already available in ${modelDir(e.model)}`);\n return;\n }\n const dir = await downloadModel(e.model, (file, into) => console.error(`fetching ${e.model}/${file} into ${into}`));\n console.log(`downloaded ${e.model} into ${dir}`);\n};\nexport default download;\n"],"names":["download","ctx","values","cfg","e","dir","parse","argv","USAGE","name","CONFIG","resolveConfig","config","embedConfig","SenseError","type","console","log","url","modelPresent","modelDir","model","downloadModel","file","into","error"],"mappings":";;;;+BA2BA;;;eAAA;;;wBA3B4B;wBACD;uBAC2B;uBAChC;wBACQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG9B,wFAAwF;AACxF,4FAA4F;AAC5F,8DAA8D;AAC9D,IAAMA,WAAoB,kBAAOC;;YACvBC,QACFC,KACAC,GAWAC;;;;oBAbEH,SAAWI,IAAAA,eAAK,EAACL,IAAIM,IAAI,EAAE,AAAC,UAAqBC,OAAZP,IAAIQ,IAAI,EAAC,KAAkB,OAAfD,cAAK,CAACR,QAAQ,GAAI,mBAAKU,gBAAM,GAA9ER;oBACFC,MAAMF,IAAIU,aAAa,CAACT,OAAOU,MAAM;oBACrCR,IAAIS,IAAAA,qBAAW,EAACV;oBACtB,IAAI,CAACC,GAAG,MAAM,IAAIU,oBAAU,CAAC,kBAAkB;oBAE/C,IAAIV,EAAEW,IAAI,KAAK,OAAO;wBACpBC,QAAQC,GAAG,CAAC,AAAC,wBAAmEhB,OAA5CG,EAAEc,GAAG,EAAC,wCAA+C,OAATjB,IAAIQ,IAAI,EAAC;wBACzF;;;oBACF;oBACA,IAAIU,IAAAA,qBAAY,EAAChB,MAAM;wBACrBa,QAAQC,GAAG,CAAC,AAAC,GAAqCG,OAAnChB,EAAEiB,KAAK,EAAC,6BAA6C,OAAlBD,IAAAA,iBAAQ,EAAChB,EAAEiB,KAAK;wBAClE;;;oBACF;oBACY;;wBAAMC,IAAAA,sBAAa,EAAClB,EAAEiB,KAAK,EAAE,SAACE,MAAMC;mCAASR,QAAQS,KAAK,CAAC,AAAC,YAAsBF,OAAXnB,EAAEiB,KAAK,EAAC,KAAgBG,OAAbD,MAAK,UAAa,OAALC;;;;oBAArGnB,MAAM;oBACZW,QAAQC,GAAG,CAAC,AAAC,cAA6BZ,OAAhBD,EAAEiB,KAAK,EAAC,UAAY,OAAJhB;;;;;;IAC5C;;IACA,WAAeL"}
@@ -3,12 +3,13 @@ export declare const USAGE: {
3
3
  readonly init: "init";
4
4
  readonly watch: "watch [--force] [--config path]";
5
5
  readonly status: "status [--format table|json] [--config path]";
6
- readonly check: "check [--format table|json] [--config path]";
7
- readonly rebuild: "rebuild [--config path]";
8
- readonly query: "query \"<sql>\" [params...] [--format table|json] [--config path]";
9
- readonly search: "search \"<terms>\" [--preset name] [--include glob ...] [--where \"<sql>\"] [--k n] [--lexical] [--format table|json] [--config path]";
6
+ readonly download: "download [--config path]";
7
+ readonly sql: "sql \"<statement>\" [params...] [--preset name] [--format table|json] [--config path]";
8
+ readonly search: "search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json] [--config path]";
10
9
  readonly map: "map [--format table|json] [--config path]";
11
- readonly peek: "peek <path> [--format table|json] [--config path]";
10
+ readonly peek: "peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--format table|json] [--config path]";
11
+ readonly path: "path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--max-depth n] [--format table|json] [--config path]";
12
+ readonly related: "related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json] [--config path]";
12
13
  };
13
14
  export declare const COMMANDS: Record<string, () => Promise<{
14
15
  default: Command;
@@ -3,12 +3,13 @@ export declare const USAGE: {
3
3
  readonly init: "init";
4
4
  readonly watch: "watch [--force] [--config path]";
5
5
  readonly status: "status [--format table|json] [--config path]";
6
- readonly check: "check [--format table|json] [--config path]";
7
- readonly rebuild: "rebuild [--config path]";
8
- readonly query: "query \"<sql>\" [params...] [--format table|json] [--config path]";
9
- readonly search: "search \"<terms>\" [--preset name] [--include glob ...] [--where \"<sql>\"] [--k n] [--lexical] [--format table|json] [--config path]";
6
+ readonly download: "download [--config path]";
7
+ readonly sql: "sql \"<statement>\" [params...] [--preset name] [--format table|json] [--config path]";
8
+ readonly search: "search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json] [--config path]";
10
9
  readonly map: "map [--format table|json] [--config path]";
11
- readonly peek: "peek <path> [--format table|json] [--config path]";
10
+ readonly peek: "peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--format table|json] [--config path]";
11
+ readonly path: "path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--max-depth n] [--format table|json] [--config path]";
12
+ readonly related: "related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json] [--config path]";
12
13
  };
13
14
  export declare const COMMANDS: Record<string, () => Promise<{
14
15
  default: Command;
@@ -61,12 +61,13 @@ var USAGE = {
61
61
  init: 'init',
62
62
  watch: 'watch [--force] [--config path]',
63
63
  status: 'status [--format table|json] [--config path]',
64
- check: 'check [--format table|json] [--config path]',
65
- rebuild: 'rebuild [--config path]',
66
- query: 'query "<sql>" [params...] [--format table|json] [--config path]',
67
- search: 'search "<terms>" [--preset name] [--include glob ...] [--where "<sql>"] [--k n] [--lexical] [--format table|json] [--config path]',
64
+ download: 'download [--config path]',
65
+ sql: 'sql "<statement>" [params...] [--preset name] [--format table|json] [--config path]',
66
+ search: 'search "<terms>" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--k n] [--format table|json] [--config path]',
68
67
  map: 'map [--format table|json] [--config path]',
69
- peek: 'peek <path> [--format table|json] [--config path]'
68
+ peek: 'peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--format table|json] [--config path]',
69
+ path: 'path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--max-depth n] [--format table|json] [--config path]',
70
+ related: 'related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--k n] [--format table|json] [--config path]'
70
71
  };
71
72
  var COMMANDS = {
72
73
  init: function init() {
@@ -84,19 +85,14 @@ var COMMANDS = {
84
85
  return /*#__PURE__*/ _interop_require_wildcard(require("./status.js"));
85
86
  });
86
87
  },
87
- check: function check() {
88
+ download: function download() {
88
89
  return Promise.resolve().then(function() {
89
- return /*#__PURE__*/ _interop_require_wildcard(require("./check.js"));
90
+ return /*#__PURE__*/ _interop_require_wildcard(require("./download.js"));
90
91
  });
91
92
  },
92
- rebuild: function rebuild() {
93
+ sql: function sql() {
93
94
  return Promise.resolve().then(function() {
94
- return /*#__PURE__*/ _interop_require_wildcard(require("./rebuild.js"));
95
- });
96
- },
97
- query: function query() {
98
- return Promise.resolve().then(function() {
99
- return /*#__PURE__*/ _interop_require_wildcard(require("./query.js"));
95
+ return /*#__PURE__*/ _interop_require_wildcard(require("./sql.js"));
100
96
  });
101
97
  },
102
98
  search: function search() {
@@ -113,6 +109,16 @@ var COMMANDS = {
113
109
  return Promise.resolve().then(function() {
114
110
  return /*#__PURE__*/ _interop_require_wildcard(require("./peek.js"));
115
111
  });
112
+ },
113
+ path: function path() {
114
+ return Promise.resolve().then(function() {
115
+ return /*#__PURE__*/ _interop_require_wildcard(require("./path.js"));
116
+ });
117
+ },
118
+ related: function related() {
119
+ return Promise.resolve().then(function() {
120
+ return /*#__PURE__*/ _interop_require_wildcard(require("./related.js"));
121
+ });
116
122
  }
117
123
  };
118
124
  /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/index.ts"],"sourcesContent":["import type { Command } from './types.ts';\n\n// Each command's usage line, minus the leading \"usage: <name> \" -- shared by cli.ts's\n// top-level usage() and the command's own parse() error/--help output, so there is one\n// copy of each line, not two that can drift.\nexport const USAGE = {\n init: 'init',\n watch: 'watch [--force] [--config path]',\n status: 'status [--format table|json] [--config path]',\n check: 'check [--format table|json] [--config path]',\n rebuild: 'rebuild [--config path]',\n query: 'query \"<sql>\" [params...] [--format table|json] [--config path]',\n search: 'search \"<terms>\" [--preset name] [--include glob ...] [--where \"<sql>\"] [--k n] [--lexical] [--format table|json] [--config path]',\n map: 'map [--format table|json] [--config path]',\n peek: 'peek <path> [--format table|json] [--config path]',\n} as const;\n\n// Lazy registry: a command's imports load only when it runs, so a heavy dependency in one\n// command never taxes the others (or --version/--help). These names are reserved: a named\n// query in config can never shadow them.\nexport const COMMANDS: Record<string, () => Promise<{ default: Command }>> = {\n init: () => import('./init.ts'),\n watch: () => import('./watch.ts'),\n status: () => import('./status.ts'),\n check: () => import('./check.ts'),\n rebuild: () => import('./rebuild.ts'),\n query: () => import('./query.ts'),\n search: () => import('./search.ts'),\n map: () => import('./map.ts'),\n peek: () => import('./peek.ts'),\n};\n\nexport type { Command, Ctx } from './types.ts';\n"],"names":["COMMANDS","USAGE","init","watch","status","check","rebuild","query","search","map","peek"],"mappings":";;;;;;;;;;;QAoBaA;eAAAA;;QAfAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAN,IAAMA,QAAQ;IACnBC,MAAM;IACNC,OAAO;IACPC,QAAQ;IACRC,OAAO;IACPC,SAAS;IACTC,OAAO;IACPC,QAAQ;IACRC,KAAK;IACLC,MAAM;AACR;AAKO,IAAMV,WAAgE;IAC3EE,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,SAAS,SAATA;eAAe;2DAAA,QAAO;;;IACtBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,KAAK,SAALA;eAAW;2DAAA,QAAO;;;IAClBC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;AACrB"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/index.ts"],"sourcesContent":["import type { Command } from './types.ts';\n\n// Each command's usage line, minus the leading \"usage: <name> \" -- shared by cli.ts's\n// top-level usage() and the command's own parse() error/--help output, so there is one\n// copy of each line, not two that can drift.\nexport const USAGE = {\n init: 'init',\n watch: 'watch [--force] [--config path]',\n status: 'status [--format table|json] [--config path]',\n download: 'download [--config path]',\n sql: 'sql \"<statement>\" [params...] [--preset name] [--format table|json] [--config path]',\n search: 'search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json] [--config path]',\n map: 'map [--format table|json] [--config path]',\n peek: 'peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--format table|json] [--config path]',\n path: 'path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--max-depth n] [--format table|json] [--config path]',\n related: 'related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json] [--config path]',\n} as const;\n\n// Lazy registry: a command's imports load only when it runs, so a heavy dependency in one\n// command never taxes the others (or --version/--help). These names are reserved: a saved\n// entry in config can never shadow them.\nexport const COMMANDS: Record<string, () => Promise<{ default: Command }>> = {\n init: () => import('./init.ts'),\n watch: () => import('./watch.ts'),\n status: () => import('./status.ts'),\n download: () => import('./download.ts'),\n sql: () => import('./sql.ts'),\n search: () => import('./search.ts'),\n map: () => import('./map.ts'),\n peek: () => import('./peek.ts'),\n path: () => import('./path.ts'),\n related: () => import('./related.ts'),\n};\n\nexport type { Command, Ctx } from './types.ts';\n"],"names":["COMMANDS","USAGE","init","watch","status","download","sql","search","map","peek","path","related"],"mappings":";;;;;;;;;;;QAqBaA;eAAAA;;QAhBAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAN,IAAMA,QAAQ;IACnBC,MAAM;IACNC,OAAO;IACPC,QAAQ;IACRC,UAAU;IACVC,KAAK;IACLC,QAAQ;IACRC,KAAK;IACLC,MAAM;IACNC,MAAM;IACNC,SAAS;AACX;AAKO,IAAMX,WAAgE;IAC3EE,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,UAAU,SAAVA;eAAgB;2DAAA,QAAO;;;IACvBC,KAAK,SAALA;eAAW;2DAAA,QAAO;;;IAClBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,KAAK,SAALA;eAAW;2DAAA,QAAO;;;IAClBC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,SAAS,SAATA;eAAe;2DAAA,QAAO;;;AACxB"}
@@ -15,7 +15,10 @@ var init = function init(ctx) {
15
15
  (0, _sharedts.parse)(ctx.argv, "usage: ".concat(ctx.name, " ").concat(_indexts.USAGE.init), {});
16
16
  var configPath = (0, _configts.initConfig)(process.cwd());
17
17
  console.log("created ".concat(configPath));
18
- console.log("query away: ".concat(ctx.name, ' query "SELECT path FROM frontmatter LIMIT 10"'));
18
+ console.log("query away: ".concat(ctx.name, ' sql "SELECT path FROM frontmatter LIMIT 10"'));
19
+ // Semantic search needs a 124 MB model that nothing downloads implicitly; name the step
20
+ // here so the first search meets it as a choice rather than as a degraded result.
21
+ console.log("for meaning-based search: ".concat(ctx.name, " download (one 124 MB model, once)"));
19
22
  // The decisions a new tree faces -- features, frontmatter conventions, note size -- are not
20
23
  // in this output; name both places that hold them, since an agent may have neither.
21
24
  console.log('features and tree design: the sense-setup skill, or schema.json');
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/init.ts"],"sourcesContent":["import { initConfig } from '../config.ts';\nimport { USAGE } from './index.ts';\nimport { parse } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst init: Command = (ctx) => {\n parse(ctx.argv, `usage: ${ctx.name} ${USAGE.init}`, {});\n const configPath = initConfig(process.cwd());\n console.log(`created ${configPath}`);\n console.log(`query away: ${ctx.name} query \"SELECT path FROM frontmatter LIMIT 10\"`);\n // The decisions a new tree faces -- features, frontmatter conventions, note size -- are not\n // in this output; name both places that hold them, since an agent may have neither.\n console.log('features and tree design: the sense-setup skill, or schema.json');\n};\nexport default init;\n"],"names":["init","ctx","parse","argv","USAGE","name","configPath","initConfig","process","cwd","console","log"],"mappings":";;;;+BAcA;;;eAAA;;;wBAd2B;uBACL;wBACA;AAGtB,IAAMA,OAAgB,cAACC;IACrBC,IAAAA,eAAK,EAACD,IAAIE,IAAI,EAAE,AAAC,UAAqBC,OAAZH,IAAII,IAAI,EAAC,KAAc,OAAXD,cAAK,CAACJ,IAAI,GAAI,CAAC;IACrD,IAAMM,aAAaC,IAAAA,oBAAU,EAACC,QAAQC,GAAG;IACzCC,QAAQC,GAAG,CAAC,AAAC,WAAqB,OAAXL;IACvBI,QAAQC,GAAG,CAAC,AAAC,eAAuB,OAATV,IAAII,IAAI,EAAC;IACpC,4FAA4F;IAC5F,oFAAoF;IACpFK,QAAQC,GAAG,CAAC;AACd;IACA,WAAeX"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/init.ts"],"sourcesContent":["import { initConfig } from '../config.ts';\nimport { USAGE } from './index.ts';\nimport { parse } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst init: Command = (ctx) => {\n parse(ctx.argv, `usage: ${ctx.name} ${USAGE.init}`, {});\n const configPath = initConfig(process.cwd());\n console.log(`created ${configPath}`);\n console.log(`query away: ${ctx.name} sql \"SELECT path FROM frontmatter LIMIT 10\"`);\n // Semantic search needs a 124 MB model that nothing downloads implicitly; name the step\n // here so the first search meets it as a choice rather than as a degraded result.\n console.log(`for meaning-based search: ${ctx.name} download (one 124 MB model, once)`);\n // The decisions a new tree faces -- features, frontmatter conventions, note size -- are not\n // in this output; name both places that hold them, since an agent may have neither.\n console.log('features and tree design: the sense-setup skill, or schema.json');\n};\nexport default init;\n"],"names":["init","ctx","parse","argv","USAGE","name","configPath","initConfig","process","cwd","console","log"],"mappings":";;;;+BAiBA;;;eAAA;;;wBAjB2B;uBACL;wBACA;AAGtB,IAAMA,OAAgB,cAACC;IACrBC,IAAAA,eAAK,EAACD,IAAIE,IAAI,EAAE,AAAC,UAAqBC,OAAZH,IAAII,IAAI,EAAC,KAAc,OAAXD,cAAK,CAACJ,IAAI,GAAI,CAAC;IACrD,IAAMM,aAAaC,IAAAA,oBAAU,EAACC,QAAQC,GAAG;IACzCC,QAAQC,GAAG,CAAC,AAAC,WAAqB,OAAXL;IACvBI,QAAQC,GAAG,CAAC,AAAC,eAAuB,OAATV,IAAII,IAAI,EAAC;IACpC,wFAAwF;IACxF,kFAAkF;IAClFK,QAAQC,GAAG,CAAC,AAAC,6BAAqC,OAATV,IAAII,IAAI,EAAC;IAClD,4FAA4F;IAC5F,oFAAoF;IACpFK,QAAQC,GAAG,CAAC;AACd;IACA,WAAeX"}
@@ -41,10 +41,10 @@ function _object_spread(target) {
41
41
  return target;
42
42
  }
43
43
  var map = function map(ctx) {
44
- var values = (0, _sharedts.parse)(ctx.argv, "usage: ".concat(ctx.name, " ").concat(_indexts.USAGE.map), _object_spread({}, _sharedts.FORMAT, _sharedts.CONFIG)).values;
44
+ var values = (0, _sharedts.parse)(ctx.argv, "usage: ".concat(ctx.name, " ").concat(_indexts.USAGE.map), _object_spread({}, _sharedts.SCOPE, _sharedts.FORMAT, _sharedts.CONFIG)).values;
45
45
  var format = (0, _sharedts.formatOf)(values);
46
46
  return (0, _sharedts.withDb)(ctx, values.config, function(db, cfg) {
47
- var result = (0, _commandsts.mapTree)(db, cfg);
47
+ var result = (0, _commandsts.mapTree)(db, cfg, (0, _sharedts.scopeOf)(values));
48
48
  console.log(format === 'json' ? JSON.stringify(result, null, 2) : (0, _outputts.renderMap)(result));
49
49
  });
50
50
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/map.ts"],"sourcesContent":["import { mapTree } from '../commands.ts';\nimport { renderMap } from '../output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, parse, 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}`, { ...FORMAT, ...CONFIG });\n const format = formatOf(values);\n return withDb(ctx, values.config as string | undefined, (db, cfg) => {\n const result = mapTree(db, cfg);\n console.log(format === 'json' ? JSON.stringify(result, null, 2) : renderMap(result));\n });\n};\nexport default map;\n"],"names":["map","ctx","values","parse","argv","USAGE","name","FORMAT","CONFIG","format","formatOf","withDb","config","db","cfg","result","mapTree","console","log","JSON","stringify","renderMap"],"mappings":";;;;+BAcA;;;eAAA;;;0BAdwB;wBACE;uBACJ;wBACkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGxD,IAAMA,MAAe,aAACC;IACpB,IAAM,AAAEC,SAAWC,IAAAA,eAAK,EAACF,IAAIG,IAAI,EAAE,AAAC,UAAqBC,OAAZJ,IAAIK,IAAI,EAAC,KAAa,OAAVD,cAAK,CAACL,GAAG,GAAI,mBAAKO,gBAAM,EAAKC,gBAAM,GAApFN;IACR,IAAMO,SAASC,IAAAA,kBAAQ,EAACR;IACxB,OAAOS,IAAAA,gBAAM,EAACV,KAAKC,OAAOU,MAAM,EAAwB,SAACC,IAAIC;QAC3D,IAAMC,SAASC,IAAAA,mBAAO,EAACH,IAAIC;QAC3BG,QAAQC,GAAG,CAACT,WAAW,SAASU,KAAKC,SAAS,CAACL,QAAQ,MAAM,KAAKM,IAAAA,mBAAS,EAACN;IAC9E;AACF;IACA,WAAef"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/map.ts"],"sourcesContent":["import { mapTree } from '../commands.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":["map","ctx","values","parse","argv","USAGE","name","SCOPE","FORMAT","CONFIG","format","formatOf","withDb","config","db","cfg","result","mapTree","scopeOf","console","log","JSON","stringify","renderMap"],"mappings":";;;;+BAcA;;;eAAA;;;0BAdwB;wBACE;uBACJ;wBACkD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGxE,IAAMA,MAAe,aAACC;IACpB,IAAM,AAAEC,SAAWC,IAAAA,eAAK,EAACF,IAAIG,IAAI,EAAE,AAAC,UAAqBC,OAAZJ,IAAIK,IAAI,EAAC,KAAa,OAAVD,cAAK,CAACL,GAAG,GAAI,mBAAKO,eAAK,EAAKC,gBAAM,EAAKC,gBAAM,GAA9FP;IACR,IAAMQ,SAASC,IAAAA,kBAAQ,EAACT;IACxB,OAAOU,IAAAA,gBAAM,EAACX,KAAKC,OAAOW,MAAM,EAAwB,SAACC,IAAIC;QAC3D,IAAMC,SAASC,IAAAA,mBAAO,EAACH,IAAIC,KAAKG,IAAAA,iBAAO,EAAChB;QACxCiB,QAAQC,GAAG,CAACV,WAAW,SAASW,KAAKC,SAAS,CAACN,QAAQ,MAAM,KAAKO,IAAAA,mBAAS,EAACP;IAC9E;AACF;IACA,WAAehB"}
@@ -2,10 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, // Fallback when the first positional is not a command: a named query from config, either a
6
- // SQL string (run as-is) or a saved search (run through the `search` command's own machinery).
7
- // Flags cover both shapes -- SEARCH_FLAGS override a saved search's fields the same way they
8
- // override a preset's.
5
+ Object.defineProperty(exports, // Fallback when the first positional is not a command: a saved query, { sql } or { search }.
6
+ // SEARCH_FLAGS override a saved search's fields the same way they override a preset's.
9
7
  "default", {
10
8
  enumerable: true,
11
9
  get: function() {
@@ -173,29 +171,25 @@ function _ts_generator(thisArg, body) {
173
171
  }
174
172
  function named(ctx, queryName) {
175
173
  return _async_to_generator(function() {
176
- var _parseK, _values_where, _values_preset, _values_include, usage, _parse, values, params, format, configPath, cfg, entry, k, where, preset, include, semantic;
174
+ var _parseK, _values_where, _values_preset, _values_include, _values_exclude, usage, _parse, values, params, format, configPath, cfg, entry, k, where, preset, include, exclude, noExclude;
177
175
  return _ts_generator(this, function(_state) {
178
176
  switch(_state.label){
179
177
  case 0:
180
- usage = "usage: ".concat(ctx.name, " ").concat(queryName, ' [params...] [--format table|json] [--config path] [--where "<sql>"] [--k n] [--preset name] [--include glob ...] [--lexical]');
178
+ usage = "usage: ".concat(ctx.name, " ").concat(queryName, ' [params...] [--format table|json] [--config path] [--where "<sql>"] [--k n] [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude]');
181
179
  _parse = (0, _sharedts.parse)(ctx.argv, usage, _object_spread({}, _sharedts.SEARCH_FLAGS, _sharedts.FORMAT, _sharedts.CONFIG)), values = _parse.values, params = _parse.positionals;
182
180
  format = (0, _sharedts.formatOf)(values);
183
181
  configPath = values.config;
184
182
  cfg = ctx.resolveConfig(configPath);
185
183
  entry = cfg.queries[queryName];
186
184
  if (entry === undefined) {
187
- console.error('unknown query: "'.concat(queryName, '"'));
188
- console.error("valid queries: ".concat(Object.keys(cfg.queries).sort().join(', ')));
185
+ console.error('unknown command or saved entry: "'.concat(queryName, '"'));
186
+ console.error("saved queries: ".concat(Object.keys(cfg.queries).sort().join(', ')));
189
187
  process.exit(2);
190
188
  }
191
- if (typeof entry === 'string') {
192
- (0, _sharedts.runSql)(cfg, entry, params, format, 'query "'.concat(queryName, '"'));
193
- return [
194
- 2
195
- ];
196
- }
197
189
  if ('sql' in entry) {
198
- (0, _sharedts.runSql)(cfg, entry.sql, params, format, 'query "'.concat(queryName, '"'));
190
+ // A saved statement written against `scope` is preset-agnostic, so the same entry can be
191
+ // re-pointed at another layer from the command line instead of being copied per preset.
192
+ (0, _sharedts.runSql)(cfg, entry.sql, params, format, 'query "'.concat(queryName, '"'), values.preset);
199
193
  return [
200
194
  2
201
195
  ];
@@ -208,9 +202,8 @@ function named(ctx, queryName) {
208
202
  where = (_values_where = values.where) !== null && _values_where !== void 0 ? _values_where : entry.where;
209
203
  preset = (_values_preset = values.preset) !== null && _values_preset !== void 0 ? _values_preset : entry.preset;
210
204
  include = (_values_include = values.include) !== null && _values_include !== void 0 ? _values_include : entry.include;
211
- // --lexical upgrades a saved search's semantic behavior the same way --where/--k
212
- // override; absent means the saved value (the flag has no default false override).
213
- semantic = values.lexical ? false : entry.semantic;
205
+ exclude = (_values_exclude = values.exclude) !== null && _values_exclude !== void 0 ? _values_exclude : entry.exclude;
206
+ noExclude = values['no-exclude'] === true;
214
207
  return [
215
208
  4,
216
209
  (0, _sharedts.withDb)(ctx, configPath, function(db, resolvedCfg) {
@@ -225,7 +218,8 @@ function named(ctx, queryName) {
225
218
  where: where,
226
219
  preset: preset,
227
220
  include: include,
228
- semantic: semantic
221
+ exclude: exclude,
222
+ noExclude: noExclude
229
223
  })
230
224
  ];
231
225
  case 1: