@voidwire/lore 0.7.1 → 0.8.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/cli.ts CHANGED
@@ -56,6 +56,7 @@ import {
56
56
  type ObservationSubtype,
57
57
  type ObservationConfidence,
58
58
  } from "./index";
59
+ import { isValidLoreType, LORE_TYPES } from "./lib/types";
59
60
 
60
61
  // ============================================================================
61
62
  // Argument Parsing
@@ -204,6 +205,17 @@ async function handleSearch(args: string[]): Promise<void> {
204
205
  const limit = parsed.has("limit") ? parseInt(parsed.get("limit")!, 10) : 20;
205
206
  const since = parsed.get("since");
206
207
  const project = parsed.get("project");
208
+ const type = parseList(parsed.get("type"));
209
+
210
+ // Validate type values against LoreType enum
211
+ if (type) {
212
+ const invalid = type.filter((t) => !isValidLoreType(t));
213
+ if (invalid.length > 0) {
214
+ fail(
215
+ `Invalid type: ${invalid.join(", ")}. Valid types: ${LORE_TYPES.join(", ")}`,
216
+ );
217
+ }
218
+ }
207
219
 
208
220
  // Handle prismis passthrough
209
221
  if (source === "prismis") {
@@ -250,7 +262,7 @@ async function handleSearch(args: string[]): Promise<void> {
250
262
  // FTS5 path (explicit --exact only)
251
263
  if (exact) {
252
264
  try {
253
- const results = search(query, { source, limit, since });
265
+ const results = search(query, { source, limit, since, type });
254
266
  output({
255
267
  success: true,
256
268
  results,
@@ -278,7 +290,12 @@ async function handleSearch(args: string[]): Promise<void> {
278
290
  // Semantic-only path (explicit --semantic)
279
291
  if (semanticOnly) {
280
292
  try {
281
- const results = await semanticSearch(query, { source, limit, project });
293
+ const results = await semanticSearch(query, {
294
+ source,
295
+ limit,
296
+ project,
297
+ type,
298
+ });
282
299
 
283
300
  if (brief) {
284
301
  console.log(formatBriefSearch(results));
@@ -308,6 +325,7 @@ async function handleSearch(args: string[]): Promise<void> {
308
325
  limit,
309
326
  project,
310
327
  since,
328
+ type,
311
329
  });
312
330
 
313
331
  if (brief) {
@@ -817,6 +835,7 @@ Usage:
817
835
 
818
836
  Search Options:
819
837
  --exact Use FTS5 text search (bypasses semantic search)
838
+ --type <types> Filter by knowledge type (gotcha, decision, learning, etc.)
820
839
  --limit <n> Maximum results (default: 20)
821
840
  --project <name> Filter results by project
822
841
  --brief Compact output (titles only)
@@ -864,6 +883,8 @@ Capture Types:
864
883
 
865
884
  Examples:
866
885
  lore search "authentication"
886
+ lore search --type=gotcha "sable"
887
+ lore search --type=gotcha,decision "lore"
867
888
  lore search blogs "typescript patterns"
868
889
  lore sources
869
890
  lore list development
@@ -888,6 +909,10 @@ Search Modes:
888
909
  --semantic Vector search only
889
910
 
890
911
  Options:
912
+ --type <types> Filter by knowledge type (pre-filters before search)
913
+ Comma-separated: --type=gotcha,decision
914
+ Valid: gotcha, decision, pattern, learning, preference,
915
+ term, style, teaching, task, todo, idea
891
916
  --limit <n> Maximum results (default: 20)
892
917
  --project <name> Filter results by project/topic
893
918
  --brief Compact output (titles only)
@@ -919,6 +944,8 @@ See also:
919
944
 
920
945
  Examples:
921
946
  lore search "authentication" # hybrid (default)
947
+ lore search --type=gotcha "sable" # filter by type
948
+ lore search --type=gotcha,decision "lore" # multiple types
922
949
  lore search --exact "def process_data" # keyword only
923
950
  lore search --semantic "login flow concepts" # vector only
924
951
  lore search blogs "typescript patterns"
package/lib/search.ts CHANGED
@@ -22,6 +22,7 @@ export interface SearchOptions {
22
22
  source?: string;
23
23
  limit?: number;
24
24
  since?: string;
25
+ type?: string | string[];
25
26
  }
26
27
 
27
28
  function getDatabasePath(): string {
@@ -73,6 +74,18 @@ export function search(
73
74
  params.push(options.source);
74
75
  }
75
76
 
77
+ if (options.type) {
78
+ const types = Array.isArray(options.type) ? options.type : [options.type];
79
+ const typeClauses = types.map(
80
+ () =>
81
+ "(json_extract(metadata, '$.type') = ? OR json_extract(metadata, '$.subtype') = ?)",
82
+ );
83
+ conditions.push(`(${typeClauses.join(" OR ")})`);
84
+ types.forEach((t) => {
85
+ params.push(t, t);
86
+ });
87
+ }
88
+
76
89
  if (options.since) {
77
90
  conditions.push(
78
91
  "json_extract(metadata, '$.date') IS NOT NULL AND json_extract(metadata, '$.date') != 'unknown' AND json_extract(metadata, '$.date') >= ?",
package/lib/semantic.ts CHANGED
@@ -25,6 +25,7 @@ export interface SemanticSearchOptions {
25
25
  source?: string;
26
26
  limit?: number;
27
27
  project?: string;
28
+ type?: string | string[];
28
29
  }
29
30
 
30
31
  /**
@@ -230,6 +231,13 @@ export async function semanticSearch(
230
231
  params.push(options.project);
231
232
  }
232
233
 
234
+ if (options.type) {
235
+ const types = Array.isArray(options.type) ? options.type : [options.type];
236
+ const placeholders = types.map(() => "?").join(", ");
237
+ conditions.push(`e.type IN (${placeholders})`);
238
+ params.push(...types);
239
+ }
240
+
233
241
  sql = `
234
242
  SELECT
235
243
  s.rowid,
@@ -274,6 +282,7 @@ export interface HybridSearchOptions {
274
282
  limit?: number;
275
283
  project?: string;
276
284
  since?: string;
285
+ type?: string | string[];
277
286
  vectorWeight?: number;
278
287
  textWeight?: number;
279
288
  }
@@ -325,12 +334,14 @@ export async function hybridSearch(
325
334
  source: options.source,
326
335
  limit: fetchLimit,
327
336
  project: options.project,
337
+ type: options.type,
328
338
  }),
329
339
  Promise.resolve(
330
340
  keywordSearch(query, {
331
341
  source: options.source,
332
342
  limit: fetchLimit,
333
343
  since: options.since,
344
+ type: options.type,
334
345
  }),
335
346
  ),
336
347
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voidwire/lore",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Unified knowledge CLI - Search, list, and capture your indexed knowledge",
5
5
  "type": "module",
6
6
  "main": "./index.ts",