context-vault 3.7.0 → 3.9.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 (73) hide show
  1. package/assets/agent-rules.md +28 -1
  2. package/assets/setup-prompt.md +16 -1
  3. package/bin/cli.js +1003 -7
  4. package/dist/auto-memory.d.ts +52 -0
  5. package/dist/auto-memory.d.ts.map +1 -0
  6. package/dist/auto-memory.js +142 -0
  7. package/dist/auto-memory.js.map +1 -0
  8. package/dist/register-tools.d.ts.map +1 -1
  9. package/dist/register-tools.js +2 -0
  10. package/dist/register-tools.js.map +1 -1
  11. package/dist/remote.d.ts +134 -0
  12. package/dist/remote.d.ts.map +1 -0
  13. package/dist/remote.js +242 -0
  14. package/dist/remote.js.map +1 -0
  15. package/dist/remote.test.d.ts +2 -0
  16. package/dist/remote.test.d.ts.map +1 -0
  17. package/dist/remote.test.js +107 -0
  18. package/dist/remote.test.js.map +1 -0
  19. package/dist/stats/recall.d.ts +33 -0
  20. package/dist/stats/recall.d.ts.map +1 -0
  21. package/dist/stats/recall.js +86 -0
  22. package/dist/stats/recall.js.map +1 -0
  23. package/dist/tools/context-status.d.ts.map +1 -1
  24. package/dist/tools/context-status.js +40 -0
  25. package/dist/tools/context-status.js.map +1 -1
  26. package/dist/tools/get-context.d.ts.map +1 -1
  27. package/dist/tools/get-context.js +44 -0
  28. package/dist/tools/get-context.js.map +1 -1
  29. package/dist/tools/publish-to-team.d.ts +11 -0
  30. package/dist/tools/publish-to-team.d.ts.map +1 -0
  31. package/dist/tools/publish-to-team.js +91 -0
  32. package/dist/tools/publish-to-team.js.map +1 -0
  33. package/dist/tools/publish-to-team.test.d.ts +2 -0
  34. package/dist/tools/publish-to-team.test.d.ts.map +1 -0
  35. package/dist/tools/publish-to-team.test.js +95 -0
  36. package/dist/tools/publish-to-team.test.js.map +1 -0
  37. package/dist/tools/recall.d.ts +1 -1
  38. package/dist/tools/recall.d.ts.map +1 -1
  39. package/dist/tools/recall.js +85 -1
  40. package/dist/tools/recall.js.map +1 -1
  41. package/dist/tools/save-context.d.ts +5 -1
  42. package/dist/tools/save-context.d.ts.map +1 -1
  43. package/dist/tools/save-context.js +163 -2
  44. package/dist/tools/save-context.js.map +1 -1
  45. package/dist/tools/session-start.d.ts.map +1 -1
  46. package/dist/tools/session-start.js +90 -86
  47. package/dist/tools/session-start.js.map +1 -1
  48. package/node_modules/@context-vault/core/dist/config.d.ts +3 -1
  49. package/node_modules/@context-vault/core/dist/config.d.ts.map +1 -1
  50. package/node_modules/@context-vault/core/dist/config.js +48 -2
  51. package/node_modules/@context-vault/core/dist/config.js.map +1 -1
  52. package/node_modules/@context-vault/core/dist/main.d.ts +1 -1
  53. package/node_modules/@context-vault/core/dist/main.d.ts.map +1 -1
  54. package/node_modules/@context-vault/core/dist/main.js.map +1 -1
  55. package/node_modules/@context-vault/core/dist/types.d.ts +7 -0
  56. package/node_modules/@context-vault/core/dist/types.d.ts.map +1 -1
  57. package/node_modules/@context-vault/core/package.json +1 -1
  58. package/node_modules/@context-vault/core/src/config.ts +50 -3
  59. package/node_modules/@context-vault/core/src/main.ts +1 -0
  60. package/node_modules/@context-vault/core/src/types.ts +8 -0
  61. package/package.json +2 -2
  62. package/src/auto-memory.ts +169 -0
  63. package/src/register-tools.ts +2 -0
  64. package/src/remote.test.ts +123 -0
  65. package/src/remote.ts +325 -0
  66. package/src/stats/recall.ts +139 -0
  67. package/src/tools/context-status.ts +40 -0
  68. package/src/tools/get-context.ts +44 -0
  69. package/src/tools/publish-to-team.test.ts +115 -0
  70. package/src/tools/publish-to-team.ts +112 -0
  71. package/src/tools/recall.ts +79 -1
  72. package/src/tools/save-context.ts +167 -1
  73. package/src/tools/session-start.ts +88 -100
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@context-vault/core",
3
- "version": "3.7.0",
3
+ "version": "3.9.0",
4
4
  "type": "module",
