clementine-agent 1.18.19 → 1.18.21
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 +17 -0
- package/dist/agent/action-enforcer.d.ts +29 -0
- package/dist/agent/action-enforcer.js +120 -0
- package/dist/agent/assistant.d.ts +14 -0
- package/dist/agent/assistant.js +190 -35
- package/dist/agent/auto-update.js +46 -2
- package/dist/agent/local-turn.d.ts +16 -0
- package/dist/agent/local-turn.js +54 -1
- package/dist/agent/route-classifier.d.ts +1 -0
- package/dist/agent/route-classifier.js +30 -3
- package/dist/agent/toolsets.d.ts +14 -0
- package/dist/agent/toolsets.js +68 -0
- package/dist/brain/ingestion-pipeline.d.ts +7 -0
- package/dist/brain/ingestion-pipeline.js +107 -21
- package/dist/channels/discord.js +38 -7
- package/dist/channels/telegram.js +5 -6
- package/dist/cli/dashboard.js +112 -6
- package/dist/cli/index.js +174 -0
- package/dist/cli/ingest.js +8 -2
- package/dist/gateway/context-hygiene.d.ts +17 -0
- package/dist/gateway/context-hygiene.js +31 -0
- package/dist/gateway/heartbeat-scheduler.d.ts +20 -0
- package/dist/gateway/heartbeat-scheduler.js +27 -10
- package/dist/gateway/router.d.ts +8 -1
- package/dist/gateway/router.js +326 -12
- package/dist/gateway/turn-ledger.d.ts +32 -0
- package/dist/gateway/turn-ledger.js +55 -0
- package/dist/memory/embeddings.d.ts +2 -0
- package/dist/memory/embeddings.js +8 -1
- package/dist/memory/store.d.ts +88 -1
- package/dist/memory/store.js +349 -18
- package/dist/memory/write-queue.d.ts +16 -0
- package/dist/memory/write-queue.js +5 -0
- package/dist/tools/shared.d.ts +89 -0
- package/dist/types.d.ts +11 -0
- package/package.json +1 -1
- package/scripts/postinstall.js +56 -6
package/dist/tools/shared.d.ts
CHANGED
|
@@ -105,6 +105,8 @@ export type MemoryStoreType = {
|
|
|
105
105
|
accessLogRetentionDays?: number;
|
|
106
106
|
transcriptRetentionDays?: number;
|
|
107
107
|
behavioralRetentionDays?: number;
|
|
108
|
+
recallTraceRetentionDays?: number;
|
|
109
|
+
memoryEventRetentionDays?: number;
|
|
108
110
|
}): {
|
|
109
111
|
episodicPruned: number;
|
|
110
112
|
accessLogPruned: number;
|
|
@@ -113,6 +115,8 @@ export type MemoryStoreType = {
|
|
|
113
115
|
feedbackPruned: number;
|
|
114
116
|
reflectionsPruned: number;
|
|
115
117
|
usageLogPruned: number;
|
|
118
|
+
recallTracesPruned: number;
|
|
119
|
+
memoryEventsPruned: number;
|
|
116
120
|
};
|
|
117
121
|
checkDuplicate(content: string, sourceFile?: string): {
|
|
118
122
|
isDuplicate: boolean;
|
|
@@ -286,6 +290,8 @@ export type MemoryStoreType = {
|
|
|
286
290
|
recordsWritten?: number;
|
|
287
291
|
recordsSkipped?: number;
|
|
288
292
|
recordsFailed?: number;
|
|
293
|
+
recordsUnchanged?: number;
|
|
294
|
+
recallCheckStatus?: string | null;
|
|
289
295
|
overviewNotePath?: string | null;
|
|
290
296
|
errorsJson?: string | null;
|
|
291
297
|
status?: 'running' | 'ok' | 'error' | 'partial';
|
|
@@ -300,6 +306,8 @@ export type MemoryStoreType = {
|
|
|
300
306
|
recordsWritten: number;
|
|
301
307
|
recordsSkipped: number;
|
|
302
308
|
recordsFailed: number;
|
|
309
|
+
recordsUnchanged: number;
|
|
310
|
+
recallCheckStatus: string | null;
|
|
303
311
|
overviewNotePath: string | null;
|
|
304
312
|
errorsJson: string | null;
|
|
305
313
|
status: string;
|
|
@@ -368,6 +376,23 @@ export type MemoryStoreType = {
|
|
|
368
376
|
chunkIds: number[];
|
|
369
377
|
scores: number[];
|
|
370
378
|
agentSlug?: string | null;
|
|
379
|
+
matchTypes?: string[];
|
|
380
|
+
backendCounts?: {
|
|
381
|
+
fts: number;
|
|
382
|
+
vector: number;
|
|
383
|
+
graph: number;
|
|
384
|
+
recency: number;
|
|
385
|
+
} | null;
|
|
386
|
+
evidence?: Array<{
|
|
387
|
+
chunkId: number;
|
|
388
|
+
matchType: string;
|
|
389
|
+
score: number;
|
|
390
|
+
sourceFile?: string;
|
|
391
|
+
section?: string;
|
|
392
|
+
}>;
|
|
393
|
+
confidence?: number | null;
|
|
394
|
+
emptyReason?: string | null;
|
|
395
|
+
allowEmpty?: boolean;
|
|
371
396
|
}): void;
|
|
372
397
|
getRecentRecallTraces(sessionKey: string, limit?: number): Array<{
|
|
373
398
|
id: number;
|
|
@@ -375,6 +400,21 @@ export type MemoryStoreType = {
|
|
|
375
400
|
query: string;
|
|
376
401
|
chunkIds: number[];
|
|
377
402
|
scores: number[];
|
|
403
|
+
backendCounts: {
|
|
404
|
+
fts: number;
|
|
405
|
+
vector: number;
|
|
406
|
+
graph: number;
|
|
407
|
+
recency: number;
|
|
408
|
+
} | null;
|
|
409
|
+
evidence: Array<{
|
|
410
|
+
chunkId: number;
|
|
411
|
+
matchType: string;
|
|
412
|
+
score: number;
|
|
413
|
+
sourceFile?: string;
|
|
414
|
+
section?: string;
|
|
415
|
+
}>;
|
|
416
|
+
confidence: number | null;
|
|
417
|
+
emptyReason: string | null;
|
|
378
418
|
retrievedAt: string;
|
|
379
419
|
}>;
|
|
380
420
|
getRecallTrace(traceId: number): {
|
|
@@ -383,6 +423,21 @@ export type MemoryStoreType = {
|
|
|
383
423
|
messageId: string | null;
|
|
384
424
|
query: string;
|
|
385
425
|
retrievedAt: string;
|
|
426
|
+
backendCounts: {
|
|
427
|
+
fts: number;
|
|
428
|
+
vector: number;
|
|
429
|
+
graph: number;
|
|
430
|
+
recency: number;
|
|
431
|
+
} | null;
|
|
432
|
+
evidence: Array<{
|
|
433
|
+
chunkId: number;
|
|
434
|
+
matchType: string;
|
|
435
|
+
score: number;
|
|
436
|
+
sourceFile?: string;
|
|
437
|
+
section?: string;
|
|
438
|
+
}>;
|
|
439
|
+
confidence: number | null;
|
|
440
|
+
emptyReason: string | null;
|
|
386
441
|
chunks: Array<{
|
|
387
442
|
id: number;
|
|
388
443
|
sourceFile: string;
|
|
@@ -503,6 +558,19 @@ export type MemoryStoreType = {
|
|
|
503
558
|
recallTracesLast30d: number;
|
|
504
559
|
extractionSkipsLast30d: number;
|
|
505
560
|
};
|
|
561
|
+
retrievalProof: {
|
|
562
|
+
tracesLast7d: number;
|
|
563
|
+
emptyTracesLast7d: number;
|
|
564
|
+
tracedChunksLast7d: number;
|
|
565
|
+
};
|
|
566
|
+
memoryEvents: {
|
|
567
|
+
total: number;
|
|
568
|
+
indexed: number;
|
|
569
|
+
bySourceType: Array<{
|
|
570
|
+
sourceType: string;
|
|
571
|
+
count: number;
|
|
572
|
+
}>;
|
|
573
|
+
};
|
|
506
574
|
topCitedLast30d: Array<{
|
|
507
575
|
chunkId: number;
|
|
508
576
|
sourceFile: string;
|
|
@@ -556,8 +624,29 @@ export type MemoryStoreType = {
|
|
|
556
624
|
}>;
|
|
557
625
|
currentModel: string;
|
|
558
626
|
ready: boolean;
|
|
627
|
+
cacheDir: string;
|
|
628
|
+
cacheExists: boolean;
|
|
629
|
+
cacheBytes: number;
|
|
630
|
+
cacheSize: string;
|
|
631
|
+
installed: boolean;
|
|
559
632
|
};
|
|
560
633
|
};
|
|
634
|
+
recordMemoryEvent?(input: {
|
|
635
|
+
sourceType: string;
|
|
636
|
+
sourceId?: number | null;
|
|
637
|
+
sessionKey?: string | null;
|
|
638
|
+
agentSlug?: string | null;
|
|
639
|
+
content: string;
|
|
640
|
+
indexed?: boolean;
|
|
641
|
+
}): void;
|
|
642
|
+
getMemoryEventStats(): {
|
|
643
|
+
total: number;
|
|
644
|
+
indexed: number;
|
|
645
|
+
bySourceType: Array<{
|
|
646
|
+
sourceType: string;
|
|
647
|
+
count: number;
|
|
648
|
+
}>;
|
|
649
|
+
};
|
|
561
650
|
logAutonomyEvent(row: {
|
|
562
651
|
component: string;
|
|
563
652
|
event: string;
|
package/dist/types.d.ts
CHANGED
|
@@ -351,6 +351,15 @@ export interface SessionSummary {
|
|
|
351
351
|
exchangeCount: number;
|
|
352
352
|
createdAt: string;
|
|
353
353
|
}
|
|
354
|
+
export interface SessionLineageEntry {
|
|
355
|
+
sessionKey: string;
|
|
356
|
+
parentSessionId: string | null;
|
|
357
|
+
childSessionId: string | null;
|
|
358
|
+
reason: string;
|
|
359
|
+
summary: string;
|
|
360
|
+
exchangeCount: number;
|
|
361
|
+
createdAt: string;
|
|
362
|
+
}
|
|
354
363
|
export interface WikilinkConnection {
|
|
355
364
|
direction: 'incoming' | 'outgoing';
|
|
356
365
|
file: string;
|
|
@@ -887,6 +896,8 @@ export interface IngestionRun {
|
|
|
887
896
|
recordsWritten: number;
|
|
888
897
|
recordsSkipped: number;
|
|
889
898
|
recordsFailed: number;
|
|
899
|
+
recordsUnchanged?: number;
|
|
900
|
+
recallCheckStatus?: string | null;
|
|
890
901
|
overviewNotePath?: string | null;
|
|
891
902
|
errorsJson?: string | null;
|
|
892
903
|
status: 'running' | 'ok' | 'error' | 'partial';
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -6,14 +6,15 @@
|
|
|
6
6
|
* 1. Rebuild native modules (better-sqlite3) for the current Node version
|
|
7
7
|
* 2. Initialize ~/.clementine/ directory structure if it doesn't exist
|
|
8
8
|
* 3. Copy default vault templates from package to data home
|
|
9
|
-
* 4.
|
|
10
|
-
* 5.
|
|
9
|
+
* 4. Optionally prefetch the local dense embedding model
|
|
10
|
+
* 5. Check for `claude` CLI on PATH (needed for OAuth login)
|
|
11
|
+
* 6. Print first-run instructions
|
|
11
12
|
*
|
|
12
13
|
* Safe to re-run — skips steps already completed.
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
|
-
import { execSync } from 'node:child_process';
|
|
16
|
-
import { cpSync, existsSync, mkdirSync, readdirSync } from 'node:fs';
|
|
16
|
+
import { execFileSync, execSync } from 'node:child_process';
|
|
17
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync } from 'node:fs';
|
|
17
18
|
import os from 'node:os';
|
|
18
19
|
import path from 'node:path';
|
|
19
20
|
import { fileURLToPath } from 'node:url';
|
|
@@ -22,6 +23,30 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
22
23
|
const PKG_DIR = path.resolve(__dirname, '..');
|
|
23
24
|
const DATA_HOME = process.env.CLEMENTINE_HOME || path.join(os.homedir(), '.clementine');
|
|
24
25
|
|
|
26
|
+
function readDataEnv() {
|
|
27
|
+
const envPath = path.join(DATA_HOME, '.env');
|
|
28
|
+
if (!existsSync(envPath)) return {};
|
|
29
|
+
try {
|
|
30
|
+
return Object.fromEntries(
|
|
31
|
+
readFileSync(envPath, 'utf-8')
|
|
32
|
+
.split(/\r?\n/)
|
|
33
|
+
.map((line) => line.trim())
|
|
34
|
+
.filter((line) => line && !line.startsWith('#') && line.includes('='))
|
|
35
|
+
.map((line) => {
|
|
36
|
+
const idx = line.indexOf('=');
|
|
37
|
+
return [line.slice(0, idx).trim(), line.slice(idx + 1).trim().replace(/^["']|["']$/g, '')];
|
|
38
|
+
}),
|
|
39
|
+
);
|
|
40
|
+
} catch {
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function flagEnabled(name, envFile) {
|
|
46
|
+
const raw = process.env[name] ?? envFile[name];
|
|
47
|
+
return /^(1|true|yes|on)$/i.test(String(raw ?? ''));
|
|
48
|
+
}
|
|
49
|
+
|
|
25
50
|
// ── Step 1: Rebuild better-sqlite3 ─────────────────────────────────
|
|
26
51
|
try {
|
|
27
52
|
process.stdout.write('Rebuilding native modules...');
|
|
@@ -80,14 +105,39 @@ if (existsSync(srcVault)) {
|
|
|
80
105
|
}
|
|
81
106
|
}
|
|
82
107
|
|
|
83
|
-
// ── Step 4:
|
|
108
|
+
// ── Step 4: Optional local embedding model prefetch ─────────────────
|
|
109
|
+
// Model weights are intentionally not bundled into the npm tarball. Users
|
|
110
|
+
// who want repo/npm updates to keep the local dense model warm can opt in:
|
|
111
|
+
// CLEMENTINE_INSTALL_EMBEDDINGS=1 npm install -g clementine-agent
|
|
112
|
+
// or put CLEMENTINE_PREFETCH_EMBEDDINGS=1 in ~/.clementine/.env.
|
|
113
|
+
const dataEnv = readDataEnv();
|
|
114
|
+
if (flagEnabled('CLEMENTINE_INSTALL_EMBEDDINGS', dataEnv) || flagEnabled('CLEMENTINE_PREFETCH_EMBEDDINGS', dataEnv)) {
|
|
115
|
+
const cliPath = path.join(PKG_DIR, 'dist', 'cli', 'index.js');
|
|
116
|
+
if (existsSync(cliPath)) {
|
|
117
|
+
try {
|
|
118
|
+
console.log('Prefetching Clementine local embedding model...');
|
|
119
|
+
execFileSync(process.execPath, [cliPath, 'memory', 'model', 'install'], {
|
|
120
|
+
cwd: PKG_DIR,
|
|
121
|
+
stdio: 'inherit',
|
|
122
|
+
env: { ...process.env, CLEMENTINE_HOME: DATA_HOME },
|
|
123
|
+
timeout: 10 * 60_000,
|
|
124
|
+
});
|
|
125
|
+
} catch {
|
|
126
|
+
console.log('Embedding model prefetch skipped/failed. Run `clementine memory model install` later.');
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
console.log('Embedding model prefetch skipped: built CLI not found yet.');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ── Step 5: Check for claude CLI ────────────────────────────────────
|
|
84
134
|
let claudeOnPath = false;
|
|
85
135
|
try {
|
|
86
136
|
execSync('claude --version', { stdio: 'pipe' });
|
|
87
137
|
claudeOnPath = true;
|
|
88
138
|
} catch { /* not on PATH */ }
|
|
89
139
|
|
|
90
|
-
// ── Step
|
|
140
|
+
// ── Step 6: Print instructions ──────────────────────────────────────
|
|
91
141
|
const alreadyConfigured = existsSync(path.join(DATA_HOME, '.env'));
|
|
92
142
|
|
|
93
143
|
if (alreadyConfigured) {
|