@soleri/core 2.8.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/dist/extensions/index.d.ts +3 -0
  2. package/dist/extensions/index.d.ts.map +1 -0
  3. package/dist/extensions/index.js +2 -0
  4. package/dist/extensions/index.js.map +1 -0
  5. package/dist/extensions/middleware.d.ts +13 -0
  6. package/dist/extensions/middleware.d.ts.map +1 -0
  7. package/dist/extensions/middleware.js +47 -0
  8. package/dist/extensions/middleware.js.map +1 -0
  9. package/dist/extensions/types.d.ts +64 -0
  10. package/dist/extensions/types.d.ts.map +1 -0
  11. package/dist/extensions/types.js +2 -0
  12. package/dist/extensions/types.js.map +1 -0
  13. package/dist/index.d.ts +8 -16
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +7 -16
  16. package/dist/index.js.map +1 -1
  17. package/dist/runtime/core-ops.d.ts +1 -1
  18. package/dist/runtime/core-ops.js +1 -1
  19. package/dist/runtime/facades/admin-facade.d.ts +8 -0
  20. package/dist/runtime/facades/admin-facade.d.ts.map +1 -0
  21. package/dist/runtime/facades/admin-facade.js +90 -0
  22. package/dist/runtime/facades/admin-facade.js.map +1 -0
  23. package/dist/runtime/facades/brain-facade.d.ts +8 -0
  24. package/dist/runtime/facades/brain-facade.d.ts.map +1 -0
  25. package/dist/runtime/facades/brain-facade.js +294 -0
  26. package/dist/runtime/facades/brain-facade.js.map +1 -0
  27. package/dist/runtime/facades/cognee-facade.d.ts +8 -0
  28. package/dist/runtime/facades/cognee-facade.d.ts.map +1 -0
  29. package/dist/runtime/facades/cognee-facade.js +154 -0
  30. package/dist/runtime/facades/cognee-facade.js.map +1 -0
  31. package/dist/runtime/facades/control-facade.d.ts +8 -0
  32. package/dist/runtime/facades/control-facade.d.ts.map +1 -0
  33. package/dist/runtime/facades/control-facade.js +244 -0
  34. package/dist/runtime/facades/control-facade.js.map +1 -0
  35. package/dist/runtime/facades/curator-facade.d.ts +8 -0
  36. package/dist/runtime/facades/curator-facade.d.ts.map +1 -0
  37. package/dist/runtime/facades/curator-facade.js +117 -0
  38. package/dist/runtime/facades/curator-facade.js.map +1 -0
  39. package/dist/runtime/facades/index.d.ts +10 -0
  40. package/dist/runtime/facades/index.d.ts.map +1 -0
  41. package/dist/runtime/facades/index.js +71 -0
  42. package/dist/runtime/facades/index.js.map +1 -0
  43. package/dist/runtime/facades/loop-facade.d.ts +8 -0
  44. package/dist/runtime/facades/loop-facade.d.ts.map +1 -0
  45. package/dist/runtime/facades/loop-facade.js +9 -0
  46. package/dist/runtime/facades/loop-facade.js.map +1 -0
  47. package/dist/runtime/facades/memory-facade.d.ts +8 -0
  48. package/dist/runtime/facades/memory-facade.d.ts.map +1 -0
  49. package/dist/runtime/facades/memory-facade.js +108 -0
  50. package/dist/runtime/facades/memory-facade.js.map +1 -0
  51. package/dist/runtime/facades/orchestrate-facade.d.ts +8 -0
  52. package/dist/runtime/facades/orchestrate-facade.d.ts.map +1 -0
  53. package/dist/runtime/facades/orchestrate-facade.js +58 -0
  54. package/dist/runtime/facades/orchestrate-facade.js.map +1 -0
  55. package/dist/runtime/facades/plan-facade.d.ts +8 -0
  56. package/dist/runtime/facades/plan-facade.d.ts.map +1 -0
  57. package/dist/runtime/facades/plan-facade.js +110 -0
  58. package/dist/runtime/facades/plan-facade.js.map +1 -0
  59. package/dist/runtime/facades/vault-facade.d.ts +8 -0
  60. package/dist/runtime/facades/vault-facade.d.ts.map +1 -0
  61. package/dist/runtime/facades/vault-facade.js +194 -0
  62. package/dist/runtime/facades/vault-facade.js.map +1 -0
  63. package/dist/runtime/vault-extra-ops.d.ts +2 -2
  64. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  65. package/dist/runtime/vault-extra-ops.js +37 -2
  66. package/dist/runtime/vault-extra-ops.js.map +1 -1
  67. package/dist/streams/index.d.ts +4 -0
  68. package/dist/streams/index.d.ts.map +1 -0
  69. package/dist/streams/index.js +3 -0
  70. package/dist/streams/index.js.map +1 -0
  71. package/dist/streams/normalize.d.ts +14 -0
  72. package/dist/streams/normalize.d.ts.map +1 -0
  73. package/dist/streams/normalize.js +43 -0
  74. package/dist/streams/normalize.js.map +1 -0
  75. package/dist/streams/replayable-stream.d.ts +19 -0
  76. package/dist/streams/replayable-stream.d.ts.map +1 -0
  77. package/dist/streams/replayable-stream.js +90 -0
  78. package/dist/streams/replayable-stream.js.map +1 -0
  79. package/dist/vault/content-hash.d.ts +16 -0
  80. package/dist/vault/content-hash.d.ts.map +1 -0
  81. package/dist/vault/content-hash.js +21 -0
  82. package/dist/vault/content-hash.js.map +1 -0
  83. package/dist/vault/vault.d.ts +9 -0
  84. package/dist/vault/vault.d.ts.map +1 -1
  85. package/dist/vault/vault.js +49 -3
  86. package/dist/vault/vault.js.map +1 -1
  87. package/package.json +1 -1
  88. package/src/__tests__/content-hash.test.ts +60 -0
  89. package/src/__tests__/core-ops.test.ts +10 -7
  90. package/src/__tests__/extensions.test.ts +233 -0
  91. package/src/__tests__/grading-ops.test.ts +2 -2
  92. package/src/__tests__/memory-cross-project-ops.test.ts +2 -2
  93. package/src/__tests__/normalize.test.ts +75 -0
  94. package/src/__tests__/playbook.test.ts +4 -4
  95. package/src/__tests__/replayable-stream.test.ts +66 -0
  96. package/src/__tests__/vault-extra-ops.test.ts +1 -1
  97. package/src/__tests__/vault.test.ts +72 -0
  98. package/src/extensions/index.ts +2 -0
  99. package/src/extensions/middleware.ts +53 -0
  100. package/src/extensions/types.ts +64 -0
  101. package/src/index.ts +14 -17
  102. package/src/runtime/facades/admin-facade.ts +101 -0
  103. package/src/runtime/facades/brain-facade.ts +331 -0
  104. package/src/runtime/facades/cognee-facade.ts +162 -0
  105. package/src/runtime/facades/control-facade.ts +279 -0
  106. package/src/runtime/facades/curator-facade.ts +132 -0
  107. package/src/runtime/facades/index.ts +74 -0
  108. package/src/runtime/facades/loop-facade.ts +12 -0
  109. package/src/runtime/facades/memory-facade.ts +114 -0
  110. package/src/runtime/facades/orchestrate-facade.ts +68 -0
  111. package/src/runtime/facades/plan-facade.ts +119 -0
  112. package/src/runtime/facades/vault-facade.ts +223 -0
  113. package/src/runtime/vault-extra-ops.ts +38 -2
  114. package/src/streams/index.ts +3 -0
  115. package/src/streams/normalize.ts +56 -0
  116. package/src/streams/replayable-stream.ts +92 -0
  117. package/src/vault/content-hash.ts +31 -0
  118. package/src/vault/vault.ts +73 -3
  119. package/src/runtime/core-ops.ts +0 -1443
