velixar-mcp-server 0.2.4 → 1.2.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/README.md +120 -64
- package/dist/api.d.ts +64 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +405 -0
- package/dist/api.js.map +1 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +52 -0
- package/dist/errors.js.map +1 -0
- package/dist/justify.d.ts +9 -0
- package/dist/justify.d.ts.map +1 -0
- package/dist/justify.js +114 -0
- package/dist/justify.js.map +1 -0
- package/dist/prompts.d.ts +88 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +693 -0
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +25 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +278 -0
- package/dist/resources.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +392 -0
- package/dist/server.js.map +1 -0
- package/dist/simulation/personas.d.ts +41 -0
- package/dist/simulation/personas.d.ts.map +1 -0
- package/dist/simulation/personas.js +173 -0
- package/dist/simulation/personas.js.map +1 -0
- package/dist/simulation/report.d.ts +28 -0
- package/dist/simulation/report.d.ts.map +1 -0
- package/dist/simulation/report.js +105 -0
- package/dist/simulation/report.js.map +1 -0
- package/dist/simulation/runner.d.ts +63 -0
- package/dist/simulation/runner.d.ts.map +1 -0
- package/dist/simulation/runner.js +167 -0
- package/dist/simulation/runner.js.map +1 -0
- package/dist/temporal_merge.d.ts +70 -0
- package/dist/temporal_merge.d.ts.map +1 -0
- package/dist/temporal_merge.js +258 -0
- package/dist/temporal_merge.js.map +1 -0
- package/dist/tools/clairvoyance.d.ts +9 -0
- package/dist/tools/clairvoyance.d.ts.map +1 -0
- package/dist/tools/clairvoyance.js +321 -0
- package/dist/tools/clairvoyance.js.map +1 -0
- package/dist/tools/cognitive.d.ts +10 -0
- package/dist/tools/cognitive.d.ts.map +1 -0
- package/dist/tools/cognitive.js +462 -0
- package/dist/tools/cognitive.js.map +1 -0
- package/dist/tools/construction.d.ts +9 -0
- package/dist/tools/construction.d.ts.map +1 -0
- package/dist/tools/construction.js +350 -0
- package/dist/tools/construction.js.map +1 -0
- package/dist/tools/graph.d.ts +14 -0
- package/dist/tools/graph.d.ts.map +1 -0
- package/dist/tools/graph.js +263 -0
- package/dist/tools/graph.js.map +1 -0
- package/dist/tools/graph_sanitizer.d.ts +24 -0
- package/dist/tools/graph_sanitizer.d.ts.map +1 -0
- package/dist/tools/graph_sanitizer.js +79 -0
- package/dist/tools/graph_sanitizer.js.map +1 -0
- package/dist/tools/lifecycle.d.ts +9 -0
- package/dist/tools/lifecycle.d.ts.map +1 -0
- package/dist/tools/lifecycle.js +1091 -0
- package/dist/tools/lifecycle.js.map +1 -0
- package/dist/tools/livedata.d.ts +9 -0
- package/dist/tools/livedata.d.ts.map +1 -0
- package/dist/tools/livedata.js +222 -0
- package/dist/tools/livedata.js.map +1 -0
- package/dist/tools/memory.d.ts +10 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +275 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/recall.d.ts +9 -0
- package/dist/tools/recall.d.ts.map +1 -0
- package/dist/tools/recall.js +206 -0
- package/dist/tools/recall.js.map +1 -0
- package/dist/tools/retrieval.d.ts +9 -0
- package/dist/tools/retrieval.d.ts.map +1 -0
- package/dist/tools/retrieval.js +338 -0
- package/dist/tools/retrieval.js.map +1 -0
- package/dist/tools/system.d.ts +12 -0
- package/dist/tools/system.d.ts.map +1 -0
- package/dist/tools/system.js +228 -0
- package/dist/tools/system.js.map +1 -0
- package/dist/types.d.ts +234 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/validate.d.ts +79 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +174 -0
- package/dist/validate.js.map +1 -0
- package/dist/validate_retrieval.d.ts +33 -0
- package/dist/validate_retrieval.d.ts.map +1 -0
- package/dist/validate_retrieval.js +97 -0
- package/dist/validate_retrieval.js.map +1 -0
- package/package.json +22 -6
- package/server.json +2 -2
- package/.github/workflows/ci.yml +0 -18
- package/.mcpregistry_github_token +0 -1
- package/.mcpregistry_registry_token +0 -1
- package/src/index.js +0 -262
- package/tests/server.test.js +0 -193
package/dist/api.js
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
// ── Velixar MCP Server — API Client ──
|
|
2
|
+
// Typed HTTP client with workspace header injection, retry, timeout, caching.
|
|
3
|
+
import { execSync } from 'node:child_process';
|
|
4
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
// ── Workspace Resolution ──
|
|
7
|
+
function resolveWorkspace() {
|
|
8
|
+
// Priority 1: explicit env var
|
|
9
|
+
const envWs = process.env.VELIXAR_WORKSPACE_ID;
|
|
10
|
+
if (envWs)
|
|
11
|
+
return { id: envWs, source: 'env' };
|
|
12
|
+
// Priority 2: .velixar.json config
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const configPath = join(cwd, '.velixar.json');
|
|
15
|
+
if (existsSync(configPath)) {
|
|
16
|
+
try {
|
|
17
|
+
const cfg = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
18
|
+
if (cfg.workspace_id)
|
|
19
|
+
return { id: cfg.workspace_id, source: 'config' };
|
|
20
|
+
}
|
|
21
|
+
catch { /* ignore parse errors */ }
|
|
22
|
+
}
|
|
23
|
+
// Priority 3: git root directory name
|
|
24
|
+
try {
|
|
25
|
+
const gitRoot = execSync('git rev-parse --show-toplevel', {
|
|
26
|
+
encoding: 'utf-8',
|
|
27
|
+
timeout: 2000,
|
|
28
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
29
|
+
}).trim();
|
|
30
|
+
const dirName = gitRoot.split('/').pop();
|
|
31
|
+
if (dirName)
|
|
32
|
+
return { id: dirName, source: 'git' };
|
|
33
|
+
}
|
|
34
|
+
catch { /* not a git repo */ }
|
|
35
|
+
// No workspace — will be display-only; backend enforces via API key
|
|
36
|
+
return { id: '', source: 'none' };
|
|
37
|
+
}
|
|
38
|
+
// ── Workspace Cross-Validation ──
|
|
39
|
+
let clientRoots = [];
|
|
40
|
+
let lastSeenWorkspaceId = null; // H4: Track workspace changes mid-session
|
|
41
|
+
export function setClientRoots(roots) {
|
|
42
|
+
clientRoots = roots.map(r => {
|
|
43
|
+
// Extract directory name from file:// URI
|
|
44
|
+
try {
|
|
45
|
+
const path = r.uri.replace('file://', '');
|
|
46
|
+
return path.split('/').pop() || path;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return r.name || r.uri;
|
|
50
|
+
}
|
|
51
|
+
}).filter(Boolean);
|
|
52
|
+
}
|
|
53
|
+
export function validateWorkspace(config) {
|
|
54
|
+
if (!config.workspaceId || clientRoots.length === 0)
|
|
55
|
+
return null;
|
|
56
|
+
// H4: Detect workspace change mid-session
|
|
57
|
+
if (lastSeenWorkspaceId && lastSeenWorkspaceId !== config.workspaceId) {
|
|
58
|
+
const warning = `Workspace changed mid-session: "${lastSeenWorkspaceId}" → "${config.workspaceId}". Memories from this point go to the new workspace.`;
|
|
59
|
+
lastSeenWorkspaceId = config.workspaceId;
|
|
60
|
+
return warning;
|
|
61
|
+
}
|
|
62
|
+
lastSeenWorkspaceId = config.workspaceId;
|
|
63
|
+
// If client provided roots and none match our workspace, warn
|
|
64
|
+
const match = clientRoots.some(root => root === config.workspaceId || root.includes(config.workspaceId) || config.workspaceId.includes(root));
|
|
65
|
+
if (!match) {
|
|
66
|
+
return `Workspace mismatch: resolved "${config.workspaceId}" (from ${config.workspaceSource}) but host roots are [${clientRoots.join(', ')}]. Memories may be stored in the wrong workspace.`;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
// ── Config ──
|
|
71
|
+
export function loadConfig() {
|
|
72
|
+
const apiKey = process.env.VELIXAR_API_KEY;
|
|
73
|
+
if (!apiKey) {
|
|
74
|
+
console.error('VELIXAR_API_KEY environment variable required');
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
const ws = resolveWorkspace();
|
|
78
|
+
// H5: Stale env var detection — warn if VELIXAR_WORKSPACE_ID doesn't match git root
|
|
79
|
+
if (ws.source === 'env') {
|
|
80
|
+
try {
|
|
81
|
+
const gitRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf-8', timeout: 2000, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
82
|
+
const gitDir = gitRoot.split('/').pop();
|
|
83
|
+
if (gitDir && gitDir !== ws.id && !ws.id.includes(gitDir)) {
|
|
84
|
+
log('warn', 'stale_workspace_env', { env_workspace: ws.id, git_root: gitDir, hint: 'VELIXAR_WORKSPACE_ID may be stale — it does not match the current git root' });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch { /* not a git repo — can't validate */ }
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
apiKey,
|
|
91
|
+
apiBase: process.env.VELIXAR_API_URL || 'https://api.velixarai.com',
|
|
92
|
+
userId: process.env.VELIXAR_USER_ID || 'mcp-user',
|
|
93
|
+
workspaceId: ws.id,
|
|
94
|
+
workspaceSource: ws.source,
|
|
95
|
+
timeoutMs: 30_000,
|
|
96
|
+
debug: process.env.VELIXAR_DEBUG === 'true',
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const LOG_JSON = process.env.VELIXAR_LOG_FORMAT === 'json';
|
|
100
|
+
export function log(level, msg, fields) {
|
|
101
|
+
if (LOG_JSON) {
|
|
102
|
+
console.error(JSON.stringify({ ts: new Date().toISOString(), level, msg, service: 'velixar-mcp', ...fields }));
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
const extra = fields ? ` ${JSON.stringify(fields)}` : '';
|
|
106
|
+
console.error(`[velixar] ${level}: ${msg}${extra}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const cache = new Map();
|
|
110
|
+
const CACHE_TTL_MS = 60_000; // 1 minute
|
|
111
|
+
// H16: Rate limit tracking
|
|
112
|
+
let _rateLimitRemaining = -1; // -1 = unknown
|
|
113
|
+
let _rateLimitTotal = -1;
|
|
114
|
+
export function getRateLimitInfo() { return { remaining: _rateLimitRemaining, total: _rateLimitTotal }; }
|
|
115
|
+
function getCached(key) {
|
|
116
|
+
const entry = cache.get(key);
|
|
117
|
+
if (!entry)
|
|
118
|
+
return undefined;
|
|
119
|
+
if (Date.now() - entry.timestamp > CACHE_TTL_MS) {
|
|
120
|
+
cache.delete(key);
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
return entry;
|
|
124
|
+
}
|
|
125
|
+
function setCache(key, data) {
|
|
126
|
+
cache.set(key, { data, timestamp: Date.now() });
|
|
127
|
+
}
|
|
128
|
+
// ── Timing Tracking ──
|
|
129
|
+
const timings = [];
|
|
130
|
+
const MAX_TIMINGS = 50;
|
|
131
|
+
export function getTimings() {
|
|
132
|
+
return timings.slice(-20);
|
|
133
|
+
}
|
|
134
|
+
function recordTiming(endpoint, duration_ms, cached) {
|
|
135
|
+
timings.push({ endpoint, duration_ms, timestamp: Date.now(), cached });
|
|
136
|
+
if (timings.length > MAX_TIMINGS)
|
|
137
|
+
timings.splice(0, timings.length - MAX_TIMINGS);
|
|
138
|
+
}
|
|
139
|
+
// ── Retry Stats ──
|
|
140
|
+
let retryCount = 0;
|
|
141
|
+
let fallbackCount = 0;
|
|
142
|
+
export function getRetryStats() {
|
|
143
|
+
return { retryCount, fallbackCount };
|
|
144
|
+
}
|
|
145
|
+
// ── Circuit Breaker ──
|
|
146
|
+
// M7: Adaptive — exponential backoff for recovery timeout
|
|
147
|
+
// M8: Cold-start aware — single timeout followed by success doesn't open circuit
|
|
148
|
+
const CIRCUIT_THRESHOLD = 5; // failures before opening
|
|
149
|
+
const CIRCUIT_INITIAL_RESET_MS = 5_000; // M7: start at 5s, increase on repeated failures
|
|
150
|
+
let circuitFailures = 0;
|
|
151
|
+
let circuitOpenedAt = 0;
|
|
152
|
+
let circuitResetMs = CIRCUIT_INITIAL_RESET_MS;
|
|
153
|
+
let consecutiveOpens = 0; // M7: track repeated circuit opens
|
|
154
|
+
function isCircuitOpen() {
|
|
155
|
+
if (circuitFailures < CIRCUIT_THRESHOLD)
|
|
156
|
+
return false;
|
|
157
|
+
if (Date.now() - circuitOpenedAt > circuitResetMs) {
|
|
158
|
+
// Half-open: allow one attempt
|
|
159
|
+
circuitFailures = CIRCUIT_THRESHOLD - 1;
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
function recordCircuitSuccess() {
|
|
165
|
+
// M8: If we had exactly threshold failures and now succeed, likely cold start
|
|
166
|
+
const wasColdStart = circuitFailures === CIRCUIT_THRESHOLD - 1;
|
|
167
|
+
circuitFailures = 0;
|
|
168
|
+
// M7: Decrease reset timeout on success (min 5s)
|
|
169
|
+
if (consecutiveOpens > 0) {
|
|
170
|
+
consecutiveOpens = Math.max(0, consecutiveOpens - 1);
|
|
171
|
+
circuitResetMs = Math.max(CIRCUIT_INITIAL_RESET_MS, CIRCUIT_INITIAL_RESET_MS * Math.pow(2, consecutiveOpens));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function recordCircuitFailure() {
|
|
175
|
+
circuitFailures++;
|
|
176
|
+
if (circuitFailures >= CIRCUIT_THRESHOLD) {
|
|
177
|
+
circuitOpenedAt = Date.now();
|
|
178
|
+
consecutiveOpens++;
|
|
179
|
+
// M7: Exponential backoff on repeated opens (max 60s)
|
|
180
|
+
circuitResetMs = Math.min(60_000, CIRCUIT_INITIAL_RESET_MS * Math.pow(2, consecutiveOpens - 1));
|
|
181
|
+
log('error', 'circuit_breaker_open', { failures: circuitFailures, reset_ms: circuitResetMs, consecutive_opens: consecutiveOpens });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
export function getCircuitState() {
|
|
185
|
+
return {
|
|
186
|
+
failures: circuitFailures,
|
|
187
|
+
open: isCircuitOpen(),
|
|
188
|
+
threshold: CIRCUIT_THRESHOLD,
|
|
189
|
+
reset_ms: circuitResetMs,
|
|
190
|
+
consecutive_opens: consecutiveOpens,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// ── API Request ──
|
|
194
|
+
export class ApiClient {
|
|
195
|
+
config;
|
|
196
|
+
constructor(config) {
|
|
197
|
+
this.config = config;
|
|
198
|
+
}
|
|
199
|
+
async request(path, options = {}) {
|
|
200
|
+
const { cacheable, ...fetchOptions } = options;
|
|
201
|
+
const cacheKey = `${path}:${JSON.stringify(fetchOptions.body || '')}`;
|
|
202
|
+
// Check cache for GET-like requests
|
|
203
|
+
if (cacheable) {
|
|
204
|
+
const cached = getCached(cacheKey);
|
|
205
|
+
if (cached) {
|
|
206
|
+
recordTiming(path, 0, true);
|
|
207
|
+
return cached.data;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (!path.startsWith('/v1/'))
|
|
211
|
+
path = `/v1${path}`; // live API is /v1-prefixed; server router normalizes identically
|
|
212
|
+
const url = `${this.config.apiBase}${path}`;
|
|
213
|
+
const start = Date.now();
|
|
214
|
+
let lastError = null;
|
|
215
|
+
// Circuit breaker check
|
|
216
|
+
if (isCircuitOpen()) {
|
|
217
|
+
// Try cache first when circuit is open
|
|
218
|
+
if (cacheable) {
|
|
219
|
+
const staleEntry = cache.get(cacheKey);
|
|
220
|
+
if (staleEntry) {
|
|
221
|
+
fallbackCount++;
|
|
222
|
+
recordTiming(path, 0, true);
|
|
223
|
+
return staleEntry.data;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
throw new Error('Circuit breaker open — backend unreachable');
|
|
227
|
+
}
|
|
228
|
+
// Retry with exponential backoff (max 3 attempts)
|
|
229
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
230
|
+
if (attempt > 0) {
|
|
231
|
+
retryCount++;
|
|
232
|
+
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 4000);
|
|
233
|
+
await new Promise(r => setTimeout(r, delay));
|
|
234
|
+
}
|
|
235
|
+
const controller = new AbortController();
|
|
236
|
+
const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);
|
|
237
|
+
try {
|
|
238
|
+
const res = await fetch(url, {
|
|
239
|
+
...fetchOptions,
|
|
240
|
+
signal: controller.signal,
|
|
241
|
+
headers: {
|
|
242
|
+
authorization: `Bearer ${this.config.apiKey}`,
|
|
243
|
+
'Content-Type': 'application/json',
|
|
244
|
+
...(fetchOptions.headers || {}),
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
if (!res.ok) {
|
|
248
|
+
const body = await res.text().catch(() => '');
|
|
249
|
+
const err = new Error(`API ${res.status}: ${body.slice(0, 200)}`);
|
|
250
|
+
// Don't retry 4xx (client errors)
|
|
251
|
+
if (res.status >= 400 && res.status < 500)
|
|
252
|
+
throw err;
|
|
253
|
+
lastError = err;
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
const data = await res.json();
|
|
257
|
+
const duration = Date.now() - start;
|
|
258
|
+
recordTiming(path, duration, false);
|
|
259
|
+
// H16: Track rate limit headers for budget awareness
|
|
260
|
+
const remaining = res.headers.get('x-ratelimit-remaining');
|
|
261
|
+
const limit = res.headers.get('x-ratelimit-limit');
|
|
262
|
+
if (remaining !== null) {
|
|
263
|
+
_rateLimitRemaining = parseInt(remaining, 10);
|
|
264
|
+
_rateLimitTotal = limit ? parseInt(limit, 10) : _rateLimitTotal;
|
|
265
|
+
}
|
|
266
|
+
if (this.config.debug) {
|
|
267
|
+
log('debug', 'api_call', { path, duration_ms: duration });
|
|
268
|
+
}
|
|
269
|
+
// M10/M29: Always log timing at info level for diagnostics
|
|
270
|
+
log('info', 'api_timing', { path, duration_ms: duration, cached: false });
|
|
271
|
+
// Cache successful reads
|
|
272
|
+
if (cacheable)
|
|
273
|
+
setCache(cacheKey, data);
|
|
274
|
+
recordCircuitSuccess();
|
|
275
|
+
return data;
|
|
276
|
+
}
|
|
277
|
+
catch (e) {
|
|
278
|
+
const err = e;
|
|
279
|
+
if (err.name === 'AbortError') {
|
|
280
|
+
lastError = new Error(`API timeout after ${this.config.timeoutMs}ms`);
|
|
281
|
+
}
|
|
282
|
+
else if (err.message.startsWith('API 4')) {
|
|
283
|
+
throw err; // Don't retry client errors
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
lastError = err;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
finally {
|
|
290
|
+
clearTimeout(timer);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// All retries exhausted — record circuit failure
|
|
294
|
+
recordCircuitFailure();
|
|
295
|
+
// Try cache fallback
|
|
296
|
+
if (cacheable) {
|
|
297
|
+
// Check even expired cache entries
|
|
298
|
+
const staleEntry = cache.get(cacheKey);
|
|
299
|
+
if (staleEntry) {
|
|
300
|
+
fallbackCount++;
|
|
301
|
+
recordTiming(path, 0, true);
|
|
302
|
+
if (this.config.debug) {
|
|
303
|
+
log('warn', 'cache_fallback', { path });
|
|
304
|
+
}
|
|
305
|
+
return staleEntry.data;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
throw lastError || new Error('API request failed');
|
|
309
|
+
}
|
|
310
|
+
// ── Convenience Methods ──
|
|
311
|
+
async get(path, cacheable = false) {
|
|
312
|
+
return this.request(path, { method: 'GET', cacheable });
|
|
313
|
+
}
|
|
314
|
+
async post(path, body) {
|
|
315
|
+
return this.request(path, {
|
|
316
|
+
method: 'POST',
|
|
317
|
+
body: JSON.stringify(body),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
async patch(path, body) {
|
|
321
|
+
return this.request(path, {
|
|
322
|
+
method: 'PATCH',
|
|
323
|
+
body: JSON.stringify(body),
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
async delete(path) {
|
|
327
|
+
return this.request(path, { method: 'DELETE' });
|
|
328
|
+
}
|
|
329
|
+
// ── Validated Variants ──
|
|
330
|
+
// Force a runtime validator on every response. Prefer these in new code.
|
|
331
|
+
// The raw cast in `request<T>` is the silent-data-loss class — avoid it.
|
|
332
|
+
async requestValidated(path, options, validate) {
|
|
333
|
+
const raw = await this.request(path, options);
|
|
334
|
+
return validate(raw, path);
|
|
335
|
+
}
|
|
336
|
+
async getValidated(path, validate, cacheable = false) {
|
|
337
|
+
return this.requestValidated(path, { method: 'GET', cacheable }, validate);
|
|
338
|
+
}
|
|
339
|
+
async postValidated(path, body, validate) {
|
|
340
|
+
return this.requestValidated(path, { method: 'POST', body: JSON.stringify(body) }, validate);
|
|
341
|
+
}
|
|
342
|
+
async patchValidated(path, body, validate) {
|
|
343
|
+
return this.requestValidated(path, { method: 'PATCH', body: JSON.stringify(body) }, validate);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function inferMemoryType(raw) {
|
|
347
|
+
// Tier 0 (pinned) and tier 2 (semantic) → semantic; tier 1 (session) → episodic
|
|
348
|
+
return raw.tier === 1 ? 'episodic' : 'semantic';
|
|
349
|
+
}
|
|
350
|
+
function inferSourceType(raw) {
|
|
351
|
+
if (raw.type === 'distill')
|
|
352
|
+
return 'distill';
|
|
353
|
+
if (raw.type === 'inferred')
|
|
354
|
+
return 'inferred';
|
|
355
|
+
return 'user';
|
|
356
|
+
}
|
|
357
|
+
export function normalizeMemory(raw) {
|
|
358
|
+
return {
|
|
359
|
+
id: raw.id,
|
|
360
|
+
workspace_id: '', // filled by caller
|
|
361
|
+
content: raw.content,
|
|
362
|
+
tags: raw.tags || [],
|
|
363
|
+
memory_type: inferMemoryType(raw),
|
|
364
|
+
source_type: inferSourceType(raw),
|
|
365
|
+
author: { type: 'user' },
|
|
366
|
+
relevance: raw.score,
|
|
367
|
+
confidence: raw.salience,
|
|
368
|
+
provenance: {
|
|
369
|
+
created_at: raw.created_at || '',
|
|
370
|
+
updated_at: raw.updated_at || raw.created_at || '',
|
|
371
|
+
last_touched: raw.created_at || '',
|
|
372
|
+
derived_from: raw.previous_memory_id ? [raw.previous_memory_id] : undefined,
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
export function makeMeta(config, overrides = {}) {
|
|
377
|
+
const meta = {
|
|
378
|
+
workspace_id: config.workspaceId,
|
|
379
|
+
confidence: 1,
|
|
380
|
+
staleness: 'fresh',
|
|
381
|
+
contradictions_present: false,
|
|
382
|
+
data_absent: false,
|
|
383
|
+
partial_context: false,
|
|
384
|
+
request_ms: 0,
|
|
385
|
+
...overrides,
|
|
386
|
+
// H8: If data_absent, require absence_reason
|
|
387
|
+
...(overrides.data_absent && !overrides.absence_reason ? { absence_reason: 'no_data' } : {}),
|
|
388
|
+
};
|
|
389
|
+
// H30: Early-exit signal — sufficient when data present, confident, no contradictions
|
|
390
|
+
if (meta.sufficient_answer === undefined) {
|
|
391
|
+
meta.sufficient_answer = !meta.data_absent && !meta.partial_context && !meta.contradictions_present && meta.confidence >= 0.7;
|
|
392
|
+
}
|
|
393
|
+
return meta;
|
|
394
|
+
}
|
|
395
|
+
export function wrapResponse(data, config, overrides = {}) {
|
|
396
|
+
return { status: overrides.partial_context ? 'partial' : 'ok', data, meta: makeMeta(config, overrides) };
|
|
397
|
+
}
|
|
398
|
+
// ── Error Helpers ──
|
|
399
|
+
export function makeError(code, message, retryable = false) {
|
|
400
|
+
return { status: 'error', error: { code, message, retryable } };
|
|
401
|
+
}
|
|
402
|
+
export function isApiError(e) {
|
|
403
|
+
return e instanceof Error;
|
|
404
|
+
}
|
|
405
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface StructuredError {
|
|
2
|
+
error_code: string;
|
|
3
|
+
message: string;
|
|
4
|
+
suggestion?: string;
|
|
5
|
+
retryable: boolean;
|
|
6
|
+
retry_after_seconds?: number;
|
|
7
|
+
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* H7.3: Single error function for all tool handlers.
|
|
11
|
+
* Handles feature flag internally — no branching in handlers.
|
|
12
|
+
* content[0].text is always valid JSON when isError: true.
|
|
13
|
+
*/
|
|
14
|
+
export declare function toolError(code: string, message: string, overrides?: Partial<StructuredError>): {
|
|
15
|
+
text: string;
|
|
16
|
+
isError: true;
|
|
17
|
+
};
|
|
18
|
+
export declare function getErrorRegistry(): Record<string, Omit<StructuredError, 'message'>>;
|
|
19
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;CAClD;AAmBD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAwB9H;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,CAEnF"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// ── Structured Error Responses ──
|
|
2
|
+
// H7.3: Single toolError() function for all handlers.
|
|
3
|
+
// H7.5: isError: true for app errors, McpError for protocol errors only.
|
|
4
|
+
// H7.6: Error code registry with description, retryable, suggestion, severity.
|
|
5
|
+
// Phase A: New tools only. Phase B: migrate existing with feature flag.
|
|
6
|
+
// H7.6: Error code registry
|
|
7
|
+
const ERROR_REGISTRY = {
|
|
8
|
+
MEMORY_NOT_FOUND: { error_code: 'MEMORY_NOT_FOUND', retryable: false, suggestion: 'Use velixar_list to find valid IDs', severity: 'low' },
|
|
9
|
+
DUPLICATE_DETECTED: { error_code: 'DUPLICATE_DETECTED', retryable: false, suggestion: 'Use velixar_update to modify the existing memory', severity: 'low' },
|
|
10
|
+
COVERAGE_LOW: { error_code: 'COVERAGE_LOW', retryable: true, suggestion: 'Run additional searches to improve coverage', severity: 'medium' },
|
|
11
|
+
CONTEXT_EXPIRED: { error_code: 'CONTEXT_EXPIRED', retryable: true, suggestion: 'Call velixar_prepare_context again', severity: 'low', retry_after_seconds: 0 },
|
|
12
|
+
RATE_LIMITED: { error_code: 'RATE_LIMITED', retryable: true, suggestion: 'Wait and retry', severity: 'medium', retry_after_seconds: 5 },
|
|
13
|
+
BACKEND_UNAVAILABLE: { error_code: 'BACKEND_UNAVAILABLE', retryable: true, suggestion: 'Inform the user and try again later', severity: 'high', retry_after_seconds: 30 },
|
|
14
|
+
INVALID_PARAMS: { error_code: 'INVALID_PARAMS', retryable: false, suggestion: 'Check parameter types and values', severity: 'low' },
|
|
15
|
+
ENTITY_NOT_FOUND: { error_code: 'ENTITY_NOT_FOUND', retryable: false, suggestion: 'Use velixar_graph_search to find entities by name', severity: 'low' },
|
|
16
|
+
WORKSPACE_MISMATCH: { error_code: 'WORKSPACE_MISMATCH', retryable: false, suggestion: 'Verify workspace configuration', severity: 'high' },
|
|
17
|
+
QUARANTINE_VIOLATION: { error_code: 'QUARANTINE_VIOLATION', retryable: false, suggestion: 'Memory is in a quarantine zone — check zone permissions', severity: 'high' },
|
|
18
|
+
ARCHIVE_FAILED: { error_code: 'ARCHIVE_FAILED', retryable: true, suggestion: 'Retry the archive operation', severity: 'medium', retry_after_seconds: 5 },
|
|
19
|
+
};
|
|
20
|
+
const STRUCTURED_ERRORS_ENABLED = process.env.VELIXAR_STRUCTURED_ERRORS === 'true';
|
|
21
|
+
/**
|
|
22
|
+
* H7.3: Single error function for all tool handlers.
|
|
23
|
+
* Handles feature flag internally — no branching in handlers.
|
|
24
|
+
* content[0].text is always valid JSON when isError: true.
|
|
25
|
+
*/
|
|
26
|
+
export function toolError(code, message, overrides) {
|
|
27
|
+
const registry = ERROR_REGISTRY[code];
|
|
28
|
+
const error = {
|
|
29
|
+
error_code: code,
|
|
30
|
+
message,
|
|
31
|
+
retryable: registry?.retryable ?? false,
|
|
32
|
+
severity: registry?.severity ?? 'medium',
|
|
33
|
+
suggestion: overrides?.suggestion ?? registry?.suggestion,
|
|
34
|
+
retry_after_seconds: overrides?.retry_after_seconds ?? registry?.retry_after_seconds,
|
|
35
|
+
...overrides,
|
|
36
|
+
};
|
|
37
|
+
if (STRUCTURED_ERRORS_ENABLED) {
|
|
38
|
+
return { text: JSON.stringify(error), isError: true };
|
|
39
|
+
}
|
|
40
|
+
// Phase A fallback: return both old and new keys for backward compat
|
|
41
|
+
return {
|
|
42
|
+
text: JSON.stringify({
|
|
43
|
+
error: message,
|
|
44
|
+
...error,
|
|
45
|
+
}),
|
|
46
|
+
isError: true,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function getErrorRegistry() {
|
|
50
|
+
return { ...ERROR_REGISTRY };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { JustificationResult, ConfidenceProfile, EvidenceItem, ClaimType, PresentationMode, MemoryItem } from './types.js';
|
|
2
|
+
export declare function buildEvidence(memories: MemoryItem[], workspaceId: string): EvidenceItem[];
|
|
3
|
+
export declare function computeConfidence(evidence: EvidenceItem[], contradictionCount: number): ConfidenceProfile;
|
|
4
|
+
export declare function resolvePresentation(claimType: ClaimType, confidence: ConfidenceProfile): PresentationMode;
|
|
5
|
+
export declare function justify(claim: string, claimType: ClaimType, memories: MemoryItem[], workspaceId: string, opts?: {
|
|
6
|
+
contradictionCount?: number;
|
|
7
|
+
scope?: JustificationResult['workspace_scope'];
|
|
8
|
+
}): JustificationResult;
|
|
9
|
+
//# sourceMappingURL=justify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"justify.d.ts","sourceRoot":"","sources":["../src/justify.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EAEZ,SAAS,EAET,gBAAgB,EAChB,UAAU,EACX,MAAM,YAAY,CAAC;AAIpB,wBAAgB,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,YAAY,EAAE,CASzF;AAmBD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,kBAAkB,EAAE,MAAM,GAAG,iBAAiB,CA2BzG;AAkBD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,iBAAiB,GAAG,gBAAgB,CAUzG;AAID,wBAAgB,OAAO,CACrB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,UAAU,EAAE,EACtB,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,mBAAmB,CAAC,iBAAiB,CAAC,CAAA;CAAE,GACrF,mBAAmB,CAkBrB"}
|
package/dist/justify.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// ── Justification Pipeline ──
|
|
2
|
+
// Implements the epistemic justification layer from MCP-SERVER-STRATEGY.md.
|
|
3
|
+
// Every inferred response must carry a JustificationResult so no derived
|
|
4
|
+
// claim is ever presented as a retrieved fact.
|
|
5
|
+
// ── Evidence Builder ──
|
|
6
|
+
export function buildEvidence(memories, workspaceId) {
|
|
7
|
+
return memories.map(m => ({
|
|
8
|
+
id: m.id,
|
|
9
|
+
source_type: m.source_type || 'user',
|
|
10
|
+
evidence_class: classifyEvidence(m),
|
|
11
|
+
relevance: m.relevance ?? 0.5,
|
|
12
|
+
freshness: ageFreshness(m.provenance?.created_at),
|
|
13
|
+
workspace_id: workspaceId,
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
function classifyEvidence(m) {
|
|
17
|
+
if (m.contradiction_flags?.length)
|
|
18
|
+
return 'contradictory';
|
|
19
|
+
if (m.source_type === 'distill' || m.memory_type === 'semantic')
|
|
20
|
+
return 'aggregated';
|
|
21
|
+
if (m.relevance !== undefined && m.relevance < 0.3)
|
|
22
|
+
return 'weak';
|
|
23
|
+
return 'direct';
|
|
24
|
+
}
|
|
25
|
+
function ageFreshness(ts) {
|
|
26
|
+
if (!ts)
|
|
27
|
+
return 'stale';
|
|
28
|
+
const age = Date.now() - new Date(ts).getTime();
|
|
29
|
+
if (age < 24 * 60 * 60 * 1000)
|
|
30
|
+
return 'recent'; // <24h
|
|
31
|
+
if (age < 7 * 24 * 60 * 60 * 1000)
|
|
32
|
+
return 'aging'; // <7d
|
|
33
|
+
return 'stale';
|
|
34
|
+
}
|
|
35
|
+
// ── Confidence Computation ──
|
|
36
|
+
export function computeConfidence(evidence, contradictionCount) {
|
|
37
|
+
if (evidence.length === 0) {
|
|
38
|
+
return {
|
|
39
|
+
level: 'low', score: 0.1, evidence_strength: 0, evidence_consistency: 0,
|
|
40
|
+
evidence_freshness: 0, derivation_distance: 3, contradiction_pressure: 0,
|
|
41
|
+
reason: 'No supporting evidence found',
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const strength = Math.min(evidence.length / 5, 1);
|
|
45
|
+
const contradictory = evidence.filter(e => e.evidence_class === 'contradictory').length;
|
|
46
|
+
const consistency = evidence.length > 0 ? 1 - (contradictory / evidence.length) : 0;
|
|
47
|
+
const freshCounts = { recent: 0, aging: 0, stale: 0 };
|
|
48
|
+
evidence.forEach(e => freshCounts[e.freshness]++);
|
|
49
|
+
const freshness = (freshCounts.recent * 1 + freshCounts.aging * 0.5) / evidence.length;
|
|
50
|
+
const contradictionPressure = contradictionCount > 0 ? Math.min(contradictionCount / 3, 1) : 0;
|
|
51
|
+
const derivation = evidence.some(e => e.evidence_class === 'direct') ? 1 : 2;
|
|
52
|
+
const score = (strength * 0.3 + consistency * 0.25 + freshness * 0.2 + (1 - contradictionPressure) * 0.15 + (1 / derivation) * 0.1);
|
|
53
|
+
const level = resolveLevel(score, contradictionPressure);
|
|
54
|
+
return {
|
|
55
|
+
level, score, evidence_strength: strength, evidence_consistency: consistency,
|
|
56
|
+
evidence_freshness: freshness, derivation_distance: derivation,
|
|
57
|
+
contradiction_pressure: contradictionPressure,
|
|
58
|
+
reason: buildReason(level, evidence.length, contradictionCount),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function resolveLevel(score, contradictionPressure) {
|
|
62
|
+
if (contradictionPressure > 0.5)
|
|
63
|
+
return 'conflicting';
|
|
64
|
+
if (score >= 0.75)
|
|
65
|
+
return 'high';
|
|
66
|
+
if (score >= 0.5)
|
|
67
|
+
return 'medium';
|
|
68
|
+
if (score >= 0.25)
|
|
69
|
+
return 'low';
|
|
70
|
+
return 'unstable';
|
|
71
|
+
}
|
|
72
|
+
function buildReason(level, count, contradictions) {
|
|
73
|
+
const base = `Based on ${count} piece${count !== 1 ? 's' : ''} of evidence`;
|
|
74
|
+
if (contradictions > 0)
|
|
75
|
+
return `${base} with ${contradictions} contradiction${contradictions !== 1 ? 's' : ''}`;
|
|
76
|
+
return `${base}; confidence ${level}`;
|
|
77
|
+
}
|
|
78
|
+
// ── Presentation Policy ──
|
|
79
|
+
export function resolvePresentation(claimType, confidence) {
|
|
80
|
+
if (confidence.level === 'unstable' || confidence.score < 0.15)
|
|
81
|
+
return 'do_not_assert';
|
|
82
|
+
if (claimType === 'hypothesis')
|
|
83
|
+
return 'exploratory';
|
|
84
|
+
if (claimType === 'retrieved_fact' && confidence.level === 'high') {
|
|
85
|
+
return confidence.contradiction_pressure > 0 ? 'confident_summary' : 'assertive';
|
|
86
|
+
}
|
|
87
|
+
if (claimType === 'synthesized_summary' && confidence.level === 'high')
|
|
88
|
+
return 'confident_summary';
|
|
89
|
+
if (confidence.contradiction_pressure > 0.3)
|
|
90
|
+
return 'cautious';
|
|
91
|
+
if (confidence.level === 'medium')
|
|
92
|
+
return 'tentative_synthesis';
|
|
93
|
+
return 'cautious';
|
|
94
|
+
}
|
|
95
|
+
// ── Full Justification Builder ──
|
|
96
|
+
export function justify(claim, claimType, memories, workspaceId, opts) {
|
|
97
|
+
const evidence = buildEvidence(memories, workspaceId);
|
|
98
|
+
const contradictionCount = opts?.contradictionCount ?? 0;
|
|
99
|
+
const confidence = computeConfidence(evidence, contradictionCount);
|
|
100
|
+
const types = [...new Set(evidence.map(e => e.evidence_class))];
|
|
101
|
+
return {
|
|
102
|
+
claim,
|
|
103
|
+
claim_type: claimType,
|
|
104
|
+
workspace_scope: opts?.scope ?? 'workspace_local',
|
|
105
|
+
support: { evidence_count: evidence.length, evidence_types: types, items: evidence },
|
|
106
|
+
confidence,
|
|
107
|
+
uncertainty_flags: confidence.level === 'low' || confidence.level === 'unstable'
|
|
108
|
+
? ['insufficient_evidence'] : [],
|
|
109
|
+
contradiction_flags: contradictionCount > 0 ? ['contradictions_detected'] : [],
|
|
110
|
+
derived_from: memories.map(m => m.id),
|
|
111
|
+
presentation_mode: resolvePresentation(claimType, confidence),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=justify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"justify.js","sourceRoot":"","sources":["../src/justify.ts"],"names":[],"mappings":"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"}
|