context-vault 3.19.0 → 3.20.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/bin/cli.js +516 -4
- package/node_modules/@context-vault/core/dist/main.d.ts +1 -0
- package/node_modules/@context-vault/core/dist/main.d.ts.map +1 -1
- package/node_modules/@context-vault/core/dist/main.js +2 -0
- package/node_modules/@context-vault/core/dist/main.js.map +1 -1
- package/node_modules/@context-vault/core/dist/search.d.ts +1 -0
- package/node_modules/@context-vault/core/dist/search.d.ts.map +1 -1
- package/node_modules/@context-vault/core/dist/search.js +10 -1
- package/node_modules/@context-vault/core/dist/search.js.map +1 -1
- package/node_modules/@context-vault/core/dist/search.test.d.ts +2 -0
- package/node_modules/@context-vault/core/dist/search.test.d.ts.map +1 -0
- package/node_modules/@context-vault/core/dist/search.test.js +49 -0
- package/node_modules/@context-vault/core/dist/search.test.js.map +1 -0
- package/node_modules/@context-vault/core/package.json +9 -1
- package/node_modules/@context-vault/core/src/main.ts +3 -0
- package/node_modules/@context-vault/core/src/search.test.ts +59 -0
- package/node_modules/@context-vault/core/src/search.ts +11 -1
- package/package.json +2 -2
- package/.claude-plugin/README.md +0 -219
- package/.claude-plugin/plugin.json +0 -11
- package/commands/vault-cleanup.md +0 -43
- package/commands/vault-snapshot.md +0 -43
- package/commands/vault-status.md +0 -35
- package/dist/tools/session-start.d.ts +0 -25
- package/dist/tools/session-start.d.ts.map +0 -1
- package/dist/tools/session-start.js +0 -469
- package/dist/tools/session-start.js.map +0 -1
- package/skills/context-assembly/SKILL.md +0 -308
- package/skills/knowledge-capture/SKILL.md +0 -303
- package/skills/memory-management/SKILL.md +0 -237
- package/src/tools/session-start.ts +0 -527
package/bin/cli.js
CHANGED
|
@@ -240,6 +240,17 @@ function getFlag(name) {
|
|
|
240
240
|
return idx !== -1 && args[idx + 1] ? args[idx + 1] : null;
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
function getFlagAll(name) {
|
|
244
|
+
const results = [];
|
|
245
|
+
for (let i = 0; i < args.length - 1; i++) {
|
|
246
|
+
if (args[i] === name) {
|
|
247
|
+
const val = args[i + 1];
|
|
248
|
+
if (val && !val.startsWith('--')) results.push(val);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return results;
|
|
252
|
+
}
|
|
253
|
+
|
|
243
254
|
function prompt(question, defaultVal) {
|
|
244
255
|
if (isNonInteractive) return Promise.resolve(defaultVal || '');
|
|
245
256
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -447,6 +458,9 @@ ${bold('Commands:')}
|
|
|
447
458
|
${cyan('reconnect')} Fix vault path, kill stale servers, re-register MCP, reindex
|
|
448
459
|
${cyan('search')} Search vault entries from CLI
|
|
449
460
|
${cyan('save')} Save an entry to the vault from CLI
|
|
461
|
+
${cyan('get')} <id|key> Fetch a single entry by ULID or identity key
|
|
462
|
+
${cyan('buckets')} List registered buckets with entry counts
|
|
463
|
+
${cyan('dupes')} Find near-duplicate entries (read-only)
|
|
450
464
|
${cyan('import')} <path> Import entries from file, directory, or .zip archive
|
|
451
465
|
${cyan('export')} Export vault entries (JSON, CSV, or portable ZIP)
|
|
452
466
|
${cyan('ingest')} <url> Fetch URL and save as vault entry
|
|
@@ -462,6 +476,7 @@ ${bold('Commands:')}
|
|
|
462
476
|
${cyan('archive')} Archive old ephemeral/event entries (use --dry-run to preview)
|
|
463
477
|
${cyan('restore')} <id> Restore an archived entry back into the vault
|
|
464
478
|
${cyan('prune')} Remove expired entries (use --dry-run to preview)
|
|
479
|
+
${cyan('delete')} <id> Hard-delete entry by ULID (DB + vec + file; clears superseded_by refs)
|
|
465
480
|
${cyan('stale')} List entries with low freshness scores
|
|
466
481
|
${cyan('stats')} recall|co-retrieval Measure recall ratio and co-retrieval graph
|
|
467
482
|
${cyan('remote')} setup|status|sync|pull Connect to hosted vault (cloud sync)
|
|
@@ -2683,6 +2698,118 @@ async function runPrune() {
|
|
|
2683
2698
|
}
|
|
2684
2699
|
}
|
|
2685
2700
|
|
|
2701
|
+
async function runDelete() {
|
|
2702
|
+
if (flags.has('--help')) {
|
|
2703
|
+
console.log(`
|
|
2704
|
+
${bold('context-vault delete')} <id> [options]
|
|
2705
|
+
|
|
2706
|
+
Hard-delete a vault entry by ULID. Removes the DB row, vector-index row,
|
|
2707
|
+
and the markdown file on disk. Also clears any ${cyan('superseded_by')} refs
|
|
2708
|
+
on other entries that pointed at this one (no dangling links).
|
|
2709
|
+
|
|
2710
|
+
Distinct from ${cyan('archive')} (soft, reversible via ${cyan('restore')})
|
|
2711
|
+
and ${cyan('prune')} (bulk by expiry policy).
|
|
2712
|
+
|
|
2713
|
+
${bold('Usage:')}
|
|
2714
|
+
context-vault delete <id> Delete entry by ULID
|
|
2715
|
+
context-vault delete <id> --dry-run Show what would be deleted, no changes
|
|
2716
|
+
context-vault delete <id> --yes Skip confirmation prompt
|
|
2717
|
+
|
|
2718
|
+
${bold('Examples:')}
|
|
2719
|
+
context-vault delete 01KQ0123456789ABCDEFGHJKMN
|
|
2720
|
+
context-vault delete 01KQ0123456789ABCDEFGHJKMN --yes
|
|
2721
|
+
`);
|
|
2722
|
+
return;
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
const entryId = args[1];
|
|
2726
|
+
if (!entryId || entryId.startsWith('--')) {
|
|
2727
|
+
console.error(red('Error: entry id is required'));
|
|
2728
|
+
console.error(`Usage: ${cyan('context-vault delete <id>')}`);
|
|
2729
|
+
process.exit(1);
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
const dryRun = flags.has('--dry-run');
|
|
2733
|
+
|
|
2734
|
+
const { resolveConfig } = await import('@context-vault/core/config');
|
|
2735
|
+
const { initDatabase, prepareStatements, deleteVec } = await import('@context-vault/core/db');
|
|
2736
|
+
|
|
2737
|
+
const config = resolveConfig();
|
|
2738
|
+
if (!config.vaultDirExists) {
|
|
2739
|
+
console.error(red(`Vault directory not found: ${config.vaultDir}`));
|
|
2740
|
+
console.error('Run ' + cyan('context-vault setup') + ' to configure.');
|
|
2741
|
+
process.exit(1);
|
|
2742
|
+
}
|
|
2743
|
+
|
|
2744
|
+
const db = await initDatabase(config.dbPath);
|
|
2745
|
+
try {
|
|
2746
|
+
const stmts = prepareStatements(db);
|
|
2747
|
+
const row = stmts.getEntryById.get(entryId);
|
|
2748
|
+
if (!row) {
|
|
2749
|
+
console.error(red(`Error: no entry found with id ${entryId}`));
|
|
2750
|
+
process.exit(1);
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
const label = row.title ? `${row.kind}: ${row.title}` : `${row.kind} (${row.id})`;
|
|
2754
|
+
const filePath = row.file_path || null;
|
|
2755
|
+
|
|
2756
|
+
if (dryRun) {
|
|
2757
|
+
console.log(`\n Would delete: ${label}`);
|
|
2758
|
+
if (filePath) console.log(dim(` file: ${filePath}`));
|
|
2759
|
+
console.log(dim(` id: ${row.id}`));
|
|
2760
|
+
const referrers = db
|
|
2761
|
+
.prepare('SELECT id, kind, title FROM vault WHERE superseded_by = ?')
|
|
2762
|
+
.all(entryId);
|
|
2763
|
+
if (referrers.length) {
|
|
2764
|
+
console.log(dim(` ${referrers.length} entr${referrers.length === 1 ? 'y has' : 'ies have'} superseded_by pointing here; those refs would be cleared:`));
|
|
2765
|
+
for (const r of referrers) {
|
|
2766
|
+
const rlabel = r.title ? `${r.kind}: ${r.title}` : `${r.kind} (${r.id})`;
|
|
2767
|
+
console.log(dim(` - ${rlabel}`));
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
console.log(dim('\n Dry run — nothing changed.'));
|
|
2771
|
+
return;
|
|
2772
|
+
}
|
|
2773
|
+
|
|
2774
|
+
if (!isNonInteractive) {
|
|
2775
|
+
const answer = await prompt(`Delete ${label}? (y/N)`, 'N');
|
|
2776
|
+
if (!/^y(es)?$/i.test((answer || '').trim())) {
|
|
2777
|
+
console.log(dim(' Aborted.'));
|
|
2778
|
+
return;
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
|
|
2782
|
+
const rowidRow = stmts.getRowid.get(entryId);
|
|
2783
|
+
if (rowidRow?.rowid) {
|
|
2784
|
+
try {
|
|
2785
|
+
deleteVec(stmts, Number(rowidRow.rowid));
|
|
2786
|
+
} catch {}
|
|
2787
|
+
}
|
|
2788
|
+
try {
|
|
2789
|
+
stmts.clearSupersededByRef.run(entryId);
|
|
2790
|
+
} catch {}
|
|
2791
|
+
stmts.deleteEntry.run(entryId);
|
|
2792
|
+
|
|
2793
|
+
if (filePath) {
|
|
2794
|
+
try {
|
|
2795
|
+
unlinkSync(filePath);
|
|
2796
|
+
} catch (e) {
|
|
2797
|
+
if (e?.code !== 'ENOENT') {
|
|
2798
|
+
console.error(yellow(` Warning: could not remove file: ${e.message}`));
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2803
|
+
console.log(`${green('✓')} Deleted ${label}`);
|
|
2804
|
+
console.log(dim(` id: ${entryId}`));
|
|
2805
|
+
if (filePath) console.log(dim(` file removed: ${filePath}`));
|
|
2806
|
+
} finally {
|
|
2807
|
+
try {
|
|
2808
|
+
db.close();
|
|
2809
|
+
} catch {}
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
|
|
2686
2813
|
async function runArchive() {
|
|
2687
2814
|
const dryRun = flags.has('--dry-run');
|
|
2688
2815
|
|
|
@@ -2908,6 +3035,226 @@ async function runCompact() {
|
|
|
2908
3035
|
console.log(dim(' Use context-vault restore <id> to recover full body.'));
|
|
2909
3036
|
}
|
|
2910
3037
|
|
|
3038
|
+
async function runGet() {
|
|
3039
|
+
if (flags.has('--help')) {
|
|
3040
|
+
console.log(`
|
|
3041
|
+
${bold('context-vault get')} <id|identity-key> [options]
|
|
3042
|
+
|
|
3043
|
+
Fetch a single vault entry by ULID or by identity key.
|
|
3044
|
+
|
|
3045
|
+
${bold('Usage:')}
|
|
3046
|
+
context-vault get 01KQ0123456789ABCDEFGHJKMN
|
|
3047
|
+
context-vault get bucket:myproject --kind bucket
|
|
3048
|
+
context-vault get myproject --kind bucket
|
|
3049
|
+
context-vault get <id> --format json
|
|
3050
|
+
|
|
3051
|
+
${bold('Options:')}
|
|
3052
|
+
--kind <kind> Resolve the argument as an identity key for this kind
|
|
3053
|
+
--format <fmt> Output format: plain (default), json
|
|
3054
|
+
--full Show full entry body (not truncated)
|
|
3055
|
+
`);
|
|
3056
|
+
return;
|
|
3057
|
+
}
|
|
3058
|
+
|
|
3059
|
+
const ref = args[1];
|
|
3060
|
+
if (!ref || ref.startsWith('--')) {
|
|
3061
|
+
console.error(red('Error: entry id or identity key is required'));
|
|
3062
|
+
console.error(`Usage: ${cyan('context-vault get <id|identity-key>')}`);
|
|
3063
|
+
process.exit(1);
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
const kindFlag = getFlag('--kind');
|
|
3067
|
+
const format = getFlag('--format') || 'plain';
|
|
3068
|
+
const showFull = flags.has('--full');
|
|
3069
|
+
|
|
3070
|
+
const { resolveConfig } = await import('@context-vault/core/config');
|
|
3071
|
+
const { initDatabase, prepareStatements } = await import('@context-vault/core/db');
|
|
3072
|
+
|
|
3073
|
+
const config = resolveConfig();
|
|
3074
|
+
if (!config.vaultDirExists) {
|
|
3075
|
+
console.error(red('No vault found. Run: context-vault setup'));
|
|
3076
|
+
process.exit(1);
|
|
3077
|
+
}
|
|
3078
|
+
|
|
3079
|
+
const db = await initDatabase(config.dbPath);
|
|
3080
|
+
try {
|
|
3081
|
+
const stmts = prepareStatements(db);
|
|
3082
|
+
|
|
3083
|
+
let row = null;
|
|
3084
|
+
if (kindFlag) {
|
|
3085
|
+
const key = ref.includes(':') ? ref : `${kindFlag}:${ref}`;
|
|
3086
|
+
row = stmts.getByIdentityKey.get(kindFlag, key) || stmts.getByIdentityKey.get(kindFlag, ref);
|
|
3087
|
+
} else {
|
|
3088
|
+
row = stmts.getEntryById.get(ref);
|
|
3089
|
+
if (!row && ref.includes(':')) {
|
|
3090
|
+
const inferredKind = ref.slice(0, ref.indexOf(':'));
|
|
3091
|
+
row = stmts.getByIdentityKey.get(inferredKind, ref);
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
|
|
3095
|
+
if (!row) {
|
|
3096
|
+
console.error(red(`Error: no entry found for "${ref}"${kindFlag ? ` (kind ${kindFlag})` : ''}`));
|
|
3097
|
+
process.exit(1);
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
if (format === 'json') {
|
|
3101
|
+
console.log(JSON.stringify(row, null, 2));
|
|
3102
|
+
return;
|
|
3103
|
+
}
|
|
3104
|
+
|
|
3105
|
+
const tags = row.tags ? JSON.parse(row.tags) : [];
|
|
3106
|
+
console.log(`\n ${bold(row.title || `${row.kind} (${row.id})`)}`);
|
|
3107
|
+
console.log(dim(` id: ${row.id}`));
|
|
3108
|
+
console.log(dim(` kind: ${row.kind}${row.category ? ` category: ${row.category}` : ''}`));
|
|
3109
|
+
if (row.identity_key) console.log(dim(` key: ${row.identity_key}`));
|
|
3110
|
+
if (tags.length) console.log(dim(` tags: ${tags.join(', ')}`));
|
|
3111
|
+
console.log(dim(` created: ${row.created_at}${row.updated_at ? ` updated: ${row.updated_at}` : ''}`));
|
|
3112
|
+
if (row.superseded_by) console.log(yellow(` superseded_by: ${row.superseded_by}`));
|
|
3113
|
+
const body = row.body || '';
|
|
3114
|
+
const shown = showFull ? body : body.slice(0, 2000);
|
|
3115
|
+
console.log('\n' + shown + (shown.length < body.length ? dim('\n … (truncated; use --full)') : ''));
|
|
3116
|
+
} finally {
|
|
3117
|
+
db.close();
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
async function runBuckets() {
|
|
3122
|
+
if (flags.has('--help')) {
|
|
3123
|
+
console.log(`
|
|
3124
|
+
${bold('context-vault buckets')} [options]
|
|
3125
|
+
|
|
3126
|
+
List all registered bucket entities with entry counts. Buckets are named
|
|
3127
|
+
scopes that group entries via ${cyan('bucket:')}-prefixed tags.
|
|
3128
|
+
|
|
3129
|
+
${bold('Options:')}
|
|
3130
|
+
--format <fmt> Output format: plain (default), json
|
|
3131
|
+
`);
|
|
3132
|
+
return;
|
|
3133
|
+
}
|
|
3134
|
+
|
|
3135
|
+
const format = getFlag('--format') || 'plain';
|
|
3136
|
+
|
|
3137
|
+
const { resolveConfig } = await import('@context-vault/core/config');
|
|
3138
|
+
const { initDatabase } = await import('@context-vault/core/db');
|
|
3139
|
+
|
|
3140
|
+
const config = resolveConfig();
|
|
3141
|
+
if (!config.vaultDirExists) {
|
|
3142
|
+
console.error(red('No vault found. Run: context-vault setup'));
|
|
3143
|
+
process.exit(1);
|
|
3144
|
+
}
|
|
3145
|
+
|
|
3146
|
+
const db = await initDatabase(config.dbPath);
|
|
3147
|
+
try {
|
|
3148
|
+
const buckets = db
|
|
3149
|
+
.prepare(
|
|
3150
|
+
`SELECT id, title, identity_key, body, tags, created_at, updated_at
|
|
3151
|
+
FROM vault
|
|
3152
|
+
WHERE kind = 'bucket'
|
|
3153
|
+
AND (expires_at IS NULL OR expires_at > datetime('now'))
|
|
3154
|
+
AND superseded_by IS NULL
|
|
3155
|
+
ORDER BY title ASC`
|
|
3156
|
+
)
|
|
3157
|
+
.all();
|
|
3158
|
+
|
|
3159
|
+
const withCounts = buckets.map((b) => {
|
|
3160
|
+
const name = b.identity_key?.replace(/^bucket:/, '') || b.title;
|
|
3161
|
+
const c = db
|
|
3162
|
+
.prepare(
|
|
3163
|
+
`SELECT COUNT(*) AS c FROM vault
|
|
3164
|
+
WHERE superseded_by IS NULL
|
|
3165
|
+
AND (expires_at IS NULL OR expires_at > datetime('now'))
|
|
3166
|
+
AND tags LIKE ?`
|
|
3167
|
+
)
|
|
3168
|
+
.get(`%"bucket:${name}"%`);
|
|
3169
|
+
return { ...b, name, entry_count: c?.c ?? 0 };
|
|
3170
|
+
});
|
|
3171
|
+
|
|
3172
|
+
if (format === 'json') {
|
|
3173
|
+
console.log(JSON.stringify(withCounts, null, 2));
|
|
3174
|
+
return;
|
|
3175
|
+
}
|
|
3176
|
+
|
|
3177
|
+
if (!withCounts.length) {
|
|
3178
|
+
console.log(dim(' No buckets registered.'));
|
|
3179
|
+
return;
|
|
3180
|
+
}
|
|
3181
|
+
|
|
3182
|
+
console.log(`\n ${bold(`Registered buckets (${withCounts.length})`)}\n`);
|
|
3183
|
+
for (const b of withCounts) {
|
|
3184
|
+
const desc = b.body ? ` — ${b.body.split('\n')[0].slice(0, 60)}` : '';
|
|
3185
|
+
console.log(` ${cyan(b.name)} ${dim(`(${b.entry_count})`)}${dim(desc)}`);
|
|
3186
|
+
}
|
|
3187
|
+
} finally {
|
|
3188
|
+
db.close();
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
|
|
3192
|
+
async function runDupes() {
|
|
3193
|
+
if (flags.has('--help')) {
|
|
3194
|
+
console.log(`
|
|
3195
|
+
${bold('context-vault dupes')} [options]
|
|
3196
|
+
|
|
3197
|
+
Find near-duplicate entries by semantic + title similarity. Read-only —
|
|
3198
|
+
reports groups, changes nothing.
|
|
3199
|
+
|
|
3200
|
+
${bold('Options:')}
|
|
3201
|
+
--threshold <n> Similarity threshold 0..1 (default: 0.85)
|
|
3202
|
+
--limit <n> Max duplicate groups (default: 50)
|
|
3203
|
+
--kind <kind> Restrict to a single kind
|
|
3204
|
+
--format <fmt> Output format: plain (default), json
|
|
3205
|
+
`);
|
|
3206
|
+
return;
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
const threshold = parseFloat(getFlag('--threshold') || '0.85');
|
|
3210
|
+
const limit = parseInt(getFlag('--limit') || '50', 10);
|
|
3211
|
+
const kind = getFlag('--kind') || undefined;
|
|
3212
|
+
const format = getFlag('--format') || 'plain';
|
|
3213
|
+
|
|
3214
|
+
const { resolveConfig } = await import('@context-vault/core/config');
|
|
3215
|
+
const { initDatabase, prepareStatements } = await import('@context-vault/core/db');
|
|
3216
|
+
const { embed } = await import('@context-vault/core/embed');
|
|
3217
|
+
const { findDuplicates } = await import('@context-vault/core/consolidation');
|
|
3218
|
+
|
|
3219
|
+
const config = resolveConfig();
|
|
3220
|
+
if (!config.vaultDirExists) {
|
|
3221
|
+
console.error(red('No vault found. Run: context-vault setup'));
|
|
3222
|
+
process.exit(1);
|
|
3223
|
+
}
|
|
3224
|
+
|
|
3225
|
+
const db = await initDatabase(config.dbPath);
|
|
3226
|
+
try {
|
|
3227
|
+
const stmts = prepareStatements(db);
|
|
3228
|
+
const ctx = { db, config, stmts, embed };
|
|
3229
|
+
const groups = await findDuplicates(ctx, { threshold, limit, kind, dryRun: true });
|
|
3230
|
+
|
|
3231
|
+
if (format === 'json') {
|
|
3232
|
+
console.log(JSON.stringify(groups, null, 2));
|
|
3233
|
+
return;
|
|
3234
|
+
}
|
|
3235
|
+
|
|
3236
|
+
if (!groups.length) {
|
|
3237
|
+
console.log(dim(` No near-duplicates found (threshold ${threshold}).`));
|
|
3238
|
+
return;
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
console.log(`\n ${bold(`Near-duplicate groups (${groups.length})`)} ${dim(`threshold ${threshold}`)}\n`);
|
|
3242
|
+
for (const g of groups) {
|
|
3243
|
+
const dupCount = (g.duplicate_ids?.length ?? 0) + 1;
|
|
3244
|
+
console.log(` ${yellow(`${dupCount}×`)} ${g.canonical_title || ''} ${dim(`sim ${g.similarity}`)}`);
|
|
3245
|
+
console.log(dim(` canonical: ${g.canonical_id}`));
|
|
3246
|
+
for (const id of g.duplicate_ids ?? []) {
|
|
3247
|
+
console.log(dim(` dup: ${id}`));
|
|
3248
|
+
}
|
|
3249
|
+
for (const t of g.sample_titles ?? []) {
|
|
3250
|
+
console.log(dim(` · ${t}`));
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
} finally {
|
|
3254
|
+
db.close();
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
|
|
2911
3258
|
async function runStatus() {
|
|
2912
3259
|
const { resolveConfig } = await import('@context-vault/core/config');
|
|
2913
3260
|
const { initDatabase } = await import('@context-vault/core/db');
|
|
@@ -4181,7 +4528,7 @@ ${bold('Examples:')}
|
|
|
4181
4528
|
const dryRun = flags.has('--dry-run');
|
|
4182
4529
|
const verbose = flags.has('--verbose');
|
|
4183
4530
|
|
|
4184
|
-
const GMAIL_CLI_PATH = '
|
|
4531
|
+
const GMAIL_CLI_PATH = join(homedir(), 'omni/workspaces/_archive/agent-tools/gmail-cli/cli.ts');
|
|
4185
4532
|
const SKIP_LABELS = new Set([
|
|
4186
4533
|
'CATEGORY_PROMOTIONS',
|
|
4187
4534
|
'CATEGORY_SOCIAL',
|
|
@@ -4322,7 +4669,7 @@ ${bold('Examples:')}
|
|
|
4322
4669
|
}
|
|
4323
4670
|
|
|
4324
4671
|
async function runSlackBridge() {
|
|
4325
|
-
const SLACK_CLI_PATH = '
|
|
4672
|
+
const SLACK_CLI_PATH = join(homedir(), 'omni/workspaces/_archive/agent-tools/slack-cli/cli.ts');
|
|
4326
4673
|
|
|
4327
4674
|
if (flags.has('--help') || (!flags.has('--list-channels') && !getFlag('--channels'))) {
|
|
4328
4675
|
console.log(`
|
|
@@ -5156,10 +5503,19 @@ ${bold('Optional:')}
|
|
|
5156
5503
|
--source <source> Source label (default: cli)
|
|
5157
5504
|
--identity-key <key> Identity key (for entity kinds)
|
|
5158
5505
|
--meta <json> Additional metadata as JSON
|
|
5506
|
+
--supersedes <id> Mark this entry as superseding an existing entry
|
|
5507
|
+
(can be passed multiple times; old entries get
|
|
5508
|
+
reciprocal superseded_by link to this new entry)
|
|
5509
|
+
--related-to <id> Add a related-to link to another entry by ULID
|
|
5510
|
+
(can be passed multiple times; builds the graph)
|
|
5159
5511
|
|
|
5160
5512
|
${bold('Examples:')}
|
|
5161
5513
|
context-vault save --kind insight --title "Express 5 gotcha" --body "body parser changed"
|
|
5162
5514
|
echo "content" | context-vault save --kind reference --title "API notes"
|
|
5515
|
+
context-vault save --kind decision --title "revised plan" --body "..." \\
|
|
5516
|
+
--supersedes 01K9... --supersedes 01KA...
|
|
5517
|
+
context-vault save --kind insight --title "graph node" --body "..." \\
|
|
5518
|
+
--related-to 01KB... --related-to 01KC...
|
|
5163
5519
|
`);
|
|
5164
5520
|
return;
|
|
5165
5521
|
}
|
|
@@ -5173,6 +5529,8 @@ ${bold('Examples:')}
|
|
|
5173
5529
|
const bodyFlag = getFlag('--body');
|
|
5174
5530
|
const identityKey = getFlag('--identity-key');
|
|
5175
5531
|
const metaRaw = getFlag('--meta');
|
|
5532
|
+
const supersedesList = getFlagAll('--supersedes');
|
|
5533
|
+
const relatedToList = getFlagAll('--related-to');
|
|
5176
5534
|
|
|
5177
5535
|
if (!kind) {
|
|
5178
5536
|
console.error(red('Error: --kind is required'));
|
|
@@ -5248,8 +5606,17 @@ ${bold('Examples:')}
|
|
|
5248
5606
|
...(tier ? { tier } : {}),
|
|
5249
5607
|
...(identityKey ? { identity_key: identityKey } : {}),
|
|
5250
5608
|
...(meta !== undefined ? { meta } : {}),
|
|
5609
|
+
...(supersedesList.length ? { supersedes: supersedesList } : {}),
|
|
5610
|
+
...(relatedToList.length ? { related_to: relatedToList } : {}),
|
|
5251
5611
|
});
|
|
5252
5612
|
console.log(`${green('✓')} Saved ${kind} — id: ${entry.id}`);
|
|
5613
|
+
if (supersedesList.length) {
|
|
5614
|
+
console.log(dim(` supersedes: ${supersedesList.join(', ')}`));
|
|
5615
|
+
console.log(dim(` (reciprocal superseded_by written to ${supersedesList.length} entr${supersedesList.length === 1 ? 'y' : 'ies'})`));
|
|
5616
|
+
}
|
|
5617
|
+
if (relatedToList.length) {
|
|
5618
|
+
console.log(dim(` related_to: ${relatedToList.join(', ')}`));
|
|
5619
|
+
}
|
|
5253
5620
|
} catch (e) {
|
|
5254
5621
|
console.error(`${red('x')} Failed to save: ${e.message}`);
|
|
5255
5622
|
process.exit(1);
|
|
@@ -6557,6 +6924,104 @@ async function runDoctor() {
|
|
|
6557
6924
|
console.log(` ${dim('Fix: run context-vault setup to download the model')}`);
|
|
6558
6925
|
}
|
|
6559
6926
|
|
|
6927
|
+
// ── Save/search roundtrip ────────────────────────────────────────────
|
|
6928
|
+
// Canary save→search check against the LIVE vault. Detects within seconds
|
|
6929
|
+
// when captureAndIndex returns success but data didn't land in the DB or
|
|
6930
|
+
// isn't findable via search (the 2026-04-19 silent-drift incident class).
|
|
6931
|
+
// kind='event' so the canary is never embedded — keeps the test stable
|
|
6932
|
+
// when embeddings are degraded.
|
|
6933
|
+
if (db) {
|
|
6934
|
+
let canaryEntry = null;
|
|
6935
|
+
let canaryStmts = null;
|
|
6936
|
+
let dbMod = null;
|
|
6937
|
+
try {
|
|
6938
|
+
dbMod = await import('@context-vault/core/db');
|
|
6939
|
+
const { embed } = await import('@context-vault/core/embed');
|
|
6940
|
+
const { captureAndIndex } = await import('@context-vault/core/capture');
|
|
6941
|
+
const { hybridSearch } = await import('@context-vault/core/search');
|
|
6942
|
+
|
|
6943
|
+
canaryStmts = dbMod.prepareStatements(db);
|
|
6944
|
+
|
|
6945
|
+
// Single alphanumeric token: stays one FTS term (no hyphen/underscore
|
|
6946
|
+
// splitting), uniquely identifies the canary in tag-search fallback,
|
|
6947
|
+
// and avoids collisions with anything else in the live vault.
|
|
6948
|
+
const canaryRand =
|
|
6949
|
+
Math.random().toString(36).slice(2, 10) + Math.random().toString(36).slice(2, 10);
|
|
6950
|
+
const canaryToken = `dcanary${canaryRand}`;
|
|
6951
|
+
|
|
6952
|
+
const ctx = {
|
|
6953
|
+
db,
|
|
6954
|
+
config,
|
|
6955
|
+
stmts: canaryStmts,
|
|
6956
|
+
embed,
|
|
6957
|
+
insertVec: (rowid, embedding) => dbMod.insertVec(canaryStmts, rowid, embedding),
|
|
6958
|
+
deleteVec: (rowid) => dbMod.deleteVec(canaryStmts, rowid),
|
|
6959
|
+
insertCtxVec: () => {},
|
|
6960
|
+
deleteCtxVec: () => {},
|
|
6961
|
+
};
|
|
6962
|
+
|
|
6963
|
+
canaryEntry = await captureAndIndex(ctx, {
|
|
6964
|
+
kind: 'event',
|
|
6965
|
+
title: 'doctor-canary',
|
|
6966
|
+
body: canaryToken,
|
|
6967
|
+
tags: [canaryToken, 'doctor-canary'],
|
|
6968
|
+
source: 'doctor',
|
|
6969
|
+
});
|
|
6970
|
+
|
|
6971
|
+
// Verify the persisted DB row matches what we saved before searching —
|
|
6972
|
+
// catches the silent-wedge case where captureAndIndex returns success
|
|
6973
|
+
// but the row never landed.
|
|
6974
|
+
const persisted = canaryStmts.getEntryById.get(canaryEntry.id);
|
|
6975
|
+
if (!persisted) {
|
|
6976
|
+
throw new Error('canary save returned success but row missing from DB');
|
|
6977
|
+
}
|
|
6978
|
+
if (persisted.body !== canaryToken) {
|
|
6979
|
+
throw new Error('canary persisted with wrong body');
|
|
6980
|
+
}
|
|
6981
|
+
|
|
6982
|
+
// kindFilter='event' scopes the search to events only. Events are not
|
|
6983
|
+
// embedded, so the vec lane is bypassed and the canary doesn't have to
|
|
6984
|
+
// out-rank thousands of recalled knowledge entries to make the page.
|
|
6985
|
+
const results = await hybridSearch(ctx, canaryToken, {
|
|
6986
|
+
kindFilter: 'event',
|
|
6987
|
+
limit: 10,
|
|
6988
|
+
});
|
|
6989
|
+
const found = results.find((r) => r.id === canaryEntry.id);
|
|
6990
|
+
if (!found) {
|
|
6991
|
+
throw new Error('canary saved but not returned by search');
|
|
6992
|
+
}
|
|
6993
|
+
if (found.body !== canaryToken) {
|
|
6994
|
+
throw new Error('canary found but body mismatch');
|
|
6995
|
+
}
|
|
6996
|
+
|
|
6997
|
+
console.log(` ${green('✓')} Save/search roundtrip`);
|
|
6998
|
+
} catch (e) {
|
|
6999
|
+
console.log(` ${red('✘')} Save/search roundtrip: ${e.message}`);
|
|
7000
|
+
allOk = false;
|
|
7001
|
+
} finally {
|
|
7002
|
+
if (canaryEntry) {
|
|
7003
|
+
try {
|
|
7004
|
+
if (existsSync(canaryEntry.filePath)) {
|
|
7005
|
+
unlinkSync(canaryEntry.filePath);
|
|
7006
|
+
}
|
|
7007
|
+
} catch {}
|
|
7008
|
+
if (canaryStmts && dbMod) {
|
|
7009
|
+
try {
|
|
7010
|
+
const rowidRow = canaryStmts.getRowid.get(canaryEntry.id);
|
|
7011
|
+
if (rowidRow?.rowid) {
|
|
7012
|
+
try {
|
|
7013
|
+
dbMod.deleteVec(canaryStmts, Number(rowidRow.rowid));
|
|
7014
|
+
} catch {}
|
|
7015
|
+
}
|
|
7016
|
+
} catch {}
|
|
7017
|
+
try {
|
|
7018
|
+
canaryStmts.deleteEntry.run(canaryEntry.id);
|
|
7019
|
+
} catch {}
|
|
7020
|
+
}
|
|
7021
|
+
}
|
|
7022
|
+
}
|
|
7023
|
+
}
|
|
7024
|
+
|
|
6560
7025
|
// ── DB/filesystem consistency ─────────────────────────────────────────
|
|
6561
7026
|
if (db && existsSync(config.vaultDir)) {
|
|
6562
7027
|
try {
|
|
@@ -7402,13 +7867,48 @@ async function runStats() {
|
|
|
7402
7867
|
await runStatsRecall({ resolveConfig, initDatabase, gatherRecallSummary });
|
|
7403
7868
|
} else if (sub === 'co-retrieval') {
|
|
7404
7869
|
await runStatsCoRetrieval({ resolveConfig, initDatabase, gatherCoRetrievalSummary });
|
|
7870
|
+
} else if (sub === 'counts') {
|
|
7871
|
+
await runStatsCounts({ resolveConfig, initDatabase });
|
|
7405
7872
|
} else {
|
|
7406
7873
|
console.error(red(` Unknown stats subcommand: ${sub}`));
|
|
7407
|
-
console.error(` Available: recall, co-retrieval`);
|
|
7874
|
+
console.error(` Available: recall, co-retrieval, counts`);
|
|
7408
7875
|
process.exit(1);
|
|
7409
7876
|
}
|
|
7410
7877
|
}
|
|
7411
7878
|
|
|
7879
|
+
async function runStatsCounts({ resolveConfig, initDatabase }) {
|
|
7880
|
+
const format = getFlag('--format') || 'plain';
|
|
7881
|
+
const config = resolveConfig();
|
|
7882
|
+
if (!config.vaultDirExists) {
|
|
7883
|
+
console.error(red('No vault found. Run: context-vault setup'));
|
|
7884
|
+
process.exit(1);
|
|
7885
|
+
}
|
|
7886
|
+
const db = await initDatabase(config.dbPath);
|
|
7887
|
+
try {
|
|
7888
|
+
const live = `superseded_by IS NULL AND (expires_at IS NULL OR expires_at > datetime('now'))`;
|
|
7889
|
+
const total = db.prepare(`SELECT COUNT(*) AS c FROM vault WHERE ${live}`).get()?.c ?? 0;
|
|
7890
|
+
const byKind = db
|
|
7891
|
+
.prepare(`SELECT kind AS name, COUNT(*) AS count FROM vault WHERE ${live} GROUP BY kind ORDER BY count DESC`)
|
|
7892
|
+
.all();
|
|
7893
|
+
const byCategory = db
|
|
7894
|
+
.prepare(`SELECT category AS name, COUNT(*) AS count FROM vault WHERE ${live} GROUP BY category ORDER BY count DESC`)
|
|
7895
|
+
.all();
|
|
7896
|
+
|
|
7897
|
+
if (format === 'json') {
|
|
7898
|
+
console.log(JSON.stringify({ total_entries: total, by_kind: byKind, by_category: byCategory }, null, 2));
|
|
7899
|
+
return;
|
|
7900
|
+
}
|
|
7901
|
+
|
|
7902
|
+
console.log(`\n ${bold('Vault counts')} ${dim(`total ${total}`)}\n`);
|
|
7903
|
+
console.log(` ${bold('By category')}`);
|
|
7904
|
+
for (const c of byCategory) console.log(` ${cyan((c.name || 'unknown').padEnd(12))} ${c.count}`);
|
|
7905
|
+
console.log(`\n ${bold('By kind')}`);
|
|
7906
|
+
for (const k of byKind) console.log(` ${cyan((k.name || 'unknown').padEnd(16))} ${k.count}`);
|
|
7907
|
+
} finally {
|
|
7908
|
+
db.close();
|
|
7909
|
+
}
|
|
7910
|
+
}
|
|
7911
|
+
|
|
7412
7912
|
async function runStatsRecall({ resolveConfig, initDatabase, gatherRecallSummary }) {
|
|
7413
7913
|
const config = resolveConfig();
|
|
7414
7914
|
let db;
|
|
@@ -9080,7 +9580,7 @@ async function main() {
|
|
|
9080
9580
|
|
|
9081
9581
|
if (flags.has('--help') || command === 'help') {
|
|
9082
9582
|
// Commands with their own --help handling: delegate to them
|
|
9083
|
-
const commandsWithHelp = new Set(['save', 'search', 'rules', 'hooks', 'team', 'remote', 'ingest-comms', 'gmail-bridge', 'slack-bridge', 'contacts']);
|
|
9583
|
+
const commandsWithHelp = new Set(['save', 'search', 'rules', 'hooks', 'team', 'remote', 'ingest-comms', 'gmail-bridge', 'slack-bridge', 'contacts', 'delete', 'get', 'buckets', 'dupes']);
|
|
9084
9584
|
if (!command || command === 'help' || !commandsWithHelp.has(command)) {
|
|
9085
9585
|
showHelp(flags.has('--all'));
|
|
9086
9586
|
return;
|
|
@@ -9193,6 +9693,18 @@ async function main() {
|
|
|
9193
9693
|
case 'prune':
|
|
9194
9694
|
await runPrune();
|
|
9195
9695
|
break;
|
|
9696
|
+
case 'delete':
|
|
9697
|
+
await runDelete();
|
|
9698
|
+
break;
|
|
9699
|
+
case 'get':
|
|
9700
|
+
await runGet();
|
|
9701
|
+
break;
|
|
9702
|
+
case 'buckets':
|
|
9703
|
+
await runBuckets();
|
|
9704
|
+
break;
|
|
9705
|
+
case 'dupes':
|
|
9706
|
+
await runDupes();
|
|
9707
|
+
break;
|
|
9196
9708
|
case 'status':
|
|
9197
9709
|
await runStatus();
|
|
9198
9710
|
break;
|
|
@@ -18,4 +18,5 @@ export { startWatcher } from './watch.js';
|
|
|
18
18
|
export type { WatcherOptions, VaultWatcher } from './watch.js';
|
|
19
19
|
export { findDuplicates, mergeEntries, computeDecayScores } from './consolidation.js';
|
|
20
20
|
export type { DuplicateGroup, MergeResult, DecayScore } from './consolidation.js';
|
|
21
|
+
export { assembleContext } from './assemble.js';
|
|
21
22
|
//# sourceMappingURL=main.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AACA,YAAY,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,eAAe,EACf,YAAY,EACZ,OAAO,EACP,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,OAAO,EACP,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,EACL,IAAI,EACJ,OAAO,EACP,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,GACR,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGrF,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/D,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG5E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG9E,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGhF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtF,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AACA,YAAY,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,eAAe,EACf,YAAY,EACZ,OAAO,EACP,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,OAAO,EACP,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,EACL,IAAI,EACJ,OAAO,EACP,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,GACR,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGrF,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/D,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG5E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG9E,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGhF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtF,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGlF,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -30,4 +30,6 @@ export { htmlToMarkdown, extractHtmlContent, ingestUrl } from './ingest-url.js';
|
|
|
30
30
|
export { startWatcher } from './watch.js';
|
|
31
31
|
// Consolidation
|
|
32
32
|
export { findDuplicates, mergeEntries, computeDecayScores } from './consolidation.js';
|
|
33
|
+
// Assemble
|
|
34
|
+
export { assembleContext } from './assemble.js';
|
|
33
35
|
//# sourceMappingURL=main.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAoBA,YAAY;AACZ,OAAO,EACL,OAAO,EACP,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,aAAa;AACb,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvD,QAAQ;AACR,OAAO,EACL,IAAI,EACJ,OAAO,EACP,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,GACR,MAAM,YAAY,CAAC;AAEpB,cAAc;AACd,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,WAAW;AACX,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB,aAAa;AACb,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErF,+BAA+B;AAC/B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/D,oBAAoB;AACpB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,UAAU;AACV,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE5E,WAAW;AACX,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAG7D,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEhF,QAAQ;AACR,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,gBAAgB;AAChB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAoBA,YAAY;AACZ,OAAO,EACL,OAAO,EACP,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,aAAa;AACb,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvD,QAAQ;AACR,OAAO,EACL,IAAI,EACJ,OAAO,EACP,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,GACR,MAAM,YAAY,CAAC;AAEpB,cAAc;AACd,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,WAAW;AACX,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB,aAAa;AACb,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErF,+BAA+B;AAC/B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/D,oBAAoB;AACpB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,UAAU;AACV,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE5E,WAAW;AACX,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAG7D,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEhF,QAAQ;AACR,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,gBAAgB;AAChB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAGtF,WAAW;AACX,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -9,6 +9,7 @@ export declare function dotProduct(a: Float32Array, b: Float32Array): number;
|
|
|
9
9
|
export declare function buildFtsQuery(query: string): string | null;
|
|
10
10
|
export declare function recencyBoost(createdAt: string, category: string, decayDays?: number): number;
|
|
11
11
|
export declare function recallBoost(recallCount: number, lastRecalledAt: string | null): number;
|
|
12
|
+
export declare function kindBoost(kind: string | null | undefined): number;
|
|
12
13
|
export declare function buildFilterClauses({ categoryFilter, excludeEvents, since, until, includeSuperseeded, includeEphemeral, }: {
|
|
13
14
|
categoryFilter?: string | null;
|
|
14
15
|
excludeEvents?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAc,MAAM,YAAY,CAAC;AAMnF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,MAAM,CAgBR;AAKD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,SAAS,SAAO,GAAG,MAAM,CAIhG;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAInE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY1D;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,SAAK,GAAG,MAAM,CAIxF;AAED,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAUtF;AAED,wBAAgB,kBAAkB,CAAC,EACjC,cAAc,EACd,aAAqB,EACrB,KAAK,EACL,KAAK,EACL,kBAA0B,EAC1B,gBAAwB,GACzB,EAAE;IACD,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,CAAA;CAAE,CA2B5D;AAED,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EAAE,EAAE,EACvB,CAAC,GAAE,MAAc,GAChB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CASrB;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,YAAY,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|