@getplumb/core 0.4.0 → 0.4.1

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 (41) hide show
  1. package/package.json +1 -1
  2. package/dist/extraction-queue.d.ts +0 -72
  3. package/dist/extraction-queue.d.ts.map +0 -1
  4. package/dist/extraction-queue.js +0 -101
  5. package/dist/extraction-queue.js.map +0 -1
  6. package/dist/extractor.d.ts +0 -22
  7. package/dist/extractor.d.ts.map +0 -1
  8. package/dist/extractor.js +0 -188
  9. package/dist/extractor.js.map +0 -1
  10. package/dist/extractor.test.d.ts +0 -2
  11. package/dist/extractor.test.d.ts.map +0 -1
  12. package/dist/extractor.test.js +0 -158
  13. package/dist/extractor.test.js.map +0 -1
  14. package/dist/fact-search.d.ts +0 -32
  15. package/dist/fact-search.d.ts.map +0 -1
  16. package/dist/fact-search.js +0 -174
  17. package/dist/fact-search.js.map +0 -1
  18. package/dist/fact-search.test.d.ts +0 -12
  19. package/dist/fact-search.test.d.ts.map +0 -1
  20. package/dist/fact-search.test.js +0 -117
  21. package/dist/fact-search.test.js.map +0 -1
  22. package/dist/llm-client.d.ts +0 -59
  23. package/dist/llm-client.d.ts.map +0 -1
  24. package/dist/llm-client.js +0 -227
  25. package/dist/llm-client.js.map +0 -1
  26. package/dist/local-store.test.d.ts +0 -2
  27. package/dist/local-store.test.d.ts.map +0 -1
  28. package/dist/local-store.test.js +0 -146
  29. package/dist/local-store.test.js.map +0 -1
  30. package/dist/raw-log-search.test.d.ts +0 -12
  31. package/dist/raw-log-search.test.d.ts.map +0 -1
  32. package/dist/raw-log-search.test.js +0 -124
  33. package/dist/raw-log-search.test.js.map +0 -1
  34. package/dist/read-path.test.d.ts +0 -15
  35. package/dist/read-path.test.d.ts.map +0 -1
  36. package/dist/read-path.test.js +0 -393
  37. package/dist/read-path.test.js.map +0 -1
  38. package/dist/scorer.test.d.ts +0 -10
  39. package/dist/scorer.test.d.ts.map +0 -1
  40. package/dist/scorer.test.js +0 -169
  41. package/dist/scorer.test.js.map +0 -1
