@soleri/core 8.1.0 → 9.0.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.
- package/dist/brain/brain.d.ts +1 -8
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +5 -134
- package/dist/brain/brain.js.map +1 -1
- package/dist/cognee/client.d.ts +5 -0
- package/dist/cognee/client.d.ts.map +1 -1
- package/dist/cognee/client.js +83 -16
- package/dist/cognee/client.js.map +1 -1
- package/dist/cognee/sync-manager.d.ts +67 -8
- package/dist/cognee/sync-manager.d.ts.map +1 -1
- package/dist/cognee/sync-manager.js +129 -32
- package/dist/cognee/sync-manager.js.map +1 -1
- package/dist/cognee/types.d.ts +16 -0
- package/dist/cognee/types.d.ts.map +1 -1
- package/dist/context/context-engine.d.ts +2 -5
- package/dist/context/context-engine.d.ts.map +1 -1
- package/dist/context/context-engine.js +4 -31
- package/dist/context/context-engine.js.map +1 -1
- package/dist/curator/curator.d.ts +2 -5
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +4 -23
- package/dist/curator/curator.js.map +1 -1
- package/dist/engine/bin/soleri-engine.js +6 -5
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/engine/core-ops.d.ts.map +1 -1
- package/dist/engine/core-ops.js +11 -6
- package/dist/engine/core-ops.js.map +1 -1
- package/dist/engine/module-manifest.d.ts +1 -1
- package/dist/engine/module-manifest.d.ts.map +1 -1
- package/dist/engine/module-manifest.js +1 -7
- package/dist/engine/module-manifest.js.map +1 -1
- package/dist/engine/register-engine.d.ts.map +1 -1
- package/dist/engine/register-engine.js +0 -7
- package/dist/engine/register-engine.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/intelligence/types.d.ts +7 -0
- package/dist/intelligence/types.d.ts.map +1 -1
- package/dist/persona/defaults.d.ts +16 -0
- package/dist/persona/defaults.d.ts.map +1 -0
- package/dist/persona/defaults.js +78 -0
- package/dist/persona/defaults.js.map +1 -0
- package/dist/persona/index.d.ts +5 -0
- package/dist/persona/index.d.ts.map +1 -0
- package/dist/persona/index.js +4 -0
- package/dist/persona/index.js.map +1 -0
- package/dist/persona/loader.d.ts +11 -0
- package/dist/persona/loader.d.ts.map +1 -0
- package/dist/persona/loader.js +45 -0
- package/dist/persona/loader.js.map +1 -0
- package/dist/persona/prompt-generator.d.ts +13 -0
- package/dist/persona/prompt-generator.d.ts.map +1 -0
- package/dist/persona/prompt-generator.js +89 -0
- package/dist/persona/prompt-generator.js.map +1 -0
- package/dist/persona/types.d.ts +56 -0
- package/dist/persona/types.d.ts.map +1 -0
- package/dist/persona/types.js +9 -0
- package/dist/persona/types.js.map +1 -0
- package/dist/plugins/types.d.ts +13 -13
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
- package/dist/runtime/admin-extra-ops.js +5 -27
- package/dist/runtime/admin-extra-ops.js.map +1 -1
- package/dist/runtime/admin-ops.d.ts.map +1 -1
- package/dist/runtime/admin-ops.js +5 -37
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +32 -16
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/cognee-sync-ops.d.ts +2 -2
- package/dist/runtime/cognee-sync-ops.d.ts.map +1 -1
- package/dist/runtime/cognee-sync-ops.js +45 -7
- package/dist/runtime/cognee-sync-ops.js.map +1 -1
- package/dist/runtime/facades/index.d.ts +1 -1
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +1 -10
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +14 -53
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +6 -8
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-linking-ops.d.ts.map +1 -1
- package/dist/runtime/vault-linking-ops.js +40 -0
- package/dist/runtime/vault-linking-ops.js.map +1 -1
- package/dist/runtime/vault-sharing-ops.d.ts.map +1 -1
- package/dist/runtime/vault-sharing-ops.js +53 -3
- package/dist/runtime/vault-sharing-ops.js.map +1 -1
- package/dist/vault/linking.d.ts +37 -0
- package/dist/vault/linking.d.ts.map +1 -1
- package/dist/vault/linking.js +73 -0
- package/dist/vault/linking.js.map +1 -1
- package/dist/vault/vault.d.ts +0 -2
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +0 -13
- package/dist/vault/vault.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/admin-extra-ops.test.ts +0 -3
- package/src/__tests__/admin-ops.test.ts +1 -5
- package/src/__tests__/brain.test.ts +1 -225
- package/src/__tests__/context-engine.test.ts +1 -6
- package/src/__tests__/core-ops.test.ts +1 -8
- package/src/__tests__/curator-extra-ops.test.ts +0 -2
- package/src/__tests__/curator-pipeline-e2e.test.ts +3 -28
- package/src/__tests__/feature-flags.test.ts +0 -1
- package/src/__tests__/health-registry.test.ts +18 -18
- package/src/__tests__/replayable-stream.test.ts +3 -3
- package/src/brain/brain.ts +4 -157
- package/src/context/context-engine.ts +3 -31
- package/src/curator/curator.ts +5 -28
- package/src/engine/bin/soleri-engine.ts +6 -5
- package/src/engine/core-ops.ts +11 -6
- package/src/engine/module-manifest.ts +1 -7
- package/src/engine/register-engine.ts +0 -7
- package/src/index.ts +20 -16
- package/src/intelligence/types.ts +8 -0
- package/src/persona/defaults.ts +96 -0
- package/src/persona/index.ts +9 -0
- package/src/persona/loader.ts +50 -0
- package/src/persona/prompt-generator.ts +109 -0
- package/src/persona/types.ts +72 -0
- package/src/runtime/admin-extra-ops.ts +5 -28
- package/src/runtime/admin-ops.ts +5 -38
- package/src/runtime/capture-ops.ts +33 -14
- package/src/runtime/facades/index.ts +1 -11
- package/src/runtime/runtime.ts +14 -54
- package/src/runtime/types.ts +6 -8
- package/src/runtime/vault-linking-ops.ts +41 -0
- package/src/runtime/vault-sharing-ops.ts +63 -4
- package/src/vault/linking.ts +94 -0
- package/src/vault/vault.ts +0 -14
- package/src/__tests__/cognee-client-gaps.test.ts +0 -474
- package/src/__tests__/cognee-client.test.ts +0 -524
- package/src/__tests__/cognee-hybrid-search.test.ts +0 -492
- package/src/__tests__/cognee-integration.test.ts +0 -80
- package/src/__tests__/cognee-sync-manager-deep.test.ts +0 -654
- package/src/__tests__/cognee-sync-manager.test.ts +0 -104
- package/src/cognee/client.ts +0 -370
- package/src/cognee/sync-manager.ts +0 -389
- package/src/cognee/types.ts +0 -62
- package/src/runtime/cognee-sync-ops.ts +0 -63
- package/src/runtime/facades/cognee-facade.ts +0 -164
package/src/brain/brain.ts
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
cosineSimilarity,
|
|
11
11
|
jaccardSimilarity,
|
|
12
12
|
} from '../text/similarity.js';
|
|
13
|
-
import type { CogneeClient } from '../cognee/client.js';
|
|
14
13
|
import type {
|
|
15
14
|
ScoringWeights,
|
|
16
15
|
ScoreBreakdown,
|
|
@@ -44,15 +43,6 @@ const DEFAULT_WEIGHTS: ScoringWeights = {
|
|
|
44
43
|
domainMatch: 0.15,
|
|
45
44
|
};
|
|
46
45
|
|
|
47
|
-
const COGNEE_WEIGHTS: ScoringWeights = {
|
|
48
|
-
semantic: 0.25,
|
|
49
|
-
vector: 0.35,
|
|
50
|
-
severity: 0.1,
|
|
51
|
-
temporalDecay: 0.1,
|
|
52
|
-
tagOverlap: 0.1,
|
|
53
|
-
domainMatch: 0.1,
|
|
54
|
-
};
|
|
55
|
-
|
|
56
46
|
const WEIGHT_BOUND = 0.15;
|
|
57
47
|
const FEEDBACK_THRESHOLD = 30;
|
|
58
48
|
const DUPLICATE_BLOCK_THRESHOLD = 0.8;
|
|
@@ -62,14 +52,12 @@ const RECENCY_HALF_LIFE_DAYS = 365;
|
|
|
62
52
|
export class Brain {
|
|
63
53
|
private vault: Vault;
|
|
64
54
|
private vaultManager: VaultManager | undefined;
|
|
65
|
-
private cognee: CogneeClient | undefined;
|
|
66
55
|
private vocabulary: Map<string, number> = new Map();
|
|
67
56
|
private weights: ScoringWeights = { ...DEFAULT_WEIGHTS };
|
|
68
57
|
|
|
69
|
-
constructor(vault: Vault,
|
|
58
|
+
constructor(vault: Vault, vaultManager?: VaultManager) {
|
|
70
59
|
this.vault = vault;
|
|
71
60
|
this.vaultManager = vaultManager;
|
|
72
|
-
this.cognee = cognee;
|
|
73
61
|
this.rebuildVocabulary();
|
|
74
62
|
this.recomputeWeights();
|
|
75
63
|
}
|
|
@@ -102,97 +90,6 @@ export class Brain {
|
|
|
102
90
|
});
|
|
103
91
|
}
|
|
104
92
|
|
|
105
|
-
// Cognee vector search (parallel, with timeout fallback)
|
|
106
|
-
let cogneeScoreMap: Map<string, number> = new Map();
|
|
107
|
-
const cogneeAvailable = this.cognee?.isAvailable ?? false;
|
|
108
|
-
if (cogneeAvailable && this.cognee) {
|
|
109
|
-
try {
|
|
110
|
-
const cogneeResults = await this.cognee.search(query, { limit: Math.max(limit * 2, 20) });
|
|
111
|
-
|
|
112
|
-
// Build title → entryIds reverse index from FTS results for text-based matching.
|
|
113
|
-
// Cognee assigns its own UUIDs to chunks and may strip embedded metadata during
|
|
114
|
-
// chunking, so we need multiple strategies to cross-reference results.
|
|
115
|
-
// Multiple entries can share a title, so map to arrays of IDs.
|
|
116
|
-
const titleToIds = new Map<string, string[]>();
|
|
117
|
-
for (const r of rawResults) {
|
|
118
|
-
const key = r.entry.title.toLowerCase().trim();
|
|
119
|
-
const ids = titleToIds.get(key) ?? [];
|
|
120
|
-
ids.push(r.entry.id);
|
|
121
|
-
titleToIds.set(key, ids);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const vaultIdPattern = /\[vault-id:([^\]]+)\]/;
|
|
125
|
-
const unmatchedCogneeResults: Array<{ text: string; score: number }> = [];
|
|
126
|
-
|
|
127
|
-
for (const cr of cogneeResults) {
|
|
128
|
-
const text = cr.text ?? '';
|
|
129
|
-
|
|
130
|
-
// Strategy 1: Extract vault ID from [vault-id:XXX] prefix (if Cognee preserved it)
|
|
131
|
-
const vaultIdMatch = text.match(vaultIdPattern);
|
|
132
|
-
if (vaultIdMatch) {
|
|
133
|
-
const vaultId = vaultIdMatch[1];
|
|
134
|
-
cogneeScoreMap.set(vaultId, Math.max(cogneeScoreMap.get(vaultId) ?? 0, cr.score));
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Strategy 2: Match first line of chunk text against known entry titles.
|
|
139
|
-
// serializeEntry() puts the title on the first line after the [vault-id:] prefix,
|
|
140
|
-
// and Cognee's chunking typically preserves this as the chunk start.
|
|
141
|
-
const firstLine = text.split('\n')[0]?.trim().toLowerCase() ?? '';
|
|
142
|
-
const matchedIds = firstLine ? titleToIds.get(firstLine) : undefined;
|
|
143
|
-
if (matchedIds) {
|
|
144
|
-
for (const id of matchedIds) {
|
|
145
|
-
cogneeScoreMap.set(id, Math.max(cogneeScoreMap.get(id) ?? 0, cr.score));
|
|
146
|
-
}
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Strategy 3: Check if any known title appears as a substring in the chunk.
|
|
151
|
-
// Handles cases where the title isn't on the first line (mid-document chunks).
|
|
152
|
-
const textLower = text.toLowerCase();
|
|
153
|
-
let found = false;
|
|
154
|
-
for (const [title, ids] of titleToIds) {
|
|
155
|
-
if (title.length >= 8 && textLower.includes(title)) {
|
|
156
|
-
for (const id of ids) {
|
|
157
|
-
cogneeScoreMap.set(id, Math.max(cogneeScoreMap.get(id) ?? 0, cr.score));
|
|
158
|
-
}
|
|
159
|
-
found = true;
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
if (!found && text.length > 0) {
|
|
164
|
-
unmatchedCogneeResults.push({ text, score: cr.score });
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Strategy 4: For Cognee-only semantic matches (not in FTS results),
|
|
169
|
-
// use the first line as a vault FTS query to find the source entry.
|
|
170
|
-
// Preserve caller filters (domain/type/severity) to avoid reintroducing
|
|
171
|
-
// entries the original query excluded.
|
|
172
|
-
for (const unmatched of unmatchedCogneeResults) {
|
|
173
|
-
const searchTerm = unmatched.text.split('\n')[0]?.trim();
|
|
174
|
-
if (!searchTerm || searchTerm.length < 3) continue;
|
|
175
|
-
const vaultHits = this.vault.search(searchTerm, {
|
|
176
|
-
domain: options?.domain,
|
|
177
|
-
type: options?.type,
|
|
178
|
-
severity: options?.severity,
|
|
179
|
-
limit: 1,
|
|
180
|
-
});
|
|
181
|
-
if (vaultHits.length > 0) {
|
|
182
|
-
const id = vaultHits[0].entry.id;
|
|
183
|
-
cogneeScoreMap.set(id, Math.max(cogneeScoreMap.get(id) ?? 0, unmatched.score));
|
|
184
|
-
// Also add to FTS results pool if not already present
|
|
185
|
-
if (!rawResults.some((r) => r.entry.id === id)) {
|
|
186
|
-
rawResults.push(vaultHits[0]);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
} catch {
|
|
191
|
-
// Cognee failed — fall back to FTS5 only
|
|
192
|
-
cogneeScoreMap = new Map();
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
93
|
if (rawResults.length === 0) return [];
|
|
197
94
|
|
|
198
95
|
const seedCount = rawResults.length;
|
|
@@ -201,22 +98,9 @@ export class Brain {
|
|
|
201
98
|
const queryDomain = options?.domain;
|
|
202
99
|
const now = Math.floor(Date.now() / 1000);
|
|
203
100
|
|
|
204
|
-
// Use cognee-aware weights only if at least one ranked candidate has a vector score
|
|
205
|
-
const hasVectorCandidate = rawResults.some((r) => cogneeScoreMap.has(r.entry.id));
|
|
206
|
-
const activeWeights = hasVectorCandidate ? this.getCogneeWeights() : this.weights;
|
|
207
|
-
|
|
208
101
|
const ranked = rawResults.map((result) => {
|
|
209
102
|
const entry = result.entry;
|
|
210
|
-
const
|
|
211
|
-
const breakdown = this.scoreEntry(
|
|
212
|
-
entry,
|
|
213
|
-
queryTokens,
|
|
214
|
-
queryTags,
|
|
215
|
-
queryDomain,
|
|
216
|
-
now,
|
|
217
|
-
vectorScore,
|
|
218
|
-
activeWeights,
|
|
219
|
-
);
|
|
103
|
+
const breakdown = this.scoreEntry(entry, queryTokens, queryTags, queryDomain, now);
|
|
220
104
|
return { entry, score: breakdown.total, breakdown };
|
|
221
105
|
});
|
|
222
106
|
|
|
@@ -335,11 +219,6 @@ export class Brain {
|
|
|
335
219
|
this.vault.add(fullEntry);
|
|
336
220
|
this.updateVocabularyIncremental(fullEntry);
|
|
337
221
|
|
|
338
|
-
// Fire-and-forget Cognee sync
|
|
339
|
-
if (this.cognee?.isAvailable) {
|
|
340
|
-
this.cognee.addEntries([fullEntry]).catch(() => {});
|
|
341
|
-
}
|
|
342
|
-
|
|
343
222
|
const result: CaptureResult = {
|
|
344
223
|
captured: true,
|
|
345
224
|
id: entry.id,
|
|
@@ -465,32 +344,6 @@ export class Brain {
|
|
|
465
344
|
});
|
|
466
345
|
}
|
|
467
346
|
|
|
468
|
-
async syncToCognee(): Promise<{ synced: number; cognified: boolean }> {
|
|
469
|
-
if (!this.cognee?.isAvailable) return { synced: 0, cognified: false };
|
|
470
|
-
|
|
471
|
-
const batchSize = 1000;
|
|
472
|
-
let offset = 0;
|
|
473
|
-
let totalSynced = 0;
|
|
474
|
-
|
|
475
|
-
while (true) {
|
|
476
|
-
const batch = this.vault.list({ limit: batchSize, offset });
|
|
477
|
-
if (batch.length === 0) break;
|
|
478
|
-
|
|
479
|
-
const { added } = await this.cognee.addEntries(batch);
|
|
480
|
-
totalSynced += added;
|
|
481
|
-
offset += batch.length;
|
|
482
|
-
|
|
483
|
-
if (batch.length < batchSize) break;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
if (totalSynced === 0) return { synced: 0, cognified: false };
|
|
487
|
-
|
|
488
|
-
let cognified = false;
|
|
489
|
-
const cognifyResult = await this.cognee.cognify();
|
|
490
|
-
cognified = cognifyResult.status === 'ok';
|
|
491
|
-
return { synced: totalSynced, cognified };
|
|
492
|
-
}
|
|
493
|
-
|
|
494
347
|
rebuildVocabulary(): void {
|
|
495
348
|
// Collect entries from all connected sources when VaultManager is available
|
|
496
349
|
let entries: IntelligenceEntry[];
|
|
@@ -616,10 +469,8 @@ export class Brain {
|
|
|
616
469
|
queryTags: string[],
|
|
617
470
|
queryDomain: string | undefined,
|
|
618
471
|
now: number,
|
|
619
|
-
vectorScore: number = 0,
|
|
620
|
-
activeWeights?: ScoringWeights,
|
|
621
472
|
): ScoreBreakdown {
|
|
622
|
-
const w =
|
|
473
|
+
const w = this.weights;
|
|
623
474
|
|
|
624
475
|
let semantic = 0;
|
|
625
476
|
if (this.vocabulary.size > 0 && queryTokens.length > 0) {
|
|
@@ -643,7 +494,7 @@ export class Brain {
|
|
|
643
494
|
|
|
644
495
|
const domainMatch = queryDomain && entry.domain === queryDomain ? 1.0 : 0;
|
|
645
496
|
|
|
646
|
-
const vector =
|
|
497
|
+
const vector = 0;
|
|
647
498
|
|
|
648
499
|
const total =
|
|
649
500
|
w.semantic * semantic +
|
|
@@ -747,10 +598,6 @@ export class Brain {
|
|
|
747
598
|
tx();
|
|
748
599
|
}
|
|
749
600
|
|
|
750
|
-
private getCogneeWeights(): ScoringWeights {
|
|
751
|
-
return { ...COGNEE_WEIGHTS };
|
|
752
|
-
}
|
|
753
|
-
|
|
754
601
|
private recomputeWeights(): void {
|
|
755
602
|
const db = this.vault.getDb();
|
|
756
603
|
// Exclude 'failed' from weight computation — system errors don't indicate relevance
|
|
@@ -3,17 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Orchestrates three signals to enrich intent classification:
|
|
5
5
|
* 1. Entity extraction (regex-based, domain-agnostic)
|
|
6
|
-
* 2. Knowledge retrieval (vault FTS +
|
|
6
|
+
* 2. Knowledge retrieval (vault FTS + brain recommendations)
|
|
7
7
|
* 3. Confidence scoring (combines entity + knowledge signals)
|
|
8
8
|
*
|
|
9
|
-
* Graceful degradation: if Cognee is unavailable, vault-only.
|
|
10
9
|
* If vault is empty, keyword confidence from IntentRouter is unchanged.
|
|
11
10
|
*/
|
|
12
11
|
|
|
13
12
|
import type { Vault } from '../vault/vault.js';
|
|
14
13
|
import type { Brain } from '../brain/brain.js';
|
|
15
14
|
import type { BrainIntelligence } from '../brain/intelligence.js';
|
|
16
|
-
import type { CogneeClient } from '../cognee/client.js';
|
|
17
15
|
import type {
|
|
18
16
|
EntityType,
|
|
19
17
|
ExtractedEntity,
|
|
@@ -105,20 +103,17 @@ export class ContextEngine {
|
|
|
105
103
|
private vault: Vault;
|
|
106
104
|
private brain: Brain;
|
|
107
105
|
private brainIntelligence: BrainIntelligence;
|
|
108
|
-
private cognee: CogneeClient | null;
|
|
109
106
|
private config: Required<ContextEngineConfig>;
|
|
110
107
|
|
|
111
108
|
constructor(
|
|
112
109
|
vault: Vault,
|
|
113
110
|
brain: Brain,
|
|
114
111
|
brainIntelligence: BrainIntelligence,
|
|
115
|
-
cognee: CogneeClient | null,
|
|
116
112
|
config?: ContextEngineConfig,
|
|
117
113
|
) {
|
|
118
114
|
this.vault = vault;
|
|
119
115
|
this.brain = brain;
|
|
120
116
|
this.brainIntelligence = brainIntelligence;
|
|
121
|
-
this.cognee = cognee;
|
|
122
117
|
this.config = {
|
|
123
118
|
vaultSearchLimit: config?.vaultSearchLimit ?? 10,
|
|
124
119
|
cogneeSearchLimit: config?.cogneeSearchLimit ?? 10,
|
|
@@ -167,7 +162,6 @@ export class ContextEngine {
|
|
|
167
162
|
async retrieveKnowledge(prompt: string, domain?: string): Promise<KnowledgeRetrievalResult> {
|
|
168
163
|
const items: KnowledgeItem[] = [];
|
|
169
164
|
let vaultHits = 0;
|
|
170
|
-
let cogneeHits = 0;
|
|
171
165
|
let brainHits = 0;
|
|
172
166
|
|
|
173
167
|
// 1. Vault FTS search
|
|
@@ -208,29 +202,7 @@ export class ContextEngine {
|
|
|
208
202
|
// Vault search failed — continue with other sources
|
|
209
203
|
}
|
|
210
204
|
|
|
211
|
-
// 2.
|
|
212
|
-
if (this.cognee) {
|
|
213
|
-
try {
|
|
214
|
-
const cogneeResults = await this.cognee.search(prompt, {
|
|
215
|
-
limit: this.config.cogneeSearchLimit,
|
|
216
|
-
});
|
|
217
|
-
for (const r of cogneeResults) {
|
|
218
|
-
// Avoid duplicates from vault
|
|
219
|
-
if (items.some((i) => i.id === r.id)) continue;
|
|
220
|
-
items.push({
|
|
221
|
-
id: r.id,
|
|
222
|
-
title: r.text.slice(0, 100),
|
|
223
|
-
score: r.score,
|
|
224
|
-
source: 'cognee',
|
|
225
|
-
});
|
|
226
|
-
cogneeHits++;
|
|
227
|
-
}
|
|
228
|
-
} catch {
|
|
229
|
-
// Cognee unavailable — continue without
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// 3. Brain recommendations
|
|
205
|
+
// 2. Brain recommendations
|
|
234
206
|
try {
|
|
235
207
|
const recommendations = this.brainIntelligence.recommend({
|
|
236
208
|
domain,
|
|
@@ -255,7 +227,7 @@ export class ContextEngine {
|
|
|
255
227
|
items.sort((a, b) => b.score - a.score);
|
|
256
228
|
const filtered = items.filter((i) => i.score >= this.config.minScoreThreshold);
|
|
257
229
|
|
|
258
|
-
return { items: filtered, vaultHits, cogneeHits, brainHits };
|
|
230
|
+
return { items: filtered, vaultHits, cogneeHits: 0, brainHits };
|
|
259
231
|
}
|
|
260
232
|
|
|
261
233
|
// ─── Context Analysis ───────────────────────────────────────────
|
package/src/curator/curator.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Vault } from '../vault/vault.js';
|
|
2
2
|
import type { IntelligenceEntry } from '../intelligence/types.js';
|
|
3
|
-
import type { CogneeClient } from '../cognee/client.js';
|
|
4
3
|
import type { PersistenceProvider } from '../persistence/types.js';
|
|
5
4
|
import {
|
|
6
5
|
tokenize,
|
|
@@ -51,12 +50,10 @@ const DEFAULT_TAG_ALIASES: Array<[string, string]> = [
|
|
|
51
50
|
|
|
52
51
|
export class Curator {
|
|
53
52
|
private vault: Vault;
|
|
54
|
-
private cognee: CogneeClient | undefined;
|
|
55
53
|
private provider: PersistenceProvider;
|
|
56
54
|
|
|
57
|
-
constructor(vault: Vault
|
|
55
|
+
constructor(vault: Vault) {
|
|
58
56
|
this.vault = vault;
|
|
59
|
-
this.cognee = cognee;
|
|
60
57
|
this.provider = vault.getProvider();
|
|
61
58
|
this.initializeTables();
|
|
62
59
|
this.seedDefaultAliases();
|
|
@@ -378,8 +375,7 @@ export class Curator {
|
|
|
378
375
|
|
|
379
376
|
async detectContradictionsHybrid(threshold?: number): Promise<{
|
|
380
377
|
contradictions: Contradiction[];
|
|
381
|
-
|
|
382
|
-
method: 'hybrid' | 'tfidf-only';
|
|
378
|
+
method: 'tfidf-only';
|
|
383
379
|
}> {
|
|
384
380
|
const effectiveThreshold = threshold ?? DEFAULT_CONTRADICTION_THRESHOLD;
|
|
385
381
|
const entries = this.vault.list({ limit: 100000 });
|
|
@@ -387,14 +383,12 @@ export class Curator {
|
|
|
387
383
|
const patterns = entries.filter((e) => e.type === 'pattern');
|
|
388
384
|
|
|
389
385
|
if (antipatterns.length === 0 || patterns.length === 0) {
|
|
390
|
-
return { contradictions: [],
|
|
386
|
+
return { contradictions: [], method: 'tfidf-only' };
|
|
391
387
|
}
|
|
392
388
|
|
|
393
389
|
const vocabulary = this.buildVocabulary(entries);
|
|
394
390
|
const detected: Contradiction[] = [];
|
|
395
391
|
|
|
396
|
-
const cogneeAvailable = this.cognee?.isAvailable ?? false;
|
|
397
|
-
|
|
398
392
|
for (const ap of antipatterns) {
|
|
399
393
|
let candidates: IntelligenceEntry[];
|
|
400
394
|
try {
|
|
@@ -410,23 +404,7 @@ export class Curator {
|
|
|
410
404
|
for (const pattern of candidates) {
|
|
411
405
|
const pText = [pattern.title, pattern.description, pattern.context ?? ''].join(' ');
|
|
412
406
|
const pVec = calculateTfIdf(tokenize(pText), vocabulary);
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
let finalScore = tfidfScore;
|
|
416
|
-
if (cogneeAvailable && this.cognee) {
|
|
417
|
-
try {
|
|
418
|
-
const cogneeResults = await this.cognee.search(`${ap.title} ${pattern.title}`, {
|
|
419
|
-
limit: 5,
|
|
420
|
-
});
|
|
421
|
-
const cogneeScore =
|
|
422
|
-
cogneeResults.length > 0
|
|
423
|
-
? cogneeResults.reduce((sum, r) => sum + r.score, 0) / cogneeResults.length
|
|
424
|
-
: 0;
|
|
425
|
-
finalScore = 0.6 * tfidfScore + 0.4 * cogneeScore;
|
|
426
|
-
} catch {
|
|
427
|
-
finalScore = tfidfScore;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
407
|
+
const finalScore = cosineSimilarity(apVec, pVec);
|
|
430
408
|
|
|
431
409
|
if (finalScore >= effectiveThreshold) {
|
|
432
410
|
const result = this.provider.run(
|
|
@@ -446,8 +424,7 @@ export class Curator {
|
|
|
446
424
|
|
|
447
425
|
return {
|
|
448
426
|
contradictions: detected,
|
|
449
|
-
|
|
450
|
-
method: cogneeAvailable ? 'hybrid' : 'tfidf-only',
|
|
427
|
+
method: 'tfidf-only',
|
|
451
428
|
};
|
|
452
429
|
}
|
|
453
430
|
|
|
@@ -71,12 +71,13 @@ async function main(): Promise<void> {
|
|
|
71
71
|
? resolve((engineConfig.vault as string).replace(/^~/, homedir()))
|
|
72
72
|
: join(homedir(), `.${agentId}`, 'vault.db');
|
|
73
73
|
|
|
74
|
-
// 3. Create runtime
|
|
74
|
+
// 3. Create runtime (with persona from agent.yaml if present)
|
|
75
|
+
const personaConfig = config.persona as Record<string, unknown> | undefined;
|
|
75
76
|
const runtime = createAgentRuntime({
|
|
76
77
|
agentId,
|
|
77
78
|
vaultPath,
|
|
78
79
|
agentDir,
|
|
79
|
-
|
|
80
|
+
persona: personaConfig as import('../../persona/types.js').PersonaConfig | undefined,
|
|
80
81
|
});
|
|
81
82
|
|
|
82
83
|
console.error(`${tag} Vault: ${vaultPath}`);
|
|
@@ -175,14 +176,14 @@ async function main(): Promise<void> {
|
|
|
175
176
|
version: '1.0.0',
|
|
176
177
|
});
|
|
177
178
|
|
|
178
|
-
// 11. Register persona prompt
|
|
179
|
-
server.prompt('persona', 'Get agent persona and
|
|
179
|
+
// 11. Register persona prompt (uses composable persona system)
|
|
180
|
+
server.prompt('persona', 'Get agent persona and character instructions', () => ({
|
|
180
181
|
messages: [
|
|
181
182
|
{
|
|
182
183
|
role: 'user' as const,
|
|
183
184
|
content: {
|
|
184
185
|
type: 'text' as const,
|
|
185
|
-
text:
|
|
186
|
+
text: runtime.personaInstructions.instructions,
|
|
186
187
|
},
|
|
187
188
|
},
|
|
188
189
|
],
|
package/src/engine/core-ops.ts
CHANGED
|
@@ -101,26 +101,32 @@ export function createCoreOps(
|
|
|
101
101
|
|
|
102
102
|
// Build activation context
|
|
103
103
|
const s = runtime.vault.stats();
|
|
104
|
+
const persona = runtime.persona;
|
|
105
|
+
const personaInstructions = runtime.personaInstructions;
|
|
104
106
|
return {
|
|
105
107
|
activated: true,
|
|
106
108
|
agent: {
|
|
107
109
|
id: identity.id,
|
|
108
|
-
name:
|
|
110
|
+
name: persona.name,
|
|
109
111
|
role: identity.role,
|
|
110
112
|
description: identity.description,
|
|
111
113
|
format: 'filetree',
|
|
112
114
|
},
|
|
113
115
|
persona: {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
template: persona.template,
|
|
117
|
+
name: persona.name,
|
|
118
|
+
culture: persona.culture,
|
|
119
|
+
voice: persona.voice,
|
|
120
|
+
traits: persona.traits,
|
|
121
|
+
quirks: persona.quirks,
|
|
122
|
+
greeting: personaInstructions.greeting,
|
|
123
|
+
instructions: personaInstructions.instructions,
|
|
117
124
|
},
|
|
118
125
|
vault: {
|
|
119
126
|
connected: true,
|
|
120
127
|
entries: s.totalEntries,
|
|
121
128
|
domains: Object.keys(s.byDomain),
|
|
122
129
|
},
|
|
123
|
-
domains: identity.domains,
|
|
124
130
|
};
|
|
125
131
|
},
|
|
126
132
|
},
|
|
@@ -162,7 +168,6 @@ export function createCoreOps(
|
|
|
162
168
|
byType: s.byType,
|
|
163
169
|
},
|
|
164
170
|
engine: {
|
|
165
|
-
cognee: runtime.cognee !== null && runtime.cognee !== undefined,
|
|
166
171
|
brain: true,
|
|
167
172
|
curator: true,
|
|
168
173
|
planner: true,
|
|
@@ -84,16 +84,10 @@ export const ENGINE_MODULE_MANIFEST: ModuleManifestEntry[] = [
|
|
|
84
84
|
description: 'Chat transport — session management, response chunking, authentication.',
|
|
85
85
|
keyOps: ['chat_send', 'chat_history', 'chat_session'],
|
|
86
86
|
},
|
|
87
|
-
{
|
|
88
|
-
suffix: 'cognee',
|
|
89
|
-
description: 'Knowledge graph — Cognee search, sync, export, graph stats.',
|
|
90
|
-
keyOps: ['cognee_search', 'cognee_add', 'cognee_cognify'],
|
|
91
|
-
conditional: true,
|
|
92
|
-
},
|
|
93
87
|
];
|
|
94
88
|
|
|
95
89
|
/** Core facade ops (always present, not in ENGINE_MODULES) */
|
|
96
90
|
export const CORE_KEY_OPS = ['health', 'identity', 'register', 'activate'];
|
|
97
91
|
|
|
98
92
|
/** Engine major version — used for compatibility checks against domain packs. */
|
|
99
|
-
export const ENGINE_MAJOR_VERSION =
|
|
93
|
+
export const ENGINE_MAJOR_VERSION = 9;
|
|
@@ -32,7 +32,6 @@ import { createCuratorFacadeOps } from '../runtime/facades/curator-facade.js';
|
|
|
32
32
|
import { createLoopFacadeOps } from '../runtime/facades/loop-facade.js';
|
|
33
33
|
import { createOrchestrateFacadeOps } from '../runtime/facades/orchestrate-facade.js';
|
|
34
34
|
import { createControlFacadeOps } from '../runtime/facades/control-facade.js';
|
|
35
|
-
import { createCogneeFacadeOps } from '../runtime/facades/cognee-facade.js';
|
|
36
35
|
import { createContextFacadeOps } from '../runtime/facades/context-facade.js';
|
|
37
36
|
import { createAgencyFacadeOps } from '../runtime/facades/agency-facade.js';
|
|
38
37
|
import { createChatFacadeOps } from '../runtime/facades/chat-facade.js';
|
|
@@ -144,12 +143,6 @@ export const ENGINE_MODULES: ModuleDef[] = [
|
|
|
144
143
|
description: 'Chat transport — session management, response chunking, authentication.',
|
|
145
144
|
createOps: createChatFacadeOps,
|
|
146
145
|
},
|
|
147
|
-
{
|
|
148
|
-
suffix: 'cognee',
|
|
149
|
-
description: 'Knowledge graph — Cognee search, sync, export, graph stats.',
|
|
150
|
-
createOps: createCogneeFacadeOps,
|
|
151
|
-
condition: (rt) => rt.cognee !== null && rt.cognee !== undefined,
|
|
152
|
-
},
|
|
153
146
|
];
|
|
154
147
|
|
|
155
148
|
// ─── Core Registration ────────────────────────────────────────────────
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// ─── Intelligence ────────────────────────────────────────────────────
|
|
2
|
-
export type {
|
|
2
|
+
export type {
|
|
3
|
+
IntelligenceEntry,
|
|
4
|
+
IntelligenceBundle,
|
|
5
|
+
IntelligenceBundleLink,
|
|
6
|
+
} from './intelligence/types.js';
|
|
3
7
|
export { loadIntelligenceData, loadPacks } from './intelligence/loader.js';
|
|
4
8
|
|
|
5
9
|
// ─── Vault ───────────────────────────────────────────────────────────
|
|
@@ -249,21 +253,6 @@ export type {
|
|
|
249
253
|
BrowserToolResult,
|
|
250
254
|
} from './chat/index.js';
|
|
251
255
|
|
|
252
|
-
// ─── Cognee ─────────────────────────────────────────────────────────
|
|
253
|
-
export { CogneeClient } from './cognee/client.js';
|
|
254
|
-
export type {
|
|
255
|
-
CogneeConfig,
|
|
256
|
-
CogneeSearchResult,
|
|
257
|
-
CogneeSearchType,
|
|
258
|
-
CogneeStatus,
|
|
259
|
-
CogneeAddResult,
|
|
260
|
-
CogneeCognifyResult,
|
|
261
|
-
} from './cognee/types.js';
|
|
262
|
-
|
|
263
|
-
// ─── Cognee Sync ──────────────────────────────────────────────────────
|
|
264
|
-
export { CogneeSyncManager } from './cognee/sync-manager.js';
|
|
265
|
-
export type { SyncOp, SyncStatus, SyncQueueItem, SyncManagerStats } from './cognee/sync-manager.js';
|
|
266
|
-
|
|
267
256
|
// ─── Intake Pipeline ──────────────────────────────────────────────────
|
|
268
257
|
export { IntakePipeline } from './intake/intake-pipeline.js';
|
|
269
258
|
export { classifyChunk, VALID_TYPES, CLASSIFICATION_PROMPT } from './intake/content-classifier.js';
|
|
@@ -489,6 +478,21 @@ export type {
|
|
|
489
478
|
IntegrityResult,
|
|
490
479
|
} from './health/index.js';
|
|
491
480
|
|
|
481
|
+
// ─── Persona ──────────────────────────────────────────────────────────
|
|
482
|
+
export type {
|
|
483
|
+
PersonaConfig,
|
|
484
|
+
ArchivedPersona,
|
|
485
|
+
PersonaCreateInput,
|
|
486
|
+
PersonaSystemInstructions,
|
|
487
|
+
} from './persona/types.js';
|
|
488
|
+
export {
|
|
489
|
+
ITALIAN_CRAFTSPERSON,
|
|
490
|
+
PERSONA_TEMPLATES,
|
|
491
|
+
createDefaultPersona,
|
|
492
|
+
} from './persona/defaults.js';
|
|
493
|
+
export { loadPersona } from './persona/loader.js';
|
|
494
|
+
export { generatePersonaInstructions, getRandomSignoff } from './persona/prompt-generator.js';
|
|
495
|
+
|
|
492
496
|
// ─── Runtime Factory ────────────────────────────────────────────────
|
|
493
497
|
export { createAgentRuntime } from './runtime/runtime.js';
|
|
494
498
|
export { createSemanticFacades } from './runtime/facades/index.js';
|
|
@@ -17,8 +17,16 @@ export interface IntelligenceEntry {
|
|
|
17
17
|
validUntil?: number; // unix epoch — when entry expires (null = never)
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
export interface IntelligenceBundleLink {
|
|
21
|
+
sourceId: string;
|
|
22
|
+
targetId: string;
|
|
23
|
+
linkType: 'supports' | 'contradicts' | 'extends' | 'sequences';
|
|
24
|
+
note?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
20
27
|
export interface IntelligenceBundle {
|
|
21
28
|
domain: string;
|
|
22
29
|
version: string;
|
|
23
30
|
entries: IntelligenceEntry[];
|
|
31
|
+
links?: IntelligenceBundleLink[];
|
|
24
32
|
}
|