audrey 0.20.0 → 0.21.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/CHANGELOG.md +15 -0
- package/README.md +170 -115
- package/dist/mcp-server/config.d.ts +25 -1
- package/dist/mcp-server/config.d.ts.map +1 -1
- package/dist/mcp-server/config.js +97 -12
- package/dist/mcp-server/config.js.map +1 -1
- package/dist/mcp-server/index.d.ts +83 -2
- package/dist/mcp-server/index.d.ts.map +1 -1
- package/dist/mcp-server/index.js +453 -36
- package/dist/mcp-server/index.js.map +1 -1
- package/dist/src/audrey.d.ts +4 -0
- package/dist/src/audrey.d.ts.map +1 -1
- package/dist/src/audrey.js +12 -0
- package/dist/src/audrey.js.map +1 -1
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/preflight.d.ts +51 -0
- package/dist/src/preflight.d.ts.map +1 -0
- package/dist/src/preflight.js +201 -0
- package/dist/src/preflight.js.map +1 -0
- package/dist/src/reflexes.d.ts +35 -0
- package/dist/src/reflexes.d.ts.map +1 -0
- package/dist/src/reflexes.js +87 -0
- package/dist/src/reflexes.js.map +1 -0
- package/dist/src/routes.d.ts.map +1 -1
- package/dist/src/routes.js +84 -7
- package/dist/src/routes.js.map +1 -1
- package/docs/assets/audrey-feature-grid.jpg +0 -0
- package/docs/assets/audrey-logo.svg +45 -0
- package/docs/assets/audrey-wordmark.png +0 -0
- package/docs/audrey-for-dummies.md +670 -0
- package/docs/future-of-llm-memory.md +452 -0
- package/docs/mcp-hosts.md +206 -0
- package/docs/ollama-local-agents.md +128 -0
- package/docs/production-readiness.md +11 -7
- package/examples/ollama-memory-agent.js +326 -0
- package/package.json +21 -2
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Audrey With Ollama Local Agents
|
|
2
|
+
|
|
3
|
+
Ollama provides local model inference. Audrey provides long-term memory. Treat Audrey as the memory sidecar that your Ollama-backed agent calls through tools.
|
|
4
|
+
|
|
5
|
+
This is intentionally host-neutral: the same Audrey data directory can be shared by Codex, Claude Code, Claude Desktop, and a local Ollama agent, or isolated per project.
|
|
6
|
+
|
|
7
|
+
## Start Audrey
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
AUDREY_AGENT=ollama-local-agent AUDREY_EMBEDDING_PROVIDER=local npx audrey serve
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Health check:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
curl http://localhost:7437/health
|
|
17
|
+
curl http://localhost:7437/v1/status
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Use `AUDREY_API_KEY` if the sidecar is reachable beyond your local process boundary:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
AUDREY_API_KEY=secret AUDREY_AGENT=ollama-local-agent npx audrey serve
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Memory Tools To Expose
|
|
27
|
+
|
|
28
|
+
Expose these Audrey routes as function tools in your local agent loop:
|
|
29
|
+
|
|
30
|
+
| Tool | Audrey route | Purpose |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `memory_preflight` | `POST /v1/preflight` | Check known risks, rules, procedures, and prior failures before tool use |
|
|
33
|
+
| `memory_reflexes` | `POST /v1/reflexes` | Convert preflight evidence into trigger-response rules the agent can automate |
|
|
34
|
+
| `memory_capsule` | `POST /v1/capsule` | Build a compact, ranked context packet for the current task |
|
|
35
|
+
| `memory_recall` | `POST /v1/recall` | Search durable memories |
|
|
36
|
+
| `memory_encode` | `POST /v1/encode` | Store useful observations, decisions, procedures, and preferences |
|
|
37
|
+
| `memory_status` | `GET /v1/status` | Check memory/index health |
|
|
38
|
+
|
|
39
|
+
Minimum useful loop:
|
|
40
|
+
|
|
41
|
+
1. Before tool use, call `memory_reflexes` or `memory_preflight` for the proposed action.
|
|
42
|
+
2. If a reflex says `block`, stop and ask for repair or approval.
|
|
43
|
+
3. Before calling Ollama, ask Audrey for a capsule using the user task as the query.
|
|
44
|
+
4. Add the capsule to the model instructions or context.
|
|
45
|
+
5. Let the model call `memory_recall` for details when needed.
|
|
46
|
+
6. After the task, call `memory_encode` for durable facts, decisions, mistakes, procedures, and preferences.
|
|
47
|
+
7. Run `npx audrey dream` on a schedule to consolidate and decay memory.
|
|
48
|
+
|
|
49
|
+
## Native Ollama Tool Shape
|
|
50
|
+
|
|
51
|
+
Ollama supports function tools on `/api/chat`. Your agent owns the loop that executes a tool call and sends the result back to the model.
|
|
52
|
+
|
|
53
|
+
Audrey ships a complete example loop:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
OLLAMA_MODEL=qwen3 node examples/ollama-memory-agent.js "What should you remember about this project?"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"type": "function",
|
|
62
|
+
"function": {
|
|
63
|
+
"name": "memory_recall",
|
|
64
|
+
"description": "Recall Audrey memories relevant to a query.",
|
|
65
|
+
"parameters": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"required": ["query"],
|
|
68
|
+
"properties": {
|
|
69
|
+
"query": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"description": "Search query for durable memory."
|
|
72
|
+
},
|
|
73
|
+
"limit": {
|
|
74
|
+
"type": "number",
|
|
75
|
+
"description": "Maximum results to return."
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Tool executor:
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
export async function memoryRecall({ query, limit = 5 }) {
|
|
87
|
+
const response = await fetch('http://localhost:7437/v1/recall', {
|
|
88
|
+
method: 'POST',
|
|
89
|
+
headers: { 'Content-Type': 'application/json' },
|
|
90
|
+
body: JSON.stringify({ query, limit }),
|
|
91
|
+
});
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
throw new Error(`Audrey recall failed: ${response.status}`);
|
|
94
|
+
}
|
|
95
|
+
return response.json();
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## OpenAI-Compatible Ollama Mode
|
|
100
|
+
|
|
101
|
+
Ollama also exposes an OpenAI-compatible API at `http://localhost:11434/v1/`. If your local agent framework already knows how to call OpenAI-style tools, point the model client at Ollama and keep Audrey as the tool executor.
|
|
102
|
+
|
|
103
|
+
The important separation is:
|
|
104
|
+
|
|
105
|
+
- Ollama answers with local models.
|
|
106
|
+
- Audrey remembers, recalls, reconciles, and consolidates.
|
|
107
|
+
- The agent loop decides when a model tool call should hit Audrey.
|
|
108
|
+
|
|
109
|
+
Official Ollama references:
|
|
110
|
+
|
|
111
|
+
- Native tool calling: <https://docs.ollama.com/capabilities/tool-calling>
|
|
112
|
+
- OpenAI-compatible API: <https://docs.ollama.com/openai>
|
|
113
|
+
|
|
114
|
+
## Data Layout
|
|
115
|
+
|
|
116
|
+
For shared memory across hosts:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
AUDREY_DATA_DIR=$HOME/.audrey/data
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
For project-local memory:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
AUDREY_DATA_DIR=.audrey-data
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Shared memory is better for personal continuity across Codex, Claude, and local agents. Project-local memory is better when clients, repositories, or experiments must not bleed into each other.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Audrey is ready to be the memory layer inside a production agent system, but it is not a complete regulated-platform package by itself. Treat it as stateful infrastructure: pin providers, isolate tenants, monitor health, and wrap it with the controls your environment requires.
|
|
4
4
|
|
|
5
|
-
First contact should now go through `npx audrey
|
|
5
|
+
First contact should now go through `npx audrey doctor`, then `npx audrey install --host <host> --dry-run` for local MCP hosts, `npx audrey install` for Claude Code specifically, or `npx audrey serve` for the sidecar path. Run `npx audrey status --json --fail-on-unhealthy` before exposing Audrey to real traffic.
|
|
6
6
|
|
|
7
7
|
## Best Vertical Fit
|
|
8
8
|
|
|
@@ -56,19 +56,24 @@ Guardrails:
|
|
|
56
56
|
|
|
57
57
|
1. Pin `AUDREY_EMBEDDING_PROVIDER` and `AUDREY_LLM_PROVIDER` explicitly. Do not rely on key-based auto-detection in production.
|
|
58
58
|
2. Set a dedicated `AUDREY_DATA_DIR` per environment and per tenant boundary.
|
|
59
|
-
3. Add a
|
|
59
|
+
3. Add a startup check that runs `npx audrey doctor --json`.
|
|
60
60
|
4. Alert on `health.healthy=false` or `health.reembed_recommended=true`.
|
|
61
61
|
5. Schedule `npx audrey dream` during low-traffic windows so consolidation and decay stay current.
|
|
62
62
|
6. Backup the SQLite data directory before changing embedding dimensions or providers.
|
|
63
63
|
7. Treat re-embedding as a controlled maintenance action and validate with `npx audrey status`.
|
|
64
|
-
8.
|
|
65
|
-
9.
|
|
66
|
-
10.
|
|
67
|
-
11.
|
|
64
|
+
8. Use `npx audrey install --host <host> --dry-run` in deployment docs so operators can preview host config without accidental writes.
|
|
65
|
+
9. Keep API keys, bearer tokens, and raw credentials out of encoded memory content.
|
|
66
|
+
10. Decide whether `private` memories are allowed for your use case and document who can create them.
|
|
67
|
+
11. Add application-level encryption, access control, logging, and retention policies around Audrey.
|
|
68
|
+
12. On graceful shutdown paths, call `await brain.waitForIdle()` before `brain.close()` so tracked background work drains cleanly.
|
|
68
69
|
|
|
69
70
|
## Operations Commands
|
|
70
71
|
|
|
71
72
|
```bash
|
|
73
|
+
# First-contact diagnostics
|
|
74
|
+
npx audrey doctor
|
|
75
|
+
npx audrey doctor --json
|
|
76
|
+
|
|
72
77
|
# Human-readable health
|
|
73
78
|
npx audrey status
|
|
74
79
|
|
|
@@ -102,7 +107,6 @@ That keeps Audrey focused on memory integrity while the host system owns complia
|
|
|
102
107
|
Audrey now ships with a first-party container path for the REST API:
|
|
103
108
|
|
|
104
109
|
```bash
|
|
105
|
-
npx audrey init sidecar-prod
|
|
106
110
|
docker compose up -d --build
|
|
107
111
|
```
|
|
108
112
|
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const AUDREY_URL = (process.env.AUDREY_URL || 'http://127.0.0.1:7437').replace(/\/$/, '');
|
|
4
|
+
const OLLAMA_URL = (process.env.OLLAMA_URL || 'http://127.0.0.1:11434').replace(/\/$/, '');
|
|
5
|
+
const OLLAMA_MODEL = process.env.OLLAMA_MODEL || 'qwen3';
|
|
6
|
+
const AUDREY_API_KEY = process.env.AUDREY_API_KEY || '';
|
|
7
|
+
const MAX_TOOL_LOOPS = Number.parseInt(process.env.MAX_TOOL_LOOPS || '4', 10);
|
|
8
|
+
|
|
9
|
+
const userPrompt = process.argv.slice(2).join(' ').trim()
|
|
10
|
+
|| 'Use Audrey memory to explain how this local Ollama agent should remember useful facts.';
|
|
11
|
+
|
|
12
|
+
function usage() {
|
|
13
|
+
console.log(`
|
|
14
|
+
Audrey + Ollama local memory agent
|
|
15
|
+
|
|
16
|
+
Prerequisites:
|
|
17
|
+
1. Start Audrey: AUDREY_AGENT=ollama-local-agent npx audrey serve
|
|
18
|
+
2. Start Ollama and pull a tool-capable model: ollama pull qwen3
|
|
19
|
+
|
|
20
|
+
Run:
|
|
21
|
+
OLLAMA_MODEL=qwen3 node examples/ollama-memory-agent.js "What should you remember about this project?"
|
|
22
|
+
|
|
23
|
+
Environment:
|
|
24
|
+
AUDREY_URL=http://127.0.0.1:7437
|
|
25
|
+
AUDREY_API_KEY=secret
|
|
26
|
+
OLLAMA_URL=http://127.0.0.1:11434
|
|
27
|
+
OLLAMA_MODEL=qwen3
|
|
28
|
+
`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function headers() {
|
|
32
|
+
const h = { 'Content-Type': 'application/json' };
|
|
33
|
+
if (AUDREY_API_KEY) h.Authorization = `Bearer ${AUDREY_API_KEY}`;
|
|
34
|
+
return h;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function jsonFetch(url, options = {}) {
|
|
38
|
+
const response = await fetch(url, options);
|
|
39
|
+
const text = await response.text();
|
|
40
|
+
let data = null;
|
|
41
|
+
if (text.trim()) {
|
|
42
|
+
try {
|
|
43
|
+
data = JSON.parse(text);
|
|
44
|
+
} catch {
|
|
45
|
+
data = { raw: text };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
const detail = data?.error || data?.message || text || response.statusText;
|
|
50
|
+
throw new Error(`${response.status} ${response.statusText}: ${detail}`);
|
|
51
|
+
}
|
|
52
|
+
return data;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function audreyGet(path) {
|
|
56
|
+
return jsonFetch(`${AUDREY_URL}${path}`, { headers: headers() });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function audreyPost(path, body) {
|
|
60
|
+
return jsonFetch(`${AUDREY_URL}${path}`, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
headers: headers(),
|
|
63
|
+
body: JSON.stringify(body),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function memoryRecall({ query, limit = 5 }) {
|
|
68
|
+
if (!query || typeof query !== 'string') {
|
|
69
|
+
throw new Error('memory_recall requires a string query');
|
|
70
|
+
}
|
|
71
|
+
return audreyPost('/v1/recall', { query, limit });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function memoryCapsule({ query, budget_chars = 4000 }) {
|
|
75
|
+
if (!query || typeof query !== 'string') {
|
|
76
|
+
throw new Error('memory_capsule requires a string query');
|
|
77
|
+
}
|
|
78
|
+
return audreyPost('/v1/capsule', { query, budget_chars });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function memoryPreflight({ action, tool, strict = false, include_capsule = false }) {
|
|
82
|
+
if (!action || typeof action !== 'string') {
|
|
83
|
+
throw new Error('memory_preflight requires a string action');
|
|
84
|
+
}
|
|
85
|
+
return audreyPost('/v1/preflight', { action, tool, strict, include_capsule });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function memoryReflexes({ action, tool, strict = false, include_preflight = false }) {
|
|
89
|
+
if (!action || typeof action !== 'string') {
|
|
90
|
+
throw new Error('memory_reflexes requires a string action');
|
|
91
|
+
}
|
|
92
|
+
return audreyPost('/v1/reflexes', { action, tool, strict, include_preflight });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function memoryEncode({ content, source = 'model-generated', tags = ['ollama-agent'] }) {
|
|
96
|
+
if (!content || typeof content !== 'string') {
|
|
97
|
+
throw new Error('memory_encode requires string content');
|
|
98
|
+
}
|
|
99
|
+
return audreyPost('/v1/encode', { content, source, tags });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const toolExecutors = {
|
|
103
|
+
memory_preflight: memoryPreflight,
|
|
104
|
+
memory_reflexes: memoryReflexes,
|
|
105
|
+
memory_recall: memoryRecall,
|
|
106
|
+
memory_capsule: memoryCapsule,
|
|
107
|
+
memory_encode: memoryEncode,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const tools = [
|
|
111
|
+
{
|
|
112
|
+
type: 'function',
|
|
113
|
+
function: {
|
|
114
|
+
name: 'memory_preflight',
|
|
115
|
+
description: 'Check Audrey memory before taking an action, so prior failures and rules are not repeated.',
|
|
116
|
+
parameters: {
|
|
117
|
+
type: 'object',
|
|
118
|
+
required: ['action'],
|
|
119
|
+
properties: {
|
|
120
|
+
action: { type: 'string', description: 'Action the agent is considering.' },
|
|
121
|
+
tool: { type: 'string', description: 'Optional tool or command family.' },
|
|
122
|
+
strict: { type: 'boolean', description: 'If true, high-severity warnings can block the action.' },
|
|
123
|
+
include_capsule: { type: 'boolean', description: 'Include full capsule context in the result.' },
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'function',
|
|
130
|
+
function: {
|
|
131
|
+
name: 'memory_reflexes',
|
|
132
|
+
description: 'Return Audrey Memory Reflexes: trigger-response rules for the action the agent is considering.',
|
|
133
|
+
parameters: {
|
|
134
|
+
type: 'object',
|
|
135
|
+
required: ['action'],
|
|
136
|
+
properties: {
|
|
137
|
+
action: { type: 'string', description: 'Action the agent is considering.' },
|
|
138
|
+
tool: { type: 'string', description: 'Optional tool or command family.' },
|
|
139
|
+
strict: { type: 'boolean', description: 'If true, high-severity warnings can become blocking reflexes.' },
|
|
140
|
+
include_preflight: { type: 'boolean', description: 'Include the full underlying preflight report.' },
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
type: 'function',
|
|
147
|
+
function: {
|
|
148
|
+
name: 'memory_recall',
|
|
149
|
+
description: 'Recall durable Audrey memories relevant to a query.',
|
|
150
|
+
parameters: {
|
|
151
|
+
type: 'object',
|
|
152
|
+
required: ['query'],
|
|
153
|
+
properties: {
|
|
154
|
+
query: { type: 'string', description: 'Search query for Audrey memory.' },
|
|
155
|
+
limit: { type: 'number', description: 'Maximum memories to return.' },
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: 'function',
|
|
162
|
+
function: {
|
|
163
|
+
name: 'memory_capsule',
|
|
164
|
+
description: 'Build a compact, evidence-backed Audrey Memory Capsule for the current task.',
|
|
165
|
+
parameters: {
|
|
166
|
+
type: 'object',
|
|
167
|
+
required: ['query'],
|
|
168
|
+
properties: {
|
|
169
|
+
query: { type: 'string', description: 'Current task or question.' },
|
|
170
|
+
budget_chars: { type: 'number', description: 'Maximum capsule size in characters.' },
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: 'function',
|
|
177
|
+
function: {
|
|
178
|
+
name: 'memory_encode',
|
|
179
|
+
description: 'Store a useful lasting observation, decision, preference, or procedure in Audrey.',
|
|
180
|
+
parameters: {
|
|
181
|
+
type: 'object',
|
|
182
|
+
required: ['content'],
|
|
183
|
+
properties: {
|
|
184
|
+
content: { type: 'string', description: 'Memory content to store.' },
|
|
185
|
+
source: {
|
|
186
|
+
type: 'string',
|
|
187
|
+
enum: ['direct-observation', 'told-by-user', 'tool-result', 'inference', 'model-generated'],
|
|
188
|
+
description: 'Source reliability category.',
|
|
189
|
+
},
|
|
190
|
+
tags: {
|
|
191
|
+
type: 'array',
|
|
192
|
+
items: { type: 'string' },
|
|
193
|
+
description: 'Searchable tags for this memory.',
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
function parseToolArguments(args) {
|
|
202
|
+
if (args == null) return {};
|
|
203
|
+
if (typeof args === 'string') {
|
|
204
|
+
try {
|
|
205
|
+
return JSON.parse(args);
|
|
206
|
+
} catch {
|
|
207
|
+
return { raw: args };
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return args;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function ollamaChat(messages) {
|
|
214
|
+
return jsonFetch(`${OLLAMA_URL}/api/chat`, {
|
|
215
|
+
method: 'POST',
|
|
216
|
+
headers: { 'Content-Type': 'application/json' },
|
|
217
|
+
body: JSON.stringify({
|
|
218
|
+
model: OLLAMA_MODEL,
|
|
219
|
+
stream: false,
|
|
220
|
+
messages,
|
|
221
|
+
tools,
|
|
222
|
+
}),
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async function main() {
|
|
227
|
+
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
228
|
+
usage();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
await audreyGet('/health');
|
|
234
|
+
} catch (err) {
|
|
235
|
+
console.error(`Audrey is not reachable at ${AUDREY_URL}.`);
|
|
236
|
+
console.error('Start it with: AUDREY_AGENT=ollama-local-agent npx audrey serve');
|
|
237
|
+
console.error(`Details: ${err.message}`);
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const reflexes = await memoryReflexes({ action: userPrompt, include_preflight: false });
|
|
242
|
+
const preflight = await memoryPreflight({ action: userPrompt, include_capsule: false });
|
|
243
|
+
const capsule = await memoryCapsule({ query: userPrompt, budget_chars: 4000 });
|
|
244
|
+
const messages = [
|
|
245
|
+
{
|
|
246
|
+
role: 'system',
|
|
247
|
+
content: [
|
|
248
|
+
'You are a local Ollama agent with Audrey long-term memory.',
|
|
249
|
+
'Use Audrey tools when memory would improve the answer.',
|
|
250
|
+
'Before taking risky tool actions, call memory_reflexes or memory_preflight and follow any warnings.',
|
|
251
|
+
'Store only durable preferences, facts, decisions, procedures, and useful lessons.',
|
|
252
|
+
'',
|
|
253
|
+
'Initial Audrey Memory Reflexes:',
|
|
254
|
+
JSON.stringify(reflexes, null, 2).slice(0, 3000),
|
|
255
|
+
'',
|
|
256
|
+
'Initial Audrey Preflight:',
|
|
257
|
+
JSON.stringify(preflight, null, 2).slice(0, 3000),
|
|
258
|
+
'',
|
|
259
|
+
'Initial Audrey Memory Capsule:',
|
|
260
|
+
JSON.stringify(capsule, null, 2).slice(0, 6000),
|
|
261
|
+
].join('\n'),
|
|
262
|
+
},
|
|
263
|
+
{ role: 'user', content: userPrompt },
|
|
264
|
+
];
|
|
265
|
+
|
|
266
|
+
console.error(`[audrey-ollama] model=${OLLAMA_MODEL} audrey=${AUDREY_URL} ollama=${OLLAMA_URL}`);
|
|
267
|
+
|
|
268
|
+
for (let i = 0; i < MAX_TOOL_LOOPS; i += 1) {
|
|
269
|
+
let response;
|
|
270
|
+
try {
|
|
271
|
+
response = await ollamaChat(messages);
|
|
272
|
+
} catch (err) {
|
|
273
|
+
console.error(`Ollama is not reachable at ${OLLAMA_URL}, or model "${OLLAMA_MODEL}" is not available.`);
|
|
274
|
+
console.error(`Try: ollama pull ${OLLAMA_MODEL}`);
|
|
275
|
+
console.error(`Details: ${err.message}`);
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const message = response.message || {};
|
|
280
|
+
messages.push(message);
|
|
281
|
+
|
|
282
|
+
const calls = message.tool_calls || [];
|
|
283
|
+
if (calls.length === 0) {
|
|
284
|
+
console.log(message.content || '(model returned no content)');
|
|
285
|
+
await memoryEncode({
|
|
286
|
+
content: `Ollama agent answered: ${userPrompt.slice(0, 240)}`,
|
|
287
|
+
source: 'model-generated',
|
|
288
|
+
tags: ['ollama-agent', 'session-summary'],
|
|
289
|
+
}).catch(() => undefined);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
for (const call of calls) {
|
|
294
|
+
const name = call.function?.name;
|
|
295
|
+
const executor = toolExecutors[name];
|
|
296
|
+
if (!executor) {
|
|
297
|
+
messages.push({ role: 'tool', tool_name: name || 'unknown', content: 'Unknown Audrey tool' });
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const args = parseToolArguments(call.function?.arguments);
|
|
302
|
+
console.error(`[audrey-ollama] tool ${name} ${JSON.stringify(args)}`);
|
|
303
|
+
try {
|
|
304
|
+
const result = await executor(args);
|
|
305
|
+
messages.push({
|
|
306
|
+
role: 'tool',
|
|
307
|
+
tool_name: name,
|
|
308
|
+
content: JSON.stringify(result).slice(0, 8000),
|
|
309
|
+
});
|
|
310
|
+
} catch (err) {
|
|
311
|
+
messages.push({
|
|
312
|
+
role: 'tool',
|
|
313
|
+
tool_name: name,
|
|
314
|
+
content: `Audrey tool error: ${err.message}`,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
console.log('Stopped after MAX_TOOL_LOOPS without a final model answer.');
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
main().catch((err) => {
|
|
324
|
+
console.error(err);
|
|
325
|
+
process.exit(1);
|
|
326
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "audrey",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.21.0",
|
|
4
|
+
"description": "Local-first memory runtime for AI agents with recall, consolidation, memory reflexes, contradiction detection, and tool-trace learning",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
7
7
|
"types": "dist/src/index.d.ts",
|
|
@@ -27,8 +27,16 @@
|
|
|
27
27
|
"dist/",
|
|
28
28
|
"docs/production-readiness.md",
|
|
29
29
|
"docs/benchmarking.md",
|
|
30
|
+
"docs/audrey-for-dummies.md",
|
|
31
|
+
"docs/future-of-llm-memory.md",
|
|
32
|
+
"docs/mcp-hosts.md",
|
|
33
|
+
"docs/ollama-local-agents.md",
|
|
34
|
+
"docs/assets/audrey-feature-grid.jpg",
|
|
35
|
+
"docs/assets/audrey-logo.svg",
|
|
36
|
+
"docs/assets/audrey-wordmark.png",
|
|
30
37
|
"docs/assets/benchmarks/",
|
|
31
38
|
"examples/",
|
|
39
|
+
"CHANGELOG.md",
|
|
32
40
|
"README.md",
|
|
33
41
|
"LICENSE"
|
|
34
42
|
],
|
|
@@ -76,6 +84,12 @@
|
|
|
76
84
|
"confidence",
|
|
77
85
|
"long-term-memory",
|
|
78
86
|
"persistent-memory",
|
|
87
|
+
"memory-preflight",
|
|
88
|
+
"memory-reflexes",
|
|
89
|
+
"agent-reflexes",
|
|
90
|
+
"agent-safety",
|
|
91
|
+
"tool-trace-memory",
|
|
92
|
+
"local-first-memory",
|
|
79
93
|
"rag",
|
|
80
94
|
"claude",
|
|
81
95
|
"agent-framework",
|
|
@@ -112,5 +126,10 @@
|
|
|
112
126
|
"@types/node": "^25.6.0",
|
|
113
127
|
"typescript": "^6.0.2",
|
|
114
128
|
"vitest": "^4.0.18"
|
|
129
|
+
},
|
|
130
|
+
"directories": {
|
|
131
|
+
"doc": "docs",
|
|
132
|
+
"example": "examples",
|
|
133
|
+
"test": "tests"
|
|
115
134
|
}
|
|
116
135
|
}
|