sensemaking 0.5.0 → 0.6.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 +13 -6
- package/dist/cjs/cli.js +5 -1
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/commands/find.js +173 -10
- package/dist/cjs/commands/find.js.map +1 -1
- package/dist/cjs/commands/map.js +1 -1
- package/dist/cjs/commands/map.js.map +1 -1
- package/dist/cjs/commands/peek.js +1 -1
- package/dist/cjs/commands/peek.js.map +1 -1
- package/dist/cjs/commands/shared.d.cts +1 -1
- package/dist/cjs/commands/shared.d.ts +1 -1
- package/dist/cjs/commands/shared.js +166 -8
- package/dist/cjs/commands/shared.js.map +1 -1
- package/dist/cjs/commands/status.js +10 -1
- package/dist/cjs/commands/status.js.map +1 -1
- package/dist/cjs/commands/types.d.cts +1 -0
- package/dist/cjs/commands/types.d.ts +1 -0
- package/dist/cjs/config.d.cts +26 -2
- package/dist/cjs/config.d.ts +26 -2
- package/dist/cjs/config.js +138 -10
- package/dist/cjs/config.js.map +1 -1
- package/dist/cjs/db.js +46 -16
- package/dist/cjs/db.js.map +1 -1
- package/dist/cjs/errors.d.cts +1 -1
- package/dist/cjs/errors.d.ts +1 -1
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/features/embed.d.cts +14 -0
- package/dist/cjs/features/embed.d.ts +14 -0
- package/dist/cjs/features/embed.js +840 -0
- package/dist/cjs/features/embed.js.map +1 -0
- package/dist/cjs/features/index.js +3 -1
- package/dist/cjs/features/index.js.map +1 -1
- package/dist/cjs/features/types.d.cts +4 -1
- package/dist/cjs/features/types.d.ts +4 -1
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/output.d.cts +5 -0
- package/dist/cjs/output.d.ts +5 -0
- package/dist/cjs/output.js +14 -1
- package/dist/cjs/output.js.map +1 -1
- package/dist/cjs/scan.js +9 -8
- package/dist/cjs/scan.js.map +1 -1
- package/dist/cjs/verbs.d.cts +8 -2
- package/dist/cjs/verbs.d.ts +8 -2
- package/dist/cjs/verbs.js +263 -80
- package/dist/cjs/verbs.js.map +1 -1
- package/dist/esm/cli.js +5 -1
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/commands/find.js +5 -4
- package/dist/esm/commands/find.js.map +1 -1
- package/dist/esm/commands/map.js +1 -3
- package/dist/esm/commands/map.js.map +1 -1
- package/dist/esm/commands/peek.js +1 -1
- package/dist/esm/commands/peek.js.map +1 -1
- package/dist/esm/commands/shared.d.ts +1 -1
- package/dist/esm/commands/shared.js +2 -2
- package/dist/esm/commands/shared.js.map +1 -1
- package/dist/esm/commands/status.js +8 -1
- package/dist/esm/commands/status.js.map +1 -1
- package/dist/esm/commands/types.d.ts +1 -0
- package/dist/esm/commands/types.js.map +1 -1
- package/dist/esm/config.d.ts +26 -2
- package/dist/esm/config.js +63 -8
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/db.js +19 -10
- package/dist/esm/db.js.map +1 -1
- package/dist/esm/errors.d.ts +1 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/features/embed.d.ts +14 -0
- package/dist/esm/features/embed.js +290 -0
- package/dist/esm/features/embed.js.map +1 -0
- package/dist/esm/features/index.js +3 -1
- package/dist/esm/features/index.js.map +1 -1
- package/dist/esm/features/types.d.ts +4 -1
- package/dist/esm/features/types.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/output.d.ts +5 -0
- package/dist/esm/output.js +11 -1
- package/dist/esm/output.js.map +1 -1
- package/dist/esm/scan.js +9 -8
- package/dist/esm/scan.js.map +1 -1
- package/dist/esm/verbs.d.ts +8 -2
- package/dist/esm/verbs.js +46 -12
- package/dist/esm/verbs.js.map +1 -1
- package/package.json +2 -1
- package/schema.json +16 -0
- package/skills/sense/EXAMPLES.md +16 -0
- package/skills/sense/SKILL.md +37 -18
- package/skills/sense-setup/SKILL.md +73 -0
package/dist/cjs/config.d.cts
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
export declare const CONFIG_FILENAME = "sense.config.json";
|
|
2
2
|
export declare const STATE_DIR = ".sense";
|
|
3
3
|
export declare const SUPPORTED_CONFIG_VERSION = 2;
|
|
4
|
-
|
|
4
|
+
declare const FEATURE_NAMES: readonly ["links", "sections", "rank", "embed"];
|
|
5
5
|
export type FeatureName = (typeof FEATURE_NAMES)[number];
|
|
6
|
+
export interface EmbedConfig {
|
|
7
|
+
model?: string;
|
|
8
|
+
type?: 'static' | 'api';
|
|
9
|
+
url?: string;
|
|
10
|
+
key?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const DEFAULT_EMBED_MODEL = "minishlab/potion-retrieval-32M";
|
|
6
13
|
export interface Config {
|
|
7
14
|
$schema?: string;
|
|
8
15
|
version?: number;
|
|
9
16
|
scan: {
|
|
10
17
|
include: string[];
|
|
11
18
|
};
|
|
12
|
-
features?:
|
|
19
|
+
features?: {
|
|
20
|
+
links?: boolean;
|
|
21
|
+
sections?: boolean;
|
|
22
|
+
rank?: boolean;
|
|
23
|
+
embed?: boolean | EmbedConfig;
|
|
24
|
+
};
|
|
13
25
|
queries: Record<string, string>;
|
|
14
26
|
}
|
|
15
27
|
export interface ResolvedConfig extends Config {
|
|
@@ -19,6 +31,17 @@ export interface ResolvedConfig extends Config {
|
|
|
19
31
|
}
|
|
20
32
|
export declare function featureEnabled(cfg: Config, name: FeatureName): boolean;
|
|
21
33
|
export declare function enabledFeatures(cfg: Config): FeatureName[];
|
|
34
|
+
export declare function featureStates(cfg: Config): {
|
|
35
|
+
on: FeatureName[];
|
|
36
|
+
off: FeatureName[];
|
|
37
|
+
};
|
|
38
|
+
export declare function embedConfig(cfg: Config): {
|
|
39
|
+
model: string;
|
|
40
|
+
type: 'static' | 'api';
|
|
41
|
+
url?: string;
|
|
42
|
+
key?: string;
|
|
43
|
+
} | null;
|
|
44
|
+
export declare function featureSignature(cfg: Config): string;
|
|
22
45
|
export declare function migrateConfig(cfg: Config): {
|
|
23
46
|
cfg: Config;
|
|
24
47
|
from: number;
|
|
@@ -26,3 +49,4 @@ export declare function migrateConfig(cfg: Config): {
|
|
|
26
49
|
export declare function initConfig(dir: string): string;
|
|
27
50
|
export declare function findConfigPath(startDir: string): string | null;
|
|
28
51
|
export declare function loadConfig(explicitPath?: string): ResolvedConfig;
|
|
52
|
+
export {};
|
package/dist/cjs/config.d.ts
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
export declare const CONFIG_FILENAME = "sense.config.json";
|
|
2
2
|
export declare const STATE_DIR = ".sense";
|
|
3
3
|
export declare const SUPPORTED_CONFIG_VERSION = 2;
|
|
4
|
-
|
|
4
|
+
declare const FEATURE_NAMES: readonly ["links", "sections", "rank", "embed"];
|
|
5
5
|
export type FeatureName = (typeof FEATURE_NAMES)[number];
|
|
6
|
+
export interface EmbedConfig {
|
|
7
|
+
model?: string;
|
|
8
|
+
type?: 'static' | 'api';
|
|
9
|
+
url?: string;
|
|
10
|
+
key?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const DEFAULT_EMBED_MODEL = "minishlab/potion-retrieval-32M";
|
|
6
13
|
export interface Config {
|
|
7
14
|
$schema?: string;
|
|
8
15
|
version?: number;
|
|
9
16
|
scan: {
|
|
10
17
|
include: string[];
|
|
11
18
|
};
|
|
12
|
-
features?:
|
|
19
|
+
features?: {
|
|
20
|
+
links?: boolean;
|
|
21
|
+
sections?: boolean;
|
|
22
|
+
rank?: boolean;
|
|
23
|
+
embed?: boolean | EmbedConfig;
|
|
24
|
+
};
|
|
13
25
|
queries: Record<string, string>;
|
|
14
26
|
}
|
|
15
27
|
export interface ResolvedConfig extends Config {
|
|
@@ -19,6 +31,17 @@ export interface ResolvedConfig extends Config {
|
|
|
19
31
|
}
|
|
20
32
|
export declare function featureEnabled(cfg: Config, name: FeatureName): boolean;
|
|
21
33
|
export declare function enabledFeatures(cfg: Config): FeatureName[];
|
|
34
|
+
export declare function featureStates(cfg: Config): {
|
|
35
|
+
on: FeatureName[];
|
|
36
|
+
off: FeatureName[];
|
|
37
|
+
};
|
|
38
|
+
export declare function embedConfig(cfg: Config): {
|
|
39
|
+
model: string;
|
|
40
|
+
type: 'static' | 'api';
|
|
41
|
+
url?: string;
|
|
42
|
+
key?: string;
|
|
43
|
+
} | null;
|
|
44
|
+
export declare function featureSignature(cfg: Config): string;
|
|
22
45
|
export declare function migrateConfig(cfg: Config): {
|
|
23
46
|
cfg: Config;
|
|
24
47
|
from: number;
|
|
@@ -26,3 +49,4 @@ export declare function migrateConfig(cfg: Config): {
|
|
|
26
49
|
export declare function initConfig(dir: string): string;
|
|
27
50
|
export declare function findConfigPath(startDir: string): string | null;
|
|
28
51
|
export declare function loadConfig(explicitPath?: string): ResolvedConfig;
|
|
52
|
+
export {};
|
package/dist/cjs/config.js
CHANGED
|
@@ -12,8 +12,8 @@ _export(exports, {
|
|
|
12
12
|
get CONFIG_FILENAME () {
|
|
13
13
|
return CONFIG_FILENAME;
|
|
14
14
|
},
|
|
15
|
-
get
|
|
16
|
-
return
|
|
15
|
+
get DEFAULT_EMBED_MODEL () {
|
|
16
|
+
return DEFAULT_EMBED_MODEL;
|
|
17
17
|
},
|
|
18
18
|
get STATE_DIR () {
|
|
19
19
|
return STATE_DIR;
|
|
@@ -21,12 +21,21 @@ _export(exports, {
|
|
|
21
21
|
get SUPPORTED_CONFIG_VERSION () {
|
|
22
22
|
return SUPPORTED_CONFIG_VERSION;
|
|
23
23
|
},
|
|
24
|
+
get embedConfig () {
|
|
25
|
+
return embedConfig;
|
|
26
|
+
},
|
|
24
27
|
get enabledFeatures () {
|
|
25
28
|
return enabledFeatures;
|
|
26
29
|
},
|
|
27
30
|
get featureEnabled () {
|
|
28
31
|
return featureEnabled;
|
|
29
32
|
},
|
|
33
|
+
get featureSignature () {
|
|
34
|
+
return featureSignature;
|
|
35
|
+
},
|
|
36
|
+
get featureStates () {
|
|
37
|
+
return featureStates;
|
|
38
|
+
},
|
|
30
39
|
get findConfigPath () {
|
|
31
40
|
return findConfigPath;
|
|
32
41
|
},
|
|
@@ -43,6 +52,14 @@ _export(exports, {
|
|
|
43
52
|
var _nodefs = require("node:fs");
|
|
44
53
|
var _nodepath = require("node:path");
|
|
45
54
|
var _errorsts = require("./errors.js");
|
|
55
|
+
function _array_like_to_array(arr, len) {
|
|
56
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
57
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
58
|
+
return arr2;
|
|
59
|
+
}
|
|
60
|
+
function _array_with_holes(arr) {
|
|
61
|
+
if (Array.isArray(arr)) return arr;
|
|
62
|
+
}
|
|
46
63
|
function _define_property(obj, key, value) {
|
|
47
64
|
if (key in obj) {
|
|
48
65
|
Object.defineProperty(obj, key, {
|
|
@@ -56,6 +73,33 @@ function _define_property(obj, key, value) {
|
|
|
56
73
|
}
|
|
57
74
|
return obj;
|
|
58
75
|
}
|
|
76
|
+
function _iterable_to_array_limit(arr, i) {
|
|
77
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
78
|
+
if (_i == null) return;
|
|
79
|
+
var _arr = [];
|
|
80
|
+
var _n = true;
|
|
81
|
+
var _d = false;
|
|
82
|
+
var _s, _e;
|
|
83
|
+
try {
|
|
84
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
85
|
+
_arr.push(_s.value);
|
|
86
|
+
if (i && _arr.length === i) break;
|
|
87
|
+
}
|
|
88
|
+
} catch (err) {
|
|
89
|
+
_d = true;
|
|
90
|
+
_e = err;
|
|
91
|
+
} finally{
|
|
92
|
+
try {
|
|
93
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
94
|
+
} finally{
|
|
95
|
+
if (_d) throw _e;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return _arr;
|
|
99
|
+
}
|
|
100
|
+
function _non_iterable_rest() {
|
|
101
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
102
|
+
}
|
|
59
103
|
function _object_spread(target) {
|
|
60
104
|
for(var i = 1; i < arguments.length; i++){
|
|
61
105
|
var source = arguments[i] != null ? arguments[i] : {};
|
|
@@ -95,21 +139,42 @@ function _object_spread_props(target, source) {
|
|
|
95
139
|
}
|
|
96
140
|
return target;
|
|
97
141
|
}
|
|
142
|
+
function _sliced_to_array(arr, i) {
|
|
143
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
144
|
+
}
|
|
98
145
|
function _type_of(obj) {
|
|
99
146
|
"@swc/helpers - typeof";
|
|
100
147
|
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
101
148
|
}
|
|
149
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
150
|
+
if (!o) return;
|
|
151
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
152
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
153
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
154
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
155
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
156
|
+
}
|
|
102
157
|
var CONFIG_FILENAME = 'sense.config.json';
|
|
103
158
|
var STATE_DIR = '.sense';
|
|
104
159
|
var SUPPORTED_CONFIG_VERSION = 2;
|
|
160
|
+
// Each feature owns its tables, parse-time extraction, and reconcile step; verbs degrade when one is off.
|
|
161
|
+
// links/sections/rank are opt-out (absent = on); embed is opt-in (absent = off) -- most trees don't need vectors.
|
|
105
162
|
var FEATURE_NAMES = [
|
|
163
|
+
'links',
|
|
164
|
+
'sections',
|
|
165
|
+
'rank',
|
|
166
|
+
'embed'
|
|
167
|
+
];
|
|
168
|
+
var OPT_OUT_NAMES = [
|
|
106
169
|
'links',
|
|
107
170
|
'sections',
|
|
108
171
|
'rank'
|
|
109
172
|
];
|
|
173
|
+
var DEFAULT_EMBED_MODEL = 'minishlab/potion-retrieval-32M';
|
|
110
174
|
function featureEnabled(cfg, name) {
|
|
111
|
-
var _cfg_features;
|
|
112
|
-
|
|
175
|
+
var _cfg_features, _cfg_features1;
|
|
176
|
+
if (name === 'embed') return Boolean((_cfg_features = cfg.features) === null || _cfg_features === void 0 ? void 0 : _cfg_features.embed);
|
|
177
|
+
var enabled = ((_cfg_features1 = cfg.features) === null || _cfg_features1 === void 0 ? void 0 : _cfg_features1[name]) !== false;
|
|
113
178
|
if (name === 'rank') return enabled && featureEnabled(cfg, 'links');
|
|
114
179
|
return enabled;
|
|
115
180
|
}
|
|
@@ -118,13 +183,44 @@ function enabledFeatures(cfg) {
|
|
|
118
183
|
return featureEnabled(cfg, name);
|
|
119
184
|
});
|
|
120
185
|
}
|
|
186
|
+
function featureStates(cfg) {
|
|
187
|
+
return {
|
|
188
|
+
on: FEATURE_NAMES.filter(function(name) {
|
|
189
|
+
return featureEnabled(cfg, name);
|
|
190
|
+
}),
|
|
191
|
+
off: FEATURE_NAMES.filter(function(name) {
|
|
192
|
+
return !featureEnabled(cfg, name);
|
|
193
|
+
})
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function embedConfig(cfg) {
|
|
197
|
+
var _o_model, _o_type;
|
|
198
|
+
var _cfg_features;
|
|
199
|
+
var e = (_cfg_features = cfg.features) === null || _cfg_features === void 0 ? void 0 : _cfg_features.embed;
|
|
200
|
+
if (!e) return null;
|
|
201
|
+
var o = e === true ? {} : e;
|
|
202
|
+
return {
|
|
203
|
+
model: (_o_model = o.model) !== null && _o_model !== void 0 ? _o_model : DEFAULT_EMBED_MODEL,
|
|
204
|
+
type: (_o_type = o.type) !== null && _o_type !== void 0 ? _o_type : 'static',
|
|
205
|
+
url: o.url,
|
|
206
|
+
key: o.key
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function featureSignature(cfg) {
|
|
210
|
+
return enabledFeatures(cfg).map(function(name) {
|
|
211
|
+
if (name !== 'embed') return name;
|
|
212
|
+
var e = embedConfig(cfg);
|
|
213
|
+
return "embed:".concat(e === null || e === void 0 ? void 0 : e.type, ":").concat(e === null || e === void 0 ? void 0 : e.model);
|
|
214
|
+
}).join(',');
|
|
215
|
+
}
|
|
121
216
|
// Pure per-version steps; loadConfig chains them from the file's version up to SUPPORTED_CONFIG_VERSION.
|
|
122
217
|
var MIGRATIONS = {
|
|
123
|
-
// v1 -> v2: features block introduced,
|
|
218
|
+
// v1 -> v2: features block introduced, opt-out features enabled (matches the old implicit
|
|
219
|
+
// behavior of `links` etc. not existing). embed stays absent -- opt-in.
|
|
124
220
|
1: function(cfg) {
|
|
125
221
|
return _object_spread_props(_object_spread({}, cfg), {
|
|
126
222
|
version: 2,
|
|
127
|
-
features: Object.fromEntries(
|
|
223
|
+
features: Object.fromEntries(OPT_OUT_NAMES.map(function(name) {
|
|
128
224
|
return [
|
|
129
225
|
name,
|
|
130
226
|
true
|
|
@@ -156,7 +252,7 @@ function starterConfig() {
|
|
|
156
252
|
'**/*.md'
|
|
157
253
|
]
|
|
158
254
|
},
|
|
159
|
-
features: Object.fromEntries(
|
|
255
|
+
features: Object.fromEntries(OPT_OUT_NAMES.map(function(name) {
|
|
160
256
|
return [
|
|
161
257
|
name,
|
|
162
258
|
true
|
|
@@ -187,6 +283,7 @@ function findConfigPath(startDir) {
|
|
|
187
283
|
// TypeError from whatever code touched the missing field first. `queries` is optional
|
|
188
284
|
// on disk (absent = none); `scan.include` has no usable default.
|
|
189
285
|
function validateConfig(parsed, configPath) {
|
|
286
|
+
var _cfg_features;
|
|
190
287
|
if ((typeof parsed === "undefined" ? "undefined" : _type_of(parsed)) !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
191
288
|
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": config must be a JSON object"));
|
|
192
289
|
}
|
|
@@ -203,11 +300,42 @@ function validateConfig(parsed, configPath) {
|
|
|
203
300
|
})) {
|
|
204
301
|
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": queries must be an object of name -> SQL string"));
|
|
205
302
|
}
|
|
206
|
-
if (cfg.features !== undefined && (_type_of(cfg.features) !== 'object' || cfg.features === null || Array.isArray(cfg.features)
|
|
207
|
-
return typeof v === 'boolean';
|
|
208
|
-
}))) {
|
|
303
|
+
if (cfg.features !== undefined && (_type_of(cfg.features) !== 'object' || cfg.features === null || Array.isArray(cfg.features))) {
|
|
209
304
|
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": features must be an object of name -> boolean"));
|
|
210
305
|
}
|
|
306
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
307
|
+
try {
|
|
308
|
+
var _loop = function() {
|
|
309
|
+
var _step_value = _sliced_to_array(_step.value, 2), name = _step_value[0], value = _step_value[1];
|
|
310
|
+
if (typeof value === 'boolean') return "continue";
|
|
311
|
+
// embed alone takes an object form: { model?, type?: static|api, url?, key? }.
|
|
312
|
+
var embed = value;
|
|
313
|
+
var shapeOk = name === 'embed' && (typeof value === "undefined" ? "undefined" : _type_of(value)) === 'object' && value !== null && !Array.isArray(value) && [
|
|
314
|
+
'model',
|
|
315
|
+
'url',
|
|
316
|
+
'key'
|
|
317
|
+
].every(function(f) {
|
|
318
|
+
return embed[f] === undefined || typeof embed[f] === 'string';
|
|
319
|
+
}) && (embed.type === undefined || embed.type === 'static' || embed.type === 'api');
|
|
320
|
+
if (!shapeOk) {
|
|
321
|
+
throw new _errorsts.SenseError('CONFIG_INVALID', "".concat(configPath, ": features.").concat(name, " must be a boolean").concat(name === 'embed' ? ' or { model?, type?: "static"|"api", url?, key? }' : ''));
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
for(var _iterator = Object.entries((_cfg_features = cfg.features) !== null && _cfg_features !== void 0 ? _cfg_features : {})[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true)_loop();
|
|
325
|
+
} catch (err) {
|
|
326
|
+
_didIteratorError = true;
|
|
327
|
+
_iteratorError = err;
|
|
328
|
+
} finally{
|
|
329
|
+
try {
|
|
330
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
331
|
+
_iterator.return();
|
|
332
|
+
}
|
|
333
|
+
} finally{
|
|
334
|
+
if (_didIteratorError) {
|
|
335
|
+
throw _iteratorError;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
211
339
|
return cfg;
|
|
212
340
|
}
|
|
213
341
|
function loadConfig(explicitPath) {
|
package/dist/cjs/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/config.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { SenseError } from './errors.ts';\n\nexport const CONFIG_FILENAME = 'sense.config.json';\nexport const STATE_DIR = '.sense';\n\n// Highest sense.config.json `version` this build understands. Older versions auto-migrate on load.\nexport const SUPPORTED_CONFIG_VERSION = 2;\n\n// Each feature owns its tables, parse-time extraction, and reconcile step; verbs degrade when one is off.\nexport const FEATURE_NAMES = ['links', 'sections', 'rank'] as const;\nexport type FeatureName = (typeof FEATURE_NAMES)[number];\n\nexport interface Config {\n // Editor-only pointer to schema.json; never read by sense.\n $schema?: string;\n version?: number;\n scan: { include: string[] };\n features?: Partial<Record<FeatureName, boolean>>;\n queries: Record<string, string>;\n}\n\nexport interface ResolvedConfig extends Config {\n baseDir: string;\n configPath: string | null;\n // Set when loadConfig auto-migrated the file on disk; cli reports it.\n migratedFrom?: number;\n}\n\n// Absent block or key means enabled -- features are opt-out. `rank` additionally requires `links`.\nexport function featureEnabled(cfg: Config, name: FeatureName): boolean {\n const enabled = cfg.features?.[name] !== false;\n if (name === 'rank') return enabled && featureEnabled(cfg, 'links');\n return enabled;\n}\n\nexport function enabledFeatures(cfg: Config): FeatureName[] {\n return FEATURE_NAMES.filter((name) => featureEnabled(cfg, name));\n}\n\n// Pure per-version steps; loadConfig chains them from the file's version up to SUPPORTED_CONFIG_VERSION.\nconst MIGRATIONS: Record<number, (cfg: Config) => Config> = {\n // v1 -> v2: features block introduced, everything enabled (matches the old implicit behavior of `links` etc. not existing).\n 1: (cfg) => ({ ...cfg, version: 2, features: Object.fromEntries(FEATURE_NAMES.map((name) => [name, true])) as Config['features'] }),\n};\n\nexport function migrateConfig(cfg: Config): { cfg: Config; from: number } {\n const from = cfg.version ?? 1;\n let current = cfg;\n for (let v = from; v < SUPPORTED_CONFIG_VERSION; v++) {\n const step = MIGRATIONS[v];\n if (!step) throw new SenseError('CONFIG_VERSION_UNSUPPORTED', `no migration from config version ${v}`);\n current = step(current);\n }\n return { cfg: current, from };\n}\n\nfunction starterConfig(): Config {\n return {\n $schema: 'https://unpkg.com/sensemaking/schema.json',\n version: SUPPORTED_CONFIG_VERSION,\n scan: { include: ['**/*.md'] },\n features: Object.fromEntries(FEATURE_NAMES.map((name) => [name, true])) as Config['features'],\n queries: {},\n };\n}\n\n// Refuses to overwrite an existing config.\nexport function initConfig(dir: string): string {\n const configPath = join(dir, CONFIG_FILENAME);\n if (existsSync(configPath)) {\n throw new SenseError('CONFIG_EXISTS', `${CONFIG_FILENAME} already exists in ${dir}`);\n }\n writeFileSync(configPath, `${JSON.stringify(starterConfig(), null, 2)}\\n`);\n return configPath;\n}\n\nexport function findConfigPath(startDir: string): string | null {\n let dir = resolve(startDir);\n for (;;) {\n const candidate = join(dir, CONFIG_FILENAME);\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n// Shape check for hand-edited files: a typo'd config fails with a named error, not a\n// TypeError from whatever code touched the missing field first. `queries` is optional\n// on disk (absent = none); `scan.include` has no usable default.\nfunction validateConfig(parsed: unknown, configPath: string): Config {\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: config must be a JSON object`);\n }\n const cfg = parsed as Record<string, unknown>;\n const scan = cfg.scan as { include?: unknown } | undefined;\n if (!scan || !Array.isArray(scan.include) || scan.include.length === 0 || !scan.include.every((g) => typeof g === 'string')) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: scan.include must be a non-empty array of glob strings`);\n }\n if (cfg.queries === undefined) cfg.queries = {};\n if (typeof cfg.queries !== 'object' || cfg.queries === null || Array.isArray(cfg.queries) || !Object.values(cfg.queries).every((q) => typeof q === 'string')) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries must be an object of name -> SQL string`);\n }\n if (cfg.features !== undefined && (typeof cfg.features !== 'object' || cfg.features === null || Array.isArray(cfg.features) || !Object.values(cfg.features).every((v) => typeof v === 'boolean'))) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: features must be an object of name -> boolean`);\n }\n return cfg as unknown as Config;\n}\n\nexport function loadConfig(explicitPath?: string): ResolvedConfig {\n let configPath: string;\n if (explicitPath) {\n configPath = resolve(process.cwd(), explicitPath);\n if (!existsSync(configPath)) throw new SenseError('CONFIG_NOT_FOUND', `config not found: ${configPath}`);\n } else {\n const found = findConfigPath(process.cwd());\n if (!found) {\n throw new SenseError('CONFIG_NOT_FOUND', `could not find ${CONFIG_FILENAME} in ${process.cwd()} or any parent directory`);\n }\n configPath = found;\n }\n\n const raw = readFileSync(configPath, 'utf8');\n const parsed: unknown = JSON.parse(raw);\n\n // Version gate before shape validation: a config written by a newer sense should fail\n // with \"requires a newer sense\", not with shape errors its own version may not have.\n const version = typeof parsed === 'object' && parsed !== null && typeof (parsed as { version?: unknown }).version === 'number' ? (parsed as { version: number }).version : 1;\n if (version > SUPPORTED_CONFIG_VERSION) {\n throw new SenseError('CONFIG_VERSION_UNSUPPORTED', `config version ${version} requires a newer sense`);\n }\n\n let cfg = validateConfig(parsed, configPath);\n\n let migratedFrom: number | undefined;\n if (version < SUPPORTED_CONFIG_VERSION) {\n const result = migrateConfig(cfg);\n cfg = result.cfg;\n migratedFrom = result.from;\n writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}\\n`);\n }\n\n return { ...cfg, baseDir: dirname(configPath), configPath, migratedFrom };\n}\n"],"names":["CONFIG_FILENAME","FEATURE_NAMES","STATE_DIR","SUPPORTED_CONFIG_VERSION","enabledFeatures","featureEnabled","findConfigPath","initConfig","loadConfig","migrateConfig","cfg","name","enabled","features","filter","MIGRATIONS","version","Object","fromEntries","map","from","current","v","step","SenseError","starterConfig","$schema","scan","include","queries","dir","configPath","join","existsSync","writeFileSync","JSON","stringify","startDir","resolve","candidate","parent","dirname","validateConfig","parsed","Array","isArray","length","every","g","undefined","values","q","explicitPath","process","cwd","found","raw","readFileSync","parse","migratedFrom","result","baseDir"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/config.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { SenseError } from './errors.ts';\n\nexport const CONFIG_FILENAME = 'sense.config.json';\nexport const STATE_DIR = '.sense';\n\n// Highest sense.config.json `version` this build understands. Older versions auto-migrate on load.\nexport const SUPPORTED_CONFIG_VERSION = 2;\n\n// Each feature owns its tables, parse-time extraction, and reconcile step; verbs degrade when one is off.\n// links/sections/rank are opt-out (absent = on); embed is opt-in (absent = off) -- most trees don't need vectors.\nconst FEATURE_NAMES = ['links', 'sections', 'rank', 'embed'] as const;\nconst OPT_OUT_NAMES = ['links', 'sections', 'rank'] as const;\nexport type FeatureName = (typeof FEATURE_NAMES)[number];\n\n// `true` = all defaults (static type, default model). A local `model` path skips the network.\nexport interface EmbedConfig {\n model?: string;\n type?: 'static' | 'api';\n url?: string; // api type: OpenAI-compatible base URL, e.g. http://localhost:11434/v1\n key?: string; // api type: name of the env var holding the bearer token, if any\n}\n\nexport const DEFAULT_EMBED_MODEL = 'minishlab/potion-retrieval-32M';\n\nexport interface Config {\n // Editor-only pointer to schema.json; never read by sense.\n $schema?: string;\n version?: number;\n scan: { include: string[] };\n features?: { links?: boolean; sections?: boolean; rank?: boolean; embed?: boolean | EmbedConfig };\n queries: Record<string, string>;\n}\n\nexport interface ResolvedConfig extends Config {\n baseDir: string;\n configPath: string | null;\n // Set when loadConfig auto-migrated the file on disk; cli reports it.\n migratedFrom?: number;\n}\n\n// Opt-out features: absent block or key means enabled. `rank` additionally requires `links`.\n// `embed` is the opposite: enabled only when the config says so.\nexport function featureEnabled(cfg: Config, name: FeatureName): boolean {\n if (name === 'embed') return Boolean(cfg.features?.embed);\n const enabled = cfg.features?.[name] !== false;\n if (name === 'rank') return enabled && featureEnabled(cfg, 'links');\n return enabled;\n}\n\nexport function enabledFeatures(cfg: Config): FeatureName[] {\n return FEATURE_NAMES.filter((name) => featureEnabled(cfg, name));\n}\n\n// Every feature with its current state; verbs surface this so \"off\" and \"empty\" stay\n// distinguishable in output.\nexport function featureStates(cfg: Config): { on: FeatureName[]; off: FeatureName[] } {\n return {\n on: FEATURE_NAMES.filter((name) => featureEnabled(cfg, name)),\n off: FEATURE_NAMES.filter((name) => !featureEnabled(cfg, name)),\n };\n}\n\n// Resolved embed settings, or null when the feature is off.\nexport function embedConfig(cfg: Config): { model: string; type: 'static' | 'api'; url?: string; key?: string } | null {\n const e = cfg.features?.embed;\n if (!e) return null;\n const o = e === true ? {} : e;\n return { model: o.model ?? DEFAULT_EMBED_MODEL, type: o.type ?? 'static', url: o.url, key: o.key };\n}\n\n// Cache-key string: embed carries its type + model so a model change rebuilds like a toggle.\nexport function featureSignature(cfg: Config): string {\n return enabledFeatures(cfg)\n .map((name) => {\n if (name !== 'embed') return name;\n const e = embedConfig(cfg);\n return `embed:${e?.type}:${e?.model}`;\n })\n .join(',');\n}\n\n// Pure per-version steps; loadConfig chains them from the file's version up to SUPPORTED_CONFIG_VERSION.\nconst MIGRATIONS: Record<number, (cfg: Config) => Config> = {\n // v1 -> v2: features block introduced, opt-out features enabled (matches the old implicit\n // behavior of `links` etc. not existing). embed stays absent -- opt-in.\n 1: (cfg) => ({ ...cfg, version: 2, features: Object.fromEntries(OPT_OUT_NAMES.map((name) => [name, true])) as Config['features'] }),\n};\n\nexport function migrateConfig(cfg: Config): { cfg: Config; from: number } {\n const from = cfg.version ?? 1;\n let current = cfg;\n for (let v = from; v < SUPPORTED_CONFIG_VERSION; v++) {\n const step = MIGRATIONS[v];\n if (!step) throw new SenseError('CONFIG_VERSION_UNSUPPORTED', `no migration from config version ${v}`);\n current = step(current);\n }\n return { cfg: current, from };\n}\n\nfunction starterConfig(): Config {\n return {\n $schema: 'https://unpkg.com/sensemaking/schema.json',\n version: SUPPORTED_CONFIG_VERSION,\n scan: { include: ['**/*.md'] },\n features: Object.fromEntries(OPT_OUT_NAMES.map((name) => [name, true])) as Config['features'],\n queries: {},\n };\n}\n\n// Refuses to overwrite an existing config.\nexport function initConfig(dir: string): string {\n const configPath = join(dir, CONFIG_FILENAME);\n if (existsSync(configPath)) {\n throw new SenseError('CONFIG_EXISTS', `${CONFIG_FILENAME} already exists in ${dir}`);\n }\n writeFileSync(configPath, `${JSON.stringify(starterConfig(), null, 2)}\\n`);\n return configPath;\n}\n\nexport function findConfigPath(startDir: string): string | null {\n let dir = resolve(startDir);\n for (;;) {\n const candidate = join(dir, CONFIG_FILENAME);\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n// Shape check for hand-edited files: a typo'd config fails with a named error, not a\n// TypeError from whatever code touched the missing field first. `queries` is optional\n// on disk (absent = none); `scan.include` has no usable default.\nfunction validateConfig(parsed: unknown, configPath: string): Config {\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: config must be a JSON object`);\n }\n const cfg = parsed as Record<string, unknown>;\n const scan = cfg.scan as { include?: unknown } | undefined;\n if (!scan || !Array.isArray(scan.include) || scan.include.length === 0 || !scan.include.every((g) => typeof g === 'string')) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: scan.include must be a non-empty array of glob strings`);\n }\n if (cfg.queries === undefined) cfg.queries = {};\n if (typeof cfg.queries !== 'object' || cfg.queries === null || Array.isArray(cfg.queries) || !Object.values(cfg.queries).every((q) => typeof q === 'string')) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries must be an object of name -> SQL string`);\n }\n if (cfg.features !== undefined && (typeof cfg.features !== 'object' || cfg.features === null || Array.isArray(cfg.features))) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: features must be an object of name -> boolean`);\n }\n for (const [name, value] of Object.entries(cfg.features ?? {})) {\n if (typeof value === 'boolean') continue;\n // embed alone takes an object form: { model?, type?: static|api, url?, key? }.\n const embed = value as Record<string, unknown>;\n const shapeOk = name === 'embed' && typeof value === 'object' && value !== null && !Array.isArray(value) && ['model', 'url', 'key'].every((f) => embed[f] === undefined || typeof embed[f] === 'string') && (embed.type === undefined || embed.type === 'static' || embed.type === 'api');\n if (!shapeOk) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: features.${name} must be a boolean${name === 'embed' ? ' or { model?, type?: \"static\"|\"api\", url?, key? }' : ''}`);\n }\n }\n return cfg as unknown as Config;\n}\n\nexport function loadConfig(explicitPath?: string): ResolvedConfig {\n let configPath: string;\n if (explicitPath) {\n configPath = resolve(process.cwd(), explicitPath);\n if (!existsSync(configPath)) throw new SenseError('CONFIG_NOT_FOUND', `config not found: ${configPath}`);\n } else {\n const found = findConfigPath(process.cwd());\n if (!found) {\n throw new SenseError('CONFIG_NOT_FOUND', `could not find ${CONFIG_FILENAME} in ${process.cwd()} or any parent directory`);\n }\n configPath = found;\n }\n\n const raw = readFileSync(configPath, 'utf8');\n const parsed: unknown = JSON.parse(raw);\n\n // Version gate before shape validation: a config written by a newer sense should fail\n // with \"requires a newer sense\", not with shape errors its own version may not have.\n const version = typeof parsed === 'object' && parsed !== null && typeof (parsed as { version?: unknown }).version === 'number' ? (parsed as { version: number }).version : 1;\n if (version > SUPPORTED_CONFIG_VERSION) {\n throw new SenseError('CONFIG_VERSION_UNSUPPORTED', `config version ${version} requires a newer sense`);\n }\n\n let cfg = validateConfig(parsed, configPath);\n\n let migratedFrom: number | undefined;\n if (version < SUPPORTED_CONFIG_VERSION) {\n const result = migrateConfig(cfg);\n cfg = result.cfg;\n migratedFrom = result.from;\n writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}\\n`);\n }\n\n return { ...cfg, baseDir: dirname(configPath), configPath, migratedFrom };\n}\n"],"names":["CONFIG_FILENAME","DEFAULT_EMBED_MODEL","STATE_DIR","SUPPORTED_CONFIG_VERSION","embedConfig","enabledFeatures","featureEnabled","featureSignature","featureStates","findConfigPath","initConfig","loadConfig","migrateConfig","FEATURE_NAMES","OPT_OUT_NAMES","cfg","name","Boolean","features","embed","enabled","filter","on","off","o","e","model","type","url","key","map","join","MIGRATIONS","version","Object","fromEntries","from","current","v","step","SenseError","starterConfig","$schema","scan","include","queries","dir","configPath","existsSync","writeFileSync","JSON","stringify","startDir","resolve","candidate","parent","dirname","validateConfig","parsed","Array","isArray","length","every","g","undefined","values","q","value","shapeOk","f","entries","explicitPath","process","cwd","found","raw","readFileSync","parse","migratedFrom","result","baseDir"],"mappings":"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"}
|
package/dist/cjs/db.js
CHANGED
|
@@ -126,7 +126,7 @@ function ensureSchema(db, cfg) {
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
if (getMeta(db, 'schema_version') === null) setMeta(db, 'schema_version', SCHEMA_VERSION);
|
|
129
|
-
if (getMeta(db, 'features') === null) setMeta(db, 'features', (0, _configts.
|
|
129
|
+
if (getMeta(db, 'features') === null) setMeta(db, 'features', (0, _configts.featureSignature)(cfg));
|
|
130
130
|
}
|
|
131
131
|
function getMeta(db, key) {
|
|
132
132
|
var row = db.prepare('SELECT value FROM meta WHERE key = ?').get(key);
|
|
@@ -301,6 +301,7 @@ function reconcile(db, cfg, baseDir) {
|
|
|
301
301
|
var _loop = function() {
|
|
302
302
|
var doc = _step5.value;
|
|
303
303
|
var _insert;
|
|
304
|
+
var _feature_store;
|
|
304
305
|
var values = allColumns.map(function(col) {
|
|
305
306
|
var _doc_data_col;
|
|
306
307
|
if (col === 'path') return doc.relPath;
|
|
@@ -309,27 +310,52 @@ function reconcile(db, cfg, baseDir) {
|
|
|
309
310
|
return (_doc_data_col = doc.data[col]) !== null && _doc_data_col !== void 0 ? _doc_data_col : null;
|
|
310
311
|
});
|
|
311
312
|
(_insert = insert).run.apply(_insert, _to_consumable_array(values));
|
|
312
|
-
|
|
313
|
+
// Delete-before-insert only for docs that have rows: an FTS5 DELETE by column
|
|
314
|
+
// cannot use an index and scans the whole table, so running it per doc on a
|
|
315
|
+
// cold build (empty table, nothing to delete) made the crawl quadratic --
|
|
316
|
+
// measured 4x time per note-count doubling at 13k/26k notes.
|
|
317
|
+
if (existing.has(doc.relPath)) {
|
|
318
|
+
var _feature_remove;
|
|
319
|
+
delBody.run(doc.relPath);
|
|
320
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
321
|
+
try {
|
|
322
|
+
for(var _iterator = features[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
323
|
+
var feature = _step.value;
|
|
324
|
+
(_feature_remove = feature.remove) === null || _feature_remove === void 0 ? void 0 : _feature_remove.call(feature, db, doc.relPath);
|
|
325
|
+
}
|
|
326
|
+
} catch (err) {
|
|
327
|
+
_didIteratorError = true;
|
|
328
|
+
_iteratorError = err;
|
|
329
|
+
} finally{
|
|
330
|
+
try {
|
|
331
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
332
|
+
_iterator.return();
|
|
333
|
+
}
|
|
334
|
+
} finally{
|
|
335
|
+
if (_didIteratorError) {
|
|
336
|
+
throw _iteratorError;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
313
341
|
insertBody.run(doc.search.title, doc.search.summary, doc.search.text, doc.relPath);
|
|
314
|
-
var
|
|
342
|
+
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
315
343
|
try {
|
|
316
|
-
for(var
|
|
317
|
-
var
|
|
318
|
-
|
|
319
|
-
(_feature_remove = feature.remove) === null || _feature_remove === void 0 ? void 0 : _feature_remove.call(feature, db, doc.relPath);
|
|
320
|
-
(_feature_store = feature.store) === null || _feature_store === void 0 ? void 0 : _feature_store.call(feature, db, doc.relPath, doc.extracted[feature.name]);
|
|
344
|
+
for(var _iterator1 = features[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
345
|
+
var feature1 = _step1.value;
|
|
346
|
+
(_feature_store = feature1.store) === null || _feature_store === void 0 ? void 0 : _feature_store.call(feature1, db, doc.relPath, doc.extracted[feature1.name]);
|
|
321
347
|
}
|
|
322
348
|
} catch (err) {
|
|
323
|
-
|
|
324
|
-
|
|
349
|
+
_didIteratorError1 = true;
|
|
350
|
+
_iteratorError1 = err;
|
|
325
351
|
} finally{
|
|
326
352
|
try {
|
|
327
|
-
if (!
|
|
328
|
-
|
|
353
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
354
|
+
_iterator1.return();
|
|
329
355
|
}
|
|
330
356
|
} finally{
|
|
331
|
-
if (
|
|
332
|
-
throw
|
|
357
|
+
if (_didIteratorError1) {
|
|
358
|
+
throw _iteratorError1;
|
|
333
359
|
}
|
|
334
360
|
}
|
|
335
361
|
}
|
|
@@ -388,14 +414,18 @@ function open(cfg) {
|
|
|
388
414
|
var dbPath = (0, _nodepath.join)(stateDir, DB_FILENAME);
|
|
389
415
|
var db = new _nodesqlite.DatabaseSync(dbPath);
|
|
390
416
|
db.exec('PRAGMA journal_mode = WAL');
|
|
391
|
-
|
|
417
|
+
// Covers a concurrent watcher's bulk reconcile: the write transaction for 500 changed
|
|
418
|
+
// files measures ~5s at 26k notes, so 5s expired exactly at the boundary and queries
|
|
419
|
+
// racing the watcher got SQLITE_BUSY. 30s bounds the wait at ~3x the largest measured
|
|
420
|
+
// reconcile; a query that outwaits it still fails loudly.
|
|
421
|
+
db.exec('PRAGMA busy_timeout = 30000');
|
|
392
422
|
registerFunctions(db);
|
|
393
423
|
db.exec('CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT)');
|
|
394
424
|
// Schema-version or feature-set mismatch: reconcile only reparses changed files, so an
|
|
395
425
|
// old cache can't be patched incrementally -- rebuild instead (cheap: nothing expensive lives here).
|
|
396
426
|
var version = getMeta(db, 'schema_version');
|
|
397
427
|
var features = getMeta(db, 'features');
|
|
398
|
-
var wantFeatures = (0, _configts.
|
|
428
|
+
var wantFeatures = (0, _configts.featureSignature)(cfg);
|
|
399
429
|
if (version !== null && version !== SCHEMA_VERSION || features !== null && features !== wantFeatures) {
|
|
400
430
|
db.close();
|
|
401
431
|
(0, _nodefs.rmSync)(stateDir, {
|
package/dist/cjs/db.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/db.ts"],"sourcesContent":["import { mkdirSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\nimport type { Config, ResolvedConfig } from './config.ts';\nimport { enabledFeatures, STATE_DIR } from './config.ts';\nimport { activeFeatures } from './features/index.ts';\nimport type { ParsedDoc } from './scan.ts';\nimport { listFiles, parseFile } from './scan.ts';\n\n// Rows -> SQLite: core schema, reconcile loop, has(). Parsing lives in scan.ts;\n// everything beyond frontmatter + content lives in src/features/.\n\nexport const DB_FILENAME = 'cache.db';\n// Cache shape version, independent of the config's own `version`.\nexport const SCHEMA_VERSION = '3';\n\nexport interface OpenResult {\n db: DatabaseSync;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n}\n\nfunction quoteIdent(name: string): string {\n return `\"${name.split('\"').join('\"\"')}\"`;\n}\n\n// has(field, value): JSON-array field -> membership, string field -> substring, NULL -> false.\nfunction registerFunctions(db: DatabaseSync): void {\n db.function('has', { deterministic: true, varargs: false }, (field: unknown, value: unknown): number => {\n if (field === null || field === undefined) return 0;\n\n const needle = String(value);\n\n if (typeof field === 'string') {\n if (field.startsWith('[')) {\n try {\n const parsed = JSON.parse(field);\n if (Array.isArray(parsed)) {\n return parsed.some((item) => String(item) === needle) ? 1 : 0;\n }\n } catch {}\n }\n return field.includes(needle) ? 1 : 0;\n }\n\n return String(field).includes(needle) ? 1 : 0;\n });\n}\n\nfunction getColumns(db: DatabaseSync): Set<string> {\n const rows = db.prepare('PRAGMA table_info(frontmatter)').all() as Array<{ name: string }>;\n return new Set(rows.map((r) => r.name));\n}\n\n// Content is a separate table (not a column on frontmatter) so `SELECT * FROM frontmatter`\n// can't dump file text into context. Features add their own tables after the core ones.\nfunction ensureSchema(db: DatabaseSync, cfg: Config): void {\n db.exec(`CREATE TABLE IF NOT EXISTS frontmatter (\"path\" TEXT PRIMARY KEY, \"_mtime\" REAL, \"_size\" INTEGER)`);\n db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS content USING fts5(title, summary, text, path UNINDEXED, tokenize = 'porter unicode61')`);\n for (const feature of activeFeatures(cfg)) feature.schema(db);\n if (getMeta(db, 'schema_version') === null) setMeta(db, 'schema_version', SCHEMA_VERSION);\n if (getMeta(db, 'features') === null) setMeta(db, 'features', enabledFeatures(cfg).join(','));\n}\n\nexport function getMeta(db: DatabaseSync, key: string): string | null {\n const row = db.prepare('SELECT value FROM meta WHERE key = ?').get(key) as { value: string } | undefined;\n return row ? row.value : null;\n}\n\nexport function setMeta(db: DatabaseSync, key: string, value: string | null): void {\n if (value === null) {\n db.prepare('DELETE FROM meta WHERE key = ?').run(key);\n return;\n }\n db.prepare('INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value').run(key, value);\n}\n\nexport function docCount(db: DatabaseSync): number {\n const row = db.prepare('SELECT COUNT(*) AS n FROM frontmatter').get() as { n: number };\n return row.n;\n}\n\nexport function reconcile(db: DatabaseSync, cfg: Config, baseDir: string): { parsed: number; warnings: string[] } {\n const files = listFiles(cfg, baseDir);\n const currentSet = new Set(files.map((f) => f.relPath));\n\n const existingRows = db.prepare(`SELECT \"path\", \"_mtime\", \"_size\" FROM frontmatter`).all() as Array<{\n path: string;\n _mtime: number;\n _size: number;\n }>;\n const existing = new Map(existingRows.map((r) => [r.path, r]));\n const vanished = existingRows.filter((r) => !currentSet.has(r.path)).map((r) => r.path);\n\n const toReparse = files.filter((f) => {\n const row = existing.get(f.relPath);\n return !row || row._mtime !== f.mtimeMs || row._size !== f.size;\n });\n\n if (vanished.length === 0 && toReparse.length === 0) return { parsed: 0, warnings: [] };\n\n const features = activeFeatures(cfg);\n const seenColumns = getColumns(db);\n const newColumns: string[] = [];\n const parsedDocs: ParsedDoc[] = [];\n const warnings: string[] = [];\n\n for (const file of toReparse) {\n const { doc, warnings: fileWarnings } = parseFile(file, features);\n warnings.push(...fileWarnings);\n for (const key of Object.keys(doc.data)) {\n if (!seenColumns.has(key)) {\n seenColumns.add(key);\n newColumns.push(key);\n }\n }\n parsedDocs.push(doc);\n }\n\n const allColumns = [...seenColumns];\n const insertSql = `INSERT OR REPLACE INTO frontmatter (${allColumns.map(quoteIdent).join(', ')}) VALUES (${allColumns.map(() => '?').join(', ')})`;\n\n db.exec('BEGIN');\n try {\n for (const col of newColumns) db.exec(`ALTER TABLE frontmatter ADD COLUMN ${quoteIdent(col)}`);\n // FTS5 has no upsert, so delete-before-insert into `content`.\n const delBody = db.prepare(`DELETE FROM content WHERE \"path\" = ?`);\n if (vanished.length > 0) {\n const del = db.prepare(`DELETE FROM frontmatter WHERE \"path\" = ?`);\n for (const path of vanished) {\n del.run(path);\n delBody.run(path);\n for (const feature of features) feature.remove?.(db, path);\n }\n }\n if (parsedDocs.length > 0) {\n const insert = db.prepare(insertSql);\n const insertBody = db.prepare(`INSERT INTO content (title, summary, text, \"path\") VALUES (?, ?, ?, ?)`);\n for (const doc of parsedDocs) {\n const values = allColumns.map((col) => {\n if (col === 'path') return doc.relPath;\n if (col === '_mtime') return doc.mtimeMs;\n if (col === '_size') return doc.size;\n return doc.data[col] ?? null;\n });\n insert.run(...values);\n delBody.run(doc.relPath);\n insertBody.run(doc.search.title, doc.search.summary, doc.search.text, doc.relPath);\n for (const feature of features) {\n feature.remove?.(db, doc.relPath);\n feature.store?.(db, doc.relPath, doc.extracted[feature.name]);\n }\n }\n }\n for (const feature of features) feature.afterReconcile?.(db, files);\n db.exec('COMMIT');\n } catch (err) {\n db.exec('ROLLBACK');\n throw err;\n }\n\n return { parsed: parsedDocs.length, warnings };\n}\n\nexport function open(cfg: ResolvedConfig): OpenResult {\n const stateDir = join(cfg.baseDir, STATE_DIR);\n mkdirSync(stateDir, { recursive: true });\n const dbPath = join(stateDir, DB_FILENAME);\n\n const db = new DatabaseSync(dbPath);\n db.exec('PRAGMA journal_mode = WAL');\n db.exec('PRAGMA busy_timeout = 5000');\n registerFunctions(db);\n\n db.exec('CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT)');\n\n // Schema-version or feature-set mismatch: reconcile only reparses changed files, so an\n // old cache can't be patched incrementally -- rebuild instead (cheap: nothing expensive lives here).\n const version = getMeta(db, 'schema_version');\n const features = getMeta(db, 'features');\n const wantFeatures = enabledFeatures(cfg).join(',');\n if ((version !== null && version !== SCHEMA_VERSION) || (features !== null && features !== wantFeatures)) {\n db.close();\n rmSync(stateDir, { recursive: true, force: true });\n return open(cfg);\n }\n\n ensureSchema(db, cfg);\n const { parsed, warnings } = reconcile(db, cfg, cfg.baseDir);\n\n return { db, cfg, dbPath, parsed, warnings };\n}\n\n// Manual reset for a doubted cache.\nexport function rebuild(cfg: ResolvedConfig): OpenResult {\n rmSync(join(cfg.baseDir, STATE_DIR), { recursive: true, force: true });\n return open(cfg);\n}\n"],"names":["DB_FILENAME","SCHEMA_VERSION","docCount","getMeta","open","rebuild","reconcile","setMeta","quoteIdent","name","split","join","registerFunctions","db","function","deterministic","varargs","field","value","undefined","needle","String","startsWith","parsed","JSON","parse","Array","isArray","some","item","includes","getColumns","rows","prepare","all","Set","map","r","ensureSchema","cfg","exec","activeFeatures","feature","schema","enabledFeatures","key","row","get","run","n","baseDir","files","listFiles","currentSet","f","relPath","existingRows","existing","Map","path","vanished","filter","has","toReparse","_mtime","mtimeMs","_size","size","length","warnings","features","seenColumns","newColumns","parsedDocs","file","parseFile","doc","fileWarnings","push","Object","keys","data","add","allColumns","insertSql","col","delBody","del","remove","insert","insertBody","values","search","title","summary","text","store","extracted","afterReconcile","err","stateDir","STATE_DIR","mkdirSync","recursive","dbPath","DatabaseSync","version","wantFeatures","close","rmSync","force"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/db.ts"],"sourcesContent":["import { mkdirSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\nimport type { Config, ResolvedConfig } from './config.ts';\nimport { featureSignature, STATE_DIR } from './config.ts';\nimport { activeFeatures } from './features/index.ts';\nimport type { ParsedDoc } from './scan.ts';\nimport { listFiles, parseFile } from './scan.ts';\n\n// Rows -> SQLite: core schema, reconcile loop, has(). Parsing lives in scan.ts;\n// everything beyond frontmatter + content lives in src/features/.\n\nexport const DB_FILENAME = 'cache.db';\n// Cache shape version, independent of the config's own `version`.\nexport const SCHEMA_VERSION = '3';\n\nexport interface OpenResult {\n db: DatabaseSync;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n}\n\nfunction quoteIdent(name: string): string {\n return `\"${name.split('\"').join('\"\"')}\"`;\n}\n\n// has(field, value): JSON-array field -> membership, string field -> substring, NULL -> false.\nfunction registerFunctions(db: DatabaseSync): void {\n db.function('has', { deterministic: true, varargs: false }, (field: unknown, value: unknown): number => {\n if (field === null || field === undefined) return 0;\n\n const needle = String(value);\n\n if (typeof field === 'string') {\n if (field.startsWith('[')) {\n try {\n const parsed = JSON.parse(field);\n if (Array.isArray(parsed)) {\n return parsed.some((item) => String(item) === needle) ? 1 : 0;\n }\n } catch {}\n }\n return field.includes(needle) ? 1 : 0;\n }\n\n return String(field).includes(needle) ? 1 : 0;\n });\n}\n\nfunction getColumns(db: DatabaseSync): Set<string> {\n const rows = db.prepare('PRAGMA table_info(frontmatter)').all() as Array<{ name: string }>;\n return new Set(rows.map((r) => r.name));\n}\n\n// Content is a separate table (not a column on frontmatter) so `SELECT * FROM frontmatter`\n// can't dump file text into context. Features add their own tables after the core ones.\nfunction ensureSchema(db: DatabaseSync, cfg: Config): void {\n db.exec(`CREATE TABLE IF NOT EXISTS frontmatter (\"path\" TEXT PRIMARY KEY, \"_mtime\" REAL, \"_size\" INTEGER)`);\n db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS content USING fts5(title, summary, text, path UNINDEXED, tokenize = 'porter unicode61')`);\n for (const feature of activeFeatures(cfg)) feature.schema(db);\n if (getMeta(db, 'schema_version') === null) setMeta(db, 'schema_version', SCHEMA_VERSION);\n if (getMeta(db, 'features') === null) setMeta(db, 'features', featureSignature(cfg));\n}\n\nexport function getMeta(db: DatabaseSync, key: string): string | null {\n const row = db.prepare('SELECT value FROM meta WHERE key = ?').get(key) as { value: string } | undefined;\n return row ? row.value : null;\n}\n\nexport function setMeta(db: DatabaseSync, key: string, value: string | null): void {\n if (value === null) {\n db.prepare('DELETE FROM meta WHERE key = ?').run(key);\n return;\n }\n db.prepare('INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value').run(key, value);\n}\n\nexport function docCount(db: DatabaseSync): number {\n const row = db.prepare('SELECT COUNT(*) AS n FROM frontmatter').get() as { n: number };\n return row.n;\n}\n\nexport function reconcile(db: DatabaseSync, cfg: Config, baseDir: string): { parsed: number; warnings: string[] } {\n const files = listFiles(cfg, baseDir);\n const currentSet = new Set(files.map((f) => f.relPath));\n\n const existingRows = db.prepare(`SELECT \"path\", \"_mtime\", \"_size\" FROM frontmatter`).all() as Array<{\n path: string;\n _mtime: number;\n _size: number;\n }>;\n const existing = new Map(existingRows.map((r) => [r.path, r]));\n const vanished = existingRows.filter((r) => !currentSet.has(r.path)).map((r) => r.path);\n\n const toReparse = files.filter((f) => {\n const row = existing.get(f.relPath);\n return !row || row._mtime !== f.mtimeMs || row._size !== f.size;\n });\n\n if (vanished.length === 0 && toReparse.length === 0) return { parsed: 0, warnings: [] };\n\n const features = activeFeatures(cfg);\n const seenColumns = getColumns(db);\n const newColumns: string[] = [];\n const parsedDocs: ParsedDoc[] = [];\n const warnings: string[] = [];\n\n for (const file of toReparse) {\n const { doc, warnings: fileWarnings } = parseFile(file, features);\n warnings.push(...fileWarnings);\n for (const key of Object.keys(doc.data)) {\n if (!seenColumns.has(key)) {\n seenColumns.add(key);\n newColumns.push(key);\n }\n }\n parsedDocs.push(doc);\n }\n\n const allColumns = [...seenColumns];\n const insertSql = `INSERT OR REPLACE INTO frontmatter (${allColumns.map(quoteIdent).join(', ')}) VALUES (${allColumns.map(() => '?').join(', ')})`;\n\n db.exec('BEGIN');\n try {\n for (const col of newColumns) db.exec(`ALTER TABLE frontmatter ADD COLUMN ${quoteIdent(col)}`);\n // FTS5 has no upsert, so delete-before-insert into `content`.\n const delBody = db.prepare(`DELETE FROM content WHERE \"path\" = ?`);\n if (vanished.length > 0) {\n const del = db.prepare(`DELETE FROM frontmatter WHERE \"path\" = ?`);\n for (const path of vanished) {\n del.run(path);\n delBody.run(path);\n for (const feature of features) feature.remove?.(db, path);\n }\n }\n if (parsedDocs.length > 0) {\n const insert = db.prepare(insertSql);\n const insertBody = db.prepare(`INSERT INTO content (title, summary, text, \"path\") VALUES (?, ?, ?, ?)`);\n for (const doc of parsedDocs) {\n const values = allColumns.map((col) => {\n if (col === 'path') return doc.relPath;\n if (col === '_mtime') return doc.mtimeMs;\n if (col === '_size') return doc.size;\n return doc.data[col] ?? null;\n });\n insert.run(...values);\n // Delete-before-insert only for docs that have rows: an FTS5 DELETE by column\n // cannot use an index and scans the whole table, so running it per doc on a\n // cold build (empty table, nothing to delete) made the crawl quadratic --\n // measured 4x time per note-count doubling at 13k/26k notes.\n if (existing.has(doc.relPath)) {\n delBody.run(doc.relPath);\n for (const feature of features) feature.remove?.(db, doc.relPath);\n }\n insertBody.run(doc.search.title, doc.search.summary, doc.search.text, doc.relPath);\n for (const feature of features) feature.store?.(db, doc.relPath, doc.extracted[feature.name]);\n }\n }\n for (const feature of features) feature.afterReconcile?.(db, files);\n db.exec('COMMIT');\n } catch (err) {\n db.exec('ROLLBACK');\n throw err;\n }\n\n return { parsed: parsedDocs.length, warnings };\n}\n\nexport function open(cfg: ResolvedConfig): OpenResult {\n const stateDir = join(cfg.baseDir, STATE_DIR);\n mkdirSync(stateDir, { recursive: true });\n const dbPath = join(stateDir, DB_FILENAME);\n\n const db = new DatabaseSync(dbPath);\n db.exec('PRAGMA journal_mode = WAL');\n // Covers a concurrent watcher's bulk reconcile: the write transaction for 500 changed\n // files measures ~5s at 26k notes, so 5s expired exactly at the boundary and queries\n // racing the watcher got SQLITE_BUSY. 30s bounds the wait at ~3x the largest measured\n // reconcile; a query that outwaits it still fails loudly.\n db.exec('PRAGMA busy_timeout = 30000');\n registerFunctions(db);\n\n db.exec('CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT)');\n\n // Schema-version or feature-set mismatch: reconcile only reparses changed files, so an\n // old cache can't be patched incrementally -- rebuild instead (cheap: nothing expensive lives here).\n const version = getMeta(db, 'schema_version');\n const features = getMeta(db, 'features');\n const wantFeatures = featureSignature(cfg);\n if ((version !== null && version !== SCHEMA_VERSION) || (features !== null && features !== wantFeatures)) {\n db.close();\n rmSync(stateDir, { recursive: true, force: true });\n return open(cfg);\n }\n\n ensureSchema(db, cfg);\n const { parsed, warnings } = reconcile(db, cfg, cfg.baseDir);\n\n return { db, cfg, dbPath, parsed, warnings };\n}\n\n// Manual reset for a doubted cache.\nexport function rebuild(cfg: ResolvedConfig): OpenResult {\n rmSync(join(cfg.baseDir, STATE_DIR), { recursive: true, force: true });\n return open(cfg);\n}\n"],"names":["DB_FILENAME","SCHEMA_VERSION","docCount","getMeta","open","rebuild","reconcile","setMeta","quoteIdent","name","split","join","registerFunctions","db","function","deterministic","varargs","field","value","undefined","needle","String","startsWith","parsed","JSON","parse","Array","isArray","some","item","includes","getColumns","rows","prepare","all","Set","map","r","ensureSchema","cfg","exec","activeFeatures","feature","schema","featureSignature","key","row","get","run","n","baseDir","files","listFiles","currentSet","f","relPath","existingRows","existing","Map","path","vanished","filter","has","toReparse","_mtime","mtimeMs","_size","size","length","warnings","features","seenColumns","newColumns","parsedDocs","file","parseFile","doc","fileWarnings","push","Object","keys","data","add","allColumns","insertSql","col","delBody","del","remove","insert","insertBody","values","search","title","summary","text","store","extracted","afterReconcile","err","stateDir","STATE_DIR","mkdirSync","recursive","dbPath","DatabaseSync","version","wantFeatures","close","rmSync","force"],"mappings":";;;;;;;;;;;QAYaA;eAAAA;;QAEAC;eAAAA;;QAiEGC;eAAAA;;QAbAC;eAAAA;;QAwGAC;eAAAA;;QAkCAC;eAAAA;;QAxHAC;eAAAA;;QAbAC;eAAAA;;;sBAvEkB;wBACb;0BACQ;wBAEe;uBACb;sBAEM;;;;;;;;;;;;;;;;;;;;;;;;;;AAK9B,IAAMP,cAAc;AAEpB,IAAMC,iBAAiB;AAU9B,SAASO,WAAWC,IAAY;IAC9B,OAAO,AAAC,IAA8B,OAA3BA,KAAKC,KAAK,CAAC,KAAKC,IAAI,CAAC,OAAM;AACxC;AAEA,+FAA+F;AAC/F,SAASC,kBAAkBC,EAAgB;IACzCA,GAAGC,QAAQ,CAAC,OAAO;QAAEC,eAAe;QAAMC,SAAS;IAAM,GAAG,SAACC,OAAgBC;QAC3E,IAAID,UAAU,QAAQA,UAAUE,WAAW,OAAO;QAElD,IAAMC,SAASC,OAAOH;QAEtB,IAAI,OAAOD,UAAU,UAAU;YAC7B,IAAIA,MAAMK,UAAU,CAAC,MAAM;gBACzB,IAAI;oBACF,IAAMC,SAASC,KAAKC,KAAK,CAACR;oBAC1B,IAAIS,MAAMC,OAAO,CAACJ,SAAS;wBACzB,OAAOA,OAAOK,IAAI,CAAC,SAACC;mCAASR,OAAOQ,UAAUT;6BAAU,IAAI;oBAC9D;gBACF,EAAE,eAAM,CAAC;YACX;YACA,OAAOH,MAAMa,QAAQ,CAACV,UAAU,IAAI;QACtC;QAEA,OAAOC,OAAOJ,OAAOa,QAAQ,CAACV,UAAU,IAAI;IAC9C;AACF;AAEA,SAASW,WAAWlB,EAAgB;IAClC,IAAMmB,OAAOnB,GAAGoB,OAAO,CAAC,kCAAkCC,GAAG;IAC7D,OAAO,IAAIC,IAAIH,KAAKI,GAAG,CAAC,SAACC;eAAMA,EAAE5B,IAAI;;AACvC;AAEA,2FAA2F;AAC3F,wFAAwF;AACxF,SAAS6B,aAAazB,EAAgB,EAAE0B,GAAW;IACjD1B,GAAG2B,IAAI,CAAC;IACR3B,GAAG2B,IAAI,CAAC;QACH,kCAAA,2BAAA;;QAAL,QAAK,YAAiBC,IAAAA,uBAAc,EAACF,yBAAhC,SAAA,6BAAA,QAAA,yBAAA;YAAA,IAAMG,UAAN;YAAsCA,QAAQC,MAAM,CAAC9B;;;QAArD;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IACL,IAAIV,QAAQU,IAAI,sBAAsB,MAAMN,QAAQM,IAAI,kBAAkBZ;IAC1E,IAAIE,QAAQU,IAAI,gBAAgB,MAAMN,QAAQM,IAAI,YAAY+B,IAAAA,0BAAgB,EAACL;AACjF;AAEO,SAASpC,QAAQU,EAAgB,EAAEgC,GAAW;IACnD,IAAMC,MAAMjC,GAAGoB,OAAO,CAAC,wCAAwCc,GAAG,CAACF;IACnE,OAAOC,MAAMA,IAAI5B,KAAK,GAAG;AAC3B;AAEO,SAASX,QAAQM,EAAgB,EAAEgC,GAAW,EAAE3B,KAAoB;IACzE,IAAIA,UAAU,MAAM;QAClBL,GAAGoB,OAAO,CAAC,kCAAkCe,GAAG,CAACH;QACjD;IACF;IACAhC,GAAGoB,OAAO,CAAC,qGAAqGe,GAAG,CAACH,KAAK3B;AAC3H;AAEO,SAAShB,SAASW,EAAgB;IACvC,IAAMiC,MAAMjC,GAAGoB,OAAO,CAAC,yCAAyCc,GAAG;IACnE,OAAOD,IAAIG,CAAC;AACd;AAEO,SAAS3C,UAAUO,EAAgB,EAAE0B,GAAW,EAAEW,OAAe;IACtE,IAAMC,QAAQC,IAAAA,iBAAS,EAACb,KAAKW;IAC7B,IAAMG,aAAa,IAAIlB,IAAIgB,MAAMf,GAAG,CAAC,SAACkB;eAAMA,EAAEC,OAAO;;IAErD,IAAMC,eAAe3C,GAAGoB,OAAO,CAAC,qDAAqDC,GAAG;IAKxF,IAAMuB,WAAW,IAAIC,IAAIF,aAAapB,GAAG,CAAC,SAACC;eAAM;YAACA,EAAEsB,IAAI;YAAEtB;SAAE;;IAC5D,IAAMuB,WAAWJ,aAAaK,MAAM,CAAC,SAACxB;eAAM,CAACgB,WAAWS,GAAG,CAACzB,EAAEsB,IAAI;OAAGvB,GAAG,CAAC,SAACC;eAAMA,EAAEsB,IAAI;;IAEtF,IAAMI,YAAYZ,MAAMU,MAAM,CAAC,SAACP;QAC9B,IAAMR,MAAMW,SAASV,GAAG,CAACO,EAAEC,OAAO;QAClC,OAAO,CAACT,OAAOA,IAAIkB,MAAM,KAAKV,EAAEW,OAAO,IAAInB,IAAIoB,KAAK,KAAKZ,EAAEa,IAAI;IACjE;IAEA,IAAIP,SAASQ,MAAM,KAAK,KAAKL,UAAUK,MAAM,KAAK,GAAG,OAAO;QAAE7C,QAAQ;QAAG8C,UAAU,EAAE;IAAC;IAEtF,IAAMC,WAAW7B,IAAAA,uBAAc,EAACF;IAChC,IAAMgC,cAAcxC,WAAWlB;IAC/B,IAAM2D,aAAuB,EAAE;IAC/B,IAAMC,aAA0B,EAAE;IAClC,IAAMJ,WAAqB,EAAE;QAExB,kCAAA,2BAAA;;QAAL,QAAK,YAAcN,8BAAd,SAAA,6BAAA,QAAA,yBAAA,iCAAyB;YAAzB,IAAMW,OAAN;gBAEHL;YADA,IAAwCM,aAAAA,IAAAA,iBAAS,EAACD,MAAMJ,WAAhDM,MAAgCD,WAAhCC,KAAKP,AAAUQ,eAAiBF,WAA3BN;YACbA,CAAAA,YAAAA,UAASS,IAAI,OAAbT,WAAc,qBAAGQ;gBACZ,mCAAA,4BAAA;;gBAAL,QAAK,aAAaE,OAAOC,IAAI,CAACJ,IAAIK,IAAI,sBAAjC,UAAA,8BAAA,SAAA,0BAAA,kCAAoC;oBAApC,IAAMpC,MAAN;oBACH,IAAI,CAAC0B,YAAYT,GAAG,CAACjB,MAAM;wBACzB0B,YAAYW,GAAG,CAACrC;wBAChB2B,WAAWM,IAAI,CAACjC;oBAClB;gBACF;;gBALK;gBAAA;;;yBAAA,8BAAA;wBAAA;;;wBAAA;8BAAA;;;;YAML4B,WAAWK,IAAI,CAACF;QAClB;;QAVK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAYL,IAAMO,aAAc,qBAAGZ;IACvB,IAAMa,YAAY,AAAC,uCAAwFD,OAAlDA,WAAW/C,GAAG,CAAC5B,YAAYG,IAAI,CAAC,OAAM,cAAiD,OAArCwE,WAAW/C,GAAG,CAAC;eAAM;OAAKzB,IAAI,CAAC,OAAM;IAEhJE,GAAG2B,IAAI,CAAC;IACR,IAAI;YAmC8BE;YAlC3B,mCAAA,4BAAA;;YAAL,QAAK,aAAa8B,+BAAb,UAAA,8BAAA,SAAA,0BAAA;gBAAA,IAAMa,MAAN;gBAAyBxE,GAAG2B,IAAI,CAAC,AAAC,sCAAqD,OAAhBhC,WAAW6E;;;YAAlF;YAAA;;;qBAAA,8BAAA;oBAAA;;;oBAAA;0BAAA;;;;QACL,8DAA8D;QAC9D,IAAMC,UAAUzE,GAAGoB,OAAO,CAAC;QAC3B,IAAI2B,SAASQ,MAAM,GAAG,GAAG;YACvB,IAAMmB,MAAM1E,GAAGoB,OAAO,CAAC;gBAClB,mCAAA,4BAAA;;gBAAL,QAAK,aAAc2B,6BAAd,UAAA,8BAAA,SAAA,0BAAA,kCAAwB;oBAAxB,IAAMD,OAAN;wBAG6BjB;oBAFhC6C,IAAIvC,GAAG,CAACW;oBACR2B,QAAQtC,GAAG,CAACW;wBACP,mCAAA,4BAAA;;wBAAL,QAAK,aAAiBW,6BAAjB,UAAA,8BAAA,SAAA,0BAAA;4BAAA,IAAM5B,UAAN;6BAA2BA,kBAAAA,QAAQ8C,MAAM,cAAd9C,sCAAAA,qBAAAA,SAAiB7B,IAAI8C;;;wBAAhD;wBAAA;;;iCAAA,8BAAA;gCAAA;;;gCAAA;sCAAA;;;;gBACP;;gBAJK;gBAAA;;;yBAAA,8BAAA;wBAAA;;;wBAAA;8BAAA;;;;QAKP;QACA,IAAIc,WAAWL,MAAM,GAAG,GAAG;YACzB,IAAMqB,SAAS5E,GAAGoB,OAAO,CAACmD;YAC1B,IAAMM,aAAa7E,GAAGoB,OAAO,CAAC;gBACzB,mCAAA,4BAAA;;;oBAAA,IAAM2C,MAAN;wBAOHa;wBAUgC/C;oBAhBhC,IAAMiD,SAASR,WAAW/C,GAAG,CAAC,SAACiD;4BAItBT;wBAHP,IAAIS,QAAQ,QAAQ,OAAOT,IAAIrB,OAAO;wBACtC,IAAI8B,QAAQ,UAAU,OAAOT,IAAIX,OAAO;wBACxC,IAAIoB,QAAQ,SAAS,OAAOT,IAAIT,IAAI;wBACpC,QAAOS,gBAAAA,IAAIK,IAAI,CAACI,IAAI,cAAbT,2BAAAA,gBAAiB;oBAC1B;oBACAa,CAAAA,UAAAA,QAAOzC,GAAG,OAAVyC,SAAW,qBAAGE;oBACd,8EAA8E;oBAC9E,4EAA4E;oBAC5E,0EAA0E;oBAC1E,6DAA6D;oBAC7D,IAAIlC,SAASK,GAAG,CAACc,IAAIrB,OAAO,GAAG;4BAEGb;wBADhC4C,QAAQtC,GAAG,CAAC4B,IAAIrB,OAAO;4BAClB,kCAAA,2BAAA;;4BAAL,QAAK,YAAiBe,6BAAjB,SAAA,6BAAA,QAAA,yBAAA;gCAAA,IAAM5B,UAAN;iCAA2BA,kBAAAA,QAAQ8C,MAAM,cAAd9C,sCAAAA,qBAAAA,SAAiB7B,IAAI+D,IAAIrB,OAAO;;;4BAA3D;4BAAA;;;qCAAA,6BAAA;oCAAA;;;oCAAA;0CAAA;;;;oBACP;oBACAmC,WAAW1C,GAAG,CAAC4B,IAAIgB,MAAM,CAACC,KAAK,EAAEjB,IAAIgB,MAAM,CAACE,OAAO,EAAElB,IAAIgB,MAAM,CAACG,IAAI,EAAEnB,IAAIrB,OAAO;wBAC5E,mCAAA,4BAAA;;wBAAL,QAAK,aAAiBe,6BAAjB,UAAA,8BAAA,SAAA,0BAAA;4BAAA,IAAM5B,WAAN;6BAA2BA,iBAAAA,SAAQsD,KAAK,cAAbtD,qCAAAA,oBAAAA,UAAgB7B,IAAI+D,IAAIrB,OAAO,EAAEqB,IAAIqB,SAAS,CAACvD,SAAQjC,IAAI,CAAC;;;wBAAvF;wBAAA;;;iCAAA,8BAAA;gCAAA;;;gCAAA;sCAAA;;;;gBACP;gBAlBA,QAAK,aAAagE,+BAAb,UAAA,8BAAA,SAAA,0BAAA;;gBAAA;gBAAA;;;yBAAA,8BAAA;wBAAA;;;wBAAA;8BAAA;;;;QAmBP;YACK,mCAAA,4BAAA;;YAAL,QAAK,aAAiBH,6BAAjB,UAAA,8BAAA,SAAA,0BAAA;gBAAA,IAAM5B,WAAN;iBAA2BA,0BAAAA,SAAQwD,cAAc,cAAtBxD,8CAAAA,6BAAAA,UAAyB7B,IAAIsC;;;YAAxD;YAAA;;;qBAAA,8BAAA;oBAAA;;;oBAAA;0BAAA;;;;QACLtC,GAAG2B,IAAI,CAAC;IACV,EAAE,OAAO2D,KAAK;QACZtF,GAAG2B,IAAI,CAAC;QACR,MAAM2D;IACR;IAEA,OAAO;QAAE5E,QAAQkD,WAAWL,MAAM;QAAEC,UAAAA;IAAS;AAC/C;AAEO,SAASjE,KAAKmC,GAAmB;IACtC,IAAM6D,WAAWzF,IAAAA,cAAI,EAAC4B,IAAIW,OAAO,EAAEmD,mBAAS;IAC5CC,IAAAA,iBAAS,EAACF,UAAU;QAAEG,WAAW;IAAK;IACtC,IAAMC,SAAS7F,IAAAA,cAAI,EAACyF,UAAUpG;IAE9B,IAAMa,KAAK,IAAI4F,wBAAY,CAACD;IAC5B3F,GAAG2B,IAAI,CAAC;IACR,sFAAsF;IACtF,qFAAqF;IACrF,sFAAsF;IACtF,0DAA0D;IAC1D3B,GAAG2B,IAAI,CAAC;IACR5B,kBAAkBC;IAElBA,GAAG2B,IAAI,CAAC;IAER,uFAAuF;IACvF,qGAAqG;IACrG,IAAMkE,UAAUvG,QAAQU,IAAI;IAC5B,IAAMyD,WAAWnE,QAAQU,IAAI;IAC7B,IAAM8F,eAAe/D,IAAAA,0BAAgB,EAACL;IACtC,IAAI,AAACmE,YAAY,QAAQA,YAAYzG,kBAAoBqE,aAAa,QAAQA,aAAaqC,cAAe;QACxG9F,GAAG+F,KAAK;QACRC,IAAAA,cAAM,EAACT,UAAU;YAAEG,WAAW;YAAMO,OAAO;QAAK;QAChD,OAAO1G,KAAKmC;IACd;IAEAD,aAAazB,IAAI0B;IACjB,IAA6BjC,aAAAA,UAAUO,IAAI0B,KAAKA,IAAIW,OAAO,GAAnD3B,SAAqBjB,WAArBiB,QAAQ8C,WAAa/D,WAAb+D;IAEhB,OAAO;QAAExD,IAAAA;QAAI0B,KAAAA;QAAKiE,QAAAA;QAAQjF,QAAAA;QAAQ8C,UAAAA;IAAS;AAC7C;AAGO,SAAShE,QAAQkC,GAAmB;IACzCsE,IAAAA,cAAM,EAAClG,IAAAA,cAAI,EAAC4B,IAAIW,OAAO,EAAEmD,mBAAS,GAAG;QAAEE,WAAW;QAAMO,OAAO;IAAK;IACpE,OAAO1G,KAAKmC;AACd"}
|
package/dist/cjs/errors.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type SenseErrorCode = 'CONFIG_NOT_FOUND' | 'CONFIG_EXISTS' | 'CONFIG_INVALID' | 'CONFIG_VERSION_UNSUPPORTED' | 'WATCH_ACTIVE' | 'NOTE_NOT_FOUND' | 'NOTE_AMBIGUOUS';
|
|
1
|
+
export type SenseErrorCode = 'CONFIG_NOT_FOUND' | 'CONFIG_EXISTS' | 'CONFIG_INVALID' | 'CONFIG_VERSION_UNSUPPORTED' | 'WATCH_ACTIVE' | 'NOTE_NOT_FOUND' | 'NOTE_AMBIGUOUS' | 'EMBED_DISABLED' | 'EMBED_MODEL';
|
|
2
2
|
export declare class SenseError extends Error {
|
|
3
3
|
code: SenseErrorCode;
|
|
4
4
|
constructor(code: SenseErrorCode, message: string);
|
package/dist/cjs/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type SenseErrorCode = 'CONFIG_NOT_FOUND' | 'CONFIG_EXISTS' | 'CONFIG_INVALID' | 'CONFIG_VERSION_UNSUPPORTED' | 'WATCH_ACTIVE' | 'NOTE_NOT_FOUND' | 'NOTE_AMBIGUOUS';
|
|
1
|
+
export type SenseErrorCode = 'CONFIG_NOT_FOUND' | 'CONFIG_EXISTS' | 'CONFIG_INVALID' | 'CONFIG_VERSION_UNSUPPORTED' | 'WATCH_ACTIVE' | 'NOTE_NOT_FOUND' | 'NOTE_AMBIGUOUS' | 'EMBED_DISABLED' | 'EMBED_MODEL';
|
|
2
2
|
export declare class SenseError extends Error {
|
|
3
3
|
code: SenseErrorCode;
|
|
4
4
|
constructor(code: SenseErrorCode, message: string);
|
package/dist/cjs/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/errors.ts"],"sourcesContent":["// Library code throws; only cli.ts prints and exits.\nexport type SenseErrorCode = 'CONFIG_NOT_FOUND' | 'CONFIG_EXISTS' | 'CONFIG_INVALID' | 'CONFIG_VERSION_UNSUPPORTED' | 'WATCH_ACTIVE' | 'NOTE_NOT_FOUND' | 'NOTE_AMBIGUOUS';\n\nexport class SenseError extends Error {\n code: SenseErrorCode;\n\n constructor(code: SenseErrorCode, message: string) {\n super(message);\n this.name = 'SenseError';\n this.code = code;\n }\n}\n"],"names":["SenseError","code","message","name","Error"],"mappings":"AAAA,qDAAqD;;;;;+BAGxCA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAN,IAAA,AAAMA,2BAAN;;cAAMA;aAAAA,WAGCC,IAAoB,EAAEC,OAAe;gCAHtCF;;gBAIT,kBAJSA;YAIHE;;QACN,MAAKC,IAAI,GAAG;QACZ,MAAKF,IAAI,GAAGA;;;WANHD;qBAAmBI"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/errors.ts"],"sourcesContent":["// Library code throws; only cli.ts prints and exits.\nexport type SenseErrorCode = 'CONFIG_NOT_FOUND' | 'CONFIG_EXISTS' | 'CONFIG_INVALID' | 'CONFIG_VERSION_UNSUPPORTED' | 'WATCH_ACTIVE' | 'NOTE_NOT_FOUND' | 'NOTE_AMBIGUOUS' | 'EMBED_DISABLED' | 'EMBED_MODEL';\n\nexport class SenseError extends Error {\n code: SenseErrorCode;\n\n constructor(code: SenseErrorCode, message: string) {\n super(message);\n this.name = 'SenseError';\n this.code = code;\n }\n}\n"],"names":["SenseError","code","message","name","Error"],"mappings":"AAAA,qDAAqD;;;;;+BAGxCA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAN,IAAA,AAAMA,2BAAN;;cAAMA;aAAAA,WAGCC,IAAoB,EAAEC,OAAe;gCAHtCF;;gBAIT,kBAJSA;YAIHE;;QACN,MAAKC,IAAI,GAAG;QACZ,MAAKF,IAAI,GAAGA;;;WANHD;qBAAmBI"}
|