sensemaking 0.26.0 → 0.27.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 +36 -4
- package/dist/cjs/cli/index.d.cts +2 -2
- package/dist/cjs/cli/index.d.ts +2 -2
- package/dist/cjs/cli/index.js +2 -2
- package/dist/cjs/cli/index.js.map +1 -1
- package/dist/cjs/cli/peek.js +43 -2
- package/dist/cjs/cli/peek.js.map +1 -1
- package/dist/cjs/cli/search.js +38 -6
- package/dist/cjs/cli/search.js.map +1 -1
- package/dist/cjs/commands/index.d.cts +2 -2
- package/dist/cjs/commands/index.d.ts +2 -2
- package/dist/cjs/commands/index.js.map +1 -1
- package/dist/cjs/commands/peek.d.cts +9 -1
- package/dist/cjs/commands/peek.d.ts +9 -1
- package/dist/cjs/commands/peek.js +72 -29
- package/dist/cjs/commands/peek.js.map +1 -1
- package/dist/cjs/commands/search.d.cts +6 -2
- package/dist/cjs/commands/search.d.ts +6 -2
- package/dist/cjs/commands/search.js +31 -4
- package/dist/cjs/commands/search.js.map +1 -1
- package/dist/cjs/commands/signals.d.cts +19 -5
- package/dist/cjs/commands/signals.d.ts +19 -5
- package/dist/cjs/commands/signals.js +64 -11
- package/dist/cjs/commands/signals.js.map +1 -1
- package/dist/cjs/config/load.js +6 -0
- package/dist/cjs/config/load.js.map +1 -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/esm/cli/index.d.ts +2 -2
- package/dist/esm/cli/index.js +2 -2
- package/dist/esm/cli/index.js.map +1 -1
- package/dist/esm/cli/peek.js +20 -2
- package/dist/esm/cli/peek.js.map +1 -1
- package/dist/esm/cli/search.js +12 -2
- package/dist/esm/cli/search.js.map +1 -1
- package/dist/esm/commands/index.d.ts +2 -2
- package/dist/esm/commands/index.js.map +1 -1
- package/dist/esm/commands/peek.d.ts +9 -1
- package/dist/esm/commands/peek.js +26 -12
- package/dist/esm/commands/peek.js.map +1 -1
- package/dist/esm/commands/search.d.ts +6 -2
- package/dist/esm/commands/search.js +11 -3
- package/dist/esm/commands/search.js.map +1 -1
- package/dist/esm/commands/signals.d.ts +19 -5
- package/dist/esm/commands/signals.js +64 -14
- package/dist/esm/commands/signals.js.map +1 -1
- package/dist/esm/config/load.js +6 -0
- package/dist/esm/config/load.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/sense/EXAMPLES.md +3 -3
- package/skills/sense/SKILL.md +7 -1
- package/skills/sense/references/search.md +17 -1
- package/skills/sense/references/sql.md +1 -1
- package/skills/sense/references/terminology.md +32 -0
- package/skills/sense-setup/references/store-benchmarks.md +5 -5
|
@@ -232,7 +232,7 @@ function resolveNote(paths, arg) {
|
|
|
232
232
|
if (matches.length > 1) throw new _errorsts.SenseError('NOTE_AMBIGUOUS', '"'.concat(arg, '" is ambiguous: ').concat(matches.join(', ')));
|
|
233
233
|
throw new _errorsts.SenseError('NOTE_NOT_FOUND', 'no note matches "'.concat(arg, '"'));
|
|
234
234
|
}
|
|
235
|
-
var
|
|
235
|
+
var PEEK_COUNT_LIMIT = 20;
|
|
236
236
|
function peek(store, cfg, pathArg) {
|
|
237
237
|
var overrides = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : {};
|
|
238
238
|
return (0, _serialqueryts.serialQuery)(store, function() {
|
|
@@ -241,12 +241,25 @@ function peek(store, cfg, pathArg) {
|
|
|
241
241
|
}
|
|
242
242
|
function peekIndexed(store, cfg, pathArg, overrides) {
|
|
243
243
|
return _async_to_generator(function() {
|
|
244
|
+
var _overrides_sectionCountLimit, _overrides_linkCountLimit, _i, _iter, name, value, sectionCountLimit, linkCountLimit;
|
|
244
245
|
return _ts_generator(this, function(_state) {
|
|
246
|
+
for(_i = 0, _iter = [
|
|
247
|
+
'sectionCountLimit',
|
|
248
|
+
'linkCountLimit'
|
|
249
|
+
]; _i < _iter.length; _i++){
|
|
250
|
+
name = _iter[_i];
|
|
251
|
+
value = overrides[name];
|
|
252
|
+
if (value !== undefined && (!Number.isSafeInteger(value) || value <= 0)) {
|
|
253
|
+
throw new _errorsts.SenseError('SEARCH_OPTION_INVALID', 'peek option "'.concat(name, '" must be a positive safe integer, got ').concat(String(value)));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
sectionCountLimit = (_overrides_sectionCountLimit = overrides.sectionCountLimit) !== null && _overrides_sectionCountLimit !== void 0 ? _overrides_sectionCountLimit : PEEK_COUNT_LIMIT;
|
|
257
|
+
linkCountLimit = (_overrides_linkCountLimit = overrides.linkCountLimit) !== null && _overrides_linkCountLimit !== void 0 ? _overrides_linkCountLimit : PEEK_COUNT_LIMIT;
|
|
245
258
|
return [
|
|
246
259
|
2,
|
|
247
260
|
store.transaction(function() {
|
|
248
261
|
return _async_to_generator(function() {
|
|
249
|
-
var _row__parse_error, _row__size, _this, pathsStmt, paths, allowed, path, excludedPath, rowStmt, row, parseError, frontmatter, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, key, value, sectionsTotal, sections, outbound, backlinks, unresolved, backlinksTotal,
|
|
262
|
+
var _row__parse_error, _row__size, _this, pathsStmt, paths, allowed, path, excludedPath, rowStmt, row, parseError, frontmatter, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, key, value, sectionsTotal, sections, outbound, backlinks, unresolved, outboundTotal, backlinksTotal, unresolvedTotal, body, byteTokens, tokens;
|
|
250
263
|
return _ts_generator(this, function(_state) {
|
|
251
264
|
switch(_state.label){
|
|
252
265
|
case 0:
|
|
@@ -354,7 +367,7 @@ function peekIndexed(store, cfg, pathArg, overrides) {
|
|
|
354
367
|
case 9:
|
|
355
368
|
return [
|
|
356
369
|
4,
|
|
357
|
-
_state.sent().all(path,
|
|
370
|
+
_state.sent().all(path, sectionCountLimit)
|
|
358
371
|
];
|
|
359
372
|
case 10:
|
|
360
373
|
sections = _state.sent();
|
|
@@ -363,10 +376,12 @@ function peekIndexed(store, cfg, pathArg, overrides) {
|
|
|
363
376
|
outbound = [];
|
|
364
377
|
backlinks = [];
|
|
365
378
|
unresolved = [];
|
|
379
|
+
outboundTotal = 0;
|
|
366
380
|
backlinksTotal = 0;
|
|
381
|
+
unresolvedTotal = 0;
|
|
367
382
|
if (!(0, _indexts1.featureEnabled)(cfg, 'links')) return [
|
|
368
383
|
3,
|
|
369
|
-
|
|
384
|
+
25
|
|
370
385
|
];
|
|
371
386
|
return [
|
|
372
387
|
4,
|
|
@@ -376,61 +391,89 @@ function peekIndexed(store, cfg, pathArg, overrides) {
|
|
|
376
391
|
_state.sent();
|
|
377
392
|
return [
|
|
378
393
|
4,
|
|
379
|
-
store.prepare('SELECT
|
|
394
|
+
store.prepare('SELECT COUNT(DISTINCT dst) AS n FROM links WHERE src = ? AND dst != src AND dst IN (SELECT "path" FROM _peek_scope)')
|
|
380
395
|
];
|
|
381
396
|
case 13:
|
|
382
397
|
return [
|
|
383
398
|
4,
|
|
384
|
-
_state.sent().
|
|
399
|
+
_state.sent().get(path)
|
|
385
400
|
];
|
|
386
401
|
case 14:
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
402
|
+
outboundTotal = _state.sent().n;
|
|
403
|
+
return [
|
|
404
|
+
4,
|
|
405
|
+
store.prepare('SELECT dst FROM links WHERE src = ? AND dst != src AND dst IN (SELECT "path" FROM _peek_scope) GROUP BY dst ORDER BY MIN(target) LIMIT ?')
|
|
406
|
+
];
|
|
407
|
+
case 15:
|
|
408
|
+
return [
|
|
409
|
+
4,
|
|
410
|
+
_state.sent().all(path, linkCountLimit)
|
|
411
|
+
];
|
|
412
|
+
case 16:
|
|
413
|
+
// The first written target determines each resolved destination's position.
|
|
414
|
+
outbound = _state.sent().map(function(r) {
|
|
415
|
+
return r.dst;
|
|
416
|
+
});
|
|
417
|
+
return [
|
|
418
|
+
4,
|
|
419
|
+
store.prepare('SELECT COUNT(*) AS n FROM links WHERE src = ? AND dst IS NULL')
|
|
420
|
+
];
|
|
421
|
+
case 17:
|
|
422
|
+
return [
|
|
423
|
+
4,
|
|
424
|
+
_state.sent().get(path)
|
|
425
|
+
];
|
|
426
|
+
case 18:
|
|
427
|
+
unresolvedTotal = _state.sent().n;
|
|
428
|
+
return [
|
|
429
|
+
4,
|
|
430
|
+
store.prepare('SELECT target FROM links WHERE src = ? AND dst IS NULL ORDER BY target LIMIT ?')
|
|
431
|
+
];
|
|
432
|
+
case 19:
|
|
433
|
+
return [
|
|
434
|
+
4,
|
|
435
|
+
_state.sent().all(path, linkCountLimit)
|
|
436
|
+
];
|
|
437
|
+
case 20:
|
|
438
|
+
unresolved = _state.sent().map(function(r) {
|
|
439
|
+
return r.target;
|
|
397
440
|
});
|
|
398
441
|
return [
|
|
399
442
|
4,
|
|
400
443
|
store.prepare('SELECT COUNT(DISTINCT src) AS n FROM links WHERE dst = ? AND src != dst AND src IN (SELECT "path" FROM _peek_scope)')
|
|
401
444
|
];
|
|
402
|
-
case
|
|
445
|
+
case 21:
|
|
403
446
|
return [
|
|
404
447
|
4,
|
|
405
448
|
_state.sent().get(path)
|
|
406
449
|
];
|
|
407
|
-
case
|
|
450
|
+
case 22:
|
|
408
451
|
backlinksTotal = _state.sent().n;
|
|
409
452
|
return [
|
|
410
453
|
4,
|
|
411
454
|
store.prepare('SELECT DISTINCT src FROM links WHERE dst = ? AND src != dst AND src IN (SELECT "path" FROM _peek_scope) ORDER BY src LIMIT ?')
|
|
412
455
|
];
|
|
413
|
-
case
|
|
456
|
+
case 23:
|
|
414
457
|
return [
|
|
415
458
|
4,
|
|
416
|
-
_state.sent().all(path,
|
|
459
|
+
_state.sent().all(path, linkCountLimit)
|
|
417
460
|
];
|
|
418
|
-
case
|
|
461
|
+
case 24:
|
|
419
462
|
backlinks = _state.sent().map(function(r) {
|
|
420
463
|
return r.src;
|
|
421
464
|
});
|
|
422
|
-
_state.label =
|
|
423
|
-
case
|
|
465
|
+
_state.label = 25;
|
|
466
|
+
case 25:
|
|
424
467
|
return [
|
|
425
468
|
4,
|
|
426
469
|
store.prepare('SELECT text FROM content WHERE "path" = ?')
|
|
427
470
|
];
|
|
428
|
-
case
|
|
471
|
+
case 26:
|
|
429
472
|
return [
|
|
430
473
|
4,
|
|
431
474
|
_state.sent().get(path)
|
|
432
475
|
];
|
|
433
|
-
case
|
|
476
|
+
case 27:
|
|
434
477
|
body = (_this = _state.sent()) === null || _this === void 0 ? void 0 : _this.text;
|
|
435
478
|
byteTokens = Math.ceil(((_row__size = row._size) !== null && _row__size !== void 0 ? _row__size : 0) / 4);
|
|
436
479
|
tokens = body !== undefined ? Math.max(Math.ceil((0, _indexts.estimateTokens)(body)), byteTokens) : byteTokens;
|
|
@@ -442,13 +485,13 @@ function peekIndexed(store, cfg, pathArg, overrides) {
|
|
|
442
485
|
frontmatter: frontmatter,
|
|
443
486
|
parseError: parseError,
|
|
444
487
|
sections: sections,
|
|
445
|
-
outbound: outbound
|
|
488
|
+
outbound: outbound,
|
|
446
489
|
backlinks: backlinks,
|
|
447
|
-
unresolved: unresolved
|
|
490
|
+
unresolved: unresolved,
|
|
448
491
|
sectionsTotal: sectionsTotal,
|
|
449
|
-
outboundTotal:
|
|
492
|
+
outboundTotal: outboundTotal,
|
|
450
493
|
backlinksTotal: backlinksTotal,
|
|
451
|
-
unresolvedTotal:
|
|
494
|
+
unresolvedTotal: unresolvedTotal,
|
|
452
495
|
off: [
|
|
453
496
|
'sections',
|
|
454
497
|
'links'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/peek.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport { estimateTokens } from '../chunk/index.ts';\nimport type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { featureEnabled } from '../config/index.ts';\nimport { SenseError } from '../errors.ts';\nimport { serialQuery } from '../lib/serial-query.ts';\nimport type { Row } from '../output/output.ts';\nimport type { Store } from '../store/types.ts';\nimport { INTERNAL_COLUMNS, materializeScope, scopedPaths } from './scope.ts';\nimport { assertQuerySnapshot } from './snapshot.ts';\n\n// Note resolution shared by peek and path: an exact path, or a unique basename (case\n// insensitive, .md stripped).\nexport function resolveNote(paths: string[], arg: string): string {\n const exact = paths.find((p) => p === arg);\n if (exact) return exact;\n const base = posix.basename(arg).replace(/\\.md$/i, '').toLowerCase();\n const matches = paths.filter((p) => posix.basename(p).replace(/\\.md$/i, '').toLowerCase() === base);\n if (matches.length === 1) return matches[0];\n if (matches.length > 1) throw new SenseError('NOTE_AMBIGUOUS', `\"${arg}\" is ambiguous: ${matches.join(', ')}`);\n throw new SenseError('NOTE_NOT_FOUND', `no note matches \"${arg}\"`);\n}\n\n/** Structured, bounded metadata returned by the root {@link peek} API. */\nexport interface Peek {\n path: string;\n tokens: number;\n frontmatter: Row;\n /** Set when frontmatter parsing failed, distinguishing that case from an empty block. */\n parseError: string | null;\n sections: PeekSection[];\n outbound: string[];\n backlinks: string[];\n unresolved: string[];\n /** Totals before each bounded list is truncated. */\n sectionsTotal: number;\n outboundTotal: number;\n backlinksTotal: number;\n unresolvedTotal: number;\n /** Disabled features whose result blocks are omitted rather than returned empty. */\n off: FeatureName[];\n}\n\nexport interface PeekSection {\n level: number;\n heading: string;\n start_line: number;\n end_line: number;\n tokens: number;\n}\n\nconst PEEK_LIST_LIMIT = 20;\n\n/**\n * Returns indexed metadata for a note in scope. Exact excluded paths fail before scoped basename\n * resolution; resolved neighbors stay in scope, while unresolved written targets remain visible.\n */\nexport function peek(store: Store, cfg: ResolvedConfig, pathArg: string, overrides: SearchOverrides = {}): Promise<Peek> {\n return serialQuery(store, () => peekIndexed(store, cfg, pathArg, overrides));\n}\n\nasync function peekIndexed(store: Store, cfg: ResolvedConfig, pathArg: string, overrides: SearchOverrides): Promise<Peek> {\n return store.transaction(async () => {\n await assertQuerySnapshot(store, cfg);\n const pathsStmt = await store.prepare('SELECT \"path\" FROM frontmatter');\n const paths = ((await pathsStmt.all()) as Array<{ path: string }>).map((r) => r.path);\n const allowed = await scopedPaths(store, cfg, overrides);\n if (paths.includes(pathArg) && !allowed.has(pathArg)) {\n throw new SenseError('NOTE_NOT_FOUND', `note \"${pathArg}\" exists but is outside the current scope; change the preset, include/exclude patterns, or where condition`);\n }\n let path: string;\n try {\n path = resolveNote([...allowed], pathArg);\n } catch (err) {\n if (err instanceof SenseError && err.code === 'NOTE_NOT_FOUND') {\n let excludedPath: string;\n try {\n excludedPath = resolveNote(paths, pathArg);\n } catch (unscopedErr) {\n if (unscopedErr instanceof SenseError && unscopedErr.code === 'NOTE_AMBIGUOUS') {\n throw new SenseError('NOTE_NOT_FOUND', `no note in the current scope matches \"${pathArg}\"; indexed matches exist outside the scope, so change the preset, include/exclude patterns, or where condition`);\n }\n throw err;\n }\n throw new SenseError('NOTE_NOT_FOUND', `note \"${excludedPath}\" exists but is outside the current scope; change the preset, include/exclude patterns, or where condition`);\n }\n throw err;\n }\n\n const rowStmt = await store.prepare('SELECT * FROM frontmatter WHERE \"path\" = ?');\n const row = (await rowStmt.get(path)) as Row;\n const parseError = (row._parse_error as string | null) ?? null;\n const frontmatter: Row = {};\n for (const [key, value] of Object.entries(row)) {\n if (!INTERNAL_COLUMNS.has(key) && value !== null) frontmatter[key] = value;\n }\n\n let sectionsTotal = 0;\n let sections: PeekSection[] = [];\n if (featureEnabled(cfg, 'sections')) {\n sectionsTotal = ((await (await store.prepare('SELECT COUNT(*) AS n FROM sections WHERE \"path\" = ?')).get(path)) as { n: number }).n;\n sections = (await (await store.prepare('SELECT level, heading, start_line, end_line, tokens FROM sections WHERE \"path\" = ? ORDER BY idx LIMIT ?')).all(path, PEEK_LIST_LIMIT)) as PeekSection[];\n }\n\n let outbound: string[] = [];\n let backlinks: string[] = [];\n let unresolved: string[] = [];\n let backlinksTotal = 0;\n if (featureEnabled(cfg, 'links')) {\n await materializeScope(store, '_peek_scope', allowed);\n const out = (await (await store.prepare('SELECT target, dst FROM links WHERE src = ? AND (dst IS NULL OR (dst != src AND dst IN (SELECT \"path\" FROM _peek_scope))) ORDER BY target')).all(path)) as Array<{ target: string; dst: string | null }>;\n outbound = [...new Set(out.filter((l): l is { target: string; dst: string } => l.dst !== null).map((l) => l.dst))];\n unresolved = out.filter((l) => l.dst === null).map((l) => l.target);\n backlinksTotal = ((await (await store.prepare('SELECT COUNT(DISTINCT src) AS n FROM links WHERE dst = ? AND src != dst AND src IN (SELECT \"path\" FROM _peek_scope)')).get(path)) as { n: number }).n;\n backlinks = ((await (await store.prepare('SELECT DISTINCT src FROM links WHERE dst = ? AND src != dst AND src IN (SELECT \"path\" FROM _peek_scope) ORDER BY src LIMIT ?')).all(path, PEEK_LIST_LIMIT)) as Array<{ src: string }>).map((r) => r.src);\n }\n\n // content.text is the stripped body already computed at reconcile time (no extra file read),\n // floored by the byte/4 estimate so stripped-away syntax and frontmatter can't vanish from the price.\n const body = ((await (await store.prepare('SELECT text FROM content WHERE \"path\" = ?')).get(path)) as { text: string } | undefined)?.text;\n const byteTokens = Math.ceil(((row._size as number) ?? 0) / 4);\n const tokens = body !== undefined ? Math.max(Math.ceil(estimateTokens(body)), byteTokens) : byteTokens;\n\n return {\n path,\n tokens,\n frontmatter,\n parseError,\n sections,\n outbound: outbound.slice(0, PEEK_LIST_LIMIT),\n backlinks,\n unresolved: unresolved.slice(0, PEEK_LIST_LIMIT),\n sectionsTotal,\n outboundTotal: outbound.length,\n backlinksTotal,\n unresolvedTotal: unresolved.length,\n off: (['sections', 'links'] as FeatureName[]).filter((name) => !featureEnabled(cfg, name)),\n };\n });\n}\n"],"names":["peek","resolveNote","paths","arg","exact","find","p","base","posix","basename","replace","toLowerCase","matches","filter","length","SenseError","join","PEEK_LIST_LIMIT","store","cfg","pathArg","overrides","serialQuery","peekIndexed","transaction","row","pathsStmt","allowed","path","excludedPath","rowStmt","parseError","frontmatter","key","value","sectionsTotal","sections","outbound","backlinks","unresolved","backlinksTotal","out","body","byteTokens","tokens","assertQuerySnapshot","prepare","all","map","r","scopedPaths","includes","has","err","code","unscopedErr","get","_parse_error","Object","entries","INTERNAL_COLUMNS","featureEnabled","n","materializeScope","Set","l","dst","target","src","text","Math","ceil","_size","undefined","max","estimateTokens","slice","outboundTotal","unresolvedTotal","off","name"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/peek.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport { estimateTokens } from '../chunk/index.ts';\nimport type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { featureEnabled } from '../config/index.ts';\nimport { SenseError } from '../errors.ts';\nimport { serialQuery } from '../lib/serial-query.ts';\nimport type { Row } from '../output/output.ts';\nimport type { Store } from '../store/types.ts';\nimport { INTERNAL_COLUMNS, materializeScope, scopedPaths } from './scope.ts';\nimport { assertQuerySnapshot } from './snapshot.ts';\n\n// Note resolution shared by peek and path: an exact path, or a unique basename (case\n// insensitive, .md stripped).\nexport function resolveNote(paths: string[], arg: string): string {\n const exact = paths.find((p) => p === arg);\n if (exact) return exact;\n const base = posix.basename(arg).replace(/\\.md$/i, '').toLowerCase();\n const matches = paths.filter((p) => posix.basename(p).replace(/\\.md$/i, '').toLowerCase() === base);\n if (matches.length === 1) return matches[0];\n if (matches.length > 1) throw new SenseError('NOTE_AMBIGUOUS', `\"${arg}\" is ambiguous: ${matches.join(', ')}`);\n throw new SenseError('NOTE_NOT_FOUND', `no note matches \"${arg}\"`);\n}\n\n/** Structured, bounded metadata returned by the root {@link peek} API. */\nexport interface Peek {\n path: string;\n tokens: number;\n frontmatter: Row;\n /** Set when frontmatter parsing failed, distinguishing that case from an empty block. */\n parseError: string | null;\n sections: PeekSection[];\n outbound: string[];\n backlinks: string[];\n unresolved: string[];\n /** Totals before each bounded list is truncated. */\n sectionsTotal: number;\n outboundTotal: number;\n backlinksTotal: number;\n unresolvedTotal: number;\n /** Disabled features whose result blocks are omitted rather than returned empty. */\n off: FeatureName[];\n}\n\n/** A section description, with an inclusive source line range and token estimate, not section prose. */\nexport interface PeekSection {\n level: number;\n heading: string;\n start_line: number;\n end_line: number;\n tokens: number;\n}\n\n/** Options for the root {@link peek} API. */\nexport interface PeekOptions extends SearchOverrides {\n /** Maximum section descriptions. Defaults to 20; must be a positive safe integer. */\n sectionCountLimit?: number;\n /** Maximum entries in each link group independently. Defaults to 20; must be a positive safe integer. */\n linkCountLimit?: number;\n}\n\nconst PEEK_COUNT_LIMIT = 20;\n\n/**\n * Returns indexed metadata for a note in scope. Exact excluded paths fail before scoped basename\n * resolution; resolved neighbors stay in scope, while unresolved written targets remain visible.\n */\nexport function peek(store: Store, cfg: ResolvedConfig, pathArg: string, overrides: PeekOptions = {}): Promise<Peek> {\n return serialQuery(store, () => peekIndexed(store, cfg, pathArg, overrides));\n}\n\nasync function peekIndexed(store: Store, cfg: ResolvedConfig, pathArg: string, overrides: PeekOptions): Promise<Peek> {\n for (const name of ['sectionCountLimit', 'linkCountLimit'] as const) {\n const value = overrides[name];\n if (value !== undefined && (!Number.isSafeInteger(value) || value <= 0)) {\n throw new SenseError('SEARCH_OPTION_INVALID', `peek option \"${name}\" must be a positive safe integer, got ${String(value)}`);\n }\n }\n const sectionCountLimit = overrides.sectionCountLimit ?? PEEK_COUNT_LIMIT;\n const linkCountLimit = overrides.linkCountLimit ?? PEEK_COUNT_LIMIT;\n return store.transaction(async () => {\n await assertQuerySnapshot(store, cfg);\n const pathsStmt = await store.prepare('SELECT \"path\" FROM frontmatter');\n const paths = ((await pathsStmt.all()) as Array<{ path: string }>).map((r) => r.path);\n const allowed = await scopedPaths(store, cfg, overrides);\n if (paths.includes(pathArg) && !allowed.has(pathArg)) {\n throw new SenseError('NOTE_NOT_FOUND', `note \"${pathArg}\" exists but is outside the current scope; change the preset, include/exclude patterns, or where condition`);\n }\n let path: string;\n try {\n path = resolveNote([...allowed], pathArg);\n } catch (err) {\n if (err instanceof SenseError && err.code === 'NOTE_NOT_FOUND') {\n let excludedPath: string;\n try {\n excludedPath = resolveNote(paths, pathArg);\n } catch (unscopedErr) {\n if (unscopedErr instanceof SenseError && unscopedErr.code === 'NOTE_AMBIGUOUS') {\n throw new SenseError('NOTE_NOT_FOUND', `no note in the current scope matches \"${pathArg}\"; indexed matches exist outside the scope, so change the preset, include/exclude patterns, or where condition`);\n }\n throw err;\n }\n throw new SenseError('NOTE_NOT_FOUND', `note \"${excludedPath}\" exists but is outside the current scope; change the preset, include/exclude patterns, or where condition`);\n }\n throw err;\n }\n\n const rowStmt = await store.prepare('SELECT * FROM frontmatter WHERE \"path\" = ?');\n const row = (await rowStmt.get(path)) as Row;\n const parseError = (row._parse_error as string | null) ?? null;\n const frontmatter: Row = {};\n for (const [key, value] of Object.entries(row)) {\n if (!INTERNAL_COLUMNS.has(key) && value !== null) frontmatter[key] = value;\n }\n\n let sectionsTotal = 0;\n let sections: PeekSection[] = [];\n if (featureEnabled(cfg, 'sections')) {\n sectionsTotal = ((await (await store.prepare('SELECT COUNT(*) AS n FROM sections WHERE \"path\" = ?')).get(path)) as { n: number }).n;\n sections = (await (await store.prepare('SELECT level, heading, start_line, end_line, tokens FROM sections WHERE \"path\" = ? ORDER BY idx LIMIT ?')).all(path, sectionCountLimit)) as PeekSection[];\n }\n\n let outbound: string[] = [];\n let backlinks: string[] = [];\n let unresolved: string[] = [];\n let outboundTotal = 0;\n let backlinksTotal = 0;\n let unresolvedTotal = 0;\n if (featureEnabled(cfg, 'links')) {\n await materializeScope(store, '_peek_scope', allowed);\n outboundTotal = ((await (await store.prepare('SELECT COUNT(DISTINCT dst) AS n FROM links WHERE src = ? AND dst != src AND dst IN (SELECT \"path\" FROM _peek_scope)')).get(path)) as { n: number }).n;\n // The first written target determines each resolved destination's position.\n outbound = ((await (await store.prepare('SELECT dst FROM links WHERE src = ? AND dst != src AND dst IN (SELECT \"path\" FROM _peek_scope) GROUP BY dst ORDER BY MIN(target) LIMIT ?')).all(path, linkCountLimit)) as Array<{ dst: string }>).map((r) => r.dst);\n unresolvedTotal = ((await (await store.prepare('SELECT COUNT(*) AS n FROM links WHERE src = ? AND dst IS NULL')).get(path)) as { n: number }).n;\n unresolved = ((await (await store.prepare('SELECT target FROM links WHERE src = ? AND dst IS NULL ORDER BY target LIMIT ?')).all(path, linkCountLimit)) as Array<{ target: string }>).map((r) => r.target);\n backlinksTotal = ((await (await store.prepare('SELECT COUNT(DISTINCT src) AS n FROM links WHERE dst = ? AND src != dst AND src IN (SELECT \"path\" FROM _peek_scope)')).get(path)) as { n: number }).n;\n backlinks = ((await (await store.prepare('SELECT DISTINCT src FROM links WHERE dst = ? AND src != dst AND src IN (SELECT \"path\" FROM _peek_scope) ORDER BY src LIMIT ?')).all(path, linkCountLimit)) as Array<{ src: string }>).map((r) => r.src);\n }\n\n // content.text is the stripped body already computed at reconcile time (no extra file read),\n // floored by the byte/4 estimate so stripped-away syntax and frontmatter can't vanish from the price.\n const body = ((await (await store.prepare('SELECT text FROM content WHERE \"path\" = ?')).get(path)) as { text: string } | undefined)?.text;\n const byteTokens = Math.ceil(((row._size as number) ?? 0) / 4);\n const tokens = body !== undefined ? Math.max(Math.ceil(estimateTokens(body)), byteTokens) : byteTokens;\n\n return {\n path,\n tokens,\n frontmatter,\n parseError,\n sections,\n outbound,\n backlinks,\n unresolved,\n sectionsTotal,\n outboundTotal,\n backlinksTotal,\n unresolvedTotal,\n off: (['sections', 'links'] as FeatureName[]).filter((name) => !featureEnabled(cfg, name)),\n };\n });\n}\n"],"names":["peek","resolveNote","paths","arg","exact","find","p","base","posix","basename","replace","toLowerCase","matches","filter","length","SenseError","join","PEEK_COUNT_LIMIT","store","cfg","pathArg","overrides","serialQuery","peekIndexed","name","value","sectionCountLimit","linkCountLimit","undefined","Number","isSafeInteger","String","transaction","row","pathsStmt","allowed","path","excludedPath","rowStmt","parseError","frontmatter","key","sectionsTotal","sections","outbound","backlinks","unresolved","outboundTotal","backlinksTotal","unresolvedTotal","body","byteTokens","tokens","assertQuerySnapshot","prepare","all","map","r","scopedPaths","includes","has","err","code","unscopedErr","get","_parse_error","Object","entries","INTERNAL_COLUMNS","featureEnabled","n","materializeScope","dst","target","src","text","Math","ceil","_size","max","estimateTokens","off"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ResolvedConfig } from '../config/index.js';
|
|
2
2
|
import type { Store } from '../store/types.js';
|
|
3
|
-
import type { SearchResultVia } from './signals.js';
|
|
4
|
-
export type { SearchResultVia } from './signals.js';
|
|
3
|
+
import type { SearchResultVia, SearchSignalContribution } from './signals.js';
|
|
4
|
+
export type { SearchResultVia, SearchSignalContribution } from './signals.js';
|
|
5
5
|
export declare const SNIPPET_CHAR_LIMIT_DEFAULT = 80;
|
|
6
6
|
export declare const SNIPPET_COUNT_LIMIT_DEFAULT = 1;
|
|
7
7
|
export declare function computeSnippets(text: string, terms: string[], charLimit: number, countLimit: number): {
|
|
@@ -12,6 +12,8 @@ export declare function lineNumberAt(text: string, offset: number): number;
|
|
|
12
12
|
/** Options for the root {@link search} API. */
|
|
13
13
|
export interface SearchOptions {
|
|
14
14
|
k?: number;
|
|
15
|
+
/** Collects ranking contributions for returned candidates; omitted or false preserves ordinary output. */
|
|
16
|
+
explain?: boolean;
|
|
15
17
|
where?: string;
|
|
16
18
|
preset?: string;
|
|
17
19
|
include?: string[];
|
|
@@ -31,6 +33,8 @@ export type SearchResult = {
|
|
|
31
33
|
score: number;
|
|
32
34
|
lines: string | null;
|
|
33
35
|
similarity?: number | null;
|
|
36
|
+
/** Present only with explain: true, in words/links/vectors order; contributions can differ from via labels. */
|
|
37
|
+
explanation?: SearchSignalContribution[];
|
|
34
38
|
};
|
|
35
39
|
export interface SearchHydrationRow {
|
|
36
40
|
path: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ResolvedConfig } from '../config/index.js';
|
|
2
2
|
import type { Store } from '../store/types.js';
|
|
3
|
-
import type { SearchResultVia } from './signals.js';
|
|
4
|
-
export type { SearchResultVia } from './signals.js';
|
|
3
|
+
import type { SearchResultVia, SearchSignalContribution } from './signals.js';
|
|
4
|
+
export type { SearchResultVia, SearchSignalContribution } from './signals.js';
|
|
5
5
|
export declare const SNIPPET_CHAR_LIMIT_DEFAULT = 80;
|
|
6
6
|
export declare const SNIPPET_COUNT_LIMIT_DEFAULT = 1;
|
|
7
7
|
export declare function computeSnippets(text: string, terms: string[], charLimit: number, countLimit: number): {
|
|
@@ -12,6 +12,8 @@ export declare function lineNumberAt(text: string, offset: number): number;
|
|
|
12
12
|
/** Options for the root {@link search} API. */
|
|
13
13
|
export interface SearchOptions {
|
|
14
14
|
k?: number;
|
|
15
|
+
/** Collects ranking contributions for returned candidates; omitted or false preserves ordinary output. */
|
|
16
|
+
explain?: boolean;
|
|
15
17
|
where?: string;
|
|
16
18
|
preset?: string;
|
|
17
19
|
include?: string[];
|
|
@@ -31,6 +33,8 @@ export type SearchResult = {
|
|
|
31
33
|
score: number;
|
|
32
34
|
lines: string | null;
|
|
33
35
|
similarity?: number | null;
|
|
36
|
+
/** Present only with explain: true, in words/links/vectors order; contributions can differ from via labels. */
|
|
37
|
+
explanation?: SearchSignalContribution[];
|
|
34
38
|
};
|
|
35
39
|
export interface SearchHydrationRow {
|
|
36
40
|
path: string;
|
|
@@ -631,6 +631,9 @@ function lineRangeFor(store, path, line) {
|
|
|
631
631
|
})();
|
|
632
632
|
}
|
|
633
633
|
function validateSearchOptions(opts) {
|
|
634
|
+
if (opts.explain !== undefined && typeof opts.explain !== 'boolean') {
|
|
635
|
+
throw new _errorsts.SenseError('SEARCH_OPTION_INVALID', 'search option "explain" must be a boolean, got '.concat(String(opts.explain)));
|
|
636
|
+
}
|
|
634
637
|
for(var _i = 0, _iter = [
|
|
635
638
|
[
|
|
636
639
|
'k',
|
|
@@ -966,7 +969,7 @@ function searchIndexed(store, cfg, terms, opts) {
|
|
|
966
969
|
}
|
|
967
970
|
function searchSnapshot(store, cfg, terms, opts, prepared, preparedSignature) {
|
|
968
971
|
return _async_to_generator(function() {
|
|
969
|
-
var _ref, signature, effective, allPaths, scopePaths, allowedPaths, semanticEligible, k, signals, fetch, scopeActive, semanticEnabled, scope, whereJoin, whereCond, scopeCond, candidates, matchRows, hasEmptyPhrase, hasBareSyntaxOnly, syntaxError, err1, matchedPaths, chunkLines, chunkSimilarity, ref, where, similarityCol, selectStmt, rows, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, row;
|
|
972
|
+
var _ref, signature, effective, allPaths, scopePaths, allowedPaths, semanticEligible, k, signals, fetch, scopeActive, semanticEnabled, scope, whereJoin, whereCond, scopeCond, candidates, matchRows, hasEmptyPhrase, hasBareSyntaxOnly, syntaxError, err1, matchedPaths, chunkLines, chunkSimilarity, ref, where, similarityCol, selectStmt, rows, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, row, _ref1, _candidates_get, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, row1;
|
|
970
973
|
return _ts_generator(this, function(_state) {
|
|
971
974
|
switch(_state.label){
|
|
972
975
|
case 0:
|
|
@@ -1029,7 +1032,7 @@ function searchSnapshot(store, cfg, terms, opts, prepared, preparedSignature) {
|
|
|
1029
1032
|
]);
|
|
1030
1033
|
return [
|
|
1031
1034
|
4,
|
|
1032
|
-
(0, _signalsts.wordsCandidates)(store, candidates, terms, whereJoin, whereCond, scopeCond, fetch, signals.words)
|
|
1035
|
+
(0, _signalsts.wordsCandidates)(store, candidates, terms, whereJoin, whereCond, scopeCond, fetch, signals.words, opts.explain)
|
|
1033
1036
|
];
|
|
1034
1037
|
case 5:
|
|
1035
1038
|
matchRows = _state.sent();
|
|
@@ -1052,7 +1055,7 @@ function searchSnapshot(store, cfg, terms, opts, prepared, preparedSignature) {
|
|
|
1052
1055
|
];
|
|
1053
1056
|
return [
|
|
1054
1057
|
4,
|
|
1055
|
-
(0, _signalsts.linksCandidates)(store, candidates, matchRows, allPaths, allowedPaths, fetch, signals.links)
|
|
1058
|
+
(0, _signalsts.linksCandidates)(store, candidates, matchRows, allPaths, allowedPaths, fetch, signals.links, opts.explain)
|
|
1056
1059
|
];
|
|
1057
1060
|
case 8:
|
|
1058
1061
|
_state.sent();
|
|
@@ -1066,7 +1069,7 @@ function searchSnapshot(store, cfg, terms, opts, prepared, preparedSignature) {
|
|
|
1066
1069
|
];
|
|
1067
1070
|
return [
|
|
1068
1071
|
4,
|
|
1069
|
-
(0, _signalsts.vectorsCandidates)(store, prepared, candidates, fetch, allowedPaths, allPaths.length, signals.vectors)
|
|
1072
|
+
(0, _signalsts.vectorsCandidates)(store, prepared, candidates, fetch, allowedPaths, allPaths.length, signals.vectors, opts.explain)
|
|
1070
1073
|
];
|
|
1071
1074
|
case 10:
|
|
1072
1075
|
ref = _state.sent(), chunkLines = ref.chunkLines, chunkSimilarity = ref.chunkSimilarity, ref;
|
|
@@ -1157,6 +1160,30 @@ function searchSnapshot(store, cfg, terms, opts, prepared, preparedSignature) {
|
|
|
1157
1160
|
];
|
|
1158
1161
|
case 18:
|
|
1159
1162
|
_state.sent();
|
|
1163
|
+
if (opts.explain) {
|
|
1164
|
+
;
|
|
1165
|
+
;
|
|
1166
|
+
_iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
1167
|
+
try {
|
|
1168
|
+
for(_iterator1 = rows[Symbol.iterator](); !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
1169
|
+
row1 = _step1.value;
|
|
1170
|
+
row1.explanation = (_ref1 = (_candidates_get = candidates.get(row1.path)) === null || _candidates_get === void 0 ? void 0 : _candidates_get.explanation) !== null && _ref1 !== void 0 ? _ref1 : [];
|
|
1171
|
+
}
|
|
1172
|
+
} catch (err) {
|
|
1173
|
+
_didIteratorError1 = true;
|
|
1174
|
+
_iteratorError1 = err;
|
|
1175
|
+
} finally{
|
|
1176
|
+
try {
|
|
1177
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
1178
|
+
_iterator1.return();
|
|
1179
|
+
}
|
|
1180
|
+
} finally{
|
|
1181
|
+
if (_didIteratorError1) {
|
|
1182
|
+
throw _iteratorError1;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1160
1187
|
return [
|
|
1161
1188
|
2,
|
|
1162
1189
|
rows
|