sensemaking 0.11.5 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/bin/cli.js +5 -2
- package/dist/cjs/cli/index.d.cts +3 -3
- package/dist/cjs/cli/index.d.ts +3 -3
- package/dist/cjs/cli/index.js +3 -3
- package/dist/cjs/cli/index.js.map +1 -1
- package/dist/cjs/cli/named.js +2 -2
- package/dist/cjs/cli/named.js.map +1 -1
- package/dist/cjs/cli/related.js +1 -1
- package/dist/cjs/cli/related.js.map +1 -1
- package/dist/cjs/cli/search.js +1 -1
- package/dist/cjs/cli/search.js.map +1 -1
- package/dist/cjs/cli/shared.d.cts +3 -1
- package/dist/cjs/cli/shared.d.ts +3 -1
- package/dist/cjs/cli/shared.js +35 -5
- package/dist/cjs/cli/shared.js.map +1 -1
- package/dist/cjs/cli/sql.js +1 -1
- package/dist/cjs/cli/sql.js.map +1 -1
- package/dist/cjs/cli.js +14 -1
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/commands.js +19 -5
- package/dist/cjs/commands.js.map +1 -1
- package/dist/cjs/config.d.cts +4 -0
- package/dist/cjs/config.d.ts +4 -0
- package/dist/cjs/config.js +39 -4
- package/dist/cjs/config.js.map +1 -1
- package/dist/cjs/db.d.cts +1 -1
- package/dist/cjs/db.d.ts +1 -1
- package/dist/cjs/db.js +158 -14
- package/dist/cjs/db.js.map +1 -1
- package/dist/cjs/output.d.cts +4 -1
- package/dist/cjs/output.d.ts +4 -1
- package/dist/cjs/output.js +158 -6
- package/dist/cjs/output.js.map +1 -1
- package/dist/cjs/segment.d.cts +2 -0
- package/dist/cjs/segment.d.ts +2 -0
- package/dist/cjs/segment.js +98 -0
- package/dist/cjs/segment.js.map +1 -0
- package/dist/esm/cli/index.d.ts +3 -3
- package/dist/esm/cli/index.js +3 -3
- package/dist/esm/cli/index.js.map +1 -1
- package/dist/esm/cli/named.js +3 -3
- package/dist/esm/cli/named.js.map +1 -1
- package/dist/esm/cli/related.js +2 -2
- package/dist/esm/cli/related.js.map +1 -1
- package/dist/esm/cli/search.js +2 -2
- package/dist/esm/cli/search.js.map +1 -1
- package/dist/esm/cli/shared.d.ts +3 -1
- package/dist/esm/cli/shared.js +32 -5
- package/dist/esm/cli/shared.js.map +1 -1
- package/dist/esm/cli/sql.js +2 -2
- package/dist/esm/cli/sql.js.map +1 -1
- package/dist/esm/cli.js +14 -1
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/commands.js +19 -5
- package/dist/esm/commands.js.map +1 -1
- package/dist/esm/config.d.ts +4 -0
- package/dist/esm/config.js +37 -4
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/db.d.ts +1 -1
- package/dist/esm/db.js +140 -15
- package/dist/esm/db.js.map +1 -1
- package/dist/esm/output.d.ts +4 -1
- package/dist/esm/output.js +104 -4
- package/dist/esm/output.js.map +1 -1
- package/dist/esm/segment.d.ts +2 -0
- package/dist/esm/segment.js +65 -0
- package/dist/esm/segment.js.map +1 -0
- package/package.json +4 -1
- package/schema.json +12 -1
- package/skills/sense/SKILL.md +5 -4
- package/skills/sense-setup/SKILL.md +1 -0
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ Every file becomes rows in these tables, plus whatever an enabled feature adds o
|
|
|
32
32
|
| table | holds | for |
|
|
33
33
|
|---|---|---|
|
|
34
34
|
| `frontmatter` | one column per key, plus `path`, `_mtime`, `_size`, `_rank`, `_parse_error` | filtering |
|
|
35
|
-
| `content` | FTS5 index: `title`, `summary`, `text` | search and ranking |
|
|
35
|
+
| `content` | FTS5 index: `title`, `summary`, `text`, `path`, plus machine-written `title_seg`/`summary_seg`/`text_seg` sidecars for matching in Chinese, Japanese, Thai, Khmer, Lao, and Burmese | search and ranking |
|
|
36
36
|
| `links` | `src`, `target` as written, `dst` resolved (`NULL` = dead link, but see the skill: a link to an attachment can never resolve) | graph |
|
|
37
37
|
| `sections` | heading, `level`, `start_line`, `end_line`, `tokens` estimate | structure |
|
|
38
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 |
|
|
@@ -65,7 +65,7 @@ ORDER BY bm25(content, 10.0, 5.0, 1.0) LIMIT 10
|
|
|
65
65
|
| `download` | fetch the embedding model named in the config (once per machine; nothing else downloads it) |
|
|
66
66
|
| `watch` | keep the index warm in the background (optional; see [WATCH.md](WATCH.md)) |
|
|
67
67
|
|
|
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.
|
|
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, and `--format csv` writes the row-returning commands one row per line, for redirecting a large result to a file instead of into context; `--version` and `--help` do what they say.
|
|
69
69
|
|
|
70
70
|
## Config
|
|
71
71
|
|
|
@@ -92,6 +92,7 @@ ORDER BY bm25(content, 10.0, 5.0, 1.0) LIMIT 10
|
|
|
92
92
|
|---|---|
|
|
93
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
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
|
+
| `content` | settings for the `content` table. `tokenize` names the FTS5 tokenizer, defaulting to `porter unicode61`: name `trigram` for substring matching inside a Latin word, or `unicode61 tokenchars '-_'` to keep hyphenated terms whole. Languages written without word spaces (Chinese, Japanese, Thai, Khmer, Lao, Burmese) need no decision here: they are indexed per grapheme and searched as ordered phrases, substring semantics, what grep gives, needing no minimum length; naming a tokenizer turns that off, since the tree has then chosen its own scheme. Changing it rebuilds the text index only; vectors, links, and sections are kept. |
|
|
95
96
|
| `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. |
|
|
96
97
|
| `version` | schema version; older configs auto-migrate on load, noted on stderr. |
|
|
97
98
|
|
|
@@ -99,7 +100,7 @@ Bare commands use the `default` preset; `--preset` names another; flags override
|
|
|
99
100
|
|
|
100
101
|
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.
|
|
101
102
|
|
|
102
|
-
`has(field, value)
|
|
103
|
+
Two custom SQL functions. `has(field, value)`: array membership on JSON-array fields, substring on strings, false on missing keys. `segment(terms)`: rewrites a run of Chinese, Japanese, Thai, Khmer, Lao, or Burmese text into the ordered grapheme phrase the sidecar columns need, leaving everything else unchanged, so it is safe to add to any hand-written `MATCH`. 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.
|
|
103
104
|
|
|
104
105
|
## Scale
|
|
105
106
|
|
package/bin/cli.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// exitCode (not exit()) lets Node flush queued stdout writes from the streaming sql path before
|
|
4
|
+
// exiting; the unref'd timer only force-exits if a stray handle would otherwise hang the process.
|
|
3
5
|
// biome-ignore lint/security/noGlobalEval: dual esm and cjs
|
|
4
|
-
if (typeof require === 'undefined') eval("import('../dist/esm/cli.js').then((cli) => cli.default(process.argv.slice(2), 'sense')).catch((err) => { console.error(err); process.exit(
|
|
6
|
+
if (typeof require === 'undefined') eval("import('../dist/esm/cli.js').then((cli) => cli.default(process.argv.slice(2), 'sense')).catch((err) => { console.error(err); process.exitCode = 1; setTimeout(() => process.exit(1), 2000).unref(); });");
|
|
5
7
|
else
|
|
6
8
|
require('../dist/cjs/cli.js')(process.argv.slice(2), 'sense').catch((err) => {
|
|
7
9
|
console.error(err);
|
|
8
|
-
process.
|
|
10
|
+
process.exitCode = 1;
|
|
11
|
+
setTimeout(() => process.exit(1), 2000).unref();
|
|
9
12
|
});
|
package/dist/cjs/cli/index.d.cts
CHANGED
|
@@ -4,12 +4,12 @@ export declare const USAGE: {
|
|
|
4
4
|
readonly watch: "watch [--force] [--config path]";
|
|
5
5
|
readonly status: "status [--format table|json] [--config path]";
|
|
6
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]";
|
|
7
|
+
readonly sql: "sql \"<statement>\" [params...] [--preset name] [--format table|json|csv] [--config path]";
|
|
8
|
+
readonly search: "search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json|csv] [--config path]";
|
|
9
9
|
readonly map: "map [--format table|json] [--config path]";
|
|
10
10
|
readonly peek: "peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--format table|json] [--config path]";
|
|
11
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
|
+
readonly related: "related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json|csv] [--config path]";
|
|
13
13
|
};
|
|
14
14
|
export declare const COMMANDS: Record<string, () => Promise<{
|
|
15
15
|
default: Command;
|
package/dist/cjs/cli/index.d.ts
CHANGED
|
@@ -4,12 +4,12 @@ export declare const USAGE: {
|
|
|
4
4
|
readonly watch: "watch [--force] [--config path]";
|
|
5
5
|
readonly status: "status [--format table|json] [--config path]";
|
|
6
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]";
|
|
7
|
+
readonly sql: "sql \"<statement>\" [params...] [--preset name] [--format table|json|csv] [--config path]";
|
|
8
|
+
readonly search: "search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json|csv] [--config path]";
|
|
9
9
|
readonly map: "map [--format table|json] [--config path]";
|
|
10
10
|
readonly peek: "peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--format table|json] [--config path]";
|
|
11
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
|
+
readonly related: "related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json|csv] [--config path]";
|
|
13
13
|
};
|
|
14
14
|
export declare const COMMANDS: Record<string, () => Promise<{
|
|
15
15
|
default: Command;
|
package/dist/cjs/cli/index.js
CHANGED
|
@@ -62,12 +62,12 @@ var USAGE = {
|
|
|
62
62
|
watch: 'watch [--force] [--config path]',
|
|
63
63
|
status: 'status [--format table|json] [--config path]',
|
|
64
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]',
|
|
65
|
+
sql: 'sql "<statement>" [params...] [--preset name] [--format table|json|csv] [--config path]',
|
|
66
|
+
search: 'search "<terms>" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--k n] [--format table|json|csv] [--config path]',
|
|
67
67
|
map: 'map [--format table|json] [--config path]',
|
|
68
68
|
peek: 'peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--format table|json] [--config path]',
|
|
69
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
|
+
related: 'related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--k n] [--format table|json|csv] [--config path]'
|
|
71
71
|
};
|
|
72
72
|
var COMMANDS = {
|
|
73
73
|
init: function init() {
|
|
@@ -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 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"}
|
|
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|csv] [--config path]',\n search: 'search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json|csv] [--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|csv] [--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"}
|
package/dist/cjs/cli/named.js
CHANGED
|
@@ -175,9 +175,9 @@ function named(ctx, queryName) {
|
|
|
175
175
|
return _ts_generator(this, function(_state) {
|
|
176
176
|
switch(_state.label){
|
|
177
177
|
case 0:
|
|
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]');
|
|
178
|
+
usage = "usage: ".concat(ctx.name, " ").concat(queryName, ' [params...] [--format table|json|csv] [--config path] [--where "<sql>"] [--k n] [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude]');
|
|
179
179
|
_parse = (0, _sharedts.parse)(ctx.argv, usage, _object_spread({}, _sharedts.SEARCH_FLAGS, _sharedts.FORMAT, _sharedts.CONFIG)), values = _parse.values, params = _parse.positionals;
|
|
180
|
-
format = (0, _sharedts.
|
|
180
|
+
format = (0, _sharedts.rowFormatOf)(values);
|
|
181
181
|
configPath = values.config;
|
|
182
182
|
cfg = ctx.resolveConfig(configPath);
|
|
183
183
|
entry = cfg.queries[queryName];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/named.ts"],"sourcesContent":["import { search } from '../commands.ts';\nimport { printRows } from '../output.ts';\nimport { CONFIG, FORMAT,
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/named.ts"],"sourcesContent":["import { search } from '../commands.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":["named","ctx","queryName","parseK","values","usage","parse","params","format","configPath","cfg","entry","k","where","preset","include","exclude","noExclude","name","argv","SEARCH_FLAGS","FORMAT","CONFIG","positionals","rowFormatOf","config","resolveConfig","queries","undefined","console","error","Object","keys","sort","join","process","exit","runSql","sql","length","usageError","withDb","db","resolvedCfg","search","printRows"],"mappings":";;;;+BAKA,6FAA6F;AAC7F,uFAAuF;AACvF;;;eAA8BA;;;0BAPP;wBACG;wBAC+D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAK1E,SAAeA,MAAMC,GAAQ,EAAEC,SAAiB;;YAyBnDC,SACKC,eACCA,gBACCA,iBACAA,iBA5BXC,OACkCC,QAAhCF,QAAqBG,QACvBC,QACAC,YAEAC,KACAC,OAkBAC,GACAC,OACAC,QACAC,SACAC,SACAC;;;;oBA7BAZ,QAAQ,AAAC,UAAqBH,OAAZD,IAAIiB,IAAI,EAAC,KAAa,OAAVhB,WAAU;oBACNI,SAAAA,IAAAA,eAAK,EAACL,IAAIkB,IAAI,EAAEd,OAAO,mBAAKe,sBAAY,EAAKC,gBAAM,EAAKC,gBAAM,IAA9FlB,SAAgCE,OAAhCF,QAAqBG,SAAWD,OAAxBiB;oBACVf,SAASgB,IAAAA,qBAAW,EAACpB;oBACrBK,aAAaL,OAAOqB,MAAM;oBAE1Bf,MAAMT,IAAIyB,aAAa,CAACjB;oBACxBE,QAAQD,IAAIiB,OAAO,CAACzB,UAAU;oBACpC,IAAIS,UAAUiB,WAAW;wBACvBC,QAAQC,KAAK,CAAC,AAAC,oCAA6C,OAAV5B,WAAU;wBAC5D2B,QAAQC,KAAK,CAAC,AAAC,kBAA4D,OAA3CC,OAAOC,IAAI,CAACtB,IAAIiB,OAAO,EAAEM,IAAI,GAAGC,IAAI,CAAC;wBACrEC,QAAQC,IAAI,CAAC;oBACf;oBAEA,IAAI,SAASzB,OAAO;wBAClB,yFAAyF;wBACzF,wFAAwF;wBACxF0B,IAAAA,gBAAM,EAAC3B,KAAKC,MAAM2B,GAAG,EAAE/B,QAAQC,QAAQ,AAAC,UAAmB,OAAVN,WAAU,MAAIE,OAAOU,MAAM;wBAC5E;;;oBACF;oBAEA,uFAAuF;oBACvF,IAAIP,OAAOgC,MAAM,GAAG,GAAG;wBACrBtC,IAAIuC,UAAU,CAAC,AAAC,IAAuHvC,OAApHC,WAAU,4GAAmH,OAATD,IAAIiB,IAAI,EAAC;oBAClJ;oBACMN,KAAIT,UAAAA,IAAAA,gBAAM,EAACC,OAAOQ,CAAC,EAAwBX,IAAIuC,UAAU,eAArDrC,qBAAAA,UAA0DQ,MAAMC,CAAC;oBACrEC,SAAST,gBAAAA,OAAOS,KAAK,cAAZT,2BAAAA,gBAAuCO,MAAME,KAAK;oBAC3DC,UAAUV,iBAAAA,OAAOU,MAAM,cAAbV,4BAAAA,iBAAwCO,MAAMG,MAAM;oBAC9DC,WAAWX,kBAAAA,OAAOW,OAAO,cAAdX,6BAAAA,kBAA2CO,MAAMI,OAAO;oBACnEC,WAAWZ,kBAAAA,OAAOY,OAAO,cAAdZ,6BAAAA,kBAA2CO,MAAMK,OAAO;oBACnEC,YAAYb,MAAM,CAAC,aAAa,KAAK;oBAC3C;;wBAAMqC,IAAAA,gBAAM,EAACxC,KAAKQ,YAAY,SAAOiC,IAAIC;;;;;4CAA0B;;gDAAMC,IAAAA,kBAAM,EAACF,IAAIC,aAAahC,MAAMiC,MAAM,EAAE;oDAAEhC,GAAAA;oDAAGC,OAAAA;oDAAOC,QAAAA;oDAAQC,SAAAA;oDAASC,SAAAA;oDAASC,WAAAA;gDAAU;;;;;gDAAtG4B,mBAAS;oDAAC;oDAAgGrC;;;;;;;;;oBAAnK;;;;;;IACF"}
|
package/dist/cjs/cli/related.js
CHANGED
|
@@ -250,7 +250,7 @@ var relatedCmd = function relatedCmd(ctx) {
|
|
|
250
250
|
var _positionals = _sliced_to_array(positionals, 1), pathArg = _positionals[0];
|
|
251
251
|
if (!pathArg) ctx.usageError(usage);
|
|
252
252
|
var k = (_parseK = (0, _sharedts.parseK)(values.k, ctx.usageError)) !== null && _parseK !== void 0 ? _parseK : RELATED_DEFAULT_K;
|
|
253
|
-
var format = (0, _sharedts.
|
|
253
|
+
var format = (0, _sharedts.rowFormatOf)(values);
|
|
254
254
|
return (0, _sharedts.withDb)(ctx, values.config, function(db, cfg) {
|
|
255
255
|
return _async_to_generator(function() {
|
|
256
256
|
var overrides;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/related.ts"],"sourcesContent":["import { relatedNotes } from '../commands.ts';\nimport type { Row } from '../output.ts';\nimport { printRows } from '../output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT,
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/related.ts"],"sourcesContent":["import { relatedNotes } from '../commands.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":["RELATED_DEFAULT_K","relatedCmd","ctx","parseK","usage","USAGE","name","related","parse","argv","SCOPE","FORMAT","CONFIG","k","type","values","positionals","pathArg","usageError","format","rowFormatOf","withDb","config","db","cfg","overrides","scopeOf","relatedNotes","printRows"],"mappings":";;;;+BAqBA;;;eAAA;;;0BArB6B;wBAEH;uBACJ;wBAC6D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGnF,IAAMA,oBAAoB;AAE1B,IAAMC,aAAsB,oBAACC;QAKjBC;IAJV,IAAMC,QAAQ,AAAC,UAAqBC,OAAZH,IAAII,IAAI,EAAC,KAAiB,OAAdD,cAAK,CAACE,OAAO;IACjD,IAAgCC,SAAAA,IAAAA,eAAK,EAACN,IAAIO,IAAI,EAAEL,OAAO,wCAAKM,eAAK,EAAKC,gBAAM,EAAKC,gBAAM;QAAEC,GAAG;YAAEC,MAAM;QAAS;SAArGC,SAAwBP,OAAxBO,QAAQC,cAAgBR,OAAhBQ;IAChB,IAAkBA,gCAAAA,iBAAXC,UAAWD;IAClB,IAAI,CAACC,SAASf,IAAIgB,UAAU,CAACd;IAC7B,IAAMS,KAAIV,UAAAA,IAAAA,gBAAM,EAACY,OAAOF,CAAC,EAAwBX,IAAIgB,UAAU,eAArDf,qBAAAA,UAA0DH;IACpE,IAAMmB,SAASC,IAAAA,qBAAW,EAACL;IAC3B,OAAOM,IAAAA,gBAAM,EAACnB,KAAKa,OAAOO,MAAM,EAAwB,SAAOC,IAAIC;;gBAC3DC;;;;wBAAAA,YAAYC,IAAAA,iBAAO,EAACX;wBACf;;4BAAMY,IAAAA,wBAAY,EAACJ,IAAIC,KAAKP,SAASQ,WAAWZ;;;wBAA3De,mBAAS;4BAAE;4BAA8DT;;;;;;;QAC3E;;AACF;IACA,WAAelB"}
|
package/dist/cjs/cli/search.js
CHANGED
|
@@ -225,7 +225,7 @@ var searchCmd = function searchCmd(ctx) {
|
|
|
225
225
|
_positionals = _sliced_to_array(positionals, 1), terms = _positionals[0];
|
|
226
226
|
if (!terms) ctx.usageError(usage);
|
|
227
227
|
k = (0, _sharedts.parseK)(values.k, ctx.usageError);
|
|
228
|
-
format = (0, _sharedts.
|
|
228
|
+
format = (0, _sharedts.rowFormatOf)(values);
|
|
229
229
|
return [
|
|
230
230
|
4,
|
|
231
231
|
(0, _sharedts.withDb)(ctx, values.config, function(db, cfg) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/search.ts"],"sourcesContent":["import { search } from '../commands.ts';\nimport { printRows } from '../output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT,
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/search.ts"],"sourcesContent":["import { search } from '../commands.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":["searchCmd","ctx","usage","parse","values","positionals","terms","k","format","USAGE","name","search","argv","SEARCH_FLAGS","FORMAT","CONFIG","usageError","parseK","rowFormatOf","withDb","config","db","cfg","scopeOf","printRows"],"mappings":";;;;+BAeA;;;eAAA;;;0BAfuB;wBACG;uBACJ;wBACoE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG1F,IAAMA,YAAqB,mBAAOC;;YAC1BC,OAC0BC,QAAxBC,QAAQC,aACAA,cAATC,OAEDC,GACAC;;;;oBALAN,QAAQ,AAAC,UAAqBO,OAAZR,IAAIS,IAAI,EAAC,KAAgB,OAAbD,cAAK,CAACE,MAAM;oBAChBR,SAAAA,IAAAA,eAAK,EAACF,IAAIW,IAAI,EAAEV,OAAO,mBAAKW,sBAAY,EAAKC,gBAAM,EAAKC,gBAAM,IAAtFX,SAAwBD,OAAxBC,QAAQC,cAAgBF,OAAhBE;oBACAA,gCAAAA,iBAATC,QAASD;oBAChB,IAAI,CAACC,OAAOL,IAAIe,UAAU,CAACd;oBACrBK,IAAIU,IAAAA,gBAAM,EAACb,OAAOG,CAAC,EAAwBN,IAAIe,UAAU;oBACzDR,SAASU,IAAAA,qBAAW,EAACd;oBAC3B;;wBAAMe,IAAAA,gBAAM,EAAClB,KAAKG,OAAOgB,MAAM,EAAwB,SAAOC,IAAIC;;;;;4CAAkB;;gDAAMX,IAAAA,kBAAM,EAACU,IAAIC,KAAKhB,OAAO;oDAAEC,GAAAA;mDAAMgB,IAAAA,iBAAO,EAACnB;;;;;gDAAvDoB,mBAAS;oDAAC;oDAAyDhB;;;;;;;;;oBAA7I;;;;;;IACF;;IACA,WAAeR"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ParseArgsOptionsConfig } from 'node:util';
|
|
2
2
|
import type { ResolvedConfig, SearchOverrides } from '../config.js';
|
|
3
3
|
import type { OpenResult } from '../db.js';
|
|
4
|
+
import type { RowFormat } from '../output.js';
|
|
4
5
|
import type { Ctx } from './types.js';
|
|
5
6
|
export declare const FORMAT: ParseArgsOptionsConfig;
|
|
6
7
|
export declare const CONFIG: ParseArgsOptionsConfig;
|
|
@@ -9,6 +10,7 @@ export declare const SEARCH_FLAGS: ParseArgsOptionsConfig;
|
|
|
9
10
|
type Values = Record<string, string | boolean | string[] | undefined>;
|
|
10
11
|
export declare function scopeOf(values: Values): SearchOverrides;
|
|
11
12
|
export declare function formatOf(values: Values): 'table' | 'json';
|
|
13
|
+
export declare function rowFormatOf(values: Values): RowFormat;
|
|
12
14
|
export declare function parse(argv: string[], usage: string, options: ParseArgsOptionsConfig): {
|
|
13
15
|
values: Values;
|
|
14
16
|
positionals: string[];
|
|
@@ -16,5 +18,5 @@ export declare function parse(argv: string[], usage: string, options: ParseArgsO
|
|
|
16
18
|
export declare function parseK(k: string | undefined, usageError: (message: string) => never): number | undefined;
|
|
17
19
|
export declare function printWarnings(warnings: string[]): void;
|
|
18
20
|
export declare function withDb(ctx: Ctx, configPath: string | undefined, fn: (db: OpenResult['db'], cfg: ResolvedConfig) => void | Promise<void>): Promise<void>;
|
|
19
|
-
export declare function runSql(cfg: ResolvedConfig, sql: string, params: string[], format:
|
|
21
|
+
export declare function runSql(cfg: ResolvedConfig, sql: string, params: string[], format: RowFormat, label: string, preset?: string): void;
|
|
20
22
|
export {};
|
package/dist/cjs/cli/shared.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ParseArgsOptionsConfig } from 'node:util';
|
|
2
2
|
import type { ResolvedConfig, SearchOverrides } from '../config.js';
|
|
3
3
|
import type { OpenResult } from '../db.js';
|
|
4
|
+
import type { RowFormat } from '../output.js';
|
|
4
5
|
import type { Ctx } from './types.js';
|
|
5
6
|
export declare const FORMAT: ParseArgsOptionsConfig;
|
|
6
7
|
export declare const CONFIG: ParseArgsOptionsConfig;
|
|
@@ -9,6 +10,7 @@ export declare const SEARCH_FLAGS: ParseArgsOptionsConfig;
|
|
|
9
10
|
type Values = Record<string, string | boolean | string[] | undefined>;
|
|
10
11
|
export declare function scopeOf(values: Values): SearchOverrides;
|
|
11
12
|
export declare function formatOf(values: Values): 'table' | 'json';
|
|
13
|
+
export declare function rowFormatOf(values: Values): RowFormat;
|
|
12
14
|
export declare function parse(argv: string[], usage: string, options: ParseArgsOptionsConfig): {
|
|
13
15
|
values: Values;
|
|
14
16
|
positionals: string[];
|
|
@@ -16,5 +18,5 @@ export declare function parse(argv: string[], usage: string, options: ParseArgsO
|
|
|
16
18
|
export declare function parseK(k: string | undefined, usageError: (message: string) => never): number | undefined;
|
|
17
19
|
export declare function printWarnings(warnings: string[]): void;
|
|
18
20
|
export declare function withDb(ctx: Ctx, configPath: string | undefined, fn: (db: OpenResult['db'], cfg: ResolvedConfig) => void | Promise<void>): Promise<void>;
|
|
19
|
-
export declare function runSql(cfg: ResolvedConfig, sql: string, params: string[], format:
|
|
21
|
+
export declare function runSql(cfg: ResolvedConfig, sql: string, params: string[], format: RowFormat, label: string, preset?: string): void;
|
|
20
22
|
export {};
|
package/dist/cjs/cli/shared.js
CHANGED
|
@@ -33,6 +33,9 @@ _export(exports, {
|
|
|
33
33
|
get printWarnings () {
|
|
34
34
|
return printWarnings;
|
|
35
35
|
},
|
|
36
|
+
get rowFormatOf () {
|
|
37
|
+
return rowFormatOf;
|
|
38
|
+
},
|
|
36
39
|
get runSql () {
|
|
37
40
|
return runSql;
|
|
38
41
|
},
|
|
@@ -300,8 +303,26 @@ function scopeOf(values) {
|
|
|
300
303
|
noExclude: values['no-exclude'] === true
|
|
301
304
|
};
|
|
302
305
|
}
|
|
306
|
+
// An unrecognised value used to fall through to `table`, so a typo looked like it worked.
|
|
307
|
+
// parseArgs is strict about flag names; this is the same strictness for the value.
|
|
308
|
+
function pickFormat(values, allowed) {
|
|
309
|
+
var format = String(values.format);
|
|
310
|
+
if (allowed.includes(format)) return format;
|
|
311
|
+
console.error('unknown --format "'.concat(format, '"; expected ').concat(allowed.join(', ')));
|
|
312
|
+
process.exit(2);
|
|
313
|
+
}
|
|
303
314
|
function formatOf(values) {
|
|
304
|
-
return values
|
|
315
|
+
return pickFormat(values, [
|
|
316
|
+
'table',
|
|
317
|
+
'json'
|
|
318
|
+
]);
|
|
319
|
+
}
|
|
320
|
+
function rowFormatOf(values) {
|
|
321
|
+
return pickFormat(values, [
|
|
322
|
+
'table',
|
|
323
|
+
'json',
|
|
324
|
+
'csv'
|
|
325
|
+
]);
|
|
305
326
|
}
|
|
306
327
|
function parse(argv, usage, options) {
|
|
307
328
|
var values;
|
|
@@ -430,10 +451,20 @@ function runSql(cfg, sql, params, format, label, preset) {
|
|
|
430
451
|
var _open = (0, _dbts.open)(cfg), db = _open.db, warnings = _open.warnings;
|
|
431
452
|
printWarnings(warnings);
|
|
432
453
|
if (preset !== undefined) bindScope(db, cfg, preset);
|
|
433
|
-
|
|
454
|
+
// Streamed rather than collected: `sql` is the one caller whose result size is the
|
|
455
|
+
// statement's business, not this package's, so the rows are never held here in bulk.
|
|
456
|
+
// columns() reads the statement's own metadata, so a 0-row csv still has its header.
|
|
457
|
+
// A mid-stream SQLite error (e.g. SQLITE_BUSY outlasting busy_timeout) can still leave
|
|
458
|
+
// partial output; the nonzero exit code is the caller's signal, output completeness is not
|
|
459
|
+
// guaranteed on failure.
|
|
434
460
|
try {
|
|
435
|
-
var
|
|
436
|
-
|
|
461
|
+
var _statement;
|
|
462
|
+
var statement = db.prepare(sql);
|
|
463
|
+
statement.setReadBigInts(true); // int64 past 2^53 arrives as BigInt instead of throwing at step time
|
|
464
|
+
var columns = statement.columns().map(function(c) {
|
|
465
|
+
return c.name;
|
|
466
|
+
});
|
|
467
|
+
(0, _outputts.printRowStream)((_statement = statement).iterate.apply(_statement, _to_consumable_array(params)), format, columns);
|
|
437
468
|
} catch (err) {
|
|
438
469
|
db.close();
|
|
439
470
|
// A saved query or ad-hoc SQL can carry `content MATCH ?` too, so the same FTS5
|
|
@@ -442,7 +473,6 @@ function runSql(cfg, sql, params, format, label, preset) {
|
|
|
442
473
|
if (/\bMATCH\b/i.test(sql)) throw (0, _searcherrorts.searchError)(err, params.join(' '));
|
|
443
474
|
throw err;
|
|
444
475
|
}
|
|
445
|
-
(0, _outputts.printRows)(rows, format);
|
|
446
476
|
db.close();
|
|
447
477
|
}
|
|
448
478
|
/* 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/shared.ts"],"sourcesContent":["import type { ParseArgsOptionsConfig } from 'node:util';\nimport { parseArgs } from 'node:util';\nimport type { ResolvedConfig, SearchOverrides } from '../config.ts';\nimport { resolvePreset } from '../config.ts';\nimport type { OpenResult } from '../db.ts';\nimport { open } from '../db.ts';\nimport type { Row } from '../output.ts';\nimport { printRows } from '../output.ts';\nimport { searchError } from '../search-error.ts';\nimport type { Ctx } from './types.ts';\n\n// Spreadable option fragments -- one flag name keeps one meaning across every command's table.\nexport const FORMAT: ParseArgsOptionsConfig = { format: { type: 'string', default: 'table' } };\nexport const CONFIG: ParseArgsOptionsConfig = { config: { type: 'string' } };\n// The scope vocabulary every scoped command shares: named preset, ad hoc include/exclude\n// globs, a where SQL condition. search adds k on top.\nexport const SCOPE: ParseArgsOptionsConfig = {\n where: { type: 'string' },\n preset: { type: 'string' },\n include: { type: 'string', multiple: true },\n exclude: { type: 'string', multiple: true },\n // Widening, which no other flag can express: --include and --exclude each override their\n // own side of the preset, so neither can drop an exclusion the preset declares.\n 'no-exclude': { type: 'boolean', default: false },\n};\nexport const SEARCH_FLAGS: ParseArgsOptionsConfig = { ...SCOPE, k: { type: 'string' } };\n\ntype Values = Record<string, string | boolean | string[] | undefined>;\n\n// The SCOPE fragment's parsed values as the overrides every scoped command passes down. One\n// place to read them, so a new scope field is added to the fragment and here, not in each\n// command's call.\nexport function scopeOf(values: Values): SearchOverrides {\n return {\n preset: values.preset as string | undefined,\n include: values.include as string[] | undefined,\n exclude: values.exclude as string[] | undefined,\n where: values.where as string | undefined,\n noExclude: values['no-exclude'] === true,\n };\n}\n\nexport function formatOf(values: Values): 'table' | 'json' {\n return values.format === 'json' ? 'json' : 'table';\n}\n\n// Per-command parseArgs: strict (a foreign flag exits 2), and every table gets --help for free.\nexport function parse(argv: string[], usage: string, options: ParseArgsOptionsConfig): { values: Values; positionals: string[] } {\n let values: Values;\n let positionals: string[];\n try {\n ({ values, positionals } = parseArgs({\n args: argv,\n options: { ...options, help: { type: 'boolean', default: false, short: 'h' } },\n strict: true,\n allowPositionals: true,\n }));\n } catch (err) {\n console.error((err as Error).message);\n console.error(usage);\n process.exit(2);\n }\n if (values.help) {\n console.log(usage);\n process.exit(0);\n }\n return { values, positionals };\n}\n\n// --k must be a positive integer: SQLite reads a bound LIMIT of -1 as \"unlimited\" and 0 as\n// \"nothing\", and parseInt would silently truncate \"5.9\" -- all three are caller mistakes\n// worth a usage error, matching the config-level SavedSearch validation.\nexport function parseK(k: string | undefined, usageError: (message: string) => never): number | undefined {\n if (k === undefined) return undefined;\n const parsed = Number(k);\n if (!Number.isInteger(parsed) || parsed <= 0) usageError(`--k expects a positive integer, got \"${k}\"`);\n return parsed;\n}\n\n// Shared open-query-close envelope for commands that touch the tree.\n\nexport function printWarnings(warnings: string[]): void {\n for (const w of warnings) console.warn(w);\n}\n\nexport async function withDb(ctx: Ctx, configPath: string | undefined, fn: (db: OpenResult['db'], cfg: ResolvedConfig) => void | Promise<void>): Promise<void> {\n const cfg = ctx.resolveConfig(configPath);\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n try {\n await fn(db, cfg);\n } finally {\n db.close();\n }\n}\n\n// `--preset` on SQL binds the scope rather than applying it: the statement joins `scope`\n// itself. Filtering behind the query's back is not available -- the obvious version, temp views\n// shadowing the base tables, cannot cover `content`, because FTS5 `MATCH` uses the table name\n// as a hidden column and a view has none. A flag that silently scoped three tables of four\n// would look scoped and not be. See plans/vault-field-report-fixes.md item F.\nfunction bindScope(db: OpenResult['db'], cfg: ResolvedConfig, preset: string): void {\n const { name } = resolvePreset(cfg, preset); // unknown names throw, listing what is declared\n db.exec('DROP TABLE IF EXISTS temp.scope');\n db.exec('CREATE TEMP TABLE scope (\"path\" TEXT PRIMARY KEY)');\n db.prepare('INSERT INTO temp.scope (\"path\") SELECT \"path\" FROM preset_files WHERE preset = ?').run(name);\n}\n\n// An unbound `?` silently binds NULL, so mismatched param counts fail loudly instead.\nexport function runSql(cfg: ResolvedConfig, sql: string, params: string[], format: 'table' | 'json', label: string, preset?: string): void {\n const placeholderCount = (sql.match(/\\?/g) ?? []).length;\n if (params.length !== placeholderCount) {\n console.error(`${label} expects ${placeholderCount} parameter(s), got ${params.length}`);\n process.exit(2);\n }\n // Naming a preset and never joining it would return the whole index while reading as scoped,\n // which is the one hazard of binding rather than applying. Refuse instead.\n if (preset !== undefined && !/\\bscope\\b/i.test(sql)) {\n console.error(`--preset binds a temporary \"scope\" table of the preset's paths, and ${label} never joins it, so the preset would have no effect`);\n console.error(`add: JOIN scope ON scope.\"path\" = <table>.\"path\"`);\n process.exit(2);\n }\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n if (preset !== undefined) bindScope(db, cfg, preset);\n let rows: Row[];\n try {\n rows = db.prepare(sql).all(...params) as Row[];\n } catch (err) {\n db.close();\n // A saved query or ad-hoc SQL can carry `content MATCH ?` too, so the same FTS5\n // punctuation trap applies -- the bound parameters are the search terms there. SQL\n // without MATCH gets its error verbatim; search advice on a plain typo would mislead.\n if (/\\bMATCH\\b/i.test(sql)) throw searchError(err as Error, params.join(' '));\n throw err;\n }\n printRows(rows, format);\n db.close();\n}\n"],"names":["CONFIG","FORMAT","SCOPE","SEARCH_FLAGS","formatOf","parse","parseK","printWarnings","runSql","scopeOf","withDb","format","type","default","config","where","preset","include","multiple","exclude","k","values","noExclude","argv","usage","options","positionals","parseArgs","args","help","short","strict","allowPositionals","err","console","error","message","process","exit","log","usageError","undefined","parsed","Number","isInteger","warnings","w","warn","ctx","configPath","fn","cfg","open","db","resolveConfig","close","bindScope","name","resolvePreset","exec","prepare","run","sql","params","label","placeholderCount","match","length","test","rows","all","searchError","join","printRows"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/shared.ts"],"sourcesContent":["import type { ParseArgsOptionsConfig } from 'node:util';\nimport { parseArgs } from 'node:util';\nimport type { ResolvedConfig, SearchOverrides } from '../config.ts';\nimport { resolvePreset } from '../config.ts';\nimport type { OpenResult } from '../db.ts';\nimport { open } from '../db.ts';\nimport type { Row, RowFormat } from '../output.ts';\nimport { printRowStream } from '../output.ts';\nimport { searchError } from '../search-error.ts';\nimport type { Ctx } from './types.ts';\n\n// Spreadable option fragments -- one flag name keeps one meaning across every command's table.\nexport const FORMAT: ParseArgsOptionsConfig = { format: { type: 'string', default: 'table' } };\nexport const CONFIG: ParseArgsOptionsConfig = { config: { type: 'string' } };\n// The scope vocabulary every scoped command shares: named preset, ad hoc include/exclude\n// globs, a where SQL condition. search adds k on top.\nexport const SCOPE: ParseArgsOptionsConfig = {\n where: { type: 'string' },\n preset: { type: 'string' },\n include: { type: 'string', multiple: true },\n exclude: { type: 'string', multiple: true },\n // Widening, which no other flag can express: --include and --exclude each override their\n // own side of the preset, so neither can drop an exclusion the preset declares.\n 'no-exclude': { type: 'boolean', default: false },\n};\nexport const SEARCH_FLAGS: ParseArgsOptionsConfig = { ...SCOPE, k: { type: 'string' } };\n\ntype Values = Record<string, string | boolean | string[] | undefined>;\n\n// The SCOPE fragment's parsed values as the overrides every scoped command passes down. One\n// place to read them, so a new scope field is added to the fragment and here, not in each\n// command's call.\nexport function scopeOf(values: Values): SearchOverrides {\n return {\n preset: values.preset as string | undefined,\n include: values.include as string[] | undefined,\n exclude: values.exclude as string[] | undefined,\n where: values.where as string | undefined,\n noExclude: values['no-exclude'] === true,\n };\n}\n\n// An unrecognised value used to fall through to `table`, so a typo looked like it worked.\n// parseArgs is strict about flag names; this is the same strictness for the value.\nfunction pickFormat<T extends string>(values: Values, allowed: readonly T[]): T {\n const format = String(values.format);\n if ((allowed as readonly string[]).includes(format)) return format as T;\n console.error(`unknown --format \"${format}\"; expected ${allowed.join(', ')}`);\n process.exit(2);\n}\n\nexport function formatOf(values: Values): 'table' | 'json' {\n return pickFormat(values, ['table', 'json'] as const);\n}\n\n// csv is a row set rendered as rows; map, peek, status, and path render structures instead,\n// and take formatOf.\nexport function rowFormatOf(values: Values): RowFormat {\n return pickFormat(values, ['table', 'json', 'csv'] as const);\n}\n\n// Per-command parseArgs: strict (a foreign flag exits 2), and every table gets --help for free.\nexport function parse(argv: string[], usage: string, options: ParseArgsOptionsConfig): { values: Values; positionals: string[] } {\n let values: Values;\n let positionals: string[];\n try {\n ({ values, positionals } = parseArgs({\n args: argv,\n options: { ...options, help: { type: 'boolean', default: false, short: 'h' } },\n strict: true,\n allowPositionals: true,\n }));\n } catch (err) {\n console.error((err as Error).message);\n console.error(usage);\n process.exit(2);\n }\n if (values.help) {\n console.log(usage);\n process.exit(0);\n }\n return { values, positionals };\n}\n\n// --k must be a positive integer: SQLite reads a bound LIMIT of -1 as \"unlimited\" and 0 as\n// \"nothing\", and parseInt would silently truncate \"5.9\" -- all three are caller mistakes\n// worth a usage error, matching the config-level SavedSearch validation.\nexport function parseK(k: string | undefined, usageError: (message: string) => never): number | undefined {\n if (k === undefined) return undefined;\n const parsed = Number(k);\n if (!Number.isInteger(parsed) || parsed <= 0) usageError(`--k expects a positive integer, got \"${k}\"`);\n return parsed;\n}\n\n// Shared open-query-close envelope for commands that touch the tree.\n\nexport function printWarnings(warnings: string[]): void {\n for (const w of warnings) console.warn(w);\n}\n\nexport async function withDb(ctx: Ctx, configPath: string | undefined, fn: (db: OpenResult['db'], cfg: ResolvedConfig) => void | Promise<void>): Promise<void> {\n const cfg = ctx.resolveConfig(configPath);\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n try {\n await fn(db, cfg);\n } finally {\n db.close();\n }\n}\n\n// `--preset` on SQL binds the scope rather than applying it: the statement joins `scope`\n// itself. Filtering behind the query's back is not available -- the obvious version, temp views\n// shadowing the base tables, cannot cover `content`, because FTS5 `MATCH` uses the table name\n// as a hidden column and a view has none. A flag that silently scoped three tables of four\n// would look scoped and not be. See plans/vault-field-report-fixes.md item F.\nfunction bindScope(db: OpenResult['db'], cfg: ResolvedConfig, preset: string): void {\n const { name } = resolvePreset(cfg, preset); // unknown names throw, listing what is declared\n db.exec('DROP TABLE IF EXISTS temp.scope');\n db.exec('CREATE TEMP TABLE scope (\"path\" TEXT PRIMARY KEY)');\n db.prepare('INSERT INTO temp.scope (\"path\") SELECT \"path\" FROM preset_files WHERE preset = ?').run(name);\n}\n\n// An unbound `?` silently binds NULL, so mismatched param counts fail loudly instead.\nexport function runSql(cfg: ResolvedConfig, sql: string, params: string[], format: RowFormat, label: string, preset?: string): void {\n const placeholderCount = (sql.match(/\\?/g) ?? []).length;\n if (params.length !== placeholderCount) {\n console.error(`${label} expects ${placeholderCount} parameter(s), got ${params.length}`);\n process.exit(2);\n }\n // Naming a preset and never joining it would return the whole index while reading as scoped,\n // which is the one hazard of binding rather than applying. Refuse instead.\n if (preset !== undefined && !/\\bscope\\b/i.test(sql)) {\n console.error(`--preset binds a temporary \"scope\" table of the preset's paths, and ${label} never joins it, so the preset would have no effect`);\n console.error(`add: JOIN scope ON scope.\"path\" = <table>.\"path\"`);\n process.exit(2);\n }\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n if (preset !== undefined) bindScope(db, cfg, preset);\n // Streamed rather than collected: `sql` is the one caller whose result size is the\n // statement's business, not this package's, so the rows are never held here in bulk.\n // columns() reads the statement's own metadata, so a 0-row csv still has its header.\n // A mid-stream SQLite error (e.g. SQLITE_BUSY outlasting busy_timeout) can still leave\n // partial output; the nonzero exit code is the caller's signal, output completeness is not\n // guaranteed on failure.\n try {\n const statement = db.prepare(sql);\n statement.setReadBigInts(true); // int64 past 2^53 arrives as BigInt instead of throwing at step time\n const columns = statement.columns().map((c) => c.name);\n printRowStream(statement.iterate(...params) as Iterable<Row>, format, columns);\n } catch (err) {\n db.close();\n // A saved query or ad-hoc SQL can carry `content MATCH ?` too, so the same FTS5\n // punctuation trap applies -- the bound parameters are the search terms there. SQL\n // without MATCH gets its error verbatim; search advice on a plain typo would mislead.\n if (/\\bMATCH\\b/i.test(sql)) throw searchError(err as Error, params.join(' '));\n throw err;\n }\n db.close();\n}\n"],"names":["CONFIG","FORMAT","SCOPE","SEARCH_FLAGS","formatOf","parse","parseK","printWarnings","rowFormatOf","runSql","scopeOf","withDb","format","type","default","config","where","preset","include","multiple","exclude","k","values","noExclude","pickFormat","allowed","String","includes","console","error","join","process","exit","argv","usage","options","positionals","parseArgs","args","help","short","strict","allowPositionals","err","message","log","usageError","undefined","parsed","Number","isInteger","warnings","w","warn","ctx","configPath","fn","cfg","open","db","resolveConfig","close","bindScope","name","resolvePreset","exec","prepare","run","sql","params","label","placeholderCount","match","length","test","statement","setReadBigInts","columns","map","c","printRowStream","iterate","searchError"],"mappings":"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"}
|
package/dist/cjs/cli/sql.js
CHANGED
|
@@ -96,7 +96,7 @@ var sqlCmd = function sqlCmd(ctx) {
|
|
|
96
96
|
})), values = _parse.values, positionals = _parse.positionals;
|
|
97
97
|
var _positionals = _to_array(positionals), sql = _positionals[0], params = _positionals.slice(1);
|
|
98
98
|
if (!sql) ctx.usageError(usage);
|
|
99
|
-
var format = (0, _sharedts.
|
|
99
|
+
var format = (0, _sharedts.rowFormatOf)(values);
|
|
100
100
|
(0, _sharedts.runSql)(ctx.resolveConfig(values.config), sql, params, format, 'ad-hoc statement', values.preset);
|
|
101
101
|
};
|
|
102
102
|
var _default = sqlCmd;
|
package/dist/cjs/cli/sql.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/sql.ts"],"sourcesContent":["import { USAGE } from './index.ts';\nimport { CONFIG, FORMAT,
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/sql.ts"],"sourcesContent":["import { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, parse, rowFormatOf, runSql } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst sqlCmd: Command = (ctx) => {\n const usage = `usage: ${ctx.name} ${USAGE.sql}`;\n const { values, positionals } = parse(ctx.argv, usage, { ...FORMAT, ...CONFIG, preset: { type: 'string' } });\n const [sql, ...params] = positionals;\n if (!sql) ctx.usageError(usage);\n const format = rowFormatOf(values);\n runSql(ctx.resolveConfig(values.config as string | undefined), sql, params, format, 'ad-hoc statement', values.preset as string | undefined);\n};\nexport default sqlCmd;\n"],"names":["sqlCmd","ctx","usage","USAGE","name","sql","parse","argv","FORMAT","CONFIG","preset","type","values","positionals","params","usageError","format","rowFormatOf","runSql","resolveConfig","config"],"mappings":";;;;+BAYA;;;eAAA;;;uBAZsB;wBACqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG3D,IAAMA,SAAkB,gBAACC;IACvB,IAAMC,QAAQ,AAAC,UAAqBC,OAAZF,IAAIG,IAAI,EAAC,KAAa,OAAVD,cAAK,CAACE,GAAG;IAC7C,IAAgCC,SAAAA,IAAAA,eAAK,EAACL,IAAIM,IAAI,EAAEL,OAAO,wCAAKM,gBAAM,EAAKC,gBAAM;QAAEC,QAAQ;YAAEC,MAAM;QAAS;SAAhGC,SAAwBN,OAAxBM,QAAQC,cAAgBP,OAAhBO;IAChB,IAAyBA,yBAAAA,cAAlBR,MAAkBQ,iBAAb,AAAGC,SAAUD,mBAAb;IACZ,IAAI,CAACR,KAAKJ,IAAIc,UAAU,CAACb;IACzB,IAAMc,SAASC,IAAAA,qBAAW,EAACL;IAC3BM,IAAAA,gBAAM,EAACjB,IAAIkB,aAAa,CAACP,OAAOQ,MAAM,GAAyBf,KAAKS,QAAQE,QAAQ,oBAAoBJ,OAAOF,MAAM;AACvH;IACA,WAAeV"}
|
package/dist/cjs/cli.js
CHANGED
|
@@ -230,7 +230,7 @@ function usage(name) {
|
|
|
230
230
|
return " ".concat(name, " ").concat(u);
|
|
231
231
|
});
|
|
232
232
|
return [
|
|
233
|
-
"usage: ".concat(name, " <name> [params...] [--format table|json] [--config path]")
|
|
233
|
+
"usage: ".concat(name, " <name> [params...] [--format table|json|csv] [--config path]")
|
|
234
234
|
].concat(_to_consumable_array(lines), [
|
|
235
235
|
" ".concat(name, " --list"),
|
|
236
236
|
" ".concat(name, " --version")
|
|
@@ -252,6 +252,19 @@ function cli(argv, name) {
|
|
|
252
252
|
return _ts_generator(this, function(_state) {
|
|
253
253
|
switch(_state.label){
|
|
254
254
|
case 0:
|
|
255
|
+
// stdout is a pipe whenever the caller pipes or redirects, and a reader that goes away
|
|
256
|
+
// (`| head`) makes every later write fail. The failure arrives asynchronously, after the
|
|
257
|
+
// write loop has already returned: console.log absorbs it, process.stdout.write (what the
|
|
258
|
+
// streaming formats use) does not, so with no listener the process dies on an unhandled
|
|
259
|
+
// 'error' event having already done its work. Neither throwing nor exiting is safe from
|
|
260
|
+
// here. The event is async, so a throw is an uncaught exception rather than something
|
|
261
|
+
// bin/cli.js can catch, and process.exit() would skip the cleanup `sense watch` runs on the
|
|
262
|
+
// way out, leaving a heartbeat behind that makes a dead watcher look alive.
|
|
263
|
+
process.stdout.on('error', function(err) {
|
|
264
|
+
if (err.code === 'EPIPE') return;
|
|
265
|
+
console.error("sense: ".concat(err.message));
|
|
266
|
+
process.exitCode = 1;
|
|
267
|
+
});
|
|
255
268
|
first = argv[0];
|
|
256
269
|
// No command word, or the first token looks like a flag: the only flags this level knows.
|
|
257
270
|
if (!first || first.startsWith('-')) {
|
package/dist/cjs/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { parseArgs } from 'node:util';\nimport { COMMANDS, USAGE } from './cli/index.ts';\nimport type { Ctx } from './cli/types.ts';\nimport { loadConfig, SUPPORTED_CONFIG_VERSION } from './config.ts';\n\n// Parsing and dispatch only; commands lazy-load from src/cli/, so nothing heavy is imported\n// here. Flags parse per command -- this file handles only --version/--help/--list/--config.\n\n// Works from dist/cjs and dist/esm alike: walk up past the dist type-marker package.json.\nfunction packageVersion(): string {\n const load = createRequire(import.meta.url);\n for (const rel of ['../package.json', '../../package.json', '../../../package.json']) {\n try {\n const pkg = load(rel) as { name?: string; version?: string };\n if (pkg.name === 'sensemaking' && pkg.version) return pkg.version;\n } catch {}\n }\n return 'unknown';\n}\n\nfunction usage(name: string): string {\n const lines = Object.values(USAGE).map((u) => ` ${name} ${u}`);\n return [`usage: ${name} <name> [params...] [--format table|json] [--config path]`, ...lines, ` ${name} --list`, ` ${name} --version`].join('\\n');\n}\n\nfunction resolveConfigFor(name: string, configPath: string | undefined) {\n const cfg = loadConfig(configPath);\n if (cfg.migratedFrom !== undefined) {\n console.warn(`${name}: migrated ${cfg.configPath} from config version ${cfg.migratedFrom} to ${SUPPORTED_CONFIG_VERSION}`);\n }\n if (cfg.unknownKeys !== undefined) {\n console.warn(`${name}: ${cfg.configPath} sets ${cfg.unknownKeys.join(', ')}, which this build does not read (no effect); see schema.json for the keys it does`);\n }\n return cfg;\n}\n\n// Thrown errors -> exit 1 with the message verbatim; usage errors exit 2 directly.\nexport default async function cli(argv: string[], name: string): Promise<void> {\n const first = argv[0];\n\n // No command word, or the first token looks like a flag: the only flags this level knows.\n if (!first || first.startsWith('-')) {\n let values: Record<string, string | boolean | undefined>;\n try {\n ({ values } = parseArgs({\n args: argv,\n options: {\n version: { type: 'boolean', default: false, short: 'v' },\n help: { type: 'boolean', default: false, short: 'h' },\n list: { type: 'boolean', default: false },\n config: { type: 'string' },\n },\n allowPositionals: true,\n }));\n } catch (err) {\n console.error((err as Error).message);\n console.error(usage(name));\n process.exit(2);\n }\n\n try {\n if (values.version) {\n console.log(packageVersion());\n return;\n }\n if (values.help) {\n console.log(usage(name));\n return;\n }\n if (values.list) {\n const queries = resolveConfigFor(name, values.config as string | undefined).queries;\n for (const queryName of Object.keys(queries).sort()) {\n // Every entry names its verb, so --list can label both kinds rather than only\n // marking the exception.\n console.log(`${queryName} (${'search' in queries[queryName] ? 'search' : 'sql'})`);\n }\n return;\n }\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n\n console.error(usage(name));\n process.exit(2);\n }\n\n // Breaking renames get one release of a pointer instead of an \"unknown\" error: find ->\n // search, and query -> sql (which took its name back from the search sense of \"query\").\n const RENAMED: Record<string, string> = { find: 'search', query: 'sql' };\n if (RENAMED[first]) {\n console.error(`${name}: ${first} is now ${RENAMED[first]}`);\n console.error(usage(name));\n process.exit(2);\n }\n\n const ctx: Ctx = {\n name,\n argv: argv.slice(1),\n resolveConfig: (configPath) => resolveConfigFor(name, configPath),\n usageError(message) {\n console.error(message);\n process.exit(2);\n },\n };\n\n try {\n const load = COMMANDS[first];\n if (load) await (await load()).default(ctx);\n else await (await import('./cli/named.ts')).default(ctx, first);\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n}\n"],"names":["cli","packageVersion","load","createRequire","rel","pkg","name","version","usage","lines","Object","values","USAGE","map","u","join","resolveConfigFor","configPath","cfg","loadConfig","migratedFrom","undefined","console","warn","SUPPORTED_CONFIG_VERSION","unknownKeys","argv","first","queries","queryName","RENAMED","ctx","err","startsWith","parseArgs","args","options","type","default","short","help","list","config","allowPositionals","
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { parseArgs } from 'node:util';\nimport { COMMANDS, USAGE } from './cli/index.ts';\nimport type { Ctx } from './cli/types.ts';\nimport { loadConfig, SUPPORTED_CONFIG_VERSION } from './config.ts';\n\n// Parsing and dispatch only; commands lazy-load from src/cli/, so nothing heavy is imported\n// here. Flags parse per command -- this file handles only --version/--help/--list/--config.\n\n// Works from dist/cjs and dist/esm alike: walk up past the dist type-marker package.json.\nfunction packageVersion(): string {\n const load = createRequire(import.meta.url);\n for (const rel of ['../package.json', '../../package.json', '../../../package.json']) {\n try {\n const pkg = load(rel) as { name?: string; version?: string };\n if (pkg.name === 'sensemaking' && pkg.version) return pkg.version;\n } catch {}\n }\n return 'unknown';\n}\n\nfunction usage(name: string): string {\n const lines = Object.values(USAGE).map((u) => ` ${name} ${u}`);\n return [`usage: ${name} <name> [params...] [--format table|json|csv] [--config path]`, ...lines, ` ${name} --list`, ` ${name} --version`].join('\\n');\n}\n\nfunction resolveConfigFor(name: string, configPath: string | undefined) {\n const cfg = loadConfig(configPath);\n if (cfg.migratedFrom !== undefined) {\n console.warn(`${name}: migrated ${cfg.configPath} from config version ${cfg.migratedFrom} to ${SUPPORTED_CONFIG_VERSION}`);\n }\n if (cfg.unknownKeys !== undefined) {\n console.warn(`${name}: ${cfg.configPath} sets ${cfg.unknownKeys.join(', ')}, which this build does not read (no effect); see schema.json for the keys it does`);\n }\n return cfg;\n}\n\n// Thrown errors -> exit 1 with the message verbatim; usage errors exit 2 directly.\nexport default async function cli(argv: string[], name: string): Promise<void> {\n // stdout is a pipe whenever the caller pipes or redirects, and a reader that goes away\n // (`| head`) makes every later write fail. The failure arrives asynchronously, after the\n // write loop has already returned: console.log absorbs it, process.stdout.write (what the\n // streaming formats use) does not, so with no listener the process dies on an unhandled\n // 'error' event having already done its work. Neither throwing nor exiting is safe from\n // here. The event is async, so a throw is an uncaught exception rather than something\n // bin/cli.js can catch, and process.exit() would skip the cleanup `sense watch` runs on the\n // way out, leaving a heartbeat behind that makes a dead watcher look alive.\n process.stdout.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EPIPE') return;\n console.error(`sense: ${err.message}`);\n process.exitCode = 1;\n });\n\n const first = argv[0];\n\n // No command word, or the first token looks like a flag: the only flags this level knows.\n if (!first || first.startsWith('-')) {\n let values: Record<string, string | boolean | undefined>;\n try {\n ({ values } = parseArgs({\n args: argv,\n options: {\n version: { type: 'boolean', default: false, short: 'v' },\n help: { type: 'boolean', default: false, short: 'h' },\n list: { type: 'boolean', default: false },\n config: { type: 'string' },\n },\n allowPositionals: true,\n }));\n } catch (err) {\n console.error((err as Error).message);\n console.error(usage(name));\n process.exit(2);\n }\n\n try {\n if (values.version) {\n console.log(packageVersion());\n return;\n }\n if (values.help) {\n console.log(usage(name));\n return;\n }\n if (values.list) {\n const queries = resolveConfigFor(name, values.config as string | undefined).queries;\n for (const queryName of Object.keys(queries).sort()) {\n // Every entry names its verb, so --list can label both kinds rather than only\n // marking the exception.\n console.log(`${queryName} (${'search' in queries[queryName] ? 'search' : 'sql'})`);\n }\n return;\n }\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n\n console.error(usage(name));\n process.exit(2);\n }\n\n // Breaking renames get one release of a pointer instead of an \"unknown\" error: find ->\n // search, and query -> sql (which took its name back from the search sense of \"query\").\n const RENAMED: Record<string, string> = { find: 'search', query: 'sql' };\n if (RENAMED[first]) {\n console.error(`${name}: ${first} is now ${RENAMED[first]}`);\n console.error(usage(name));\n process.exit(2);\n }\n\n const ctx: Ctx = {\n name,\n argv: argv.slice(1),\n resolveConfig: (configPath) => resolveConfigFor(name, configPath),\n usageError(message) {\n console.error(message);\n process.exit(2);\n },\n };\n\n try {\n const load = COMMANDS[first];\n if (load) await (await load()).default(ctx);\n else await (await import('./cli/named.ts')).default(ctx, first);\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n}\n"],"names":["cli","packageVersion","load","createRequire","rel","pkg","name","version","usage","lines","Object","values","USAGE","map","u","join","resolveConfigFor","configPath","cfg","loadConfig","migratedFrom","undefined","console","warn","SUPPORTED_CONFIG_VERSION","unknownKeys","argv","first","queries","queryName","RENAMED","ctx","err","process","stdout","on","code","error","message","exitCode","startsWith","parseArgs","args","options","type","default","short","help","list","config","allowPositionals","exit","log","keys","sort","find","query","slice","resolveConfig","usageError","COMMANDS"],"mappings":"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"}
|
package/dist/cjs/commands.js
CHANGED
|
@@ -40,6 +40,7 @@ var _embedts = require("./features/embed.js");
|
|
|
40
40
|
var _indexts = require("./features/index.js");
|
|
41
41
|
var _graphts = require("./graph.js");
|
|
42
42
|
var _searcherrorts = require("./search-error.js");
|
|
43
|
+
var _segmentts = require("./segment.js");
|
|
43
44
|
function _array_like_to_array(arr, len) {
|
|
44
45
|
if (len == null || len > arr.length) len = arr.length;
|
|
45
46
|
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
@@ -233,7 +234,9 @@ function _ts_generator(thisArg, body) {
|
|
|
233
234
|
}
|
|
234
235
|
// The three commands: mapTree (orient), search (locate), peek (structure).
|
|
235
236
|
// Each returns data; cli.ts renders. All of them degrade when a feature is off.
|
|
236
|
-
|
|
237
|
+
// Mirrors the main columns onto the sidecars, so a title match found through title_seg ranks
|
|
238
|
+
// like a title match found through title, not like a body match.
|
|
239
|
+
var WEIGHTED_BM25 = 'bm25(content, 10.0, 5.0, 1.0, 0, 10.0, 5.0, 1.0)';
|
|
237
240
|
var RRF_K = 60;
|
|
238
241
|
// snippet() re-tokenizes each candidate doc, superlinearly: ~10s for one 1MB doc
|
|
239
242
|
// (BENCHMARKING.md). Past this bound, rows get the linear JS excerpt instead.
|
|
@@ -393,7 +396,7 @@ function scopeHasEmbeddings(db, cfg, scopedPaths) {
|
|
|
393
396
|
}
|
|
394
397
|
function search(_0, _1, _2) {
|
|
395
398
|
return _async_to_generator(function(db, cfg, terms) {
|
|
396
|
-
var opts, _hits_get, _chunkLines_get, _chunkSimilarity_get, effective, k, include, exclude, allPaths, adHocScope, scopedPaths, scopeActive, fetch, wantsVectors, semanticEnabled, scope, whereJoin, whereCond, matchSql, matchRows, hits, oversized, candidates, edges, linked, seeds, ranked, chunkLines, chunkSimilarity, vec, insert, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, path, c, where, similarityCol, rows, bareTerms, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, row, text, _computeExcerpt, excerpt, offset;
|
|
399
|
+
var opts, _hits_get, _chunkLines_get, _chunkSimilarity_get, effective, k, include, exclude, allPaths, adHocScope, scopedPaths, scopeActive, fetch, wantsVectors, semanticEnabled, scope, whereJoin, whereCond, matchSql, query, matchRows, hits, oversized, candidates, edges, linked, seeds, ranked, chunkLines, chunkSimilarity, vec, insert, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, path, c, where, similarityCol, rows, bareTerms, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, row, text, _computeExcerpt, excerpt, offset;
|
|
397
400
|
var _arguments = arguments;
|
|
398
401
|
return _ts_generator(this, function(_state) {
|
|
399
402
|
switch(_state.label){
|
|
@@ -424,7 +427,14 @@ function search(_0, _1, _2) {
|
|
|
424
427
|
throw new _errorsts.SenseError('EMBED_MODEL_MISSING', 'preset "'.concat(effective.presetName, '" searches with vectors, but the embedding model is not available; run `sense download`, or set "semantic": false on that preset to search on words and links'));
|
|
425
428
|
}
|
|
426
429
|
semanticEnabled = wantsVectors && scopeHasEmbeddings(db, cfg, scopedPaths);
|
|
427
|
-
// Terms pass
|
|
430
|
+
// Terms pass to MATCH as written, with one transform: a run of text whose language marks no
|
|
431
|
+
// word boundaries becomes a quoted grapheme phrase (and a title:/summary:/text: qualifier
|
|
432
|
+
// ahead of it retargets its _seg column), matching how it was indexed. Text that already
|
|
433
|
+
// carries boundaries comes through untouched, so this is a no-op for the languages that
|
|
434
|
+
// never needed it. Gated on the same predicate that decided whether the sidecars were
|
|
435
|
+
// populated (contentTokenize(cfg) === undefined), so index and query can't disagree. Invalid
|
|
436
|
+
// syntax still errors rather than being rewritten.
|
|
437
|
+
// --where
|
|
428
438
|
// applies inside the candidate query (a post-filter would drop matches ranked past the pool)
|
|
429
439
|
// and again on the final select, for link-derived rows.
|
|
430
440
|
scope = effective.where;
|
|
@@ -432,9 +442,13 @@ function search(_0, _1, _2) {
|
|
|
432
442
|
whereCond = scope ? "AND (".concat(scope, ")") : '';
|
|
433
443
|
// Docs past SNIPPET_BOUND skip snippet() entirely -- SQLite
|
|
434
444
|
// short-circuits the untaken CASE branch, so it's never invoked on them.
|
|
435
|
-
|
|
445
|
+
// Column 2 (text), not -1 (best column): -1 could surface a _seg sidecar as the excerpt,
|
|
446
|
+
// which is machine-spaced and not what the author wrote. A row that matches only in a
|
|
447
|
+
// sidecar gets an unhighlighted text excerpt below instead -- a stated cost.
|
|
448
|
+
matchSql = "SELECT content.path AS path, CASE WHEN length(content.text) <= ".concat(SNIPPET_BOUND, " THEN snippet(content, 2, '\xab', '\xbb', '…', 10) ELSE NULL END AS hit FROM content ").concat(whereJoin, " WHERE content MATCH ? ").concat(whereCond, " ORDER BY ").concat(WEIGHTED_BM25, " LIMIT ").concat(fetch);
|
|
449
|
+
query = (0, _configts.contentTokenize)(cfg) === undefined ? (0, _segmentts.segmentMatch)(terms) : terms;
|
|
436
450
|
try {
|
|
437
|
-
matchRows = db.prepare(matchSql).all(
|
|
451
|
+
matchRows = db.prepare(matchSql).all(query);
|
|
438
452
|
} catch (err) {
|
|
439
453
|
throw (0, _searcherrorts.searchError)(err, terms, scope);
|
|
440
454
|
}
|