shieldcortex 3.1.0 → 3.2.1
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 +64 -9
- package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
- package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +3 -3
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/chunks/ssr/dashboard_3051539d._.js +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/98e2c181d5c4349f.js +1 -0
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/9cb86821c1107fd6.js +9 -0
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/a56c497e02afd4ba.css +3 -0
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/a90355d73183a5e6.js +1 -0
- package/dist/api/routes/memories.js +366 -1
- package/dist/api/routes/recall.js +53 -0
- package/dist/cloud/graph-sync.js +6 -3
- package/dist/cloud/memory-sync.d.ts +1 -0
- package/dist/cloud/memory-sync.js +3 -0
- package/dist/database/init.js +29 -0
- package/dist/memory/search.d.ts +1 -0
- package/dist/memory/search.js +4 -0
- package/dist/memory/store.js +146 -28
- package/dist/memory/types.d.ts +31 -0
- package/dist/setup/quickstart.js +13 -6
- package/dist/tools/context.d.ts +4 -4
- package/dist/tools/forget.d.ts +4 -4
- package/dist/tools/recall.d.ts +8 -8
- package/dist/tools/remember.d.ts +19 -4
- package/dist/tools/remember.js +17 -1
- package/hooks/openclaw/cortex-memory/handler.ts +8 -0
- package/package.json +2 -2
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/0a69eb25d08447ee.js +0 -1
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/3cc7e8d4f73cf5d2.js +0 -1
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/97537d3db46c8467.css +0 -3
- package/dashboard/.next/standalone/dashboard/.next/static/chunks/aa6e9b8a52353969.js +0 -9
- /package/dashboard/.next/standalone/dashboard/.next/static/{RnvqrTXo_jN8SuMdaNcIj → Oi8lTcFeUV-igSMtPHAG-}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{RnvqrTXo_jN8SuMdaNcIj → Oi8lTcFeUV-igSMtPHAG-}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{RnvqrTXo_jN8SuMdaNcIj → Oi8lTcFeUV-igSMtPHAG-}/_ssgManifest.js +0 -0
package/dist/memory/store.js
CHANGED
|
@@ -122,6 +122,32 @@ function safeJsonParse(value, fallback) {
|
|
|
122
122
|
return fallback;
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
+
function inferSourceDetails(input, source) {
|
|
126
|
+
const tags = (input.tags ?? []).map((tag) => tag.toLowerCase());
|
|
127
|
+
if (tags.includes('openclaw-hook')) {
|
|
128
|
+
return { sourceKind: 'hook', captureMethod: tags.includes('auto-extracted') ? 'auto' : 'hook', sourceValue: 'hook:openclaw' };
|
|
129
|
+
}
|
|
130
|
+
if (tags.includes('realtime-plugin') || tags.includes('llm-output')) {
|
|
131
|
+
return { sourceKind: 'plugin', captureMethod: tags.includes('auto-extracted') ? 'auto' : 'plugin', sourceValue: 'agent:openclaw-plugin' };
|
|
132
|
+
}
|
|
133
|
+
if (source?.type === 'hook') {
|
|
134
|
+
return { sourceKind: 'hook', captureMethod: 'hook', sourceValue: `${source.type}:${source.identifier}` };
|
|
135
|
+
}
|
|
136
|
+
if (source?.type === 'agent') {
|
|
137
|
+
return { sourceKind: 'agent', captureMethod: 'plugin', sourceValue: `${source.type}:${source.identifier}` };
|
|
138
|
+
}
|
|
139
|
+
if (source?.type === 'api') {
|
|
140
|
+
return { sourceKind: 'api', captureMethod: 'api', sourceValue: `${source.type}:${source.identifier}` };
|
|
141
|
+
}
|
|
142
|
+
if (source?.type === 'cli') {
|
|
143
|
+
return { sourceKind: 'cli', captureMethod: 'manual', sourceValue: `${source.type}:${source.identifier}` };
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
sourceKind: input.sourceKind ?? 'user',
|
|
147
|
+
captureMethod: input.captureMethod ?? (tags.includes('auto-extracted') ? 'auto' : 'manual'),
|
|
148
|
+
sourceValue: input.source ?? (source ? `${source.type}:${source.identifier}` : 'user:direct'),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
125
151
|
/**
|
|
126
152
|
* Convert database row to Memory object
|
|
127
153
|
*/
|
|
@@ -145,6 +171,16 @@ export function rowToMemory(row) {
|
|
|
145
171
|
embedding: row.embedding,
|
|
146
172
|
scope: row.scope ?? 'project',
|
|
147
173
|
transferable: Boolean(row.transferable),
|
|
174
|
+
status: (row.status ?? 'active'),
|
|
175
|
+
pinned: Boolean(row.pinned),
|
|
176
|
+
reviewedAt: row.reviewed_at ? new Date(row.reviewed_at) : null,
|
|
177
|
+
reviewedBy: row.reviewed_by ?? null,
|
|
178
|
+
sourceKind: (row.source_kind ?? 'user'),
|
|
179
|
+
captureMethod: (row.capture_method ?? 'manual'),
|
|
180
|
+
trustScore: Number(row.trust_score ?? 1),
|
|
181
|
+
sensitivityLevel: row.sensitivity_level ?? 'INTERNAL',
|
|
182
|
+
source: row.source ?? null,
|
|
183
|
+
cloudExcluded: Boolean(row.cloud_excluded),
|
|
148
184
|
};
|
|
149
185
|
}
|
|
150
186
|
/**
|
|
@@ -357,9 +393,16 @@ export function addMemory(input, config = DEFAULT_CONFIG, source) {
|
|
|
357
393
|
const scope = input.scope ??
|
|
358
394
|
(detectGlobalPattern(input.content, category, tags) ? 'global' : 'project');
|
|
359
395
|
const transferable = input.transferable ?? (scope === 'global' ? 1 : 0);
|
|
396
|
+
const sourceDetails = inferSourceDetails({ ...input, tags }, source);
|
|
397
|
+
const status = input.status ?? 'active';
|
|
398
|
+
const pinned = input.pinned ? 1 : 0;
|
|
399
|
+
const cloudExcluded = input.cloudExcluded ? 1 : 0;
|
|
360
400
|
const stmt = db.prepare(`
|
|
361
|
-
INSERT INTO memories (
|
|
362
|
-
|
|
401
|
+
INSERT INTO memories (
|
|
402
|
+
uuid, type, category, title, content, project, tags, salience, metadata, scope, transferable,
|
|
403
|
+
status, pinned, reviewed_at, reviewed_by, source_kind, capture_method, cloud_excluded, updated_at
|
|
404
|
+
)
|
|
405
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
|
363
406
|
`);
|
|
364
407
|
// Anti-bloat: Truncate content if too large
|
|
365
408
|
const truncationResult = truncateContent(input.content);
|
|
@@ -372,10 +415,14 @@ export function addMemory(input, config = DEFAULT_CONFIG, source) {
|
|
|
372
415
|
// Transaction: INSERT + defence UPDATE must be atomic to prevent wrong trust scores
|
|
373
416
|
const insertedId = db.transaction(() => {
|
|
374
417
|
const memoryUuid = randomUUID();
|
|
375
|
-
const result = stmt.run(memoryUuid, type, category, input.title, truncationResult.content, input.project || null, JSON.stringify(tags), salience, JSON.stringify(input.metadata || {}), scope, transferable);
|
|
418
|
+
const result = stmt.run(memoryUuid, type, category, input.title, truncationResult.content, input.project || null, JSON.stringify(tags), salience, JSON.stringify(input.metadata || {}), scope, transferable, status, pinned, input.reviewedBy ? new Date().toISOString() : null, input.reviewedBy ?? null, sourceDetails.sourceKind, sourceDetails.captureMethod, cloudExcluded);
|
|
376
419
|
if (defenceResult) {
|
|
377
420
|
db.prepare(`UPDATE memories SET trust_score = ?, sensitivity_level = ?, source = ? WHERE id = ?`)
|
|
378
|
-
.run(defenceResult.trust.score, defenceResult.sensitivity.level,
|
|
421
|
+
.run(defenceResult.trust.score, defenceResult.sensitivity.level, sourceDetails.sourceValue, result.lastInsertRowid);
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
db.prepare(`UPDATE memories SET source = ?, trust_score = COALESCE(trust_score, ?), sensitivity_level = COALESCE(sensitivity_level, ?) WHERE id = ?`)
|
|
425
|
+
.run(sourceDetails.sourceValue, input.trustScore ?? 1.0, input.sensitivityLevel ?? 'INTERNAL', result.lastInsertRowid);
|
|
379
426
|
}
|
|
380
427
|
return result.lastInsertRowid;
|
|
381
428
|
})();
|
|
@@ -455,30 +502,32 @@ export function addMemory(input, config = DEFAULT_CONFIG, source) {
|
|
|
455
502
|
});
|
|
456
503
|
// Anti-bloat: Check if limits exceeded and trigger async cleanup
|
|
457
504
|
// We use setImmediate to not block the insert response
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
505
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
506
|
+
setImmediate(() => {
|
|
507
|
+
try {
|
|
508
|
+
if (!isDatabaseInitialized()) {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
const stats = getMemoryStats();
|
|
512
|
+
if (stats.shortTerm > config.maxShortTermMemories ||
|
|
513
|
+
stats.longTerm > config.maxLongTermMemories) {
|
|
514
|
+
// Import dynamically to avoid circular dependency
|
|
515
|
+
import('./consolidate.js').then(({ enforceMemoryLimits }) => {
|
|
516
|
+
if (typeof enforceMemoryLimits === 'function') {
|
|
517
|
+
enforceMemoryLimits(config);
|
|
518
|
+
}
|
|
519
|
+
}).catch((e) => {
|
|
520
|
+
// Log but don't fail - consolidation will happen on next scheduled run
|
|
521
|
+
console.warn('[shieldcortex] Async cleanup import failed:', e instanceof Error ? e.message : e);
|
|
522
|
+
});
|
|
523
|
+
}
|
|
462
524
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
// Import dynamically to avoid circular dependency
|
|
467
|
-
import('./consolidate.js').then(({ enforceMemoryLimits }) => {
|
|
468
|
-
if (typeof enforceMemoryLimits === 'function') {
|
|
469
|
-
enforceMemoryLimits(config);
|
|
470
|
-
}
|
|
471
|
-
}).catch((e) => {
|
|
472
|
-
// Log but don't fail - consolidation will happen on next scheduled run
|
|
473
|
-
console.warn('[shieldcortex] Async cleanup import failed:', e instanceof Error ? e.message : e);
|
|
474
|
-
});
|
|
525
|
+
catch (e) {
|
|
526
|
+
// Log unexpected errors in async cleanup
|
|
527
|
+
console.warn('[shieldcortex] Async cleanup check failed:', e instanceof Error ? e.message : e);
|
|
475
528
|
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// Log unexpected errors in async cleanup
|
|
479
|
-
console.warn('[shieldcortex] Async cleanup check failed:', e instanceof Error ? e.message : e);
|
|
480
|
-
}
|
|
481
|
-
});
|
|
529
|
+
});
|
|
530
|
+
}
|
|
482
531
|
return memory;
|
|
483
532
|
}
|
|
484
533
|
/**
|
|
@@ -541,6 +590,44 @@ export function updateMemory(id, updates) {
|
|
|
541
590
|
fields.push('metadata = ?');
|
|
542
591
|
values.push(JSON.stringify(updates.metadata));
|
|
543
592
|
}
|
|
593
|
+
if (updates.status !== undefined) {
|
|
594
|
+
fields.push('status = ?');
|
|
595
|
+
values.push(updates.status);
|
|
596
|
+
}
|
|
597
|
+
if (updates.pinned !== undefined) {
|
|
598
|
+
fields.push('pinned = ?');
|
|
599
|
+
values.push(updates.pinned ? 1 : 0);
|
|
600
|
+
}
|
|
601
|
+
if (updates.reviewedBy !== undefined) {
|
|
602
|
+
fields.push('reviewed_by = ?');
|
|
603
|
+
values.push(updates.reviewedBy);
|
|
604
|
+
fields.push('reviewed_at = ?');
|
|
605
|
+
values.push(updates.reviewedBy ? new Date().toISOString() : null);
|
|
606
|
+
}
|
|
607
|
+
if (updates.sourceKind !== undefined) {
|
|
608
|
+
fields.push('source_kind = ?');
|
|
609
|
+
values.push(updates.sourceKind);
|
|
610
|
+
}
|
|
611
|
+
if (updates.captureMethod !== undefined) {
|
|
612
|
+
fields.push('capture_method = ?');
|
|
613
|
+
values.push(updates.captureMethod);
|
|
614
|
+
}
|
|
615
|
+
if (updates.trustScore !== undefined) {
|
|
616
|
+
fields.push('trust_score = ?');
|
|
617
|
+
values.push(updates.trustScore);
|
|
618
|
+
}
|
|
619
|
+
if (updates.sensitivityLevel !== undefined) {
|
|
620
|
+
fields.push('sensitivity_level = ?');
|
|
621
|
+
values.push(updates.sensitivityLevel);
|
|
622
|
+
}
|
|
623
|
+
if (updates.source !== undefined) {
|
|
624
|
+
fields.push('source = ?');
|
|
625
|
+
values.push(updates.source);
|
|
626
|
+
}
|
|
627
|
+
if (updates.cloudExcluded !== undefined) {
|
|
628
|
+
fields.push('cloud_excluded = ?');
|
|
629
|
+
values.push(updates.cloudExcluded ? 1 : 0);
|
|
630
|
+
}
|
|
544
631
|
if (fields.length === 0)
|
|
545
632
|
return existing;
|
|
546
633
|
values.push(id);
|
|
@@ -877,6 +964,12 @@ async function searchMemoriesInternal(options, config, source, execution) {
|
|
|
877
964
|
sql += ' AND m.type = ?';
|
|
878
965
|
params.push(options.type);
|
|
879
966
|
}
|
|
967
|
+
if (!options.includeArchived) {
|
|
968
|
+
sql += ` AND m.status != 'archived'`;
|
|
969
|
+
}
|
|
970
|
+
if (!options.includeSuppressed) {
|
|
971
|
+
sql += ` AND m.status != 'suppressed'`;
|
|
972
|
+
}
|
|
880
973
|
if (options.minSalience) {
|
|
881
974
|
sql += ' AND m.salience >= ?';
|
|
882
975
|
params.push(options.minSalience);
|
|
@@ -915,12 +1008,33 @@ async function searchMemoriesInternal(options, config, source, execution) {
|
|
|
915
1008
|
const vectorSimilarity = vectorResults.get(memory.id) || 0;
|
|
916
1009
|
const vectorBoost = vectorSimilarity * 0.3;
|
|
917
1010
|
const priorityBoost = calculatePriority(memory) * 0.05;
|
|
1011
|
+
const contradictionCount = db.prepare(`SELECT COUNT(*) as count FROM memory_links WHERE relationship = 'contradicts' AND (source_id = ? OR target_id = ?)`).get(memory.id, memory.id).count;
|
|
1012
|
+
const contradictionPenalty = Math.min(0.12, contradictionCount * 0.03);
|
|
1013
|
+
const eligibilityReasons = [];
|
|
1014
|
+
if (memory.status === 'archived')
|
|
1015
|
+
eligibilityReasons.push('Archived memories are excluded from normal recall');
|
|
1016
|
+
if (memory.status === 'suppressed')
|
|
1017
|
+
eligibilityReasons.push('Suppressed memories are excluded from normal recall');
|
|
1018
|
+
if (memory.cloudExcluded)
|
|
1019
|
+
eligibilityReasons.push('Excluded from cloud sync');
|
|
1020
|
+
if (memory.trustScore < 0.7)
|
|
1021
|
+
eligibilityReasons.push(`Low trust source (${memory.trustScore.toFixed(2)})`);
|
|
1022
|
+
if (contradictionCount > 0)
|
|
1023
|
+
eligibilityReasons.push(`${contradictionCount} contradiction link${contradictionCount === 1 ? '' : 's'} attached`);
|
|
918
1024
|
const relevanceScore = (ftsScore * 0.25 +
|
|
919
1025
|
vectorBoost +
|
|
920
1026
|
decayedScore * 0.2 +
|
|
921
1027
|
priorityBoost +
|
|
922
|
-
recencyBoost + categoryBoost + linkBoost + tagBoost + activationBoost
|
|
923
|
-
|
|
1028
|
+
recencyBoost + categoryBoost + linkBoost + tagBoost + activationBoost -
|
|
1029
|
+
contradictionPenalty);
|
|
1030
|
+
const result = {
|
|
1031
|
+
memory,
|
|
1032
|
+
relevanceScore,
|
|
1033
|
+
recallEligibility: {
|
|
1034
|
+
eligible: eligibilityReasons.length === 0,
|
|
1035
|
+
reasons: eligibilityReasons,
|
|
1036
|
+
},
|
|
1037
|
+
};
|
|
924
1038
|
if (execution.includeExplanation) {
|
|
925
1039
|
result.explanation = buildSearchExplanation(memory, scoringContext, {
|
|
926
1040
|
ftsScore,
|
|
@@ -933,8 +1047,12 @@ async function searchMemoriesInternal(options, config, source, execution) {
|
|
|
933
1047
|
linkBoost,
|
|
934
1048
|
tagBoost,
|
|
935
1049
|
activationBoost,
|
|
1050
|
+
contradictionPenalty,
|
|
936
1051
|
finalScore: relevanceScore,
|
|
937
1052
|
});
|
|
1053
|
+
if (result.explanation) {
|
|
1054
|
+
result.explanation.eligibility = result.recallEligibility;
|
|
1055
|
+
}
|
|
938
1056
|
}
|
|
939
1057
|
return result;
|
|
940
1058
|
});
|
package/dist/memory/types.d.ts
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* Core type definitions for the ShieldCortex memory system
|
|
3
3
|
*/
|
|
4
4
|
export type MemoryType = 'short_term' | 'long_term' | 'episodic';
|
|
5
|
+
export type MemoryStatus = 'active' | 'archived' | 'suppressed' | 'canonical';
|
|
6
|
+
export type MemorySourceKind = 'user' | 'cli' | 'hook' | 'plugin' | 'agent' | 'import' | 'cloud' | 'api' | 'system';
|
|
7
|
+
export type MemoryCaptureMethod = 'manual' | 'hook' | 'plugin' | 'import' | 'cloud' | 'api' | 'auto' | 'review';
|
|
5
8
|
export type MemoryCategory = 'architecture' | 'pattern' | 'preference' | 'error' | 'context' | 'learning' | 'todo' | 'note' | 'relationship' | 'custom';
|
|
6
9
|
export interface Memory {
|
|
7
10
|
id: number;
|
|
@@ -22,6 +25,16 @@ export interface Memory {
|
|
|
22
25
|
embedding?: Buffer;
|
|
23
26
|
scope: 'project' | 'global';
|
|
24
27
|
transferable: boolean;
|
|
28
|
+
status: MemoryStatus;
|
|
29
|
+
pinned: boolean;
|
|
30
|
+
reviewedAt: Date | null;
|
|
31
|
+
reviewedBy: string | null;
|
|
32
|
+
sourceKind: MemorySourceKind;
|
|
33
|
+
captureMethod: MemoryCaptureMethod;
|
|
34
|
+
trustScore: number;
|
|
35
|
+
sensitivityLevel: string;
|
|
36
|
+
source: string | null;
|
|
37
|
+
cloudExcluded: boolean;
|
|
25
38
|
}
|
|
26
39
|
export interface MemoryInput {
|
|
27
40
|
type?: MemoryType;
|
|
@@ -34,6 +47,15 @@ export interface MemoryInput {
|
|
|
34
47
|
metadata?: Record<string, unknown>;
|
|
35
48
|
scope?: 'project' | 'global';
|
|
36
49
|
transferable?: boolean;
|
|
50
|
+
status?: MemoryStatus;
|
|
51
|
+
pinned?: boolean;
|
|
52
|
+
reviewedBy?: string | null;
|
|
53
|
+
sourceKind?: MemorySourceKind;
|
|
54
|
+
captureMethod?: MemoryCaptureMethod;
|
|
55
|
+
trustScore?: number;
|
|
56
|
+
sensitivityLevel?: string;
|
|
57
|
+
source?: string | null;
|
|
58
|
+
cloudExcluded?: boolean;
|
|
37
59
|
}
|
|
38
60
|
export interface SearchOptions {
|
|
39
61
|
query: string;
|
|
@@ -45,6 +67,8 @@ export interface SearchOptions {
|
|
|
45
67
|
limit?: number;
|
|
46
68
|
includeDecayed?: boolean;
|
|
47
69
|
includeGlobal?: boolean;
|
|
70
|
+
includeArchived?: boolean;
|
|
71
|
+
includeSuppressed?: boolean;
|
|
48
72
|
}
|
|
49
73
|
export interface SearchResult {
|
|
50
74
|
memory: Memory;
|
|
@@ -55,6 +79,7 @@ export interface SearchResult {
|
|
|
55
79
|
score: number;
|
|
56
80
|
}[];
|
|
57
81
|
explanation?: SearchExplanation;
|
|
82
|
+
recallEligibility?: RecallEligibility;
|
|
58
83
|
}
|
|
59
84
|
export interface SearchScoreBreakdown {
|
|
60
85
|
ftsScore: number;
|
|
@@ -67,14 +92,20 @@ export interface SearchScoreBreakdown {
|
|
|
67
92
|
linkBoost: number;
|
|
68
93
|
tagBoost: number;
|
|
69
94
|
activationBoost: number;
|
|
95
|
+
contradictionPenalty: number;
|
|
70
96
|
finalScore: number;
|
|
71
97
|
matchedTags: string[];
|
|
72
98
|
matchedCategory: string | null;
|
|
73
99
|
}
|
|
100
|
+
export interface RecallEligibility {
|
|
101
|
+
eligible: boolean;
|
|
102
|
+
reasons: string[];
|
|
103
|
+
}
|
|
74
104
|
export interface SearchExplanation {
|
|
75
105
|
query: string;
|
|
76
106
|
reasons: string[];
|
|
77
107
|
breakdown: SearchScoreBreakdown;
|
|
108
|
+
eligibility?: RecallEligibility;
|
|
78
109
|
}
|
|
79
110
|
export interface ConsolidationResult {
|
|
80
111
|
consolidated: number;
|
package/dist/setup/quickstart.js
CHANGED
|
@@ -41,27 +41,34 @@ function printAutoGuide() {
|
|
|
41
41
|
lines.push('');
|
|
42
42
|
lines.push('ShieldCortex Quickstart');
|
|
43
43
|
lines.push('────────────────────────────────────────────────────');
|
|
44
|
+
lines.push('Goal: give your agent memory you can inspect and security you can trust.');
|
|
44
45
|
lines.push(`Detected: Claude=${env.claude ? 'yes' : 'no'} · OpenClaw=${env.openclaw ? 'yes' : 'no'} · Copilot/Cursor=${env.copilot ? 'yes' : 'no'}`);
|
|
45
46
|
lines.push('');
|
|
47
|
+
lines.push('Best paths:');
|
|
48
|
+
lines.push('');
|
|
46
49
|
if (env.claude) {
|
|
47
|
-
lines.push('
|
|
50
|
+
lines.push('Claude Code');
|
|
51
|
+
lines.push(' Make recall and review available in Claude sessions:');
|
|
48
52
|
lines.push(' shieldcortex quickstart claude');
|
|
49
53
|
lines.push('');
|
|
50
54
|
}
|
|
51
55
|
if (env.openclaw) {
|
|
52
|
-
lines.push('
|
|
56
|
+
lines.push('OpenClaw');
|
|
57
|
+
lines.push(' Install the hook + realtime plugin for session capture and defence:');
|
|
53
58
|
lines.push(' shieldcortex quickstart openclaw');
|
|
54
59
|
lines.push('');
|
|
55
60
|
}
|
|
56
61
|
if (env.copilot) {
|
|
57
|
-
lines.push('
|
|
62
|
+
lines.push('VS Code / Cursor');
|
|
63
|
+
lines.push(' Wire ShieldCortex in as an MCP memory + security layer:');
|
|
58
64
|
lines.push(' shieldcortex quickstart copilot');
|
|
59
65
|
lines.push('');
|
|
60
66
|
}
|
|
61
|
-
lines.push('Security-only
|
|
67
|
+
lines.push('Security-only');
|
|
68
|
+
lines.push(' Scan prompts, tools, and environments without adopting memory first:');
|
|
62
69
|
lines.push(' shieldcortex quickstart security');
|
|
63
70
|
lines.push('');
|
|
64
|
-
lines.push('
|
|
71
|
+
lines.push('Direct commands:');
|
|
65
72
|
lines.push(' shieldcortex setup');
|
|
66
73
|
lines.push(' shieldcortex openclaw install');
|
|
67
74
|
lines.push(' shieldcortex copilot install');
|
|
@@ -79,7 +86,7 @@ ShieldCortex Security Quickstart
|
|
|
79
86
|
2. Audit your local agent environment:
|
|
80
87
|
shieldcortex audit
|
|
81
88
|
|
|
82
|
-
3. Open the dashboard for quarantine,
|
|
89
|
+
3. Open the dashboard for quarantine, recall review, and sync visibility:
|
|
83
90
|
shieldcortex dashboard
|
|
84
91
|
`);
|
|
85
92
|
}
|
package/dist/tools/context.d.ts
CHANGED
|
@@ -15,23 +15,23 @@ export declare const getContextSchema: z.ZodObject<{
|
|
|
15
15
|
type: z.ZodEnum<["user", "cli", "hook", "email", "web", "agent", "file", "api", "tool_response"]>;
|
|
16
16
|
identifier: z.ZodString;
|
|
17
17
|
}, "strip", z.ZodTypeAny, {
|
|
18
|
-
type: "
|
|
18
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
19
19
|
identifier: string;
|
|
20
20
|
}, {
|
|
21
|
-
type: "
|
|
21
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
22
22
|
identifier: string;
|
|
23
23
|
}>>;
|
|
24
24
|
}, "strip", z.ZodTypeAny, {
|
|
25
25
|
format: "summary" | "detailed" | "raw";
|
|
26
26
|
source?: {
|
|
27
|
-
type: "
|
|
27
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
28
28
|
identifier: string;
|
|
29
29
|
} | undefined;
|
|
30
30
|
project?: string | undefined;
|
|
31
31
|
query?: string | undefined;
|
|
32
32
|
}, {
|
|
33
33
|
source?: {
|
|
34
|
-
type: "
|
|
34
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
35
35
|
identifier: string;
|
|
36
36
|
} | undefined;
|
|
37
37
|
project?: string | undefined;
|
package/dist/tools/forget.d.ts
CHANGED
|
@@ -17,17 +17,17 @@ export declare const forgetSchema: z.ZodObject<{
|
|
|
17
17
|
type: z.ZodEnum<["user", "cli", "hook", "email", "web", "agent", "file", "api", "tool_response"]>;
|
|
18
18
|
identifier: z.ZodString;
|
|
19
19
|
}, "strip", z.ZodTypeAny, {
|
|
20
|
-
type: "
|
|
20
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
21
21
|
identifier: string;
|
|
22
22
|
}, {
|
|
23
|
-
type: "
|
|
23
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
24
24
|
identifier: string;
|
|
25
25
|
}>>;
|
|
26
26
|
}, "strip", z.ZodTypeAny, {
|
|
27
27
|
dryRun: boolean;
|
|
28
28
|
confirm: boolean;
|
|
29
29
|
source?: {
|
|
30
|
-
type: "
|
|
30
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
31
31
|
identifier: string;
|
|
32
32
|
} | undefined;
|
|
33
33
|
project?: string | undefined;
|
|
@@ -38,7 +38,7 @@ export declare const forgetSchema: z.ZodObject<{
|
|
|
38
38
|
belowSalience?: number | undefined;
|
|
39
39
|
}, {
|
|
40
40
|
source?: {
|
|
41
|
-
type: "
|
|
41
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
42
42
|
identifier: string;
|
|
43
43
|
} | undefined;
|
|
44
44
|
project?: string | undefined;
|
package/dist/tools/recall.d.ts
CHANGED
|
@@ -20,10 +20,10 @@ export declare const recallSchema: z.ZodObject<{
|
|
|
20
20
|
type: z.ZodEnum<["user", "cli", "hook", "email", "web", "agent", "file", "api", "tool_response"]>;
|
|
21
21
|
identifier: z.ZodString;
|
|
22
22
|
}, "strip", z.ZodTypeAny, {
|
|
23
|
-
type: "
|
|
23
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
24
24
|
identifier: string;
|
|
25
25
|
}, {
|
|
26
|
-
type: "
|
|
26
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
27
27
|
identifier: string;
|
|
28
28
|
}>>;
|
|
29
29
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -32,7 +32,7 @@ export declare const recallSchema: z.ZodObject<{
|
|
|
32
32
|
includeDecayed: boolean;
|
|
33
33
|
includeGlobal: boolean;
|
|
34
34
|
source?: {
|
|
35
|
-
type: "
|
|
35
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
36
36
|
identifier: string;
|
|
37
37
|
} | undefined;
|
|
38
38
|
project?: string | undefined;
|
|
@@ -42,7 +42,7 @@ export declare const recallSchema: z.ZodObject<{
|
|
|
42
42
|
query?: string | undefined;
|
|
43
43
|
}, {
|
|
44
44
|
source?: {
|
|
45
|
-
type: "
|
|
45
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
46
46
|
identifier: string;
|
|
47
47
|
} | undefined;
|
|
48
48
|
project?: string | undefined;
|
|
@@ -87,22 +87,22 @@ export declare const getMemorySchema: z.ZodObject<{
|
|
|
87
87
|
type: z.ZodEnum<["user", "cli", "hook", "email", "web", "agent", "file", "api", "tool_response"]>;
|
|
88
88
|
identifier: z.ZodString;
|
|
89
89
|
}, "strip", z.ZodTypeAny, {
|
|
90
|
-
type: "
|
|
90
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
91
91
|
identifier: string;
|
|
92
92
|
}, {
|
|
93
|
-
type: "
|
|
93
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
94
94
|
identifier: string;
|
|
95
95
|
}>>;
|
|
96
96
|
}, "strip", z.ZodTypeAny, {
|
|
97
97
|
id: number;
|
|
98
98
|
source?: {
|
|
99
|
-
type: "
|
|
99
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
100
100
|
identifier: string;
|
|
101
101
|
} | undefined;
|
|
102
102
|
}, {
|
|
103
103
|
id: number;
|
|
104
104
|
source?: {
|
|
105
|
-
type: "
|
|
105
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
106
106
|
identifier: string;
|
|
107
107
|
} | undefined;
|
|
108
108
|
}>;
|
package/dist/tools/remember.d.ts
CHANGED
|
@@ -19,40 +19,55 @@ export declare const rememberSchema: z.ZodObject<{
|
|
|
19
19
|
type: z.ZodEnum<["user", "cli", "hook", "email", "web", "agent", "file", "api", "tool_response"]>;
|
|
20
20
|
identifier: z.ZodString;
|
|
21
21
|
}, "strip", z.ZodTypeAny, {
|
|
22
|
-
type: "
|
|
22
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
23
23
|
identifier: string;
|
|
24
24
|
}, {
|
|
25
|
-
type: "
|
|
25
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
26
26
|
identifier: string;
|
|
27
27
|
}>>;
|
|
28
|
+
sourceType: z.ZodOptional<z.ZodEnum<["user", "cli", "hook", "email", "web", "agent", "file", "api", "tool_response"]>>;
|
|
29
|
+
sourceIdentifier: z.ZodOptional<z.ZodString>;
|
|
30
|
+
sessionId: z.ZodOptional<z.ZodString>;
|
|
31
|
+
agentId: z.ZodOptional<z.ZodString>;
|
|
32
|
+
workspaceDir: z.ZodOptional<z.ZodString>;
|
|
28
33
|
}, "strip", z.ZodTypeAny, {
|
|
29
34
|
title: string;
|
|
30
35
|
content: string;
|
|
31
36
|
scope?: "project" | "global" | undefined;
|
|
32
37
|
transferable?: boolean | undefined;
|
|
33
38
|
source?: {
|
|
34
|
-
type: "
|
|
39
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
35
40
|
identifier: string;
|
|
36
41
|
} | undefined;
|
|
37
42
|
project?: string | undefined;
|
|
38
43
|
type?: "short_term" | "long_term" | "episodic" | undefined;
|
|
39
44
|
category?: "architecture" | "pattern" | "preference" | "error" | "context" | "learning" | "todo" | "note" | "relationship" | "custom" | undefined;
|
|
40
45
|
tags?: string[] | undefined;
|
|
46
|
+
sourceIdentifier?: string | undefined;
|
|
47
|
+
sessionId?: string | undefined;
|
|
41
48
|
importance?: "critical" | "low" | "high" | "normal" | undefined;
|
|
49
|
+
sourceType?: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response" | undefined;
|
|
50
|
+
agentId?: string | undefined;
|
|
51
|
+
workspaceDir?: string | undefined;
|
|
42
52
|
}, {
|
|
43
53
|
title: string;
|
|
44
54
|
content: string;
|
|
45
55
|
scope?: "project" | "global" | undefined;
|
|
46
56
|
transferable?: boolean | undefined;
|
|
47
57
|
source?: {
|
|
48
|
-
type: "
|
|
58
|
+
type: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response";
|
|
49
59
|
identifier: string;
|
|
50
60
|
} | undefined;
|
|
51
61
|
project?: string | undefined;
|
|
52
62
|
type?: "short_term" | "long_term" | "episodic" | undefined;
|
|
53
63
|
category?: "architecture" | "pattern" | "preference" | "error" | "context" | "learning" | "todo" | "note" | "relationship" | "custom" | undefined;
|
|
54
64
|
tags?: string[] | undefined;
|
|
65
|
+
sourceIdentifier?: string | undefined;
|
|
66
|
+
sessionId?: string | undefined;
|
|
55
67
|
importance?: "critical" | "low" | "high" | "normal" | undefined;
|
|
68
|
+
sourceType?: "user" | "cli" | "hook" | "agent" | "api" | "email" | "web" | "file" | "tool_response" | undefined;
|
|
69
|
+
agentId?: string | undefined;
|
|
70
|
+
workspaceDir?: string | undefined;
|
|
56
71
|
}>;
|
|
57
72
|
export type RememberInput = z.infer<typeof rememberSchema>;
|
|
58
73
|
/**
|
package/dist/tools/remember.js
CHANGED
|
@@ -30,6 +30,13 @@ export const rememberSchema = z.object({
|
|
|
30
30
|
type: z.enum(['user', 'cli', 'hook', 'email', 'web', 'agent', 'file', 'api', 'tool_response']),
|
|
31
31
|
identifier: z.string(),
|
|
32
32
|
}).optional().describe('Source of this memory for trust scoring (agents should pass this)'),
|
|
33
|
+
sourceType: z.enum(['user', 'cli', 'hook', 'email', 'web', 'agent', 'file', 'api', 'tool_response']).optional()
|
|
34
|
+
.describe('Flat source type for integrations that cannot pass nested objects'),
|
|
35
|
+
sourceIdentifier: z.string().optional()
|
|
36
|
+
.describe('Flat source identifier for integrations that cannot pass nested objects'),
|
|
37
|
+
sessionId: z.string().optional().describe('Optional integration session identifier'),
|
|
38
|
+
agentId: z.string().optional().describe('Optional integration agent identifier'),
|
|
39
|
+
workspaceDir: z.string().optional().describe('Optional workspace/source path'),
|
|
33
40
|
});
|
|
34
41
|
/**
|
|
35
42
|
* Execute the remember tool
|
|
@@ -53,6 +60,14 @@ export async function executeRemember(input) {
|
|
|
53
60
|
}
|
|
54
61
|
// Resolve project (auto-detect if not provided)
|
|
55
62
|
const resolvedProject = resolveProject(input.project);
|
|
63
|
+
const derivedSource = input.source ?? (input.sourceType && input.sourceIdentifier
|
|
64
|
+
? { type: input.sourceType, identifier: input.sourceIdentifier }
|
|
65
|
+
: undefined);
|
|
66
|
+
const metadata = {
|
|
67
|
+
...(input.sessionId ? { sessionId: input.sessionId } : {}),
|
|
68
|
+
...(input.agentId ? { agentId: input.agentId } : {}),
|
|
69
|
+
...(input.workspaceDir ? { workspaceDir: input.workspaceDir } : {}),
|
|
70
|
+
};
|
|
56
71
|
// Map importance to salience override
|
|
57
72
|
let salienceOverride;
|
|
58
73
|
if (input.importance) {
|
|
@@ -96,7 +111,8 @@ export async function executeRemember(input) {
|
|
|
96
111
|
salience: salienceOverride,
|
|
97
112
|
scope: input.scope,
|
|
98
113
|
transferable: input.transferable,
|
|
99
|
-
|
|
114
|
+
metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
|
|
115
|
+
}, undefined, derivedSource ?? { type: 'cli', identifier: 'mcp' });
|
|
100
116
|
// Auto-detect and create relationships with existing memories
|
|
101
117
|
let linksCreated = 0;
|
|
102
118
|
try {
|
|
@@ -400,6 +400,9 @@ async function onSessionEnd(event) {
|
|
|
400
400
|
scope: "global",
|
|
401
401
|
importance: "high",
|
|
402
402
|
tags: "auto-extracted,openclaw-hook",
|
|
403
|
+
sourceType: "hook",
|
|
404
|
+
sourceIdentifier: "openclaw-session-end",
|
|
405
|
+
workspaceDir: context.workspaceDir || "",
|
|
403
406
|
});
|
|
404
407
|
if (result) {
|
|
405
408
|
saved++;
|
|
@@ -468,6 +471,9 @@ async function onSessionStop(event) {
|
|
|
468
471
|
scope: "global",
|
|
469
472
|
importance: "high",
|
|
470
473
|
tags: "auto-extracted,openclaw-hook,session-stop",
|
|
474
|
+
sourceType: "hook",
|
|
475
|
+
sourceIdentifier: "openclaw-session-stop",
|
|
476
|
+
workspaceDir: context.workspaceDir || "",
|
|
471
477
|
});
|
|
472
478
|
if (result) {
|
|
473
479
|
saved++;
|
|
@@ -611,6 +617,8 @@ async function checkAndSaveKeywordTrigger(messageText, event) {
|
|
|
611
617
|
scope: "global",
|
|
612
618
|
importance: matchedTrigger.importance,
|
|
613
619
|
tags: `keyword-trigger,openclaw-hook,trigger:${matchedTrigger.phrase.replace(/\s+/g, "-")}`,
|
|
620
|
+
sourceType: "hook",
|
|
621
|
+
sourceIdentifier: `openclaw-keyword:${matchedTrigger.phrase.replace(/\s+/g, "-")}`,
|
|
614
622
|
});
|
|
615
623
|
|
|
616
624
|
if (result) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shieldcortex",
|
|
3
|
-
"version": "3.1
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.2.1",
|
|
4
|
+
"description": "Trustworthy memory and security for AI agents. Recall debugging, review queue, OpenClaw session capture, and memory poisoning defence for Claude Code, OpenClaw, LangChain, and MCP agents.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"exports": {
|