@getplumb/core 0.1.6 → 0.4.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/README.md +2 -2
- package/dist/context-builder.d.ts +1 -7
- package/dist/context-builder.d.ts.map +1 -1
- package/dist/context-builder.js +7 -44
- package/dist/context-builder.js.map +1 -1
- package/dist/embedder.d.ts +16 -2
- package/dist/embedder.d.ts.map +1 -1
- package/dist/embedder.js +23 -4
- package/dist/embedder.js.map +1 -1
- package/dist/extraction-queue.d.ts +13 -3
- package/dist/extraction-queue.d.ts.map +1 -1
- package/dist/extraction-queue.js +21 -4
- package/dist/extraction-queue.js.map +1 -1
- package/dist/extractor.d.ts +2 -1
- package/dist/extractor.d.ts.map +1 -1
- package/dist/extractor.js +106 -7
- package/dist/extractor.js.map +1 -1
- package/dist/extractor.test.d.ts +2 -0
- package/dist/extractor.test.d.ts.map +1 -0
- package/dist/extractor.test.js +158 -0
- package/dist/extractor.test.js.map +1 -0
- package/dist/fact-search.d.ts +9 -5
- package/dist/fact-search.d.ts.map +1 -1
- package/dist/fact-search.js +25 -16
- package/dist/fact-search.js.map +1 -1
- package/dist/fact-search.test.d.ts +12 -0
- package/dist/fact-search.test.d.ts.map +1 -0
- package/dist/fact-search.test.js +117 -0
- package/dist/fact-search.test.js.map +1 -0
- package/dist/index.d.ts +6 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -5
- package/dist/index.js.map +1 -1
- package/dist/llm-client.d.ts +11 -2
- package/dist/llm-client.d.ts.map +1 -1
- package/dist/llm-client.js +47 -3
- package/dist/llm-client.js.map +1 -1
- package/dist/local-store.d.ts +19 -63
- package/dist/local-store.d.ts.map +1 -1
- package/dist/local-store.js +353 -262
- package/dist/local-store.js.map +1 -1
- package/dist/local-store.test.d.ts +2 -0
- package/dist/local-store.test.d.ts.map +1 -0
- package/dist/local-store.test.js +146 -0
- package/dist/local-store.test.js.map +1 -0
- package/dist/raw-log-search.d.ts +9 -5
- package/dist/raw-log-search.d.ts.map +1 -1
- package/dist/raw-log-search.js +107 -29
- package/dist/raw-log-search.js.map +1 -1
- package/dist/raw-log-search.test.d.ts +12 -0
- package/dist/raw-log-search.test.d.ts.map +1 -0
- package/dist/raw-log-search.test.js +124 -0
- package/dist/raw-log-search.test.js.map +1 -0
- package/dist/read-path.d.ts +6 -23
- package/dist/read-path.d.ts.map +1 -1
- package/dist/read-path.js +9 -48
- package/dist/read-path.js.map +1 -1
- package/dist/read-path.test.d.ts +15 -0
- package/dist/read-path.test.d.ts.map +1 -0
- package/dist/read-path.test.js +393 -0
- package/dist/read-path.test.js.map +1 -0
- package/dist/schema.d.ts +4 -13
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +42 -52
- package/dist/schema.js.map +1 -1
- package/dist/scorer.d.ts +0 -9
- package/dist/scorer.d.ts.map +1 -1
- package/dist/scorer.js +1 -31
- package/dist/scorer.js.map +1 -1
- package/dist/scorer.test.d.ts +10 -0
- package/dist/scorer.test.d.ts.map +1 -0
- package/dist/scorer.test.js +169 -0
- package/dist/scorer.test.js.map +1 -0
- package/dist/store.d.ts +2 -14
- package/dist/store.d.ts.map +1 -1
- package/dist/types.d.ts +0 -25
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -6
- package/dist/types.js.map +1 -1
- package/dist/wasm-db.d.ts +63 -8
- package/dist/wasm-db.d.ts.map +1 -1
- package/dist/wasm-db.js +124 -31
- package/dist/wasm-db.js.map +1 -1
- package/package.json +14 -2
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { extractFacts } from './extractor.js';
|
|
4
|
+
import { DecayRate } from './types.js';
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Test fixtures
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
const testExchange = {
|
|
9
|
+
userMessage: 'I prefer dark mode for all my editors.',
|
|
10
|
+
agentResponse: 'Noted, I will use dark mode settings.',
|
|
11
|
+
timestamp: new Date('2026-01-01T12:00:00Z'),
|
|
12
|
+
source: 'openclaw',
|
|
13
|
+
sessionId: 'session-001',
|
|
14
|
+
sessionLabel: 'prefs-chat',
|
|
15
|
+
};
|
|
16
|
+
const testExchangeNoLabel = {
|
|
17
|
+
userMessage: 'I use TypeScript for everything.',
|
|
18
|
+
agentResponse: 'Great choice.',
|
|
19
|
+
timestamp: new Date('2026-01-01T13:00:00Z'),
|
|
20
|
+
source: 'openclaw',
|
|
21
|
+
sessionId: 'session-002',
|
|
22
|
+
};
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// In-memory mock store
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
function createMockStore() {
|
|
27
|
+
const stored = [];
|
|
28
|
+
const store = {
|
|
29
|
+
async store(fact) {
|
|
30
|
+
const id = crypto.randomUUID();
|
|
31
|
+
stored.push({ id, ...fact });
|
|
32
|
+
return id;
|
|
33
|
+
},
|
|
34
|
+
async search(_query, _limit) {
|
|
35
|
+
return [];
|
|
36
|
+
},
|
|
37
|
+
async delete(_id) { },
|
|
38
|
+
async status() {
|
|
39
|
+
return { factCount: stored.length, rawLogCount: 0, lastIngestion: null, storageBytes: 0 };
|
|
40
|
+
},
|
|
41
|
+
async ingest(_exchange) {
|
|
42
|
+
return { rawLogId: crypto.randomUUID(), factsExtracted: 0, factIds: [] };
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
return { store, stored };
|
|
46
|
+
}
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// LLM mock helpers
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
function mockLLM(responseJson) {
|
|
51
|
+
return async (_prompt) => JSON.stringify(responseJson);
|
|
52
|
+
}
|
|
53
|
+
function mockLLMWithFences(responseJson) {
|
|
54
|
+
return async (_prompt) => '```json\n' + JSON.stringify(responseJson) + '\n```';
|
|
55
|
+
}
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Tests: structured output parsing
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
test('extractFacts: parses a valid JSON array and stores each fact', async () => {
|
|
60
|
+
const { store, stored } = createMockStore();
|
|
61
|
+
const result = await extractFacts(testExchange, 'user-1', store, mockLLM([
|
|
62
|
+
{
|
|
63
|
+
subject: 'user',
|
|
64
|
+
predicate: 'prefers',
|
|
65
|
+
object: 'dark mode',
|
|
66
|
+
context: 'mentioned for all editors',
|
|
67
|
+
confidence: 0.9,
|
|
68
|
+
decay_rate: 'slow',
|
|
69
|
+
},
|
|
70
|
+
]));
|
|
71
|
+
assert.equal(result.length, 1);
|
|
72
|
+
assert.equal(result[0].subject, 'user');
|
|
73
|
+
assert.equal(result[0].predicate, 'prefers');
|
|
74
|
+
assert.equal(result[0].object, 'dark mode');
|
|
75
|
+
assert.equal(result[0].context, 'mentioned for all editors');
|
|
76
|
+
assert.equal(result[0].confidence, 0.9);
|
|
77
|
+
assert.equal(result[0].decayRate, DecayRate.slow);
|
|
78
|
+
assert.equal(result[0].sourceSessionId, 'session-001');
|
|
79
|
+
assert.equal(result[0].sourceSessionLabel, 'prefs-chat');
|
|
80
|
+
assert.match(result[0].id, /^[0-9a-f-]{36}$/);
|
|
81
|
+
assert.equal(stored.length, 1);
|
|
82
|
+
});
|
|
83
|
+
test('extractFacts: strips markdown code fences before parsing', async () => {
|
|
84
|
+
const { store } = createMockStore();
|
|
85
|
+
const result = await extractFacts(testExchange, 'user-1', store, mockLLMWithFences([
|
|
86
|
+
{ subject: 'user', predicate: 'uses', object: 'TypeScript', confidence: 0.95, decay_rate: 'medium' },
|
|
87
|
+
]));
|
|
88
|
+
assert.equal(result.length, 1);
|
|
89
|
+
assert.equal(result[0].object, 'TypeScript');
|
|
90
|
+
assert.equal(result[0].decayRate, DecayRate.medium);
|
|
91
|
+
});
|
|
92
|
+
test('extractFacts: returns [] and stores nothing when LLM returns []', async () => {
|
|
93
|
+
const { store, stored } = createMockStore();
|
|
94
|
+
const result = await extractFacts(testExchange, 'user-1', store, mockLLM([]));
|
|
95
|
+
assert.equal(result.length, 0);
|
|
96
|
+
assert.equal(stored.length, 0);
|
|
97
|
+
});
|
|
98
|
+
test('extractFacts: returns [] gracefully when LLM returns invalid JSON', async () => {
|
|
99
|
+
const { store, stored } = createMockStore();
|
|
100
|
+
const result = await extractFacts(testExchange, 'user-1', store, async () => 'This is definitely not JSON.');
|
|
101
|
+
assert.equal(result.length, 0);
|
|
102
|
+
assert.equal(stored.length, 0);
|
|
103
|
+
});
|
|
104
|
+
test('extractFacts: handles multiple facts in one LLM response', async () => {
|
|
105
|
+
const { store, stored } = createMockStore();
|
|
106
|
+
const result = await extractFacts(testExchange, 'user-1', store, mockLLM([
|
|
107
|
+
{ subject: 'user', predicate: 'prefers', object: 'dark mode', confidence: 0.9, decay_rate: 'slow' },
|
|
108
|
+
{ subject: 'user', predicate: 'uses', object: 'vim keybindings', confidence: 0.8, decay_rate: 'medium' },
|
|
109
|
+
]));
|
|
110
|
+
assert.equal(result.length, 2);
|
|
111
|
+
assert.equal(stored.length, 2);
|
|
112
|
+
});
|
|
113
|
+
test('extractFacts: clamps confidence to [0, 1]', async () => {
|
|
114
|
+
const { store } = createMockStore();
|
|
115
|
+
const result = await extractFacts(testExchange, 'user-1', store, mockLLM([
|
|
116
|
+
{ subject: 'a', predicate: 'b', object: 'c', confidence: 1.5, decay_rate: 'slow' },
|
|
117
|
+
{ subject: 'd', predicate: 'e', object: 'f', confidence: -0.3, decay_rate: 'fast' },
|
|
118
|
+
]));
|
|
119
|
+
assert.equal(result[0].confidence, 1.0);
|
|
120
|
+
assert.equal(result[1].confidence, 0.0);
|
|
121
|
+
});
|
|
122
|
+
test('extractFacts: unknown decay_rate defaults to medium', async () => {
|
|
123
|
+
const { store } = createMockStore();
|
|
124
|
+
const result = await extractFacts(testExchange, 'user-1', store, mockLLM([{ subject: 'a', predicate: 'b', object: 'c', confidence: 0.5, decay_rate: 'unknown-rate' }]));
|
|
125
|
+
assert.equal(result[0].decayRate, DecayRate.medium);
|
|
126
|
+
});
|
|
127
|
+
test('extractFacts: sourceSessionLabel is omitted when exchange has no sessionLabel', async () => {
|
|
128
|
+
const { store } = createMockStore();
|
|
129
|
+
const result = await extractFacts(testExchangeNoLabel, 'user-1', store, mockLLM([{ subject: 'user', predicate: 'uses', object: 'TypeScript', confidence: 0.9, decay_rate: 'slow' }]));
|
|
130
|
+
assert.equal(result[0].sourceSessionId, 'session-002');
|
|
131
|
+
assert.equal(result[0].sourceSessionLabel, undefined);
|
|
132
|
+
});
|
|
133
|
+
test('extractFacts: context field is omitted when LLM does not include it', async () => {
|
|
134
|
+
const { store } = createMockStore();
|
|
135
|
+
const result = await extractFacts(testExchange, 'user-1', store, mockLLM([{ subject: 'user', predicate: 'prefers', object: 'dark mode', confidence: 0.9, decay_rate: 'slow' }]));
|
|
136
|
+
assert.equal(result[0].context, undefined);
|
|
137
|
+
});
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
// Tests: deduplication strategy
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
test('extractFacts dedup: inserts new entry when same subject+predicate already exists', async () => {
|
|
142
|
+
const { store, stored } = createMockStore();
|
|
143
|
+
const singleFact = [
|
|
144
|
+
{ subject: 'user', predicate: 'prefers', object: 'dark mode', confidence: 0.9, decay_rate: 'slow' },
|
|
145
|
+
];
|
|
146
|
+
// First extraction
|
|
147
|
+
await extractFacts(testExchange, 'user-1', store, mockLLM(singleFact));
|
|
148
|
+
assert.equal(stored.length, 1);
|
|
149
|
+
// Second extraction with same subject+predicate
|
|
150
|
+
await extractFacts(testExchange, 'user-1', store, mockLLM(singleFact));
|
|
151
|
+
assert.equal(stored.length, 2, 'should insert new entry, not overwrite existing');
|
|
152
|
+
// Both entries have unique IDs
|
|
153
|
+
assert.notEqual(stored[0].id, stored[1].id);
|
|
154
|
+
// Both have same subject+predicate
|
|
155
|
+
assert.equal(stored[0].subject, stored[1].subject);
|
|
156
|
+
assert.equal(stored[0].predicate, stored[1].predicate);
|
|
157
|
+
});
|
|
158
|
+
//# sourceMappingURL=extractor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.test.js","sourceRoot":"","sources":["../src/extractor.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E,MAAM,YAAY,GAAoB;IACpC,WAAW,EAAE,wCAAwC;IACrD,aAAa,EAAE,uCAAuC;IACtD,SAAS,EAAE,IAAI,IAAI,CAAC,sBAAsB,CAAC;IAC3C,MAAM,EAAE,UAAU;IAClB,SAAS,EAAE,aAAa;IACxB,YAAY,EAAE,YAAY;CAC3B,CAAC;AAEF,MAAM,mBAAmB,GAAoB;IAC3C,WAAW,EAAE,kCAAkC;IAC/C,aAAa,EAAE,eAAe;IAC9B,SAAS,EAAE,IAAI,IAAI,CAAC,sBAAsB,CAAC;IAC3C,MAAM,EAAE,UAAU;IAClB,SAAS,EAAE,aAAa;CACzB,CAAC;AAEF,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E,SAAS,eAAe;IACtB,MAAM,MAAM,GAAW,EAAE,CAAC;IAE1B,MAAM,KAAK,GAAgB;QACzB,KAAK,CAAC,KAAK,CAAC,IAAsB;YAChC,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YAC/B,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;YAC7B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAe;YAC1C,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,GAAW,IAAkB,CAAC;QAC3C,KAAK,CAAC,MAAM;YACV,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;QAC5F,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,SAA0B;YACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC3E,CAAC;KACF,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,SAAS,OAAO,CAAC,YAAqB;IACpC,OAAO,KAAK,EAAE,OAAe,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,iBAAiB,CAAC,YAAqB;IAC9C,OAAO,KAAK,EAAE,OAAe,EAAE,EAAE,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC;AACzF,CAAC;AAED,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E;AAE9E,IAAI,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;IAC9E,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;IAE5C,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,OAAO,CAAC;QACN;YACE,OAAO,EAAE,MAAM;YACf,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,WAAW;YACnB,OAAO,EAAE,2BAA2B;YACpC,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,MAAM;SACnB;KACF,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,OAAO,EAAE,2BAA2B,CAAC,CAAC;IAC9D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;IACxD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC;IAC1D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAC;IAC/C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;IAC1E,MAAM,EAAE,KAAK,EAAE,GAAG,eAAe,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,iBAAiB,CAAC;QAChB,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE;KACrG,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;IACjF,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;IACnF,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,KAAK,IAAI,EAAE,CAAC,8BAA8B,CAC3C,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;IAC1E,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;IAE5C,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,OAAO,CAAC;QACN,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE;QACnG,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE;KACzG,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;IAC3D,MAAM,EAAE,KAAK,EAAE,GAAG,eAAe,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,OAAO,CAAC;QACN,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE;QAClF,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE;KACpF,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;IACrE,MAAM,EAAE,KAAK,EAAE,GAAG,eAAe,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC,CAAC,CACtG,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;IAC/F,MAAM,EAAE,KAAK,EAAE,GAAG,eAAe,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,mBAAmB,EACnB,QAAQ,EACR,KAAK,EACL,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,CAC7G,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;IACxD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;IACrF,MAAM,EAAE,KAAK,EAAE,GAAG,eAAe,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,CAC/G,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAC9C,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E,IAAI,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;IAClG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;IAE5C,MAAM,UAAU,GAAG;QACjB,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE;KACpG,CAAC;IAEF,mBAAmB;IACnB,MAAM,YAAY,CAAC,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IACvE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAE/B,gDAAgD;IAChD,MAAM,YAAY,CAAC,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IACvE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,iDAAiD,CAAC,CAAC;IAElF,+BAA+B;IAC/B,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC;IAE9C,mCAAmC;IACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,SAAS,CAAC,CAAC;AAC3D,CAAC,CAAC,CAAC"}
|
package/dist/fact-search.d.ts
CHANGED
|
@@ -19,10 +19,14 @@ import type { SearchResult } from './types.js';
|
|
|
19
19
|
/**
|
|
20
20
|
* Hybrid search over facts.
|
|
21
21
|
*
|
|
22
|
-
* @param db
|
|
23
|
-
* @param userId
|
|
24
|
-
* @param query
|
|
25
|
-
* @param limit
|
|
22
|
+
* @param db The WASM SQLite Database instance
|
|
23
|
+
* @param userId Scopes the search to this user's data
|
|
24
|
+
* @param query Natural language query string
|
|
25
|
+
* @param limit Number of results to return (default 20)
|
|
26
|
+
* @param preloadedCorpus Optional pre-loaded vec_facts corpus (T-096: in-memory cache)
|
|
26
27
|
*/
|
|
27
|
-
export declare function searchFacts(db: WasmDb, userId: string, query: string, limit?: number
|
|
28
|
+
export declare function searchFacts(db: WasmDb, userId: string, query: string, limit?: number, preloadedCorpus?: Array<{
|
|
29
|
+
rowid: number;
|
|
30
|
+
embedding: Float32Array;
|
|
31
|
+
}>): Promise<readonly SearchResult[]>;
|
|
28
32
|
//# sourceMappingURL=fact-search.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fact-search.d.ts","sourceRoot":"","sources":["../src/fact-search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA0F/C
|
|
1
|
+
{"version":3,"file":"fact-search.d.ts","sourceRoot":"","sources":["../src/fact-search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA0F/C;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,KAAK,SAAK,EACV,eAAe,CAAC,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC,GAClE,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC,CA2GlC"}
|
package/dist/fact-search.js
CHANGED
|
@@ -75,18 +75,19 @@ function rrf(vecRanked, bm25Ranked) {
|
|
|
75
75
|
/**
|
|
76
76
|
* Hybrid search over facts.
|
|
77
77
|
*
|
|
78
|
-
* @param db
|
|
79
|
-
* @param userId
|
|
80
|
-
* @param query
|
|
81
|
-
* @param limit
|
|
78
|
+
* @param db The WASM SQLite Database instance
|
|
79
|
+
* @param userId Scopes the search to this user's data
|
|
80
|
+
* @param query Natural language query string
|
|
81
|
+
* @param limit Number of results to return (default 20)
|
|
82
|
+
* @param preloadedCorpus Optional pre-loaded vec_facts corpus (T-096: in-memory cache)
|
|
82
83
|
*/
|
|
83
|
-
export async function searchFacts(db, userId, query, limit = 20) {
|
|
84
|
+
export async function searchFacts(db, userId, query, limit = 20, preloadedCorpus) {
|
|
84
85
|
// ── 1. Fetch all non-deleted fact rows for this user ────────────────────
|
|
85
86
|
const stmt = db.prepare(`SELECT id, user_id, subject, predicate, object, confidence,
|
|
86
87
|
decay_rate, timestamp, source_session_id, source_session_label,
|
|
87
88
|
context, deleted_at, vec_rowid
|
|
88
89
|
FROM facts
|
|
89
|
-
WHERE user_id = ? AND deleted_at IS NULL
|
|
90
|
+
WHERE user_id = ? AND deleted_at IS NULL AND confidence >= 0.65
|
|
90
91
|
ORDER BY timestamp DESC`);
|
|
91
92
|
stmt.bind([userId]);
|
|
92
93
|
const allRows = [];
|
|
@@ -106,17 +107,25 @@ export async function searchFacts(db, userId, query, limit = 20) {
|
|
|
106
107
|
.sort((a, b) => b[1] - a[1]);
|
|
107
108
|
// ── 3. Vector search via JS cosine similarity ───────────────────────────
|
|
108
109
|
const queryVec = await embedQuery(query);
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
// T-096: Use preloaded corpus if provided, otherwise fetch from vec_facts
|
|
111
|
+
let vecCorpus;
|
|
112
|
+
if (preloadedCorpus !== undefined) {
|
|
113
|
+
// Map rowid → id for knnSearch compatibility
|
|
114
|
+
vecCorpus = preloadedCorpus.map(entry => ({ id: entry.rowid, embedding: entry.embedding }));
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
// Fetch all embeddings from vec_facts (legacy path, used if cache not provided)
|
|
118
|
+
const vecStmt = db.prepare(`SELECT id, embedding FROM vec_facts`);
|
|
119
|
+
vecCorpus = [];
|
|
120
|
+
while (vecStmt.step()) {
|
|
121
|
+
const row = vecStmt.get({});
|
|
122
|
+
vecCorpus.push({
|
|
123
|
+
id: row.id,
|
|
124
|
+
embedding: deserializeEmbedding(row.embedding),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
vecStmt.finalize();
|
|
118
128
|
}
|
|
119
|
-
vecStmt.finalize();
|
|
120
129
|
// Perform KNN search
|
|
121
130
|
const vecFetchLimit = Math.min(allRows.length, Math.max(RERANK_TOP_K * 2, limit * 3, 50));
|
|
122
131
|
const vecResults = knnSearch(queryVec, vecCorpus, vecFetchLimit);
|
package/dist/fact-search.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fact-search.js","sourceRoot":"","sources":["../src/fact-search.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"fact-search.js","sourceRoot":"","sources":["../src/fact-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Layer 2 hybrid search (fact-search.ts).
|
|
3
|
+
*
|
|
4
|
+
* Stores 3 facts with distinct topics via store.store(), then verifies that
|
|
5
|
+
* search() 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.
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=fact-search.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-search.test.d.ts","sourceRoot":"","sources":["../src/fact-search.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Layer 2 hybrid search (fact-search.ts).
|
|
3
|
+
*
|
|
4
|
+
* Stores 3 facts with distinct topics via store.store(), then verifies that
|
|
5
|
+
* search() 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.
|
|
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
|
+
import { DecayRate } from './types.js';
|
|
18
|
+
const dbPath = join(tmpdir(), `plumb-fact-search-test-${Date.now()}.db`);
|
|
19
|
+
const store = new LocalStore({ dbPath, userId: 'fact-search-test-user' });
|
|
20
|
+
after(() => {
|
|
21
|
+
store.close();
|
|
22
|
+
rmSync(dbPath, { force: true });
|
|
23
|
+
});
|
|
24
|
+
// ─── Fixtures ────────────────────────────────────────────────────────────────
|
|
25
|
+
const FACTS = [
|
|
26
|
+
{
|
|
27
|
+
subject: 'Clay',
|
|
28
|
+
predicate: 'is actively searching for',
|
|
29
|
+
object: 'software engineering jobs',
|
|
30
|
+
context: 'Clay is looking at Samsara, applied to multiple companies, tracking applications and interviews',
|
|
31
|
+
confidence: 0.95,
|
|
32
|
+
decayRate: DecayRate.slow,
|
|
33
|
+
timestamp: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000), // 1 day ago
|
|
34
|
+
sourceSessionId: 'session-job-search',
|
|
35
|
+
sourceSessionLabel: 'job-search-chat',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
subject: 'Clay',
|
|
39
|
+
predicate: 'prefers',
|
|
40
|
+
object: 'TypeScript over JavaScript',
|
|
41
|
+
context: 'Clay mentioned preferring strict typing and has all projects configured with strict mode',
|
|
42
|
+
confidence: 0.9,
|
|
43
|
+
decayRate: DecayRate.slow,
|
|
44
|
+
timestamp: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000), // 5 days ago
|
|
45
|
+
sourceSessionId: 'session-ts-prefs',
|
|
46
|
+
sourceSessionLabel: 'typescript-chat',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
subject: 'chocolate cake recipe',
|
|
50
|
+
predicate: 'requires',
|
|
51
|
+
object: '200g butter and 50g cocoa powder',
|
|
52
|
+
context: 'Classic recipe baked at 180 degrees for 30 minutes with ganache frosting',
|
|
53
|
+
confidence: 0.85,
|
|
54
|
+
decayRate: DecayRate.fast,
|
|
55
|
+
timestamp: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000), // 2 days ago
|
|
56
|
+
sourceSessionId: 'session-cooking',
|
|
57
|
+
sourceSessionLabel: 'cooking-chat',
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
// ─── Store facts (shared setup) ──────────────────────────────────────────────
|
|
61
|
+
test('store 3 facts with distinct topics', { timeout: 120_000 }, async () => {
|
|
62
|
+
for (const fact of FACTS) {
|
|
63
|
+
const id = await store.store(fact);
|
|
64
|
+
assert.match(id, /^[0-9a-f-]{36}$/, 'id should be a UUID');
|
|
65
|
+
}
|
|
66
|
+
const status = await store.status();
|
|
67
|
+
assert.equal(status.factCount, 3, 'all 3 facts should be stored');
|
|
68
|
+
});
|
|
69
|
+
// ─── Search ──────────────────────────────────────────────────────────────────
|
|
70
|
+
test('search returns results with required SearchResult fields', { timeout: 120_000 }, async () => {
|
|
71
|
+
const results = await store.search('job search applications', 3);
|
|
72
|
+
assert.ok(results.length > 0, 'should return at least one result');
|
|
73
|
+
for (const r of results) {
|
|
74
|
+
assert.ok(typeof r.fact.id === 'string', 'fact.id must be a string');
|
|
75
|
+
assert.ok(typeof r.fact.subject === 'string', 'fact.subject must be a string');
|
|
76
|
+
assert.ok(typeof r.fact.predicate === 'string', 'fact.predicate must be a string');
|
|
77
|
+
assert.ok(typeof r.fact.object === 'string', 'fact.object must be a string');
|
|
78
|
+
assert.ok(typeof r.score === 'number', 'score must be a number');
|
|
79
|
+
assert.ok(typeof r.ageInDays === 'number', 'ageInDays must be a number');
|
|
80
|
+
assert.ok(r.fact.timestamp instanceof Date, 'timestamp must be a Date');
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
test('search ranks job-search fact first for job query', { timeout: 120_000 }, async () => {
|
|
84
|
+
const results = await store.search('job search applications Samsara', 3);
|
|
85
|
+
assert.ok(results.length > 0, 'should return results');
|
|
86
|
+
const top = results[0];
|
|
87
|
+
assert.ok(top !== undefined, 'should have a top result');
|
|
88
|
+
// The job-search fact should rank first.
|
|
89
|
+
assert.equal(top.fact.subject, 'Clay', 'top result subject should be Clay');
|
|
90
|
+
assert.ok(top.fact.object.includes('job') || top.fact.object.includes('engineering'), 'top result should be about job search');
|
|
91
|
+
});
|
|
92
|
+
test('search returns cooking fact in results for recipe query', { timeout: 120_000 }, async () => {
|
|
93
|
+
const results = await store.search('chocolate cake recipe baking', 3);
|
|
94
|
+
assert.ok(results.length > 0, 'should return results');
|
|
95
|
+
const cookingResult = results.find((r) => r.fact.sourceSessionId === 'session-cooking');
|
|
96
|
+
assert.ok(cookingResult !== undefined, 'cooking fact should appear in results');
|
|
97
|
+
});
|
|
98
|
+
test('search returns empty array when no facts exist', { timeout: 30_000 }, async () => {
|
|
99
|
+
const emptyStore = new LocalStore({
|
|
100
|
+
dbPath: join(tmpdir(), `plumb-fact-empty-${Date.now()}.db`),
|
|
101
|
+
userId: 'empty-user',
|
|
102
|
+
});
|
|
103
|
+
try {
|
|
104
|
+
const results = await emptyStore.search('anything', 5);
|
|
105
|
+
assert.deepEqual(results, []);
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
emptyStore.close();
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
test('benchmark smoke: job search query returns at least 1 result with correct subject', { timeout: 120_000 }, async () => {
|
|
112
|
+
const results = await store.search('job search applications', 5);
|
|
113
|
+
assert.ok(results.length >= 1, 'should return at least 1 result');
|
|
114
|
+
const jobResult = results.find((r) => r.fact.subject === 'Clay' && r.fact.object.includes('job'));
|
|
115
|
+
assert.ok(jobResult !== undefined, 'should find Clay job search fact');
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=fact-search.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-search.test.js","sourceRoot":"","sources":["../src/fact-search.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export { DecayRate } from './types.js';
|
|
1
|
+
export type { IngestResult, MessageExchange, StoreStatus } from './types.js';
|
|
3
2
|
export type { MemoryStore } from './store.js';
|
|
4
3
|
export type { RawLogChunk, ScoreResult } from './scorer.js';
|
|
5
|
-
export {
|
|
4
|
+
export { scoreRawLog } from './scorer.js';
|
|
6
5
|
export { LocalStore } from './local-store.js';
|
|
7
|
-
export type { LocalStoreOptions, RawLogSearchResult,
|
|
8
|
-
export { ExtractionQueue } from './extraction-queue.js';
|
|
9
|
-
export type { ExtractFn, ExtractionQueueOptions } from './extraction-queue.js';
|
|
10
|
-
export { extractFacts } from './extractor.js';
|
|
11
|
-
export { callLLM, callLLMWithConfig, resolveAnthropicKey } from './llm-client.js';
|
|
12
|
-
export type { LLMConfig } from './llm-client.js';
|
|
6
|
+
export type { LocalStoreOptions, RawLogSearchResult, RawLogEntry, ExportData } from './local-store.js';
|
|
13
7
|
export { embed, embedQuery, rerankScores, EMBED_DIM } from './embedder.js';
|
|
14
8
|
export { Bm25, tokenize } from './bm25.js';
|
|
15
9
|
export { chunkExchange, formatExchange, CHUNK_WORDS, OVERLAP_WORDS } from './chunker.js';
|
|
16
10
|
export type { Chunk } from './chunker.js';
|
|
17
11
|
export { searchRawLog } from './raw-log-search.js';
|
|
18
|
-
export type {
|
|
12
|
+
export type { RawChunk, MemoryContext, ReadPathOptions, ReadPathStore } from './read-path.js';
|
|
19
13
|
export { buildMemoryContext } from './read-path.js';
|
|
20
14
|
export { formatContextBlock, formatAge } from './context-builder.js';
|
|
15
|
+
export { openDb } from './wasm-db.js';
|
|
16
|
+
export type { WasmDb } from './wasm-db.js';
|
|
21
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACvG,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzF,YAAY,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,YAAY,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { computeDecay, scoreFact, scoreRawLog } from './scorer.js';
|
|
1
|
+
export { scoreRawLog } from './scorer.js';
|
|
3
2
|
export { LocalStore } from './local-store.js';
|
|
4
|
-
export { ExtractionQueue } from './extraction-queue.js';
|
|
5
|
-
export { extractFacts } from './extractor.js';
|
|
6
|
-
export { callLLM, callLLMWithConfig, resolveAnthropicKey } from './llm-client.js';
|
|
7
3
|
export { embed, embedQuery, rerankScores, EMBED_DIM } from './embedder.js';
|
|
8
4
|
export { Bm25, tokenize } from './bm25.js';
|
|
9
5
|
export { chunkExchange, formatExchange, CHUNK_WORDS, OVERLAP_WORDS } from './chunker.js';
|
|
10
6
|
export { searchRawLog } from './raw-log-search.js';
|
|
11
7
|
export { buildMemoryContext } from './read-path.js';
|
|
12
8
|
export { formatContextBlock, formatAge } from './context-builder.js';
|
|
9
|
+
export { openDb } from './wasm-db.js';
|
|
13
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEzF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/llm-client.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* When provided, these values take precedence over env vars.
|
|
4
4
|
*/
|
|
5
5
|
export interface LLMConfig {
|
|
6
|
-
/** Provider: 'openai' | 'anthropic' | 'ollama' | 'openai-compatible'. Defaults to 'openai'. */
|
|
6
|
+
/** Provider: 'google' (recommended) | 'openai' | 'anthropic' | 'ollama' | 'openai-compatible'. Defaults to 'openai'. */
|
|
7
7
|
provider?: string;
|
|
8
8
|
/** Model ID. Defaults to provider-specific default. */
|
|
9
9
|
model?: string;
|
|
@@ -30,10 +30,19 @@ export declare function resolveOpenAIKey(): string;
|
|
|
30
30
|
* @throws Error if no key is found
|
|
31
31
|
*/
|
|
32
32
|
export declare function resolveAnthropicKey(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the Gemini API key from environment variables.
|
|
35
|
+
* Returns the key if found, otherwise throws a clear error.
|
|
36
|
+
*
|
|
37
|
+
* Set GEMINI_API_KEY in your environment before using Plumb with the Google provider.
|
|
38
|
+
*
|
|
39
|
+
* @throws Error if no key is found
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveGeminiKey(): string;
|
|
33
42
|
/**
|
|
34
43
|
* Calls the configured LLM with the given prompt and returns the text response.
|
|
35
44
|
* Provider and model are configurable via env:
|
|
36
|
-
* PLUMB_LLM_PROVIDER — 'openai' (default), 'anthropic', 'ollama', 'openai-compatible'
|
|
45
|
+
* PLUMB_LLM_PROVIDER — 'openai' (default), 'anthropic', 'ollama', 'openai-compatible', 'google'
|
|
37
46
|
* PLUMB_LLM_MODEL — model ID, defaults vary per provider
|
|
38
47
|
* PLUMB_LLM_BASE_URL — for 'openai-compatible' provider
|
|
39
48
|
* OLLAMA_HOST — for 'ollama' provider (default: http://localhost:11434/v1)
|
package/dist/llm-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-client.d.ts","sourceRoot":"","sources":["../src/llm-client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"llm-client.d.ts","sourceRoot":"","sources":["../src/llm-client.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,wHAAwH;IACxH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAQzC;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAQ5C;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAQzC;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA2F7D;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAoF1F"}
|