5
5
  "description": "Pure local engine: capture, index, search, and utilities for context-vault",
6
6
  "main": "dist/main.js",
@@ -1,8 +1,8 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
- import { join, resolve } from 'node:path';
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
2
+ import { join, resolve, dirname } from 'node:path';
3
3
  import { homedir, tmpdir } from 'node:os';
4
4
  import { DEFAULT_GROWTH_THRESHOLDS, DEFAULT_LIFECYCLE, DEFAULT_AUTO_INSIGHTS, DEFAULT_INDEXING } from './constants.js';
5
- import type { VaultConfig } from './types.js';
5
+ import type { VaultConfig, RemoteConfig } from './types.js';
6
6
 
7
7
  /**
8
8
  * Guard against writes to the real config file during test runs.
@@ -162,6 +162,15 @@ export function resolveConfig(): VaultConfig {
162
162
  if (ix.maxBodySize != null) config.indexing.maxBodySize = Number(ix.maxBodySize);
163
163
  if (ix.autoIndexEvents != null) config.indexing.autoIndexEvents = ix.autoIndexEvents === true;
164
164
  }
165
+ if (fc.remote && typeof fc.remote === 'object') {
166
+ const r = fc.remote;
167
+ config.remote = {
168
+ enabled: r.enabled === true,
169
+ url: typeof r.url === 'string' ? r.url : 'https://api.context-vault.com',
170
+ apiKey: typeof r.apiKey === 'string' ? r.apiKey : '',
171
+ ...(typeof r.teamId === 'string' && r.teamId ? { teamId: r.teamId } : {}),
172
+ };
173
+ }
165
174
  config.resolvedFrom = 'config file';
166
175
  } catch (e) {
167
176
  throw new Error(`[context-vault] Invalid config at ${configPath}: ${(e as Error).message}`);
@@ -221,3 +230,41 @@ export function resolveConfig(): VaultConfig {
221
230
 
222
231
  return config;
223
232
  }
233
+
234
+ export function getRemoteConfig(dataDir?: string): RemoteConfig | null {
235
+ const dir = dataDir || join(homedir(), '.context-mcp');
236
+ const configPath = join(dir, 'config.json');
237
+ if (!existsSync(configPath)) return null;
238
+ try {
239
+ const fc = JSON.parse(readFileSync(configPath, 'utf-8'));
240
+ if (!fc.remote || typeof fc.remote !== 'object') return null;
241
+ return {
242
+ enabled: fc.remote.enabled === true,
243
+ url: typeof fc.remote.url === 'string' ? fc.remote.url : 'https://api.context-vault.com',
244
+ apiKey: typeof fc.remote.apiKey === 'string' ? fc.remote.apiKey : '',
245
+ ...(typeof fc.remote.teamId === 'string' && fc.remote.teamId ? { teamId: fc.remote.teamId } : {}),
246
+ };
247
+ } catch {
248
+ return null;
249
+ }
250
+ }
251
+
252
+ export function saveRemoteConfig(remote: Partial<RemoteConfig>, dataDir?: string): void {
253
+ const dir = dataDir || join(homedir(), '.context-mcp');
254
+ const configPath = join(dir, 'config.json');
255
+ assertNotTestMode(configPath);
256
+
257
+ mkdirSync(dirname(configPath), { recursive: true });
258
+
259
+ let fc: Record<string, any> = {};
260
+ if (existsSync(configPath)) {
261
+ try {
262
+ fc = JSON.parse(readFileSync(configPath, 'utf-8'));
263
+ } catch {
264
+ fc = {};
265
+ }
266
+ }
267
+
268
+ fc.remote = { ...(fc.remote || {}), ...remote };
269
+ writeFileSync(configPath, JSON.stringify(fc, null, 2) + '\n');
270
+ }
@@ -1,6 +1,7 @@
1
1
  // Types
2
2
  export type {
3
3
  VaultConfig,
4
+ RemoteConfig,
4
5
  RecallConfig,
5
6
  ConsolidationConfig,
6
7
  GrowthThresholds,
@@ -15,6 +15,13 @@ export interface IndexingConfig {
15
15
  autoIndexEvents: boolean;
16
16
  }
17
17
 
18
+ export interface RemoteConfig {
19
+ enabled: boolean;
20
+ url: string;
21
+ apiKey: string;
22
+ teamId?: string;
23
+ }
24
+
18
25
  export interface VaultConfig {
19
26
  vaultDir: string;
20
27
  dataDir: string;
@@ -31,6 +38,7 @@ export interface VaultConfig {
31
38
  lifecycle: Record<string, { archiveAfterDays?: number }>;
32
39
  autoInsights: AutoInsightsConfig;
33
40
  indexing: IndexingConfig;
41
+ remote?: RemoteConfig;
34
42
  }
35
43
 
36
44
  export interface RecallConfig {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-vault",
3
- "version": "3.7.0",
3
+ "version": "3.9.0",
4
4
  "type": "module",
5
5
  "description": "Persistent memory for AI agents — saves and searches knowledge across sessions",
6
6
  "bin": {
@@ -63,7 +63,7 @@
63
63
  "@context-vault/core"
64
64
  ],
65
65
  "dependencies": {
66
- "@context-vault/core": "^3.7.0",
66
+ "@context-vault/core": "^3.9.0",
67
67
  "@modelcontextprotocol/sdk": "^1.26.0",
68
68
  "adm-zip": "^0.5.16",
69
69
  "sqlite-vec": "^0.1.0"
@@ -0,0 +1,169 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+
5
+ export interface AutoMemoryEntry {
6
+ file: string;
7
+ name: string;
8
+ description: string;
9
+ type: string;
10
+ body: string;
11
+ }
12
+
13
+ export interface AutoMemoryResult {
14
+ detected: boolean;
15
+ path: string | null;
16
+ entries: AutoMemoryEntry[];
17
+ linesUsed: number;
18
+ }
19
+
20
+ /**
21
+ * Detect the Claude Code auto-memory directory for the current project.
22
+ * Convention: ~/.claude/projects/-<cwd-with-slashes-replaced-by-dashes>/memory/
23
+ */
24
+ export function detectAutoMemoryPath(): string | null {
25
+ try {
26
+ const cwd = process.cwd();
27
+ const projectKey = cwd.replace(/\//g, '-');
28
+ const memoryDir = join(homedir(), '.claude', 'projects', projectKey, 'memory');
29
+ const memoryIndex = join(memoryDir, 'MEMORY.md');
30
+ if (existsSync(memoryIndex)) return memoryDir;
31
+ } catch {}
32
+ return null;
33
+ }
34
+
35
+ /**
36
+ * Parse YAML-ish frontmatter from a memory file.
37
+ * Returns { name, description, type } and the body after frontmatter.
38
+ */
39
+ export function parseMemoryFile(content: string): { name: string; description: string; type: string; body: string } {
40
+ const result = { name: '', description: '', type: '', body: content };
41
+ const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);
42
+ if (!fmMatch) return result;
43
+
44
+ const frontmatter = fmMatch[1];
45
+ result.body = fmMatch[2].trim();
46
+
47
+ for (const line of frontmatter.split('\n')) {
48
+ const kv = line.match(/^(\w+)\s*:\s*(.+)$/);
49
+ if (!kv) continue;
50
+ const [, key, val] = kv;
51
+ if (key === 'name') result.name = val.trim();
52
+ else if (key === 'description') result.description = val.trim();
53
+ else if (key === 'type') result.type = val.trim();
54
+ }
55
+ return result;
56
+ }
57
+
58
+ /**
59
+ * Read and parse all auto-memory entries from a memory directory.
60
+ */
61
+ export function readAutoMemory(memoryDir: string): AutoMemoryResult {
62
+ const indexPath = join(memoryDir, 'MEMORY.md');
63
+ let linesUsed = 0;
64
+
65
+ try {
66
+ const indexContent = readFileSync(indexPath, 'utf-8');
67
+ linesUsed = indexContent.split('\n').length;
68
+ } catch {
69
+ return { detected: true, path: memoryDir, entries: [], linesUsed: 0 };
70
+ }
71
+
72
+ const entries: AutoMemoryEntry[] = [];
73
+
74
+ try {
75
+ const files = readdirSync(memoryDir).filter(
76
+ (f) => f.endsWith('.md') && f !== 'MEMORY.md'
77
+ );
78
+
79
+ for (const file of files) {
80
+ try {
81
+ const content = readFileSync(join(memoryDir, file), 'utf-8');
82
+ const parsed = parseMemoryFile(content);
83
+ entries.push({
84
+ file,
85
+ name: parsed.name || file.replace('.md', ''),
86
+ description: parsed.description,
87
+ type: parsed.type,
88
+ body: parsed.body,
89
+ });
90
+ } catch {}
91
+ }
92
+ } catch {}
93
+
94
+ return { detected: true, path: memoryDir, entries, linesUsed };
95
+ }
96
+
97
+ /**
98
+ * Resolve auto-memory path from explicit param or auto-detection.
99
+ */
100
+ export function resolveAutoMemoryPath(explicitPath?: string): string | null {
101
+ if (explicitPath?.trim()) {
102
+ return existsSync(join(explicitPath.trim(), 'MEMORY.md')) ? explicitPath.trim() : null;
103
+ }
104
+ return detectAutoMemoryPath();
105
+ }
106
+
107
+ /**
108
+ * Get auto-memory result: detect path and read entries.
109
+ */
110
+ export function getAutoMemory(explicitPath?: string): AutoMemoryResult {
111
+ const resolvedPath = resolveAutoMemoryPath(explicitPath);
112
+ if (!resolvedPath) {
113
+ return { detected: false, path: null, entries: [], linesUsed: 0 };
114
+ }
115
+ return readAutoMemory(resolvedPath);
116
+ }
117
+
118
+ /**
119
+ * Check if a text is similar to any auto-memory entry body.
120
+ * Returns matches above the given threshold (simple text comparison).
121
+ * For real similarity, callers should use embeddings.
122
+ */
123
+ export function findAutoMemoryOverlaps(
124
+ autoMemory: AutoMemoryResult,
125
+ text: string,
126
+ threshold = 0.9
127
+ ): Array<{ file: string; name: string; type: string; similarity: number }> {
128
+ if (!autoMemory.detected || autoMemory.entries.length === 0) return [];
129
+
130
+ const normalizedText = text.toLowerCase().replace(/\s+/g, ' ').trim();
131
+ if (!normalizedText) return [];
132
+
133
+ const overlaps: Array<{ file: string; name: string; type: string; similarity: number }> = [];
134
+
135
+ for (const entry of autoMemory.entries) {
136
+ const entryText = [entry.name, entry.description, entry.body]
137
+ .filter(Boolean)
138
+ .join(' ')
139
+ .toLowerCase()
140
+ .replace(/\s+/g, ' ')
141
+ .trim();
142
+
143
+ if (!entryText) continue;
144
+
145
+ // Simple token overlap similarity (Jaccard-like)
146
+ const textTokens = new Set(normalizedText.split(' ').filter(w => w.length >= 3));
147
+ const entryTokens = new Set(entryText.split(' ').filter(w => w.length >= 3));
148
+
149
+ if (textTokens.size === 0 || entryTokens.size === 0) continue;
150
+
151
+ let intersection = 0;
152
+ for (const token of textTokens) {
153
+ if (entryTokens.has(token)) intersection++;
154
+ }
155
+ const union = textTokens.size + entryTokens.size - intersection;
156
+ const similarity = union > 0 ? intersection / union : 0;
157
+
158
+ if (similarity >= threshold) {
159
+ overlaps.push({
160
+ file: entry.file,
161
+ name: entry.name,
162
+ type: entry.type,
163
+ similarity,
164
+ });
165
+ }
166
+ }
167
+
168
+ return overlaps.sort((a, b) => b.similarity - a.similarity);
169
+ }
@@ -23,6 +23,7 @@ import * as listBuckets from './tools/list-buckets.js';
23
23
  import * as ingestProject from './tools/ingest-project.js';
