sensemaking 0.9.3 → 0.9.5
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 +35 -93
- package/dist/cjs/cli/check.js +1 -2
- package/dist/cjs/cli/check.js.map +1 -1
- package/dist/cjs/cli/named.js +5 -2
- package/dist/cjs/cli/named.js.map +1 -1
- package/dist/cjs/cli/shared.d.cts +8 -13
- package/dist/cjs/cli/shared.d.ts +8 -13
- package/dist/cjs/cli/shared.js +29 -124
- package/dist/cjs/cli/shared.js.map +1 -1
- package/dist/cjs/cli.js +111 -116
- package/dist/cjs/cli.js.map +1 -1
- package/dist/esm/cli/check.js +1 -2
- package/dist/esm/cli/check.js.map +1 -1
- package/dist/esm/cli/named.js +5 -2
- package/dist/esm/cli/named.js.map +1 -1
- package/dist/esm/cli/shared.d.ts +8 -13
- package/dist/esm/cli/shared.js +33 -55
- package/dist/esm/cli/shared.js.map +1 -1
- package/dist/esm/cli.js +74 -68
- package/dist/esm/cli.js.map +1 -1
- package/package.json +12 -5
- package/skills/sense/EXAMPLES.md +6 -15
- package/skills/sense/SKILL.md +33 -130
- package/skills/sense-setup/EXAMPLES.md +8 -27
- package/skills/sense-setup/SKILL.md +21 -82
- package/dist/cjs/cli/exit.d.cts +0 -5
- package/dist/cjs/cli/exit.d.ts +0 -5
- package/dist/cjs/cli/exit.js +0 -147
- package/dist/cjs/cli/exit.js.map +0 -1
- package/dist/esm/cli/exit.d.ts +0 -5
- package/dist/esm/cli/exit.js +0 -15
- package/dist/esm/cli/exit.js.map +0 -1
package/dist/esm/cli/shared.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { parseArgs } from 'node:util';
|
|
2
2
|
import { open } from '../db.js';
|
|
3
3
|
import { printRows } from '../output.js';
|
|
4
4
|
import { searchError } from '../search-error.js';
|
|
5
|
-
|
|
5
|
+
// Spreadable option fragments -- one flag name keeps one meaning across every command's table.
|
|
6
6
|
export const FORMAT = {
|
|
7
7
|
format: {
|
|
8
8
|
type: 'string',
|
|
@@ -36,70 +36,45 @@ export const SEARCH_FLAGS = {
|
|
|
36
36
|
export function formatOf(values) {
|
|
37
37
|
return values.format === 'json' ? 'json' : 'table';
|
|
38
38
|
}
|
|
39
|
-
// Per-command
|
|
40
|
-
export function parse(argv, usage,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
39
|
+
// Per-command parseArgs: strict (a foreign flag exits 2), and every table gets --help for free.
|
|
40
|
+
export function parse(argv, usage, options) {
|
|
41
|
+
let values;
|
|
42
|
+
let positionals;
|
|
43
|
+
try {
|
|
44
|
+
({ values, positionals } = parseArgs({
|
|
45
|
+
args: argv,
|
|
46
|
+
options: {
|
|
47
|
+
...options,
|
|
48
|
+
help: {
|
|
49
|
+
type: 'boolean',
|
|
50
|
+
default: false,
|
|
51
|
+
short: 'h'
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
strict: true,
|
|
55
|
+
allowPositionals: true
|
|
56
|
+
}));
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.error(err.message);
|
|
59
|
+
console.error(usage);
|
|
60
|
+
process.exit(2);
|
|
57
61
|
}
|
|
58
|
-
|
|
59
|
-
// ignored, which is the bug 0.9.2 fixed. Record the first and fail below; returning false
|
|
60
|
-
// also keeps it out of the result. `--k -1` arrives here as unknown option "1", because
|
|
61
|
-
// getopts reads a leading dash as a new option rather than as --k's value; the message is
|
|
62
|
-
// blunter than the old one but it is still a usage error rather than a silent default.
|
|
63
|
-
let unknown;
|
|
64
|
-
const parsed = getopts(argv, {
|
|
65
|
-
string,
|
|
66
|
-
boolean,
|
|
67
|
-
alias,
|
|
68
|
-
default: defaults,
|
|
69
|
-
unknown: (name)=>{
|
|
70
|
-
if (unknown === undefined) unknown = name;
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
if (unknown !== undefined) usageError(`unknown option: ${unknown}`, usage);
|
|
75
|
-
if (parsed.help) {
|
|
62
|
+
if (values.help) {
|
|
76
63
|
console.log(usage);
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
// Two getopts shapes the callers must not see: an unset string flag reads as "" rather
|
|
80
|
-
// than undefined, and a flag passed once reads as a string rather than a one-element
|
|
81
|
-
// array. Both matter -- `?? saved.field` means "flag absent", and --include is a list.
|
|
82
|
-
const values = {};
|
|
83
|
-
for (const [name, flag] of Object.entries(table)){
|
|
84
|
-
const raw = parsed[name];
|
|
85
|
-
if (flag.type === 'boolean') values[name] = raw;
|
|
86
|
-
else if (flag.multiple) values[name] = raw === '' ? undefined : Array.isArray(raw) ? raw : [
|
|
87
|
-
raw
|
|
88
|
-
];
|
|
89
|
-
else values[name] = raw === '' ? undefined : raw;
|
|
64
|
+
process.exit(0);
|
|
90
65
|
}
|
|
91
66
|
return {
|
|
92
67
|
values,
|
|
93
|
-
positionals
|
|
68
|
+
positionals
|
|
94
69
|
};
|
|
95
70
|
}
|
|
96
71
|
// --k must be a positive integer: SQLite reads a bound LIMIT of -1 as "unlimited" and 0 as
|
|
97
72
|
// "nothing", and parseInt would silently truncate "5.9" -- all three are caller mistakes
|
|
98
73
|
// worth a usage error, matching the config-level SavedSearch validation.
|
|
99
|
-
export function parseK(k,
|
|
74
|
+
export function parseK(k, usageError) {
|
|
100
75
|
if (k === undefined) return undefined;
|
|
101
76
|
const parsed = Number(k);
|
|
102
|
-
if (!Number.isInteger(parsed) || parsed <= 0)
|
|
77
|
+
if (!Number.isInteger(parsed) || parsed <= 0) usageError(`--k expects a positive integer, got "${k}"`);
|
|
103
78
|
return parsed;
|
|
104
79
|
}
|
|
105
80
|
// Shared open-query-close envelope for commands that touch the tree.
|
|
@@ -120,7 +95,10 @@ export async function withDb(ctx, configPath, fn) {
|
|
|
120
95
|
export function runSql(cfg, sql, params, format, label) {
|
|
121
96
|
var _sql_match;
|
|
122
97
|
const placeholderCount = ((_sql_match = sql.match(/\?/g)) !== null && _sql_match !== void 0 ? _sql_match : []).length;
|
|
123
|
-
if (params.length !== placeholderCount)
|
|
98
|
+
if (params.length !== placeholderCount) {
|
|
99
|
+
console.error(`${label} expects ${placeholderCount} parameter(s), got ${params.length}`);
|
|
100
|
+
process.exit(2);
|
|
101
|
+
}
|
|
124
102
|
const { db, warnings } = open(cfg);
|
|
125
103
|
printWarnings(warnings);
|
|
126
104
|
let rows;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/shared.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/shared.ts"],"sourcesContent":["import type { ParseArgsOptionsConfig } from 'node:util';\nimport { parseArgs } from 'node:util';\nimport type { ResolvedConfig } from '../config.ts';\nimport type { OpenResult } from '../db.ts';\nimport { open } from '../db.ts';\nimport type { Row } from '../output.ts';\nimport { printRows } from '../output.ts';\nimport { searchError } from '../search-error.ts';\nimport type { Ctx } from './types.ts';\n\n// Spreadable option fragments -- one flag name keeps one meaning across every command's table.\nexport const FORMAT: ParseArgsOptionsConfig = { format: { type: 'string', default: 'table' } };\nexport const CONFIG: ParseArgsOptionsConfig = { config: { type: 'string' } };\nexport const SEARCH_FLAGS: ParseArgsOptionsConfig = {\n where: { type: 'string' },\n k: { type: 'string' },\n preset: { type: 'string' },\n include: { type: 'string', multiple: true },\n lexical: { type: 'boolean', default: false },\n};\n\ntype Values = Record<string, string | boolean | string[] | undefined>;\n\nexport function formatOf(values: Values): 'table' | 'json' {\n return values.format === 'json' ? 'json' : 'table';\n}\n\n// Per-command parseArgs: strict (a foreign flag exits 2), and every table gets --help for free.\nexport function parse(argv: string[], usage: string, options: ParseArgsOptionsConfig): { values: Values; positionals: string[] } {\n let values: Values;\n let positionals: string[];\n try {\n ({ values, positionals } = parseArgs({\n args: argv,\n options: { ...options, help: { type: 'boolean', default: false, short: 'h' } },\n strict: true,\n allowPositionals: true,\n }));\n } catch (err) {\n console.error((err as Error).message);\n console.error(usage);\n process.exit(2);\n }\n if (values.help) {\n console.log(usage);\n process.exit(0);\n }\n return { values, positionals };\n}\n\n// --k must be a positive integer: SQLite reads a bound LIMIT of -1 as \"unlimited\" and 0 as\n// \"nothing\", and parseInt would silently truncate \"5.9\" -- all three are caller mistakes\n// worth a usage error, matching the config-level SavedSearch validation.\nexport function parseK(k: string | undefined, usageError: (message: string) => never): number | undefined {\n if (k === undefined) return undefined;\n const parsed = Number(k);\n if (!Number.isInteger(parsed) || parsed <= 0) usageError(`--k expects a positive integer, got \"${k}\"`);\n return parsed;\n}\n\n// Shared open-query-close envelope for commands that touch the tree.\n\nexport function printWarnings(warnings: string[]): void {\n for (const w of warnings) console.warn(w);\n}\n\nexport async function withDb(ctx: Ctx, configPath: string | undefined, fn: (db: OpenResult['db'], cfg: ResolvedConfig) => void | Promise<void>): Promise<void> {\n const cfg = ctx.resolveConfig(configPath);\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n try {\n await fn(db, cfg);\n } finally {\n db.close();\n }\n}\n\n// An unbound `?` silently binds NULL, so mismatched param counts fail loudly instead.\nexport function runSql(cfg: ResolvedConfig, sql: string, params: string[], format: 'table' | 'json', label: string): void {\n const placeholderCount = (sql.match(/\\?/g) ?? []).length;\n if (params.length !== placeholderCount) {\n console.error(`${label} expects ${placeholderCount} parameter(s), got ${params.length}`);\n process.exit(2);\n }\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n let rows: Row[];\n try {\n rows = db.prepare(sql).all(...params) as Row[];\n } catch (err) {\n db.close();\n // A saved query or ad-hoc SQL can carry `content MATCH ?` too, so the same FTS5\n // punctuation trap applies -- the bound parameters are the search terms there. SQL\n // without MATCH gets its error verbatim; search advice on a plain typo would mislead.\n if (/\\bMATCH\\b/i.test(sql)) throw searchError(err as Error, params.join(' '));\n throw err;\n }\n printRows(rows, format);\n db.close();\n}\n"],"names":["parseArgs","open","printRows","searchError","FORMAT","format","type","default","CONFIG","config","SEARCH_FLAGS","where","k","preset","include","multiple","lexical","formatOf","values","parse","argv","usage","options","positionals","args","help","short","strict","allowPositionals","err","console","error","message","process","exit","log","parseK","usageError","undefined","parsed","Number","isInteger","printWarnings","warnings","w","warn","withDb","ctx","configPath","fn","cfg","resolveConfig","db","close","runSql","sql","params","label","placeholderCount","match","length","rows","prepare","all","test","join"],"mappings":"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"}
|
package/dist/esm/cli.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
|
-
import
|
|
3
|
-
import getopts from 'getopts-compat';
|
|
4
|
-
import { ExitError, usageError } from './cli/exit.js';
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
5
3
|
import { COMMANDS, USAGE } from './cli/index.js';
|
|
6
4
|
import { loadConfig, SUPPORTED_CONFIG_VERSION } from './config.js';
|
|
7
5
|
// Parsing and dispatch only. Commands live in src/cli/, one file each, lazy-loaded --
|
|
8
6
|
// nothing tree- or dependency-heavy may be imported at the top of this file. Flags parse
|
|
9
7
|
// per command (each command's own parse() call); this file only handles the bare top-level
|
|
10
|
-
// flags (--version/--help/--list/--config) and dispatch
|
|
8
|
+
// flags (--version/--help/--list/--config) and dispatch.
|
|
11
9
|
// Works from dist/cjs and dist/esm alike: walk up past the dist type-marker package.json.
|
|
12
10
|
function packageVersion() {
|
|
13
11
|
const load = createRequire(import.meta.url);
|
|
@@ -42,79 +40,87 @@ function resolveConfigFor(name, configPath) {
|
|
|
42
40
|
}
|
|
43
41
|
return cfg;
|
|
44
42
|
}
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
43
|
+
// Thrown errors -> exit 1 with the message verbatim; usage errors exit 2 directly.
|
|
44
|
+
export default async function cli(argv, name) {
|
|
45
|
+
const first = argv[0];
|
|
46
|
+
// No command word, or the first token looks like a flag: the only flags this level knows.
|
|
47
|
+
if (!first || first.startsWith('-')) {
|
|
48
|
+
let values;
|
|
49
|
+
try {
|
|
50
|
+
({ values } = parseArgs({
|
|
51
|
+
args: argv,
|
|
52
|
+
options: {
|
|
53
|
+
version: {
|
|
54
|
+
type: 'boolean',
|
|
55
|
+
default: false,
|
|
56
|
+
short: 'v'
|
|
57
|
+
},
|
|
58
|
+
help: {
|
|
59
|
+
type: 'boolean',
|
|
60
|
+
default: false,
|
|
61
|
+
short: 'h'
|
|
62
|
+
},
|
|
63
|
+
list: {
|
|
64
|
+
type: 'boolean',
|
|
65
|
+
default: false
|
|
66
|
+
},
|
|
67
|
+
config: {
|
|
68
|
+
type: 'string'
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
allowPositionals: true
|
|
72
|
+
}));
|
|
73
|
+
} catch (err) {
|
|
74
|
+
console.error(err.message);
|
|
75
|
+
console.error(usage(name));
|
|
76
|
+
process.exit(2);
|
|
70
77
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
try {
|
|
79
|
+
if (values.version) {
|
|
80
|
+
console.log(packageVersion());
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (values.help) {
|
|
84
|
+
console.log(usage(name));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (values.list) {
|
|
88
|
+
const queries = resolveConfigFor(name, values.config).queries;
|
|
89
|
+
for (const queryName of Object.keys(queries).sort()){
|
|
90
|
+
const entry = queries[queryName];
|
|
91
|
+
const isSavedSearch = typeof entry === 'object' && entry !== null && 'search' in entry;
|
|
92
|
+
console.log(isSavedSearch ? `${queryName} (search)` : queryName);
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
} catch (err) {
|
|
97
|
+
console.error(err.message);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
console.error(usage(name));
|
|
101
|
+
process.exit(2);
|
|
76
102
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
103
|
+
// find -> search (breaking rename): one release of a pointer instead of "unknown query".
|
|
104
|
+
if (first === 'find') {
|
|
105
|
+
console.error(`${name}: find is now search`);
|
|
106
|
+
console.error(usage(name));
|
|
107
|
+
process.exit(2);
|
|
80
108
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
console.
|
|
109
|
+
const ctx = {
|
|
110
|
+
name,
|
|
111
|
+
argv: argv.slice(1),
|
|
112
|
+
resolveConfig: (configPath)=>resolveConfigFor(name, configPath),
|
|
113
|
+
usageError (message) {
|
|
114
|
+
console.error(message);
|
|
115
|
+
process.exit(2);
|
|
87
116
|
}
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
console.error(usage(name));
|
|
91
|
-
throw new ExitError(2);
|
|
92
|
-
}
|
|
93
|
-
// ExitError carries a chosen code; anything else is an error -> exit 1 with its message.
|
|
94
|
-
export default async function cli(argv, name) {
|
|
117
|
+
};
|
|
95
118
|
try {
|
|
96
|
-
const first = argv[0];
|
|
97
|
-
if (!first || first.startsWith('-')) {
|
|
98
|
-
topLevel(argv, name);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
// find -> search (breaking rename): one release of a pointer instead of "unknown query".
|
|
102
|
-
if (first === 'find') usageError(`${name}: find is now search`, usage(name));
|
|
103
|
-
const ctx = {
|
|
104
|
-
name,
|
|
105
|
-
argv: argv.slice(1),
|
|
106
|
-
resolveConfig: (configPath)=>resolveConfigFor(name, configPath),
|
|
107
|
-
usageError: (message)=>usageError(message)
|
|
108
|
-
};
|
|
109
119
|
const load = COMMANDS[first];
|
|
110
120
|
if (load) await (await load()).default(ctx);
|
|
111
121
|
else await (await import('./cli/named.js')).default(ctx, first);
|
|
112
122
|
} catch (err) {
|
|
113
|
-
if (err instanceof ExitError) {
|
|
114
|
-
exit(err.code);
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
123
|
console.error(err.message);
|
|
118
|
-
exit(1);
|
|
124
|
+
process.exit(1);
|
|
119
125
|
}
|
|
120
126
|
}
|
package/dist/esm/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { parseArgs } from 'node:util';\nimport { COMMANDS, USAGE } from './cli/index.ts';\nimport type { Ctx } from './cli/types.ts';\nimport { loadConfig, SUPPORTED_CONFIG_VERSION } from './config.ts';\n\n// Parsing and dispatch only. Commands live in src/cli/, one file each, lazy-loaded --\n// nothing tree- or dependency-heavy may be imported at the top of this file. Flags parse\n// per command (each command's own parse() call); this file only handles the bare top-level\n// flags (--version/--help/--list/--config) and dispatch.\n\n// Works from dist/cjs and dist/esm alike: walk up past the dist type-marker package.json.\nfunction packageVersion(): string {\n const load = createRequire(import.meta.url);\n for (const rel of ['../package.json', '../../package.json', '../../../package.json']) {\n try {\n const pkg = load(rel) as { name?: string; version?: string };\n if (pkg.name === 'sensemaking' && pkg.version) return pkg.version;\n } catch {}\n }\n return 'unknown';\n}\n\nfunction usage(name: string): string {\n const lines = Object.values(USAGE).map((u) => ` ${name} ${u}`);\n return [`usage: ${name} <name> [params...] [--format table|json] [--config path]`, ...lines, ` ${name} --list`, ` ${name} --version`].join('\\n');\n}\n\nfunction resolveConfigFor(name: string, configPath: string | undefined) {\n const cfg = loadConfig(configPath);\n if (cfg.migratedFrom !== undefined) {\n console.warn(`${name}: migrated ${cfg.configPath} from config version ${cfg.migratedFrom} to ${SUPPORTED_CONFIG_VERSION}`);\n }\n if (cfg.unknownKeys !== undefined) {\n console.warn(`${name}: ${cfg.configPath} sets ${cfg.unknownKeys.join(', ')}, which this build does not read (no effect); see schema.json for the keys it does`);\n }\n return cfg;\n}\n\n// Thrown errors -> exit 1 with the message verbatim; usage errors exit 2 directly.\nexport default async function cli(argv: string[], name: string): Promise<void> {\n const first = argv[0];\n\n // No command word, or the first token looks like a flag: the only flags this level knows.\n if (!first || first.startsWith('-')) {\n let values: Record<string, string | boolean | undefined>;\n try {\n ({ values } = parseArgs({\n args: argv,\n options: {\n version: { type: 'boolean', default: false, short: 'v' },\n help: { type: 'boolean', default: false, short: 'h' },\n list: { type: 'boolean', default: false },\n config: { type: 'string' },\n },\n allowPositionals: true,\n }));\n } catch (err) {\n console.error((err as Error).message);\n console.error(usage(name));\n process.exit(2);\n }\n\n try {\n if (values.version) {\n console.log(packageVersion());\n return;\n }\n if (values.help) {\n console.log(usage(name));\n return;\n }\n if (values.list) {\n const queries = resolveConfigFor(name, values.config as string | undefined).queries;\n for (const queryName of Object.keys(queries).sort()) {\n const entry = queries[queryName];\n const isSavedSearch = typeof entry === 'object' && entry !== null && 'search' in entry;\n console.log(isSavedSearch ? `${queryName} (search)` : queryName);\n }\n return;\n }\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n\n console.error(usage(name));\n process.exit(2);\n }\n\n // find -> search (breaking rename): one release of a pointer instead of \"unknown query\".\n if (first === 'find') {\n console.error(`${name}: find is now search`);\n console.error(usage(name));\n process.exit(2);\n }\n\n const ctx: Ctx = {\n name,\n argv: argv.slice(1),\n resolveConfig: (configPath) => resolveConfigFor(name, configPath),\n usageError(message) {\n console.error(message);\n process.exit(2);\n },\n };\n\n try {\n const load = COMMANDS[first];\n if (load) await (await load()).default(ctx);\n else await (await import('./cli/named.ts')).default(ctx, first);\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n}\n"],"names":["createRequire","parseArgs","COMMANDS","USAGE","loadConfig","SUPPORTED_CONFIG_VERSION","packageVersion","load","url","rel","pkg","name","version","usage","lines","Object","values","map","u","join","resolveConfigFor","configPath","cfg","migratedFrom","undefined","console","warn","unknownKeys","cli","argv","first","startsWith","args","options","type","default","short","help","list","config","allowPositionals","err","error","message","process","exit","log","queries","queryName","keys","sort","entry","isSavedSearch","ctx","slice","resolveConfig","usageError"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sensemaking",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Query and search
|
|
3
|
+
"version": "0.9.5",
|
|
4
|
+
"description": "Query and search your markdown notes with context-aware progressive disclosure: SQL over frontmatter, links, and text, plus semantic search and link-graph ranking. No server, no build step",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
7
7
|
"frontmatter",
|
|
@@ -11,10 +11,19 @@
|
|
|
11
11
|
"query",
|
|
12
12
|
"search",
|
|
13
13
|
"semantic-search",
|
|
14
|
+
"hybrid-search",
|
|
14
15
|
"knowledge-base",
|
|
15
16
|
"rag",
|
|
16
|
-
"
|
|
17
|
+
"markdown-database",
|
|
18
|
+
"document-os",
|
|
17
19
|
"notes",
|
|
20
|
+
"obsidian",
|
|
21
|
+
"markdowndb",
|
|
22
|
+
"iwe",
|
|
23
|
+
"silverbullet",
|
|
24
|
+
"logseq",
|
|
25
|
+
"anytype",
|
|
26
|
+
"zk",
|
|
18
27
|
"agent",
|
|
19
28
|
"agent-memory",
|
|
20
29
|
"memory-consolidation",
|
|
@@ -58,9 +67,7 @@
|
|
|
58
67
|
},
|
|
59
68
|
"dependencies": {
|
|
60
69
|
"@huggingface/tokenizers": "^0.1.3",
|
|
61
|
-
"exit-compat": "^1.0.5",
|
|
62
70
|
"fast-glob": "^3.3.3",
|
|
63
|
-
"getopts-compat": "^2.2.6",
|
|
64
71
|
"remove-markdown": "^0.6.4",
|
|
65
72
|
"yaml": "^2.9.0"
|
|
66
73
|
},
|
package/skills/sense/EXAMPLES.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# sense: worked examples
|
|
2
2
|
|
|
3
|
-
Outputs below are illustrative. Every result is a reference; reading happens afterward, through
|
|
4
|
-
the filesystem, on the paths that earned it.
|
|
3
|
+
Outputs below are illustrative. Every result is a reference; reading happens afterward, through the filesystem, on the paths that earned it.
|
|
5
4
|
|
|
6
5
|
## A. "Do the notes say anything about X?"
|
|
7
6
|
|
|
@@ -18,9 +17,7 @@ sense search "pricing OR billing OR invoicing" --k 10 --format json
|
|
|
18
17
|
]
|
|
19
18
|
```
|
|
20
19
|
|
|
21
|
-
Tens of tokens per row; often the `summary` answers the question with no read at all. A row with
|
|
22
|
-
`via: "link"` never contained the terms — it is linked from notes that did. `lines`, when
|
|
23
|
-
set, is the section that earned the row, a direct `Read` range.
|
|
20
|
+
Tens of tokens per row; often the `summary` answers the question with no read at all. A row with `via: "link"` never contained the terms. It is linked from notes that did. `lines`, when set, is the section that earned the row, a direct `Read` range.
|
|
24
21
|
|
|
25
22
|
## B. Known-field filtering (no search)
|
|
26
23
|
|
|
@@ -28,11 +25,9 @@ set, is the section that earned the row, a direct `Read` range.
|
|
|
28
25
|
sense query "SELECT path, title, status FROM frontmatter WHERE status = 'active' AND has(tags, ?)" pricing --format json
|
|
29
26
|
```
|
|
30
27
|
|
|
31
|
-
Plain SQL on discovered columns. Combine with search by joining `content` and adding
|
|
32
|
-
`AND content MATCH ?` — filter and rank in one query.
|
|
28
|
+
Plain SQL on discovered columns. Combine with search by joining `content` and adding `AND content MATCH ?`: filter and rank in one query.
|
|
33
29
|
|
|
34
|
-
Per-member counts on an array field (GROUP BY on the raw column would split `["a","b"]` from
|
|
35
|
-
`["b","a"]`):
|
|
30
|
+
Per-member counts on an array field (GROUP BY on the raw column would split `["a","b"]` from `["b","a"]`):
|
|
36
31
|
|
|
37
32
|
```
|
|
38
33
|
sense query "SELECT j.value AS tag, COUNT(*) n FROM frontmatter, json_each(frontmatter.tags) j GROUP BY j.value ORDER BY n DESC"
|
|
@@ -55,8 +50,7 @@ links out (7): notes/pricing-model.md, ...
|
|
|
55
50
|
backlinks (2): notes/_index.md, notes/roadmap.md
|
|
56
51
|
```
|
|
57
52
|
|
|
58
|
-
The note is ~4,400 tokens; the peek is ~500. If only one section matters, `Read` its line range
|
|
59
|
-
(~400 tokens) — a tenth of the file.
|
|
53
|
+
The note is ~4,400 tokens; the peek is ~500. If only one section matters, `Read` its line range (~400 tokens), a tenth of the file.
|
|
60
54
|
|
|
61
55
|
## D. The graph
|
|
62
56
|
|
|
@@ -89,10 +83,7 @@ sense search "children dying from poor nutrition" --k 3 --format json
|
|
|
89
83
|
]
|
|
90
84
|
```
|
|
91
85
|
|
|
92
|
-
A `via: "vector"` row never contained the terms
|
|
93
|
-
the cosine against the chunk `lines` names, a direct `Read` range. Vector rows appear whenever
|
|
94
|
-
the scope's preset has semantic on (the default); a result of only vector rows means the words
|
|
95
|
-
themselves are nowhere in the scope.
|
|
86
|
+
A `via: "vector"` row never contained the terms. It is semantically near them; `similarity` is the cosine against the chunk `lines` names, a direct `Read` range. Vector rows appear whenever the scope's preset has semantic on (the default); a result of only vector rows means the words themselves are nowhere in the scope.
|
|
96
87
|
|
|
97
88
|
## Consequences
|
|
98
89
|
|