agent-knowledge 1.0.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.
Files changed (130) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/LICENSE +21 -0
  3. package/README.md +191 -0
  4. package/dist/dashboard.d.ts +4 -0
  5. package/dist/dashboard.d.ts.map +1 -0
  6. package/dist/dashboard.js +434 -0
  7. package/dist/dashboard.js.map +1 -0
  8. package/dist/embeddings/claude.d.ts +21 -0
  9. package/dist/embeddings/claude.d.ts.map +1 -0
  10. package/dist/embeddings/claude.js +84 -0
  11. package/dist/embeddings/claude.js.map +1 -0
  12. package/dist/embeddings/factory.d.ts +9 -0
  13. package/dist/embeddings/factory.d.ts.map +1 -0
  14. package/dist/embeddings/factory.js +60 -0
  15. package/dist/embeddings/factory.js.map +1 -0
  16. package/dist/embeddings/gemini.d.ts +21 -0
  17. package/dist/embeddings/gemini.d.ts.map +1 -0
  18. package/dist/embeddings/gemini.js +86 -0
  19. package/dist/embeddings/gemini.js.map +1 -0
  20. package/dist/embeddings/index.d.ts +4 -0
  21. package/dist/embeddings/index.d.ts.map +1 -0
  22. package/dist/embeddings/index.js +3 -0
  23. package/dist/embeddings/index.js.map +1 -0
  24. package/dist/embeddings/local.d.ts +20 -0
  25. package/dist/embeddings/local.d.ts.map +1 -0
  26. package/dist/embeddings/local.js +73 -0
  27. package/dist/embeddings/local.js.map +1 -0
  28. package/dist/embeddings/openai.d.ts +20 -0
  29. package/dist/embeddings/openai.d.ts.map +1 -0
  30. package/dist/embeddings/openai.js +84 -0
  31. package/dist/embeddings/openai.js.map +1 -0
  32. package/dist/embeddings/types.d.ts +39 -0
  33. package/dist/embeddings/types.d.ts.map +1 -0
  34. package/dist/embeddings/types.js +12 -0
  35. package/dist/embeddings/types.js.map +1 -0
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +18 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/knowledge/distill.d.ts +27 -0
  41. package/dist/knowledge/distill.d.ts.map +1 -0
  42. package/dist/knowledge/distill.js +407 -0
  43. package/dist/knowledge/distill.js.map +1 -0
  44. package/dist/knowledge/git.d.ts +30 -0
  45. package/dist/knowledge/git.d.ts.map +1 -0
  46. package/dist/knowledge/git.js +228 -0
  47. package/dist/knowledge/git.js.map +1 -0
  48. package/dist/knowledge/search.d.ts +20 -0
  49. package/dist/knowledge/search.d.ts.map +1 -0
  50. package/dist/knowledge/search.js +72 -0
  51. package/dist/knowledge/search.js.map +1 -0
  52. package/dist/knowledge/store.d.ts +47 -0
  53. package/dist/knowledge/store.d.ts.map +1 -0
  54. package/dist/knowledge/store.js +173 -0
  55. package/dist/knowledge/store.js.map +1 -0
  56. package/dist/search/excerpt.d.ts +12 -0
  57. package/dist/search/excerpt.d.ts.map +1 -0
  58. package/dist/search/excerpt.js +28 -0
  59. package/dist/search/excerpt.js.map +1 -0
  60. package/dist/search/fuzzy.d.ts +15 -0
  61. package/dist/search/fuzzy.d.ts.map +1 -0
  62. package/dist/search/fuzzy.js +81 -0
  63. package/dist/search/fuzzy.js.map +1 -0
  64. package/dist/search/tfidf.d.ts +19 -0
  65. package/dist/search/tfidf.d.ts.map +1 -0
  66. package/dist/search/tfidf.js +200 -0
  67. package/dist/search/tfidf.js.map +1 -0
  68. package/dist/search/types.d.ts +19 -0
  69. package/dist/search/types.d.ts.map +1 -0
  70. package/dist/search/types.js +2 -0
  71. package/dist/search/types.js.map +1 -0
  72. package/dist/server.d.ts +3 -0
  73. package/dist/server.d.ts.map +1 -0
  74. package/dist/server.js +518 -0
  75. package/dist/server.js.map +1 -0
  76. package/dist/sessions/indexer.d.ts +15 -0
  77. package/dist/sessions/indexer.d.ts.map +1 -0
  78. package/dist/sessions/indexer.js +182 -0
  79. package/dist/sessions/indexer.js.map +1 -0
  80. package/dist/sessions/parser.d.ts +58 -0
  81. package/dist/sessions/parser.d.ts.map +1 -0
  82. package/dist/sessions/parser.js +142 -0
  83. package/dist/sessions/parser.js.map +1 -0
  84. package/dist/sessions/scopes.d.ts +16 -0
  85. package/dist/sessions/scopes.d.ts.map +1 -0
  86. package/dist/sessions/scopes.js +153 -0
  87. package/dist/sessions/scopes.js.map +1 -0
  88. package/dist/sessions/search.d.ts +26 -0
  89. package/dist/sessions/search.d.ts.map +1 -0
  90. package/dist/sessions/search.js +256 -0
  91. package/dist/sessions/search.js.map +1 -0
  92. package/dist/sessions/summary.d.ts +28 -0
  93. package/dist/sessions/summary.d.ts.map +1 -0
  94. package/dist/sessions/summary.js +135 -0
  95. package/dist/sessions/summary.js.map +1 -0
  96. package/dist/types.d.ts +26 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +109 -0
  99. package/dist/types.js.map +1 -0
  100. package/dist/ui/app.js +1029 -0
  101. package/dist/ui/index.html +373 -0
  102. package/dist/ui/styles.css +1508 -0
  103. package/dist/ui/ui/app.js +811 -0
  104. package/dist/ui/ui/index.html +300 -0
  105. package/dist/ui/ui/styles.css +1154 -0
  106. package/dist/validate.d.ts +21 -0
  107. package/dist/validate.d.ts.map +1 -0
  108. package/dist/validate.js +86 -0
  109. package/dist/validate.js.map +1 -0
  110. package/dist/vectorstore/chunker.d.ts +48 -0
  111. package/dist/vectorstore/chunker.d.ts.map +1 -0
  112. package/dist/vectorstore/chunker.js +165 -0
  113. package/dist/vectorstore/chunker.js.map +1 -0
  114. package/dist/vectorstore/index.d.ts +5 -0
  115. package/dist/vectorstore/index.d.ts.map +1 -0
  116. package/dist/vectorstore/index.js +3 -0
  117. package/dist/vectorstore/index.js.map +1 -0
  118. package/dist/vectorstore/store.d.ts +139 -0
  119. package/dist/vectorstore/store.d.ts.map +1 -0
  120. package/dist/vectorstore/store.js +500 -0
  121. package/dist/vectorstore/store.js.map +1 -0
  122. package/dist/version.d.ts +2 -0
  123. package/dist/version.d.ts.map +1 -0
  124. package/dist/version.js +2 -0
  125. package/dist/version.js.map +1 -0
  126. package/docs/ARCHITECTURE.md +244 -0
  127. package/docs/DASHBOARD.md +133 -0
  128. package/docs/SETUP.md +178 -0
  129. package/package.json +92 -0
  130. package/scripts/copy-ui.js +6 -0