24
24
  import * as sessionEnd from './tools/session-end.js';
25
25
  import * as recall from './tools/recall.js';
26
+ import * as publishToTeam from './tools/publish-to-team.js';
26
27
 
27
28
  const toolModules = [
28
29
  getContext,
@@ -38,6 +39,7 @@ const toolModules = [
38
39
  sessionEnd,
39
40
  listBuckets,
40
41
  recall,
42
+ publishToTeam,
41
43
  ];
42
44
 
43
45
  const TOOL_TIMEOUT_MS = 120_000;
@@ -0,0 +1,123 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import {
3
+ mergeRemoteResults,
4
+ mergeWithTeamResults,
5
+ applyTeamRecallBoost,
6
+ getTeamId,
7
+ } from './remote.js';
8
+
9
+ describe('mergeRemoteResults', () => {
10
+ it('deduplicates by id, keeping local over remote', () => {
11
+ const local = [
12
+ { id: 'a', score: 0.9 },
13
+ { id: 'b', score: 0.8 },
14
+ ];
15
+ const remote = [
16
+ { id: 'b', score: 0.95 },
17
+ { id: 'c', score: 0.7 },
18
+ ];
19
+ const result = mergeRemoteResults(local, remote, 10);
20
+ expect(result.map(r => r.id)).toEqual(['a', 'b', 'c']);
21
+ // local 'b' wins (score 0.8), not remote's 0.95
22
+ expect(result.find(r => r.id === 'b')!.score).toBe(0.8);
23
+ });
24
+
25
+ it('respects limit', () => {
26
+ const local = [{ id: 'a', score: 0.9 }];
27
+ const remote = [
28
+ { id: 'b', score: 0.8 },
29
+ { id: 'c', score: 0.7 },
30
+ ];
31
+ const result = mergeRemoteResults(local, remote, 2);
32
+ expect(result).toHaveLength(2);
33
+ });
34
+
35
+ it('sorts by score descending', () => {
36
+ const local = [{ id: 'a', score: 0.5 }];
37
+ const remote = [{ id: 'b', score: 0.9 }];
38
+ const result = mergeRemoteResults(local, remote, 10);
39
+ expect(result[0].id).toBe('b');
40
+ expect(result[1].id).toBe('a');
41
+ });
42
+ });
43
+
44
+ describe('applyTeamRecallBoost', () => {
45
+ it('boosts entries with recall_count > 0', () => {
46
+ const entries = [
47
+ { id: 'a', score: 1.0, recall_count: 5, recall_members: 2 },
48
+ { id: 'b', score: 1.0, recall_count: 0, recall_members: 0 },
49
+ ];
50
+ const boosted = applyTeamRecallBoost(entries);
51
+ expect(boosted.find(e => e.id === 'a')!.score).toBeGreaterThan(1.0);
52
+ expect(boosted.find(e => e.id === 'b')!.score).toBe(1.0);
53
+ });
54
+
55
+ it('applies formula: score * log(1 + recall_count) * (1 + 0.1 * recall_members)', () => {
56
+ const entries = [{ id: 'x', score: 2.0, recall_count: 10, recall_members: 3 }];
57
+ const boosted = applyTeamRecallBoost(entries);
58
+ const expected = 2.0 * Math.log(1 + 10) * (1 + 0.1 * 3);
59
+ expect(boosted[0].score).toBeCloseTo(expected, 5);
60
+ });
61
+
62
+ it('handles missing recall fields gracefully', () => {
63
+ const entries = [{ id: 'a', score: 0.5 }];
64
+ const boosted = applyTeamRecallBoost(entries);
65
+ expect(boosted[0].score).toBe(0.5);
66
+ });
67
+ });
68
+
69
+ describe('mergeWithTeamResults', () => {
70
+ it('deduplicates team results against local+personal', () => {
71
+ const localAndPersonal = [
72
+ { id: 'a', score: 0.9 },
73
+ { id: 'b', score: 0.8 },
74
+ ];
75
+ const team = [
76
+ { id: 'b', score: 0.7, recall_count: 5, recall_members: 2 },
77
+ { id: 'c', score: 0.6, recall_count: 3, recall_members: 1 },
78
+ ];
79
+ const result = mergeWithTeamResults(localAndPersonal, team, 10);
80
+ const ids = result.map(r => r.id);
81
+ expect(ids).toContain('a');
82
+ expect(ids).toContain('b');
83
+ expect(ids).toContain('c');
84
+ // 'b' should appear only once (from local+personal)
85
+ expect(ids.filter(id => id === 'b')).toHaveLength(1);
86
+ });
87
+
88
+ it('boosts team results by recall before merging', () => {
89
+ const localAndPersonal = [{ id: 'a', score: 0.5 }];
90
+ const team = [{ id: 'b', score: 0.3, recall_count: 100, recall_members: 5 }];
91
+ const result = mergeWithTeamResults(localAndPersonal, team, 10);
92
+ // team entry 'b' should be boosted significantly by high recall
93
+ const bResult = result.find(r => r.id === 'b');
94
+ expect(bResult).toBeDefined();
95
+ expect(bResult!.score!).toBeGreaterThan(0.3);
96
+ });
97
+
98
+ it('respects limit', () => {
99
+ const local = [{ id: 'a', score: 0.9 }];
100
+ const team = [
101
+ { id: 'b', score: 0.8, recall_count: 1, recall_members: 1 },
102
+ { id: 'c', score: 0.7, recall_count: 1, recall_members: 1 },
103
+ ];
104
+ const result = mergeWithTeamResults(local, team, 2);
105
+ expect(result).toHaveLength(2);
106
+ });
107
+ });
108
+
109
+ describe('getTeamId', () => {
110
+ it('returns teamId when present', () => {
111
+ const config = { remote: { enabled: true, url: 'http://x', apiKey: 'k', teamId: 'team-1' } };
112
+ expect(getTeamId(config)).toBe('team-1');
113
+ });
114
+
115
+ it('returns null when no remote config', () => {
116
+ expect(getTeamId({})).toBeNull();
117
+ });
118
+
119
+ it('returns null when teamId not set', () => {
120
+ const config = { remote: { enabled: true, url: 'http://x', apiKey: 'k' } };
121
+ expect(getTeamId(config)).toBeNull();
122
+ });
123
+ });