@psiclawops/hypermem 0.1.0 → 0.5.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/ARCHITECTURE.md +4 -3
- package/README.md +457 -174
- package/dist/background-indexer.d.ts +19 -4
- package/dist/background-indexer.d.ts.map +1 -1
- package/dist/background-indexer.js +329 -17
- package/dist/cache.d.ts +110 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +495 -0
- package/dist/compaction-fence.d.ts +1 -1
- package/dist/compaction-fence.js +1 -1
- package/dist/compositor.d.ts +114 -27
- package/dist/compositor.d.ts.map +1 -1
- package/dist/compositor.js +1678 -229
- package/dist/content-type-classifier.d.ts +41 -0
- package/dist/content-type-classifier.d.ts.map +1 -0
- package/dist/content-type-classifier.js +181 -0
- package/dist/cross-agent.d.ts +5 -0
- package/dist/cross-agent.d.ts.map +1 -1
- package/dist/cross-agent.js +5 -0
- package/dist/db.d.ts +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +6 -2
- package/dist/desired-state-store.d.ts +1 -1
- package/dist/desired-state-store.d.ts.map +1 -1
- package/dist/desired-state-store.js +15 -5
- package/dist/doc-chunk-store.d.ts +26 -1
- package/dist/doc-chunk-store.d.ts.map +1 -1
- package/dist/doc-chunk-store.js +114 -1
- package/dist/doc-chunker.d.ts +1 -1
- package/dist/doc-chunker.js +1 -1
- package/dist/dreaming-promoter.d.ts +86 -0
- package/dist/dreaming-promoter.d.ts.map +1 -0
- package/dist/dreaming-promoter.js +381 -0
- package/dist/episode-store.d.ts +2 -1
- package/dist/episode-store.d.ts.map +1 -1
- package/dist/episode-store.js +4 -4
- package/dist/fact-store.d.ts +19 -1
- package/dist/fact-store.d.ts.map +1 -1
- package/dist/fact-store.js +64 -3
- package/dist/fleet-store.d.ts +1 -1
- package/dist/fleet-store.js +1 -1
- package/dist/fos-mod.d.ts +178 -0
- package/dist/fos-mod.d.ts.map +1 -0
- package/dist/fos-mod.js +416 -0
- package/dist/hybrid-retrieval.d.ts +5 -1
- package/dist/hybrid-retrieval.d.ts.map +1 -1
- package/dist/hybrid-retrieval.js +7 -3
- package/dist/image-eviction.d.ts +49 -0
- package/dist/image-eviction.d.ts.map +1 -0
- package/dist/image-eviction.js +251 -0
- package/dist/index.d.ts +50 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -43
- package/dist/keystone-scorer.d.ts +51 -0
- package/dist/keystone-scorer.d.ts.map +1 -0
- package/dist/keystone-scorer.js +52 -0
- package/dist/knowledge-graph.d.ts +1 -1
- package/dist/knowledge-graph.js +1 -1
- package/dist/knowledge-lint.d.ts +29 -0
- package/dist/knowledge-lint.d.ts.map +1 -0
- package/dist/knowledge-lint.js +116 -0
- package/dist/knowledge-store.d.ts +1 -1
- package/dist/knowledge-store.d.ts.map +1 -1
- package/dist/knowledge-store.js +8 -2
- package/dist/library-schema.d.ts +3 -3
- package/dist/library-schema.d.ts.map +1 -1
- package/dist/library-schema.js +324 -3
- package/dist/message-store.d.ts +15 -2
- package/dist/message-store.d.ts.map +1 -1
- package/dist/message-store.js +51 -1
- package/dist/metrics-dashboard.d.ts +114 -0
- package/dist/metrics-dashboard.d.ts.map +1 -0
- package/dist/metrics-dashboard.js +260 -0
- package/dist/obsidian-exporter.d.ts +57 -0
- package/dist/obsidian-exporter.d.ts.map +1 -0
- package/dist/obsidian-exporter.js +274 -0
- package/dist/obsidian-watcher.d.ts +147 -0
- package/dist/obsidian-watcher.d.ts.map +1 -0
- package/dist/obsidian-watcher.js +403 -0
- package/dist/open-domain.d.ts +46 -0
- package/dist/open-domain.d.ts.map +1 -0
- package/dist/open-domain.js +125 -0
- package/dist/preference-store.d.ts +1 -1
- package/dist/preference-store.js +1 -1
- package/dist/preservation-gate.d.ts +1 -1
- package/dist/preservation-gate.js +1 -1
- package/dist/proactive-pass.d.ts +63 -0
- package/dist/proactive-pass.d.ts.map +1 -0
- package/dist/proactive-pass.js +239 -0
- package/dist/profiles.d.ts +44 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +227 -0
- package/dist/provider-translator.d.ts +13 -3
- package/dist/provider-translator.d.ts.map +1 -1
- package/dist/provider-translator.js +63 -9
- package/dist/rate-limiter.d.ts +1 -1
- package/dist/rate-limiter.js +1 -1
- package/dist/repair-tool-pairs.d.ts +38 -0
- package/dist/repair-tool-pairs.d.ts.map +1 -0
- package/dist/repair-tool-pairs.js +138 -0
- package/dist/retrieval-policy.d.ts +51 -0
- package/dist/retrieval-policy.d.ts.map +1 -0
- package/dist/retrieval-policy.js +77 -0
- package/dist/schema.d.ts +2 -2
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +28 -2
- package/dist/secret-scanner.d.ts +1 -1
- package/dist/secret-scanner.js +1 -1
- package/dist/seed.d.ts +2 -2
- package/dist/seed.js +2 -2
- package/dist/session-flusher.d.ts +53 -0
- package/dist/session-flusher.d.ts.map +1 -0
- package/dist/session-flusher.js +69 -0
- package/dist/session-topic-map.d.ts +41 -0
- package/dist/session-topic-map.d.ts.map +1 -0
- package/dist/session-topic-map.js +77 -0
- package/dist/spawn-context.d.ts +54 -0
- package/dist/spawn-context.d.ts.map +1 -0
- package/dist/spawn-context.js +159 -0
- package/dist/system-store.d.ts +1 -1
- package/dist/system-store.js +1 -1
- package/dist/temporal-store.d.ts +80 -0
- package/dist/temporal-store.d.ts.map +1 -0
- package/dist/temporal-store.js +149 -0
- package/dist/topic-detector.d.ts +35 -0
- package/dist/topic-detector.d.ts.map +1 -0
- package/dist/topic-detector.js +249 -0
- package/dist/topic-store.d.ts +1 -1
- package/dist/topic-store.js +1 -1
- package/dist/topic-synthesizer.d.ts +51 -0
- package/dist/topic-synthesizer.d.ts.map +1 -0
- package/dist/topic-synthesizer.js +315 -0
- package/dist/trigger-registry.d.ts +63 -0
- package/dist/trigger-registry.d.ts.map +1 -0
- package/dist/trigger-registry.js +163 -0
- package/dist/types.d.ts +214 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/vector-store.d.ts +43 -5
- package/dist/vector-store.d.ts.map +1 -1
- package/dist/vector-store.js +189 -10
- package/dist/version.d.ts +34 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +34 -0
- package/dist/wiki-page-emitter.d.ts +65 -0
- package/dist/wiki-page-emitter.d.ts.map +1 -0
- package/dist/wiki-page-emitter.js +258 -0
- package/dist/work-store.d.ts +1 -1
- package/dist/work-store.js +1 -1
- package/package.json +15 -5
- package/dist/redis.d.ts +0 -188
- package/dist/redis.d.ts.map +0 -1
- package/dist/redis.js +0 -534
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Type Classifier
|
|
3
|
+
*
|
|
4
|
+
* Classifies message content by signal type: decision, spec, preference,
|
|
5
|
+
* skill, attribute, discussion, ack, or noise. Used by:
|
|
6
|
+
* - Keystone history slot (P2.1) for decisional weight scoring
|
|
7
|
+
* - Background indexer for extraction priority
|
|
8
|
+
* - Compaction for retention decisions
|
|
9
|
+
*
|
|
10
|
+
* Ported from ClawText content-type-classifier.ts — adapted for
|
|
11
|
+
* hypermem's NeutralMessage interface.
|
|
12
|
+
*
|
|
13
|
+
* No LLM dependency. Pure pattern matching + heuristics.
|
|
14
|
+
*/
|
|
15
|
+
export type ContentType = 'decision' | 'spec' | 'preference' | 'skill' | 'attribute' | 'discussion' | 'ack' | 'noise';
|
|
16
|
+
export interface ContentTypeResult {
|
|
17
|
+
type: ContentType;
|
|
18
|
+
confidence: number;
|
|
19
|
+
/** Approximate half-life in days. Infinity = never decays. 0 = discard immediately. */
|
|
20
|
+
halfLifeDays: number;
|
|
21
|
+
}
|
|
22
|
+
/** Signal value weight for context assembly prioritization (0–1). */
|
|
23
|
+
export declare const SIGNAL_WEIGHT: Record<ContentType, number>;
|
|
24
|
+
/**
|
|
25
|
+
* Classify a message's content by signal type.
|
|
26
|
+
*
|
|
27
|
+
* @param content - Raw text content of the message
|
|
28
|
+
* @returns Classification with type, confidence, and decay half-life
|
|
29
|
+
*/
|
|
30
|
+
export declare function classifyContentType(content: string): ContentTypeResult;
|
|
31
|
+
/**
|
|
32
|
+
* Convenience: classify and return the signal weight (0–1).
|
|
33
|
+
* Higher = more valuable for context retention.
|
|
34
|
+
*/
|
|
35
|
+
export declare function signalWeight(content: string): number;
|
|
36
|
+
/**
|
|
37
|
+
* Convenience: is this message worth keeping in context?
|
|
38
|
+
* Returns false for ack and noise.
|
|
39
|
+
*/
|
|
40
|
+
export declare function isSignalBearing(content: string): boolean;
|
|
41
|
+
//# sourceMappingURL=content-type-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-type-classifier.d.ts","sourceRoot":"","sources":["../src/content-type-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,MAAM,MAAM,WAAW,GACnB,UAAU,GACV,MAAM,GACN,YAAY,GACZ,OAAO,GACP,WAAW,GACX,YAAY,GACZ,KAAK,GACL,OAAO,CAAC;AAEZ,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qEAAqE;AACrE,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CASrD,CAAC;AAwGF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAmDtE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGxD"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Type Classifier
|
|
3
|
+
*
|
|
4
|
+
* Classifies message content by signal type: decision, spec, preference,
|
|
5
|
+
* skill, attribute, discussion, ack, or noise. Used by:
|
|
6
|
+
* - Keystone history slot (P2.1) for decisional weight scoring
|
|
7
|
+
* - Background indexer for extraction priority
|
|
8
|
+
* - Compaction for retention decisions
|
|
9
|
+
*
|
|
10
|
+
* Ported from ClawText content-type-classifier.ts — adapted for
|
|
11
|
+
* hypermem's NeutralMessage interface.
|
|
12
|
+
*
|
|
13
|
+
* No LLM dependency. Pure pattern matching + heuristics.
|
|
14
|
+
*/
|
|
15
|
+
/** Signal value weight for context assembly prioritization (0–1). */
|
|
16
|
+
export const SIGNAL_WEIGHT = {
|
|
17
|
+
decision: 1.0,
|
|
18
|
+
spec: 0.85,
|
|
19
|
+
preference: 0.8,
|
|
20
|
+
skill: 0.6,
|
|
21
|
+
attribute: 0.5,
|
|
22
|
+
discussion: 0.4,
|
|
23
|
+
ack: 0.0,
|
|
24
|
+
noise: 0.0,
|
|
25
|
+
};
|
|
26
|
+
// ─── Patterns ───────────────────────────────────────────────────
|
|
27
|
+
const DECISION_PATTERNS = [
|
|
28
|
+
/\bdecided\b/i,
|
|
29
|
+
/\bthe approach is\b/i,
|
|
30
|
+
/\bwe(?:'|')ll go with\b/i,
|
|
31
|
+
/\bthe plan is\b/i,
|
|
32
|
+
/\bapproved\b/i,
|
|
33
|
+
/\bconfirmed\b/i,
|
|
34
|
+
/\bshipped\b/i,
|
|
35
|
+
/\bmerged\b/i,
|
|
36
|
+
/\bdeployed\b/i,
|
|
37
|
+
/\b(?:decision|verdict|ruling|conclusion)\s*:/i,
|
|
38
|
+
/🟢\s*GREEN/,
|
|
39
|
+
/🔴\s*RED/,
|
|
40
|
+
/🟡\s*YELLOW/,
|
|
41
|
+
];
|
|
42
|
+
const SPEC_PATTERNS = [
|
|
43
|
+
/```[\s\S]*?```/m,
|
|
44
|
+
/\binterface\s+[A-Za-z0-9_]+/,
|
|
45
|
+
/\btype\s+[A-Za-z0-9_]+\s*=/,
|
|
46
|
+
/\barchitecture\b/i,
|
|
47
|
+
/\bapi\b/i,
|
|
48
|
+
/\bcontract\b/i,
|
|
49
|
+
/\bschema\b/i,
|
|
50
|
+
/\bmigration\b/i,
|
|
51
|
+
/\bspec\b/i,
|
|
52
|
+
];
|
|
53
|
+
const PREFERENCE_PATTERNS = [
|
|
54
|
+
/\b(?:i|we)\s+(?:prefer|like|love|favor)\b/i,
|
|
55
|
+
/\bmy\s+preferred\b/i,
|
|
56
|
+
/\bpreference\b/i,
|
|
57
|
+
/\bi(?:'|')d\s+rather\b/i,
|
|
58
|
+
/\bdefault\s+to\b/i,
|
|
59
|
+
/\b(?:always|usually)\s+use\b/i,
|
|
60
|
+
];
|
|
61
|
+
const SKILL_PATTERNS = [
|
|
62
|
+
/\b(?:i|we)\s+(?:know|understand|can|able to)\b/i,
|
|
63
|
+
/\b(?:experienced|proficient|expert)\s+with\b/i,
|
|
64
|
+
/\b(?:skill|strength|competenc(?:y|ies))\b/i,
|
|
65
|
+
/\b(?:familiar|comfortable)\s+with\b/i,
|
|
66
|
+
];
|
|
67
|
+
const ATTRIBUTE_PATTERNS = [
|
|
68
|
+
/\b(?:i|we)\s+(?:am|are)\b/i,
|
|
69
|
+
/\bmy\s+(?:role|timezone|location|name|pronouns|schedule|availability)\b/i,
|
|
70
|
+
/\b(?:timezone|pronouns|role|availability|schedule)\s*:/i,
|
|
71
|
+
/\b(?:working\s+hours|hard\s+stop|deadline)\b/i,
|
|
72
|
+
];
|
|
73
|
+
const NOISE_PATTERNS = [
|
|
74
|
+
/\bheartbeat\b/i,
|
|
75
|
+
/\braw log\b/i,
|
|
76
|
+
/^\[[A-Z_]+\]/m,
|
|
77
|
+
/\b(system|daemon|telemetry)\s+message\b/i,
|
|
78
|
+
/\btraceback\b/i,
|
|
79
|
+
/\bstdout\b/i,
|
|
80
|
+
/\bstderr\b/i,
|
|
81
|
+
/^NO_REPLY$/,
|
|
82
|
+
/^HEARTBEAT_OK$/,
|
|
83
|
+
];
|
|
84
|
+
const ACK_PHRASES = new Set([
|
|
85
|
+
'ok',
|
|
86
|
+
'okay',
|
|
87
|
+
'yes',
|
|
88
|
+
'sounds good',
|
|
89
|
+
'lets do it',
|
|
90
|
+
"let's do it",
|
|
91
|
+
'perfect',
|
|
92
|
+
'nice',
|
|
93
|
+
'got it',
|
|
94
|
+
'acknowledged',
|
|
95
|
+
'roger',
|
|
96
|
+
'done',
|
|
97
|
+
'thanks',
|
|
98
|
+
'thank you',
|
|
99
|
+
'ty',
|
|
100
|
+
'lgtm',
|
|
101
|
+
'👍',
|
|
102
|
+
]);
|
|
103
|
+
const HALF_LIFE = {
|
|
104
|
+
decision: Number.POSITIVE_INFINITY,
|
|
105
|
+
spec: 180,
|
|
106
|
+
preference: 180,
|
|
107
|
+
skill: 120,
|
|
108
|
+
attribute: 30,
|
|
109
|
+
discussion: 60,
|
|
110
|
+
ack: 0,
|
|
111
|
+
noise: 0,
|
|
112
|
+
};
|
|
113
|
+
// ─── Classifier ─────────────────────────────────────────────────
|
|
114
|
+
function normalized(content) {
|
|
115
|
+
return content.trim().toLowerCase().replace(/[.!?]+$/g, '');
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Classify a message's content by signal type.
|
|
119
|
+
*
|
|
120
|
+
* @param content - Raw text content of the message
|
|
121
|
+
* @returns Classification with type, confidence, and decay half-life
|
|
122
|
+
*/
|
|
123
|
+
export function classifyContentType(content) {
|
|
124
|
+
const raw = String(content ?? '');
|
|
125
|
+
const body = raw.trim();
|
|
126
|
+
const lc = normalized(body);
|
|
127
|
+
if (!body) {
|
|
128
|
+
return { type: 'noise', confidence: 0.95, halfLifeDays: HALF_LIFE.noise };
|
|
129
|
+
}
|
|
130
|
+
// Noise first — fast path for system/control messages
|
|
131
|
+
if (NOISE_PATTERNS.some((rx) => rx.test(body))) {
|
|
132
|
+
return { type: 'noise', confidence: 0.85, halfLifeDays: HALF_LIFE.noise };
|
|
133
|
+
}
|
|
134
|
+
// Short acks — "ok", "sounds good", etc.
|
|
135
|
+
if (body.length < 40 && ACK_PHRASES.has(lc)) {
|
|
136
|
+
return { type: 'ack', confidence: 0.95, halfLifeDays: HALF_LIFE.ack };
|
|
137
|
+
}
|
|
138
|
+
// Decisions — highest value signal
|
|
139
|
+
if (DECISION_PATTERNS.some((rx) => rx.test(body))) {
|
|
140
|
+
return { type: 'decision', confidence: 0.9, halfLifeDays: HALF_LIFE.decision };
|
|
141
|
+
}
|
|
142
|
+
// Specs — code blocks, type definitions, architecture
|
|
143
|
+
if (SPEC_PATTERNS.some((rx) => rx.test(body))) {
|
|
144
|
+
return { type: 'spec', confidence: 0.82, halfLifeDays: HALF_LIFE.spec };
|
|
145
|
+
}
|
|
146
|
+
// Preferences — user likes, defaults
|
|
147
|
+
if (PREFERENCE_PATTERNS.some((rx) => rx.test(body))) {
|
|
148
|
+
return { type: 'preference', confidence: 0.8, halfLifeDays: HALF_LIFE.preference };
|
|
149
|
+
}
|
|
150
|
+
// Skills — capabilities, knowledge
|
|
151
|
+
if (SKILL_PATTERNS.some((rx) => rx.test(body))) {
|
|
152
|
+
return { type: 'skill', confidence: 0.78, halfLifeDays: HALF_LIFE.skill };
|
|
153
|
+
}
|
|
154
|
+
// Attributes — identity, schedule, role
|
|
155
|
+
if (ATTRIBUTE_PATTERNS.some((rx) => rx.test(body))) {
|
|
156
|
+
return { type: 'attribute', confidence: 0.72, halfLifeDays: HALF_LIFE.attribute };
|
|
157
|
+
}
|
|
158
|
+
// Questions and exploratory discussion
|
|
159
|
+
if (/\?$/.test(body) || /\b(why|how|maybe|could|should|explore|question)\b/i.test(body)) {
|
|
160
|
+
return { type: 'discussion', confidence: 0.75, halfLifeDays: HALF_LIFE.discussion };
|
|
161
|
+
}
|
|
162
|
+
// Default: generic discussion
|
|
163
|
+
return { type: 'discussion', confidence: 0.6, halfLifeDays: HALF_LIFE.discussion };
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Convenience: classify and return the signal weight (0–1).
|
|
167
|
+
* Higher = more valuable for context retention.
|
|
168
|
+
*/
|
|
169
|
+
export function signalWeight(content) {
|
|
170
|
+
const { type } = classifyContentType(content);
|
|
171
|
+
return SIGNAL_WEIGHT[type];
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Convenience: is this message worth keeping in context?
|
|
175
|
+
* Returns false for ack and noise.
|
|
176
|
+
*/
|
|
177
|
+
export function isSignalBearing(content) {
|
|
178
|
+
const { type } = classifyContentType(content);
|
|
179
|
+
return type !== 'ack' && type !== 'noise';
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=content-type-classifier.js.map
|
package/dist/cross-agent.d.ts
CHANGED
|
@@ -49,6 +49,11 @@ export declare function visibilityFilter(requester: AgentIdentity, targetAgentId
|
|
|
49
49
|
* in the hardcoded registry (not yet seeded to the DB) are preserved as fallback.
|
|
50
50
|
*/
|
|
51
51
|
export declare function buildOrgRegistryFromDb(libraryDb: DatabaseSync): OrgRegistry;
|
|
52
|
+
/**
|
|
53
|
+
* Alias for buildOrgRegistryFromDb — preferred name per P1.4 spec.
|
|
54
|
+
* Both names are exported for backward compatibility.
|
|
55
|
+
*/
|
|
56
|
+
export declare const loadOrgRegistryFromDb: typeof buildOrgRegistryFromDb;
|
|
52
57
|
/**
|
|
53
58
|
* Query another agent's memory with visibility-scoped access.
|
|
54
59
|
* All queries go to the central library DB — no per-agent DB needed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cross-agent.d.ts","sourceRoot":"","sources":["../src/cross-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK1C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACvC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,CA2BhD;AAID,wBAAgB,SAAS,CACvB,SAAS,EAAE,aAAa,EACxB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,WAAW,GACpB,OAAO,CAaT;AASD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,aAAa,EACxB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,WAAW,GACpB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAE,CA6B3F;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,YAAY,GAAG,WAAW,CAgD3E;
|
|
1
|
+
{"version":3,"file":"cross-agent.d.ts","sourceRoot":"","sources":["../src/cross-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK1C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACvC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,CA2BhD;AAID,wBAAgB,SAAS,CACvB,SAAS,EAAE,aAAa,EACxB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,WAAW,GACpB,OAAO,CAaT;AASD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,aAAa,EACxB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,WAAW,GACpB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAE,CA6B3F;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,YAAY,GAAG,WAAW,CAgD3E;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,+BAAyB,CAAC;AAI5D;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,WAAW,GACpB,OAAO,EAAE,CAgCX"}
|
package/dist/cross-agent.js
CHANGED
|
@@ -156,6 +156,11 @@ export function buildOrgRegistryFromDb(libraryDb) {
|
|
|
156
156
|
return fallback;
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Alias for buildOrgRegistryFromDb — preferred name per P1.4 spec.
|
|
161
|
+
* Both names are exported for backward compatibility.
|
|
162
|
+
*/
|
|
163
|
+
export const loadOrgRegistryFromDb = buildOrgRegistryFromDb;
|
|
159
164
|
// ─── Cross-Agent Query Engine ────────────────────────────────────
|
|
160
165
|
/**
|
|
161
166
|
* Query another agent's memory with visibility-scoped access.
|
package/dist/db.d.ts
CHANGED
package/dist/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAqC3C,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB;AAQD;;;GAGG;AACH,iBAAS,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAI9C;AAED;;;GAGG;AACH,iBAAS,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAIvD;AAmBD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,CAAC;AAEpD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmC;IAC9D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmC;IAC7D,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,aAAa,CAAwB;IAE7C,6EAA6E;IAC7E,IAAI,YAAY,IAAI,OAAO,CAE1B;gBAEW,MAAM,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAKnD;;;OAGG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY;IAiB3C;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IA0BjD;;;;;;OAMG;IACH,iBAAiB,IAAI,YAAY,GAAG,IAAI;IAsBxC;;;OAGG;IACH,YAAY,IAAI,YAAY;IAa5B;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY;IAIzC;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAClC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GAAG,IAAI;IA2BR;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA+BxB;;OAEG;IACH,UAAU,IAAI,MAAM,EAAE;IAWtB;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAKpC;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAQzC;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAWzC;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IA8C/C;;;;;;;OAOG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QACnC,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG;QAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IA4BzE;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY;IAc9D;;OAEG;IACH,KAAK,IAAI,IAAI;CAgBd"}
|
package/dist/db.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* hypermem Database Manager
|
|
3
3
|
*
|
|
4
4
|
* Three-file architecture per agent:
|
|
5
5
|
* agents/{agentId}/messages.db — write-heavy conversation log (rotatable)
|
|
@@ -14,6 +14,7 @@ import os from 'node:os';
|
|
|
14
14
|
import path from 'node:path';
|
|
15
15
|
import { migrate } from './schema.js';
|
|
16
16
|
import { migrateLibrary } from './library-schema.js';
|
|
17
|
+
import { ENGINE_VERSION } from './version.js';
|
|
17
18
|
// sqlite-vec extension loading — optional dependency
|
|
18
19
|
import { createRequire } from 'node:module';
|
|
19
20
|
let sqliteVecAvailable = null;
|
|
@@ -174,7 +175,7 @@ export class DatabaseManager {
|
|
|
174
175
|
const dbPath = path.join(this.dataDir, 'library.db');
|
|
175
176
|
this.libraryDb = new DatabaseSync(dbPath);
|
|
176
177
|
applyPragmas(this.libraryDb);
|
|
177
|
-
migrateLibrary(this.libraryDb);
|
|
178
|
+
migrateLibrary(this.libraryDb, ENGINE_VERSION);
|
|
178
179
|
return this.libraryDb;
|
|
179
180
|
}
|
|
180
181
|
// ── Legacy compatibility ──────────────────────────────────────
|
|
@@ -232,7 +233,10 @@ export class DatabaseManager {
|
|
|
232
233
|
const agentsDir = path.join(this.dataDir, 'agents');
|
|
233
234
|
if (!fs.existsSync(agentsDir))
|
|
234
235
|
return [];
|
|
236
|
+
const VALID_AGENT_ID = /^[a-z0-9][a-z0-9-]*$/;
|
|
235
237
|
return fs.readdirSync(agentsDir).filter(f => {
|
|
238
|
+
if (!VALID_AGENT_ID.test(f))
|
|
239
|
+
return false;
|
|
236
240
|
const stat = fs.statSync(path.join(agentsDir, f));
|
|
237
241
|
return stat.isDirectory();
|
|
238
242
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"desired-state-store.d.ts","sourceRoot":"","sources":["../src/desired-state-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMhD,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"desired-state-store.d.ts","sourceRoot":"","sources":["../src/desired-state-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMhD,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAyCD,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,YAAY;IAE7C;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;QAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,iBAAiB;IA8DrB;;;OAGG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,WAAW;IA6BnF;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;IAQhG;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI;IAQtE;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE;IAQnD;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IASxD;;OAEG;IACH,UAAU,IAAI,iBAAiB,EAAE;IAQjC;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE;IAQtD;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,WAAW,EAAE;IAgBlF;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAgB3E;;OAEG;IACH,eAAe,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;CAelG"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* hypermem Agent Desired State Store
|
|
3
3
|
*
|
|
4
4
|
* Stores intended configuration for each agent and tracks drift.
|
|
5
5
|
* Enables fleet-wide config visibility and enforcement.
|
|
@@ -16,12 +16,22 @@
|
|
|
16
16
|
function nowIso() {
|
|
17
17
|
return new Date().toISOString();
|
|
18
18
|
}
|
|
19
|
+
function tryParseJson(val) {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(val);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Value is a bare string (e.g. model names like "copilot-local/claude-sonnet-4.6")
|
|
25
|
+
// stored without JSON quoting — return as-is.
|
|
26
|
+
return val;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
19
29
|
function parseEntry(row) {
|
|
20
30
|
return {
|
|
21
31
|
agentId: row.agent_id,
|
|
22
32
|
configKey: row.config_key,
|
|
23
|
-
desiredValue: row.desired_value ?
|
|
24
|
-
actualValue: row.actual_value ?
|
|
33
|
+
desiredValue: row.desired_value ? tryParseJson(row.desired_value) : null,
|
|
34
|
+
actualValue: row.actual_value ? tryParseJson(row.actual_value) : null,
|
|
25
35
|
source: row.source,
|
|
26
36
|
setBy: row.set_by || null,
|
|
27
37
|
driftStatus: row.drift_status || 'unknown',
|
|
@@ -37,8 +47,8 @@ function parseEvent(row) {
|
|
|
37
47
|
agentId: row.agent_id,
|
|
38
48
|
configKey: row.config_key,
|
|
39
49
|
eventType: row.event_type,
|
|
40
|
-
oldValue: row.old_value ?
|
|
41
|
-
newValue: row.new_value ?
|
|
50
|
+
oldValue: row.old_value ? tryParseJson(row.old_value) : null,
|
|
51
|
+
newValue: row.new_value ? tryParseJson(row.new_value) : null,
|
|
42
52
|
changedBy: row.changed_by || null,
|
|
43
53
|
createdAt: row.created_at,
|
|
44
54
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* hypermem Document Chunk Store
|
|
3
3
|
*
|
|
4
4
|
* Manages doc_chunks in library.db:
|
|
5
5
|
* - Atomic re-indexing by source hash (no stale/fresh coexistence)
|
|
@@ -101,6 +101,31 @@ export declare class DocChunkStore {
|
|
|
101
101
|
* Delete all chunks for a specific source file.
|
|
102
102
|
*/
|
|
103
103
|
deleteSource(sourcePath: string, collection: string): number;
|
|
104
|
+
/**
|
|
105
|
+
* Index simple string chunks with an optional session key (for ephemeral spawn context).
|
|
106
|
+
*
|
|
107
|
+
* Unlike indexChunks() which works with DocChunk objects and hash-based dedup,
|
|
108
|
+
* this method is designed for ad-hoc session-scoped content: it always inserts fresh
|
|
109
|
+
* rows tagged with the sessionKey, without hash-based skip logic.
|
|
110
|
+
*
|
|
111
|
+
* Chunks stored with a sessionKey are ephemeral — use clearSessionChunks() to remove them.
|
|
112
|
+
*/
|
|
113
|
+
indexDocChunks(agentId: string, source: string, chunks: string[], options?: {
|
|
114
|
+
sessionKey?: string;
|
|
115
|
+
}): void;
|
|
116
|
+
/**
|
|
117
|
+
* Query doc chunks by agentId+query string, with optional session key scoping.
|
|
118
|
+
* When sessionKey is provided, only chunks tagged with that session key are returned.
|
|
119
|
+
*/
|
|
120
|
+
queryDocChunks(agentId: string, query: string, options?: {
|
|
121
|
+
sessionKey?: string;
|
|
122
|
+
limit?: number;
|
|
123
|
+
}): DocChunkRow[];
|
|
124
|
+
/**
|
|
125
|
+
* Delete all doc chunks associated with a specific session key.
|
|
126
|
+
* Call this when a spawn session is complete to release ephemeral storage.
|
|
127
|
+
*/
|
|
128
|
+
clearSessionChunks(sessionKey: string): number;
|
|
104
129
|
/**
|
|
105
130
|
* Get chunk stats: count per collection.
|
|
106
131
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doc-chunk-store.d.ts","sourceRoot":"","sources":["../src/doc-chunk-store.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"doc-chunk-store.d.ts","sourceRoot":"","sources":["../src/doc-chunk-store.ts"],"names":[],"mappings":"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"}
|
package/dist/doc-chunk-store.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* hypermem Document Chunk Store
|
|
3
3
|
*
|
|
4
4
|
* Manages doc_chunks in library.db:
|
|
5
5
|
* - Atomic re-indexing by source hash (no stale/fresh coexistence)
|
|
@@ -236,6 +236,119 @@ export class DocChunkStore {
|
|
|
236
236
|
throw err;
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Index simple string chunks with an optional session key (for ephemeral spawn context).
|
|
241
|
+
*
|
|
242
|
+
* Unlike indexChunks() which works with DocChunk objects and hash-based dedup,
|
|
243
|
+
* this method is designed for ad-hoc session-scoped content: it always inserts fresh
|
|
244
|
+
* rows tagged with the sessionKey, without hash-based skip logic.
|
|
245
|
+
*
|
|
246
|
+
* Chunks stored with a sessionKey are ephemeral — use clearSessionChunks() to remove them.
|
|
247
|
+
*/
|
|
248
|
+
indexDocChunks(agentId, source, chunks, options) {
|
|
249
|
+
if (chunks.length === 0)
|
|
250
|
+
return;
|
|
251
|
+
const now = new Date().toISOString();
|
|
252
|
+
const sessionKey = options?.sessionKey ?? null;
|
|
253
|
+
// Use a stable collection name derived from source path
|
|
254
|
+
const collection = `spawn/${agentId}`;
|
|
255
|
+
try {
|
|
256
|
+
this.db.exec('BEGIN');
|
|
257
|
+
const insert = this.db.prepare(`
|
|
258
|
+
INSERT INTO doc_chunks
|
|
259
|
+
(id, collection, section_path, depth, content, token_estimate,
|
|
260
|
+
source_hash, source_path, scope, tier, agent_id, parent_path,
|
|
261
|
+
session_key, created_at, updated_at)
|
|
262
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
263
|
+
`);
|
|
264
|
+
chunks.forEach((chunkContent, idx) => {
|
|
265
|
+
const id = `spawn:${agentId}:${sessionKey ?? 'none'}:${source}:${idx}:${Date.now()}`;
|
|
266
|
+
const tokenEstimate = Math.ceil(chunkContent.length / 4);
|
|
267
|
+
insert.run(id, collection, `${source}#chunk-${idx}`, 2, chunkContent, tokenEstimate, `spawn-${Date.now()}-${idx}`, // non-deduped hash
|
|
268
|
+
source, 'per-agent', null, agentId, null, sessionKey, now, now);
|
|
269
|
+
});
|
|
270
|
+
this.db.exec('COMMIT');
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
try {
|
|
274
|
+
this.db.exec('ROLLBACK');
|
|
275
|
+
}
|
|
276
|
+
catch { /* ignore */ }
|
|
277
|
+
console.warn('[hypermem:doc-chunk-store] indexDocChunks failed:', err.message);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Query doc chunks by agentId+query string, with optional session key scoping.
|
|
282
|
+
* When sessionKey is provided, only chunks tagged with that session key are returned.
|
|
283
|
+
*/
|
|
284
|
+
queryDocChunks(agentId, query, options) {
|
|
285
|
+
const limit = options?.limit ?? 10;
|
|
286
|
+
const sessionKey = options?.sessionKey;
|
|
287
|
+
const collection = `spawn/${agentId}`;
|
|
288
|
+
try {
|
|
289
|
+
if (query.trim() && query.trim().length >= 3) {
|
|
290
|
+
// FTS5 keyword search
|
|
291
|
+
let sql = `
|
|
292
|
+
SELECT c.id, c.collection, c.section_path, c.depth, c.content, c.token_estimate,
|
|
293
|
+
c.source_hash, c.source_path, c.scope, c.tier, c.agent_id, c.parent_path,
|
|
294
|
+
c.created_at, c.updated_at
|
|
295
|
+
FROM (
|
|
296
|
+
SELECT rowid, rank FROM doc_chunks_fts WHERE doc_chunks_fts MATCH ? ORDER BY rank LIMIT ?
|
|
297
|
+
) sub
|
|
298
|
+
JOIN doc_chunks c ON c.rowid = sub.rowid
|
|
299
|
+
WHERE c.collection = ?
|
|
300
|
+
`;
|
|
301
|
+
const params = [query, limit * 3, collection];
|
|
302
|
+
if (sessionKey !== undefined) {
|
|
303
|
+
sql += ' AND c.session_key = ?';
|
|
304
|
+
params.push(sessionKey);
|
|
305
|
+
}
|
|
306
|
+
sql += ' ORDER BY sub.rank LIMIT ?';
|
|
307
|
+
params.push(limit);
|
|
308
|
+
const rows = this.db.prepare(sql).all(...params);
|
|
309
|
+
return rows.map(this.mapRow);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
// Fallback: return most recent chunks for this session
|
|
313
|
+
let sql = `
|
|
314
|
+
SELECT id, collection, section_path, depth, content, token_estimate,
|
|
315
|
+
source_hash, source_path, scope, tier, agent_id, parent_path,
|
|
316
|
+
created_at, updated_at
|
|
317
|
+
FROM doc_chunks
|
|
318
|
+
WHERE collection = ?
|
|
319
|
+
`;
|
|
320
|
+
const params = [collection];
|
|
321
|
+
if (sessionKey !== undefined) {
|
|
322
|
+
sql += ' AND session_key = ?';
|
|
323
|
+
params.push(sessionKey);
|
|
324
|
+
}
|
|
325
|
+
sql += ' ORDER BY created_at DESC LIMIT ?';
|
|
326
|
+
params.push(limit);
|
|
327
|
+
const rows = this.db.prepare(sql).all(...params);
|
|
328
|
+
return rows.map(this.mapRow);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
catch (err) {
|
|
332
|
+
console.warn('[hypermem:doc-chunk-store] queryDocChunks failed:', err.message);
|
|
333
|
+
return [];
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Delete all doc chunks associated with a specific session key.
|
|
338
|
+
* Call this when a spawn session is complete to release ephemeral storage.
|
|
339
|
+
*/
|
|
340
|
+
clearSessionChunks(sessionKey) {
|
|
341
|
+
try {
|
|
342
|
+
const result = this.db
|
|
343
|
+
.prepare('DELETE FROM doc_chunks WHERE session_key = ?')
|
|
344
|
+
.run(sessionKey);
|
|
345
|
+
return result.changes;
|
|
346
|
+
}
|
|
347
|
+
catch (err) {
|
|
348
|
+
console.warn('[hypermem:doc-chunk-store] clearSessionChunks failed:', err.message);
|
|
349
|
+
return 0;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
239
352
|
/**
|
|
240
353
|
* Get chunk stats: count per collection.
|
|
241
354
|
*/
|
package/dist/doc-chunker.d.ts
CHANGED
package/dist/doc-chunker.js
CHANGED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dreaming-promoter.ts
|
|
3
|
+
*
|
|
4
|
+
* hypermem-native dreaming promotion pass.
|
|
5
|
+
*
|
|
6
|
+
* Unlike the stock memory-core dreaming feature (which appends raw content to
|
|
7
|
+
* MEMORY.md), this promoter generates pointer-format entries that match the
|
|
8
|
+
* council's MEMORY.md convention:
|
|
9
|
+
*
|
|
10
|
+
* - **{domain} — {title}:** {summary}
|
|
11
|
+
* → `memory_search("{query}")`
|
|
12
|
+
*
|
|
13
|
+
* Scoring uses confidence, decay, recency, and domain cluster weight.
|
|
14
|
+
* Dedup prevents re-promoting topics already covered by existing pointers.
|
|
15
|
+
*
|
|
16
|
+
* Dry-run mode returns what would be written without modifying any files.
|
|
17
|
+
*/
|
|
18
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
19
|
+
export interface DreamerConfig {
|
|
20
|
+
/** Enable the promotion pass. Default: false */
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
/** Minimum composite score for promotion. Default: 0.70 */
|
|
23
|
+
minScore: number;
|
|
24
|
+
/** Minimum confidence threshold (pre-scoring). Default: 0.70 */
|
|
25
|
+
minConfidence: number;
|
|
26
|
+
/** Max new pointer entries to write per agent per run. Default: 5 */
|
|
27
|
+
maxPromotionsPerRun: number;
|
|
28
|
+
/** How often to run: every N indexer ticks. Default: 12 (~1hr at 5min interval) */
|
|
29
|
+
tickInterval: number;
|
|
30
|
+
/** Preview what would be promoted without writing. Default: false */
|
|
31
|
+
dryRun: boolean;
|
|
32
|
+
/** Recency half-life in days (score decays to 0.5 at this age). Default: 14 */
|
|
33
|
+
recencyHalfLifeDays: number;
|
|
34
|
+
/** Max age in days to consider a fact. Default: 90 */
|
|
35
|
+
maxAgeDays: number;
|
|
36
|
+
}
|
|
37
|
+
export declare const DEFAULT_DREAMER_CONFIG: DreamerConfig;
|
|
38
|
+
export interface FactCandidate {
|
|
39
|
+
id: number;
|
|
40
|
+
agentId: string;
|
|
41
|
+
domain: string;
|
|
42
|
+
content: string;
|
|
43
|
+
confidence: number;
|
|
44
|
+
decayScore: number;
|
|
45
|
+
ageDays: number;
|
|
46
|
+
score: number;
|
|
47
|
+
}
|
|
48
|
+
export interface PromotionEntry {
|
|
49
|
+
factId: number;
|
|
50
|
+
domain: string;
|
|
51
|
+
pointer: string;
|
|
52
|
+
title: string;
|
|
53
|
+
summary: string;
|
|
54
|
+
query: string;
|
|
55
|
+
score: number;
|
|
56
|
+
dryRun: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface DreamerResult {
|
|
59
|
+
agentId: string;
|
|
60
|
+
candidates: number;
|
|
61
|
+
promoted: number;
|
|
62
|
+
skippedDuplicate: number;
|
|
63
|
+
skippedThreshold: number;
|
|
64
|
+
entries: PromotionEntry[];
|
|
65
|
+
memoryPath: string | null;
|
|
66
|
+
dryRun: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the workspace directory for an agent.
|
|
70
|
+
* Council agents live at ~/.openclaw/workspace-council/{agentId}/
|
|
71
|
+
* Other agents at ~/.openclaw/workspace/{agentId}/
|
|
72
|
+
*/
|
|
73
|
+
export declare function resolveAgentWorkspacePath(agentId: string): Promise<string | null>;
|
|
74
|
+
/**
|
|
75
|
+
* Run the dreaming promotion pass for a single agent.
|
|
76
|
+
*
|
|
77
|
+
* Reads qualified facts from library.db, scores them, deduplicates against
|
|
78
|
+
* existing MEMORY.md pointers, and writes new pointer entries.
|
|
79
|
+
*/
|
|
80
|
+
export declare function runDreamingPromoter(agentId: string, libraryDb: DatabaseSync, config?: Partial<DreamerConfig>): Promise<DreamerResult>;
|
|
81
|
+
/**
|
|
82
|
+
* Run the dreaming promotion pass for all agents in a fleet.
|
|
83
|
+
* Called from the BackgroundIndexer on every N ticks.
|
|
84
|
+
*/
|
|
85
|
+
export declare function runDreamingPassForFleet(agentIds: string[], libraryDb: DatabaseSync, config?: Partial<DreamerConfig>): Promise<DreamerResult[]>;
|
|
86
|
+
//# sourceMappingURL=dreaming-promoter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dreaming-promoter.d.ts","sourceRoot":"","sources":["../src/dreaming-promoter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB,+EAA+E;IAC/E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,sBAAsB,EAAE,aASpC,CAAC;AAIF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;CACjB;AAID;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBvF;AA2ND;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,YAAY,EACvB,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,aAAa,CAAC,CAgJxB;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAAE,EAClB,SAAS,EAAE,YAAY,EACvB,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,GAClC,OAAO,CAAC,aAAa,EAAE,CAAC,CAa1B"}
|