audrey 1.0.1 → 1.0.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/CHANGELOG.md +30 -0
- package/README.md +5 -3
- package/benchmarks/adapter-self-test.mjs +6 -2
- package/benchmarks/adapters/example-allow.mjs +5 -2
- package/benchmarks/adapters/mem0-platform.mjs +19 -12
- package/benchmarks/adapters/zep-cloud.mjs +51 -27
- package/benchmarks/baselines.js +11 -6
- package/benchmarks/build-leaderboard.mjs +36 -23
- package/benchmarks/cases.js +24 -12
- package/benchmarks/create-conformance-card.mjs +12 -3
- package/benchmarks/create-submission-bundle.mjs +22 -8
- package/benchmarks/dry-run-external-adapters.mjs +24 -12
- package/benchmarks/guardbench.js +263 -123
- package/benchmarks/output/adapter-self-test/guardbench-adapter-self-test.json +4 -4
- package/benchmarks/output/external/guardbench-external-dry-run.json +1 -1
- package/benchmarks/output/external/guardbench-external-evidence.json +1 -1
- package/benchmarks/output/guardbench-conformance-card.json +11 -11
- package/benchmarks/output/guardbench-raw.json +107 -108
- package/benchmarks/output/guardbench-summary.json +170 -172
- package/benchmarks/output/leaderboard/guardbench-leaderboard.json +5 -5
- package/benchmarks/output/leaderboard/guardbench-leaderboard.md +2 -2
- package/benchmarks/output/submission-bundle/guardbench-conformance-card.json +11 -11
- package/benchmarks/output/submission-bundle/guardbench-raw.json +107 -108
- package/benchmarks/output/submission-bundle/guardbench-summary.json +170 -172
- package/benchmarks/output/submission-bundle/submission-manifest.json +11 -11
- package/benchmarks/output/submission-bundle/validation-report.json +1 -1
- package/benchmarks/output/summary.json +57 -57
- package/benchmarks/perf-snapshot.js +12 -9
- package/benchmarks/perf.bench.js +14 -6
- package/benchmarks/public-paths.mjs +11 -5
- package/benchmarks/reference-results.js +10 -5
- package/benchmarks/report.js +48 -27
- package/benchmarks/run-external-guardbench.mjs +47 -25
- package/benchmarks/run.js +112 -59
- package/benchmarks/validate-adapter-module.mjs +13 -10
- package/benchmarks/validate-adapter-registry.mjs +16 -5
- package/benchmarks/validate-guardbench-artifacts.mjs +76 -19
- package/benchmarks/verify-external-evidence.mjs +86 -31
- package/benchmarks/verify-publication-artifacts.mjs +34 -11
- package/benchmarks/verify-submission-bundle.mjs +9 -4
- package/dist/mcp-server/config.d.ts +1 -1
- package/dist/mcp-server/config.d.ts.map +1 -1
- package/dist/mcp-server/config.js +5 -3
- package/dist/mcp-server/config.js.map +1 -1
- package/dist/mcp-server/index.d.ts +4 -3
- package/dist/mcp-server/index.d.ts.map +1 -1
- package/dist/mcp-server/index.js +479 -172
- package/dist/mcp-server/index.js.map +1 -1
- package/dist/src/action-key.d.ts.map +1 -1
- package/dist/src/action-key.js +6 -2
- package/dist/src/action-key.js.map +1 -1
- package/dist/src/adaptive.d.ts.map +1 -1
- package/dist/src/adaptive.js +4 -2
- package/dist/src/adaptive.js.map +1 -1
- package/dist/src/affect.d.ts.map +1 -1
- package/dist/src/affect.js +8 -5
- package/dist/src/affect.js.map +1 -1
- package/dist/src/audrey.d.ts +1 -1
- package/dist/src/audrey.d.ts.map +1 -1
- package/dist/src/audrey.js +93 -49
- package/dist/src/audrey.js.map +1 -1
- package/dist/src/capsule.d.ts.map +1 -1
- package/dist/src/capsule.js +37 -15
- package/dist/src/capsule.js.map +1 -1
- package/dist/src/causal.d.ts +1 -1
- package/dist/src/causal.d.ts.map +1 -1
- package/dist/src/causal.js +4 -2
- package/dist/src/causal.js.map +1 -1
- package/dist/src/confidence.d.ts.map +1 -1
- package/dist/src/confidence.js +5 -5
- package/dist/src/confidence.js.map +1 -1
- package/dist/src/consolidate.d.ts.map +1 -1
- package/dist/src/consolidate.js +17 -9
- package/dist/src/consolidate.js.map +1 -1
- package/dist/src/context.js +1 -1
- package/dist/src/context.js.map +1 -1
- package/dist/src/controller.d.ts.map +1 -1
- package/dist/src/controller.js +24 -13
- package/dist/src/controller.js.map +1 -1
- package/dist/src/db.d.ts.map +1 -1
- package/dist/src/db.js +78 -27
- package/dist/src/db.js.map +1 -1
- package/dist/src/decay.d.ts +1 -1
- package/dist/src/decay.d.ts.map +1 -1
- package/dist/src/decay.js +1 -1
- package/dist/src/decay.js.map +1 -1
- package/dist/src/embedding.d.ts +12 -4
- package/dist/src/embedding.d.ts.map +1 -1
- package/dist/src/embedding.js +18 -16
- package/dist/src/embedding.js.map +1 -1
- package/dist/src/encode.d.ts.map +1 -1
- package/dist/src/encode.js +5 -4
- package/dist/src/encode.js.map +1 -1
- package/dist/src/events.d.ts +3 -2
- package/dist/src/events.d.ts.map +1 -1
- package/dist/src/events.js +7 -3
- package/dist/src/events.js.map +1 -1
- package/dist/src/export.d.ts.map +1 -1
- package/dist/src/export.js +21 -7
- package/dist/src/export.js.map +1 -1
- package/dist/src/feedback.d.ts.map +1 -1
- package/dist/src/feedback.js +1 -1
- package/dist/src/feedback.js.map +1 -1
- package/dist/src/forget.d.ts.map +1 -1
- package/dist/src/forget.js +12 -6
- package/dist/src/forget.js.map +1 -1
- package/dist/src/fts.d.ts.map +1 -1
- package/dist/src/fts.js +20 -8
- package/dist/src/fts.js.map +1 -1
- package/dist/src/hybrid-recall.d.ts.map +1 -1
- package/dist/src/hybrid-recall.js +12 -6
- package/dist/src/hybrid-recall.js.map +1 -1
- package/dist/src/impact.d.ts.map +1 -1
- package/dist/src/impact.js +26 -10
- package/dist/src/impact.js.map +1 -1
- package/dist/src/import.d.ts.map +1 -1
- package/dist/src/import.js +11 -6
- package/dist/src/import.js.map +1 -1
- package/dist/src/index.d.ts +3 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/interference.d.ts.map +1 -1
- package/dist/src/interference.js +10 -5
- package/dist/src/interference.js.map +1 -1
- package/dist/src/introspect.d.ts.map +1 -1
- package/dist/src/introspect.js +12 -6
- package/dist/src/introspect.js.map +1 -1
- package/dist/src/llm.d.ts +2 -2
- package/dist/src/llm.d.ts.map +1 -1
- package/dist/src/llm.js +6 -6
- package/dist/src/llm.js.map +1 -1
- package/dist/src/migrate.d.ts.map +1 -1
- package/dist/src/migrate.js +10 -4
- package/dist/src/migrate.js.map +1 -1
- package/dist/src/preflight.d.ts.map +1 -1
- package/dist/src/preflight.js +6 -8
- package/dist/src/preflight.js.map +1 -1
- package/dist/src/profile.d.ts.map +1 -1
- package/dist/src/profile.js.map +1 -1
- package/dist/src/promote.d.ts.map +1 -1
- package/dist/src/promote.js +16 -7
- package/dist/src/promote.js.map +1 -1
- package/dist/src/prompts.d.ts.map +1 -1
- package/dist/src/prompts.js +1 -2
- package/dist/src/prompts.js.map +1 -1
- package/dist/src/recall.d.ts.map +1 -1
- package/dist/src/recall.js +85 -18
- package/dist/src/recall.js.map +1 -1
- package/dist/src/redact.d.ts.map +1 -1
- package/dist/src/redact.js +9 -4
- package/dist/src/redact.js.map +1 -1
- package/dist/src/reflexes.d.ts.map +1 -1
- package/dist/src/reflexes.js +1 -7
- package/dist/src/reflexes.js.map +1 -1
- package/dist/src/rollback.d.ts.map +1 -1
- package/dist/src/rollback.js +4 -2
- package/dist/src/rollback.js.map +1 -1
- package/dist/src/routes.d.ts.map +1 -1
- package/dist/src/routes.js +33 -13
- package/dist/src/routes.js.map +1 -1
- package/dist/src/rules-compiler.d.ts.map +1 -1
- package/dist/src/rules-compiler.js +24 -2
- package/dist/src/rules-compiler.js.map +1 -1
- package/dist/src/server.js +2 -2
- package/dist/src/server.js.map +1 -1
- package/dist/src/tool-trace.d.ts +2 -2
- package/dist/src/tool-trace.d.ts.map +1 -1
- package/dist/src/tool-trace.js +12 -4
- package/dist/src/tool-trace.js.map +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/ulid.js +1 -1
- package/dist/src/ulid.js.map +1 -1
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js.map +1 -1
- package/dist/src/validate.d.ts.map +1 -1
- package/dist/src/validate.js +20 -10
- package/dist/src/validate.js.map +1 -1
- package/docs/paper/07-evaluation.md +5 -5
- package/docs/paper/audrey-paper-v1.md +5 -5
- package/docs/paper/evidence-ledger.md +1 -1
- package/docs/paper/output/arxiv/arxiv-manifest.json +4 -4
- package/docs/paper/output/arxiv/main.tex +5 -5
- package/docs/paper/output/arxiv-compile-report.json +3 -3
- package/docs/paper/output/submission-bundle/README.md +5 -3
- package/docs/paper/output/submission-bundle/benchmarks/output/adapter-self-test/guardbench-adapter-self-test.json +4 -4
- package/docs/paper/output/submission-bundle/benchmarks/output/external/guardbench-external-dry-run.json +1 -1
- package/docs/paper/output/submission-bundle/benchmarks/output/external/guardbench-external-evidence.json +1 -1
- package/docs/paper/output/submission-bundle/benchmarks/output/guardbench-conformance-card.json +11 -11
- package/docs/paper/output/submission-bundle/benchmarks/output/guardbench-raw.json +107 -108
- package/docs/paper/output/submission-bundle/benchmarks/output/guardbench-summary.json +170 -172
- package/docs/paper/output/submission-bundle/benchmarks/output/leaderboard/guardbench-leaderboard.json +5 -5
- package/docs/paper/output/submission-bundle/benchmarks/output/leaderboard/guardbench-leaderboard.md +2 -2
- package/docs/paper/output/submission-bundle/benchmarks/output/submission-bundle/submission-manifest.json +11 -11
- package/docs/paper/output/submission-bundle/benchmarks/output/submission-bundle/validation-report.json +1 -1
- package/docs/paper/output/submission-bundle/benchmarks/output/summary.json +58 -58
- package/docs/paper/output/submission-bundle/docs/paper/07-evaluation.md +5 -5
- package/docs/paper/output/submission-bundle/docs/paper/audrey-paper-v1.md +5 -5
- package/docs/paper/output/submission-bundle/docs/paper/evidence-ledger.md +1 -1
- package/docs/paper/output/submission-bundle/docs/paper/output/arxiv/arxiv-manifest.json +4 -4
- package/docs/paper/output/submission-bundle/docs/paper/output/arxiv/main.tex +5 -5
- package/docs/paper/output/submission-bundle/docs/paper/output/arxiv-compile-report.json +3 -3
- package/docs/paper/output/submission-bundle/package.json +17 -4
- package/docs/paper/output/submission-bundle/paper-submission-manifest.json +36 -36
- package/examples/fintech-ops-demo.js +12 -5
- package/examples/healthcare-ops-demo.js +8 -4
- package/examples/ollama-memory-agent.js +41 -13
- package/examples/stripe-demo.js +12 -5
- package/package.json +17 -4
- package/scripts/audit-release-completion.mjs +179 -101
- package/scripts/create-arxiv-source.mjs +20 -14
- package/scripts/create-paper-submission-bundle.mjs +6 -2
- package/scripts/finalize-release.mjs +111 -36
- package/scripts/prepare-release-cut.mjs +14 -6
- package/scripts/publish-release-bundle.mjs +62 -23
- package/scripts/publish-release-github-api.mjs +89 -24
- package/scripts/smoke-cli.js +9 -9
- package/scripts/sync-paper-artifacts.mjs +5 -1
- package/scripts/verify-arxiv-compile.mjs +52 -16
- package/scripts/verify-arxiv-source.mjs +45 -15
- package/scripts/verify-browser-launch-plan.mjs +28 -11
- package/scripts/verify-browser-launch-results.mjs +32 -14
- package/scripts/verify-paper-artifacts.mjs +539 -79
- package/scripts/verify-paper-claims.mjs +48 -20
- package/scripts/verify-paper-submission-bundle.mjs +22 -11
- package/scripts/verify-publication-pack.mjs +23 -9
- package/scripts/verify-release-readiness.mjs +211 -76
package/dist/mcp-server/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { homedir, platform, tmpdir } from 'node:os';
|
|
4
4
|
import { dirname, join, resolve } from 'node:path';
|
|
5
|
-
import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync, } from 'node:fs';
|
|
6
6
|
import { execFileSync } from 'node:child_process';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
import { Audrey, MemoryController } from '../src/index.js';
|
|
@@ -56,21 +56,46 @@ function isEmbeddingWarmupDisabled(env = process.env) {
|
|
|
56
56
|
return value === '1' || value?.toLowerCase() === 'true' || value?.toLowerCase() === 'yes';
|
|
57
57
|
}
|
|
58
58
|
export const memoryEncodeToolSchema = {
|
|
59
|
-
content: z
|
|
59
|
+
content: z
|
|
60
|
+
.string()
|
|
60
61
|
.max(MAX_MEMORY_CONTENT_LENGTH)
|
|
61
62
|
.refine(isNonEmptyText, 'Content must not be empty')
|
|
62
63
|
.describe('The memory content to encode'),
|
|
63
64
|
source: z.enum(VALID_SOURCES).describe('Source type of the memory'),
|
|
64
65
|
tags: z.array(z.string()).optional().describe('Optional tags for categorization'),
|
|
65
66
|
salience: z.number().min(0).max(1).optional().describe('Importance weight 0-1'),
|
|
66
|
-
context: z
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
context: z
|
|
68
|
+
.record(z.string(), z.string())
|
|
69
|
+
.optional()
|
|
70
|
+
.describe('Situational context as key-value pairs (e.g., {task: "debugging", domain: "payments"})'),
|
|
71
|
+
affect: z
|
|
72
|
+
.object({
|
|
73
|
+
valence: z
|
|
74
|
+
.number()
|
|
75
|
+
.min(-1)
|
|
76
|
+
.max(1)
|
|
77
|
+
.describe('Emotional valence: -1 (very negative) to 1 (very positive)'),
|
|
78
|
+
arousal: z
|
|
79
|
+
.number()
|
|
80
|
+
.min(0)
|
|
81
|
+
.max(1)
|
|
82
|
+
.optional()
|
|
83
|
+
.describe('Emotional arousal: 0 (calm) to 1 (highly activated)'),
|
|
84
|
+
label: z
|
|
85
|
+
.string()
|
|
86
|
+
.optional()
|
|
87
|
+
.describe('Human-readable emotion label (e.g., "curiosity", "frustration", "relief")'),
|
|
88
|
+
})
|
|
89
|
+
.optional()
|
|
90
|
+
.describe('Emotional affect - how this memory feels'),
|
|
91
|
+
private: z
|
|
92
|
+
.boolean()
|
|
93
|
+
.optional()
|
|
94
|
+
.describe('If true, memory is only visible to the AI and excluded from public recall results'),
|
|
95
|
+
wait_for_consolidation: z
|
|
96
|
+
.boolean()
|
|
97
|
+
.optional()
|
|
98
|
+
.describe('If true, wait for post-encode validation/interference/resonance work before returning. Defaults to false.'),
|
|
74
99
|
};
|
|
75
100
|
export const memoryRecallToolSchema = {
|
|
76
101
|
query: z.string().describe('Search query to match against memories'),
|
|
@@ -78,73 +103,196 @@ export const memoryRecallToolSchema = {
|
|
|
78
103
|
types: z.array(z.enum(VALID_TYPES)).optional().describe('Memory types to search'),
|
|
79
104
|
min_confidence: z.number().min(0).max(1).optional().describe('Minimum confidence threshold'),
|
|
80
105
|
tags: z.array(z.string()).optional().describe('Only return episodic memories with these tags'),
|
|
81
|
-
sources: z
|
|
106
|
+
sources: z
|
|
107
|
+
.array(z.enum(VALID_SOURCES))
|
|
108
|
+
.optional()
|
|
109
|
+
.describe('Only return episodic memories from these sources'),
|
|
82
110
|
after: z.string().optional().describe('Only return memories created after this ISO date'),
|
|
83
111
|
before: z.string().optional().describe('Only return memories created before this ISO date'),
|
|
84
|
-
context: z
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
112
|
+
context: z
|
|
113
|
+
.record(z.string(), z.string())
|
|
114
|
+
.optional()
|
|
115
|
+
.describe('Retrieval context - memories encoded in matching context get boosted'),
|
|
116
|
+
mood: z
|
|
117
|
+
.object({
|
|
118
|
+
valence: z
|
|
119
|
+
.number()
|
|
120
|
+
.min(-1)
|
|
121
|
+
.max(1)
|
|
122
|
+
.describe('Current emotional valence: -1 (negative) to 1 (positive)'),
|
|
123
|
+
arousal: z
|
|
124
|
+
.number()
|
|
125
|
+
.min(0)
|
|
126
|
+
.max(1)
|
|
127
|
+
.optional()
|
|
128
|
+
.describe('Current arousal: 0 (calm) to 1 (activated)'),
|
|
129
|
+
})
|
|
130
|
+
.optional()
|
|
131
|
+
.describe('Current mood - boosts recall of memories encoded in similar emotional state'),
|
|
132
|
+
retrieval: z
|
|
133
|
+
.enum(['hybrid', 'vector'])
|
|
134
|
+
.optional()
|
|
135
|
+
.describe('Retrieval strategy. hybrid is the default (vector + FTS/BM25 fusion); vector bypasses FTS for lower latency but loses lexical exact-match signal.'),
|
|
136
|
+
scope: z
|
|
137
|
+
.enum(['agent', 'shared'])
|
|
138
|
+
.optional()
|
|
139
|
+
.describe('agent restricts recall to this MCP server agent identity. shared searches the whole store. Defaults to shared for backward compatibility.'),
|
|
91
140
|
};
|
|
92
141
|
export const memoryImportToolSchema = {
|
|
93
142
|
snapshot: importSnapshotSchema.describe('A validated snapshot from memory_export'),
|
|
94
143
|
};
|
|
95
144
|
export const memoryForgetToolSchema = {
|
|
96
145
|
id: z.string().optional().describe('ID of the memory to forget'),
|
|
97
|
-
query: z
|
|
98
|
-
|
|
99
|
-
|
|
146
|
+
query: z
|
|
147
|
+
.string()
|
|
148
|
+
.optional()
|
|
149
|
+
.describe('Semantic query to find and forget the closest matching memory'),
|
|
150
|
+
min_similarity: z
|
|
151
|
+
.number()
|
|
152
|
+
.min(0)
|
|
153
|
+
.max(1)
|
|
154
|
+
.optional()
|
|
155
|
+
.describe('Minimum similarity for query-based forget (default 0.9)'),
|
|
156
|
+
purge: z
|
|
157
|
+
.boolean()
|
|
158
|
+
.optional()
|
|
159
|
+
.describe('Hard-delete the memory permanently (default false, soft-delete)'),
|
|
100
160
|
};
|
|
101
161
|
export const memoryValidateToolSchema = {
|
|
102
162
|
id: z.string().describe('ID of the memory to validate'),
|
|
103
|
-
outcome: z
|
|
163
|
+
outcome: z
|
|
164
|
+
.enum(['used', 'helpful', 'wrong'])
|
|
165
|
+
.describe('How the memory played out: "used" (referenced without obvious value), "helpful" (drove a correct action — reinforces salience and retrieval), "wrong" (memory was misleading — bumps challenge_count and decreases salience).'),
|
|
104
166
|
};
|
|
105
167
|
export const memoryPreflightToolSchema = {
|
|
106
|
-
action: z
|
|
168
|
+
action: z
|
|
169
|
+
.string()
|
|
107
170
|
.refine(isNonEmptyText, 'Action must not be empty')
|
|
108
171
|
.describe('Natural-language description of the action the agent is about to take.'),
|
|
109
|
-
tool: z
|
|
110
|
-
|
|
172
|
+
tool: z
|
|
173
|
+
.string()
|
|
174
|
+
.optional()
|
|
175
|
+
.describe('Tool or command family about to be used, e.g. Bash, npm test, Edit, deploy.'),
|
|
176
|
+
session_id: z
|
|
177
|
+
.string()
|
|
178
|
+
.optional()
|
|
179
|
+
.describe('Session identifier for grouping the optional preflight event.'),
|
|
111
180
|
cwd: z.string().optional().describe('Working directory for the action.'),
|
|
112
|
-
files: z
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
181
|
+
files: z
|
|
182
|
+
.array(z.string())
|
|
183
|
+
.optional()
|
|
184
|
+
.describe('File paths to fingerprint if record_event is true.'),
|
|
185
|
+
strict: z
|
|
186
|
+
.boolean()
|
|
187
|
+
.optional()
|
|
188
|
+
.describe('If true, high-severity memory warnings produce decision=block instead of caution.'),
|
|
189
|
+
limit: z
|
|
190
|
+
.number()
|
|
191
|
+
.int()
|
|
192
|
+
.min(1)
|
|
193
|
+
.max(50)
|
|
194
|
+
.optional()
|
|
195
|
+
.describe('Max recall results to consider before preflight categorization.'),
|
|
196
|
+
budget_chars: z
|
|
197
|
+
.number()
|
|
198
|
+
.int()
|
|
199
|
+
.min(200)
|
|
200
|
+
.max(32000)
|
|
201
|
+
.optional()
|
|
202
|
+
.describe('Capsule budget in characters.'),
|
|
203
|
+
mode: z
|
|
204
|
+
.enum(['balanced', 'conservative', 'aggressive'])
|
|
205
|
+
.optional()
|
|
206
|
+
.describe('Underlying capsule mode. Defaults to conservative.'),
|
|
207
|
+
failure_window_hours: z
|
|
208
|
+
.number()
|
|
209
|
+
.int()
|
|
210
|
+
.min(1)
|
|
211
|
+
.max(8760)
|
|
212
|
+
.optional()
|
|
213
|
+
.describe('How far back to check failed tool events. Defaults to 168 hours.'),
|
|
214
|
+
include_status: z
|
|
215
|
+
.boolean()
|
|
216
|
+
.optional()
|
|
217
|
+
.describe('Include memory health in the response and warning calculation. Defaults to true.'),
|
|
218
|
+
record_event: z
|
|
219
|
+
.boolean()
|
|
220
|
+
.optional()
|
|
221
|
+
.describe('Record a redacted PreToolUse event for this preflight. Defaults to false.'),
|
|
222
|
+
include_capsule: z
|
|
223
|
+
.boolean()
|
|
224
|
+
.optional()
|
|
225
|
+
.describe('If false, omit the embedded Memory Capsule from the response.'),
|
|
226
|
+
scope: z
|
|
227
|
+
.enum(['agent', 'shared'])
|
|
228
|
+
.optional()
|
|
229
|
+
.describe('agent restricts memory recall to this server agent identity. shared searches the whole store. Defaults to agent.'),
|
|
122
230
|
};
|
|
123
231
|
const { record_event: _preflightRecordEvent, ...memoryGuardBeforeFields } = memoryPreflightToolSchema;
|
|
124
232
|
export const memoryGuardBeforeToolSchema = {
|
|
125
233
|
...memoryGuardBeforeFields,
|
|
126
|
-
session_id: z
|
|
127
|
-
|
|
234
|
+
session_id: z
|
|
235
|
+
.string()
|
|
236
|
+
.optional()
|
|
237
|
+
.describe('Session identifier for grouping the required guard receipt event.'),
|
|
238
|
+
files: z
|
|
239
|
+
.array(z.string())
|
|
240
|
+
.optional()
|
|
241
|
+
.describe('File paths to fingerprint in the required guard receipt.'),
|
|
128
242
|
};
|
|
129
243
|
export const memoryGuardAfterToolSchema = {
|
|
130
|
-
receipt_id: z
|
|
244
|
+
receipt_id: z
|
|
245
|
+
.string()
|
|
131
246
|
.refine(isNonEmptyText, 'Receipt id must not be empty')
|
|
132
247
|
.describe('Receipt id returned by memory_guard_before.'),
|
|
133
|
-
tool: z
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
248
|
+
tool: z
|
|
249
|
+
.string()
|
|
250
|
+
.optional()
|
|
251
|
+
.describe('Tool or command family that completed, e.g. Bash, npm test, Edit, deploy.'),
|
|
252
|
+
session_id: z
|
|
253
|
+
.string()
|
|
254
|
+
.optional()
|
|
255
|
+
.describe('Session identifier for grouping related guard events.'),
|
|
256
|
+
input: z
|
|
257
|
+
.unknown()
|
|
258
|
+
.optional()
|
|
259
|
+
.describe('Tool input. Hashed and never stored raw; redacted metadata is only stored when retain_details is true.'),
|
|
260
|
+
output: z
|
|
261
|
+
.unknown()
|
|
262
|
+
.optional()
|
|
263
|
+
.describe('Tool output. Same redaction and storage policy as input.'),
|
|
264
|
+
outcome: z
|
|
265
|
+
.enum(['succeeded', 'failed', 'blocked', 'skipped', 'unknown'])
|
|
266
|
+
.optional()
|
|
267
|
+
.describe('Outcome classification'),
|
|
268
|
+
error_summary: z
|
|
269
|
+
.string()
|
|
270
|
+
.optional()
|
|
271
|
+
.describe('Short error description if the action failed. Redacted and truncated to 2 KB.'),
|
|
139
272
|
cwd: z.string().optional().describe('Working directory at the time of the action.'),
|
|
140
|
-
files: z
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
273
|
+
files: z
|
|
274
|
+
.array(z.string())
|
|
275
|
+
.optional()
|
|
276
|
+
.describe('File paths to fingerprint (size + mtime + content hash).'),
|
|
277
|
+
metadata: z
|
|
278
|
+
.record(z.string(), z.unknown())
|
|
279
|
+
.optional()
|
|
280
|
+
.describe('Arbitrary structured metadata (redacted before storage).'),
|
|
281
|
+
retain_details: z
|
|
282
|
+
.boolean()
|
|
283
|
+
.optional()
|
|
284
|
+
.describe('If true, redacted input and output payloads are stored alongside hashes. Defaults to false.'),
|
|
285
|
+
evidence_feedback: z
|
|
286
|
+
.record(z.string(), z.enum(['used', 'helpful', 'wrong']))
|
|
287
|
+
.optional()
|
|
288
|
+
.describe('Map of evidence ids from the guard receipt to memory validation outcomes.'),
|
|
144
289
|
};
|
|
145
290
|
export const memoryReflexesToolSchema = {
|
|
146
291
|
...memoryPreflightToolSchema,
|
|
147
|
-
include_preflight: z
|
|
292
|
+
include_preflight: z
|
|
293
|
+
.boolean()
|
|
294
|
+
.optional()
|
|
295
|
+
.describe('If true, include the full underlying preflight report.'),
|
|
148
296
|
};
|
|
149
297
|
// ---------------------------------------------------------------------------
|
|
150
298
|
// CLI subcommands
|
|
@@ -160,7 +308,9 @@ async function serveHttp() {
|
|
|
160
308
|
if (apiKey) {
|
|
161
309
|
console.error('[audrey-http] API key authentication enabled');
|
|
162
310
|
}
|
|
163
|
-
else if (server.hostname === '127.0.0.1' ||
|
|
311
|
+
else if (server.hostname === '127.0.0.1' ||
|
|
312
|
+
server.hostname === '::1' ||
|
|
313
|
+
server.hostname === 'localhost') {
|
|
164
314
|
console.error('[audrey-http] no API key set (loopback only — set AUDREY_API_KEY to enable network access)');
|
|
165
315
|
}
|
|
166
316
|
}
|
|
@@ -178,7 +328,9 @@ async function reembed() {
|
|
|
178
328
|
try {
|
|
179
329
|
await initializeEmbeddingProvider(audrey.embeddingProvider);
|
|
180
330
|
const { reembedAll } = await import('../src/migrate.js');
|
|
181
|
-
const counts = await reembedAll(audrey.db, audrey.embeddingProvider, {
|
|
331
|
+
const counts = await reembedAll(audrey.db, audrey.embeddingProvider, {
|
|
332
|
+
dropAndRecreate: dimensionsChanged,
|
|
333
|
+
});
|
|
182
334
|
console.log(`Done. Re-embedded: ${counts.episodes} episodes, ${counts.semantics} semantics, ${counts.procedures} procedures`);
|
|
183
335
|
}
|
|
184
336
|
finally {
|
|
@@ -208,13 +360,13 @@ async function dream() {
|
|
|
208
360
|
console.log(`[audrey] Embedding: ${embeddingLabel}`);
|
|
209
361
|
const result = await audrey.dream();
|
|
210
362
|
const health = audrey.memoryStatus();
|
|
211
|
-
console.log(`[audrey] Consolidation: evaluated ${result.consolidation.episodesEvaluated} episodes, `
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
console.log(`[audrey] Decay: evaluated ${result.decay.totalEvaluated} memories, `
|
|
215
|
-
|
|
216
|
-
console.log(`[audrey] Final: ${result.stats.episodic} episodic, ${result.stats.semantic} semantic, ${result.stats.procedural} procedural `
|
|
217
|
-
|
|
363
|
+
console.log(`[audrey] Consolidation: evaluated ${result.consolidation.episodesEvaluated} episodes, ` +
|
|
364
|
+
`found ${result.consolidation.clustersFound} clusters, extracted ${result.consolidation.principlesExtracted} principles ` +
|
|
365
|
+
`(${result.consolidation.semanticsCreated ?? 0} semantic, ${result.consolidation.proceduresCreated ?? 0} procedural)`);
|
|
366
|
+
console.log(`[audrey] Decay: evaluated ${result.decay.totalEvaluated} memories, ` +
|
|
367
|
+
`${result.decay.transitionedToDormant} transitioned to dormant`);
|
|
368
|
+
console.log(`[audrey] Final: ${result.stats.episodic} episodic, ${result.stats.semantic} semantic, ${result.stats.procedural} procedural ` +
|
|
369
|
+
`| ${health.healthy ? 'healthy' : 'unhealthy'}`);
|
|
218
370
|
console.log('[audrey] Dream complete.');
|
|
219
371
|
}
|
|
220
372
|
finally {
|
|
@@ -257,9 +409,9 @@ async function greeting() {
|
|
|
257
409
|
}
|
|
258
410
|
const storedDimensions = readStoredDimensions(dataDir);
|
|
259
411
|
const resolvedEmbedding = resolveEmbeddingProvider(process.env, process.env['AUDREY_EMBEDDING_PROVIDER']);
|
|
260
|
-
const canUseResolvedEmbedding = Boolean(contextArg)
|
|
261
|
-
|
|
262
|
-
|
|
412
|
+
const canUseResolvedEmbedding = Boolean(contextArg) &&
|
|
413
|
+
storedDimensions !== null &&
|
|
414
|
+
storedDimensions === resolvedEmbedding.dimensions;
|
|
263
415
|
const dimensions = storedDimensions || resolvedEmbedding.dimensions || 8;
|
|
264
416
|
const audrey = new Audrey({
|
|
265
417
|
dataDir,
|
|
@@ -272,28 +424,30 @@ async function greeting() {
|
|
|
272
424
|
if (canUseResolvedEmbedding) {
|
|
273
425
|
await initializeEmbeddingProvider(audrey.embeddingProvider);
|
|
274
426
|
}
|
|
275
|
-
const result = await audrey.greeting({
|
|
427
|
+
const result = await audrey.greeting({
|
|
428
|
+
context: canUseResolvedEmbedding ? contextArg : undefined,
|
|
429
|
+
});
|
|
276
430
|
const health = audrey.memoryStatus();
|
|
277
431
|
const lines = [];
|
|
278
432
|
lines.push(`[Audrey v${VERSION}] Memory briefing`);
|
|
279
433
|
lines.push('');
|
|
280
434
|
if (contextArg && !canUseResolvedEmbedding) {
|
|
281
|
-
lines.push(`Context recall skipped: stored index is ${storedDimensions ?? 'unknown'}d `
|
|
282
|
-
|
|
435
|
+
lines.push(`Context recall skipped: stored index is ${storedDimensions ?? 'unknown'}d ` +
|
|
436
|
+
`but current embedding config resolves to ${resolvedEmbedding.dimensions}d.`);
|
|
283
437
|
lines.push('');
|
|
284
438
|
}
|
|
285
439
|
// Mood
|
|
286
440
|
if (result.mood && result.mood.samples > 0) {
|
|
287
441
|
const v = result.mood.valence;
|
|
288
442
|
const moodWord = v > 0.3 ? 'positive' : v < -0.3 ? 'negative' : 'neutral';
|
|
289
|
-
lines.push(`Mood: ${moodWord} (valence=${v.toFixed(2)}, `
|
|
290
|
-
|
|
291
|
-
|
|
443
|
+
lines.push(`Mood: ${moodWord} (valence=${v.toFixed(2)}, ` +
|
|
444
|
+
`arousal=${result.mood.arousal.toFixed(2)}, ` +
|
|
445
|
+
`from ${result.mood.samples} recent memories)`);
|
|
292
446
|
}
|
|
293
447
|
// Health
|
|
294
448
|
const stats = audrey.introspect();
|
|
295
|
-
lines.push(`Memory: ${stats.episodic} episodic, ${stats.semantic} semantic, `
|
|
296
|
-
|
|
449
|
+
lines.push(`Memory: ${stats.episodic} episodic, ${stats.semantic} semantic, ` +
|
|
450
|
+
`${stats.procedural} procedural | ${health.healthy ? 'healthy' : 'needs attention'}`);
|
|
297
451
|
lines.push('');
|
|
298
452
|
// Principles (semantic memories)
|
|
299
453
|
if (result.principles?.length > 0) {
|
|
@@ -398,12 +552,12 @@ async function reflect() {
|
|
|
398
552
|
// Always run dream cycle after reflect
|
|
399
553
|
console.log('[audrey] Starting dream cycle...');
|
|
400
554
|
const result = await audrey.dream();
|
|
401
|
-
console.log(`[audrey] Consolidation: ${result.consolidation.episodesEvaluated} episodes evaluated, `
|
|
402
|
-
|
|
403
|
-
console.log(`[audrey] Decay: ${result.decay.totalEvaluated} evaluated, `
|
|
404
|
-
|
|
405
|
-
console.log(`[audrey] Status: ${result.stats.episodic} episodic, ${result.stats.semantic} semantic, `
|
|
406
|
-
|
|
555
|
+
console.log(`[audrey] Consolidation: ${result.consolidation.episodesEvaluated} episodes evaluated, ` +
|
|
556
|
+
`${result.consolidation.clustersFound} clusters, ${result.consolidation.principlesExtracted} principles`);
|
|
557
|
+
console.log(`[audrey] Decay: ${result.decay.totalEvaluated} evaluated, ` +
|
|
558
|
+
`${result.decay.transitionedToDormant} dormant`);
|
|
559
|
+
console.log(`[audrey] Status: ${result.stats.episodic} episodic, ${result.stats.semantic} semantic, ` +
|
|
560
|
+
`${result.stats.procedural} procedural`);
|
|
407
561
|
console.log('[audrey] Dream complete.');
|
|
408
562
|
}
|
|
409
563
|
finally {
|
|
@@ -449,11 +603,7 @@ export function formatInstallGuide(host, env = process.env, dryRun = false) {
|
|
|
449
603
|
formatMcpHostConfig(normalizedHost, env),
|
|
450
604
|
'',
|
|
451
605
|
...(normalizedHost === 'claude-code'
|
|
452
|
-
? [
|
|
453
|
-
'Generated Claude Code hook config:',
|
|
454
|
-
formatClaudeCodeHookConfig(),
|
|
455
|
-
'',
|
|
456
|
-
]
|
|
606
|
+
? ['Generated Claude Code hook config:', formatClaudeCodeHookConfig(), '']
|
|
457
607
|
: []),
|
|
458
608
|
'Next steps:',
|
|
459
609
|
];
|
|
@@ -643,8 +793,12 @@ function printHookConfig() {
|
|
|
643
793
|
dryRun: options.dryRun,
|
|
644
794
|
});
|
|
645
795
|
const action = result.dryRun
|
|
646
|
-
? result.changed
|
|
647
|
-
|
|
796
|
+
? result.changed
|
|
797
|
+
? 'would update'
|
|
798
|
+
: 'would leave unchanged'
|
|
799
|
+
: result.changed
|
|
800
|
+
? 'updated'
|
|
801
|
+
: 'already up to date';
|
|
648
802
|
console.log(`[audrey] Claude Code hook settings ${action}: ${result.settingsPath}`);
|
|
649
803
|
if (result.backupPath)
|
|
650
804
|
console.log(`[audrey] backup written: ${result.backupPath}`);
|
|
@@ -826,7 +980,9 @@ export function applyClaudeCodeHookConfig(options) {
|
|
|
826
980
|
}
|
|
827
981
|
catch (err) {
|
|
828
982
|
const message = err instanceof Error ? err.message : String(err);
|
|
829
|
-
throw new Error(`Cannot merge Audrey hooks into invalid JSON at ${settingsPath}: ${message}
|
|
983
|
+
throw new Error(`Cannot merge Audrey hooks into invalid JSON at ${settingsPath}: ${message}`, {
|
|
984
|
+
cause: err,
|
|
985
|
+
});
|
|
830
986
|
}
|
|
831
987
|
}
|
|
832
988
|
const settings = mergeClaudeCodeHookSettings(existing);
|
|
@@ -875,11 +1031,7 @@ function demoScenario(argv = process.argv) {
|
|
|
875
1031
|
return cliValue('--scenario', argv);
|
|
876
1032
|
}
|
|
877
1033
|
function formatControllerGuardResult(result) {
|
|
878
|
-
const label = result.decision === 'block'
|
|
879
|
-
? 'BLOCKED'
|
|
880
|
-
: result.decision === 'warn'
|
|
881
|
-
? 'WARN'
|
|
882
|
-
: 'ALLOW';
|
|
1034
|
+
const label = result.decision === 'block' ? 'BLOCKED' : result.decision === 'warn' ? 'WARN' : 'ALLOW';
|
|
883
1035
|
const lines = [];
|
|
884
1036
|
lines.push(`Audrey Guard: ${label}`);
|
|
885
1037
|
lines.push('');
|
|
@@ -992,8 +1144,8 @@ export async function runDemoCommand({ out = console.log, keep = process.argv.in
|
|
|
992
1144
|
tags: ['procedure', 'memory-capsule', 'agent-loop'],
|
|
993
1145
|
}));
|
|
994
1146
|
ids.push(await audrey.encode({
|
|
995
|
-
content: 'If a host cannot auto-install Audrey, run npx audrey mcp-config codex '
|
|
996
|
-
|
|
1147
|
+
content: 'If a host cannot auto-install Audrey, run npx audrey mcp-config codex ' +
|
|
1148
|
+
'or npx audrey mcp-config generic and paste the generated config.',
|
|
997
1149
|
source: 'direct-observation',
|
|
998
1150
|
tags: ['procedure', 'mcp', 'first-contact'],
|
|
999
1151
|
}));
|
|
@@ -1011,8 +1163,8 @@ export async function runDemoCommand({ out = console.log, keep = process.argv.in
|
|
|
1011
1163
|
event: 'PostToolUse',
|
|
1012
1164
|
tool: 'npm test',
|
|
1013
1165
|
outcome: 'failed',
|
|
1014
|
-
errorSummary: 'Vitest can fail with spawn EPERM on locked-down Windows hosts; '
|
|
1015
|
-
|
|
1166
|
+
errorSummary: 'Vitest can fail with spawn EPERM on locked-down Windows hosts; ' +
|
|
1167
|
+
'use build, typecheck, benchmarks, and direct dist smokes as the fallback evidence path.',
|
|
1016
1168
|
cwd: process.cwd(),
|
|
1017
1169
|
metadata: { demo: true, source: 'audrey demo' },
|
|
1018
1170
|
});
|
|
@@ -1118,12 +1270,15 @@ export function buildStatusReport({ dataDir = resolveDataDir(process.env), claud
|
|
|
1118
1270
|
});
|
|
1119
1271
|
report.stats = audrey.introspect();
|
|
1120
1272
|
report.health = audrey.memoryStatus();
|
|
1121
|
-
report.lastConsolidation =
|
|
1273
|
+
report.lastConsolidation =
|
|
1274
|
+
audrey.db
|
|
1275
|
+
.prepare(`
|
|
1122
1276
|
SELECT completed_at FROM consolidation_runs
|
|
1123
1277
|
WHERE status = 'completed'
|
|
1124
1278
|
ORDER BY completed_at DESC
|
|
1125
1279
|
LIMIT 1
|
|
1126
|
-
`)
|
|
1280
|
+
`)
|
|
1281
|
+
.get()?.completed_at ?? 'never';
|
|
1127
1282
|
audrey.close();
|
|
1128
1283
|
}
|
|
1129
1284
|
catch (err) {
|
|
@@ -1145,11 +1300,11 @@ export function formatStatusReport(report) {
|
|
|
1145
1300
|
lines.push(`Data directory: ${report.dataDir}`);
|
|
1146
1301
|
lines.push(`Stored dimensions: ${report.storedDimensions ?? 'unknown'}`);
|
|
1147
1302
|
lines.push(`Memories: ${report.stats.episodic} episodic, ${report.stats.semantic} semantic, ${report.stats.procedural} procedural`);
|
|
1148
|
-
lines.push(`Index sync: ${report.health.vec_episodes}/${report.health.searchable_episodes} episodic, `
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
lines.push(`Health: ${report.health.healthy ? 'healthy' : 'unhealthy'}`
|
|
1152
|
-
|
|
1303
|
+
lines.push(`Index sync: ${report.health.vec_episodes}/${report.health.searchable_episodes} episodic, ` +
|
|
1304
|
+
`${report.health.vec_semantics}/${report.health.searchable_semantics} semantic, ` +
|
|
1305
|
+
`${report.health.vec_procedures}/${report.health.searchable_procedures} procedural`);
|
|
1306
|
+
lines.push(`Health: ${report.health.healthy ? 'healthy' : 'unhealthy'}` +
|
|
1307
|
+
`${report.health.reembed_recommended ? ' (re-embed recommended)' : ''}`);
|
|
1153
1308
|
lines.push(`Dormant: ${report.stats.dormant}`);
|
|
1154
1309
|
lines.push(`Causal links: ${report.stats.causalLinks}`);
|
|
1155
1310
|
lines.push(`Contradictions: ${report.stats.contradictions.open} open, ${report.stats.contradictions.resolved} resolved`);
|
|
@@ -1165,8 +1320,11 @@ export function runStatusCommand({ argv = process.argv, dataDir = resolveDataDir
|
|
|
1165
1320
|
else {
|
|
1166
1321
|
out(formatStatusReport(report));
|
|
1167
1322
|
}
|
|
1168
|
-
const exitCode = report.error
|
|
1169
|
-
|
|
1323
|
+
const exitCode = report.error ||
|
|
1324
|
+
(cliHasFlag('--fail-on-unhealthy', argv) &&
|
|
1325
|
+
report.exists &&
|
|
1326
|
+
report.health &&
|
|
1327
|
+
!report.health.healthy)
|
|
1170
1328
|
? 1
|
|
1171
1329
|
: 0;
|
|
1172
1330
|
return { report, exitCode };
|
|
@@ -1319,23 +1477,30 @@ function toolResult(data, diagnostics) {
|
|
|
1319
1477
|
return result;
|
|
1320
1478
|
}
|
|
1321
1479
|
function toolError(err) {
|
|
1322
|
-
return {
|
|
1480
|
+
return {
|
|
1481
|
+
isError: true,
|
|
1482
|
+
content: [{ type: 'text', text: `Error: ${err.message || String(err)}` }],
|
|
1483
|
+
};
|
|
1323
1484
|
}
|
|
1324
1485
|
function jsonResource(uri, data) {
|
|
1325
1486
|
return {
|
|
1326
|
-
contents: [
|
|
1487
|
+
contents: [
|
|
1488
|
+
{
|
|
1327
1489
|
uri: uri.toString(),
|
|
1328
1490
|
mimeType: 'application/json',
|
|
1329
1491
|
text: JSON.stringify(data, null, 2),
|
|
1330
|
-
}
|
|
1492
|
+
},
|
|
1493
|
+
],
|
|
1331
1494
|
};
|
|
1332
1495
|
}
|
|
1333
1496
|
function promptText(text) {
|
|
1334
1497
|
return {
|
|
1335
|
-
messages: [
|
|
1498
|
+
messages: [
|
|
1499
|
+
{
|
|
1336
1500
|
role: 'user',
|
|
1337
1501
|
content: { type: 'text', text },
|
|
1338
|
-
}
|
|
1502
|
+
},
|
|
1503
|
+
],
|
|
1339
1504
|
};
|
|
1340
1505
|
}
|
|
1341
1506
|
export function registerShutdownHandlers(processRef, audrey, logger = console.error) {
|
|
@@ -1350,8 +1515,8 @@ export function registerShutdownHandlers(processRef, audrey, logger = console.er
|
|
|
1350
1515
|
if (typeof audrey.drainPostEncodeQueue === 'function') {
|
|
1351
1516
|
const drain = await audrey.drainPostEncodeQueue(5000);
|
|
1352
1517
|
if (!drain.drained && drain.pendingIds.length > 0) {
|
|
1353
|
-
logger(`[audrey-mcp] post-encode queue did not drain within 5000ms; `
|
|
1354
|
-
|
|
1518
|
+
logger(`[audrey-mcp] post-encode queue did not drain within 5000ms; ` +
|
|
1519
|
+
`pending ids: ${drain.pendingIds.join(', ')}`);
|
|
1355
1520
|
}
|
|
1356
1521
|
}
|
|
1357
1522
|
audrey.close();
|
|
@@ -1365,9 +1530,15 @@ export function registerShutdownHandlers(processRef, audrey, logger = console.er
|
|
|
1365
1530
|
processRef.exit(exitCode);
|
|
1366
1531
|
}
|
|
1367
1532
|
};
|
|
1368
|
-
processRef.once('SIGINT', () => {
|
|
1369
|
-
|
|
1370
|
-
|
|
1533
|
+
processRef.once('SIGINT', () => {
|
|
1534
|
+
void shutdown('[audrey-mcp] received SIGINT, shutting down');
|
|
1535
|
+
});
|
|
1536
|
+
processRef.once('SIGTERM', () => {
|
|
1537
|
+
void shutdown('[audrey-mcp] received SIGTERM, shutting down');
|
|
1538
|
+
});
|
|
1539
|
+
processRef.once('SIGHUP', () => {
|
|
1540
|
+
void shutdown('[audrey-mcp] received SIGHUP, shutting down');
|
|
1541
|
+
});
|
|
1371
1542
|
processRef.once('uncaughtException', (err) => {
|
|
1372
1543
|
logger('[audrey-mcp] uncaught exception:', err);
|
|
1373
1544
|
void shutdown(undefined, 1);
|
|
@@ -1381,13 +1552,20 @@ export function registerShutdownHandlers(processRef, audrey, logger = console.er
|
|
|
1381
1552
|
});
|
|
1382
1553
|
return (message, exitCode = 0) => shutdown(message, exitCode);
|
|
1383
1554
|
}
|
|
1384
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1385
1555
|
export function registerDreamTool(server, audrey) {
|
|
1386
1556
|
server.tool('memory_dream', {
|
|
1387
1557
|
min_cluster_size: z.number().optional().describe('Minimum episodes per cluster (default 3)'),
|
|
1388
|
-
similarity_threshold: z
|
|
1389
|
-
|
|
1390
|
-
|
|
1558
|
+
similarity_threshold: z
|
|
1559
|
+
.number()
|
|
1560
|
+
.optional()
|
|
1561
|
+
.describe('Similarity threshold for clustering (default 0.85)'),
|
|
1562
|
+
dormant_threshold: z
|
|
1563
|
+
.number()
|
|
1564
|
+
.min(0)
|
|
1565
|
+
.max(1)
|
|
1566
|
+
.optional()
|
|
1567
|
+
.describe('Confidence below which memories go dormant (default 0.1)'),
|
|
1568
|
+
}, async ({ min_cluster_size, similarity_threshold, dormant_threshold, }) => {
|
|
1391
1569
|
try {
|
|
1392
1570
|
const result = await audrey.dream({
|
|
1393
1571
|
minClusterSize: min_cluster_size,
|
|
@@ -1401,7 +1579,6 @@ export function registerDreamTool(server, audrey) {
|
|
|
1401
1579
|
}
|
|
1402
1580
|
});
|
|
1403
1581
|
}
|
|
1404
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1405
1582
|
export function registerHostResources(server, audrey) {
|
|
1406
1583
|
server.registerResource('audrey-status', 'audrey://status', {
|
|
1407
1584
|
title: 'Audrey Status',
|
|
@@ -1448,7 +1625,6 @@ export function registerHostResources(server, audrey) {
|
|
|
1448
1625
|
});
|
|
1449
1626
|
});
|
|
1450
1627
|
}
|
|
1451
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1452
1628
|
export function registerHostPrompts(server) {
|
|
1453
1629
|
server.registerPrompt('audrey-session-briefing', {
|
|
1454
1630
|
title: 'Audrey Session Briefing',
|
|
@@ -1476,13 +1652,18 @@ export function registerHostPrompts(server) {
|
|
|
1476
1652
|
title: 'Audrey Memory Reflection',
|
|
1477
1653
|
description: 'Reflect at the end of a meaningful session and encode durable lessons.',
|
|
1478
1654
|
argsSchema: {
|
|
1479
|
-
summary: z
|
|
1655
|
+
summary: z
|
|
1656
|
+
.string()
|
|
1657
|
+
.optional()
|
|
1658
|
+
.describe('Optional compact summary of the session to reflect on.'),
|
|
1480
1659
|
},
|
|
1481
1660
|
}, ({ summary }) => promptText([
|
|
1482
1661
|
'Call memory_reflect with the important user and assistant turns from this session.',
|
|
1483
1662
|
'Encode only durable preferences, decisions, fixes, failures, and project facts that should affect future work.',
|
|
1484
1663
|
summary ? `Session summary hint: ${summary}` : undefined,
|
|
1485
|
-
]
|
|
1664
|
+
]
|
|
1665
|
+
.filter(Boolean)
|
|
1666
|
+
.join('\n')));
|
|
1486
1667
|
}
|
|
1487
1668
|
async function main() {
|
|
1488
1669
|
const { McpServer } = await import('@modelcontextprotocol/sdk/server/mcp.js');
|
|
@@ -1626,7 +1807,10 @@ async function main() {
|
|
|
1626
1807
|
purge: purge ?? false,
|
|
1627
1808
|
});
|
|
1628
1809
|
if (!result) {
|
|
1629
|
-
return toolResult({
|
|
1810
|
+
return toolResult({
|
|
1811
|
+
forgotten: false,
|
|
1812
|
+
reason: 'No memory found above similarity threshold',
|
|
1813
|
+
});
|
|
1630
1814
|
}
|
|
1631
1815
|
}
|
|
1632
1816
|
return toolResult({ forgotten: true, ...result });
|
|
@@ -1647,7 +1831,12 @@ async function main() {
|
|
|
1647
1831
|
}
|
|
1648
1832
|
});
|
|
1649
1833
|
server.tool('memory_decay', {
|
|
1650
|
-
dormant_threshold: z
|
|
1834
|
+
dormant_threshold: z
|
|
1835
|
+
.number()
|
|
1836
|
+
.min(0)
|
|
1837
|
+
.max(1)
|
|
1838
|
+
.optional()
|
|
1839
|
+
.describe('Confidence below which memories go dormant (default 0.1)'),
|
|
1651
1840
|
}, async ({ dormant_threshold }) => {
|
|
1652
1841
|
try {
|
|
1653
1842
|
return toolResult(audrey.decay({ dormantThreshold: dormant_threshold }));
|
|
@@ -1665,10 +1854,12 @@ async function main() {
|
|
|
1665
1854
|
}
|
|
1666
1855
|
});
|
|
1667
1856
|
server.tool('memory_reflect', {
|
|
1668
|
-
turns: z
|
|
1857
|
+
turns: z
|
|
1858
|
+
.array(z.object({
|
|
1669
1859
|
role: z.string().describe('Message role: user or assistant'),
|
|
1670
1860
|
content: z.string().describe('Message content'),
|
|
1671
|
-
}))
|
|
1861
|
+
}))
|
|
1862
|
+
.describe('Conversation turns to reflect on. Call at end of meaningful conversations to form lasting memories.'),
|
|
1672
1863
|
}, async ({ turns }) => {
|
|
1673
1864
|
try {
|
|
1674
1865
|
return toolResult(await audrey.reflect(turns));
|
|
@@ -1679,8 +1870,14 @@ async function main() {
|
|
|
1679
1870
|
});
|
|
1680
1871
|
registerDreamTool(server, audrey);
|
|
1681
1872
|
server.tool('memory_greeting', {
|
|
1682
|
-
context: z
|
|
1683
|
-
|
|
1873
|
+
context: z
|
|
1874
|
+
.string()
|
|
1875
|
+
.optional()
|
|
1876
|
+
.describe('Optional hint about this session. When provided, Audrey also returns semantically relevant memories.'),
|
|
1877
|
+
scope: z
|
|
1878
|
+
.enum(['agent', 'shared'])
|
|
1879
|
+
.optional()
|
|
1880
|
+
.describe('agent keeps greeting scoped to this server agent identity. shared includes the whole store. Defaults to agent.'),
|
|
1684
1881
|
}, async ({ context, scope }) => {
|
|
1685
1882
|
try {
|
|
1686
1883
|
return toolResult(await audrey.greeting({ context, scope: scope ?? 'agent' }));
|
|
@@ -1690,17 +1887,40 @@ async function main() {
|
|
|
1690
1887
|
}
|
|
1691
1888
|
});
|
|
1692
1889
|
server.tool('memory_observe_tool', {
|
|
1693
|
-
event: z
|
|
1890
|
+
event: z
|
|
1891
|
+
.string()
|
|
1892
|
+
.describe('Hook event name (PreToolUse, PostToolUse, PostToolUseFailure, PreCompact, PostCompact, etc.)'),
|
|
1694
1893
|
tool: z.string().describe('Tool name being observed (Bash, Edit, Write, etc.)'),
|
|
1695
1894
|
session_id: z.string().optional().describe('Session identifier for grouping related events'),
|
|
1696
|
-
input: z
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1895
|
+
input: z
|
|
1896
|
+
.unknown()
|
|
1897
|
+
.optional()
|
|
1898
|
+
.describe('Tool input. Hashed and never stored raw; redacted metadata is only stored when retain_details is true.'),
|
|
1899
|
+
output: z
|
|
1900
|
+
.unknown()
|
|
1901
|
+
.optional()
|
|
1902
|
+
.describe('Tool output. Same redaction and storage policy as input.'),
|
|
1903
|
+
outcome: z
|
|
1904
|
+
.enum(['succeeded', 'failed', 'blocked', 'skipped', 'unknown'])
|
|
1905
|
+
.optional()
|
|
1906
|
+
.describe('Outcome classification'),
|
|
1907
|
+
error_summary: z
|
|
1908
|
+
.string()
|
|
1909
|
+
.optional()
|
|
1910
|
+
.describe('Short error description if the tool failed. Redacted and truncated to 2 KB.'),
|
|
1700
1911
|
cwd: z.string().optional().describe('Working directory at the time of the tool call'),
|
|
1701
|
-
files: z
|
|
1702
|
-
|
|
1703
|
-
|
|
1912
|
+
files: z
|
|
1913
|
+
.array(z.string())
|
|
1914
|
+
.optional()
|
|
1915
|
+
.describe('File paths to fingerprint (size + mtime + content hash)'),
|
|
1916
|
+
metadata: z
|
|
1917
|
+
.record(z.string(), z.unknown())
|
|
1918
|
+
.optional()
|
|
1919
|
+
.describe('Arbitrary structured metadata (redacted before storage)'),
|
|
1920
|
+
retain_details: z
|
|
1921
|
+
.boolean()
|
|
1922
|
+
.optional()
|
|
1923
|
+
.describe('If true, redacted input and output payloads are stored alongside hashes. Defaults to false.'),
|
|
1704
1924
|
}, async ({ event, tool, session_id, input, output, outcome, error_summary, cwd, files, metadata, retain_details, }) => {
|
|
1705
1925
|
try {
|
|
1706
1926
|
const result = audrey.observeTool({
|
|
@@ -1732,7 +1952,13 @@ async function main() {
|
|
|
1732
1952
|
});
|
|
1733
1953
|
server.tool('memory_recent_failures', {
|
|
1734
1954
|
since: z.string().optional().describe('ISO timestamp lower bound (defaults to 7 days ago)'),
|
|
1735
|
-
limit: z
|
|
1955
|
+
limit: z
|
|
1956
|
+
.number()
|
|
1957
|
+
.int()
|
|
1958
|
+
.min(1)
|
|
1959
|
+
.max(200)
|
|
1960
|
+
.optional()
|
|
1961
|
+
.describe('Max rows to return (defaults to 20)'),
|
|
1736
1962
|
}, async ({ since, limit }) => {
|
|
1737
1963
|
try {
|
|
1738
1964
|
return toolResult(audrey.recentFailures({ since, limit }));
|
|
@@ -1743,13 +1969,43 @@ async function main() {
|
|
|
1743
1969
|
});
|
|
1744
1970
|
server.tool('memory_capsule', {
|
|
1745
1971
|
query: z.string().describe('Natural-language query for the turn. Drives what gets surfaced.'),
|
|
1746
|
-
limit: z
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1972
|
+
limit: z
|
|
1973
|
+
.number()
|
|
1974
|
+
.int()
|
|
1975
|
+
.min(1)
|
|
1976
|
+
.max(50)
|
|
1977
|
+
.optional()
|
|
1978
|
+
.describe('Max recall results to consider before categorization.'),
|
|
1979
|
+
budget_chars: z
|
|
1980
|
+
.number()
|
|
1981
|
+
.int()
|
|
1982
|
+
.min(200)
|
|
1983
|
+
.max(32000)
|
|
1984
|
+
.optional()
|
|
1985
|
+
.describe('Token budget in characters (defaults to AUDREY_CONTEXT_BUDGET_CHARS or 4000).'),
|
|
1986
|
+
mode: z
|
|
1987
|
+
.enum(['balanced', 'conservative', 'aggressive'])
|
|
1988
|
+
.optional()
|
|
1989
|
+
.describe('Capsule mode: conservative = fewer, higher-confidence entries; aggressive = broader sweep.'),
|
|
1990
|
+
recent_change_window_hours: z
|
|
1991
|
+
.number()
|
|
1992
|
+
.int()
|
|
1993
|
+
.min(1)
|
|
1994
|
+
.max(720)
|
|
1995
|
+
.optional()
|
|
1996
|
+
.describe('How far back "recent_changes" looks (default 24h).'),
|
|
1997
|
+
include_risks: z
|
|
1998
|
+
.boolean()
|
|
1999
|
+
.optional()
|
|
2000
|
+
.describe('Include recent tool failures as risks (default true).'),
|
|
2001
|
+
include_contradictions: z
|
|
2002
|
+
.boolean()
|
|
2003
|
+
.optional()
|
|
2004
|
+
.describe('Include open contradictions (default true).'),
|
|
2005
|
+
scope: z
|
|
2006
|
+
.enum(['agent', 'shared'])
|
|
2007
|
+
.optional()
|
|
2008
|
+
.describe('agent restricts memory recall to this MCP server agent identity. shared searches the whole store. Defaults to agent.'),
|
|
1753
2009
|
}, async ({ query, limit, budget_chars, mode, recent_change_window_hours, include_risks, include_contradictions, scope, }) => {
|
|
1754
2010
|
try {
|
|
1755
2011
|
const capsule = await audrey.capsule(query, {
|
|
@@ -1860,14 +2116,42 @@ async function main() {
|
|
|
1860
2116
|
}
|
|
1861
2117
|
});
|
|
1862
2118
|
server.tool('memory_promote', {
|
|
1863
|
-
target: z
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
2119
|
+
target: z
|
|
2120
|
+
.enum(['claude-rules'])
|
|
2121
|
+
.optional()
|
|
2122
|
+
.describe('Promotion target. Only claude-rules is implemented in PR 4 v1.'),
|
|
2123
|
+
min_confidence: z
|
|
2124
|
+
.number()
|
|
2125
|
+
.min(0)
|
|
2126
|
+
.max(1)
|
|
2127
|
+
.optional()
|
|
2128
|
+
.describe('Minimum memory confidence for promotion (default 0.7 for procedural, 0.8 for semantic).'),
|
|
2129
|
+
min_evidence: z
|
|
2130
|
+
.number()
|
|
2131
|
+
.int()
|
|
2132
|
+
.min(1)
|
|
2133
|
+
.optional()
|
|
2134
|
+
.describe('Minimum supporting episode count (default 2).'),
|
|
2135
|
+
limit: z
|
|
2136
|
+
.number()
|
|
2137
|
+
.int()
|
|
2138
|
+
.min(1)
|
|
2139
|
+
.max(50)
|
|
2140
|
+
.optional()
|
|
2141
|
+
.describe('Max candidates to return/apply (default 20).'),
|
|
2142
|
+
dry_run: z
|
|
2143
|
+
.boolean()
|
|
2144
|
+
.optional()
|
|
2145
|
+
.describe('If true (default), return candidates without writing. Pair with yes=true to actually write.'),
|
|
2146
|
+
yes: z
|
|
2147
|
+
.boolean()
|
|
2148
|
+
.optional()
|
|
2149
|
+
.describe('Confirm write. Without this or dry_run=false the command stays in dry-run mode.'),
|
|
2150
|
+
project_dir: z
|
|
2151
|
+
.string()
|
|
2152
|
+
.optional()
|
|
2153
|
+
.describe('Absolute path to the project root where .claude/rules/ should be created. Defaults to process.cwd().'),
|
|
2154
|
+
}, async ({ target, min_confidence, min_evidence, limit, dry_run, yes, project_dir }) => {
|
|
1871
2155
|
try {
|
|
1872
2156
|
const result = await audrey.promote({
|
|
1873
2157
|
target,
|
|
@@ -1890,7 +2174,8 @@ async function main() {
|
|
|
1890
2174
|
console.error('[audrey-mcp] connected via stdio');
|
|
1891
2175
|
}
|
|
1892
2176
|
if (!isEmbeddingWarmupDisabled(process.env)) {
|
|
1893
|
-
void audrey
|
|
2177
|
+
void audrey
|
|
2178
|
+
.startEmbeddingWarmup()
|
|
1894
2179
|
.then(() => {
|
|
1895
2180
|
if (process.env.AUDREY_DEBUG === '1') {
|
|
1896
2181
|
const status = audrey.memoryStatus();
|
|
@@ -1925,7 +2210,10 @@ function parseObserveToolArgs(argv) {
|
|
|
1925
2210
|
else if (token === '--files') {
|
|
1926
2211
|
const list = next();
|
|
1927
2212
|
if (list)
|
|
1928
|
-
out.files = list
|
|
2213
|
+
out.files = list
|
|
2214
|
+
.split(',')
|
|
2215
|
+
.map(s => s.trim())
|
|
2216
|
+
.filter(Boolean);
|
|
1929
2217
|
}
|
|
1930
2218
|
else if (token === '--input-json')
|
|
1931
2219
|
out.inputJson = next();
|
|
@@ -1980,13 +2268,11 @@ async function observeToolCli() {
|
|
|
1980
2268
|
};
|
|
1981
2269
|
const inputPayload = args.inputJson !== undefined
|
|
1982
2270
|
? parseMaybeJson(args.inputJson)
|
|
1983
|
-
: stdinPayload?.tool_input ?? stdinPayload?.input;
|
|
2271
|
+
: (stdinPayload?.tool_input ?? stdinPayload?.input);
|
|
1984
2272
|
const outputPayload = args.outputJson !== undefined
|
|
1985
2273
|
? parseMaybeJson(args.outputJson)
|
|
1986
|
-
: stdinPayload?.tool_response ?? stdinPayload?.tool_output ?? stdinPayload?.output;
|
|
1987
|
-
const metadataPayload = args.metadataJson !== undefined
|
|
1988
|
-
? parseMaybeJson(args.metadataJson)
|
|
1989
|
-
: stdinPayload?.metadata;
|
|
2274
|
+
: (stdinPayload?.tool_response ?? stdinPayload?.tool_output ?? stdinPayload?.output);
|
|
2275
|
+
const metadataPayload = args.metadataJson !== undefined ? parseMaybeJson(args.metadataJson) : stdinPayload?.metadata;
|
|
1990
2276
|
const sessionId = args.sessionId ?? stdinPayload?.session_id;
|
|
1991
2277
|
const cwd = args.cwd ?? stdinPayload?.cwd;
|
|
1992
2278
|
// Detect failure from Claude Code hook payload shape: tool_response often
|
|
@@ -2124,7 +2410,7 @@ function guardDisplayDecision(result) {
|
|
|
2124
2410
|
return 'allow';
|
|
2125
2411
|
}
|
|
2126
2412
|
function summarizeToolInput(payload, tool) {
|
|
2127
|
-
const input =
|
|
2413
|
+
const input = payload.tool_input && typeof payload.tool_input === 'object'
|
|
2128
2414
|
? payload.tool_input
|
|
2129
2415
|
: {};
|
|
2130
2416
|
const command = typeof input.command === 'string' ? input.command : undefined;
|
|
@@ -2139,9 +2425,7 @@ function summarizeToolInput(payload, tool) {
|
|
|
2139
2425
|
return { action: `${tool}: ${description}`, files };
|
|
2140
2426
|
const compactInput = JSON.stringify(input);
|
|
2141
2427
|
return {
|
|
2142
|
-
action: compactInput && compactInput !== '{}'
|
|
2143
|
-
? `${tool} ${compactInput}`
|
|
2144
|
-
: `Use ${tool}`,
|
|
2428
|
+
action: compactInput && compactInput !== '{}' ? `${tool} ${compactInput}` : `Use ${tool}`,
|
|
2145
2429
|
files,
|
|
2146
2430
|
};
|
|
2147
2431
|
}
|
|
@@ -2160,7 +2444,9 @@ function formatHookReason(result) {
|
|
|
2160
2444
|
result.summary,
|
|
2161
2445
|
recommendations.length > 0 ? `Recommended: ${recommendations.join(' ')}` : '',
|
|
2162
2446
|
result.evidence_ids.length > 0 ? `Evidence: ${result.evidence_ids.slice(0, 5).join(', ')}` : '',
|
|
2163
|
-
]
|
|
2447
|
+
]
|
|
2448
|
+
.filter(Boolean)
|
|
2449
|
+
.join('\n');
|
|
2164
2450
|
}
|
|
2165
2451
|
function formatPreToolUseHookOutput(result, failOnWarn) {
|
|
2166
2452
|
const decision = guardDisplayDecision(result);
|
|
@@ -2253,7 +2539,11 @@ async function guardCli() {
|
|
|
2253
2539
|
tool: hookTool ?? args.tool,
|
|
2254
2540
|
sessionId: args.sessionId ?? hookSessionId,
|
|
2255
2541
|
cwd: args.cwd ?? hookCwd ?? process.cwd(),
|
|
2256
|
-
files: args.files.length > 0
|
|
2542
|
+
files: args.files.length > 0
|
|
2543
|
+
? args.files
|
|
2544
|
+
: hookSummary?.files?.length
|
|
2545
|
+
? hookSummary.files
|
|
2546
|
+
: undefined,
|
|
2257
2547
|
strict: args.strict || args.failOnWarn || args.hook,
|
|
2258
2548
|
recordEvent: true,
|
|
2259
2549
|
includeCapsule: args.includeCapsule || args.explain,
|
|
@@ -2268,7 +2558,9 @@ async function guardCli() {
|
|
|
2268
2558
|
console.log(formatGuardDecision(result, { explain: args.explain }));
|
|
2269
2559
|
}
|
|
2270
2560
|
const display = guardDisplayDecision(result);
|
|
2271
|
-
if (!args.hook &&
|
|
2561
|
+
if (!args.hook &&
|
|
2562
|
+
(display === 'block' || (args.failOnWarn && display === 'warn')) &&
|
|
2563
|
+
!args.override) {
|
|
2272
2564
|
process.exitCode = 2;
|
|
2273
2565
|
}
|
|
2274
2566
|
}
|
|
@@ -2314,9 +2606,9 @@ async function readOptionalJsonFromStdin(command) {
|
|
|
2314
2606
|
}
|
|
2315
2607
|
}
|
|
2316
2608
|
function inferGuardAfterOutcome(stdinPayload) {
|
|
2317
|
-
const response = stdinPayload?.tool_response
|
|
2318
|
-
|
|
2319
|
-
|
|
2609
|
+
const response = stdinPayload?.tool_response ??
|
|
2610
|
+
stdinPayload?.tool_output ??
|
|
2611
|
+
stdinPayload?.output;
|
|
2320
2612
|
const success = response?.success;
|
|
2321
2613
|
if (typeof success === 'boolean')
|
|
2322
2614
|
return success ? 'succeeded' : 'failed';
|
|
@@ -2433,8 +2725,8 @@ async function promoteCli() {
|
|
|
2433
2725
|
const snippet = c.content.length > 120 ? c.content.slice(0, 117) + '...' : c.content;
|
|
2434
2726
|
console.log(` memory: ${snippet}`);
|
|
2435
2727
|
console.log(` why: ${c.reason}`);
|
|
2436
|
-
console.log(` confidence=${(c.confidence * 100).toFixed(1)}% `
|
|
2437
|
-
|
|
2728
|
+
console.log(` confidence=${(c.confidence * 100).toFixed(1)}% ` +
|
|
2729
|
+
`evidence=${c.evidence_count} prevented_failures=${c.failure_prevented}`);
|
|
2438
2730
|
}
|
|
2439
2731
|
if (result.dry_run) {
|
|
2440
2732
|
console.log('');
|
|
@@ -2454,11 +2746,26 @@ function canonicalEntryPath(path) {
|
|
|
2454
2746
|
return resolved.toLowerCase();
|
|
2455
2747
|
}
|
|
2456
2748
|
}
|
|
2457
|
-
const isDirectRun = Boolean(process.argv[1])
|
|
2458
|
-
|
|
2749
|
+
const isDirectRun = Boolean(process.argv[1]) &&
|
|
2750
|
+
canonicalEntryPath(process.argv[1]) === canonicalEntryPath(fileURLToPath(import.meta.url));
|
|
2459
2751
|
const KNOWN_SUBCOMMANDS = [
|
|
2460
|
-
'install',
|
|
2461
|
-
'
|
|
2752
|
+
'install',
|
|
2753
|
+
'uninstall',
|
|
2754
|
+
'mcp-config',
|
|
2755
|
+
'hook-config',
|
|
2756
|
+
'demo',
|
|
2757
|
+
'reembed',
|
|
2758
|
+
'dream',
|
|
2759
|
+
'greeting',
|
|
2760
|
+
'reflect',
|
|
2761
|
+
'serve',
|
|
2762
|
+
'status',
|
|
2763
|
+
'doctor',
|
|
2764
|
+
'observe-tool',
|
|
2765
|
+
'guard',
|
|
2766
|
+
'guard-after',
|
|
2767
|
+
'promote',
|
|
2768
|
+
'impact',
|
|
2462
2769
|
];
|
|
2463
2770
|
function printHelp() {
|
|
2464
2771
|
process.stdout.write(`audrey ${VERSION} — local-first memory runtime for AI agents
|