@@ -1,146 +0,0 @@
1
- import { test, after } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
5
- import { rmSync } from 'node:fs';
6
- import { LocalStore } from './local-store.js';
7
- import { DecayRate } from './types.js';
8
- // Use a unique temp path per test run so tests don't interfere with each other.
9
- const dbPath = join(tmpdir(), `plumb-test-${Date.now()}.db`);
10
- const store = new LocalStore({ dbPath, userId: 'test-user' });
11
- after(() => {
12
- store.close();
13
- rmSync(dbPath, { force: true });
14
- });
15
- test('store() inserts a fact and returns a UUID', async () => {
16
- const id = await store.store({
17
- subject: 'user',
18
- predicate: 'prefers',
19
- object: 'dark mode',
20
- confidence: 0.95,
21
- decayRate: DecayRate.slow,
22
- timestamp: new Date(),
23
- sourceSessionId: 'session-abc',
24
- sourceSessionLabel: 'test-session',
25
- context: 'user mentioned this in passing',
26
- });
27
- assert.match(id, /^[0-9a-f-]{36}$/, 'id should be a UUID');
28
- });
29
- test('search() retrieves stored fact by keyword', async () => {
30
- await store.store({
31
- subject: 'user',
32
- predicate: 'uses',
33
- object: 'TypeScript',
34
- confidence: 0.9,
35
- decayRate: DecayRate.medium,
36
- timestamp: new Date(),
37
- sourceSessionId: 'session-abc',
38
- });
39
- const results = await store.search('TypeScript');
40
- assert.ok(results.length > 0, 'should return at least one result');
41
- const match = results.find((r) => r.fact.object === 'TypeScript');
42
- assert.ok(match !== undefined, 'should find the TypeScript fact');
43
- assert.equal(match.fact.subject, 'user');
44
- assert.equal(match.fact.predicate, 'uses');
45
- assert.ok(match.ageInDays >= 0, 'ageInDays should be non-negative');
46
- assert.ok(match.score >= 0, 'score should be non-negative');
47
- });
48
- test('delete() soft-deletes a fact (sets deleted_at, excludes from search)', async () => {
49
- const id = await store.store({
50
- subject: 'user',
51
- predicate: 'dislikes',
52
- object: 'Comic Sans',
53
- confidence: 0.99,
54
- decayRate: DecayRate.slow,
55
- timestamp: new Date(),
56
- sourceSessionId: 'session-xyz',
57
- });
58
- // Fact should be findable before deletion.
59
- const before = await store.search('Comic Sans');
60
- assert.ok(before.some((r) => r.fact.id === id), 'fact should be visible before deletion');
61
- await store.delete(id);
62
- // Fact should be excluded after soft delete.
63
- const after = await store.search('Comic Sans');
64
- assert.ok(!after.some((r) => r.fact.id === id), 'soft-deleted fact should not appear in search');
65
- });
66
- test('status() returns accurate factCount and rawLogCount', async () => {
67
- const fresh = new LocalStore({
68
- dbPath: join(tmpdir(), `plumb-status-test-${Date.now()}.db`),
69
- userId: 'status-test-user',
70
- });
71
- try {
72
- const initial = await fresh.status();
73
- assert.equal(initial.factCount, 0);
74
- assert.equal(initial.rawLogCount, 0);
75
- assert.equal(initial.lastIngestion, null);
76
- assert.ok(initial.storageBytes > 0, 'storageBytes should be positive even for empty DB');
77
- await fresh.store({
78
- subject: 'user',
79
- predicate: 'is',
80
- object: 'a developer',
81
- confidence: 0.8,
82
- decayRate: DecayRate.slow,
83
- timestamp: new Date(),
84
- sourceSessionId: 's1',
85
- });
86
- const afterStore = await fresh.status();
87
- assert.equal(afterStore.factCount, 1);
88
- assert.equal(afterStore.rawLogCount, 0);
89
- await fresh.ingest({
90
- userMessage: 'Hello!',
91
- agentResponse: 'Hi there!',
92
- timestamp: new Date(),
93
- source: 'openclaw',
94
- sessionId: 'session-1',
95
- });
96
- const afterIngest = await fresh.status();
97
- assert.equal(afterIngest.rawLogCount, 1);
98
- assert.ok(afterIngest.lastIngestion !== null, 'lastIngestion should be set after ingest');
99
- }
100
- finally {
101
- fresh.close();
102
- }
103
- });
104
- test('ingest() writes to raw_log and returns rawLogId', async () => {
105
- const result = await store.ingest({
106
- userMessage: 'What is the capital of France?',
107
- agentResponse: 'The capital of France is Paris.',
108
- timestamp: new Date(),
109
- source: 'claude-code',
110
- sessionId: 'session-ingest-test',
111
- sessionLabel: 'geography-chat',
112
- });
113
- assert.match(result.rawLogId, /^[0-9a-f-]{36}$/, 'rawLogId should be a UUID');
114
- assert.equal(result.factsExtracted, 0, 'no facts extracted yet (T-005)');
115
- assert.deepEqual(result.factIds, []);
116
- });
117
- test('ingest() cross-session: facts from different sessions visible in same status()', async () => {
118
- const crossStore = new LocalStore({
119
- dbPath: join(tmpdir(), `plumb-cross-session-${Date.now()}.db`),
120
- userId: 'cross-user',
121
- });
122
- try {
123
- await crossStore.ingest({
124
- userMessage: 'Planning session A',
125
- agentResponse: 'Got it.',
126
- timestamp: new Date(),
127
- source: 'openclaw',
128
- sessionId: 'session-A',
129
- sessionLabel: 'planning',
130
- });
131
- await crossStore.ingest({
132
- userMessage: 'Continuing in session B',
133
- agentResponse: 'Understood.',
134
- timestamp: new Date(),
135
- source: 'openclaw',
136
- sessionId: 'session-B',
137
- sessionLabel: 'followup',
138
- });
139
- const status = await crossStore.status();
140
- assert.equal(status.rawLogCount, 2, 'both sessions should be counted in raw_log');
141
- }
142
- finally {
143
- crossStore.close();
144
- }
145
- });
146
- //# sourceMappingURL=local-store.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"local-store.test.js","sourceRoot":"","sources":["../src/local-store.test.ts"],"names":[],"mappings":"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"}
@@ -1,12 +0,0 @@
1
- /**
2
- * Tests for Layer 1 hybrid search (raw-log-search.ts).
3
- *
4
- * Ingests 3 exchanges with distinct topics, then verifies that searchRawLog()
5
- * returns ranked results with the expected structure.
6
- *
7
- * Note: The first test run downloads the BAAI/bge-small-en-v1.5 embedding model
8
- * (~100 MB) and the ms-marco cross-encoder (~50 MB) — subsequent runs use the
9
- * local ~/.cache/huggingface/ cache. Tests are marked with a generous timeout.
10
- */
11
- export {};
12
- //# sourceMappingURL=raw-log-search.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"raw-log-search.test.d.ts","sourceRoot":"","sources":["../src/raw-log-search.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -1,124 +0,0 @@
1
- /**
2
- * Tests for Layer 1 hybrid search (raw-log-search.ts).
3
- *
4
- * Ingests 3 exchanges with distinct topics, then verifies that searchRawLog()
5
- * returns ranked results with the expected structure.
6
- *
7
- * Note: The first test run downloads the BAAI/bge-small-en-v1.5 embedding model
8
- * (~100 MB) and the ms-marco cross-encoder (~50 MB) — subsequent runs use the
9
- * local ~/.cache/huggingface/ cache. Tests are marked with a generous timeout.
10
- */
11
- import { test, after } from 'node:test';
12
- import assert from 'node:assert/strict';
13
- import { tmpdir } from 'node:os';
14
- import { join } from 'node:path';
15
- import { rmSync } from 'node:fs';
16
- import { LocalStore } from './local-store.js';
17
- const dbPath = join(tmpdir(), `plumb-search-test-${Date.now()}.db`);
18
- const store = new LocalStore({ dbPath, userId: 'search-test-user' });
19
- after(() => {
20
- store.close();
21
- rmSync(dbPath, { force: true });
22
- });
23
- // ─── Fixtures ────────────────────────────────────────────────────────────────
24
- const EXCHANGES = [
25
- {
26
- userMessage: 'How do I configure TypeScript strict mode?',
27
- agentResponse: 'Enable strict mode in tsconfig.json by setting "strict": true. ' +
28
- 'This enables noImplicitAny, strictNullChecks, and several other checks ' +
29
- 'that catch common bugs at compile time.',
30
- sessionId: 'session-ts',
31
- sessionLabel: 'typescript-help',
32
- source: 'openclaw',
33
- timestamp: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000), // 1 day ago
34
- },
35
- {
36
- userMessage: 'What is the best recipe for chocolate cake?',
37
- agentResponse: 'For a classic chocolate cake, cream 200g butter with 200g sugar, ' +
38
- 'beat in 4 eggs, fold in 175g self-raising flour and 50g cocoa powder. ' +
39
- 'Bake at 180°C for 30 minutes. Frost with ganache when cool.',
40
- sessionId: 'session-recipe',
41
- sessionLabel: 'cooking-chat',
42
- source: 'openclaw',
43
- timestamp: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000), // 2 days ago
44
- },
45
- {
46
- userMessage: 'Explain SQLite WAL mode and when to use it.',
47
- agentResponse: 'WAL (Write-Ahead Log) mode improves SQLite concurrency by allowing ' +
48
- 'readers to proceed while a writer is active. Enable it with PRAGMA ' +
49
- 'journal_mode = WAL. It is recommended for applications with multiple ' +
50
- 'readers and infrequent writers, like desktop apps and local servers.',
51
- sessionId: 'session-sqlite',
52
- sessionLabel: 'database-chat',
53
- source: 'claude-code',
54
- timestamp: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000), // 3 days ago
55
- },
56
- ];
57
- // ─── Ingest (shared setup) ───────────────────────────────────────────────────
58
- test('ingest 3 exchanges with distinct topics', { timeout: 120_000 }, async () => {
59
- for (const exchange of EXCHANGES) {
60
- const result = await store.ingest(exchange);
61
- assert.match(result.rawLogId, /^[0-9a-f-]{36}$/, 'rawLogId should be a UUID');
62
- }
63
- const status = await store.status();
64
- assert.equal(status.rawLogCount, 3, 'all 3 exchanges should be in raw_log');
65
- });
66
- // ─── Search ──────────────────────────────────────────────────────────────────
67
- test('searchRawLog returns results with required fields', { timeout: 120_000 }, async () => {
68
- const results = await store.searchRawLog('TypeScript configuration', 3);
69
- assert.ok(results.length > 0, 'should return at least one result');
70
- for (const r of results) {
71
- assert.ok(typeof r.chunk_text === 'string', 'chunk_text must be a string');
72
- assert.ok(typeof r.session_id === 'string', 'session_id must be a string');
73
- assert.ok(typeof r.timestamp === 'string', 'timestamp must be a string');
74
- assert.ok(typeof r.final_score === 'number', 'final_score must be a number');
75
- // session_label may be null
76
- assert.ok(r.session_label === null || typeof r.session_label === 'string', 'session_label must be string or null');
77
- }
78
- });
79
- test('searchRawLog ranks TypeScript exchange first for TS query', { timeout: 120_000 }, async () => {
80
- const results = await store.searchRawLog('TypeScript strict mode tsconfig', 3);
81
- assert.ok(results.length > 0, 'should return results');
82
- const top = results[0];
83
- assert.ok(top !== undefined, 'should have a top result');
84
- // The TypeScript exchange should rank first (or at least in top 2).
85
- const tsResult = results.find((r) => r.session_id === 'session-ts');
86
- assert.ok(tsResult !== undefined, 'TypeScript exchange should appear in results');
87
- // Top result should be the TS exchange (semantic match is strong).
88
- assert.equal(top.session_id, 'session-ts', 'TypeScript exchange should rank #1');
89
- });
90
- test('searchRawLog returns SQLite exchange in top results for database query', { timeout: 120_000 }, async () => {
91
- const results = await store.searchRawLog('SQLite WAL journal mode database', 3);
92
- assert.ok(results.length > 0, 'should return results');
93
- // SQLite exchange should appear in top-3 results — exact rank depends on model scores.
94
- const sqliteResult = results.find((r) => r.session_id === 'session-sqlite');
95
- assert.ok(sqliteResult !== undefined, 'SQLite exchange should appear in top-3 results');
96
- // The recipe exchange (no SQLite content) should NOT rank above SQLite.
97
- const recipeRank = results.findIndex((r) => r.session_id === 'session-recipe');
98
- const sqliteRank = results.findIndex((r) => r.session_id === 'session-sqlite');
99
- assert.ok(recipeRank === -1 || sqliteRank < recipeRank, 'SQLite exchange should outrank the recipe exchange for a database query');
100
- });
101
- test('searchRawLog is cross-session (no session filter applied)', { timeout: 120_000 }, async () => {
102
- // A broad query — all 3 sessions should be retrievable.
103
- const results = await store.searchRawLog('what did we discuss', 3);
104
- // We just check structure — cross-session means limit=3 can return up to all 3.
105
- assert.ok(results.length <= 3);
106
- assert.ok(results.length >= 1);
107
- for (const r of results) {
108
- assert.ok(['session-ts', 'session-recipe', 'session-sqlite'].includes(r.session_id));
109
- }
110
- });
111
- test('searchRawLog returns empty array when no rows exist', { timeout: 30_000 }, async () => {
112
- const emptyStore = new LocalStore({
113
- dbPath: join(tmpdir(), `plumb-empty-${Date.now()}.db`),
114
- userId: 'empty-user',
115
- });
116
- try {
117
- const results = await emptyStore.searchRawLog('anything', 5);
118
- assert.deepEqual(results, []);
119
- }
120
- finally {
121
- emptyStore.close();
122
- }
123
- });
124
- //# sourceMappingURL=raw-log-search.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"raw-log-search.test.js","sourceRoot":"","sources":["../src/raw-log-search.test.ts"],"names":[],"mappings":"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"}
@@ -1,15 +0,0 @@
1
- /**
2
- * Tests for read-path.ts (buildMemoryContext) and context-builder.ts (formatContextBlock).
3
- *
4
- * Strategy:
5
- * - Unit tests use a mock ReadPathStore to avoid ML model downloads and keep
6
- * tests fast and deterministic.
7
- * - One integration smoke test uses a real LocalStore with real facts inserted
8
- * via store.store() (keyword search, no embedder needed) to verify the
9
- * end-to-end cross-session provenance path.
10
- *
11
- * Cross-session test (acceptance criteria): facts ingested in session A must
12
- * be returned when querying in session B context — no session filter applied.
13
- */
14
- export {};
15
- //# sourceMappingURL=read-path.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"read-path.test.d.ts","sourceRoot":"","sources":["../src/read-path.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}