sensemaking 0.1.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/LICENSE +21 -0
- package/README.md +132 -0
- package/bin/cli.js +5 -0
- package/dist/cjs/cli.d.cts +1 -0
- package/dist/cjs/cli.d.ts +1 -0
- package/dist/cjs/cli.js +422 -0
- package/dist/cjs/cli.js.map +1 -0
- package/dist/cjs/config.d.cts +18 -0
- package/dist/cjs/config.d.ts +18 -0
- package/dist/cjs/config.js +147 -0
- package/dist/cjs/config.js.map +1 -0
- package/dist/cjs/db.d.cts +20 -0
- package/dist/cjs/db.d.ts +20 -0
- package/dist/cjs/db.js +326 -0
- package/dist/cjs/db.js.map +1 -0
- package/dist/cjs/errors.d.cts +5 -0
- package/dist/cjs/errors.d.ts +5 -0
- package/dist/cjs/errors.js +134 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.d.cts +12 -0
- package/dist/cjs/index.d.ts +12 -0
- package/dist/cjs/index.js +76 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/output.d.cts +2 -0
- package/dist/cjs/output.d.ts +2 -0
- package/dist/cjs/output.js +90 -0
- package/dist/cjs/output.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/scan.d.cts +18 -0
- package/dist/cjs/scan.d.ts +18 -0
- package/dist/cjs/scan.js +113 -0
- package/dist/cjs/scan.js.map +1 -0
- package/dist/cjs/watch.d.cts +19 -0
- package/dist/cjs/watch.d.ts +19 -0
- package/dist/cjs/watch.js +237 -0
- package/dist/cjs/watch.js.map +1 -0
- package/dist/esm/cli.d.ts +1 -0
- package/dist/esm/cli.js +171 -0
- package/dist/esm/cli.js.map +1 -0
- package/dist/esm/config.d.ts +18 -0
- package/dist/esm/config.js +78 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/db.d.ts +20 -0
- package/dist/esm/db.js +176 -0
- package/dist/esm/db.js.map +1 -0
- package/dist/esm/errors.d.ts +5 -0
- package/dist/esm/errors.js +10 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/output.d.ts +2 -0
- package/dist/esm/output.js +25 -0
- package/dist/esm/output.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/scan.d.ts +18 -0
- package/dist/esm/scan.js +69 -0
- package/dist/esm/scan.js.map +1 -0
- package/dist/esm/watch.d.ts +19 -0
- package/dist/esm/watch.js +93 -0
- package/dist/esm/watch.js.map +1 -0
- package/package.json +63 -0
- package/schema.json +38 -0
- package/skills/sense/SKILL.md +95 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kevin Malakoff
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# sensemaking
|
|
2
|
+
|
|
3
|
+
Query a knowledge base you build with an agent: filter notes by frontmatter, then search inside them.
|
|
4
|
+
|
|
5
|
+
## The problem
|
|
6
|
+
|
|
7
|
+
When you work with an AI agent on anything substantial, you end up with a pile of small notes —
|
|
8
|
+
findings, decisions, sources, summaries. The pile is the point: it's how knowledge accumulates
|
|
9
|
+
instead of being re-derived every session.
|
|
10
|
+
|
|
11
|
+
But accumulation only pays off if it's findable. Past a couple dozen notes, an agent can't tell
|
|
12
|
+
which fifteen of two hundred bear on its task, so it greps blindly, swallows the whole folder into
|
|
13
|
+
context, or quietly rebuilds knowledge that already exists three files away.
|
|
14
|
+
|
|
15
|
+
The classification an agent adds while writing — `status`, `type`, `tags`, `source` — is what keeps
|
|
16
|
+
the pile navigable. `sensemaking` is the layer that acts on it, without an app running, a build
|
|
17
|
+
step, or you re-explaining anything.
|
|
18
|
+
|
|
19
|
+
## How it works
|
|
20
|
+
|
|
21
|
+
Every file becomes a row; every frontmatter key becomes a column. You write named SQL queries once
|
|
22
|
+
and run them by name.
|
|
23
|
+
|
|
24
|
+
```markdown
|
|
25
|
+
---
|
|
26
|
+
title: Ship the Q3 report
|
|
27
|
+
status: active
|
|
28
|
+
tags: [urgent, reports]
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
Notes about the report…
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Two properties make it trustworthy:
|
|
35
|
+
|
|
36
|
+
- **Never stale.** Every query re-checks the filesystem first, re-reading only what changed. The
|
|
37
|
+
SQLite cache under `.sense/` is disposable — delete it any time, the next query rebuilds it. An
|
|
38
|
+
agent can trust a result without knowing when anything was last indexed.
|
|
39
|
+
- **Headless.** Files on disk are the only source of truth. Nothing needs to be open — not
|
|
40
|
+
Obsidian, not a server, not a daemon.
|
|
41
|
+
|
|
42
|
+
## Use it
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install -g sensemaking
|
|
46
|
+
cd your-notes && sense init # writes a starter sense.config.json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Edit the queries to match your own frontmatter (the `$schema` line gives your editor autocomplete
|
|
50
|
+
and validation):
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"$schema": "https://unpkg.com/sensemaking/schema.json",
|
|
55
|
+
"version": 1,
|
|
56
|
+
"scan": { "include": ["**/*.md"] },
|
|
57
|
+
"queries": {
|
|
58
|
+
"all": "SELECT path, title FROM docs ORDER BY path",
|
|
59
|
+
"by-tag": "SELECT path, title FROM docs WHERE has(tags, ?) ORDER BY path"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
sense all # run a named query
|
|
66
|
+
sense by-tag urgent # positional args bind to ? placeholders (count-checked)
|
|
67
|
+
sense query "SELECT … FROM docs" # ad-hoc SQL for one-off questions, no config edit
|
|
68
|
+
sense --list # what queries exist
|
|
69
|
+
sense <name> --format json # structured output (the default is a table)
|
|
70
|
+
sense status | rebuild # cache info / delete .sense/ and re-crawl
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Discovery walks up from your cwd git-style, so you can run `sense` from anywhere in the tree
|
|
74
|
+
(`--config <path>` overrides). Exit codes: `0` ok, `1` real error (SQLite's message verbatim),
|
|
75
|
+
`2` usage error.
|
|
76
|
+
|
|
77
|
+
The one custom SQL function is `has(field, value)`: array membership on a JSON-array field (like
|
|
78
|
+
`tags`), substring match on a string, always false on a missing key. Reserved columns: `path`,
|
|
79
|
+
`_mtime`, `_size`.
|
|
80
|
+
|
|
81
|
+
### For AI agents
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install -g sensemaking # the CLI
|
|
85
|
+
npx skills add kmalakoff/sensemaking # the agent skill (add -g for global, -a claude-code to target)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The skill teaches an agent the essentials: discovery, `--list`, `--format json`, `has()`, when to
|
|
89
|
+
use ad-hoc `query` versus saving a named one, and when to `rebuild`.
|
|
90
|
+
|
|
91
|
+
### Optional: a background pre-warmer
|
|
92
|
+
|
|
93
|
+
`sense watch` runs the same reconcile ahead of time whenever the filesystem changes, so queries
|
|
94
|
+
open on an already-warm cache. It's purely an optimization — queries reconcile on open anyway, so
|
|
95
|
+
a missed event can never make a result wrong — and under ~1000 files you likely won't notice a
|
|
96
|
+
difference. It runs in the foreground and never daemonizes; process supervision belongs to the OS.
|
|
97
|
+
launchd and systemd examples: [WATCH.md](WATCH.md).
|
|
98
|
+
|
|
99
|
+
## Why not …
|
|
100
|
+
|
|
101
|
+
- **Obsidian (Bases/Dataview):** filters this well — but only inside the running Electron app,
|
|
102
|
+
through its own view formats. There's no headless mode for queries (only Sync), so scripts and
|
|
103
|
+
agents must keep the app open. `sensemaking` needs no app and speaks plain SQL. Your vault works
|
|
104
|
+
unmodified either way; Obsidian stays a fine viewer for the same files.
|
|
105
|
+
- **RAG / semantic search:** retrieves by similarity and hopes relevance follows. That can't
|
|
106
|
+
express "only active notes from this project" as a hard constraint — a `WHERE` clause can. The
|
|
107
|
+
two compose rather than compete: filter first, rank later.
|
|
108
|
+
- **Index-on-build tools (MarkdownDB and similar):** you run an explicit index step and query the
|
|
109
|
+
snapshot, which is stale the moment a file changes. `sensemaking` reconciles on every query, so
|
|
110
|
+
there's no stale window by construction.
|
|
111
|
+
- **Note CLIs (zk and similar):** good at their own model — tags, links, full text — but they
|
|
112
|
+
can't filter on arbitrary frontmatter fields, which is the whole point here.
|
|
113
|
+
- **grep / one-off scripts:** fine until you want named, reusable, parameterized queries with real
|
|
114
|
+
AND/OR/ORDER BY — at which point you've started writing a worse query engine.
|
|
115
|
+
|
|
116
|
+
`sensemaking` is deliberately thin glue: [gray-matter](https://github.com/jonschlinkert/gray-matter)
|
|
117
|
+
parses, [fast-glob](https://github.com/mrmlnc/fast-glob) walks, and Node's built-in SQLite
|
|
118
|
+
(`node:sqlite`) does all the querying. Two dependencies, no native builds, no background services
|
|
119
|
+
required.
|
|
120
|
+
|
|
121
|
+
## Roadmap
|
|
122
|
+
|
|
123
|
+
Content search is the next stage: BM25 relevance over note bodies, scoped to a frontmatter filter,
|
|
124
|
+
so you can ask "the active within-tech notes, ranked by how well they discuss compensation" in one
|
|
125
|
+
query. The filter shrinks the haystack; the search finds the needle.
|
|
126
|
+
|
|
127
|
+
Beyond that, the corpus model isn't tied to markdown — anything carrying structured metadata
|
|
128
|
+
(document properties, sidecar JSON) can join it without changing the query surface.
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
MIT © Kevin Malakoff
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// 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(-1); });");
|
|
5
|
+
else require('../dist/cjs/cli.js')(process.argv.slice(2), 'sense');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function cli(argv: string[], name: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function cli(argv: string[], name: string): Promise<void>;
|
package/dist/cjs/cli.js
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, // Everything below that can throw (bad JSON, a config `version` newer than
|
|
6
|
+
// this build supports, another watcher's fresh heartbeat, a SQLite error)
|
|
7
|
+
// is caught by the top-level handler below and reported as exit 1 with the
|
|
8
|
+
// error's message verbatim. Usage errors (missing/unknown query name, wrong
|
|
9
|
+
// parameter count) exit(2) directly instead of throwing.
|
|
10
|
+
"default", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function() {
|
|
13
|
+
return cli;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
var _nodeutil = require("node:util");
|
|
17
|
+
var _configts = require("./config.js");
|
|
18
|
+
var _dbts = require("./db.js");
|
|
19
|
+
var _outputts = require("./output.js");
|
|
20
|
+
var _watchts = require("./watch.js");
|
|
21
|
+
function _array_like_to_array(arr, len) {
|
|
22
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
23
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
24
|
+
return arr2;
|
|
25
|
+
}
|
|
26
|
+
function _array_with_holes(arr) {
|
|
27
|
+
if (Array.isArray(arr)) return arr;
|
|
28
|
+
}
|
|
29
|
+
function _array_without_holes(arr) {
|
|
30
|
+
if (Array.isArray(arr)) return _array_like_to_array(arr);
|
|
31
|
+
}
|
|
32
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
33
|
+
try {
|
|
34
|
+
var info = gen[key](arg);
|
|
35
|
+
var value = info.value;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
reject(error);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (info.done) {
|
|
41
|
+
resolve(value);
|
|
42
|
+
} else {
|
|
43
|
+
Promise.resolve(value).then(_next, _throw);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function _async_to_generator(fn) {
|
|
47
|
+
return function() {
|
|
48
|
+
var self = this, args = arguments;
|
|
49
|
+
return new Promise(function(resolve, reject) {
|
|
50
|
+
var gen = fn.apply(self, args);
|
|
51
|
+
function _next(value) {
|
|
52
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
53
|
+
}
|
|
54
|
+
function _throw(err) {
|
|
55
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
56
|
+
}
|
|
57
|
+
_next(undefined);
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function _iterable_to_array(iter) {
|
|
62
|
+
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
63
|
+
}
|
|
64
|
+
function _non_iterable_rest() {
|
|
65
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
66
|
+
}
|
|
67
|
+
function _non_iterable_spread() {
|
|
68
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
69
|
+
}
|
|
70
|
+
function _to_array(arr) {
|
|
71
|
+
return _array_with_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_rest();
|
|
72
|
+
}
|
|
73
|
+
function _to_consumable_array(arr) {
|
|
74
|
+
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
|
|
75
|
+
}
|
|
76
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
77
|
+
if (!o) return;
|
|
78
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
79
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
80
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
81
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
82
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
83
|
+
}
|
|
84
|
+
function _ts_generator(thisArg, body) {
|
|
85
|
+
var f, y, t, _ = {
|
|
86
|
+
label: 0,
|
|
87
|
+
sent: function() {
|
|
88
|
+
if (t[0] & 1) throw t[1];
|
|
89
|
+
return t[1];
|
|
90
|
+
},
|
|
91
|
+
trys: [],
|
|
92
|
+
ops: []
|
|
93
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
|
|
94
|
+
return d(g, "next", {
|
|
95
|
+
value: verb(0)
|
|
96
|
+
}), d(g, "throw", {
|
|
97
|
+
value: verb(1)
|
|
98
|
+
}), d(g, "return", {
|
|
99
|
+
value: verb(2)
|
|
100
|
+
}), typeof Symbol === "function" && d(g, Symbol.iterator, {
|
|
101
|
+
value: function() {
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
}), g;
|
|
105
|
+
function verb(n) {
|
|
106
|
+
return function(v) {
|
|
107
|
+
return step([
|
|
108
|
+
n,
|
|
109
|
+
v
|
|
110
|
+
]);
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function step(op) {
|
|
114
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
115
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
116
|
+
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;
|
|
117
|
+
if (y = 0, t) op = [
|
|
118
|
+
op[0] & 2,
|
|
119
|
+
t.value
|
|
120
|
+
];
|
|
121
|
+
switch(op[0]){
|
|
122
|
+
case 0:
|
|
123
|
+
case 1:
|
|
124
|
+
t = op;
|
|
125
|
+
break;
|
|
126
|
+
case 4:
|
|
127
|
+
_.label++;
|
|
128
|
+
return {
|
|
129
|
+
value: op[1],
|
|
130
|
+
done: false
|
|
131
|
+
};
|
|
132
|
+
case 5:
|
|
133
|
+
_.label++;
|
|
134
|
+
y = op[1];
|
|
135
|
+
op = [
|
|
136
|
+
0
|
|
137
|
+
];
|
|
138
|
+
continue;
|
|
139
|
+
case 7:
|
|
140
|
+
op = _.ops.pop();
|
|
141
|
+
_.trys.pop();
|
|
142
|
+
continue;
|
|
143
|
+
default:
|
|
144
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
145
|
+
_ = 0;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
149
|
+
_.label = op[1];
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
153
|
+
_.label = t[1];
|
|
154
|
+
t = op;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
if (t && _.label < t[2]) {
|
|
158
|
+
_.label = t[2];
|
|
159
|
+
_.ops.push(op);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
if (t[2]) _.ops.pop();
|
|
163
|
+
_.trys.pop();
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
op = body.call(thisArg, _);
|
|
167
|
+
} catch (e) {
|
|
168
|
+
op = [
|
|
169
|
+
6,
|
|
170
|
+
e
|
|
171
|
+
];
|
|
172
|
+
y = 0;
|
|
173
|
+
} finally{
|
|
174
|
+
f = t = 0;
|
|
175
|
+
}
|
|
176
|
+
if (op[0] & 5) throw op[1];
|
|
177
|
+
return {
|
|
178
|
+
value: op[0] ? op[1] : void 0,
|
|
179
|
+
done: true
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function usage(name) {
|
|
184
|
+
return "usage: ".concat(name, " <name> [params...] [--format table|json] [--config path]\n") + " ".concat(name, ' query "<sql>" [params...]\n') + " ".concat(name, " --list\n") + " ".concat(name, " init\n") + " ".concat(name, " watch [--force]\n") + " ".concat(name, " status\n") + " ".concat(name, " rebuild");
|
|
185
|
+
}
|
|
186
|
+
function parseCliArgs(argv, name) {
|
|
187
|
+
try {
|
|
188
|
+
return (0, _nodeutil.parseArgs)({
|
|
189
|
+
args: argv,
|
|
190
|
+
options: {
|
|
191
|
+
format: {
|
|
192
|
+
type: 'string',
|
|
193
|
+
default: 'table'
|
|
194
|
+
},
|
|
195
|
+
config: {
|
|
196
|
+
type: 'string'
|
|
197
|
+
},
|
|
198
|
+
list: {
|
|
199
|
+
type: 'boolean',
|
|
200
|
+
default: false
|
|
201
|
+
},
|
|
202
|
+
force: {
|
|
203
|
+
type: 'boolean',
|
|
204
|
+
default: false
|
|
205
|
+
},
|
|
206
|
+
help: {
|
|
207
|
+
type: 'boolean',
|
|
208
|
+
default: false,
|
|
209
|
+
short: 'h'
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
allowPositionals: true
|
|
213
|
+
});
|
|
214
|
+
} catch (err) {
|
|
215
|
+
console.error(err.message);
|
|
216
|
+
console.error(usage(name));
|
|
217
|
+
process.exit(2);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function printWarnings(warnings) {
|
|
221
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
222
|
+
try {
|
|
223
|
+
for(var _iterator = warnings[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
224
|
+
var w = _step.value;
|
|
225
|
+
console.warn(w);
|
|
226
|
+
}
|
|
227
|
+
} catch (err) {
|
|
228
|
+
_didIteratorError = true;
|
|
229
|
+
_iteratorError = err;
|
|
230
|
+
} finally{
|
|
231
|
+
try {
|
|
232
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
233
|
+
_iterator.return();
|
|
234
|
+
}
|
|
235
|
+
} finally{
|
|
236
|
+
if (_didIteratorError) {
|
|
237
|
+
throw _iteratorError;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// Shared tail of both the named-query and ad-hoc `query` paths. An unbound
|
|
243
|
+
// `?` silently binds NULL and returns misleading empty results — fail
|
|
244
|
+
// loudly instead. (Naive count; queries putting '?' in string literals
|
|
245
|
+
// would miscount, which none of ours do.)
|
|
246
|
+
function runSql(cfg, sql, params, format, label) {
|
|
247
|
+
var _db_prepare;
|
|
248
|
+
var _sql_match;
|
|
249
|
+
var placeholderCount = ((_sql_match = sql.match(/\?/g)) !== null && _sql_match !== void 0 ? _sql_match : []).length;
|
|
250
|
+
if (params.length !== placeholderCount) {
|
|
251
|
+
console.error("".concat(label, " expects ").concat(placeholderCount, " parameter(s), got ").concat(params.length));
|
|
252
|
+
process.exit(2);
|
|
253
|
+
}
|
|
254
|
+
var _open = (0, _dbts.open)(cfg), db = _open.db, warnings = _open.warnings;
|
|
255
|
+
printWarnings(warnings);
|
|
256
|
+
var rows = (_db_prepare = db.prepare(sql)).all.apply(_db_prepare, _to_consumable_array(params));
|
|
257
|
+
(0, _outputts.printRows)(rows, format);
|
|
258
|
+
db.close();
|
|
259
|
+
}
|
|
260
|
+
function logWatchEvent(event) {
|
|
261
|
+
if (event.type === 'started') {
|
|
262
|
+
console.log("sense watch: watching ".concat(event.baseDir));
|
|
263
|
+
console.log("sense watch: db ".concat(event.dbPath));
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (event.type === 'reconciled') {
|
|
267
|
+
printWarnings(event.warnings);
|
|
268
|
+
if (event.parsed > 0) {
|
|
269
|
+
console.log("sense watch: reconciled, ".concat(event.parsed, " file(s) reparsed (").concat(event.total, " total)"));
|
|
270
|
+
}
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
console.error("sense watch: reconcile error: ".concat(event.message));
|
|
274
|
+
}
|
|
275
|
+
function cli(argv, name) {
|
|
276
|
+
return _async_to_generator(function() {
|
|
277
|
+
var _parseCliArgs, values, positionals, resolveConfig, _positionals, first, rest, configPath, cfg, cfg1, _open, db, dbPath, warnings, heartbeat, ageSec, cfg2, result, cfg3, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, queryName, format, _rest, sql, params, _concat, name_, params1, cfg4, sql1, err1;
|
|
278
|
+
return _ts_generator(this, function(_state) {
|
|
279
|
+
switch(_state.label){
|
|
280
|
+
case 0:
|
|
281
|
+
_parseCliArgs = parseCliArgs(argv, name), values = _parseCliArgs.values, positionals = _parseCliArgs.positionals;
|
|
282
|
+
if (values.help) {
|
|
283
|
+
console.log(usage(name));
|
|
284
|
+
process.exit(0);
|
|
285
|
+
}
|
|
286
|
+
// cli.ts's only config knowledge is the --config flag; discovery, parsing,
|
|
287
|
+
// and version-gating all live in config.ts.
|
|
288
|
+
resolveConfig = function resolveConfig() {
|
|
289
|
+
return (0, _configts.loadConfig)(values.config);
|
|
290
|
+
};
|
|
291
|
+
_state.label = 1;
|
|
292
|
+
case 1:
|
|
293
|
+
_state.trys.push([
|
|
294
|
+
1,
|
|
295
|
+
4,
|
|
296
|
+
,
|
|
297
|
+
5
|
|
298
|
+
]);
|
|
299
|
+
_positionals = _to_array(positionals), first = _positionals[0], rest = _positionals.slice(1);
|
|
300
|
+
if (first === 'init') {
|
|
301
|
+
configPath = (0, _configts.initConfig)(process.cwd());
|
|
302
|
+
console.log("created ".concat(configPath));
|
|
303
|
+
console.log('edit the queries to fit your tree, then: sense --list');
|
|
304
|
+
process.exit(0);
|
|
305
|
+
}
|
|
306
|
+
if (!(first === 'watch')) return [
|
|
307
|
+
3,
|
|
308
|
+
3
|
|
309
|
+
];
|
|
310
|
+
cfg = resolveConfig();
|
|
311
|
+
return [
|
|
312
|
+
4,
|
|
313
|
+
(0, _watchts.runWatch)(cfg, {
|
|
314
|
+
force: values.force,
|
|
315
|
+
onEvent: logWatchEvent
|
|
316
|
+
})
|
|
317
|
+
];
|
|
318
|
+
case 2:
|
|
319
|
+
_state.sent();
|
|
320
|
+
process.exit(0);
|
|
321
|
+
_state.label = 3;
|
|
322
|
+
case 3:
|
|
323
|
+
if (first === 'status') {
|
|
324
|
+
cfg1 = resolveConfig();
|
|
325
|
+
_open = (0, _dbts.open)(cfg1), db = _open.db, dbPath = _open.dbPath, warnings = _open.warnings;
|
|
326
|
+
printWarnings(warnings);
|
|
327
|
+
console.log("db: ".concat(dbPath));
|
|
328
|
+
console.log("docs: ".concat((0, _dbts.docCount)(db)));
|
|
329
|
+
heartbeat = (0, _dbts.getMeta)(db, 'watch_heartbeat');
|
|
330
|
+
if (heartbeat) {
|
|
331
|
+
ageSec = Math.round((Date.now() - Date.parse(heartbeat)) / 1000);
|
|
332
|
+
console.log("watcher: last heartbeat ".concat(ageSec, "s ago"));
|
|
333
|
+
} else {
|
|
334
|
+
console.log('watcher: no watcher');
|
|
335
|
+
}
|
|
336
|
+
db.close();
|
|
337
|
+
process.exit(0);
|
|
338
|
+
}
|
|
339
|
+
if (first === 'rebuild') {
|
|
340
|
+
cfg2 = resolveConfig();
|
|
341
|
+
result = (0, _dbts.rebuild)(cfg2);
|
|
342
|
+
printWarnings(result.warnings);
|
|
343
|
+
console.log("rebuilt: ".concat((0, _dbts.docCount)(result.db), " docs"));
|
|
344
|
+
result.db.close();
|
|
345
|
+
process.exit(0);
|
|
346
|
+
}
|
|
347
|
+
if (values.list) {
|
|
348
|
+
cfg3 = resolveConfig();
|
|
349
|
+
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
350
|
+
try {
|
|
351
|
+
for(_iterator = Object.keys(cfg3.queries).sort()[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
352
|
+
queryName = _step.value;
|
|
353
|
+
console.log(queryName);
|
|
354
|
+
}
|
|
355
|
+
} catch (err) {
|
|
356
|
+
_didIteratorError = true;
|
|
357
|
+
_iteratorError = err;
|
|
358
|
+
} finally{
|
|
359
|
+
try {
|
|
360
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
361
|
+
_iterator.return();
|
|
362
|
+
}
|
|
363
|
+
} finally{
|
|
364
|
+
if (_didIteratorError) {
|
|
365
|
+
throw _iteratorError;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
process.exit(0);
|
|
370
|
+
}
|
|
371
|
+
format = values.format === 'json' ? 'json' : 'table';
|
|
372
|
+
// Ad-hoc SQL without touching the config -- for one-off questions;
|
|
373
|
+
// save a query into sense.config.json only when it'll be reused.
|
|
374
|
+
if (first === 'query') {
|
|
375
|
+
_rest = _to_array(rest), sql = _rest[0], params = _rest.slice(1);
|
|
376
|
+
if (!sql) {
|
|
377
|
+
console.error("usage: ".concat(name, ' query "<sql>" [params...]'));
|
|
378
|
+
process.exit(2);
|
|
379
|
+
}
|
|
380
|
+
runSql(resolveConfig(), sql, params, format, 'ad-hoc query');
|
|
381
|
+
return [
|
|
382
|
+
2
|
|
383
|
+
];
|
|
384
|
+
}
|
|
385
|
+
_concat = _to_array([
|
|
386
|
+
first
|
|
387
|
+
].concat(_to_consumable_array(rest))), name_ = _concat[0], params1 = _concat.slice(1);
|
|
388
|
+
if (!name_) {
|
|
389
|
+
console.error(usage(name));
|
|
390
|
+
process.exit(2);
|
|
391
|
+
}
|
|
392
|
+
cfg4 = resolveConfig();
|
|
393
|
+
sql1 = cfg4.queries[name_];
|
|
394
|
+
if (!sql1) {
|
|
395
|
+
console.error('unknown query: "'.concat(name_, '"'));
|
|
396
|
+
console.error("valid queries: ".concat(Object.keys(cfg4.queries).sort().join(', ')));
|
|
397
|
+
process.exit(2);
|
|
398
|
+
}
|
|
399
|
+
runSql(cfg4, sql1, params1, format, 'query "'.concat(name_, '"'));
|
|
400
|
+
return [
|
|
401
|
+
3,
|
|
402
|
+
5
|
|
403
|
+
];
|
|
404
|
+
case 4:
|
|
405
|
+
err1 = _state.sent();
|
|
406
|
+
// SQLite's own error message, a bad config, an unsupported config
|
|
407
|
+
// version, or an already-active watcher — printed verbatim.
|
|
408
|
+
console.error(err1.message);
|
|
409
|
+
process.exit(1);
|
|
410
|
+
return [
|
|
411
|
+
3,
|
|
412
|
+
5
|
|
413
|
+
];
|
|
414
|
+
case 5:
|
|
415
|
+
return [
|
|
416
|
+
2
|
|
417
|
+
];
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
})();
|
|
421
|
+
}
|
|
422
|
+
/* 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.ts"],"sourcesContent":["import { parseArgs } from 'node:util';\nimport type { ResolvedConfig } from './config.ts';\nimport { initConfig, loadConfig } from './config.ts';\nimport { docCount, getMeta, open, rebuild } from './db.ts';\nimport type { Row } from './output.ts';\nimport { printRows } from './output.ts';\nimport type { WatchEvent } from './watch.ts';\nimport { runWatch } from './watch.ts';\n\nfunction usage(name: string): string {\n return `usage: ${name} <name> [params...] [--format table|json] [--config path]\\n` + ` ${name} query \"<sql>\" [params...]\\n` + ` ${name} --list\\n` + ` ${name} init\\n` + ` ${name} watch [--force]\\n` + ` ${name} status\\n` + ` ${name} rebuild`;\n}\n\nfunction parseCliArgs(argv: string[], name: string) {\n try {\n return parseArgs({\n args: argv,\n options: {\n format: { type: 'string', default: 'table' },\n config: { type: 'string' },\n list: { type: 'boolean', default: false },\n force: { type: 'boolean', default: false },\n help: { type: 'boolean', default: false, short: 'h' },\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\nfunction printWarnings(warnings: string[]): void {\n for (const w of warnings) console.warn(w);\n}\n\n// Shared tail of both the named-query and ad-hoc `query` paths. An unbound\n// `?` silently binds NULL and returns misleading empty results — fail\n// loudly instead. (Naive count; queries putting '?' in string literals\n// would miscount, which none of ours do.)\nfunction runSql(cfg: ResolvedConfig, sql: string, params: string[], format: 'table' | 'json', label: 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 const { db, warnings } = open(cfg);\n printWarnings(warnings);\n const rows = db.prepare(sql).all(...params) as Row[];\n printRows(rows, format);\n db.close();\n}\n\nfunction logWatchEvent(event: WatchEvent): void {\n if (event.type === 'started') {\n console.log(`sense watch: watching ${event.baseDir}`);\n console.log(`sense watch: db ${event.dbPath}`);\n return;\n }\n if (event.type === 'reconciled') {\n printWarnings(event.warnings);\n if (event.parsed > 0) {\n console.log(`sense watch: reconciled, ${event.parsed} file(s) reparsed (${event.total} total)`);\n }\n return;\n }\n console.error(`sense watch: reconcile error: ${event.message}`);\n}\n\n// Everything below that can throw (bad JSON, a config `version` newer than\n// this build supports, another watcher's fresh heartbeat, a SQLite error)\n// is caught by the top-level handler below and reported as exit 1 with the\n// error's message verbatim. Usage errors (missing/unknown query name, wrong\n// parameter count) exit(2) directly instead of throwing.\nexport default async function cli(argv: string[], name: string): Promise<void> {\n const { values, positionals } = parseCliArgs(argv, name);\n\n if (values.help) {\n console.log(usage(name));\n process.exit(0);\n }\n\n // cli.ts's only config knowledge is the --config flag; discovery, parsing,\n // and version-gating all live in config.ts.\n const resolveConfig = () => loadConfig(values.config);\n\n try {\n const [first, ...rest] = positionals;\n\n if (first === 'init') {\n const configPath = initConfig(process.cwd());\n console.log(`created ${configPath}`);\n console.log('edit the queries to fit your tree, then: sense --list');\n process.exit(0);\n }\n\n if (first === 'watch') {\n const cfg = resolveConfig();\n await runWatch(cfg, { force: values.force, onEvent: logWatchEvent });\n process.exit(0);\n }\n\n if (first === 'status') {\n const cfg = resolveConfig();\n const { db, dbPath, warnings } = open(cfg);\n printWarnings(warnings);\n console.log(`db: ${dbPath}`);\n console.log(`docs: ${docCount(db)}`);\n const heartbeat = getMeta(db, 'watch_heartbeat');\n if (heartbeat) {\n const ageSec = Math.round((Date.now() - Date.parse(heartbeat)) / 1000);\n console.log(`watcher: last heartbeat ${ageSec}s ago`);\n } else {\n console.log('watcher: no watcher');\n }\n db.close();\n process.exit(0);\n }\n\n if (first === 'rebuild') {\n const cfg = resolveConfig();\n const result = rebuild(cfg);\n printWarnings(result.warnings);\n console.log(`rebuilt: ${docCount(result.db)} docs`);\n result.db.close();\n process.exit(0);\n }\n\n if (values.list) {\n const cfg = resolveConfig();\n for (const queryName of Object.keys(cfg.queries).sort()) console.log(queryName);\n process.exit(0);\n }\n\n const format = values.format === 'json' ? 'json' : 'table';\n\n // Ad-hoc SQL without touching the config -- for one-off questions;\n // save a query into sense.config.json only when it'll be reused.\n if (first === 'query') {\n const [sql, ...params] = rest;\n if (!sql) {\n console.error(`usage: ${name} query \"<sql>\" [params...]`);\n process.exit(2);\n }\n runSql(resolveConfig(), sql, params, format, 'ad-hoc query');\n return;\n }\n\n const [name_, ...params] = [first, ...rest];\n\n if (!name_) {\n console.error(usage(name));\n process.exit(2);\n }\n\n const cfg = resolveConfig();\n\n const sql = cfg.queries[name_];\n if (!sql) {\n console.error(`unknown query: \"${name_}\"`);\n console.error(`valid queries: ${Object.keys(cfg.queries).sort().join(', ')}`);\n process.exit(2);\n }\n\n runSql(cfg, sql, params, format, `query \"${name_}\"`);\n } catch (err) {\n // SQLite's own error message, a bad config, an unsupported config\n // version, or an already-active watcher — printed verbatim.\n console.error((err as Error).message);\n process.exit(1);\n }\n}\n"],"names":["cli","usage","name","parseCliArgs","argv","parseArgs","args","options","format","type","default","config","list","force","help","short","allowPositionals","err","console","error","message","process","exit","printWarnings","warnings","w","warn","runSql","cfg","sql","params","label","db","placeholderCount","match","length","open","rows","prepare","all","printRows","close","logWatchEvent","event","log","baseDir","dbPath","parsed","total","values","positionals","resolveConfig","first","rest","configPath","heartbeat","ageSec","result","queryName","name_","loadConfig","initConfig","cwd","runWatch","onEvent","docCount","getMeta","Math","round","Date","now","parse","rebuild","Object","keys","queries","sort","join"],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const CONFIG_FILENAME = "sense.config.json";
|
|
2
|
+
export declare const STATE_DIR = ".sense";
|
|
3
|
+
export declare const SUPPORTED_CONFIG_VERSION = 1;
|
|
4
|
+
export interface Config {
|
|
5
|
+
$schema?: string;
|
|
6
|
+
version?: number;
|
|
7
|
+
scan: {
|
|
8
|
+
include: string[];
|
|
9
|
+
};
|
|
10
|
+
queries: Record<string, string>;
|
|
11
|
+
}
|
|
12
|
+
export interface ResolvedConfig extends Config {
|
|
13
|
+
baseDir: string;
|
|
14
|
+
configPath: string | null;
|
|
15
|
+
}
|
|
16
|
+
export declare function initConfig(dir: string): string;
|
|
17
|
+
export declare function findConfigPath(startDir: string): string | null;
|
|
18
|
+
export declare function loadConfig(explicitPath?: string): ResolvedConfig;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const CONFIG_FILENAME = "sense.config.json";
|
|
2
|
+
export declare const STATE_DIR = ".sense";
|
|
3
|
+
export declare const SUPPORTED_CONFIG_VERSION = 1;
|
|
4
|
+
export interface Config {
|
|
5
|
+
$schema?: string;
|
|
6
|
+
version?: number;
|
|
7
|
+
scan: {
|
|
8
|
+
include: string[];
|
|
9
|
+
};
|
|
10
|
+
queries: Record<string, string>;
|
|
11
|
+
}
|
|
12
|
+
export interface ResolvedConfig extends Config {
|
|
13
|
+
baseDir: string;
|
|
14
|
+
configPath: string | null;
|
|
15
|
+
}
|
|
16
|
+
export declare function initConfig(dir: string): string;
|
|
17
|
+
export declare function findConfigPath(startDir: string): string | null;
|
|
18
|
+
export declare function loadConfig(explicitPath?: string): ResolvedConfig;
|