@@ -0,0 +1,182 @@
1
+ import { getEmbeddingProvider } from '../embeddings/index.js';
2
+ import { VectorStore, chunkKnowledge, chunkSession } from '../vectorstore/index.js';
3
+ import { listEntries, readEntry } from '../knowledge/store.js';
4
+ import { getProjectDirs, getSessionFiles, parseSessionFile, extractMessages, getSessionMeta, } from './parser.js';
5
+ import { getConfig } from '../types.js';
6
+ import { distillSessions } from '../knowledge/distill.js';
7
+ let _vectorStore = null;
8
+ function getVectorStore() {
9
+ if (!_vectorStore) {
10
+ _vectorStore = new VectorStore();
11
+ }
12
+ return _vectorStore;
13
+ }
14
+ /**
15
+ * Index a single knowledge entry into the vector store.
16
+ */
17
+ export async function indexKnowledgeEntry(path, content) {
18
+ const provider = await getEmbeddingProvider();
19
+ if (!provider)
20
+ return;
21
+ const store = getVectorStore();
22
+ const chunks = chunkKnowledge(content);
23
+ if (chunks.length === 0)
24
+ return;
25
+ const texts = chunks.map((c) => c.text);
26
+ const embeddings = await provider.embed(texts);
27
+ const entries = chunks.map((chunk, i) => ({
28
+ id: `knowledge:${path}:${chunk.index}`,
29
+ source: 'knowledge',
30
+ sourceId: path,
31
+ chunkIndex: chunk.index,
32
+ chunkText: chunk.text,
33
+ provider: provider.name,
34
+ dimensions: provider.dimensions,
35
+ embedding: embeddings[i],
36
+ metadata: chunk.metadata,
37
+ }));
38
+ store.upsert(entries);
39
+ }
40
+ /**
41
+ * Index session messages into the vector store.
42
+ */
43
+ export async function indexSessionMessages(sessionId, messages) {
44
+ const provider = await getEmbeddingProvider();
45
+ if (!provider)
46
+ return;
47
+ const store = getVectorStore();
48
+ const chunks = chunkSession(messages);
49
+ if (chunks.length === 0)
50
+ return;
51
+ const texts = chunks.map((c) => c.text);
52
+ const embeddings = await provider.embed(texts);
53
+ const entries = chunks.map((chunk, i) => ({
54
+ id: `session:${sessionId}:${chunk.index}`,
55
+ source: 'session',
56
+ sourceId: sessionId,
57
+ chunkIndex: chunk.index,
58
+ chunkText: chunk.text,
59
+ provider: provider.name,
60
+ dimensions: provider.dimensions,
61
+ embedding: embeddings[i],
62
+ metadata: chunk.metadata,
63
+ }));
64
+ store.upsert(entries);
65
+ }
66
+ /**
67
+ * Background indexer that embeds all unindexed knowledge entries and session
68
+ * messages. Runs non-blocking after server startup.
69
+ */
70
+ export async function backgroundIndex() {
71
+ const provider = await getEmbeddingProvider();
72
+ if (!provider) {
73
+ console.error('[knowledge] No embedding provider available, skipping background index');
74
+ return;
75
+ }
76
+ const store = getVectorStore();
77
+ const wiped = store.setProvider(provider.name, provider.dimensions);
78
+ if (wiped) {
79
+ console.error('[knowledge] Embedding provider changed, wiped existing vectors');
80
+ }
81
+ const config = getConfig();
82
+ // ── Index knowledge entries ─────────────────────────────────────────────
83
+ try {
84
+ const entries = listEntries(config.memoryDir);
85
+ let indexed = 0;
86
+ const total = entries.length;
87
+ for (const entry of entries) {
88
+ try {
89
+ if (store.hasEmbeddings(entry.path)) {
90
+ indexed++;
91
+ continue;
92
+ }
93
+ const { content } = readEntry(config.memoryDir, entry.path);
94
+ await indexKnowledgeEntry(entry.path, content);
95
+ indexed++;
96
+ if (indexed % 10 === 0 || indexed === total) {
97
+ console.error(`[knowledge] Indexed ${indexed}/${total} knowledge entries...`);
98
+ }
99
+ await new Promise((r) => setTimeout(r, 100));
100
+ }
101
+ catch (err) {
102
+ console.error(`[knowledge] Failed to index knowledge entry ${entry.path}: ${err}`);
103
+ }
104
+ }
105
+ if (total > 0) {
106
+ console.error(`[knowledge] Knowledge indexing complete: ${indexed}/${total}`);
107
+ }
108
+ }
109
+ catch (err) {
110
+ console.error(`[knowledge] Knowledge indexing failed: ${err}`);
111
+ }
112
+ // ── Index session messages ──────────────────────────────────────────────
113
+ try {
114
+ const projects = getProjectDirs();
115
+ let totalSessions = 0;
116
+ let indexedSessions = 0;
117
+ for (const proj of projects) {
118
+ const sessions = getSessionFiles(proj.path);
119
+ totalSessions += sessions.length;
120
+ }
121
+ for (const proj of projects) {
122
+ const sessions = getSessionFiles(proj.path);
123
+ for (const sess of sessions) {
124
+ try {
125
+ if (store.hasEmbeddings(sess.id)) {
126
+ indexedSessions++;
127
+ continue;
128
+ }
129
+ const entries = parseSessionFile(sess.file);
130
+ if (entries.length === 0) {
131
+ indexedSessions++;
132
+ continue;
133
+ }
134
+ const meta = getSessionMeta(entries);
135
+ const messages = extractMessages(entries);
136
+ const sessionMessages = messages.map((m) => ({
137
+ role: m.role,
138
+ text: m.content,
139
+ timestamp: m.timestamp ?? meta.startTime,
140
+ sessionId: sess.id,
141
+ }));
142
+ await indexSessionMessages(sess.id, sessionMessages);
143
+ indexedSessions++;
144
+ if (indexedSessions % 20 === 0 || indexedSessions === totalSessions) {
145
+ console.error(`[knowledge] Indexed ${indexedSessions}/${totalSessions} sessions...`);
146
+ }
147
+ await new Promise((r) => setTimeout(r, 100));
148
+ }
149
+ catch (err) {
150
+ console.error(`[knowledge] Failed to index session ${sess.id}: ${err}`);
151
+ indexedSessions++;
152
+ }
153
+ }
154
+ }
155
+ if (totalSessions > 0) {
156
+ console.error(`[knowledge] Session indexing complete: ${indexedSessions}/${totalSessions}`);
157
+ }
158
+ }
159
+ catch (err) {
160
+ console.error(`[knowledge] Session indexing failed: ${err}`);
161
+ }
162
+ console.error('[knowledge] Background indexing complete');
163
+ // ── Auto-distill session insights into knowledge base ───────────────────
164
+ const config2 = getConfig();
165
+ if (config2.autoDistill) {
166
+ try {
167
+ console.error('[knowledge] Starting auto-distillation...');
168
+ const result = await distillSessions();
169
+ const total = result.updated.length + result.created.length;
170
+ if (total > 0) {
171
+ console.error(`[knowledge] Distilled ${total} project(s): ${result.updated.length} updated, ${result.created.length} created`);
172
+ }
173
+ else {
174
+ console.error('[knowledge] No new sessions to distill');
175
+ }
176
+ }
177
+ catch (err) {
178
+ console.error(`[knowledge] Auto-distillation failed: ${err}`);
179
+ }
180
+ }
181
+ }
182
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../src/sessions/indexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ export interface SessionEntry {
2
+ type: string;
3
+ timestamp?: string;
4
+ sessionId?: string;
5
+ cwd?: string;
6
+ gitBranch?: string;
7
+ message?: {
8
+ role?: string;
9
+ content: unknown;
10
+ };
11
+ content?: string;
12
+ }
13
+ export interface SessionMessage {
14
+ role: 'user' | 'assistant' | 'tool_use' | 'tool_result';
15
+ content: string;
16
+ timestamp: string | null;
17
+ }
18
+ export interface SessionMeta {
19
+ startTime: string;
20
+ endTime: string;
21
+ cwd: string;
22
+ branch: string;
23
+ messageCount: number;
24
+ userMessageCount: number;
25
+ preview: string;
26
+ }
27
+ /**
28
+ * Parse a JSONL session file into an array of entries.
29
+ * Malformed lines are silently skipped.
30
+ */
31
+ export declare function parseSessionFile(filePath: string): SessionEntry[];
32
+ /**
33
+ * Extract structured messages from raw session entries.
34
+ *
35
+ * - User messages: entry.message.content (string or stringified)
36
+ * - Assistant messages: text parts from content array
37
+ * - Tool use / result: content truncated to 500 chars
38
+ */
39
+ export declare function extractMessages(entries: SessionEntry[]): SessionMessage[];
40
+ /**
41
+ * Extract metadata from session entries (first/last entry, counts, preview).
42
+ */
43
+ export declare function getSessionMeta(entries: SessionEntry[]): SessionMeta;
44
+ /**
45
+ * Discover all project directories under ~/.claude/projects/
46
+ */
47
+ export declare function getProjectDirs(): Array<{
48
+ name: string;
49
+ path: string;
50
+ }>;
51
+ /**
52
+ * List all .jsonl session files in a given project directory.
53
+ */
54
+ export declare function getSessionFiles(projectPath: string): Array<{
55
+ id: string;
56
+ file: string;
57
+ }>;
58
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/sessions/parser.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,aAAa,CAAC;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAoBjE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAuDzE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,WAAW,CA2BnE;AAID;;GAEG;AACH,wBAAgB,cAAc,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAWtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAUxF"}
@@ -0,0 +1,142 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { getConfig } from '../types.js';
4
+ // ── Parsing ─────────────────────────────────────────────────────────────────
5
+ /**
6
+ * Parse a JSONL session file into an array of entries.
7
+ * Malformed lines are silently skipped.
8
+ */
9
+ export function parseSessionFile(filePath) {
10
+ let raw;
11
+ try {
12
+ raw = fs.readFileSync(filePath, 'utf-8');
13
+ }
14
+ catch {
15
+ return [];
16
+ }
17
+ const lines = raw.split('\n').filter((l) => l.trim());
18
+ const entries = [];
19
+ for (const line of lines) {
20
+ try {
21
+ entries.push(JSON.parse(line));
22
+ }
23
+ catch {
24
+ // skip malformed lines gracefully
25
+ }
26
+ }
27
+ return entries;
28
+ }
29
+ /**
30
+ * Extract structured messages from raw session entries.
31
+ *
32
+ * - User messages: entry.message.content (string or stringified)
33
+ * - Assistant messages: text parts from content array
34
+ * - Tool use / result: content truncated to 500 chars
35
+ */
36
+ export function extractMessages(entries) {
37
+ const messages = [];
38
+ for (const entry of entries) {
39
+ const ts = entry.timestamp ?? null;
40
+ if (entry.type === 'user' && entry.message?.content) {
41
+ const content = typeof entry.message.content === 'string'
42
+ ? entry.message.content
43
+ : JSON.stringify(entry.message.content);
44
+ messages.push({ role: 'user', content, timestamp: ts });
45
+ }
46
+ else if (entry.type === 'assistant' && entry.message?.content) {
47
+ const parts = Array.isArray(entry.message.content)
48
+ ? entry.message.content
49
+ : [entry.message.content];
50
+ const textParts = parts
51
+ .filter((p) => typeof p === 'string' ||
52
+ (typeof p === 'object' &&
53
+ p !== null &&
54
+ 'type' in p &&
55
+ p.type === 'text'))
56
+ .map((p) => (typeof p === 'string' ? p : p.text))
57
+ .filter(Boolean);
58
+ if (textParts.length > 0) {
59
+ messages.push({
60
+ role: 'assistant',
61
+ content: textParts.join('\n'),
62
+ timestamp: ts,
63
+ });
64
+ }
65
+ }
66
+ else if (entry.type === 'tool_use' || entry.type === 'tool_result') {
67
+ const content = typeof entry.content === 'string'
68
+ ? entry.content
69
+ : typeof entry.message?.content === 'string'
70
+ ? entry.message.content
71
+ : null;
72
+ if (content) {
73
+ messages.push({
74
+ role: entry.type,
75
+ content: content.substring(0, 500),
76
+ timestamp: ts,
77
+ });
78
+ }
79
+ }
80
+ }
81
+ return messages;
82
+ }
83
+ /**
84
+ * Extract metadata from session entries (first/last entry, counts, preview).
85
+ */
86
+ export function getSessionMeta(entries) {
87
+ if (entries.length === 0) {
88
+ return {
89
+ startTime: 'unknown',
90
+ endTime: 'unknown',
91
+ cwd: 'unknown',
92
+ branch: 'unknown',
93
+ messageCount: 0,
94
+ userMessageCount: 0,
95
+ preview: 'N/A',
96
+ };
97
+ }
98
+ const first = entries[0];
99
+ const last = entries[entries.length - 1];
100
+ const userMessages = entries.filter((e) => e.type === 'user');
101
+ const firstUserMsg = userMessages[0]?.message?.content;
102
+ return {
103
+ startTime: first?.timestamp ?? 'unknown',
104
+ endTime: last?.timestamp ?? 'unknown',
105
+ cwd: first?.cwd ?? 'unknown',
106
+ branch: first?.gitBranch ?? 'unknown',
107
+ messageCount: entries.length,
108
+ userMessageCount: userMessages.length,
109
+ preview: typeof firstUserMsg === 'string' ? firstUserMsg.substring(0, 200) : 'N/A',
110
+ };
111
+ }
112
+ // ── Discovery ───────────────────────────────────────────────────────────────
113
+ /**
114
+ * Discover all project directories under ~/.claude/projects/
115
+ */
116
+ export function getProjectDirs() {
117
+ const { projectsDir } = getConfig();
118
+ if (!fs.existsSync(projectsDir))
119
+ return [];
120
+ return fs
121
+ .readdirSync(projectsDir, { withFileTypes: true })
122
+ .filter((d) => d.isDirectory())
123
+ .map((d) => ({
124
+ name: d.name,
125
+ path: path.join(projectsDir, d.name),
126
+ }));
127
+ }
128
+ /**
129
+ * List all .jsonl session files in a given project directory.
130
+ */
131
+ export function getSessionFiles(projectPath) {
132
+ if (!fs.existsSync(projectPath))
133
+ return [];
134
+ return fs
135
+ .readdirSync(projectPath)
136
+ .filter((f) => f.endsWith('.jsonl'))
137
+ .map((f) => ({
138
+ id: f.replace('.jsonl', ''),
139
+ file: path.join(projectPath, f),
140
+ }));
141
+ }
142
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/sessions/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { SearchResult } from '../search/types.js';
2
+ export type SearchScope = 'errors' | 'plans' | 'configs' | 'tools' | 'files' | 'decisions' | 'all';
3
+ export interface ScopedSearchOptions {
4
+ project?: string;
5
+ maxResults?: number;
6
+ semantic?: boolean;
7
+ }
8
+ /**
9
+ * Perform a search scoped to a specific category of content.
10
+ *
11
+ * Each scope pre-filters messages by role/content patterns, then applies TF-IDF
12
+ * ranking with the user query on the remaining messages. When semantic search
13
+ * is available, blends vector similarity with TF-IDF scores.
14
+ */
15
+ export declare function scopedSearch(scope: SearchScope, query: string, options?: ScopedSearchOptions): Promise<SearchResult[]>;
16
+ //# sourceMappingURL=scopes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../../src/sessions/scopes.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAOvD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,GAAG,KAAK,CAAC;AAEnG,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA8BD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,YAAY,EAAE,CAAC,CAuIzB"}
@@ -0,0 +1,153 @@
1
+ import { getProjectDirs, getSessionFiles, parseSessionFile, extractMessages, getSessionMeta, } from './parser.js';
2
+ import { TfIdfIndex, recencyDecay } from '../search/tfidf.js';
3
+ import { buildExcerpt } from '../search/excerpt.js';
4
+ import { getEmbeddingProvider } from '../embeddings/index.js';
5
+ import { VectorStore } from '../vectorstore/index.js';
6
+ import { getConfig } from '../types.js';
7
+ // ── Lazy VectorStore singleton ──────────────────────────────────────────────
8
+ let _vectorStore = null;
9
+ function getVectorStore() {
10
+ if (!_vectorStore) {
11
+ _vectorStore = new VectorStore();
12
+ }
13
+ return _vectorStore;
14
+ }
15
+ // ── Scope pattern definitions ───────────────────────────────────────────────
16
+ const SCOPE_PATTERNS = {
17
+ errors: /\b(error|exception|failed|failure|crash|stack\s*trace|ENOENT|EACCES|EPERM|ECONNREFUSED|TypeError|ReferenceError|SyntaxError|FATAL|panic|segfault|abort|unhandled|rejected)\b/i,
18
+ plans: /\b(plan|step\s+\d|phase|approach|strategy|TODO|FIXME|architecture|roadmap|milestone|objective|next\s+steps|action\s+items)\b/i,
19
+ configs: /\b(config|settings|\.env|\.json|\.yaml|\.yml|\.toml|tsconfig|package\.json|webpack|vite|eslint|prettier|docker|compose|nginx)\b/i,
20
+ files: /(?:src\/|lib\/|dist\/|\.ts\b|\.js\b|\.py\b|\.rs\b|\.go\b|\.java\b|\.vue\b|\.tsx\b|\.jsx\b|\/[\w.-]+\/|created|modified|deleted|renamed|moved)\b/i,
21
+ decisions: /\b(decided|chose|chosen|because|tradeoff|trade-off|instead\s+of|going\s+with|opted\s+for|rationale|reasoning|prefer|alternative|pros\s+and\s+cons|conclusion)\b/i,
22
+ };
23
+ // ── Scoped search ───────────────────────────────────────────────────────────
24
+ /**
25
+ * Perform a search scoped to a specific category of content.
26
+ *
27
+ * Each scope pre-filters messages by role/content patterns, then applies TF-IDF
28
+ * ranking with the user query on the remaining messages. When semantic search
29
+ * is available, blends vector similarity with TF-IDF scores.
30
+ */
31
+ export async function scopedSearch(scope, query, options = {}) {
32
+ const { project, maxResults = 20, semantic = true } = options;
33
+ const projects = getProjectDirs().filter((p) => !project || p.name.toLowerCase().includes(project.toLowerCase()));
34
+ const index = new TfIdfIndex();
35
+ const docMap = new Map();
36
+ let docCounter = 0;
37
+ for (const proj of projects) {
38
+ const sessions = getSessionFiles(proj.path);
39
+ for (const sess of sessions) {
40
+ try {
41
+ const entries = parseSessionFile(sess.file);
42
+ if (entries.length === 0)
43
+ continue;
44
+ const meta = getSessionMeta(entries);
45
+ const messages = extractMessages(entries);
46
+ const filtered = filterByScope(scope, messages);
47
+ for (const msg of filtered) {
48
+ const docId = `doc_${docCounter++}`;
49
+ index.addDocument(docId, msg.content);
50
+ docMap.set(docId, {
51
+ project: proj.name,
52
+ sessionId: sess.id,
53
+ role: msg.role,
54
+ timestamp: msg.timestamp,
55
+ content: msg.content,
56
+ sessionDate: meta.startTime,
57
+ });
58
+ }
59
+ }
60
+ catch {
61
+ // skip broken files
62
+ }
63
+ }
64
+ }
65
+ const ranked = index.search(query, maxResults * 2);
66
+ const tfidfResults = ranked
67
+ .map(({ id, score }) => {
68
+ const doc = docMap.get(id);
69
+ if (!doc)
70
+ return null;
71
+ const excerpt = buildExcerpt(doc.content, query);
72
+ const ts = doc.timestamp ?? doc.sessionDate;
73
+ const decay = recencyDecay(ts);
74
+ const adjustedScore = score * decay;
75
+ return {
76
+ source: 'session',
77
+ id: doc.sessionId,
78
+ project: doc.project,
79
+ role: doc.role,
80
+ timestamp: ts,
81
+ excerpt,
82
+ score: adjustedScore,
83
+ metadata: {
84
+ scope,
85
+ sessionDate: doc.sessionDate,
86
+ relevanceScore: score,
87
+ recencyMultiplier: Math.round(decay * 100) / 100,
88
+ },
89
+ };
90
+ })
91
+ .filter((r) => r !== null);
92
+ tfidfResults.sort((a, b) => b.score - a.score);
93
+ const trimmedTfidf = tfidfResults.slice(0, maxResults);
94
+ if (!semantic) {
95
+ return trimmedTfidf;
96
+ }
97
+ try {
98
+ const provider = await getEmbeddingProvider();
99
+ if (!provider)
100
+ return trimmedTfidf;
101
+ const queryVector = await provider.embedOne(query);
102
+ const store = getVectorStore();
103
+ const vectorResults = store.searchBySource(queryVector, 'session', maxResults * 2);
104
+ if (vectorResults.length === 0)
105
+ return trimmedTfidf;
106
+ const config = getConfig();
107
+ const alpha = config.embeddingAlpha;
108
+ const semanticScores = new Map();
109
+ for (const vr of vectorResults) {
110
+ const existing = semanticScores.get(vr.sourceId) ?? 0;
111
+ if (vr.score > existing) {
112
+ semanticScores.set(vr.sourceId, vr.score);
113
+ }
114
+ }
115
+ const maxTfidf = trimmedTfidf.length > 0 ? Math.max(...trimmedTfidf.map((r) => r.score)) : 1;
116
+ const normFactor = maxTfidf > 0 ? maxTfidf : 1;
117
+ const results = trimmedTfidf.map((result) => {
118
+ const normalizedTfidf = result.score / normFactor;
119
+ const semanticScore = semanticScores.get(result.id) ?? 0;
120
+ const blended = alpha * normalizedTfidf + (1 - alpha) * semanticScore;
121
+ const ts = result.timestamp ?? result.metadata?.sessionDate;
122
+ const decay = ts ? recencyDecay(ts) : 1;
123
+ const finalScore = blended * decay;
124
+ return {
125
+ ...result,
126
+ score: finalScore,
127
+ metadata: {
128
+ ...result.metadata,
129
+ tfidfScore: normalizedTfidf,
130
+ semanticScore,
131
+ blendAlpha: alpha,
132
+ },
133
+ };
134
+ });
135
+ results.sort((a, b) => b.score - a.score);
136
+ return results.slice(0, maxResults);
137
+ }
138
+ catch {
139
+ return trimmedTfidf;
140
+ }
141
+ }
142
+ // ── Scope filters ───────────────────────────────────────────────────────────
143
+ function filterByScope(scope, messages) {
144
+ if (scope === 'all') {
145
+ return messages;
146
+ }
147
+ if (scope === 'tools') {
148
+ return messages.filter((m) => m.role === 'tool_use' || m.role === 'tool_result');
149
+ }
150
+ const pattern = SCOPE_PATTERNS[scope];
151
+ return messages.filter((m) => pattern.test(m.content));
152
+ }
153
+ //# sourceMappingURL=scopes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/sessions/scopes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { SearchResult } from '../search/types.js';
2
+ export interface SearchSessionOptions {
3
+ project?: string;
4
+ role?: 'user' | 'assistant' | 'all';
5
+ caseSensitive?: boolean;
6
+ maxResults?: number;
7
+ /** When true (default), use TF-IDF ranking. When false, use regex matching. */
8
+ ranked?: boolean;
9
+ /** When true (default when embeddings available), blend semantic similarity with TF-IDF. */
10
+ semantic?: boolean;
11
+ }
12
+ /**
13
+ * Search across all session transcripts.
14
+ *
15
+ * Supports three modes:
16
+ * - **hybrid** (default when embeddings available): blends TF-IDF ranking
17
+ * with semantic vector similarity using configurable alpha weighting.
18
+ * - **ranked** (default fallback): builds a TF-IDF index over all messages,
19
+ * returns results ordered by relevance score.
20
+ * - **legacy** (`ranked: false`): regex-based matching, faster for exact
21
+ * phrases and pattern searches.
22
+ *
23
+ * Returns results with excerpts (100 chars before + 100 chars after match).
24
+ */
25
+ export declare function searchSessions(query: string, options?: SearchSessionOptions): Promise<SearchResult[]>;
26
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/sessions/search.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,KAAK,CAAC;IACpC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAaD;;;;;;;;;;;;GAYG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,YAAY,EAAE,CAAC,CAoCzB"}