package/src/index.ts CHANGED
@@ -29,8 +29,6 @@ export type {
29
29
  MergedPlaybook,
30
30
  PlaybookMatchResult,
31
31
  } from './playbooks/index.js';
32
- export { createPlaybookOps } from './runtime/playbook-ops.js';
33
-
34
32
  // ─── Text Utilities ─────────────────────────────────────────────────
35
33
  export {
36
34
  tokenize,
@@ -239,6 +237,10 @@ export {
239
237
  export { KeyPool, loadKeyPoolConfig } from './llm/key-pool.js';
240
238
  export type { KeyPoolFiles } from './llm/key-pool.js';
241
239
 
240
+ // ─── Extensions ──────────────────────────────────────────────────────
241
+ export type { AgentExtensions, OpMiddleware, MiddlewareContext } from './extensions/index.js';
242
+ export { wrapWithMiddleware } from './extensions/index.js';
243
+
242
244
  // ─── Facades ─────────────────────────────────────────────────────────
243
245
  export { registerFacade, registerAllFacades } from './facades/facade-factory.js';
244
246
  export { facadeInputSchema } from './facades/types.js';
@@ -285,22 +287,8 @@ export type { LogLevel, LogEntry, LogContext, LoggerConfig } from './logging/typ
285
287
 
286
288
  // ─── Runtime Factory ────────────────────────────────────────────────
287
289
  export { createAgentRuntime } from './runtime/runtime.js';
288
- export { createCoreOps } from './runtime/core-ops.js';
290
+ export { createSemanticFacades } from './runtime/facades/index.js';
289
291
  export { createDomainFacade, createDomainFacades } from './runtime/domain-ops.js';
290
- export { createPlanningExtraOps } from './runtime/planning-extra-ops.js';
291
- export { createMemoryExtraOps } from './runtime/memory-extra-ops.js';
292
- export { createVaultExtraOps } from './runtime/vault-extra-ops.js';
293
- export { createAdminOps } from './runtime/admin-ops.js';
294
- export { createAdminExtraOps } from './runtime/admin-extra-ops.js';
295
- export { createLoopOps } from './runtime/loop-ops.js';
296
- export { createOrchestrateOps } from './runtime/orchestrate-ops.js';
297
- export { createGradingOps } from './runtime/grading-ops.js';
298
- export { createCaptureOps } from './runtime/capture-ops.js';
299
- export { createCuratorExtraOps } from './runtime/curator-extra-ops.js';
300
- export { createProjectOps } from './runtime/project-ops.js';
301
- export { createMemoryCrossProjectOps } from './runtime/memory-cross-project-ops.js';
302
- export { createCogneeSyncOps } from './runtime/cognee-sync-ops.js';
303
- export { createIntakeOps } from './runtime/intake-ops.js';
304
292
  export type { AgentRuntimeConfig, AgentRuntime } from './runtime/types.js';
305
293
 
306
294
  // ─── Errors ────────────────────────────────────────────────────────────
@@ -337,6 +325,15 @@ export type {
337
325
  FtsSearchOptions,
338
326
  } from './persistence/index.js';
339
327
 
328
+ // ─── Streams ──────────────────────────────────────────────────────────
329
+ export { ReplayableStream } from './streams/index.js';
330
+ export { normalize, collect } from './streams/index.js';
331
+ export type { NestableInput } from './streams/index.js';
332
+
333
+ // ─── Content Hashing ──────────────────────────────────────────────────
334
+ export { computeContentHash } from './vault/content-hash.js';
335
+ export type { HashableEntry } from './vault/content-hash.js';
336
+
340
337
  // ─── Prompts ───────────────────────────────────────────────────────────
341
338
  export { TemplateManager, parseVariables, resolveIncludes } from './prompts/index.js';
342
339
  export type { PromptTemplate, TemplateVariable, RenderOptions } from './prompts/index.js';
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Admin facade — infrastructure ops.
3
+ * health, config, telemetry, tokens, LLM, prompts.
4
+ */
5
+
6
+ import { z } from 'zod';
7
+ import type { OpDefinition } from '../../facades/types.js';
8
+ import type { AgentRuntime } from '../types.js';
9
+ import { createAdminOps } from '../admin-ops.js';
10
+ import { createAdminExtraOps } from '../admin-extra-ops.js';
11
+
12
+ export function createAdminFacadeOps(runtime: AgentRuntime): OpDefinition[] {
13
+ const { llmClient, keyPool } = runtime;
14
+
15
+ return [
16
+ // ─── LLM (inline from core-ops.ts) ──────────────────────────
17
+ {
18
+ name: 'llm_rotate',
19
+ description:
20
+ 'Force rotate the active API key for a provider. Useful when rate-limited or key is failing.',
21
+ auth: 'write',
22
+ schema: z.object({
23
+ provider: z.enum(['openai', 'anthropic']),
24
+ }),
25
+ handler: async (params) => {
26
+ const provider = params.provider as 'openai' | 'anthropic';
27
+ const pool = keyPool[provider];
28
+ if (!pool.hasKeys) return { rotated: false, error: `No ${provider} keys configured` };
29
+ const newKey = pool.rotateOnError();
30
+ return {
31
+ rotated: newKey !== null,
32
+ activeKeyIndex: pool.activeKeyIndex,
33
+ poolSize: pool.poolSize,
34
+ exhausted: pool.exhausted,
35
+ };
36
+ },
37
+ },
38
+ {
39
+ name: 'llm_call',
40
+ description: 'Make an LLM completion call. Uses model routing config and key pool rotation.',
41
+ auth: 'write',
42
+ schema: z.object({
43
+ systemPrompt: z.string().describe('System prompt for the LLM.'),
44
+ userPrompt: z.string().describe('User prompt / task input.'),
45
+ model: z
46
+ .string()
47
+ .optional()
48
+ .describe('Model name. Routed via model-routing.json if omitted.'),
49
+ temperature: z.number().optional().describe('Sampling temperature (0-2). Default 0.3.'),
50
+ maxTokens: z.number().optional().describe('Max output tokens. Default 500.'),
51
+ caller: z.string().optional().describe('Caller name for routing. Default "core-ops".'),
52
+ task: z.string().optional().describe('Task name for routing.'),
53
+ }),
54
+ handler: async (params) => {
55
+ return llmClient.complete({
56
+ provider: 'openai',
57
+ model: (params.model as string) ?? '',
58
+ systemPrompt: params.systemPrompt as string,
59
+ userPrompt: params.userPrompt as string,
60
+ temperature: params.temperature as number | undefined,
61
+ maxTokens: params.maxTokens as number | undefined,
62
+ caller: (params.caller as string) ?? 'core-ops',
63
+ task: params.task as string | undefined,
64
+ });
65
+ },
66
+ },
67
+
68
+ // ─── Prompt Templates (inline from core-ops.ts) ─────────────
69
+ {
70
+ name: 'render_prompt',
71
+ description:
72
+ 'Render a prompt template with variable substitution. Templates are .prompt files loaded from the templates directory.',
73
+ auth: 'read' as const,
74
+ schema: z.object({
75
+ template: z.string().describe('Template name (without .prompt extension)'),
76
+ variables: z.record(z.string()).optional().default({}),
77
+ strict: z.boolean().optional().default(true),
78
+ }),
79
+ handler: async (params) => {
80
+ const rendered = runtime.templateManager.render(
81
+ params.template as string,
82
+ (params.variables ?? {}) as Record<string, string>,
83
+ { strict: params.strict as boolean },
84
+ );
85
+ return { rendered };
86
+ },
87
+ },
88
+ {
89
+ name: 'list_templates',
90
+ description: 'List all loaded prompt templates.',
91
+ auth: 'read' as const,
92
+ handler: async () => ({
93
+ templates: runtime.templateManager.listTemplates(),
94
+ }),
95
+ },
96
+
97
+ // ─── Satellite ops ───────────────────────────────────────────
98
+ ...createAdminOps(runtime),
99
+ ...createAdminExtraOps(runtime),
100
+ ];
101
+ }
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Brain facade — learning system ops.
3
+ * intelligence pipeline, strengths, feedback, sessions.
4
+ */
5
+
6
+ import { z } from 'zod';
7
+ import type { OpDefinition } from '../../facades/types.js';
8
+ import type { AgentRuntime } from '../types.js';
9
+
10
+ export function createBrainFacadeOps(runtime: AgentRuntime): OpDefinition[] {
11
+ const { brain, brainIntelligence, llmClient, keyPool, governance } = runtime;
12
+
13
+ return [
14
+ // ─── Brain (inline from core-ops.ts) ────────────────────────
15
+ {
16
+ name: 'record_feedback',
17
+ description:
18
+ 'Record feedback on a search result — accepted or dismissed. Used for adaptive weight tuning.',
19
+ auth: 'write',
20
+ schema: z.object({
21
+ query: z.string().describe('The original search query'),
22
+ entryId: z.string().describe('The entry ID that was accepted or dismissed'),
23
+ action: z.enum(['accepted', 'dismissed']),
24
+ }),
25
+ handler: async (params) => {
26
+ brain.recordFeedback(
27
+ params.query as string,
28
+ params.entryId as string,
29
+ params.action as 'accepted' | 'dismissed',
30
+ );
31
+ return {
32
+ recorded: true,
33
+ query: params.query,
34
+ entryId: params.entryId,
35
+ action: params.action,
36
+ };
37
+ },
38
+ },
39
+ {
40
+ name: 'brain_feedback',
41
+ description:
42
+ 'Enhanced feedback with typed actions (accepted/dismissed/modified/failed), source tracking, confidence, duration, and reason.',
43
+ auth: 'write',
44
+ schema: z.object({
45
+ query: z.string().describe('The original search query'),
46
+ entryId: z.string().describe('The entry ID'),
47
+ action: z.enum(['accepted', 'dismissed', 'modified', 'failed']),
48
+ source: z
49
+ .enum(['search', 'recommendation', 'tool-execution', 'explicit'])
50
+ .optional()
51
+ .describe("Feedback source. Default 'search'."),
52
+ confidence: z.number().optional().describe('Confidence 0-1. Default 0.6.'),
53
+ duration: z.number().optional().describe('Duration in ms.'),
54
+ context: z.string().optional().describe("JSON context string. Default '{}'."),
55
+ reason: z.string().optional().describe('Human-readable reason.'),
56
+ }),
57
+ handler: async (params) => {
58
+ const entry = brain.recordFeedback({
59
+ query: params.query as string,
60
+ entryId: params.entryId as string,
61
+ action: params.action as 'accepted' | 'dismissed' | 'modified' | 'failed',
62
+ source: params.source as
63
+ | 'search'
64
+ | 'recommendation'
65
+ | 'tool-execution'
66
+ | 'explicit'
67
+ | undefined,
68
+ confidence: params.confidence as number | undefined,
69
+ duration: params.duration as number | undefined,
70
+ context: params.context as string | undefined,
71
+ reason: params.reason as string | undefined,
72
+ });
73
+ return entry;
74
+ },
75
+ },
76
+ {
77
+ name: 'brain_feedback_stats',
78
+ description:
79
+ 'Feedback statistics — counts by action and source, acceptance rate, average confidence.',
80
+ auth: 'read',
81
+ handler: async () => {
82
+ return brain.getFeedbackStats();
83
+ },
84
+ },
85
+ {
86
+ name: 'rebuild_vocabulary',
87
+ description: 'Force rebuild the TF-IDF vocabulary from all vault entries.',
88
+ auth: 'write',
89
+ handler: async () => {
90
+ brain.rebuildVocabulary();
91
+ return { rebuilt: true, vocabularySize: brain.getVocabularySize() };
92
+ },
93
+ },
94
+ {
95
+ name: 'brain_stats',
96
+ description:
97
+ 'Get brain intelligence stats — vocabulary size, feedback count, current scoring weights, intelligence pipeline stats.',
98
+ auth: 'read',
99
+ handler: async () => {
100
+ const base = brain.getStats();
101
+ const intelligence = brainIntelligence.getStats();
102
+ return { ...base, intelligence };
103
+ },
104
+ },
105
+ {
106
+ name: 'brain_decay_report',
107
+ description:
108
+ 'Show temporal decay scores for entries matching a query — reveals which entries are expiring, active, or expired.',
109
+ auth: 'read',
110
+ schema: z.object({
111
+ query: z.string().describe('Search query to find entries'),
112
+ limit: z.number().optional().describe('Max results (default 10)'),
113
+ }),
114
+ handler: async (params) => {
115
+ const results = await brain.getDecayReport(
116
+ params.query as string,
117
+ (params.limit as number | undefined) ?? 10,
118
+ );
119
+ return { results, count: results.length };
120
+ },
121
+ },
122
+ {
123
+ name: 'llm_status',
124
+ description:
125
+ 'LLM client status — provider availability, key pool status, model routing config.',
126
+ auth: 'read',
127
+ handler: async () => {
128
+ const available = llmClient.isAvailable();
129
+ return {
130
+ providers: {
131
+ openai: {
132
+ available: available.openai,
133
+ keyPool: keyPool.openai.hasKeys ? keyPool.openai.getStatus() : null,
134
+ },
135
+ anthropic: {
136
+ available: available.anthropic,
137
+ keyPool: keyPool.anthropic.hasKeys ? keyPool.anthropic.getStatus() : null,
138
+ },
139
+ },
140
+ routes: llmClient.getRoutes(),
141
+ };
142
+ },
143
+ },
144
+
145
+ // ─── Brain Intelligence ──────────────────────────────────────
146
+ {
147
+ name: 'brain_session_context',
148
+ description:
149
+ 'Get recent session context — sessions, tool usage frequency, file change frequency.',
150
+ auth: 'read',
151
+ schema: z.object({
152
+ limit: z.number().optional().describe('Number of recent sessions. Default 10.'),
153
+ }),
154
+ handler: async (params) => {
155
+ return brainIntelligence.getSessionContext((params.limit as number) ?? 10);
156
+ },
157
+ },
158
+ {
159
+ name: 'brain_strengths',
160
+ description:
161
+ 'Get pattern strength scores. 4-signal scoring: usage (0-25) + spread (0-25) + success (0-25) + recency (0-25).',
162
+ auth: 'read',
163
+ schema: z.object({
164
+ domain: z.string().optional(),
165
+ minStrength: z.number().optional().describe('Minimum strength score (0-100).'),
166
+ limit: z.number().optional(),
167
+ }),
168
+ handler: async (params) => {
169
+ return brainIntelligence.getStrengths({
170
+ domain: params.domain as string | undefined,
171
+ minStrength: params.minStrength as number | undefined,
172
+ limit: (params.limit as number) ?? 50,
173
+ });
174
+ },
175
+ },
176
+ {
177
+ name: 'brain_global_patterns',
178
+ description:
179
+ 'Get cross-domain pattern registry — patterns that appear across multiple domains.',
180
+ auth: 'read',
181
+ schema: z.object({
182
+ limit: z.number().optional(),
183
+ }),
184
+ handler: async (params) => {
185
+ return brainIntelligence.getGlobalPatterns((params.limit as number) ?? 20);
186
+ },
187
+ },
188
+ {
189
+ name: 'brain_recommend',
190
+ description:
191
+ 'Get pattern recommendations for a task context. Matches domain, task terms, and source-specific acceptance rates against known strengths.',
192
+ auth: 'read',
193
+ schema: z.object({
194
+ domain: z.string().optional(),
195
+ task: z.string().optional().describe('Task description for contextual matching.'),
196
+ source: z
197
+ .string()
198
+ .optional()
199
+ .describe(
200
+ 'Feedback source to boost by (search, recommendation, tool-execution, explicit).',
201
+ ),
202
+ limit: z.number().optional(),
203
+ }),
204
+ handler: async (params) => {
205
+ return brainIntelligence.recommend({
206
+ domain: params.domain as string | undefined,
207
+ task: params.task as string | undefined,
208
+ source: params.source as string | undefined,
209
+ limit: (params.limit as number) ?? 5,
210
+ });
211
+ },
212
+ },
213
+ {
214
+ name: 'brain_build_intelligence',
215
+ description:
216
+ 'Run the full intelligence pipeline: compute strengths → build global registry → build domain profiles.',
217
+ auth: 'write',
218
+ handler: async () => {
219
+ return brainIntelligence.buildIntelligence();
220
+ },
221
+ },
222
+ {
223
+ name: 'brain_export',
224
+ description:
225
+ 'Export all brain intelligence data — strengths, sessions, proposals, global patterns, domain profiles.',
226
+ auth: 'read',
227
+ handler: async () => {
228
+ return brainIntelligence.exportData();
229
+ },
230
+ },
231
+ {
232
+ name: 'brain_import',
233
+ description: 'Import brain intelligence data from a previous export.',
234
+ auth: 'write',
235
+ schema: z.object({
236
+ data: z.any().describe('BrainExportData object from brain_export.'),
237
+ }),
238
+ handler: async (params) => {
239
+ return brainIntelligence.importData(
240
+ params.data as import('../../brain/types.js').BrainExportData,
241
+ );
242
+ },
243
+ },
244
+ {
245
+ name: 'brain_extract_knowledge',
246
+ description:
247
+ 'Extract knowledge proposals from a session using 6 heuristic rules (repeated tools, multi-file edits, long sessions, plan outcomes, feedback ratios).',
248
+ auth: 'write',
249
+ schema: z.object({
250
+ sessionId: z.string().describe('Session ID to extract knowledge from.'),
251
+ }),
252
+ handler: async (params) => {
253
+ return brainIntelligence.extractKnowledge(params.sessionId as string);
254
+ },
255
+ },
256
+ {
257
+ name: 'brain_archive_sessions',
258
+ description: 'Archive (delete) completed sessions older than N days.',
259
+ auth: 'write',
260
+ schema: z.object({
261
+ olderThanDays: z.number().optional().describe('Days threshold. Default 30.'),
262
+ }),
263
+ handler: async (params) => {
264
+ return brainIntelligence.archiveSessions((params.olderThanDays as number) ?? 30);
265
+ },
266
+ },
267
+ {
268
+ name: 'brain_promote_proposals',
269
+ description:
270
+ 'Promote knowledge proposals to vault entries. Creates intelligence entries from auto-extracted patterns. Gated by governance policies.',
271
+ auth: 'write',
272
+ schema: z.object({
273
+ proposalIds: z.array(z.string()).describe('IDs of proposals to promote.'),
274
+ projectPath: z.string().optional().default('.'),
275
+ }),
276
+ handler: async (params) => {
277
+ const pp = (params.projectPath as string | undefined) ?? '.';
278
+ return brainIntelligence.promoteProposals(params.proposalIds as string[], governance, pp);
279
+ },
280
+ },
281
+ {
282
+ name: 'brain_lifecycle',
283
+ description:
284
+ 'Start or end a brain session. Sessions track tool usage, file changes, and plan context.',
285
+ auth: 'write',
286
+ schema: z.object({
287
+ action: z.enum(['start', 'end']),
288
+ sessionId: z
289
+ .string()
290
+ .optional()
291
+ .describe('Required for end. Auto-generated for start if omitted.'),
292
+ domain: z.string().optional(),
293
+ context: z.string().optional(),
294
+ toolsUsed: z.array(z.string()).optional(),
295
+ filesModified: z.array(z.string()).optional(),
296
+ planId: z.string().optional(),
297
+ planOutcome: z.string().optional(),
298
+ }),
299
+ handler: async (params) => {
300
+ return brainIntelligence.lifecycle({
301
+ action: params.action as 'start' | 'end',
302
+ sessionId: params.sessionId as string | undefined,
303
+ domain: params.domain as string | undefined,
304
+ context: params.context as string | undefined,
305
+ toolsUsed: params.toolsUsed as string[] | undefined,
306
+ filesModified: params.filesModified as string[] | undefined,
307
+ planId: params.planId as string | undefined,
308
+ planOutcome: params.planOutcome as string | undefined,
309
+ });
310
+ },
311
+ },
312
+ {
313
+ name: 'brain_reset_extracted',
314
+ description:
315
+ 'Reset extraction status on brain sessions, allowing re-extraction. Filter by sessionId, since date, or all.',
316
+ auth: 'write',
317
+ schema: z.object({
318
+ sessionId: z.string().optional().describe('Reset a specific session.'),
319
+ since: z.string().optional().describe('Reset sessions extracted since this ISO date.'),
320
+ all: z.boolean().optional().describe('Reset all extracted sessions.'),
321
+ }),
322
+ handler: async (params) => {
323
+ return brainIntelligence.resetExtracted({
324
+ sessionId: params.sessionId as string | undefined,
325
+ since: params.since as string | undefined,
326
+ all: params.all as boolean | undefined,
327
+ });
328
+ },
329
+ },
330
+ ];
331
+ }
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Cognee facade — knowledge graph ops.
3
+ * Cognee search, sync, export, graph stats.
4
+ */
5
+
6
+ import { z } from 'zod';
7
+ import type { OpDefinition } from '../../facades/types.js';
8
+ import type { IntelligenceEntry } from '../../intelligence/types.js';
9
+ import type { AgentRuntime } from '../types.js';
10
+ import type { CogneeSearchType } from '../../cognee/types.js';
11
+ import { createCogneeSyncOps } from '../cognee-sync-ops.js';
12
+
13
+ export function createCogneeFacadeOps(runtime: AgentRuntime): OpDefinition[] {
14
+ const { cognee, vault, syncManager } = runtime;
15
+
16
+ return [
17
+ // ─── Cognee (inline from core-ops.ts) ───────────────────────
18
+ {
19
+ name: 'cognee_status',
20
+ description:
21
+ 'Cognee vector search health — availability, URL, latency. Checks the Cognee API endpoint.',
22
+ auth: 'read',
23
+ handler: async () => {
24
+ return cognee.healthCheck();
25
+ },
26
+ },
27
+ {
28
+ name: 'cognee_search',
29
+ description:
30
+ 'Vector similarity search via Cognee. Complements TF-IDF vault search with semantic understanding.',
31
+ auth: 'read',
32
+ schema: z.object({
33
+ query: z.string(),
34
+ searchType: z
35
+ .enum([
36
+ 'SUMMARIES',
37
+ 'CHUNKS',
38
+ 'RAG_COMPLETION',
39
+ 'TRIPLET_COMPLETION',
40
+ 'GRAPH_COMPLETION',
41
+ 'GRAPH_SUMMARY_COMPLETION',
42
+ 'NATURAL_LANGUAGE',
43
+ 'GRAPH_COMPLETION_COT',
44
+ 'FEELING_LUCKY',
45
+ 'CHUNKS_LEXICAL',
46
+ ])
47
+ .optional()
48
+ .describe('Cognee search type. Default CHUNKS (pure vector similarity).'),
49
+ limit: z.number().optional(),
50
+ }),
51
+ handler: async (params) => {
52
+ return cognee.search(params.query as string, {
53
+ searchType: params.searchType as CogneeSearchType | undefined,
54
+ limit: (params.limit as number) ?? 10,
55
+ });
56
+ },
57
+ },
58
+ {
59
+ name: 'cognee_add',
60
+ description:
61
+ 'Ingest vault entries into Cognee for vector indexing. Auto-schedules cognify after ingest.',
62
+ auth: 'write',
63
+ schema: z.object({
64
+ entryIds: z.array(z.string()).describe('Vault entry IDs to ingest into Cognee.'),
65
+ }),
66
+ handler: async (params) => {
67
+ const ids = params.entryIds as string[];
68
+ const entries = ids
69
+ .map((id) => vault.get(id))
70
+ .filter((e): e is IntelligenceEntry => e !== null && e !== undefined);
71
+ if (entries.length === 0) return { added: 0, error: 'No matching vault entries found' };
72
+ return cognee.addEntries(entries);
73
+ },
74
+ },
75
+ {
76
+ name: 'cognee_cognify',
77
+ description:
78
+ 'Trigger Cognee knowledge graph processing on the vault dataset. Usually auto-scheduled after add.',
79
+ auth: 'write',
80
+ handler: async () => {
81
+ return cognee.cognify();
82
+ },
83
+ },
84
+ {
85
+ name: 'cognee_config',
86
+ description: 'Get current Cognee client configuration and cached health status.',
87
+ auth: 'read',
88
+ handler: async () => {
89
+ return { config: cognee.getConfig(), cachedStatus: cognee.getStatus() };
90
+ },
91
+ },
92
+ // ─── Cognee Graph ────────────────────────────────────────────
93
+ {
94
+ name: 'cognee_get_node',
95
+ description: 'Get a specific Cognee graph node by UUID with all properties and connections.',
96
+ auth: 'read',
97
+ schema: z.object({
98
+ nodeId: z.string().describe('UUID of the graph node'),
99
+ }),
100
+ handler: async (params) => {
101
+ try {
102
+ const results = await cognee.search(params.nodeId as string, {
103
+ searchType: 'GRAPH_COMPLETION' as CogneeSearchType,
104
+ limit: 1,
105
+ });
106
+ if (!results || (Array.isArray(results) && results.length === 0)) {
107
+ return { found: false, nodeId: params.nodeId };
108
+ }
109
+ return {
110
+ found: true,
111
+ nodeId: params.nodeId,
112
+ node: Array.isArray(results) ? results[0] : results,
113
+ };
114
+ } catch (err) {
115
+ return { error: (err as Error).message };
116
+ }
117
+ },
118
+ },
119
+ {
120
+ name: 'cognee_graph_stats',
121
+ description:
122
+ 'Cognee graph statistics — availability, endpoint, latency from last health check.',
123
+ auth: 'read',
124
+ handler: async () => {
125
+ try {
126
+ const status = cognee.getStatus();
127
+ const health = await cognee.healthCheck();
128
+ return {
129
+ available: status?.available ?? false,
130
+ url: status?.url ?? cognee.getConfig().baseUrl,
131
+ latencyMs: status?.latencyMs ?? health.latencyMs ?? null,
132
+ error: status?.error ?? health.error ?? null,
133
+ };
134
+ } catch (err) {
135
+ return { error: (err as Error).message };
136
+ }
137
+ },
138
+ },
139
+ {
140
+ name: 'cognee_export_status',
141
+ description: 'Check Cognee dataset and processing status — availability, pending operations.',
142
+ auth: 'read',
143
+ handler: async () => {
144
+ try {
145
+ const status = cognee.getStatus();
146
+ const config = cognee.getConfig();
147
+ return {
148
+ available: status?.available ?? false,
149
+ dataset: config.dataset ?? 'default',
150
+ pendingCognify: false,
151
+ url: status?.url ?? config.baseUrl,
152
+ };
153
+ } catch (err) {
154
+ return { error: (err as Error).message };
155
+ }
156
+ },
157
+ },
158
+
159
+ // ─── Satellite ops ───────────────────────────────────────────
160
+ ...createCogneeSyncOps(syncManager),
161
+ ];
162
+ }