@soleri/forge 4.1.0 → 4.2.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.
@@ -4,20 +4,20 @@
4
4
  */
5
5
  export function generateCoreFacade(config) {
6
6
  return `import { z } from 'zod';
7
- import type { FacadeConfig, Vault, IntelligenceEntry, Planner, Brain, KeyPool } from '@soleri/core';
7
+ import type { FacadeConfig, Vault, IntelligenceEntry, Planner, Brain, KeyPool, CogneeClient } from '@soleri/core';
8
8
  import { PERSONA } from '../identity/persona.js';
9
9
  import { activateAgent, deactivateAgent } from '../activation/activate.js';
10
10
  import { injectClaudeMd, injectClaudeMdGlobal, hasAgentMarker } from '../activation/inject-claude-md.js';
11
11
  import type { LLMClient } from '../llm/llm-client.js';
12
12
 
13
- export function createCoreFacade(vault: Vault, planner: Planner, brain: Brain, llmClient?: LLMClient, openaiKeyPool?: KeyPool, anthropicKeyPool?: KeyPool): FacadeConfig {
13
+ export function createCoreFacade(vault: Vault, planner: Planner, brain: Brain, cognee?: CogneeClient, llmClient?: LLMClient, openaiKeyPool?: KeyPool, anthropicKeyPool?: KeyPool): FacadeConfig {
14
14
  return {
15
15
  name: '${config.id}_core',
16
16
  description: 'Core operations — vault stats, cross-domain search, health check, identity, and activation system.',
17
17
  ops: [
18
18
  {
19
19
  name: 'search',
20
- description: 'Search across all knowledge domains. Results ranked by TF-IDF + severity + recency + tag overlap + domain match.',
20
+ description: 'Search across all knowledge domains. Results ranked by TF-IDF + severity + recency + tag overlap + domain match. When Cognee is available, adds vector similarity for hybrid ranking.',
21
21
  auth: 'read',
22
22
  schema: z.object({
23
23
  query: z.string(),
@@ -28,7 +28,7 @@ export function createCoreFacade(vault: Vault, planner: Planner, brain: Brain, l
28
28
  limit: z.number().optional(),
29
29
  }),
30
30
  handler: async (params) => {
31
- return brain.intelligentSearch(params.query as string, {
31
+ return await brain.intelligentSearch(params.query as string, {
32
32
  domain: params.domain as string | undefined,
33
33
  type: params.type as string | undefined,
34
34
  severity: params.severity as string | undefined,
@@ -448,6 +448,66 @@ export function createCoreFacade(vault: Vault, planner: Planner, brain: Brain, l
448
448
  };
449
449
  },
450
450
  },
451
+ {
452
+ name: 'cognee_status',
453
+ description: 'Check Cognee vector search availability and connection status.',
454
+ auth: 'read',
455
+ handler: async () => {
456
+ if (!cognee) return { available: false, message: 'Cognee not configured' };
457
+ const status = cognee.getStatus();
458
+ const cfg = cognee.getConfig();
459
+ return {
460
+ available: cognee.isAvailable,
461
+ config: {
462
+ baseUrl: cfg.baseUrl,
463
+ dataset: cfg.dataset,
464
+ timeoutMs: cfg.timeoutMs,
465
+ searchTimeoutMs: cfg.searchTimeoutMs,
466
+ healthTimeoutMs: cfg.healthTimeoutMs,
467
+ healthCacheTtlMs: cfg.healthCacheTtlMs,
468
+ cognifyDebounceMs: cfg.cognifyDebounceMs,
469
+ hasApiToken: Boolean(cfg.apiToken),
470
+ hasServiceCredentials: Boolean(cfg.serviceEmail && cfg.servicePassword),
471
+ },
472
+ lastHealth: status,
473
+ };
474
+ },
475
+ },
476
+ {
477
+ name: 'cognee_sync',
478
+ description: 'Force sync all vault entries to Cognee and trigger knowledge graph build. Requires Cognee to be running.',
479
+ auth: 'write',
480
+ handler: async () => {
481
+ if (!cognee?.isAvailable) {
482
+ return { synced: false, message: 'Cognee not available. Start with: docker compose -f docker/docker-compose.cognee.yml up -d' };
483
+ }
484
+ const result = await brain.syncToCognee();
485
+ return { ok: true, entriesSynced: result.synced, cognified: result.cognified };
486
+ },
487
+ },
488
+ {
489
+ name: 'graph_search',
490
+ description: 'Search using Cognee knowledge graph completion. Returns semantically related entries that keyword search might miss.',
491
+ auth: 'read',
492
+ schema: z.object({
493
+ query: z.string(),
494
+ searchType: z.enum(['SUMMARIES', 'CHUNKS', 'RAG_COMPLETION', 'GRAPH_COMPLETION', 'GRAPH_SUMMARY_COMPLETION', 'NATURAL_LANGUAGE', 'FEELING_LUCKY', 'CHUNKS_LEXICAL']).optional().default('CHUNKS'),
495
+ limit: z.number().optional().default(10),
496
+ }),
497
+ handler: async (params) => {
498
+ if (!cognee?.isAvailable) {
499
+ return { results: [], message: 'Cognee not available — use search op for FTS5 results' };
500
+ }
501
+ const results = await cognee.search(
502
+ params.query as string,
503
+ {
504
+ searchType: params.searchType as 'SUMMARIES' | 'CHUNKS' | 'GRAPH_COMPLETION',
505
+ limit: params.limit as number,
506
+ },
507
+ );
508
+ return { results, count: results.length };
509
+ },
510
+ },
451
511
  ],
452
512
  };
453
513
  }
@@ -1 +1 @@
1
- {"version":3,"file":"core-facade.js","sourceRoot":"","sources":["../../src/templates/core-facade.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IACpD,OAAO;;;;;;;;;aASI,MAAM,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uGA2EiF,MAAM,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCA6D9E,MAAM,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gEAiCiB,MAAM,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8Q1E,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"core-facade.js","sourceRoot":"","sources":["../../src/templates/core-facade.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IACpD,OAAO;;;;;;;;;aASI,MAAM,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uGA2EiF,MAAM,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCA6D9E,MAAM,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gEAiCiB,MAAM,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0U1E,CAAC;AACF,CAAC"}
@@ -20,7 +20,7 @@ import { dirname, join } from 'node:path';
20
20
  import { fileURLToPath } from 'node:url';
21
21
  import { homedir } from 'node:os';
22
22
 
23
- import { Vault, Brain, Planner, KeyPool, loadKeyPoolConfig, loadIntelligenceData, registerAllFacades } from '@soleri/core';
23
+ import { Vault, Brain, Planner, KeyPool, CogneeClient, loadKeyPoolConfig, loadIntelligenceData, registerAllFacades } from '@soleri/core';
24
24
  ${facadeImports}
25
25
  import { createCoreFacade } from './facades/core.facade.js';
26
26
  import { LLMClient } from './llm/llm-client.js';
@@ -49,10 +49,29 @@ async function main(): Promise<void> {
49
49
  const planner = new Planner(plansPath);
50
50
  console.error(\`[\${PERSONA.name.toLowerCase()}] Planner: \${plansPath}\`);
51
51
 
52
+ // Initialize Cognee client (optional — vector search + knowledge graph)
53
+ // Auto-registers a service account on first use. Override with env vars.
54
+ const cognee = new CogneeClient({
55
+ baseUrl: process.env.COGNEE_URL ?? 'http://localhost:8000',
56
+ dataset: '${config.id}-vault',
57
+ ...(process.env.COGNEE_API_TOKEN ? { apiToken: process.env.COGNEE_API_TOKEN } : {}),
58
+ ...(process.env.COGNEE_EMAIL ? { serviceEmail: process.env.COGNEE_EMAIL } : {}),
59
+ ...(process.env.COGNEE_PASSWORD ? { servicePassword: process.env.COGNEE_PASSWORD } : {}),
60
+ });
61
+ await cognee.healthCheck();
62
+ console.error(\`[\${PERSONA.name.toLowerCase()}] Cognee: \${cognee.isAvailable ? 'available' : 'not running (FTS5 fallback)'}\`);
63
+
52
64
  // Initialize brain — intelligence layer for ranked search, auto-tagging, dedup
53
- const brain = new Brain(vault);
65
+ const brain = new Brain(vault, cognee.isAvailable ? cognee : undefined);
54
66
  console.error(\`[\${PERSONA.name.toLowerCase()}] Brain: vocabulary \${brain.getVocabularySize()} terms\`);
55
67
 
68
+ // Background sync vault to Cognee if available
69
+ if (cognee.isAvailable) {
70
+ brain.syncToCognee().catch((err) => {
71
+ console.error(\`[\${PERSONA.name.toLowerCase()}] Cognee sync failed:\`, err);
72
+ });
73
+ }
74
+
56
75
  // Initialize LLM client (optional — works without API keys)
57
76
  const keyPoolFiles = loadKeyPoolConfig('${config.id}');
58
77
  const openaiKeyPool = new KeyPool(keyPoolFiles.openai);
@@ -75,7 +94,7 @@ async function main(): Promise<void> {
75
94
  // Create and register facades
76
95
  const facades = [
77
96
  ${facadeCreations}
78
- createCoreFacade(vault, planner, brain, llmClient, openaiKeyPool, anthropicKeyPool),
97
+ createCoreFacade(vault, planner, brain, cognee.isAvailable ? cognee : undefined, llmClient, openaiKeyPool, anthropicKeyPool),
79
98
  ];
80
99
 
81
100
  registerAllFacades(server, facades);
@@ -1 +1 @@
1
- {"version":3,"file":"entry-point.js","sourceRoot":"","sources":["../../src/templates/entry-point.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IACpD,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO;SACjC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,EAAE,GAAG,SAAS,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC;QAC9B,OAAO,YAAY,EAAE,sBAAsB,IAAI,IAAI,CAAC;IACtD,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO;SACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,UAAU,CAAC,CAAC,CAAC,uBAAuB,CAAC;SAC7D,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO;;;;;;;;;EASP,aAAa;;;;;;;;yCAQ0B,MAAM,CAAC,EAAE;wCACV,MAAM,CAAC,EAAE;;;;;;;;;;;;;;gCAcjB,MAAM,CAAC,EAAE;wCACD,MAAM,CAAC,EAAE;;;;;;;;;4CASL,MAAM,CAAC,EAAE;;;;;;;;;aASxC,MAAM,CAAC,EAAE;;;;;;;;;;;EAWpB,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBA4BG,MAAM,CAAC,EAAE;;;CAG5B,CAAC;AACF,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC;SACL,KAAK,CAAC,SAAS,CAAC;SAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAClD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"entry-point.js","sourceRoot":"","sources":["../../src/templates/entry-point.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IACpD,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO;SACjC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,EAAE,GAAG,SAAS,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC;QAC9B,OAAO,YAAY,EAAE,sBAAsB,IAAI,IAAI,CAAC;IACtD,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO;SACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,UAAU,CAAC,CAAC,CAAC,uBAAuB,CAAC;SAC7D,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO;;;;;;;;;EASP,aAAa;;;;;;;;yCAQ0B,MAAM,CAAC,EAAE;wCACV,MAAM,CAAC,EAAE;;;;;;;;;;;;;;gCAcjB,MAAM,CAAC,EAAE;wCACD,MAAM,CAAC,EAAE;;;;;;;;gBAQjC,MAAM,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;4CAoBmB,MAAM,CAAC,EAAE;;;;;;;;;aASxC,MAAM,CAAC,EAAE;;;;;;;;;;;EAWpB,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBA4BG,MAAM,CAAC,EAAE;;;CAG5B,CAAC;AACF,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC;SACL,KAAK,CAAC,SAAS,CAAC;SAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAClD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
@@ -21,7 +21,7 @@ export function generatePackageJson(config) {
21
21
  dependencies: {
22
22
  '@anthropic-ai/sdk': '^0.39.0',
23
23
  '@modelcontextprotocol/sdk': '^1.12.1',
24
- '@soleri/core': '^1.0.0',
24
+ '@soleri/core': '^2.0.0',
25
25
  zod: '^3.24.2',
26
26
  },
27
27
  devDependencies: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soleri/forge",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "Scaffold AI agents that learn, remember, and grow with you.",
5
5
  "keywords": [
6
6
  "agent",
@@ -6,20 +6,20 @@ import type { AgentConfig } from '../types.js';
6
6
  */
7
7
  export function generateCoreFacade(config: AgentConfig): string {
8
8
  return `import { z } from 'zod';
9
- import type { FacadeConfig, Vault, IntelligenceEntry, Planner, Brain, KeyPool } from '@soleri/core';
9
+ import type { FacadeConfig, Vault, IntelligenceEntry, Planner, Brain, KeyPool, CogneeClient } from '@soleri/core';
10
10
  import { PERSONA } from '../identity/persona.js';
11
11
  import { activateAgent, deactivateAgent } from '../activation/activate.js';
12
12
  import { injectClaudeMd, injectClaudeMdGlobal, hasAgentMarker } from '../activation/inject-claude-md.js';
13
13
  import type { LLMClient } from '../llm/llm-client.js';
14
14
 
15
- export function createCoreFacade(vault: Vault, planner: Planner, brain: Brain, llmClient?: LLMClient, openaiKeyPool?: KeyPool, anthropicKeyPool?: KeyPool): FacadeConfig {
15
+ export function createCoreFacade(vault: Vault, planner: Planner, brain: Brain, cognee?: CogneeClient, llmClient?: LLMClient, openaiKeyPool?: KeyPool, anthropicKeyPool?: KeyPool): FacadeConfig {
16
16
  return {
17
17
  name: '${config.id}_core',
18
18
  description: 'Core operations — vault stats, cross-domain search, health check, identity, and activation system.',
19
19
  ops: [
20
20
  {
21
21
  name: 'search',
22
- description: 'Search across all knowledge domains. Results ranked by TF-IDF + severity + recency + tag overlap + domain match.',
22
+ description: 'Search across all knowledge domains. Results ranked by TF-IDF + severity + recency + tag overlap + domain match. When Cognee is available, adds vector similarity for hybrid ranking.',
23
23
  auth: 'read',
24
24
  schema: z.object({
25
25
  query: z.string(),
@@ -30,7 +30,7 @@ export function createCoreFacade(vault: Vault, planner: Planner, brain: Brain, l
30
30
  limit: z.number().optional(),
31
31
  }),
32
32
  handler: async (params) => {
33
- return brain.intelligentSearch(params.query as string, {
33
+ return await brain.intelligentSearch(params.query as string, {
34
34
  domain: params.domain as string | undefined,
35
35
  type: params.type as string | undefined,
36
36
  severity: params.severity as string | undefined,
@@ -450,6 +450,66 @@ export function createCoreFacade(vault: Vault, planner: Planner, brain: Brain, l
450
450
  };
451
451
  },
452
452
  },
453
+ {
454
+ name: 'cognee_status',
455
+ description: 'Check Cognee vector search availability and connection status.',
456
+ auth: 'read',
457
+ handler: async () => {
458
+ if (!cognee) return { available: false, message: 'Cognee not configured' };
459
+ const status = cognee.getStatus();
460
+ const cfg = cognee.getConfig();
461
+ return {
462
+ available: cognee.isAvailable,
463
+ config: {
464
+ baseUrl: cfg.baseUrl,
465
+ dataset: cfg.dataset,
466
+ timeoutMs: cfg.timeoutMs,
467
+ searchTimeoutMs: cfg.searchTimeoutMs,
468
+ healthTimeoutMs: cfg.healthTimeoutMs,
469
+ healthCacheTtlMs: cfg.healthCacheTtlMs,
470
+ cognifyDebounceMs: cfg.cognifyDebounceMs,
471
+ hasApiToken: Boolean(cfg.apiToken),
472
+ hasServiceCredentials: Boolean(cfg.serviceEmail && cfg.servicePassword),
473
+ },
474
+ lastHealth: status,
475
+ };
476
+ },
477
+ },
478
+ {
479
+ name: 'cognee_sync',
480
+ description: 'Force sync all vault entries to Cognee and trigger knowledge graph build. Requires Cognee to be running.',
481
+ auth: 'write',
482
+ handler: async () => {
483
+ if (!cognee?.isAvailable) {
484
+ return { synced: false, message: 'Cognee not available. Start with: docker compose -f docker/docker-compose.cognee.yml up -d' };
485
+ }
486
+ const result = await brain.syncToCognee();
487
+ return { ok: true, entriesSynced: result.synced, cognified: result.cognified };
488
+ },
489
+ },
490
+ {
491
+ name: 'graph_search',
492
+ description: 'Search using Cognee knowledge graph completion. Returns semantically related entries that keyword search might miss.',
493
+ auth: 'read',
494
+ schema: z.object({
495
+ query: z.string(),
496
+ searchType: z.enum(['SUMMARIES', 'CHUNKS', 'RAG_COMPLETION', 'GRAPH_COMPLETION', 'GRAPH_SUMMARY_COMPLETION', 'NATURAL_LANGUAGE', 'FEELING_LUCKY', 'CHUNKS_LEXICAL']).optional().default('CHUNKS'),
497
+ limit: z.number().optional().default(10),
498
+ }),
499
+ handler: async (params) => {
500
+ if (!cognee?.isAvailable) {
501
+ return { results: [], message: 'Cognee not available — use search op for FTS5 results' };
502
+ }
503
+ const results = await cognee.search(
504
+ params.query as string,
505
+ {
506
+ searchType: params.searchType as 'SUMMARIES' | 'CHUNKS' | 'GRAPH_COMPLETION',
507
+ limit: params.limit as number,
508
+ },
509
+ );
510
+ return { results, count: results.length };
511
+ },
512
+ },
453
513
  ],
454
514
  };
455
515
  }
@@ -24,7 +24,7 @@ import { dirname, join } from 'node:path';
24
24
  import { fileURLToPath } from 'node:url';
25
25
  import { homedir } from 'node:os';
26
26
 
27
- import { Vault, Brain, Planner, KeyPool, loadKeyPoolConfig, loadIntelligenceData, registerAllFacades } from '@soleri/core';
27
+ import { Vault, Brain, Planner, KeyPool, CogneeClient, loadKeyPoolConfig, loadIntelligenceData, registerAllFacades } from '@soleri/core';
28
28
  ${facadeImports}
29
29
  import { createCoreFacade } from './facades/core.facade.js';
30
30
  import { LLMClient } from './llm/llm-client.js';
@@ -53,10 +53,29 @@ async function main(): Promise<void> {
53
53
  const planner = new Planner(plansPath);
54
54
  console.error(\`[\${PERSONA.name.toLowerCase()}] Planner: \${plansPath}\`);
55
55
 
56
+ // Initialize Cognee client (optional — vector search + knowledge graph)
57
+ // Auto-registers a service account on first use. Override with env vars.
58
+ const cognee = new CogneeClient({
59
+ baseUrl: process.env.COGNEE_URL ?? 'http://localhost:8000',
60
+ dataset: '${config.id}-vault',
61
+ ...(process.env.COGNEE_API_TOKEN ? { apiToken: process.env.COGNEE_API_TOKEN } : {}),
62
+ ...(process.env.COGNEE_EMAIL ? { serviceEmail: process.env.COGNEE_EMAIL } : {}),
63
+ ...(process.env.COGNEE_PASSWORD ? { servicePassword: process.env.COGNEE_PASSWORD } : {}),
64
+ });
65
+ await cognee.healthCheck();
66
+ console.error(\`[\${PERSONA.name.toLowerCase()}] Cognee: \${cognee.isAvailable ? 'available' : 'not running (FTS5 fallback)'}\`);
67
+
56
68
  // Initialize brain — intelligence layer for ranked search, auto-tagging, dedup
57
- const brain = new Brain(vault);
69
+ const brain = new Brain(vault, cognee.isAvailable ? cognee : undefined);
58
70
  console.error(\`[\${PERSONA.name.toLowerCase()}] Brain: vocabulary \${brain.getVocabularySize()} terms\`);
59
71
 
72
+ // Background sync vault to Cognee if available
73
+ if (cognee.isAvailable) {
74
+ brain.syncToCognee().catch((err) => {
75
+ console.error(\`[\${PERSONA.name.toLowerCase()}] Cognee sync failed:\`, err);
76
+ });
77
+ }
78
+
60
79
  // Initialize LLM client (optional — works without API keys)
61
80
  const keyPoolFiles = loadKeyPoolConfig('${config.id}');
62
81
  const openaiKeyPool = new KeyPool(keyPoolFiles.openai);
@@ -79,7 +98,7 @@ async function main(): Promise<void> {
79
98
  // Create and register facades
80
99
  const facades = [
81
100
  ${facadeCreations}
82
- createCoreFacade(vault, planner, brain, llmClient, openaiKeyPool, anthropicKeyPool),
101
+ createCoreFacade(vault, planner, brain, cognee.isAvailable ? cognee : undefined, llmClient, openaiKeyPool, anthropicKeyPool),
83
102
  ];
84
103
 
85
104
  registerAllFacades(server, facades);
@@ -23,7 +23,7 @@ export function generatePackageJson(config: AgentConfig): string {
23
23
  dependencies: {
24
24
  '@anthropic-ai/sdk': '^0.39.0',
25
25
  '@modelcontextprotocol/sdk': '^1.12.1',
26
- '@soleri/core': '^1.0.0',
26
+ '@soleri/core': '^2.0.0',
27
27
  zod: '^3.24.2',
28
28
  },
29
29
  devDependencies: {