audrey 0.3.0 → 0.3.2
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/README.md +160 -63
- package/mcp-server/config.js +60 -0
- package/mcp-server/index.js +122 -28
- package/package.json +4 -3
- package/src/audrey.js +97 -0
- package/src/causal.js +18 -0
- package/src/confidence.js +37 -0
- package/src/consolidate.js +12 -0
- package/src/db.js +9 -0
- package/src/decay.js +5 -0
- package/src/embedding.js +65 -0
- package/src/encode.js +6 -0
- package/src/introspect.js +4 -0
- package/src/llm.js +84 -0
- package/src/prompts.js +20 -0
- package/src/recall.js +14 -0
- package/src/rollback.js +9 -0
- package/src/ulid.js +9 -2
- package/src/utils.js +16 -0
- package/src/validate.js +22 -0
- package/mcp-server/register.sh +0 -30
package/src/prompts.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { safeJsonParse } from './utils.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @param {Object[]} episodes
|
|
5
|
+
* @returns {import('./llm.js').ChatMessage[]}
|
|
6
|
+
*/
|
|
3
7
|
export function buildPrincipleExtractionPrompt(episodes) {
|
|
4
8
|
const episodeList = episodes.map((ep, i) => {
|
|
5
9
|
const tags = safeJsonParse(ep.tags, []);
|
|
@@ -36,6 +40,11 @@ Rules:
|
|
|
36
40
|
];
|
|
37
41
|
}
|
|
38
42
|
|
|
43
|
+
/**
|
|
44
|
+
* @param {string} newContent
|
|
45
|
+
* @param {string} existingContent
|
|
46
|
+
* @returns {import('./llm.js').ChatMessage[]}
|
|
47
|
+
*/
|
|
39
48
|
export function buildContradictionDetectionPrompt(newContent, existingContent) {
|
|
40
49
|
return [
|
|
41
50
|
{
|
|
@@ -67,6 +76,11 @@ EXISTING CLAIM: ${existingContent}`,
|
|
|
67
76
|
];
|
|
68
77
|
}
|
|
69
78
|
|
|
79
|
+
/**
|
|
80
|
+
* @param {{ content: string, source: string }} cause
|
|
81
|
+
* @param {{ content: string, source: string }} effect
|
|
82
|
+
* @returns {import('./llm.js').ChatMessage[]}
|
|
83
|
+
*/
|
|
70
84
|
export function buildCausalArticulationPrompt(cause, effect) {
|
|
71
85
|
return [
|
|
72
86
|
{
|
|
@@ -100,6 +114,12 @@ EFFECT: ${effect.content} (source: ${effect.source})`,
|
|
|
100
114
|
];
|
|
101
115
|
}
|
|
102
116
|
|
|
117
|
+
/**
|
|
118
|
+
* @param {string} claimA
|
|
119
|
+
* @param {string} claimB
|
|
120
|
+
* @param {string} [context]
|
|
121
|
+
* @returns {import('./llm.js').ChatMessage[]}
|
|
122
|
+
*/
|
|
103
123
|
export function buildContextResolutionPrompt(claimA, claimB, context) {
|
|
104
124
|
const contextSection = context
|
|
105
125
|
? `\n\nADDITIONAL CONTEXT: ${context}`
|
package/src/recall.js
CHANGED
|
@@ -190,6 +190,13 @@ function knnProcedural(db, queryBuffer, candidateK, now, minConfidence, includeP
|
|
|
190
190
|
return { results, matchedIds };
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
+
/**
|
|
194
|
+
* @param {import('better-sqlite3').Database} db
|
|
195
|
+
* @param {import('./embedding.js').EmbeddingProvider} embeddingProvider
|
|
196
|
+
* @param {string} query
|
|
197
|
+
* @param {{ minConfidence?: number, types?: string[], limit?: number, includeProvenance?: boolean, includeDormant?: boolean }} [options]
|
|
198
|
+
* @returns {AsyncGenerator<{ id: string, content: string, type: string, confidence: number, score: number, source: string, createdAt: string }>}
|
|
199
|
+
*/
|
|
193
200
|
export async function* recallStream(db, embeddingProvider, query, options = {}) {
|
|
194
201
|
const {
|
|
195
202
|
minConfidence = 0,
|
|
@@ -251,6 +258,13 @@ export async function* recallStream(db, embeddingProvider, query, options = {})
|
|
|
251
258
|
}
|
|
252
259
|
}
|
|
253
260
|
|
|
261
|
+
/**
|
|
262
|
+
* @param {import('better-sqlite3').Database} db
|
|
263
|
+
* @param {import('./embedding.js').EmbeddingProvider} embeddingProvider
|
|
264
|
+
* @param {string} query
|
|
265
|
+
* @param {{ minConfidence?: number, types?: string[], limit?: number, includeProvenance?: boolean, includeDormant?: boolean }} [options]
|
|
266
|
+
* @returns {Promise<Array<{ id: string, content: string, type: string, confidence: number, score: number, source: string, createdAt: string }>>}
|
|
267
|
+
*/
|
|
254
268
|
export async function recall(db, embeddingProvider, query, options = {}) {
|
|
255
269
|
const results = [];
|
|
256
270
|
for await (const entry of recallStream(db, embeddingProvider, query, options)) {
|
package/src/rollback.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { safeJsonParse } from './utils.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @param {import('better-sqlite3').Database} db
|
|
5
|
+
* @returns {Array<{ id: string, checkpoint_cursor: string|null, input_episode_ids: string, output_memory_ids: string, started_at: string, completed_at: string|null, status: string }>}
|
|
6
|
+
*/
|
|
3
7
|
export function getConsolidationHistory(db) {
|
|
4
8
|
return db.prepare(`
|
|
5
9
|
SELECT id, checkpoint_cursor, input_episode_ids, output_memory_ids,
|
|
@@ -8,6 +12,11 @@ export function getConsolidationHistory(db) {
|
|
|
8
12
|
`).all();
|
|
9
13
|
}
|
|
10
14
|
|
|
15
|
+
/**
|
|
16
|
+
* @param {import('better-sqlite3').Database} db
|
|
17
|
+
* @param {string} runId
|
|
18
|
+
* @returns {{ rolledBackMemories: number, restoredEpisodes: number }}
|
|
19
|
+
*/
|
|
11
20
|
export function rollbackConsolidation(db, runId) {
|
|
12
21
|
const run = db.prepare('SELECT * FROM consolidation_runs WHERE id = ?').get(runId);
|
|
13
22
|
if (!run) throw new Error(`Consolidation run not found: ${runId}`);
|
package/src/ulid.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { monotonicFactory } from 'ulid';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
|
|
4
|
+
const monotonic = monotonicFactory();
|
|
5
|
+
|
|
6
|
+
/** @returns {string} */
|
|
4
7
|
export function generateId() {
|
|
5
|
-
return
|
|
8
|
+
return monotonic();
|
|
6
9
|
}
|
|
7
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @param {...*} parts
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
8
15
|
export function generateDeterministicId(...parts) {
|
|
9
16
|
const input = JSON.stringify(parts);
|
|
10
17
|
return createHash('sha256').update(input).digest('hex').slice(0, 26);
|
package/src/utils.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {Buffer} bufA
|
|
3
|
+
* @param {Buffer} bufB
|
|
4
|
+
* @param {import('./embedding.js').EmbeddingProvider} provider
|
|
5
|
+
* @returns {number}
|
|
6
|
+
*/
|
|
1
7
|
export function cosineSimilarity(bufA, bufB, provider) {
|
|
2
8
|
const a = provider.bufferToVector(bufA);
|
|
3
9
|
const b = provider.bufferToVector(bufB);
|
|
@@ -11,10 +17,20 @@ export function cosineSimilarity(bufA, bufB, provider) {
|
|
|
11
17
|
return mag === 0 ? 0 : dot / mag;
|
|
12
18
|
}
|
|
13
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} dateStr
|
|
22
|
+
* @param {Date} now
|
|
23
|
+
* @returns {number}
|
|
24
|
+
*/
|
|
14
25
|
export function daysBetween(dateStr, now) {
|
|
15
26
|
return Math.max(0, (now.getTime() - new Date(dateStr).getTime()) / (1000 * 60 * 60 * 24));
|
|
16
27
|
}
|
|
17
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @param {string | null | undefined} str
|
|
31
|
+
* @param {*} [fallback=null]
|
|
32
|
+
* @returns {*}
|
|
33
|
+
*/
|
|
18
34
|
export function safeJsonParse(str, fallback = null) {
|
|
19
35
|
if (!str) return fallback;
|
|
20
36
|
try { return JSON.parse(str); }
|
package/src/validate.js
CHANGED
|
@@ -5,6 +5,13 @@ import { buildContradictionDetectionPrompt } from './prompts.js';
|
|
|
5
5
|
const REINFORCEMENT_THRESHOLD = 0.85;
|
|
6
6
|
const CONTRADICTION_THRESHOLD = 0.60;
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @param {import('better-sqlite3').Database} db
|
|
10
|
+
* @param {import('./embedding.js').EmbeddingProvider} embeddingProvider
|
|
11
|
+
* @param {{ id: string, content: string, source: string }} episode
|
|
12
|
+
* @param {{ threshold?: number, contradictionThreshold?: number, llmProvider?: { json: (messages: any) => Promise<any> } }} [options]
|
|
13
|
+
* @returns {Promise<{ action: string, semanticId?: string, similarity?: number, contradictionId?: string, resolution?: string }>}
|
|
14
|
+
*/
|
|
8
15
|
export async function validateMemory(db, embeddingProvider, episode, options = {}) {
|
|
9
16
|
const {
|
|
10
17
|
threshold = REINFORCEMENT_THRESHOLD,
|
|
@@ -121,6 +128,15 @@ function computeSourceDiversity(db, evidenceIds, currentEpisode) {
|
|
|
121
128
|
return sourceTypes.size;
|
|
122
129
|
}
|
|
123
130
|
|
|
131
|
+
/**
|
|
132
|
+
* @param {import('better-sqlite3').Database} db
|
|
133
|
+
* @param {string} claimAId
|
|
134
|
+
* @param {string} claimAType
|
|
135
|
+
* @param {string} claimBId
|
|
136
|
+
* @param {string} claimBType
|
|
137
|
+
* @param {object|null} resolution
|
|
138
|
+
* @returns {string}
|
|
139
|
+
*/
|
|
124
140
|
export function createContradiction(db, claimAId, claimAType, claimBId, claimBType, resolution) {
|
|
125
141
|
const id = generateId();
|
|
126
142
|
const now = new Date().toISOString();
|
|
@@ -138,6 +154,12 @@ export function createContradiction(db, claimAId, claimAType, claimBId, claimBTy
|
|
|
138
154
|
return id;
|
|
139
155
|
}
|
|
140
156
|
|
|
157
|
+
/**
|
|
158
|
+
* @param {import('better-sqlite3').Database} db
|
|
159
|
+
* @param {string} contradictionId
|
|
160
|
+
* @param {string} newEvidenceId
|
|
161
|
+
* @returns {void}
|
|
162
|
+
*/
|
|
141
163
|
export function reopenContradiction(db, contradictionId, newEvidenceId) {
|
|
142
164
|
const now = new Date().toISOString();
|
|
143
165
|
db.prepare(`
|
package/mcp-server/register.sh
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Register Audrey MCP server with Claude Code
|
|
3
|
-
# Usage: bash mcp-server/register.sh [--openai] [--anthropic]
|
|
4
|
-
|
|
5
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
-
SERVER_PATH="$SCRIPT_DIR/index.js"
|
|
7
|
-
|
|
8
|
-
ARGS="--transport stdio --scope user"
|
|
9
|
-
ENV_ARGS=""
|
|
10
|
-
|
|
11
|
-
ENV_ARGS="$ENV_ARGS --env AUDREY_DATA_DIR=$HOME/.audrey/data"
|
|
12
|
-
|
|
13
|
-
if [[ "$*" == *"--openai"* ]]; then
|
|
14
|
-
ENV_ARGS="$ENV_ARGS --env AUDREY_EMBEDDING_PROVIDER=openai --env AUDREY_EMBEDDING_DIMENSIONS=1536"
|
|
15
|
-
[ -n "$OPENAI_API_KEY" ] && ENV_ARGS="$ENV_ARGS --env OPENAI_API_KEY=$OPENAI_API_KEY"
|
|
16
|
-
else
|
|
17
|
-
ENV_ARGS="$ENV_ARGS --env AUDREY_EMBEDDING_PROVIDER=mock --env AUDREY_EMBEDDING_DIMENSIONS=8"
|
|
18
|
-
fi
|
|
19
|
-
|
|
20
|
-
if [[ "$*" == *"--anthropic"* ]]; then
|
|
21
|
-
ENV_ARGS="$ENV_ARGS --env AUDREY_LLM_PROVIDER=anthropic"
|
|
22
|
-
[ -n "$ANTHROPIC_API_KEY" ] && ENV_ARGS="$ENV_ARGS --env ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY"
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
echo "Registering Audrey MCP server..."
|
|
26
|
-
echo " Server: $SERVER_PATH"
|
|
27
|
-
|
|
28
|
-
claude mcp add $ARGS $ENV_ARGS audrey-memory -- node "$SERVER_PATH"
|
|
29
|
-
|
|
30
|
-
echo "Done. Run 'claude mcp list' to verify."
|