@yeaft/webchat-agent 0.1.665 → 0.1.666
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/connection/message-router.js +1 -24
- package/package.json +1 -1
- package/unify/cli.js +5 -84
- package/unify/engine.js +22 -130
- package/unify/features/summary.js +15 -98
- package/unify/index.js +0 -2
- package/unify/memory/consolidate.js +10 -125
- package/unify/prompts.js +3 -19
- package/unify/session.js +1 -21
- package/unify/stop-hooks.js +8 -44
- package/unify/tools/index.js +0 -11
- package/unify/web-bridge.js +0 -98
- package/unify/memory/dream-shard.js +0 -722
- package/unify/memory/extract.js +0 -101
- package/unify/memory/layout.js +0 -358
- package/unify/memory/schema.js +0 -166
- package/unify/memory/shard-store.js +0 -373
- package/unify/memory/store.js +0 -578
- package/unify/memory/types.js +0 -139
- package/unify/memory/user-memory-store.js +0 -452
- package/unify/tools/memory-query.js +0 -134
- package/unify/tools/memory-read.js +0 -90
- package/unify/tools/memory-search.js +0 -140
- package/unify/tools/memory-trace.js +0 -135
- package/unify/tools/memory-write.js +0 -113
- package/unify/user-memory.js +0 -107
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* consolidate.js —
|
|
2
|
+
* consolidate.js — Hot-window budget partitioning utilities.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* 2. Extract memory entries → write to entries/ ("long-term memory")
|
|
4
|
+
* Reduced surface (PR-B rip): the legacy LLM-driven consolidate() pipeline
|
|
5
|
+
* (compact summary + entries-store extraction) has been retired. The only
|
|
6
|
+
* survivors are the pure functions used by the compact orchestrator:
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
8
|
+
* - shouldConsolidate(store, budget) — decide when to compact
|
|
9
|
+
* - partitionMessages(messages, budget) — split hot messages into
|
|
10
|
+
* toArchive / toKeep based on token budget
|
|
12
11
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Memory extraction is now owned by Dream V2 (per-group diff -> triage ->
|
|
13
|
+
* merge by target scope -> apply via segment-store + summary-store).
|
|
14
|
+
* Conversation summarisation lives in compact/orchestrator.js's hooks.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { extractMemories } from './extract.js';
|
|
18
|
-
import { pickEffort } from '../effort.js';
|
|
19
|
-
|
|
20
17
|
// ─── Constants ──────────────────────────────────────────────────
|
|
21
18
|
|
|
22
19
|
/** Default MESSAGE_TOKEN_BUDGET (context * 4%, default ~8192). */
|
|
@@ -28,8 +25,6 @@ export const COMPACT_KEEP_RATIO = 0.4;
|
|
|
28
25
|
/** Minimum messages to keep hot (newest). */
|
|
29
26
|
const MIN_KEEP_MESSAGES = 3;
|
|
30
27
|
|
|
31
|
-
// ─── Consolidate ────────────────────────────────────────────────
|
|
32
|
-
|
|
33
28
|
/**
|
|
34
29
|
* Check if consolidation should be triggered.
|
|
35
30
|
*
|
|
@@ -81,113 +76,3 @@ export function partitionMessages(messages, budget = DEFAULT_MESSAGE_TOKEN_BUDGE
|
|
|
81
76
|
toKeep: messages.slice(keepStart),
|
|
82
77
|
};
|
|
83
78
|
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Generate a compact summary of messages.
|
|
87
|
-
*
|
|
88
|
-
* @param {object[]} messages — messages to summarize
|
|
89
|
-
* @param {object} adapter — LLM adapter with .call()
|
|
90
|
-
* @param {object} config — { model }
|
|
91
|
-
* @returns {Promise<string>} — compact summary text
|
|
92
|
-
*/
|
|
93
|
-
async function generateSummary(messages, adapter, config) {
|
|
94
|
-
const conversation = messages.map(m => {
|
|
95
|
-
const prefix = m.role === 'user' ? 'User' : m.role === 'assistant' ? 'Assistant' : m.role;
|
|
96
|
-
return `[${prefix}]: ${(m.content || '').slice(0, 500)}`;
|
|
97
|
-
}).join('\n\n');
|
|
98
|
-
|
|
99
|
-
const system = 'You are a conversation summarizer. Summarize the conversation concisely in 2-3 paragraphs, preserving key decisions, facts, and context. Write in the same language as the conversation.';
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
const result = await adapter.call({
|
|
103
|
-
model: config.model,
|
|
104
|
-
system,
|
|
105
|
-
messages: [{ role: 'user', content: `Summarize this conversation:\n\n${conversation}` }],
|
|
106
|
-
maxTokens: 1024,
|
|
107
|
-
// task-327c: consolidate is a high-complexity side-query; flag as
|
|
108
|
-
// 'max' effort so supported models use extended thinking / reasoning.
|
|
109
|
-
// Router/adapter silently drops the param for models that don't
|
|
110
|
-
// support thinking, or when UNIFY_THINKING_V1 is off.
|
|
111
|
-
effort: pickEffort({ scenario: 'consolidate' }),
|
|
112
|
-
});
|
|
113
|
-
return result.text.trim();
|
|
114
|
-
} catch {
|
|
115
|
-
// Fallback: simple concatenation of first/last messages
|
|
116
|
-
const first = messages[0]?.content?.slice(0, 200) || '';
|
|
117
|
-
const last = messages[messages.length - 1]?.content?.slice(0, 200) || '';
|
|
118
|
-
return `[Auto-summary failed] Started with: ${first}... Ended with: ${last}`;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Run the full Consolidate pipeline.
|
|
124
|
-
*
|
|
125
|
-
* 1. Partition messages (what to archive vs keep)
|
|
126
|
-
* 2. Generate compact summary (LLM call)
|
|
127
|
-
* 3. Extract memory entries (LLM call)
|
|
128
|
-
* 4. Move archived messages to cold/
|
|
129
|
-
* 5. Update compact.md, index.md, scopes.md
|
|
130
|
-
*
|
|
131
|
-
* @param {{
|
|
132
|
-
* conversationStore: import('../conversation/persist.js').ConversationStore,
|
|
133
|
-
* memoryStore: import('./store.js').MemoryStore,
|
|
134
|
-
* adapter: object,
|
|
135
|
-
* config: object,
|
|
136
|
-
* budget?: number
|
|
137
|
-
* }} params
|
|
138
|
-
* @returns {Promise<{ compactSummary: string, extractedEntries: string[], archivedCount: number }>}
|
|
139
|
-
*/
|
|
140
|
-
export async function consolidate({ conversationStore, memoryStore, adapter, config, budget = DEFAULT_MESSAGE_TOKEN_BUDGET }) {
|
|
141
|
-
// Load all hot messages
|
|
142
|
-
const messages = conversationStore.loadAll();
|
|
143
|
-
|
|
144
|
-
if (messages.length <= MIN_KEEP_MESSAGES) {
|
|
145
|
-
return { compactSummary: '', extractedEntries: [], archivedCount: 0 };
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Step 1: Partition
|
|
149
|
-
const { toArchive, toKeep } = partitionMessages(messages, budget);
|
|
150
|
-
|
|
151
|
-
if (toArchive.length === 0) {
|
|
152
|
-
return { compactSummary: '', extractedEntries: [], archivedCount: 0 };
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Step 2: Generate compact summary
|
|
156
|
-
const compactSummary = await generateSummary(toArchive, adapter, config);
|
|
157
|
-
|
|
158
|
-
// Step 3: Extract memory entries
|
|
159
|
-
const extracted = await extractMemories({ messages: toArchive, adapter, config });
|
|
160
|
-
|
|
161
|
-
// Step 4: Move archived messages to cold
|
|
162
|
-
const archiveIds = toArchive.map(m => m.id).filter(Boolean);
|
|
163
|
-
conversationStore.moveToColdBatch(archiveIds);
|
|
164
|
-
|
|
165
|
-
// Step 5a: Update compact.md
|
|
166
|
-
if (compactSummary) {
|
|
167
|
-
conversationStore.updateCompactSummary(compactSummary);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Step 5b: Write extracted memory entries
|
|
171
|
-
const entryNames = [];
|
|
172
|
-
for (const entry of extracted) {
|
|
173
|
-
const slug = memoryStore.writeEntry(entry);
|
|
174
|
-
entryNames.push(slug);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Step 5c: Update index.md
|
|
178
|
-
const lastMsg = toKeep[toKeep.length - 1];
|
|
179
|
-
conversationStore.updateIndex({
|
|
180
|
-
lastMessageId: lastMsg?.id || null,
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
// Step 5d: Rebuild scopes.md
|
|
184
|
-
if (entryNames.length > 0) {
|
|
185
|
-
memoryStore.rebuildScopes();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return {
|
|
189
|
-
compactSummary,
|
|
190
|
-
extractedEntries: entryNames,
|
|
191
|
-
archivedCount: archiveIds.length,
|
|
192
|
-
};
|
|
193
|
-
}
|
package/unify/prompts.js
CHANGED
|
@@ -368,27 +368,11 @@ export function buildSystemPrompt({
|
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
// ─── 6. Memory Section ─────────────────────────────────
|
|
371
|
+
// FTS5 pre-flow recall + AMS snapshot are concatenated upstream by the
|
|
372
|
+
// engine into a single `memoryInjection` block. The legacy entries-based
|
|
373
|
+
// memory.profile / memory.entries shape was retired in the H2-AMS rip.
|
|
371
374
|
if (memoryInjection && memoryInjection.trim()) {
|
|
372
|
-
// New path (task-287): prebuilt injection from memory/layout.buildMemoryInjection()
|
|
373
|
-
// Contains index.md + user-preferences.md + optional project header excerpt.
|
|
374
375
|
parts.push(memoryInjection.trim());
|
|
375
|
-
} else if (memory && (memory.profile || (memory.entries && memory.entries.length > 0))) {
|
|
376
|
-
// Legacy path — kept for callers (tests, CLI) that have not migrated yet.
|
|
377
|
-
const memoryParts = [lang.memoryHeader];
|
|
378
|
-
|
|
379
|
-
if (memory.profile) {
|
|
380
|
-
memoryParts.push(`${lang.profileHeader}\n${memory.profile}`);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
if (memory.entries && memory.entries.length > 0) {
|
|
384
|
-
const entryLines = memory.entries.map(e => {
|
|
385
|
-
const tags = (e.tags && e.tags.length > 0) ? ` [${e.tags.join(', ')}]` : '';
|
|
386
|
-
return `- **${e.name}** (${e.kind}): ${e.content}${tags}`;
|
|
387
|
-
});
|
|
388
|
-
memoryParts.push(`${lang.recalledHeader}\n${entryLines.join('\n')}`);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
parts.push(memoryParts.join('\n\n'));
|
|
392
376
|
}
|
|
393
377
|
|
|
394
378
|
// ─── 7. Compact Summary Section ────────────────────────
|
package/unify/session.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Wires all subsystems together:
|
|
7
7
|
* initYeaftDir → loadConfig → createTrace → createLLMAdapter →
|
|
8
|
-
* ConversationStore →
|
|
8
|
+
* ConversationStore → SkillManager → MCPManager →
|
|
9
9
|
* ToolRegistry → Engine → Session
|
|
10
10
|
*
|
|
11
11
|
* The ~/.yeaft/ directory is the agent's persistent workspace.
|
|
@@ -18,8 +18,6 @@ import { loadConfig, loadMCPConfig } from './config.js';
|
|
|
18
18
|
import { createTrace } from './debug-trace.js';
|
|
19
19
|
import { createLLMAdapter } from './llm/adapter.js';
|
|
20
20
|
import { ConversationStore } from './conversation/persist.js';
|
|
21
|
-
import { MemoryStore } from './memory/store.js';
|
|
22
|
-
import { openMemoryShardStore } from './memory/shard-store.js';
|
|
23
21
|
import { SkillManager, createSkillManager } from './skills.js';
|
|
24
22
|
import { MCPManager } from './mcp.js';
|
|
25
23
|
import { createFullRegistry } from './tools/index.js';
|
|
@@ -68,7 +66,6 @@ import { existsSync as existsSyncSafe, readFileSync as readFileSyncSafe } from '
|
|
|
68
66
|
* @property {import('./llm/adapter.js').LLMAdapter} adapter — The LLM adapter
|
|
69
67
|
* @property {object} config — Resolved configuration
|
|
70
68
|
* @property {ConversationStore} conversationStore — Conversation persistence
|
|
71
|
-
* @property {MemoryStore} memoryStore — Memory persistence
|
|
72
69
|
* @property {SkillManager} skillManager — Skill manager
|
|
73
70
|
* @property {MCPManager} mcpManager — MCP manager
|
|
74
71
|
* @property {import('./tools/registry.js').ToolRegistry} toolRegistry — Tool registry
|
|
@@ -169,19 +166,6 @@ export async function loadSession(options = {}) {
|
|
|
169
166
|
|
|
170
167
|
// ─── 5. Create stores ──────────────────────────────────
|
|
171
168
|
const conversationStore = new ConversationStore(yeaftDir);
|
|
172
|
-
const memoryStore = new MemoryStore(yeaftDir);
|
|
173
|
-
|
|
174
|
-
// ─── 5-shard. Open R6 memory shard store (task-334f) ──────
|
|
175
|
-
// VP-level memory shard store rooted at ~/.yeaft/memory/vp/default.
|
|
176
|
-
// The 'default' VP matches the single-user Unify mode; R6 multi-VP
|
|
177
|
-
// callers open per-VP stores via openMemoryShardStore() directly.
|
|
178
|
-
const memoryShardDir = join(yeaftDir, 'memory', 'vp', 'default');
|
|
179
|
-
let memoryShardStore = null;
|
|
180
|
-
try {
|
|
181
|
-
memoryShardStore = openMemoryShardStore(memoryShardDir, 'vp');
|
|
182
|
-
} catch (err) {
|
|
183
|
-
console.warn(`[Yeaft] Failed to open R6 memory shard store: ${err?.message || err}`);
|
|
184
|
-
}
|
|
185
169
|
|
|
186
170
|
// ─── 5-fts. (GC.1) Open SegmentIndex for FTS pre-flow ────
|
|
187
171
|
// When config.memoryV2 is on, build a SQLite FTS5 index over
|
|
@@ -290,8 +274,6 @@ export async function loadSession(options = {}) {
|
|
|
290
274
|
trace,
|
|
291
275
|
config,
|
|
292
276
|
conversationStore,
|
|
293
|
-
memoryStore,
|
|
294
|
-
memoryShardStore,
|
|
295
277
|
memoryIndex,
|
|
296
278
|
amsRegistry,
|
|
297
279
|
toolRegistry,
|
|
@@ -363,8 +345,6 @@ export async function loadSession(options = {}) {
|
|
|
363
345
|
adapter,
|
|
364
346
|
config,
|
|
365
347
|
conversationStore,
|
|
366
|
-
memoryStore,
|
|
367
|
-
memoryShardStore,
|
|
368
348
|
dreamScheduler,
|
|
369
349
|
skillManager,
|
|
370
350
|
mcpManager,
|
package/unify/stop-hooks.js
CHANGED
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Runs after each query loop completes:
|
|
5
5
|
* 1. Persist messages to conversation/messages/
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
|
+
* Consolidation (compact orchestrator) is driven by the engine itself
|
|
8
|
+
* via `#maybeConsolidate`; the legacy LLM-driven `consolidate()` plus
|
|
9
|
+
* entries-store extraction was retired in the H2-AMS rip.
|
|
7
10
|
*
|
|
8
11
|
* Dream V2 owns all background memory maintenance (scope summaries +
|
|
9
|
-
* memory writes via dream-v2/session-wiring.js → createV2DreamScheduler)
|
|
10
|
-
* the legacy `memory/dream.js` gate that used to fire here was retired
|
|
11
|
-
* alongside recall-r6.
|
|
12
|
+
* memory writes via dream-v2/session-wiring.js → createV2DreamScheduler).
|
|
12
13
|
*
|
|
13
14
|
* Reference: yeaft-unify-core-systems.md §4.4
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
|
-
import { shouldConsolidate, consolidate } from './memory/consolidate.js';
|
|
17
17
|
import { isPermissionError } from './init.js';
|
|
18
18
|
|
|
19
19
|
/** Track whether we've already warned about permission issues in stop hooks. */
|
|
@@ -26,7 +26,6 @@ let _permissionWarned = false;
|
|
|
26
26
|
* yeaftDir: string,
|
|
27
27
|
* mode: string,
|
|
28
28
|
* conversationStore: import('./conversation/persist.js').ConversationStore,
|
|
29
|
-
* memoryStore: import('./memory/store.js').MemoryStore,
|
|
30
29
|
* adapter: object,
|
|
31
30
|
* config: object,
|
|
32
31
|
* primaryModel?: string,
|
|
@@ -42,7 +41,6 @@ export async function runStopHooks(context) {
|
|
|
42
41
|
yeaftDir,
|
|
43
42
|
mode,
|
|
44
43
|
conversationStore,
|
|
45
|
-
memoryStore,
|
|
46
44
|
adapter,
|
|
47
45
|
config,
|
|
48
46
|
primaryModel,
|
|
@@ -60,7 +58,6 @@ export async function runStopHooks(context) {
|
|
|
60
58
|
|
|
61
59
|
const result = {
|
|
62
60
|
messagesPersisted: 0,
|
|
63
|
-
consolidated: false,
|
|
64
61
|
errors: [],
|
|
65
62
|
};
|
|
66
63
|
|
|
@@ -133,41 +130,9 @@ export async function runStopHooks(context) {
|
|
|
133
130
|
}
|
|
134
131
|
}
|
|
135
132
|
|
|
136
|
-
// 2.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (shouldConsolidate(conversationStore, config.messageTokenBudget)) {
|
|
140
|
-
const consolidated = await consolidate({
|
|
141
|
-
conversationStore,
|
|
142
|
-
memoryStore,
|
|
143
|
-
adapter,
|
|
144
|
-
config,
|
|
145
|
-
budget: config.messageTokenBudget,
|
|
146
|
-
});
|
|
147
|
-
result.consolidated = true;
|
|
148
|
-
trace?.logEvent({
|
|
149
|
-
eventType: 'consolidate',
|
|
150
|
-
eventData: {
|
|
151
|
-
archivedCount: consolidated.archivedCount,
|
|
152
|
-
extractedEntries: consolidated.extractedEntries.length,
|
|
153
|
-
},
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
} catch (err) {
|
|
158
|
-
if (isPermissionError(err)) {
|
|
159
|
-
if (!_permissionWarned) {
|
|
160
|
-
result.errors.push('Cannot write to ~/.yeaft/ — consolidation skipped');
|
|
161
|
-
_permissionWarned = true;
|
|
162
|
-
}
|
|
163
|
-
} else {
|
|
164
|
-
result.errors.push(`Consolidate failed: ${err.message}`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// 3. Dream V2 owns background scope-memory maintenance via the session
|
|
169
|
-
// dream scheduler (createV2DreamScheduler). No legacy dream gate is
|
|
170
|
-
// invoked here; the scheduler decides when to run on its own cadence.
|
|
133
|
+
// 2. Consolidation is owned by the engine (#maybeConsolidate → compact
|
|
134
|
+
// orchestrator). Dream V2 owns background scope-memory maintenance
|
|
135
|
+
// via the session dream scheduler (createV2DreamScheduler).
|
|
171
136
|
|
|
172
137
|
return result;
|
|
173
138
|
}
|
|
@@ -175,6 +140,5 @@ export async function runStopHooks(context) {
|
|
|
175
140
|
/**
|
|
176
141
|
* @typedef {Object} StopHookResult
|
|
177
142
|
* @property {number} messagesPersisted — how many messages were persisted
|
|
178
|
-
* @property {boolean} consolidated — whether consolidation ran
|
|
179
143
|
* @property {string[]} errors — any non-fatal errors
|
|
180
144
|
*/
|
package/unify/tools/index.js
CHANGED
|
@@ -18,11 +18,6 @@ import exitWorktree from './exit-worktree.js';
|
|
|
18
18
|
|
|
19
19
|
// --- P0 Core tools ---
|
|
20
20
|
import askUser from './ask-user.js';
|
|
21
|
-
import memoryRead from './memory-read.js';
|
|
22
|
-
import memoryWrite from './memory-write.js';
|
|
23
|
-
import memorySearch, { memorySearchAlias } from './memory-search.js';
|
|
24
|
-
import memoryQuery from './memory-query.js';
|
|
25
|
-
import memoryTrace from './memory-trace.js';
|
|
26
21
|
import openSourceMessage from './open-source-message.js';
|
|
27
22
|
import webSearch from './web-search.js';
|
|
28
23
|
import webFetch from './web-fetch.js';
|
|
@@ -89,12 +84,6 @@ export const allTools = [
|
|
|
89
84
|
|
|
90
85
|
// P0 Core
|
|
91
86
|
askUser,
|
|
92
|
-
memoryRead,
|
|
93
|
-
memoryWrite,
|
|
94
|
-
memorySearch,
|
|
95
|
-
memorySearchAlias,
|
|
96
|
-
memoryQuery,
|
|
97
|
-
memoryTrace,
|
|
98
87
|
openSourceMessage,
|
|
99
88
|
webSearch,
|
|
100
89
|
webFetch,
|
package/unify/web-bridge.js
CHANGED
|
@@ -26,10 +26,6 @@ import { createVp, updateVp, deleteVp, readVp, VpCrudError } from './vp/vp-crud.
|
|
|
26
26
|
import { scanVpLibrary } from './vp/vp-store.js';
|
|
27
27
|
import { createRouter } from './routing/router.js';
|
|
28
28
|
import { handleUnifyFeatureMessage as _handleUnifyFeatureMessage } from './feature-message.js';
|
|
29
|
-
import {
|
|
30
|
-
handleUnifyUserMemoryWrite as _handleUnifyUserMemoryWrite,
|
|
31
|
-
handleUnifyUserMemoryRemove as _handleUnifyUserMemoryRemove,
|
|
32
|
-
} from './user-memory.js';
|
|
33
29
|
import {
|
|
34
30
|
GroupCrudError,
|
|
35
31
|
createGroupFromSpec,
|
|
@@ -209,36 +205,6 @@ export function handleUnifyFeatureMessage(msg) {
|
|
|
209
205
|
_handleUnifyFeatureMessage(msg, sendUnifyEvent);
|
|
210
206
|
}
|
|
211
207
|
|
|
212
|
-
export function handleUnifyUserMemoryWrite(msg) {
|
|
213
|
-
_handleUnifyUserMemoryWrite(msg, sendUnifyEvent);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export function handleUnifyUserMemoryRemove(msg) {
|
|
217
|
-
_handleUnifyUserMemoryRemove(msg, sendUnifyEvent);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export function handleUnifyMemoryScopeList(msg) {
|
|
221
|
-
const requestId = msg && typeof msg.requestId === 'string' ? msg.requestId : undefined;
|
|
222
|
-
try {
|
|
223
|
-
const store = session && session.memoryStore;
|
|
224
|
-
const entries = store && typeof store.listEntries === 'function'
|
|
225
|
-
? store.listEntries()
|
|
226
|
-
: [];
|
|
227
|
-
sendUnifyEvent({
|
|
228
|
-
type: 'memory_scope_snapshot',
|
|
229
|
-
entries,
|
|
230
|
-
...(requestId ? { requestId } : {}),
|
|
231
|
-
});
|
|
232
|
-
} catch (err) {
|
|
233
|
-
sendUnifyEvent({
|
|
234
|
-
type: 'memory_scope_snapshot',
|
|
235
|
-
entries: [],
|
|
236
|
-
error: String(err && err.message || err),
|
|
237
|
-
...(requestId ? { requestId } : {}),
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
208
|
export function handleUnifyVpRead(msg) {
|
|
243
209
|
const requestId = msg && msg.requestId;
|
|
244
210
|
const vpId = msg && msg.vpId;
|
|
@@ -1130,70 +1096,6 @@ export function handleUnifyModeSwitch(_msg) {
|
|
|
1130
1096
|
console.warn('[Unify] unify_mode_switch is deprecated and ignored — Unify now runs in a single unified mode.');
|
|
1131
1097
|
}
|
|
1132
1098
|
|
|
1133
|
-
/** Read-only memory query for the UI memory browser. */
|
|
1134
|
-
export function handleUnifyMemoryQuery(msg = {}) {
|
|
1135
|
-
const requestId = typeof msg.requestId === 'string' ? msg.requestId : undefined;
|
|
1136
|
-
const vpId = typeof msg.vpId === 'string' ? msg.vpId : null;
|
|
1137
|
-
const featureId = typeof msg.featureId === 'string' ? msg.featureId : null;
|
|
1138
|
-
const limit = Number.isFinite(msg.limit) ? Math.max(1, Math.min(200, msg.limit)) : 50;
|
|
1139
|
-
|
|
1140
|
-
const reply = (extra = {}) => sendUnifyEvent({
|
|
1141
|
-
type: 'unify_memory_query_result',
|
|
1142
|
-
scope: { vpId, featureId },
|
|
1143
|
-
...extra,
|
|
1144
|
-
...(requestId ? { requestId } : {}),
|
|
1145
|
-
});
|
|
1146
|
-
|
|
1147
|
-
if (!session || !session.memoryShardStore) {
|
|
1148
|
-
reply({ entries: [], error: 'no_memory_store' });
|
|
1149
|
-
return;
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
try {
|
|
1153
|
-
const filter = {};
|
|
1154
|
-
if (vpId) filter.vp = vpId;
|
|
1155
|
-
if (featureId) filter.feature = featureId;
|
|
1156
|
-
const res = session.memoryShardStore.query(filter);
|
|
1157
|
-
const list = Array.isArray(res?.results) ? res.results : [];
|
|
1158
|
-
list.sort((a, b) => {
|
|
1159
|
-
const ax = (a && (a.updatedAt || a.createdAt)) || 0;
|
|
1160
|
-
const bx = (b && (b.updatedAt || b.createdAt)) || 0;
|
|
1161
|
-
const at = typeof ax === 'string' ? Date.parse(ax) : ax;
|
|
1162
|
-
const bt = typeof bx === 'string' ? Date.parse(bx) : bx;
|
|
1163
|
-
return (bt || 0) - (at || 0);
|
|
1164
|
-
});
|
|
1165
|
-
reply({ entries: list.slice(0, limit) });
|
|
1166
|
-
} catch (err) {
|
|
1167
|
-
reply({ entries: [], error: String(err?.message || err) });
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
/** Open the source message behind a memory entry. */
|
|
1172
|
-
export function handleUnifyMemoryTrace(msg = {}) {
|
|
1173
|
-
const requestId = typeof msg.requestId === 'string' ? msg.requestId : undefined;
|
|
1174
|
-
const entryId = typeof msg.entryId === 'string' ? msg.entryId : null;
|
|
1175
|
-
|
|
1176
|
-
const reply = (extra = {}) => sendUnifyEvent({
|
|
1177
|
-
type: 'unify_memory_trace_result',
|
|
1178
|
-
entryId,
|
|
1179
|
-
...extra,
|
|
1180
|
-
...(requestId ? { requestId } : {}),
|
|
1181
|
-
});
|
|
1182
|
-
|
|
1183
|
-
if (!entryId) { reply({ entry: null, sourceRef: null, error: 'missing_entry_id' }); return; }
|
|
1184
|
-
if (!session || !session.memoryShardStore) {
|
|
1185
|
-
reply({ entry: null, sourceRef: null, error: 'no_memory_store' });
|
|
1186
|
-
return;
|
|
1187
|
-
}
|
|
1188
|
-
try {
|
|
1189
|
-
const entry = session.memoryShardStore.get(entryId);
|
|
1190
|
-
if (!entry) { reply({ entry: null, sourceRef: null, error: 'not_found' }); return; }
|
|
1191
|
-
reply({ entry, sourceRef: entry.sourceRef || null });
|
|
1192
|
-
} catch (err) {
|
|
1193
|
-
reply({ entry: null, sourceRef: null, error: String(err?.message || err) });
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
1099
|
/** Fetch a feature's summary history (revision chain). */
|
|
1198
1100
|
export async function handleUnifyFetchSummaryHistory(msg = {}) {
|
|
1199
1101
|
const requestId = typeof msg.requestId === 'string' ? msg.requestId : undefined;
|