@soleri/core 7.0.0 → 8.1.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/dist/agency/agency-manager.d.ts +27 -1
- package/dist/agency/agency-manager.d.ts.map +1 -1
- package/dist/agency/agency-manager.js +180 -9
- package/dist/agency/agency-manager.js.map +1 -1
- package/dist/agency/default-rules.d.ts +7 -0
- package/dist/agency/default-rules.d.ts.map +1 -0
- package/dist/agency/default-rules.js +79 -0
- package/dist/agency/default-rules.js.map +1 -0
- package/dist/agency/types.d.ts +48 -0
- package/dist/agency/types.d.ts.map +1 -1
- package/dist/brain/brain.d.ts +17 -2
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +118 -8
- package/dist/brain/brain.js.map +1 -1
- package/dist/brain/knowledge-synthesizer.d.ts +37 -0
- package/dist/brain/knowledge-synthesizer.d.ts.map +1 -0
- package/dist/brain/knowledge-synthesizer.js +159 -0
- package/dist/brain/knowledge-synthesizer.js.map +1 -0
- package/dist/brain/learning-radar.d.ts +96 -0
- package/dist/brain/learning-radar.d.ts.map +1 -0
- package/dist/brain/learning-radar.js +202 -0
- package/dist/brain/learning-radar.js.map +1 -0
- package/dist/brain/types.d.ts +15 -0
- package/dist/brain/types.d.ts.map +1 -1
- package/dist/context/context-engine.d.ts.map +1 -1
- package/dist/context/context-engine.js +82 -17
- package/dist/context/context-engine.js.map +1 -1
- package/dist/context/types.d.ts +5 -0
- package/dist/context/types.d.ts.map +1 -1
- package/dist/control/intent-router.d.ts +12 -1
- package/dist/control/intent-router.d.ts.map +1 -1
- package/dist/control/intent-router.js +68 -0
- package/dist/control/intent-router.js.map +1 -1
- package/dist/control/types.d.ts +17 -0
- package/dist/control/types.d.ts.map +1 -1
- package/dist/curator/classifier.d.ts +18 -0
- package/dist/curator/classifier.d.ts.map +1 -0
- package/dist/curator/classifier.js +59 -0
- package/dist/curator/classifier.js.map +1 -0
- package/dist/curator/quality-gate.d.ts +29 -0
- package/dist/curator/quality-gate.d.ts.map +1 -0
- package/dist/curator/quality-gate.js +86 -0
- package/dist/curator/quality-gate.js.map +1 -0
- package/dist/domain-packs/index.d.ts +0 -3
- package/dist/domain-packs/index.d.ts.map +1 -1
- package/dist/domain-packs/index.js +0 -3
- package/dist/domain-packs/index.js.map +1 -1
- package/dist/domain-packs/loader.d.ts.map +1 -1
- package/dist/domain-packs/loader.js +20 -4
- package/dist/domain-packs/loader.js.map +1 -1
- package/dist/domain-packs/pack-runtime.d.ts +5 -5
- package/dist/domain-packs/pack-runtime.d.ts.map +1 -1
- package/dist/domain-packs/pack-runtime.js +2 -2
- package/dist/domain-packs/pack-runtime.js.map +1 -1
- package/dist/domain-packs/types.d.ts +8 -2
- package/dist/domain-packs/types.d.ts.map +1 -1
- package/dist/domain-packs/types.js.map +1 -1
- package/dist/engine/bin/soleri-engine.js +13 -2
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/engine/index.d.ts +2 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +1 -0
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/module-manifest.d.ts +28 -0
- package/dist/engine/module-manifest.d.ts.map +1 -0
- package/dist/engine/module-manifest.js +85 -0
- package/dist/engine/module-manifest.js.map +1 -0
- package/dist/engine/register-engine.d.ts +19 -0
- package/dist/engine/register-engine.d.ts.map +1 -1
- package/dist/engine/register-engine.js +15 -2
- package/dist/engine/register-engine.js.map +1 -1
- package/dist/events/event-bus.d.ts +30 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/event-bus.js +51 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/flows/chain-runner.d.ts +46 -0
- package/dist/flows/chain-runner.d.ts.map +1 -0
- package/dist/flows/chain-runner.js +271 -0
- package/dist/flows/chain-runner.js.map +1 -0
- package/dist/flows/chain-types.d.ts +103 -0
- package/dist/flows/chain-types.d.ts.map +1 -0
- package/dist/flows/chain-types.js +23 -0
- package/dist/flows/chain-types.js.map +1 -0
- package/dist/health/doctor-checks.d.ts +15 -0
- package/dist/health/doctor-checks.d.ts.map +1 -0
- package/dist/health/doctor-checks.js +98 -0
- package/dist/health/doctor-checks.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/intake/content-classifier.d.ts.map +1 -1
- package/dist/intake/content-classifier.js +0 -2
- package/dist/intake/content-classifier.js.map +1 -1
- package/dist/intake/text-ingester.d.ts +52 -0
- package/dist/intake/text-ingester.d.ts.map +1 -0
- package/dist/intake/text-ingester.js +181 -0
- package/dist/intake/text-ingester.js.map +1 -0
- package/dist/llm/llm-client.d.ts.map +1 -1
- package/dist/llm/llm-client.js +45 -5
- package/dist/llm/llm-client.js.map +1 -1
- package/dist/llm/oauth-discovery.d.ts +18 -0
- package/dist/llm/oauth-discovery.d.ts.map +1 -0
- package/dist/llm/oauth-discovery.js +130 -0
- package/dist/llm/oauth-discovery.js.map +1 -0
- package/dist/llm/types.d.ts +4 -2
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/packs/pack-installer.d.ts +2 -1
- package/dist/packs/pack-installer.d.ts.map +1 -1
- package/dist/packs/pack-installer.js +10 -1
- package/dist/packs/pack-installer.js.map +1 -1
- package/dist/persistence/index.d.ts +0 -1
- package/dist/persistence/index.d.ts.map +1 -1
- package/dist/persistence/index.js +0 -1
- package/dist/persistence/index.js.map +1 -1
- package/dist/persistence/types.d.ts +2 -6
- package/dist/persistence/types.d.ts.map +1 -1
- package/dist/planning/evidence-collector.d.ts +41 -0
- package/dist/planning/evidence-collector.d.ts.map +1 -0
- package/dist/planning/evidence-collector.js +194 -0
- package/dist/planning/evidence-collector.js.map +1 -0
- package/dist/planning/planner.d.ts +4 -0
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +11 -0
- package/dist/planning/planner.js.map +1 -1
- package/dist/plugins/index.d.ts +4 -0
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/plugin-registry.d.ts +4 -0
- package/dist/plugins/plugin-registry.d.ts.map +1 -1
- package/dist/plugins/plugin-registry.js +4 -0
- package/dist/plugins/plugin-registry.js.map +1 -1
- package/dist/plugins/types.d.ts +32 -27
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/plugins/types.js +6 -3
- package/dist/plugins/types.js.map +1 -1
- package/dist/queue/job-queue.d.ts +92 -0
- package/dist/queue/job-queue.d.ts.map +1 -0
- package/dist/queue/job-queue.js +180 -0
- package/dist/queue/job-queue.js.map +1 -0
- package/dist/queue/pipeline-runner.d.ts +62 -0
- package/dist/queue/pipeline-runner.d.ts.map +1 -0
- package/dist/queue/pipeline-runner.js +126 -0
- package/dist/queue/pipeline-runner.js.map +1 -0
- package/dist/runtime/admin-setup-ops.d.ts +20 -0
- package/dist/runtime/admin-setup-ops.d.ts.map +1 -0
- package/dist/runtime/admin-setup-ops.js +583 -0
- package/dist/runtime/admin-setup-ops.js.map +1 -0
- package/dist/runtime/chain-ops.d.ts +9 -0
- package/dist/runtime/chain-ops.d.ts.map +1 -0
- package/dist/runtime/chain-ops.js +107 -0
- package/dist/runtime/chain-ops.js.map +1 -0
- package/dist/runtime/claude-md-helpers.d.ts +56 -0
- package/dist/runtime/claude-md-helpers.d.ts.map +1 -0
- package/dist/runtime/claude-md-helpers.js +160 -0
- package/dist/runtime/claude-md-helpers.js.map +1 -0
- package/dist/runtime/curator-extra-ops.d.ts +3 -2
- package/dist/runtime/curator-extra-ops.d.ts.map +1 -1
- package/dist/runtime/curator-extra-ops.js +81 -3
- package/dist/runtime/curator-extra-ops.js.map +1 -1
- package/dist/runtime/facades/admin-facade.d.ts.map +1 -1
- package/dist/runtime/facades/admin-facade.js +5 -2
- package/dist/runtime/facades/admin-facade.js.map +1 -1
- package/dist/runtime/facades/agency-facade.d.ts.map +1 -1
- package/dist/runtime/facades/agency-facade.js +64 -0
- package/dist/runtime/facades/agency-facade.js.map +1 -1
- package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
- package/dist/runtime/facades/brain-facade.js +122 -1
- package/dist/runtime/facades/brain-facade.js.map +1 -1
- package/dist/runtime/facades/control-facade.d.ts.map +1 -1
- package/dist/runtime/facades/control-facade.js +42 -0
- package/dist/runtime/facades/control-facade.js.map +1 -1
- package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
- package/dist/runtime/facades/memory-facade.js +20 -2
- package/dist/runtime/facades/memory-facade.js.map +1 -1
- package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
- package/dist/runtime/facades/plan-facade.js +2 -0
- package/dist/runtime/facades/plan-facade.js.map +1 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +25 -5
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/intake-ops.d.ts +7 -5
- package/dist/runtime/intake-ops.d.ts.map +1 -1
- package/dist/runtime/intake-ops.js +98 -5
- package/dist/runtime/intake-ops.js.map +1 -1
- package/dist/runtime/memory-extra-ops.d.ts +6 -3
- package/dist/runtime/memory-extra-ops.d.ts.map +1 -1
- package/dist/runtime/memory-extra-ops.js +292 -4
- package/dist/runtime/memory-extra-ops.js.map +1 -1
- package/dist/runtime/pack-ops.d.ts +3 -0
- package/dist/runtime/pack-ops.d.ts.map +1 -1
- package/dist/runtime/pack-ops.js +18 -1
- package/dist/runtime/pack-ops.js.map +1 -1
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
- package/dist/runtime/planning-extra-ops.js +85 -0
- package/dist/runtime/planning-extra-ops.js.map +1 -1
- package/dist/runtime/playbook-ops.js +1 -1
- package/dist/runtime/playbook-ops.js.map +1 -1
- package/dist/runtime/plugin-ops.d.ts.map +1 -1
- package/dist/runtime/plugin-ops.js +3 -0
- package/dist/runtime/plugin-ops.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +143 -2
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/session-briefing.d.ts +23 -0
- package/dist/runtime/session-briefing.d.ts.map +1 -0
- package/dist/runtime/session-briefing.js +154 -0
- package/dist/runtime/session-briefing.js.map +1 -0
- package/dist/runtime/types.d.ts +23 -0
- 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 +3 -7
- package/dist/runtime/vault-linking-ops.js.map +1 -1
- package/dist/vault/vault.d.ts +34 -0
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +89 -3
- package/dist/vault/vault.js.map +1 -1
- package/package.json +6 -4
- package/src/__tests__/admin-setup-ops.test.ts +355 -0
- package/src/__tests__/async-infrastructure.test.ts +307 -0
- package/src/__tests__/cognee-client-gaps.test.ts +6 -2
- package/src/__tests__/cognee-hybrid-search.test.ts +49 -35
- package/src/__tests__/cognee-sync-manager-deep.test.ts +89 -65
- package/src/__tests__/curator-extra-ops.test.ts +6 -2
- package/src/__tests__/curator-pipeline-e2e.test.ts +545 -0
- package/src/__tests__/memory-extra-ops.test.ts +2 -2
- package/src/__tests__/module-manifest-drift.test.ts +59 -0
- package/src/__tests__/planning-extra-ops.test.ts +2 -2
- package/src/__tests__/second-brain-features.test.ts +583 -0
- package/src/agency/agency-manager.ts +217 -9
- package/src/agency/default-rules.ts +83 -0
- package/src/agency/types.ts +61 -0
- package/src/brain/brain.ts +110 -8
- package/src/brain/knowledge-synthesizer.ts +216 -0
- package/src/brain/learning-radar.ts +340 -0
- package/src/brain/types.ts +16 -0
- package/src/context/context-engine.ts +114 -15
- package/src/context/types.ts +5 -0
- package/src/control/intent-router.ts +107 -0
- package/src/control/types.ts +10 -0
- package/src/curator/classifier.ts +86 -0
- package/src/curator/quality-gate.ts +127 -0
- package/src/domain-packs/index.ts +0 -6
- package/src/domain-packs/loader.ts +25 -5
- package/src/domain-packs/pack-runtime.ts +6 -6
- package/src/domain-packs/types.ts +8 -2
- package/src/engine/bin/soleri-engine.ts +18 -2
- package/src/engine/index.ts +2 -0
- package/src/engine/module-manifest.ts +99 -0
- package/src/engine/register-engine.ts +21 -2
- package/src/events/event-bus.ts +58 -0
- package/src/flows/chain-runner.ts +369 -0
- package/src/flows/chain-types.ts +57 -0
- package/src/index.ts +0 -1
- package/src/intake/content-classifier.ts +0 -2
- package/src/intake/text-ingester.ts +234 -0
- package/src/llm/llm-client.ts +50 -7
- package/src/llm/oauth-discovery.ts +151 -0
- package/src/llm/types.ts +4 -2
- package/src/packs/pack-installer.ts +16 -1
- package/src/persistence/index.ts +0 -1
- package/src/persistence/types.ts +2 -6
- package/src/planning/evidence-collector.ts +247 -0
- package/src/planning/planner.ts +11 -0
- package/src/plugins/index.ts +4 -0
- package/src/plugins/plugin-registry.ts +6 -1
- package/src/plugins/types.ts +10 -5
- package/src/queue/job-queue.ts +281 -0
- package/src/queue/pipeline-runner.ts +149 -0
- package/src/runtime/admin-setup-ops.ts +664 -0
- package/src/runtime/chain-ops.ts +121 -0
- package/src/runtime/claude-md-helpers.ts +218 -0
- package/src/runtime/curator-extra-ops.ts +86 -3
- package/src/runtime/facades/admin-facade.ts +5 -2
- package/src/runtime/facades/agency-facade.ts +68 -0
- package/src/runtime/facades/brain-facade.ts +142 -1
- package/src/runtime/facades/control-facade.ts +45 -0
- package/src/runtime/facades/memory-facade.ts +20 -2
- package/src/runtime/facades/plan-facade.ts +2 -0
- package/src/runtime/facades/vault-facade.ts +28 -5
- package/src/runtime/intake-ops.ts +107 -5
- package/src/runtime/memory-extra-ops.ts +312 -4
- package/src/runtime/pack-ops.ts +26 -1
- package/src/runtime/planning-extra-ops.ts +94 -0
- package/src/runtime/playbook-ops.ts +1 -1
- package/src/runtime/plugin-ops.ts +3 -0
- package/src/runtime/runtime.ts +138 -2
- package/src/runtime/session-briefing.ts +175 -0
- package/src/runtime/types.ts +23 -0
- package/src/runtime/vault-linking-ops.ts +3 -7
- package/src/vault/vault.ts +105 -4
- package/src/__tests__/postgres-provider.test.ts +0 -116
- package/src/persistence/postgres-provider.ts +0 -310
package/src/runtime/runtime.ts
CHANGED
|
@@ -19,10 +19,12 @@ import { LoopManager } from '../loop/loop-manager.js';
|
|
|
19
19
|
import { IdentityManager } from '../control/identity-manager.js';
|
|
20
20
|
import { IntentRouter } from '../control/intent-router.js';
|
|
21
21
|
import { KeyPool, loadKeyPoolConfig } from '../llm/key-pool.js';
|
|
22
|
+
import { discoverAnthropicToken } from '../llm/oauth-discovery.js';
|
|
22
23
|
import { loadIntelligenceData } from '../intelligence/loader.js';
|
|
23
24
|
import { LLMClient } from '../llm/llm-client.js';
|
|
24
25
|
import { CogneeSyncManager } from '../cognee/sync-manager.js';
|
|
25
26
|
import { IntakePipeline } from '../intake/intake-pipeline.js';
|
|
27
|
+
import { TextIngester } from '../intake/text-ingester.js';
|
|
26
28
|
import { Telemetry } from '../telemetry/telemetry.js';
|
|
27
29
|
import { ProjectRegistry } from '../project/project-registry.js';
|
|
28
30
|
import { TemplateManager } from '../prompts/template-manager.js';
|
|
@@ -39,6 +41,14 @@ import { VaultBranching } from '../vault/vault-branching.js';
|
|
|
39
41
|
import { ContextEngine } from '../context/context-engine.js';
|
|
40
42
|
import { AgencyManager } from '../agency/agency-manager.js';
|
|
41
43
|
import { KnowledgeReview } from '../vault/knowledge-review.js';
|
|
44
|
+
import { LinkManager } from '../vault/linking.js';
|
|
45
|
+
import { LearningRadar } from '../brain/learning-radar.js';
|
|
46
|
+
import { KnowledgeSynthesizer } from '../brain/knowledge-synthesizer.js';
|
|
47
|
+
import { ChainRunner } from '../flows/chain-runner.js';
|
|
48
|
+
import { JobQueue } from '../queue/job-queue.js';
|
|
49
|
+
import { PipelineRunner } from '../queue/pipeline-runner.js';
|
|
50
|
+
import { evaluateQuality } from '../curator/quality-gate.js';
|
|
51
|
+
import { classifyEntry } from '../curator/classifier.js';
|
|
42
52
|
import type { AgentRuntimeConfig, AgentRuntime } from './types.js';
|
|
43
53
|
|
|
44
54
|
/**
|
|
@@ -96,7 +106,8 @@ export function createAgentRuntime(config: AgentRuntimeConfig): AgentRuntime {
|
|
|
96
106
|
}
|
|
97
107
|
|
|
98
108
|
// Brain — intelligence layer (TF-IDF scoring, auto-tagging, dedup)
|
|
99
|
-
|
|
109
|
+
// Pass vaultManager so intelligentSearch queries all connected sources (not just agent tier)
|
|
110
|
+
const brain = new Brain(vault, cognee ?? undefined, vaultManager);
|
|
100
111
|
|
|
101
112
|
// Brain Intelligence — pattern strengths, session knowledge, intelligence pipeline
|
|
102
113
|
const brainIntelligence = new BrainIntelligence(vault, brain);
|
|
@@ -130,9 +141,15 @@ export function createAgentRuntime(config: AgentRuntimeConfig): AgentRuntime {
|
|
|
130
141
|
}
|
|
131
142
|
|
|
132
143
|
// LLM key pools and client
|
|
144
|
+
// Try OAuth token discovery for Anthropic (Claude Code subscription → free API access)
|
|
133
145
|
const keyPoolFiles = loadKeyPoolConfig(agentId);
|
|
146
|
+
const oauthToken = discoverAnthropicToken();
|
|
147
|
+
const anthropicConfig = keyPoolFiles.anthropic;
|
|
148
|
+
if (oauthToken && anthropicConfig.keys.length === 0) {
|
|
149
|
+
anthropicConfig.keys.push(oauthToken);
|
|
150
|
+
}
|
|
134
151
|
const openaiKeyPool = new KeyPool(keyPoolFiles.openai);
|
|
135
|
-
const anthropicKeyPool = new KeyPool(
|
|
152
|
+
const anthropicKeyPool = new KeyPool(anthropicConfig);
|
|
136
153
|
const llmClient = new LLMClient(openaiKeyPool, anthropicKeyPool, agentId);
|
|
137
154
|
|
|
138
155
|
// Cognee Sync Manager — queue-based dirty tracking with offline resilience (only when Cognee enabled)
|
|
@@ -146,8 +163,13 @@ export function createAgentRuntime(config: AgentRuntimeConfig): AgentRuntime {
|
|
|
146
163
|
vault.setSyncManager(syncManager);
|
|
147
164
|
}
|
|
148
165
|
|
|
166
|
+
// Link Manager — Zettelkasten auto-linking on vault ingestion
|
|
167
|
+
const linkManager = new LinkManager(vault.getProvider());
|
|
168
|
+
vault.setLinkManager(linkManager, { enabled: true, maxLinks: 3 });
|
|
169
|
+
|
|
149
170
|
// Intake Pipeline — PDF/book ingestion with LLM classification
|
|
150
171
|
const intakePipeline = new IntakePipeline(vault.getProvider(), vault, llmClient);
|
|
172
|
+
const textIngester = new TextIngester(vault, llmClient);
|
|
151
173
|
|
|
152
174
|
// Playbook Executor — in-memory step-by-step workflow sessions
|
|
153
175
|
const playbookExecutor = new PlaybookExecutor();
|
|
@@ -217,6 +239,7 @@ export function createAgentRuntime(config: AgentRuntimeConfig): AgentRuntime {
|
|
|
217
239
|
templateManager,
|
|
218
240
|
syncManager,
|
|
219
241
|
intakePipeline,
|
|
242
|
+
textIngester,
|
|
220
243
|
authPolicy: { mode: 'permissive', callerLevel: 'admin' },
|
|
221
244
|
flags: new FeatureFlags(join(agentHome, 'flags.json')),
|
|
222
245
|
health,
|
|
@@ -228,6 +251,119 @@ export function createAgentRuntime(config: AgentRuntimeConfig): AgentRuntime {
|
|
|
228
251
|
contextEngine,
|
|
229
252
|
agencyManager,
|
|
230
253
|
knowledgeReview,
|
|
254
|
+
linkManager,
|
|
255
|
+
learningRadar: new LearningRadar(vault, brain),
|
|
256
|
+
knowledgeSynthesizer: new KnowledgeSynthesizer(brain, llmClient),
|
|
257
|
+
chainRunner: new ChainRunner(vault.getProvider()),
|
|
258
|
+
jobQueue: new JobQueue(vault.getProvider()),
|
|
259
|
+
pipelineRunner: (() => {
|
|
260
|
+
const jq = new JobQueue(vault.getProvider());
|
|
261
|
+
const pr = new PipelineRunner(jq);
|
|
262
|
+
// Register default job handlers for curator pipeline
|
|
263
|
+
pr.registerHandler('tag-normalize', async (job) => {
|
|
264
|
+
const entry = vault.get(job.entryId ?? '');
|
|
265
|
+
if (!entry) return { skipped: true, reason: 'entry not found' };
|
|
266
|
+
const result = curator.normalizeTag(entry.tags[0] ?? '');
|
|
267
|
+
return result;
|
|
268
|
+
});
|
|
269
|
+
pr.registerHandler('dedup-check', async (job) => {
|
|
270
|
+
const entry = vault.get(job.entryId ?? '');
|
|
271
|
+
if (!entry) return { skipped: true, reason: 'entry not found' };
|
|
272
|
+
return curator.detectDuplicates(entry.id);
|
|
273
|
+
});
|
|
274
|
+
pr.registerHandler('auto-link', async (job) => {
|
|
275
|
+
if (linkManager) {
|
|
276
|
+
const suggestions = linkManager.suggestLinks(job.entryId ?? '', 3);
|
|
277
|
+
for (const s of suggestions) {
|
|
278
|
+
linkManager.addLink(
|
|
279
|
+
job.entryId ?? '',
|
|
280
|
+
s.entryId,
|
|
281
|
+
s.suggestedType,
|
|
282
|
+
`pipeline: ${s.reason}`,
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
return { linked: suggestions.length };
|
|
286
|
+
}
|
|
287
|
+
return { skipped: true, reason: 'link manager not available' };
|
|
288
|
+
});
|
|
289
|
+
pr.registerHandler('quality-gate', async (job) => {
|
|
290
|
+
const entry = vault.get(job.entryId ?? '');
|
|
291
|
+
if (!entry) return { skipped: true, reason: 'entry not found' };
|
|
292
|
+
return evaluateQuality(entry, llmClient);
|
|
293
|
+
});
|
|
294
|
+
pr.registerHandler('classify', async (job) => {
|
|
295
|
+
const entry = vault.get(job.entryId ?? '');
|
|
296
|
+
if (!entry) return { skipped: true, reason: 'entry not found' };
|
|
297
|
+
return classifyEntry(entry, llmClient);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// ─── 9 additional handlers for full Salvador parity (#216) ────
|
|
301
|
+
pr.registerHandler('enrich-frontmatter', async (job) => {
|
|
302
|
+
const entry = vault.get(job.entryId ?? '');
|
|
303
|
+
if (!entry) return { skipped: true, reason: 'entry not found' };
|
|
304
|
+
return curator.enrichMetadata(entry.id);
|
|
305
|
+
});
|
|
306
|
+
pr.registerHandler('detect-staleness', async (job) => {
|
|
307
|
+
const entry = vault.get(job.entryId ?? '');
|
|
308
|
+
if (!entry) return { skipped: true, reason: 'entry not found' };
|
|
309
|
+
// Check if entry is older than 90 days (using validFrom or fallback to 0)
|
|
310
|
+
const entryTimestamp = (entry.validFrom ?? 0) * 1000 || Date.now();
|
|
311
|
+
const ageMs = Date.now() - entryTimestamp;
|
|
312
|
+
const staleDays = 90;
|
|
313
|
+
const isStale = ageMs > staleDays * 86400000;
|
|
314
|
+
return { stale: isStale, ageDays: Math.floor(ageMs / 86400000), entryId: entry.id };
|
|
315
|
+
});
|
|
316
|
+
pr.registerHandler('detect-duplicate', async (job) => {
|
|
317
|
+
const entry = vault.get(job.entryId ?? '');
|
|
318
|
+
if (!entry) return { skipped: true, reason: 'entry not found' };
|
|
319
|
+
return curator.detectDuplicates(entry.id);
|
|
320
|
+
});
|
|
321
|
+
pr.registerHandler('detect-contradiction', async (job) => {
|
|
322
|
+
const entry = vault.get(job.entryId ?? '');
|
|
323
|
+
if (!entry) return { skipped: true, reason: 'entry not found' };
|
|
324
|
+
const contradictions = curator.detectContradictions(0.4);
|
|
325
|
+
const relevant = contradictions.filter(
|
|
326
|
+
(c) => c.patternId === job.entryId || c.antipatternId === job.entryId,
|
|
327
|
+
);
|
|
328
|
+
return { found: relevant.length, contradictions: relevant };
|
|
329
|
+
});
|
|
330
|
+
pr.registerHandler('consolidate-duplicates', async (_job) => {
|
|
331
|
+
return curator.consolidate({ dryRun: false, staleDaysThreshold: 90 });
|
|
332
|
+
});
|
|
333
|
+
pr.registerHandler('archive-stale', async (_job) => {
|
|
334
|
+
// Run consolidation with stale detection
|
|
335
|
+
const result = curator.consolidate({ dryRun: false, staleDaysThreshold: 90 });
|
|
336
|
+
return { archived: result.staleEntries.length, result };
|
|
337
|
+
});
|
|
338
|
+
pr.registerHandler('cognee-ingest', async (job) => {
|
|
339
|
+
if (!cognee) return { skipped: true, reason: 'cognee not available' };
|
|
340
|
+
const entry = vault.get(job.entryId ?? '');
|
|
341
|
+
if (!entry) return { skipped: true, reason: 'entry not found' };
|
|
342
|
+
try {
|
|
343
|
+
const result = await cognee.addEntries([entry]);
|
|
344
|
+
return { ingested: result.added };
|
|
345
|
+
} catch {
|
|
346
|
+
return { skipped: true, reason: 'cognee ingestion failed' };
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
pr.registerHandler('cognee-cognify', async (_job) => {
|
|
350
|
+
if (!cognee) return { skipped: true, reason: 'cognee not available' };
|
|
351
|
+
try {
|
|
352
|
+
const result = await cognee.cognify();
|
|
353
|
+
return result;
|
|
354
|
+
} catch {
|
|
355
|
+
return { skipped: true, reason: 'cognee cognify failed' };
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
pr.registerHandler('verify-searchable', async (job) => {
|
|
359
|
+
const entry = vault.get(job.entryId ?? '');
|
|
360
|
+
if (!entry) return { skipped: true, reason: 'entry not found' };
|
|
361
|
+
const searchResults = vault.search(entry.title, { limit: 1 });
|
|
362
|
+
const found = searchResults.some((r) => r.entry.id === entry.id);
|
|
363
|
+
return { searchable: found, entryId: entry.id };
|
|
364
|
+
});
|
|
365
|
+
return pr;
|
|
366
|
+
})(),
|
|
231
367
|
createdAt: Date.now(),
|
|
232
368
|
close: () => {
|
|
233
369
|
syncManager?.close();
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Briefing — proactive context loading on session start.
|
|
3
|
+
*
|
|
4
|
+
* Gathers data from all subsystems (sessions, plans, vault, brain, curator)
|
|
5
|
+
* and produces a concise, structured briefing for the agent.
|
|
6
|
+
*
|
|
7
|
+
* Design: gather all data in parallel, skip sections with nothing to report.
|
|
8
|
+
* Target: < 15 lines of output, < 3 seconds latency.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import type { OpDefinition } from '../facades/types.js';
|
|
13
|
+
import type { AgentRuntime } from './types.js';
|
|
14
|
+
|
|
15
|
+
export interface BriefingSection {
|
|
16
|
+
label: string;
|
|
17
|
+
content: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SessionBriefing {
|
|
21
|
+
sections: BriefingSection[];
|
|
22
|
+
generatedAt: number;
|
|
23
|
+
/** Total entries consulted across all data sources. */
|
|
24
|
+
dataPointsConsulted: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function createSessionBriefingOps(runtime: AgentRuntime): OpDefinition[] {
|
|
28
|
+
const { brainIntelligence, planner, vault, curator } = runtime;
|
|
29
|
+
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
name: 'session_briefing',
|
|
33
|
+
description:
|
|
34
|
+
'Proactive session briefing — gathers last session, active plans, recent vault captures, brain recommendations, and stale knowledge warnings into a concise summary.',
|
|
35
|
+
auth: 'read',
|
|
36
|
+
schema: z.object({
|
|
37
|
+
maxSections: z.number().optional().default(6).describe('Max sections to include'),
|
|
38
|
+
recencyHours: z.number().optional().default(48).describe('Look back window in hours'),
|
|
39
|
+
}),
|
|
40
|
+
handler: async (params) => {
|
|
41
|
+
const maxSections = params.maxSections as number;
|
|
42
|
+
const sections: BriefingSection[] = [];
|
|
43
|
+
let dataPoints = 0;
|
|
44
|
+
|
|
45
|
+
// 0. Day-one welcome (vault has few non-playbook entries)
|
|
46
|
+
try {
|
|
47
|
+
const stats = vault.stats();
|
|
48
|
+
const nonPlaybook = stats.totalEntries - (stats.byType?.playbook ?? 0);
|
|
49
|
+
if (nonPlaybook < 10) {
|
|
50
|
+
sections.push({
|
|
51
|
+
label: 'Welcome',
|
|
52
|
+
content: `Vault has ${nonPlaybook} knowledge entries. Capture patterns as you work — the brain learns from every session. Use op:capture_knowledge to persist insights.`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
} catch {
|
|
56
|
+
// Vault stats unavailable — skip
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 1. Last session
|
|
60
|
+
try {
|
|
61
|
+
const sessions = brainIntelligence.listSessions({ limit: 1, active: false });
|
|
62
|
+
dataPoints += sessions.length;
|
|
63
|
+
if (sessions.length > 0) {
|
|
64
|
+
const last = sessions[0];
|
|
65
|
+
const ago = formatTimeAgo(last.endedAt ? new Date(last.endedAt).getTime() : Date.now());
|
|
66
|
+
const domain = last.domain ? ` [${last.domain}]` : '';
|
|
67
|
+
const context = last.context ? `: ${last.context.slice(0, 80)}` : '';
|
|
68
|
+
const tools = last.toolsUsed.length > 0 ? `, used ${last.toolsUsed.length} tools` : '';
|
|
69
|
+
const files =
|
|
70
|
+
last.filesModified.length > 0 ? `, modified ${last.filesModified.length} files` : '';
|
|
71
|
+
sections.push({
|
|
72
|
+
label: 'Last session',
|
|
73
|
+
content: `(${ago})${domain}${context}${tools}${files}`,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
} catch {
|
|
77
|
+
// Session data unavailable — skip
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 2. Active plans
|
|
81
|
+
try {
|
|
82
|
+
const plans = planner.list();
|
|
83
|
+
const active = plans.filter(
|
|
84
|
+
(p) =>
|
|
85
|
+
p.status === 'executing' ||
|
|
86
|
+
p.status === 'approved' ||
|
|
87
|
+
p.status === 'reconciling' ||
|
|
88
|
+
p.status === 'validating',
|
|
89
|
+
);
|
|
90
|
+
dataPoints += plans.length;
|
|
91
|
+
if (active.length > 0) {
|
|
92
|
+
const summaries = active.map((p) => {
|
|
93
|
+
const tasksDone = p.tasks.filter((t) => t.status === 'completed').length;
|
|
94
|
+
return `${p.objective?.slice(0, 40) || p.id} (${p.status}, ${tasksDone}/${p.tasks.length} tasks)`;
|
|
95
|
+
});
|
|
96
|
+
sections.push({
|
|
97
|
+
label: active.length === 1 ? 'Active plan' : `Active plans (${active.length})`,
|
|
98
|
+
content: summaries.join('; '),
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
} catch {
|
|
102
|
+
// Planner unavailable — skip
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 3. Recent vault captures
|
|
106
|
+
try {
|
|
107
|
+
const recent = vault.getRecent(10);
|
|
108
|
+
dataPoints += recent.length;
|
|
109
|
+
if (recent.length > 0) {
|
|
110
|
+
const count = Math.min(recent.length, 5);
|
|
111
|
+
const titles = recent.slice(0, 3).map((e) => e.title.slice(0, 50));
|
|
112
|
+
sections.push({
|
|
113
|
+
label: 'Recent captures',
|
|
114
|
+
content: `${count} entries — ${titles.join(', ')}${count > 3 ? '...' : ''}`,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
// Vault unavailable — skip
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 4. Brain recommendations
|
|
122
|
+
try {
|
|
123
|
+
const recs = brainIntelligence.recommend({ limit: 3 });
|
|
124
|
+
dataPoints += recs.length;
|
|
125
|
+
if (recs.length > 0) {
|
|
126
|
+
const items = recs.map((r) => `"${r.pattern}" (strength: ${r.strength.toFixed(2)})`);
|
|
127
|
+
sections.push({
|
|
128
|
+
label: 'Brain recommends',
|
|
129
|
+
content: items.join(', '),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
} catch {
|
|
133
|
+
// Brain unavailable — skip
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 5. Stale knowledge / health warnings
|
|
137
|
+
try {
|
|
138
|
+
const health = curator.healthAudit();
|
|
139
|
+
dataPoints += 1;
|
|
140
|
+
const warnings: string[] = [];
|
|
141
|
+
if (health.score < 70) {
|
|
142
|
+
warnings.push(`vault health: ${health.score}/100`);
|
|
143
|
+
}
|
|
144
|
+
if (health.recommendations && health.recommendations.length > 0) {
|
|
145
|
+
warnings.push(health.recommendations[0]);
|
|
146
|
+
}
|
|
147
|
+
if (warnings.length > 0) {
|
|
148
|
+
sections.push({
|
|
149
|
+
label: 'Attention',
|
|
150
|
+
content: warnings.join('. '),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
} catch {
|
|
154
|
+
// Curator unavailable — skip
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
sections: sections.slice(0, maxSections),
|
|
159
|
+
generatedAt: Date.now(),
|
|
160
|
+
dataPointsConsulted: dataPoints,
|
|
161
|
+
} satisfies SessionBriefing;
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function formatTimeAgo(timestamp: number): string {
|
|
168
|
+
const diff = Date.now() - timestamp;
|
|
169
|
+
const minutes = Math.floor(diff / 60000);
|
|
170
|
+
if (minutes < 60) return `${minutes}m ago`;
|
|
171
|
+
const hours = Math.floor(minutes / 60);
|
|
172
|
+
if (hours < 24) return `${hours}h ago`;
|
|
173
|
+
const days = Math.floor(hours / 24);
|
|
174
|
+
return `${days}d ago`;
|
|
175
|
+
}
|
package/src/runtime/types.ts
CHANGED
|
@@ -28,6 +28,13 @@ import type { VaultBranching } from '../vault/vault-branching.js';
|
|
|
28
28
|
import type { ContextEngine } from '../context/context-engine.js';
|
|
29
29
|
import type { AgencyManager } from '../agency/agency-manager.js';
|
|
30
30
|
import type { KnowledgeReview } from '../vault/knowledge-review.js';
|
|
31
|
+
import type { LinkManager } from '../vault/linking.js';
|
|
32
|
+
import type { LearningRadar } from '../brain/learning-radar.js';
|
|
33
|
+
import type { TextIngester } from '../intake/text-ingester.js';
|
|
34
|
+
import type { KnowledgeSynthesizer } from '../brain/knowledge-synthesizer.js';
|
|
35
|
+
import type { ChainRunner } from '../flows/chain-runner.js';
|
|
36
|
+
import type { JobQueue } from '../queue/job-queue.js';
|
|
37
|
+
import type { PipelineRunner } from '../queue/pipeline-runner.js';
|
|
31
38
|
|
|
32
39
|
/**
|
|
33
40
|
* Configuration for creating an agent runtime.
|
|
@@ -50,6 +57,8 @@ export interface AgentRuntimeConfig {
|
|
|
50
57
|
sharedVaultPath?: string;
|
|
51
58
|
/** Enable Cognee vector search integration. Default: false (opt-in). */
|
|
52
59
|
cognee?: boolean;
|
|
60
|
+
/** Path to the agent's root directory (containing agent.yaml, instructions/, etc.). Optional — set by engine binary. */
|
|
61
|
+
agentDir?: string;
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
/**
|
|
@@ -100,6 +109,20 @@ export interface AgentRuntime {
|
|
|
100
109
|
agencyManager: AgencyManager;
|
|
101
110
|
/** Knowledge review — team review workflows (submit/approve/reject). */
|
|
102
111
|
knowledgeReview: KnowledgeReview;
|
|
112
|
+
/** Link manager — Zettelkasten bidirectional linking with auto-link on ingestion. */
|
|
113
|
+
linkManager: LinkManager;
|
|
114
|
+
/** Learning radar — automatic pattern detection from session signals. */
|
|
115
|
+
learningRadar: LearningRadar;
|
|
116
|
+
/** Text ingester — ingest articles, transcripts, and plain text into vault. */
|
|
117
|
+
textIngester: TextIngester;
|
|
118
|
+
/** Knowledge synthesizer — turn vault knowledge into briefs, outlines, posts. */
|
|
119
|
+
knowledgeSynthesizer: KnowledgeSynthesizer;
|
|
120
|
+
/** Chain runner — composable multi-step workflows with data flow and gates. */
|
|
121
|
+
chainRunner: ChainRunner;
|
|
122
|
+
/** Job queue — SQLite-backed async job processing with DAG dependencies. */
|
|
123
|
+
jobQueue: JobQueue;
|
|
124
|
+
/** Pipeline runner — background polling loop for job execution. */
|
|
125
|
+
pipelineRunner: PipelineRunner;
|
|
103
126
|
/** Timestamp (ms since epoch) when this runtime was created. */
|
|
104
127
|
createdAt: number;
|
|
105
128
|
/** Close the vault database connection. Call on shutdown. */
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
import { z } from 'zod';
|
|
12
12
|
import type { OpDefinition } from '../facades/types.js';
|
|
13
13
|
import type { AgentRuntime } from './types.js';
|
|
14
|
-
import { LinkManager } from '../vault/linking.js';
|
|
15
14
|
|
|
16
15
|
const EVAL_SYSTEM_PROMPT = `You evaluate pairs of knowledge entries to determine if they should be linked in a Zettelkasten vault. For EACH pair, decide:
|
|
17
16
|
- If meaningfully related → return { "link": true, "type": "<type>", "note": "<1 sentence why>" }
|
|
@@ -26,8 +25,7 @@ Link types:
|
|
|
26
25
|
Rules: Same category alone is NOT enough. Be selective. Return a JSON array.`;
|
|
27
26
|
|
|
28
27
|
export function createVaultLinkingOps(runtime: AgentRuntime): OpDefinition[] {
|
|
29
|
-
const { vault } = runtime;
|
|
30
|
-
const linkManager = new LinkManager(vault.getProvider());
|
|
28
|
+
const { vault, linkManager } = runtime;
|
|
31
29
|
|
|
32
30
|
return [
|
|
33
31
|
{
|
|
@@ -330,13 +328,11 @@ export function createVaultLinkingOps(runtime: AgentRuntime): OpDefinition[] {
|
|
|
330
328
|
|
|
331
329
|
try {
|
|
332
330
|
const result = await llmClient.complete({
|
|
333
|
-
provider: llmClient.isAvailable().anthropic ? 'anthropic' : 'openai',
|
|
334
|
-
model: llmClient.isAvailable().anthropic ? 'claude-sonnet-4-20250514' : 'gpt-4o-mini',
|
|
335
331
|
systemPrompt: EVAL_SYSTEM_PROMPT,
|
|
336
332
|
userPrompt: pairsText,
|
|
337
333
|
maxTokens: 2000,
|
|
338
|
-
caller: '
|
|
339
|
-
task: '
|
|
334
|
+
caller: 'vault-linking',
|
|
335
|
+
task: 'evaluate-links',
|
|
340
336
|
});
|
|
341
337
|
llmCalls++;
|
|
342
338
|
|
package/src/vault/vault.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { PersistenceProvider } from '../persistence/types.js';
|
|
|
2
2
|
import { SQLitePersistenceProvider } from '../persistence/sqlite-provider.js';
|
|
3
3
|
import type { IntelligenceEntry } from '../intelligence/types.js';
|
|
4
4
|
import { computeContentHash } from './content-hash.js';
|
|
5
|
+
import type { LinkManager } from './linking.js';
|
|
5
6
|
|
|
6
7
|
export interface SearchResult {
|
|
7
8
|
entry: IntelligenceEntry;
|
|
@@ -29,6 +30,16 @@ export interface Memory {
|
|
|
29
30
|
topics: string[];
|
|
30
31
|
filesModified: string[];
|
|
31
32
|
toolsUsed: string[];
|
|
33
|
+
/** What the user was trying to accomplish. */
|
|
34
|
+
intent: string | null;
|
|
35
|
+
/** Key decisions made and their rationale. */
|
|
36
|
+
decisions: string[];
|
|
37
|
+
/** Where things stand at capture time. */
|
|
38
|
+
currentState: string | null;
|
|
39
|
+
/** What should happen next session. */
|
|
40
|
+
nextSteps: string[];
|
|
41
|
+
/** Vault entries that informed this session. */
|
|
42
|
+
vaultEntriesReferenced: string[];
|
|
32
43
|
createdAt: number;
|
|
33
44
|
archivedAt: number | null;
|
|
34
45
|
}
|
|
@@ -42,6 +53,10 @@ export class Vault {
|
|
|
42
53
|
private provider: PersistenceProvider;
|
|
43
54
|
private sqliteProvider: SQLitePersistenceProvider | null;
|
|
44
55
|
private syncManager: import('../cognee/sync-manager.js').CogneeSyncManager | null = null;
|
|
56
|
+
private linkManager: LinkManager | null = null;
|
|
57
|
+
private autoLinkEnabled = true;
|
|
58
|
+
/** Minimum number of FTS5 suggestions to auto-link. Top N are linked. */
|
|
59
|
+
private autoLinkMaxLinks = 3;
|
|
45
60
|
|
|
46
61
|
/**
|
|
47
62
|
* Create a Vault with a PersistenceProvider or a SQLite path (backward compat).
|
|
@@ -61,12 +76,60 @@ export class Vault {
|
|
|
61
76
|
providerOrPath instanceof SQLitePersistenceProvider ? providerOrPath : null;
|
|
62
77
|
}
|
|
63
78
|
this.initialize();
|
|
79
|
+
this.checkFormatVersion();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Vault format version — tracks schema changes for migration safety.
|
|
84
|
+
* Increment when schema changes in a way that requires migration.
|
|
85
|
+
*
|
|
86
|
+
* History:
|
|
87
|
+
* 1 — Initial schema (v8.0.0): entries, memories, brain_feedback, FTS5
|
|
88
|
+
*/
|
|
89
|
+
static readonly FORMAT_VERSION = 1;
|
|
90
|
+
|
|
91
|
+
private checkFormatVersion(): void {
|
|
92
|
+
const row = this.provider.get<{ user_version: number }>('PRAGMA user_version');
|
|
93
|
+
const current = row?.user_version ?? 0;
|
|
94
|
+
|
|
95
|
+
if (current === 0) {
|
|
96
|
+
// Fresh database — stamp with current version
|
|
97
|
+
this.provider.run(`PRAGMA user_version = ${Vault.FORMAT_VERSION}`);
|
|
98
|
+
} else if (current > Vault.FORMAT_VERSION) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
`Vault format version ${current} is newer than engine supports (${Vault.FORMAT_VERSION}). ` +
|
|
101
|
+
`Upgrade @soleri/core to a compatible version.`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
// current < FORMAT_VERSION → future: run migration scripts here
|
|
64
105
|
}
|
|
65
106
|
|
|
66
107
|
setSyncManager(mgr: import('../cognee/sync-manager.js').CogneeSyncManager): void {
|
|
67
108
|
this.syncManager = mgr;
|
|
68
109
|
}
|
|
69
110
|
|
|
111
|
+
setLinkManager(mgr: LinkManager, opts?: { enabled?: boolean; maxLinks?: number }): void {
|
|
112
|
+
this.linkManager = mgr;
|
|
113
|
+
if (opts?.enabled !== undefined) this.autoLinkEnabled = opts.enabled;
|
|
114
|
+
if (opts?.maxLinks !== undefined) this.autoLinkMaxLinks = opts.maxLinks;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Auto-link a newly added entry using FTS5 suggestions.
|
|
119
|
+
* Called after seed() for each entry. Creates links for top N suggestions.
|
|
120
|
+
*/
|
|
121
|
+
private autoLink(entryId: string): void {
|
|
122
|
+
if (!this.linkManager || !this.autoLinkEnabled) return;
|
|
123
|
+
try {
|
|
124
|
+
const suggestions = this.linkManager.suggestLinks(entryId, this.autoLinkMaxLinks);
|
|
125
|
+
for (const s of suggestions) {
|
|
126
|
+
this.linkManager.addLink(entryId, s.entryId, s.suggestedType, `auto: ${s.reason}`);
|
|
127
|
+
}
|
|
128
|
+
} catch {
|
|
129
|
+
// Auto-linking is best-effort — never block ingestion
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
70
133
|
/** Backward-compatible factory. */
|
|
71
134
|
static createWithSQLite(dbPath: string = ':memory:'): Vault {
|
|
72
135
|
return new Vault(dbPath);
|
|
@@ -140,7 +203,23 @@ export class Vault {
|
|
|
140
203
|
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
141
204
|
id, context, summary, topics,
|
|
142
205
|
content='memories', content_rowid='rowid', tokenize='porter unicode61'
|
|
143
|
-
);
|
|
206
|
+
);`);
|
|
207
|
+
|
|
208
|
+
// Add new columns if they don't exist (backward-compatible migration)
|
|
209
|
+
const memCols = this.provider
|
|
210
|
+
.all<{ name: string }>(`PRAGMA table_info(memories)`)
|
|
211
|
+
.map((r) => r.name);
|
|
212
|
+
if (!memCols.includes('intent')) {
|
|
213
|
+
this.provider.execSql(`
|
|
214
|
+
ALTER TABLE memories ADD COLUMN intent TEXT;
|
|
215
|
+
ALTER TABLE memories ADD COLUMN decisions TEXT NOT NULL DEFAULT '[]';
|
|
216
|
+
ALTER TABLE memories ADD COLUMN current_state TEXT;
|
|
217
|
+
ALTER TABLE memories ADD COLUMN next_steps TEXT NOT NULL DEFAULT '[]';
|
|
218
|
+
ALTER TABLE memories ADD COLUMN vault_entries_referenced TEXT NOT NULL DEFAULT '[]';
|
|
219
|
+
`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
this.provider.execSql(`
|
|
144
223
|
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
145
224
|
INSERT INTO memories_fts(rowid,id,context,summary,topics) VALUES(new.rowid,new.id,new.context,new.summary,new.topics);
|
|
146
225
|
END;
|
|
@@ -339,6 +418,13 @@ export class Vault {
|
|
|
339
418
|
this.syncManager.enqueue('ingest', entry.id, entry);
|
|
340
419
|
}
|
|
341
420
|
}
|
|
421
|
+
// Auto-link after all entries are inserted (so they can link to each other).
|
|
422
|
+
// Skip for large batches (>100) — use relink_vault for bulk imports.
|
|
423
|
+
if (entries.length <= 100) {
|
|
424
|
+
for (const entry of entries) {
|
|
425
|
+
this.autoLink(entry.id);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
342
428
|
return count;
|
|
343
429
|
});
|
|
344
430
|
}
|
|
@@ -676,7 +762,7 @@ export class Vault {
|
|
|
676
762
|
}
|
|
677
763
|
return {
|
|
678
764
|
total: rows.length,
|
|
679
|
-
buckets: bucketDefs.map((b, i) => ({
|
|
765
|
+
buckets: bucketDefs.map((b, i) => Object.assign({}, b, { count: counts[i] })),
|
|
680
766
|
oldestTimestamp: oldest,
|
|
681
767
|
newestTimestamp: newest,
|
|
682
768
|
};
|
|
@@ -727,7 +813,8 @@ export class Vault {
|
|
|
727
813
|
captureMemory(memory: Omit<Memory, 'id' | 'createdAt' | 'archivedAt'>): Memory {
|
|
728
814
|
const id = `mem-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
729
815
|
this.provider.run(
|
|
730
|
-
`INSERT INTO memories (id, project_path, type, context, summary, topics, files_modified, tools_used
|
|
816
|
+
`INSERT INTO memories (id, project_path, type, context, summary, topics, files_modified, tools_used, intent, decisions, current_state, next_steps, vault_entries_referenced)
|
|
817
|
+
VALUES (@id, @projectPath, @type, @context, @summary, @topics, @filesModified, @toolsUsed, @intent, @decisions, @currentState, @nextSteps, @vaultEntriesReferenced)`,
|
|
731
818
|
{
|
|
732
819
|
id,
|
|
733
820
|
projectPath: memory.projectPath,
|
|
@@ -737,6 +824,11 @@ export class Vault {
|
|
|
737
824
|
topics: JSON.stringify(memory.topics),
|
|
738
825
|
filesModified: JSON.stringify(memory.filesModified),
|
|
739
826
|
toolsUsed: JSON.stringify(memory.toolsUsed),
|
|
827
|
+
intent: memory.intent ?? null,
|
|
828
|
+
decisions: JSON.stringify(memory.decisions ?? []),
|
|
829
|
+
currentState: memory.currentState ?? null,
|
|
830
|
+
nextSteps: JSON.stringify(memory.nextSteps ?? []),
|
|
831
|
+
vaultEntriesReferenced: JSON.stringify(memory.vaultEntriesReferenced ?? []),
|
|
740
832
|
},
|
|
741
833
|
);
|
|
742
834
|
return this.getMemory(id)!;
|
|
@@ -744,7 +836,7 @@ export class Vault {
|
|
|
744
836
|
|
|
745
837
|
searchMemories(
|
|
746
838
|
query: string,
|
|
747
|
-
options?: { type?: string; projectPath?: string; limit?: number },
|
|
839
|
+
options?: { type?: string; projectPath?: string; intent?: string; limit?: number },
|
|
748
840
|
): Memory[] {
|
|
749
841
|
const limit = options?.limit ?? 10;
|
|
750
842
|
const filters: string[] = ['m.archived_at IS NULL'];
|
|
@@ -757,6 +849,10 @@ export class Vault {
|
|
|
757
849
|
filters.push('m.project_path = @projectPath');
|
|
758
850
|
fp.projectPath = options.projectPath;
|
|
759
851
|
}
|
|
852
|
+
if (options?.intent) {
|
|
853
|
+
filters.push('m.intent = @intent');
|
|
854
|
+
fp.intent = options.intent;
|
|
855
|
+
}
|
|
760
856
|
const wc = filters.length > 0 ? `AND ${filters.join(' AND ')}` : '';
|
|
761
857
|
try {
|
|
762
858
|
const rows = this.provider.all<Record<string, unknown>>(
|
|
@@ -1239,6 +1335,11 @@ function rowToMemory(row: Record<string, unknown>): Memory {
|
|
|
1239
1335
|
topics: JSON.parse((row.topics as string) || '[]'),
|
|
1240
1336
|
filesModified: JSON.parse((row.files_modified as string) || '[]'),
|
|
1241
1337
|
toolsUsed: JSON.parse((row.tools_used as string) || '[]'),
|
|
1338
|
+
intent: (row.intent as string) ?? null,
|
|
1339
|
+
decisions: JSON.parse((row.decisions as string) || '[]'),
|
|
1340
|
+
currentState: (row.current_state as string) ?? null,
|
|
1341
|
+
nextSteps: JSON.parse((row.next_steps as string) || '[]'),
|
|
1342
|
+
vaultEntriesReferenced: JSON.parse((row.vault_entries_referenced as string) || '[]'),
|
|
1242
1343
|
createdAt: row.created_at as number,
|
|
1243
1344
|
archivedAt: (row.archived_at as number) ?? null,
|
|
1244
1345
|
};
|