clementine-agent 1.0.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/.env.example +44 -0
- package/LICENSE +21 -0
- package/README.md +795 -0
- package/dist/agent/agent-manager.d.ts +69 -0
- package/dist/agent/agent-manager.js +441 -0
- package/dist/agent/assistant.d.ts +225 -0
- package/dist/agent/assistant.js +3888 -0
- package/dist/agent/auto-update.d.ts +32 -0
- package/dist/agent/auto-update.js +186 -0
- package/dist/agent/daily-planner.d.ts +24 -0
- package/dist/agent/daily-planner.js +379 -0
- package/dist/agent/execution-advisor.d.ts +10 -0
- package/dist/agent/execution-advisor.js +272 -0
- package/dist/agent/hooks.d.ts +45 -0
- package/dist/agent/hooks.js +564 -0
- package/dist/agent/insight-engine.d.ts +66 -0
- package/dist/agent/insight-engine.js +225 -0
- package/dist/agent/intent-classifier.d.ts +48 -0
- package/dist/agent/intent-classifier.js +214 -0
- package/dist/agent/link-extractor.d.ts +19 -0
- package/dist/agent/link-extractor.js +90 -0
- package/dist/agent/mcp-bridge.d.ts +62 -0
- package/dist/agent/mcp-bridge.js +435 -0
- package/dist/agent/metacognition.d.ts +66 -0
- package/dist/agent/metacognition.js +221 -0
- package/dist/agent/orchestrator.d.ts +81 -0
- package/dist/agent/orchestrator.js +790 -0
- package/dist/agent/profiles.d.ts +22 -0
- package/dist/agent/profiles.js +91 -0
- package/dist/agent/prompt-cache.d.ts +24 -0
- package/dist/agent/prompt-cache.js +68 -0
- package/dist/agent/prompt-evolver.d.ts +28 -0
- package/dist/agent/prompt-evolver.js +279 -0
- package/dist/agent/role-scaffolds.d.ts +28 -0
- package/dist/agent/role-scaffolds.js +433 -0
- package/dist/agent/safe-restart.d.ts +41 -0
- package/dist/agent/safe-restart.js +150 -0
- package/dist/agent/self-improve.d.ts +66 -0
- package/dist/agent/self-improve.js +1706 -0
- package/dist/agent/session-event-log.d.ts +114 -0
- package/dist/agent/session-event-log.js +233 -0
- package/dist/agent/skill-extractor.d.ts +72 -0
- package/dist/agent/skill-extractor.js +435 -0
- package/dist/agent/source-mods.d.ts +61 -0
- package/dist/agent/source-mods.js +230 -0
- package/dist/agent/source-preflight.d.ts +25 -0
- package/dist/agent/source-preflight.js +100 -0
- package/dist/agent/stall-guard.d.ts +62 -0
- package/dist/agent/stall-guard.js +109 -0
- package/dist/agent/strategic-planner.d.ts +60 -0
- package/dist/agent/strategic-planner.js +352 -0
- package/dist/agent/team-bus.d.ts +89 -0
- package/dist/agent/team-bus.js +556 -0
- package/dist/agent/team-router.d.ts +26 -0
- package/dist/agent/team-router.js +37 -0
- package/dist/agent/tool-loop-detector.d.ts +59 -0
- package/dist/agent/tool-loop-detector.js +242 -0
- package/dist/agent/workflow-runner.d.ts +36 -0
- package/dist/agent/workflow-runner.js +317 -0
- package/dist/agent/workflow-variables.d.ts +16 -0
- package/dist/agent/workflow-variables.js +62 -0
- package/dist/channels/discord-agent-bot.d.ts +101 -0
- package/dist/channels/discord-agent-bot.js +881 -0
- package/dist/channels/discord-bot-manager.d.ts +80 -0
- package/dist/channels/discord-bot-manager.js +262 -0
- package/dist/channels/discord-utils.d.ts +51 -0
- package/dist/channels/discord-utils.js +293 -0
- package/dist/channels/discord.d.ts +12 -0
- package/dist/channels/discord.js +1832 -0
- package/dist/channels/slack-agent-bot.d.ts +73 -0
- package/dist/channels/slack-agent-bot.js +320 -0
- package/dist/channels/slack-bot-manager.d.ts +66 -0
- package/dist/channels/slack-bot-manager.js +236 -0
- package/dist/channels/slack-utils.d.ts +39 -0
- package/dist/channels/slack-utils.js +189 -0
- package/dist/channels/slack.d.ts +11 -0
- package/dist/channels/slack.js +196 -0
- package/dist/channels/telegram.d.ts +10 -0
- package/dist/channels/telegram.js +235 -0
- package/dist/channels/webhook.d.ts +9 -0
- package/dist/channels/webhook.js +78 -0
- package/dist/channels/whatsapp.d.ts +11 -0
- package/dist/channels/whatsapp.js +181 -0
- package/dist/cli/chat.d.ts +14 -0
- package/dist/cli/chat.js +220 -0
- package/dist/cli/cron.d.ts +17 -0
- package/dist/cli/cron.js +552 -0
- package/dist/cli/dashboard.d.ts +15 -0
- package/dist/cli/dashboard.js +17677 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +2474 -0
- package/dist/cli/routes/delegations.d.ts +19 -0
- package/dist/cli/routes/delegations.js +154 -0
- package/dist/cli/routes/digest.d.ts +17 -0
- package/dist/cli/routes/digest.js +375 -0
- package/dist/cli/routes/goals.d.ts +14 -0
- package/dist/cli/routes/goals.js +258 -0
- package/dist/cli/routes/workflows.d.ts +18 -0
- package/dist/cli/routes/workflows.js +97 -0
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.js +619 -0
- package/dist/cli/tunnel.d.ts +35 -0
- package/dist/cli/tunnel.js +141 -0
- package/dist/config.d.ts +145 -0
- package/dist/config.js +278 -0
- package/dist/events/bus.d.ts +43 -0
- package/dist/events/bus.js +136 -0
- package/dist/gateway/cron-scheduler.d.ts +166 -0
- package/dist/gateway/cron-scheduler.js +1767 -0
- package/dist/gateway/delivery-queue.d.ts +30 -0
- package/dist/gateway/delivery-queue.js +110 -0
- package/dist/gateway/heartbeat-scheduler.d.ts +99 -0
- package/dist/gateway/heartbeat-scheduler.js +1298 -0
- package/dist/gateway/heartbeat.d.ts +3 -0
- package/dist/gateway/heartbeat.js +3 -0
- package/dist/gateway/lanes.d.ts +24 -0
- package/dist/gateway/lanes.js +76 -0
- package/dist/gateway/notifications.d.ts +29 -0
- package/dist/gateway/notifications.js +75 -0
- package/dist/gateway/router.d.ts +210 -0
- package/dist/gateway/router.js +1330 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +1015 -0
- package/dist/memory/chunker.d.ts +28 -0
- package/dist/memory/chunker.js +226 -0
- package/dist/memory/consolidation.d.ts +44 -0
- package/dist/memory/consolidation.js +171 -0
- package/dist/memory/context-assembler.d.ts +50 -0
- package/dist/memory/context-assembler.js +149 -0
- package/dist/memory/embeddings.d.ts +38 -0
- package/dist/memory/embeddings.js +180 -0
- package/dist/memory/graph-store.d.ts +66 -0
- package/dist/memory/graph-store.js +613 -0
- package/dist/memory/mmr.d.ts +21 -0
- package/dist/memory/mmr.js +75 -0
- package/dist/memory/search.d.ts +26 -0
- package/dist/memory/search.js +67 -0
- package/dist/memory/store.d.ts +530 -0
- package/dist/memory/store.js +2022 -0
- package/dist/security/integrity.d.ts +24 -0
- package/dist/security/integrity.js +58 -0
- package/dist/security/patterns.d.ts +34 -0
- package/dist/security/patterns.js +110 -0
- package/dist/security/scanner.d.ts +32 -0
- package/dist/security/scanner.js +263 -0
- package/dist/tools/admin-tools.d.ts +12 -0
- package/dist/tools/admin-tools.js +1278 -0
- package/dist/tools/external-tools.d.ts +11 -0
- package/dist/tools/external-tools.js +1327 -0
- package/dist/tools/goal-tools.d.ts +9 -0
- package/dist/tools/goal-tools.js +159 -0
- package/dist/tools/mcp-server.d.ts +13 -0
- package/dist/tools/mcp-server.js +141 -0
- package/dist/tools/memory-tools.d.ts +10 -0
- package/dist/tools/memory-tools.js +568 -0
- package/dist/tools/session-tools.d.ts +6 -0
- package/dist/tools/session-tools.js +146 -0
- package/dist/tools/shared.d.ts +216 -0
- package/dist/tools/shared.js +340 -0
- package/dist/tools/team-tools.d.ts +6 -0
- package/dist/tools/team-tools.js +447 -0
- package/dist/tools/tool-meta.d.ts +34 -0
- package/dist/tools/tool-meta.js +133 -0
- package/dist/tools/vault-tools.d.ts +8 -0
- package/dist/tools/vault-tools.js +457 -0
- package/dist/types.d.ts +716 -0
- package/dist/types.js +16 -0
- package/dist/vault-migrations/0001-add-execution-framework.d.ts +10 -0
- package/dist/vault-migrations/0001-add-execution-framework.js +47 -0
- package/dist/vault-migrations/0002-add-agentic-communication.d.ts +12 -0
- package/dist/vault-migrations/0002-add-agentic-communication.js +79 -0
- package/dist/vault-migrations/0003-update-execution-pipeline-narration.d.ts +11 -0
- package/dist/vault-migrations/0003-update-execution-pipeline-narration.js +73 -0
- package/dist/vault-migrations/helpers.d.ts +14 -0
- package/dist/vault-migrations/helpers.js +44 -0
- package/dist/vault-migrations/runner.d.ts +14 -0
- package/dist/vault-migrations/runner.js +139 -0
- package/dist/vault-migrations/types.d.ts +42 -0
- package/dist/vault-migrations/types.js +9 -0
- package/install.sh +320 -0
- package/package.json +84 -0
- package/scripts/postinstall.js +125 -0
- package/vault/00-System/AGENTS.md +66 -0
- package/vault/00-System/CRON.md +71 -0
- package/vault/00-System/HEARTBEAT.md +58 -0
- package/vault/00-System/MEMORY.md +16 -0
- package/vault/00-System/SOUL.md +96 -0
- package/vault/05-Tasks/TASKS.md +19 -0
- package/vault/06-Templates/_Daily-Template.md +28 -0
- package/vault/06-Templates/_People-Template.md +22 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clementine TypeScript — Maximal Marginal Relevance re-ranking.
|
|
3
|
+
*
|
|
4
|
+
* Ensures search results are both relevant AND diverse by penalizing
|
|
5
|
+
* results too similar to already-selected ones.
|
|
6
|
+
* Uses Jaccard similarity on tokenized content (no embedding provider needed).
|
|
7
|
+
*/
|
|
8
|
+
/** Tokenize text into lowercase word set for Jaccard similarity. */
|
|
9
|
+
export function tokenize(text) {
|
|
10
|
+
return new Set(text.toLowerCase()
|
|
11
|
+
.replace(/[^\w\s]/g, ' ')
|
|
12
|
+
.split(/\s+/)
|
|
13
|
+
.filter(w => w.length > 2));
|
|
14
|
+
}
|
|
15
|
+
/** Jaccard similarity between two token sets: |A∩B| / |A∪B| */
|
|
16
|
+
export function jaccard(a, b) {
|
|
17
|
+
if (a.size === 0 && b.size === 0)
|
|
18
|
+
return 1;
|
|
19
|
+
let intersection = 0;
|
|
20
|
+
for (const token of a) {
|
|
21
|
+
if (b.has(token))
|
|
22
|
+
intersection++;
|
|
23
|
+
}
|
|
24
|
+
const union = a.size + b.size - intersection;
|
|
25
|
+
return union === 0 ? 0 : intersection / union;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Re-rank results using Maximal Marginal Relevance.
|
|
29
|
+
*
|
|
30
|
+
* @param results - Scored search results (higher score = more relevant)
|
|
31
|
+
* @param lambda - Balance: 0 = max diversity, 1 = max relevance (default 0.7)
|
|
32
|
+
* @param limit - Max results to return
|
|
33
|
+
*/
|
|
34
|
+
export function mmrRerank(results, lambda = 0.7, limit) {
|
|
35
|
+
if (results.length === 0)
|
|
36
|
+
return [];
|
|
37
|
+
const maxResults = limit ?? results.length;
|
|
38
|
+
if (results.length <= 1)
|
|
39
|
+
return results.slice(0, maxResults);
|
|
40
|
+
// Normalize scores to [0, 1]
|
|
41
|
+
const scores = results.map(r => r.score);
|
|
42
|
+
const minScore = Math.min(...scores);
|
|
43
|
+
const maxScore = Math.max(...scores);
|
|
44
|
+
const range = maxScore - minScore;
|
|
45
|
+
const normScores = scores.map(s => range === 0 ? 1 : (s - minScore) / range);
|
|
46
|
+
// Cache tokenized content
|
|
47
|
+
const tokens = results.map(r => tokenize(r.content));
|
|
48
|
+
const selected = [];
|
|
49
|
+
const remaining = new Set(results.map((_, i) => i));
|
|
50
|
+
for (let step = 0; step < maxResults && remaining.size > 0; step++) {
|
|
51
|
+
let bestIdx = -1;
|
|
52
|
+
let bestMmr = -Infinity;
|
|
53
|
+
for (const i of remaining) {
|
|
54
|
+
const relevance = normScores[i];
|
|
55
|
+
// Max similarity to any already-selected result
|
|
56
|
+
let maxSim = 0;
|
|
57
|
+
for (const j of selected) {
|
|
58
|
+
const sim = jaccard(tokens[i], tokens[j]);
|
|
59
|
+
if (sim > maxSim)
|
|
60
|
+
maxSim = sim;
|
|
61
|
+
}
|
|
62
|
+
const mmr = lambda * relevance - (1 - lambda) * maxSim;
|
|
63
|
+
if (mmr > bestMmr) {
|
|
64
|
+
bestMmr = mmr;
|
|
65
|
+
bestIdx = i;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (bestIdx === -1)
|
|
69
|
+
break;
|
|
70
|
+
selected.push(bestIdx);
|
|
71
|
+
remaining.delete(bestIdx);
|
|
72
|
+
}
|
|
73
|
+
return selected.map(i => results[i]);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=mmr.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clementine TypeScript — Search result helpers.
|
|
3
|
+
*
|
|
4
|
+
* Utility functions for temporal decay, deduplication, and formatting
|
|
5
|
+
* of search results for system prompt injection.
|
|
6
|
+
*/
|
|
7
|
+
import type { SearchResult } from '../types.js';
|
|
8
|
+
export { mmrRerank } from './mmr.js';
|
|
9
|
+
/**
|
|
10
|
+
* Exponential decay multiplier based on age.
|
|
11
|
+
*
|
|
12
|
+
* score = exp(-0.693 * days / halfLife)
|
|
13
|
+
* At halfLife days, score = 0.5. At 0 days, score = 1.0.
|
|
14
|
+
*/
|
|
15
|
+
export declare function temporalDecay(daysOld: number, halfLife?: number): number;
|
|
16
|
+
/**
|
|
17
|
+
* Deduplicate results by (sourceFile, section), keeping the highest-scored.
|
|
18
|
+
*/
|
|
19
|
+
export declare function deduplicateResults(results: SearchResult[]): SearchResult[];
|
|
20
|
+
/**
|
|
21
|
+
* Format search results as a context block for the system prompt.
|
|
22
|
+
*
|
|
23
|
+
* Truncates to stay within maxChars.
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatResultsForPrompt(results: SearchResult[], maxChars?: number): string;
|
|
26
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clementine TypeScript — Search result helpers.
|
|
3
|
+
*
|
|
4
|
+
* Utility functions for temporal decay, deduplication, and formatting
|
|
5
|
+
* of search results for system prompt injection.
|
|
6
|
+
*/
|
|
7
|
+
export { mmrRerank } from './mmr.js';
|
|
8
|
+
/**
|
|
9
|
+
* Exponential decay multiplier based on age.
|
|
10
|
+
*
|
|
11
|
+
* score = exp(-0.693 * days / halfLife)
|
|
12
|
+
* At halfLife days, score = 0.5. At 0 days, score = 1.0.
|
|
13
|
+
*/
|
|
14
|
+
export function temporalDecay(daysOld, halfLife = 30) {
|
|
15
|
+
if (daysOld <= 0)
|
|
16
|
+
return 1.0;
|
|
17
|
+
return Math.exp(-0.693 * daysOld / halfLife);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Deduplicate results by (sourceFile, section), keeping the highest-scored.
|
|
21
|
+
*/
|
|
22
|
+
export function deduplicateResults(results) {
|
|
23
|
+
const seen = new Map();
|
|
24
|
+
for (const r of results) {
|
|
25
|
+
const key = `${r.sourceFile}\0${r.section}`;
|
|
26
|
+
const existing = seen.get(key);
|
|
27
|
+
if (!existing || r.score > existing.score) {
|
|
28
|
+
seen.set(key, r);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return Array.from(seen.values());
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Format search results as a context block for the system prompt.
|
|
35
|
+
*
|
|
36
|
+
* Truncates to stay within maxChars.
|
|
37
|
+
*/
|
|
38
|
+
export function formatResultsForPrompt(results, maxChars = 8000) {
|
|
39
|
+
if (results.length === 0)
|
|
40
|
+
return '';
|
|
41
|
+
const parts = [];
|
|
42
|
+
let total = 0;
|
|
43
|
+
for (const r of results) {
|
|
44
|
+
// Add relative time annotation so the agent can reference recency naturally
|
|
45
|
+
let timeHint = '';
|
|
46
|
+
if (r.lastUpdated) {
|
|
47
|
+
const daysAgo = Math.floor((Date.now() - new Date(r.lastUpdated).getTime()) / 86_400_000);
|
|
48
|
+
if (daysAgo === 0)
|
|
49
|
+
timeHint = ' (today)';
|
|
50
|
+
else if (daysAgo === 1)
|
|
51
|
+
timeHint = ' (yesterday)';
|
|
52
|
+
else if (daysAgo < 7)
|
|
53
|
+
timeHint = ` (${daysAgo} days ago)`;
|
|
54
|
+
else if (daysAgo < 30)
|
|
55
|
+
timeHint = ` (${Math.floor(daysAgo / 7)} weeks ago)`;
|
|
56
|
+
else if (daysAgo < 365)
|
|
57
|
+
timeHint = ` (${Math.floor(daysAgo / 30)} months ago)`;
|
|
58
|
+
}
|
|
59
|
+
const entry = `### ${r.sourceFile} > ${r.section}${timeHint}\n${r.content}\n`;
|
|
60
|
+
if (total + entry.length > maxChars)
|
|
61
|
+
break;
|
|
62
|
+
parts.push(entry);
|
|
63
|
+
total += entry.length;
|
|
64
|
+
}
|
|
65
|
+
return parts.join('\n');
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clementine TypeScript — SQLite FTS5 memory store.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Obsidian vault as a search-optimized index. The vault remains
|
|
5
|
+
* the source of truth; this is a read-optimized cache.
|
|
6
|
+
*
|
|
7
|
+
* FTS5 = full-text search built into SQLite. Zero cost. Zero latency.
|
|
8
|
+
*
|
|
9
|
+
* Concurrency: WAL mode allows concurrent readers. Writes are serialized
|
|
10
|
+
* (single-user, one MCP subprocess handles all writes).
|
|
11
|
+
*/
|
|
12
|
+
import type { Feedback, MemoryExtraction, SearchResult, SessionSummary, SyncStats, TranscriptTurn, WikilinkConnection } from '../types.js';
|
|
13
|
+
export declare class MemoryStore {
|
|
14
|
+
private dbPath;
|
|
15
|
+
private vaultDir;
|
|
16
|
+
private db;
|
|
17
|
+
private _stmtChunkCount;
|
|
18
|
+
private _stmtInsertTranscript;
|
|
19
|
+
private _stmtInsertUsage;
|
|
20
|
+
constructor(dbPath: string, vaultDir: string);
|
|
21
|
+
/**
|
|
22
|
+
* Create the database and schema if needed.
|
|
23
|
+
*/
|
|
24
|
+
initialize(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Close the database connection.
|
|
27
|
+
*/
|
|
28
|
+
close(): void;
|
|
29
|
+
/** Lazily-initializing accessor for the database connection. */
|
|
30
|
+
private get conn();
|
|
31
|
+
/** Return the total number of indexed chunks. */
|
|
32
|
+
getChunkCount(): number;
|
|
33
|
+
/**
|
|
34
|
+
* Scan the entire vault, hash-compare, and re-index changed files.
|
|
35
|
+
*/
|
|
36
|
+
fullSync(): SyncStats;
|
|
37
|
+
/**
|
|
38
|
+
* Re-index a single file after a write operation.
|
|
39
|
+
*/
|
|
40
|
+
updateFile(relPath: string, agentSlug?: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Full-text search using FTS5 with BM25 ranking.
|
|
43
|
+
*/
|
|
44
|
+
searchFts(query: string, limit?: number, filters?: {
|
|
45
|
+
category?: string;
|
|
46
|
+
topic?: string;
|
|
47
|
+
}, isolateAgentSlug?: string): SearchResult[];
|
|
48
|
+
/**
|
|
49
|
+
* Get the most recently updated chunks.
|
|
50
|
+
*/
|
|
51
|
+
getRecentChunks(limit?: number, agentSlug?: string, filters?: {
|
|
52
|
+
category?: string;
|
|
53
|
+
topic?: string;
|
|
54
|
+
}, strict?: boolean): SearchResult[];
|
|
55
|
+
/**
|
|
56
|
+
* Combined FTS5 relevance + recency search for context injection.
|
|
57
|
+
*
|
|
58
|
+
* Layer 3 of the memory architecture:
|
|
59
|
+
* 1. FTS5 search -> top N relevant
|
|
60
|
+
* 2. Recency fetch -> N most recent chunks
|
|
61
|
+
* 3. Deduplicate by (source_file, section)
|
|
62
|
+
* 4. Apply salience boost to FTS results
|
|
63
|
+
*/
|
|
64
|
+
searchContext(query: string, limitOrOpts?: number | {
|
|
65
|
+
limit?: number;
|
|
66
|
+
recencyLimit?: number;
|
|
67
|
+
agentSlug?: string;
|
|
68
|
+
category?: string;
|
|
69
|
+
topic?: string;
|
|
70
|
+
strict?: boolean;
|
|
71
|
+
}, recencyLimitArg?: number): SearchResult[];
|
|
72
|
+
/**
|
|
73
|
+
* Search chunks by embedding cosine similarity.
|
|
74
|
+
* Scans chunks that have stored embeddings and returns top matches.
|
|
75
|
+
*/
|
|
76
|
+
private searchByEmbedding;
|
|
77
|
+
/**
|
|
78
|
+
* Promote a memory chunk to global visibility (agent_slug = NULL).
|
|
79
|
+
* Used by agents to deliberately share an insight across the agent ecosystem.
|
|
80
|
+
* Does NOT copy the chunk — it promotes the existing chunk in-place.
|
|
81
|
+
*
|
|
82
|
+
* @param chunkId - ID of the chunk to promote
|
|
83
|
+
* @param promotedBy - slug of the agent promoting it (for audit log)
|
|
84
|
+
* @returns description of what was promoted, or error message
|
|
85
|
+
*/
|
|
86
|
+
promoteToGlobal(chunkId: number, promotedBy?: string): string;
|
|
87
|
+
/**
|
|
88
|
+
* Get all notes connected to/from the given note via wikilinks.
|
|
89
|
+
*/
|
|
90
|
+
getConnections(noteName: string): WikilinkConnection[];
|
|
91
|
+
/**
|
|
92
|
+
* Save a conversation turn to the transcripts table.
|
|
93
|
+
*/
|
|
94
|
+
saveTurn(sessionKey: string, role: string, content: string, model?: string): void;
|
|
95
|
+
/**
|
|
96
|
+
* Get all turns for a given session, ordered chronologically.
|
|
97
|
+
*/
|
|
98
|
+
getSessionTranscript(sessionKey: string): TranscriptTurn[];
|
|
99
|
+
/**
|
|
100
|
+
* Get recent transcript activity across all sessions since a given timestamp.
|
|
101
|
+
* Returns a compact summary of what happened (sessions, message counts, snippets).
|
|
102
|
+
*/
|
|
103
|
+
getRecentActivity(sinceIso: string, maxEntries?: number): Array<{
|
|
104
|
+
sessionKey: string;
|
|
105
|
+
role: string;
|
|
106
|
+
content: string;
|
|
107
|
+
createdAt: string;
|
|
108
|
+
}>;
|
|
109
|
+
/**
|
|
110
|
+
* Search transcripts by keyword. Returns matching turns with context.
|
|
111
|
+
*/
|
|
112
|
+
searchTranscripts(query: string, limit?: number, sessionKey?: string): TranscriptTurn[];
|
|
113
|
+
/**
|
|
114
|
+
* Save a session summary for cross-session context.
|
|
115
|
+
*/
|
|
116
|
+
saveSessionSummary(sessionKey: string, summary: string, exchangeCount?: number): void;
|
|
117
|
+
/**
|
|
118
|
+
* Get the most recent session summaries.
|
|
119
|
+
*/
|
|
120
|
+
getRecentSummaries(limit?: number): SessionSummary[];
|
|
121
|
+
/**
|
|
122
|
+
* Record that chunks were accessed (retrieved/displayed).
|
|
123
|
+
*/
|
|
124
|
+
recordAccess(chunkIds: number[], accessType?: string): void;
|
|
125
|
+
/**
|
|
126
|
+
* Recompute salience score for a chunk based on access patterns.
|
|
127
|
+
*
|
|
128
|
+
* salience = frequency_bonus + recency_bonus
|
|
129
|
+
* frequency_bonus = log(access_count + 1) * 0.15
|
|
130
|
+
* recency_bonus = decay(days_since_last_access, half_life=7) * 0.3
|
|
131
|
+
*/
|
|
132
|
+
private recomputeSalience;
|
|
133
|
+
/**
|
|
134
|
+
* Apply temporal decay to all chunk salience scores.
|
|
135
|
+
*
|
|
136
|
+
* Call daily (or on startup). Reduces salience for chunks that
|
|
137
|
+
* haven't been accessed recently, so stale memories naturally
|
|
138
|
+
* sink below active ones.
|
|
139
|
+
*
|
|
140
|
+
* decay = exp(-0.693 * daysSinceLastAccess / halfLife)
|
|
141
|
+
*/
|
|
142
|
+
decaySalience(halfLifeDays?: number): number;
|
|
143
|
+
/**
|
|
144
|
+
* Prune stale data to keep the database bounded.
|
|
145
|
+
*
|
|
146
|
+
* - Deletes episodic chunks with salience < threshold and age > maxDays
|
|
147
|
+
* - Trims access_log entries older than retentionDays
|
|
148
|
+
* - Trims transcripts older than retentionDays
|
|
149
|
+
*
|
|
150
|
+
* Returns counts of deleted items.
|
|
151
|
+
*/
|
|
152
|
+
pruneStaleData(opts?: {
|
|
153
|
+
maxAgeDays?: number;
|
|
154
|
+
salienceThreshold?: number;
|
|
155
|
+
accessLogRetentionDays?: number;
|
|
156
|
+
transcriptRetentionDays?: number;
|
|
157
|
+
}): {
|
|
158
|
+
episodicPruned: number;
|
|
159
|
+
accessLogPruned: number;
|
|
160
|
+
transcriptsPruned: number;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Get chunks within a date range, ordered chronologically.
|
|
164
|
+
* Useful for "what happened last week" type queries.
|
|
165
|
+
*/
|
|
166
|
+
getTimeline(startDate: string, endDate: string, limit?: number): SearchResult[];
|
|
167
|
+
/**
|
|
168
|
+
* Index a session summary as an episodic memory chunk.
|
|
169
|
+
*
|
|
170
|
+
* These chunks have sector='episodic' and a synthetic source_file
|
|
171
|
+
* so they can be found by search but distinguished from vault content.
|
|
172
|
+
*/
|
|
173
|
+
indexEpisodicChunk(sessionKey: string, summaryText: string): void;
|
|
174
|
+
/**
|
|
175
|
+
* Check if content is a duplicate of something already stored.
|
|
176
|
+
* Returns match info or null if content is unique.
|
|
177
|
+
*
|
|
178
|
+
* Strategy:
|
|
179
|
+
* 1. Exact match via content_hash (fast)
|
|
180
|
+
* 2. Near-duplicate via FTS5 BM25 + word overlap (conservative)
|
|
181
|
+
*/
|
|
182
|
+
checkDuplicate(content: string, sourceFile?: string): {
|
|
183
|
+
isDuplicate: boolean;
|
|
184
|
+
matchType: 'exact' | 'near' | null;
|
|
185
|
+
matchId?: number;
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Bump a chunk's salience and update its timestamp when a duplicate is detected.
|
|
189
|
+
* Instead of discarding duplicate mentions, this reinforces the existing chunk
|
|
190
|
+
* so frequently-mentioned facts surface higher in search results.
|
|
191
|
+
*/
|
|
192
|
+
bumpChunkSalience(chunkId: number, boost?: number): void;
|
|
193
|
+
/**
|
|
194
|
+
* Log a memory extraction event for transparency tracking.
|
|
195
|
+
*/
|
|
196
|
+
logExtraction(extraction: Omit<MemoryExtraction, 'id'>): void;
|
|
197
|
+
/**
|
|
198
|
+
* Get recent memory extractions, optionally filtered by status.
|
|
199
|
+
*/
|
|
200
|
+
getRecentExtractions(limit?: number, status?: string): MemoryExtraction[];
|
|
201
|
+
/**
|
|
202
|
+
* Mark an extraction as corrected with a replacement fact.
|
|
203
|
+
* Also removes the wrong content from the search index so it stops surfacing.
|
|
204
|
+
*/
|
|
205
|
+
correctExtraction(id: number, correction: string): void;
|
|
206
|
+
/**
|
|
207
|
+
* Dismiss an extraction (mark as invalid).
|
|
208
|
+
* Also removes the content from the search index.
|
|
209
|
+
*/
|
|
210
|
+
dismissExtraction(id: number): void;
|
|
211
|
+
/**
|
|
212
|
+
* Get recent corrections to use as negative examples in auto-memory extraction.
|
|
213
|
+
* Returns corrections from the last 30 days so the extraction prompt knows
|
|
214
|
+
* what facts have been corrected and shouldn't be re-extracted.
|
|
215
|
+
*/
|
|
216
|
+
getRecentCorrections(limit?: number): Array<{
|
|
217
|
+
toolInput: string;
|
|
218
|
+
correction: string;
|
|
219
|
+
}>;
|
|
220
|
+
/**
|
|
221
|
+
* Log feedback about response quality.
|
|
222
|
+
*/
|
|
223
|
+
logFeedback(feedback: {
|
|
224
|
+
sessionKey?: string;
|
|
225
|
+
channel: string;
|
|
226
|
+
messageSnippet?: string;
|
|
227
|
+
responseSnippet?: string;
|
|
228
|
+
rating: 'positive' | 'negative' | 'mixed';
|
|
229
|
+
comment?: string;
|
|
230
|
+
}): void;
|
|
231
|
+
/**
|
|
232
|
+
* Get recent feedback entries.
|
|
233
|
+
*/
|
|
234
|
+
getRecentFeedback(limit?: number): Feedback[];
|
|
235
|
+
/**
|
|
236
|
+
* Get aggregate feedback statistics.
|
|
237
|
+
*/
|
|
238
|
+
getFeedbackStats(): {
|
|
239
|
+
positive: number;
|
|
240
|
+
negative: number;
|
|
241
|
+
mixed: number;
|
|
242
|
+
total: number;
|
|
243
|
+
};
|
|
244
|
+
saveSessionReflection(reflection: {
|
|
245
|
+
sessionKey: string;
|
|
246
|
+
exchangeCount: number;
|
|
247
|
+
frictionSignals: string[];
|
|
248
|
+
qualityScore: number;
|
|
249
|
+
behavioralCorrections: Array<{
|
|
250
|
+
correction: string;
|
|
251
|
+
category: string;
|
|
252
|
+
strength: string;
|
|
253
|
+
}>;
|
|
254
|
+
preferencesLearned: Array<{
|
|
255
|
+
preference: string;
|
|
256
|
+
confidence: string;
|
|
257
|
+
}>;
|
|
258
|
+
agentSlug?: string;
|
|
259
|
+
}): void;
|
|
260
|
+
getRecentReflections(limit?: number, agentSlug?: string): Array<{
|
|
261
|
+
sessionKey: string;
|
|
262
|
+
exchangeCount: number;
|
|
263
|
+
frictionSignals: string[];
|
|
264
|
+
qualityScore: number;
|
|
265
|
+
behavioralCorrections: Array<{
|
|
266
|
+
correction: string;
|
|
267
|
+
category: string;
|
|
268
|
+
strength: string;
|
|
269
|
+
}>;
|
|
270
|
+
preferencesLearned: Array<{
|
|
271
|
+
preference: string;
|
|
272
|
+
confidence: string;
|
|
273
|
+
}>;
|
|
274
|
+
agentSlug: string | null;
|
|
275
|
+
createdAt: string;
|
|
276
|
+
}>;
|
|
277
|
+
/** Get recurring behavioral corrections (appeared in 2+ sessions). */
|
|
278
|
+
getBehavioralPatterns(minOccurrences?: number): Array<{
|
|
279
|
+
correction: string;
|
|
280
|
+
category: string;
|
|
281
|
+
count: number;
|
|
282
|
+
lastSeen: string;
|
|
283
|
+
}>;
|
|
284
|
+
/**
|
|
285
|
+
* Log token usage from an SDK query result.
|
|
286
|
+
* Iterates modelUsage record and inserts one row per model.
|
|
287
|
+
*/
|
|
288
|
+
logUsage(entry: {
|
|
289
|
+
sessionKey: string;
|
|
290
|
+
source: string;
|
|
291
|
+
modelUsage: Record<string, {
|
|
292
|
+
inputTokens: number;
|
|
293
|
+
outputTokens: number;
|
|
294
|
+
cacheReadInputTokens: number;
|
|
295
|
+
cacheCreationInputTokens: number;
|
|
296
|
+
}>;
|
|
297
|
+
numTurns: number;
|
|
298
|
+
durationMs: number;
|
|
299
|
+
agentSlug?: string;
|
|
300
|
+
}): void;
|
|
301
|
+
/**
|
|
302
|
+
* Get aggregated usage summary, optionally filtered by time.
|
|
303
|
+
*/
|
|
304
|
+
getUsageSummary(sinceIso?: string): {
|
|
305
|
+
totalInput: number;
|
|
306
|
+
totalOutput: number;
|
|
307
|
+
totalCacheRead: number;
|
|
308
|
+
totalCacheCreation: number;
|
|
309
|
+
totalTokens: number;
|
|
310
|
+
byModel: Array<{
|
|
311
|
+
model: string;
|
|
312
|
+
input: number;
|
|
313
|
+
output: number;
|
|
314
|
+
cacheRead: number;
|
|
315
|
+
}>;
|
|
316
|
+
bySource: Array<{
|
|
317
|
+
source: string;
|
|
318
|
+
input: number;
|
|
319
|
+
output: number;
|
|
320
|
+
}>;
|
|
321
|
+
byDay: Array<{
|
|
322
|
+
day: string;
|
|
323
|
+
input: number;
|
|
324
|
+
output: number;
|
|
325
|
+
}>;
|
|
326
|
+
};
|
|
327
|
+
/**
|
|
328
|
+
* Get per-agent usage stats for observability dashboard.
|
|
329
|
+
*/
|
|
330
|
+
getAgentStats(agentSlug: string, sinceIso?: string): {
|
|
331
|
+
totalInput: number;
|
|
332
|
+
totalOutput: number;
|
|
333
|
+
totalTokens: number;
|
|
334
|
+
numQueries: number;
|
|
335
|
+
avgTurns: number;
|
|
336
|
+
avgDurationMs: number;
|
|
337
|
+
bySource: Array<{
|
|
338
|
+
source: string;
|
|
339
|
+
count: number;
|
|
340
|
+
tokens: number;
|
|
341
|
+
}>;
|
|
342
|
+
byDay: Array<{
|
|
343
|
+
day: string;
|
|
344
|
+
tokens: number;
|
|
345
|
+
count: number;
|
|
346
|
+
}>;
|
|
347
|
+
};
|
|
348
|
+
/**
|
|
349
|
+
* Compare all agents by usage. Returns a leaderboard.
|
|
350
|
+
*/
|
|
351
|
+
getAgentComparison(sinceIso?: string): Array<{
|
|
352
|
+
agentSlug: string;
|
|
353
|
+
totalTokens: number;
|
|
354
|
+
numQueries: number;
|
|
355
|
+
avgTurns: number;
|
|
356
|
+
}>;
|
|
357
|
+
/**
|
|
358
|
+
* Get usage summary for a specific session.
|
|
359
|
+
*/
|
|
360
|
+
getSessionUsage(sessionKey: string): {
|
|
361
|
+
totalInput: number;
|
|
362
|
+
totalOutput: number;
|
|
363
|
+
totalTokens: number;
|
|
364
|
+
numQueries: number;
|
|
365
|
+
};
|
|
366
|
+
/**
|
|
367
|
+
* Get chunks that are candidates for consolidation:
|
|
368
|
+
* - Older than `minAgeDays`
|
|
369
|
+
* - Not already consolidated
|
|
370
|
+
* - Grouped by source file prefix (topic area)
|
|
371
|
+
*
|
|
372
|
+
* Returns groups with 3+ chunks that can be synthesized into summaries.
|
|
373
|
+
*/
|
|
374
|
+
getConsolidationCandidates(minAgeDays?: number): Array<{
|
|
375
|
+
topic: string;
|
|
376
|
+
chunkIds: number[];
|
|
377
|
+
contents: string[];
|
|
378
|
+
totalChars: number;
|
|
379
|
+
}>;
|
|
380
|
+
/**
|
|
381
|
+
* Mark chunks as consolidated after they've been synthesized into a summary.
|
|
382
|
+
* Reduces salience so they appear lower in search results (but aren't deleted).
|
|
383
|
+
*/
|
|
384
|
+
markConsolidated(chunkIds: number[]): void;
|
|
385
|
+
/**
|
|
386
|
+
* Get consolidation stats for monitoring.
|
|
387
|
+
*/
|
|
388
|
+
getConsolidationStats(): {
|
|
389
|
+
totalChunks: number;
|
|
390
|
+
consolidated: number;
|
|
391
|
+
unconsolidated: number;
|
|
392
|
+
};
|
|
393
|
+
/**
|
|
394
|
+
* Insert a summary chunk created by the consolidation engine.
|
|
395
|
+
* Gets higher initial salience than regular chunks.
|
|
396
|
+
*/
|
|
397
|
+
insertSummaryChunk(sourceFile: string, section: string, content: string): void;
|
|
398
|
+
upsertLead(lead: {
|
|
399
|
+
agentSlug: string;
|
|
400
|
+
email: string;
|
|
401
|
+
name: string;
|
|
402
|
+
company?: string;
|
|
403
|
+
title?: string;
|
|
404
|
+
status?: string;
|
|
405
|
+
source?: string;
|
|
406
|
+
sfId?: string;
|
|
407
|
+
metadata?: Record<string, unknown>;
|
|
408
|
+
}): {
|
|
409
|
+
id: number;
|
|
410
|
+
created: boolean;
|
|
411
|
+
};
|
|
412
|
+
searchLeads(filters: {
|
|
413
|
+
agentSlug?: string;
|
|
414
|
+
status?: string;
|
|
415
|
+
company?: string;
|
|
416
|
+
query?: string;
|
|
417
|
+
limit?: number;
|
|
418
|
+
}): Array<Record<string, unknown>>;
|
|
419
|
+
getLeadByEmail(email: string): Record<string, unknown> | undefined;
|
|
420
|
+
getLeadById(id: number): Record<string, unknown> | undefined;
|
|
421
|
+
enrollSequence(enrollment: {
|
|
422
|
+
leadId: number;
|
|
423
|
+
sequenceName: string;
|
|
424
|
+
nextStepDueAt?: string;
|
|
425
|
+
}): number;
|
|
426
|
+
advanceSequence(id: number, updates: {
|
|
427
|
+
currentStep?: number;
|
|
428
|
+
status?: string;
|
|
429
|
+
nextStepDueAt?: string | null;
|
|
430
|
+
}): void;
|
|
431
|
+
getDueSequences(agentSlug?: string): Array<Record<string, unknown>>;
|
|
432
|
+
getSequencesByLead(leadId: number): Array<Record<string, unknown>>;
|
|
433
|
+
logActivity(activity: {
|
|
434
|
+
leadId?: number;
|
|
435
|
+
agentSlug: string;
|
|
436
|
+
type: string;
|
|
437
|
+
subject?: string;
|
|
438
|
+
detail?: string;
|
|
439
|
+
templateUsed?: string;
|
|
440
|
+
}): number;
|
|
441
|
+
getActivities(filters: {
|
|
442
|
+
leadId?: number;
|
|
443
|
+
agentSlug?: string;
|
|
444
|
+
type?: string;
|
|
445
|
+
limit?: number;
|
|
446
|
+
sinceIso?: string;
|
|
447
|
+
}): Array<Record<string, unknown>>;
|
|
448
|
+
addSuppression(email: string, reason: string, addedBy?: string): void;
|
|
449
|
+
isSuppressed(email: string): boolean;
|
|
450
|
+
getSuppressionList(limit?: number): Array<Record<string, unknown>>;
|
|
451
|
+
logSend(entry: {
|
|
452
|
+
agentSlug: string;
|
|
453
|
+
recipient: string;
|
|
454
|
+
subject?: string;
|
|
455
|
+
templateUsed?: string;
|
|
456
|
+
policyRef?: string;
|
|
457
|
+
}): void;
|
|
458
|
+
getDailySendCount(agentSlug: string): number;
|
|
459
|
+
getSendLog(filters: {
|
|
460
|
+
agentSlug?: string;
|
|
461
|
+
limit?: number;
|
|
462
|
+
sinceIso?: string;
|
|
463
|
+
}): Array<Record<string, unknown>>;
|
|
464
|
+
addApproval(entry: {
|
|
465
|
+
agentSlug: string;
|
|
466
|
+
actionType: string;
|
|
467
|
+
summary: string;
|
|
468
|
+
detail?: Record<string, unknown>;
|
|
469
|
+
}): number;
|
|
470
|
+
resolveApproval(id: number, status: 'approved' | 'rejected', resolvedBy?: string): void;
|
|
471
|
+
getPendingApprovals(agentSlug?: string): Array<Record<string, unknown>>;
|
|
472
|
+
getApprovalById(id: number): Record<string, unknown> | undefined;
|
|
473
|
+
getAgentKpis(agentSlug: string, sinceIso?: string): Record<string, number>;
|
|
474
|
+
/** Get current month's token spend for an agent (in cents, estimated from token counts). */
|
|
475
|
+
getAgentMonthlySpend(agentSlug: string): number;
|
|
476
|
+
/** Check if an agent has exceeded its monthly budget. */
|
|
477
|
+
isOverBudget(agentSlug: string, budgetCents: number): boolean;
|
|
478
|
+
/** Snapshot a config file before writing changes. */
|
|
479
|
+
snapshotConfig(agentSlug: string, fileName: string, content: string, changedBy?: string): void;
|
|
480
|
+
/** Get revision history for an agent's config files. */
|
|
481
|
+
getConfigRevisions(agentSlug: string, fileName?: string, limit?: number): Array<Record<string, unknown>>;
|
|
482
|
+
/** Get a specific config revision's content. */
|
|
483
|
+
getConfigRevisionContent(id: number): string | null;
|
|
484
|
+
logSfSync(record: {
|
|
485
|
+
localTable: string;
|
|
486
|
+
localId: number;
|
|
487
|
+
sfObjectType: string;
|
|
488
|
+
sfId: string;
|
|
489
|
+
syncDirection: string;
|
|
490
|
+
syncStatus?: string;
|
|
491
|
+
errorMessage?: string;
|
|
492
|
+
}): number;
|
|
493
|
+
getSfSyncHistory(opts?: {
|
|
494
|
+
limit?: number;
|
|
495
|
+
sfObjectType?: string;
|
|
496
|
+
syncStatus?: string;
|
|
497
|
+
}): Array<Record<string, unknown>>;
|
|
498
|
+
getLeadBySfId(sfId: string): Record<string, unknown> | undefined;
|
|
499
|
+
getUnsyncedLeads(agentSlug?: string): Array<Record<string, unknown>>;
|
|
500
|
+
getLeadsModifiedSince(since: string, agentSlug?: string): Array<Record<string, unknown>>;
|
|
501
|
+
/**
|
|
502
|
+
* Build the TF-IDF vocabulary from all chunk contents, then backfill
|
|
503
|
+
* embeddings for any chunks that don't have one yet.
|
|
504
|
+
* Safe to call repeatedly — skips chunks that already have embeddings.
|
|
505
|
+
*/
|
|
506
|
+
buildEmbeddings(): {
|
|
507
|
+
vocabSize: number;
|
|
508
|
+
backfilled: number;
|
|
509
|
+
};
|
|
510
|
+
/**
|
|
511
|
+
* Delete all chunks, wikilinks, file hash, and access log for a given file.
|
|
512
|
+
*/
|
|
513
|
+
private deleteFileChunks;
|
|
514
|
+
/**
|
|
515
|
+
* Sanitize a query for FTS5 syntax.
|
|
516
|
+
*
|
|
517
|
+
* Quotes each word and joins with OR to match any word (not all).
|
|
518
|
+
* This works better for natural language queries.
|
|
519
|
+
*/
|
|
520
|
+
static sanitizeFtsQuery(query: string): string;
|
|
521
|
+
/**
|
|
522
|
+
* Parse and index [[wikilinks]] from a file.
|
|
523
|
+
*/
|
|
524
|
+
private indexWikilinks;
|
|
525
|
+
/**
|
|
526
|
+
* Recursively walk a directory for .md files.
|
|
527
|
+
*/
|
|
528
|
+
private walkMdFiles;
|
|
529
|
+
}
|
|
530
|
+
//# sourceMappingURL=store.d.ts.map
|