@lumenflow/memory 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +181 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/mem-checkpoint-core.d.ts +91 -0
- package/dist/mem-checkpoint-core.d.ts.map +1 -0
- package/dist/mem-checkpoint-core.js +175 -0
- package/dist/mem-checkpoint-core.js.map +1 -0
- package/dist/mem-cleanup-core.d.ts +202 -0
- package/dist/mem-cleanup-core.d.ts.map +1 -0
- package/dist/mem-cleanup-core.js +364 -0
- package/dist/mem-cleanup-core.js.map +1 -0
- package/dist/mem-create-core.d.ts +93 -0
- package/dist/mem-create-core.d.ts.map +1 -0
- package/dist/mem-create-core.js +369 -0
- package/dist/mem-create-core.js.map +1 -0
- package/dist/mem-id.d.ts +91 -0
- package/dist/mem-id.d.ts.map +1 -0
- package/dist/mem-id.js +136 -0
- package/dist/mem-id.js.map +1 -0
- package/dist/mem-init-core.d.ts +91 -0
- package/dist/mem-init-core.d.ts.map +1 -0
- package/dist/mem-init-core.js +138 -0
- package/dist/mem-init-core.js.map +1 -0
- package/dist/mem-ready-core.d.ts +56 -0
- package/dist/mem-ready-core.d.ts.map +1 -0
- package/dist/mem-ready-core.js +232 -0
- package/dist/mem-ready-core.js.map +1 -0
- package/dist/mem-signal-core.d.ts +132 -0
- package/dist/mem-signal-core.d.ts.map +1 -0
- package/dist/mem-signal-core.js +249 -0
- package/dist/mem-signal-core.js.map +1 -0
- package/dist/mem-start-core.d.ts +76 -0
- package/dist/mem-start-core.d.ts.map +1 -0
- package/dist/mem-start-core.js +133 -0
- package/dist/mem-start-core.js.map +1 -0
- package/dist/mem-summarize-core.d.ts +105 -0
- package/dist/mem-summarize-core.d.ts.map +1 -0
- package/dist/mem-summarize-core.js +263 -0
- package/dist/mem-summarize-core.js.map +1 -0
- package/dist/mem-triage-core.d.ts +127 -0
- package/dist/mem-triage-core.d.ts.map +1 -0
- package/dist/mem-triage-core.js +332 -0
- package/dist/mem-triage-core.js.map +1 -0
- package/dist/memory-schema.d.ts +150 -0
- package/dist/memory-schema.d.ts.map +1 -0
- package/dist/memory-schema.js +149 -0
- package/dist/memory-schema.js.map +1 -0
- package/dist/memory-store.d.ts +108 -0
- package/dist/memory-store.d.ts.map +1 -0
- package/dist/memory-store.js +234 -0
- package/dist/memory-store.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Signal Core Logic (WU-1473)
|
|
3
|
+
*
|
|
4
|
+
* Core logic for creating coordination signals between parallel agents.
|
|
5
|
+
* Enables sub-100ms agent communication via JSONL append operations.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Append-only writes for sub-100ms performance
|
|
9
|
+
* - WU-scoped signals for focused coordination
|
|
10
|
+
* - Lane-targeted signals for cross-team communication
|
|
11
|
+
* - Read/unread tracking for mem:inbox integration
|
|
12
|
+
*
|
|
13
|
+
* @see {@link tools/mem-signal.mjs} - CLI wrapper
|
|
14
|
+
* @see {@link tools/__tests__/mem-signal.test.mjs} - Tests
|
|
15
|
+
*/
|
|
16
|
+
import { randomBytes } from 'node:crypto';
|
|
17
|
+
import fs from 'node:fs/promises';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
/**
|
|
20
|
+
* Signal file name constant
|
|
21
|
+
*/
|
|
22
|
+
export const SIGNAL_FILE_NAME = 'signals.jsonl';
|
|
23
|
+
/**
|
|
24
|
+
* Memory directory path within project
|
|
25
|
+
*/
|
|
26
|
+
const MEMORY_DIR = '.beacon/memory';
|
|
27
|
+
/**
|
|
28
|
+
* WU ID validation pattern (from memory-schema.mjs)
|
|
29
|
+
*/
|
|
30
|
+
const WU_ID_PATTERN = /^WU-\d+$/;
|
|
31
|
+
/**
|
|
32
|
+
* Signal ID prefix
|
|
33
|
+
*/
|
|
34
|
+
const SIGNAL_ID_PREFIX = 'sig-';
|
|
35
|
+
/**
|
|
36
|
+
* Number of hex characters in signal ID suffix
|
|
37
|
+
*/
|
|
38
|
+
const SIGNAL_ID_LENGTH = 8;
|
|
39
|
+
/**
|
|
40
|
+
* Error messages for validation
|
|
41
|
+
*/
|
|
42
|
+
const ERROR_MESSAGES = {
|
|
43
|
+
MESSAGE_REQUIRED: 'message is required and cannot be empty',
|
|
44
|
+
INVALID_WU_ID: 'Invalid WU ID format. Expected WU-XXX (e.g., WU-1473)',
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Generates a unique signal ID using random bytes.
|
|
48
|
+
*
|
|
49
|
+
* Format: sig-[8 hex chars]
|
|
50
|
+
* Uses crypto.randomBytes for uniqueness (not content-based like mem-id).
|
|
51
|
+
*
|
|
52
|
+
* @returns {string} Signal ID in format sig-XXXXXXXX
|
|
53
|
+
*/
|
|
54
|
+
function generateSignalId() {
|
|
55
|
+
const bytes = randomBytes(4);
|
|
56
|
+
const hex = bytes.toString('hex').slice(0, SIGNAL_ID_LENGTH);
|
|
57
|
+
return `${SIGNAL_ID_PREFIX}${hex}`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Gets the memory directory path for a project.
|
|
61
|
+
*
|
|
62
|
+
* @param baseDir - Project base directory
|
|
63
|
+
* @returns Full path to memory directory
|
|
64
|
+
*/
|
|
65
|
+
function getMemoryDir(baseDir) {
|
|
66
|
+
return path.join(baseDir, MEMORY_DIR);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Gets the signals file path for a project.
|
|
70
|
+
*
|
|
71
|
+
* @param baseDir - Project base directory
|
|
72
|
+
* @returns Full path to signals.jsonl
|
|
73
|
+
*/
|
|
74
|
+
function getSignalsPath(baseDir) {
|
|
75
|
+
return path.join(getMemoryDir(baseDir), SIGNAL_FILE_NAME);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Validates a WU ID format.
|
|
79
|
+
*
|
|
80
|
+
* @param wuId - WU ID to validate
|
|
81
|
+
* @returns True if valid
|
|
82
|
+
*/
|
|
83
|
+
function isValidWuId(wuId) {
|
|
84
|
+
return WU_ID_PATTERN.test(wuId);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Creates a coordination signal between parallel agents.
|
|
88
|
+
*
|
|
89
|
+
* Signals are appended to signals.jsonl using append-only writes
|
|
90
|
+
* for sub-100ms performance. Signals can be scoped to a specific
|
|
91
|
+
* WU or targeted at a specific lane.
|
|
92
|
+
*
|
|
93
|
+
* @param {string} baseDir - Project base directory
|
|
94
|
+
* @param {CreateSignalOptions} options - Signal options
|
|
95
|
+
* @returns {Promise<CreateSignalResult>} Result with created signal
|
|
96
|
+
* @throws {Error} If message is missing or WU ID is invalid
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* const result = await createSignal('/project', {
|
|
100
|
+
* message: 'Starting feature implementation',
|
|
101
|
+
* wuId: 'WU-1473',
|
|
102
|
+
* lane: 'Operations: Tooling',
|
|
103
|
+
* });
|
|
104
|
+
*/
|
|
105
|
+
export async function createSignal(baseDir, options) {
|
|
106
|
+
const { message, wuId, lane } = options;
|
|
107
|
+
// Validate message is provided and non-empty
|
|
108
|
+
if (!message || typeof message !== 'string' || message.trim().length === 0) {
|
|
109
|
+
throw new Error(ERROR_MESSAGES.MESSAGE_REQUIRED);
|
|
110
|
+
}
|
|
111
|
+
// Validate WU ID format if provided
|
|
112
|
+
if (wuId !== undefined && !isValidWuId(wuId)) {
|
|
113
|
+
throw new Error(ERROR_MESSAGES.INVALID_WU_ID);
|
|
114
|
+
}
|
|
115
|
+
// Build signal object
|
|
116
|
+
const signal = {
|
|
117
|
+
id: generateSignalId(),
|
|
118
|
+
message: message.trim(),
|
|
119
|
+
created_at: new Date().toISOString(),
|
|
120
|
+
read: false,
|
|
121
|
+
};
|
|
122
|
+
// Add optional fields
|
|
123
|
+
if (wuId) {
|
|
124
|
+
signal.wu_id = wuId;
|
|
125
|
+
}
|
|
126
|
+
if (lane) {
|
|
127
|
+
signal.lane = lane;
|
|
128
|
+
}
|
|
129
|
+
// Ensure memory directory exists
|
|
130
|
+
const memoryDir = getMemoryDir(baseDir);
|
|
131
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- CLI tool creates known directory
|
|
132
|
+
await fs.mkdir(memoryDir, { recursive: true });
|
|
133
|
+
// Append signal to file (append-only for speed)
|
|
134
|
+
const signalsPath = getSignalsPath(baseDir);
|
|
135
|
+
const line = `${JSON.stringify(signal)}\n`;
|
|
136
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- CLI tool writes signals file
|
|
137
|
+
await fs.appendFile(signalsPath, line, 'utf-8');
|
|
138
|
+
return {
|
|
139
|
+
success: true,
|
|
140
|
+
signal,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Loads signals from the signals file with optional filtering.
|
|
145
|
+
*
|
|
146
|
+
* Signals are returned in chronological order (oldest first).
|
|
147
|
+
* Supports filtering by WU ID, lane, and read status.
|
|
148
|
+
*
|
|
149
|
+
* @param {string} baseDir - Project base directory
|
|
150
|
+
* @param {LoadSignalsOptions} [options={}] - Filter options
|
|
151
|
+
* @returns {Promise<Signal[]>} Array of signals matching filters
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* // Load all signals
|
|
155
|
+
* const all = await loadSignals('/project');
|
|
156
|
+
*
|
|
157
|
+
* // Load unread signals for a specific WU
|
|
158
|
+
* const unread = await loadSignals('/project', {
|
|
159
|
+
* wuId: 'WU-1473',
|
|
160
|
+
* unreadOnly: true,
|
|
161
|
+
* });
|
|
162
|
+
*/
|
|
163
|
+
export async function loadSignals(baseDir, options = {}) {
|
|
164
|
+
const { wuId, lane, unreadOnly, since } = options;
|
|
165
|
+
const signalsPath = getSignalsPath(baseDir);
|
|
166
|
+
// Read file content
|
|
167
|
+
let content;
|
|
168
|
+
try {
|
|
169
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- CLI tool reads signals file
|
|
170
|
+
content = await fs.readFile(signalsPath, { encoding: 'utf-8' });
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
const error = err;
|
|
174
|
+
if (error.code === 'ENOENT') {
|
|
175
|
+
// File doesn't exist - return empty array
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
// Parse JSONL content
|
|
181
|
+
const lines = content.split('\n').filter((line) => line.trim());
|
|
182
|
+
const signals = lines.map((line) => JSON.parse(line));
|
|
183
|
+
// Apply filters
|
|
184
|
+
let filtered = signals;
|
|
185
|
+
if (wuId) {
|
|
186
|
+
filtered = filtered.filter((sig) => sig.wu_id === wuId);
|
|
187
|
+
}
|
|
188
|
+
if (lane) {
|
|
189
|
+
filtered = filtered.filter((sig) => sig.lane === lane);
|
|
190
|
+
}
|
|
191
|
+
if (unreadOnly) {
|
|
192
|
+
filtered = filtered.filter((sig) => sig.read === false);
|
|
193
|
+
}
|
|
194
|
+
if (since) {
|
|
195
|
+
const sinceTime = since instanceof Date ? since : new Date(since);
|
|
196
|
+
filtered = filtered.filter((sig) => new Date(sig.created_at) > sinceTime);
|
|
197
|
+
}
|
|
198
|
+
// Return in chronological order (file order is already chronological due to append-only)
|
|
199
|
+
return filtered;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Marks signals as read by updating the signals file.
|
|
203
|
+
*
|
|
204
|
+
* Reads the entire file, updates the read status for matching IDs,
|
|
205
|
+
* and writes back. Only signals that were previously unread are counted.
|
|
206
|
+
*
|
|
207
|
+
* @param baseDir - Project base directory
|
|
208
|
+
* @param signalIds - Array of signal IDs to mark as read
|
|
209
|
+
* @returns Result with count of signals marked
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* const result = await markSignalsAsRead('/project', ['sig-abc12345', 'sig-def67890']);
|
|
213
|
+
* console.log(result.markedCount); // 2
|
|
214
|
+
*/
|
|
215
|
+
export async function markSignalsAsRead(baseDir, signalIds) {
|
|
216
|
+
const signalsPath = getSignalsPath(baseDir);
|
|
217
|
+
const idSet = new Set(signalIds);
|
|
218
|
+
let markedCount = 0;
|
|
219
|
+
// Read file content
|
|
220
|
+
let content;
|
|
221
|
+
try {
|
|
222
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- CLI tool reads signals file
|
|
223
|
+
content = await fs.readFile(signalsPath, { encoding: 'utf-8' });
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
const error = err;
|
|
227
|
+
if (error.code === 'ENOENT') {
|
|
228
|
+
// No signals file - nothing to mark
|
|
229
|
+
return { markedCount: 0 };
|
|
230
|
+
}
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
// Parse JSONL content
|
|
234
|
+
const lines = content.split('\n').filter((line) => line.trim());
|
|
235
|
+
const updatedLines = lines.map((line) => {
|
|
236
|
+
const signal = JSON.parse(line);
|
|
237
|
+
if (idSet.has(signal.id) && signal.read === false) {
|
|
238
|
+
signal.read = true;
|
|
239
|
+
markedCount++;
|
|
240
|
+
}
|
|
241
|
+
return JSON.stringify(signal);
|
|
242
|
+
});
|
|
243
|
+
// Write back updated content
|
|
244
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- CLI tool writes signals file
|
|
245
|
+
await fs.writeFile(signalsPath, `${updatedLines.join('\n')}\n`, {
|
|
246
|
+
encoding: 'utf-8',
|
|
247
|
+
});
|
|
248
|
+
return { markedCount };
|
|
249
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mem-signal-core.js","sourceRoot":"","sources":["../src/mem-signal-core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Start Core (WU-1466)
|
|
3
|
+
*
|
|
4
|
+
* Core logic for creating session nodes linked to WUs.
|
|
5
|
+
* Called by wu:claim enhancement for context restoration after /clear.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Creates session nodes with WU reference
|
|
9
|
+
* - Stores agent type, start timestamp, context tier
|
|
10
|
+
* - Idempotent: multiple starts create separate sessions
|
|
11
|
+
* - Auto-initializes memory layer if not present
|
|
12
|
+
*
|
|
13
|
+
* @see {@link tools/mem-start.mjs} - CLI wrapper
|
|
14
|
+
* @see {@link tools/__tests__/mem-start.test.mjs} - Tests
|
|
15
|
+
* @see {@link tools/lib/memory-schema.mjs} - Schema definitions
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Session start options
|
|
19
|
+
*/
|
|
20
|
+
export interface StartSessionOptions {
|
|
21
|
+
/** Work Unit ID (required) */
|
|
22
|
+
wuId: string;
|
|
23
|
+
/** Agent type (defaults to 'unknown') */
|
|
24
|
+
agentType?: string;
|
|
25
|
+
/** Context tier (defaults to 'full') */
|
|
26
|
+
contextTier?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Session node structure
|
|
30
|
+
*/
|
|
31
|
+
interface SessionNode {
|
|
32
|
+
id: string;
|
|
33
|
+
type: 'session';
|
|
34
|
+
lifecycle: 'wu';
|
|
35
|
+
content: string;
|
|
36
|
+
created_at: string;
|
|
37
|
+
wu_id: string;
|
|
38
|
+
session_id: string;
|
|
39
|
+
metadata: {
|
|
40
|
+
agentType: string;
|
|
41
|
+
contextTier: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Session start result
|
|
46
|
+
*/
|
|
47
|
+
export interface StartSessionResult {
|
|
48
|
+
/** Whether the operation succeeded */
|
|
49
|
+
success: boolean;
|
|
50
|
+
/** Created session node */
|
|
51
|
+
session: SessionNode;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Creates a new session node linked to a WU.
|
|
55
|
+
*
|
|
56
|
+
* Creates a session-type memory node with:
|
|
57
|
+
* - Unique ID (mem-XXXX format)
|
|
58
|
+
* - Link to WU via wu_id field
|
|
59
|
+
* - Agent type and context tier in metadata
|
|
60
|
+
* - UUID session_id for unique identification
|
|
61
|
+
*
|
|
62
|
+
* @param baseDir - Base directory containing .beacon/memory/
|
|
63
|
+
* @param options - Session options
|
|
64
|
+
* @returns Result with created session node
|
|
65
|
+
* @throws If wuId is missing or invalid
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* const result = await startSession('/path/to/project', {
|
|
69
|
+
* wuId: 'WU-1234',
|
|
70
|
+
* agentType: 'general-purpose',
|
|
71
|
+
* contextTier: 'core',
|
|
72
|
+
* });
|
|
73
|
+
* console.log(result.session.id); // 'mem-a1b2'
|
|
74
|
+
*/
|
|
75
|
+
export declare function startSession(baseDir: string, options: StartSessionOptions): Promise<StartSessionResult>;
|
|
76
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mem-start-core.d.ts","sourceRoot":"","sources":["../src/mem-start-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA2EH;;;;;;;GAOG;AAEH;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,YAAY,CAAC,OAAO,KAAA,EAAE,OAAO,KAAA;;;;;;;;;;;;;;;GA+ClD"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Start Core (WU-1466)
|
|
3
|
+
*
|
|
4
|
+
* Core logic for creating session nodes linked to WUs.
|
|
5
|
+
* Called by wu:claim enhancement for context restoration after /clear.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Creates session nodes with WU reference
|
|
9
|
+
* - Stores agent type, start timestamp, context tier
|
|
10
|
+
* - Idempotent: multiple starts create separate sessions
|
|
11
|
+
* - Auto-initializes memory layer if not present
|
|
12
|
+
*
|
|
13
|
+
* @see {@link tools/mem-start.mjs} - CLI wrapper
|
|
14
|
+
* @see {@link tools/__tests__/mem-start.test.mjs} - Tests
|
|
15
|
+
* @see {@link tools/lib/memory-schema.mjs} - Schema definitions
|
|
16
|
+
*/
|
|
17
|
+
import { randomUUID } from 'node:crypto';
|
|
18
|
+
import fs from 'node:fs/promises';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
import { generateMemId } from './mem-id.js';
|
|
21
|
+
import { appendNode } from './memory-store.js';
|
|
22
|
+
import { MEMORY_PATTERNS } from './memory-schema.js';
|
|
23
|
+
/**
|
|
24
|
+
* Memory directory path relative to base directory
|
|
25
|
+
*/
|
|
26
|
+
const MEMORY_DIR = '.beacon/memory';
|
|
27
|
+
/**
|
|
28
|
+
* Default values for session metadata
|
|
29
|
+
*/
|
|
30
|
+
const DEFAULTS = {
|
|
31
|
+
AGENT_TYPE: 'unknown',
|
|
32
|
+
CONTEXT_TIER: 'full',
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Error messages for validation
|
|
36
|
+
*/
|
|
37
|
+
const ERROR_MESSAGES = {
|
|
38
|
+
WU_ID_REQUIRED: 'wuId is required',
|
|
39
|
+
WU_ID_INVALID: 'Invalid WU ID format. Expected pattern: WU-XXX (e.g., WU-123)',
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Validates WU ID format
|
|
43
|
+
*
|
|
44
|
+
* @param wuId - WU ID to validate
|
|
45
|
+
* @returns True if valid
|
|
46
|
+
*/
|
|
47
|
+
function isValidWuId(wuId) {
|
|
48
|
+
return MEMORY_PATTERNS.WU_ID.test(wuId);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Ensures the memory directory exists
|
|
52
|
+
*
|
|
53
|
+
* @param baseDir - Base directory
|
|
54
|
+
* @returns Memory directory path
|
|
55
|
+
*/
|
|
56
|
+
async function ensureMemoryDir(baseDir) {
|
|
57
|
+
const memoryDir = path.join(baseDir, MEMORY_DIR);
|
|
58
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- Known directory path
|
|
59
|
+
await fs.mkdir(memoryDir, { recursive: true });
|
|
60
|
+
return memoryDir;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Generates content description for session node
|
|
64
|
+
*
|
|
65
|
+
* @param wuId - WU ID
|
|
66
|
+
* @param agentType - Agent type
|
|
67
|
+
* @param contextTier - Context tier
|
|
68
|
+
* @returns Content description
|
|
69
|
+
*/
|
|
70
|
+
function generateSessionContent(wuId, agentType, contextTier) {
|
|
71
|
+
return `Session started for ${wuId}. Agent: ${agentType}, Context: ${contextTier}`;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Creates a new session node linked to a WU.
|
|
75
|
+
*
|
|
76
|
+
* Creates a session-type memory node with:
|
|
77
|
+
* - Unique ID (mem-XXXX format)
|
|
78
|
+
* - Link to WU via wu_id field
|
|
79
|
+
* - Agent type and context tier in metadata
|
|
80
|
+
* - UUID session_id for unique identification
|
|
81
|
+
*
|
|
82
|
+
* @param baseDir - Base directory containing .beacon/memory/
|
|
83
|
+
* @param options - Session options
|
|
84
|
+
* @returns Result with created session node
|
|
85
|
+
* @throws If wuId is missing or invalid
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const result = await startSession('/path/to/project', {
|
|
89
|
+
* wuId: 'WU-1234',
|
|
90
|
+
* agentType: 'general-purpose',
|
|
91
|
+
* contextTier: 'core',
|
|
92
|
+
* });
|
|
93
|
+
* console.log(result.session.id); // 'mem-a1b2'
|
|
94
|
+
*/
|
|
95
|
+
export async function startSession(baseDir, options) {
|
|
96
|
+
const { wuId, agentType = DEFAULTS.AGENT_TYPE, contextTier = DEFAULTS.CONTEXT_TIER } = options;
|
|
97
|
+
// Validate required fields
|
|
98
|
+
if (!wuId) {
|
|
99
|
+
throw new Error(ERROR_MESSAGES.WU_ID_REQUIRED);
|
|
100
|
+
}
|
|
101
|
+
// Validate WU ID format
|
|
102
|
+
if (!isValidWuId(wuId)) {
|
|
103
|
+
throw new Error(ERROR_MESSAGES.WU_ID_INVALID);
|
|
104
|
+
}
|
|
105
|
+
// Ensure memory directory exists
|
|
106
|
+
const memoryDir = await ensureMemoryDir(baseDir);
|
|
107
|
+
// Generate session node
|
|
108
|
+
const timestamp = new Date().toISOString();
|
|
109
|
+
const sessionId = randomUUID();
|
|
110
|
+
const content = generateSessionContent(wuId, agentType, contextTier);
|
|
111
|
+
// Generate deterministic ID from content + timestamp for uniqueness
|
|
112
|
+
const idContent = `${content}-${timestamp}-${sessionId}`;
|
|
113
|
+
const id = generateMemId(idContent);
|
|
114
|
+
const sessionNode = {
|
|
115
|
+
id,
|
|
116
|
+
type: 'session',
|
|
117
|
+
lifecycle: 'wu',
|
|
118
|
+
content,
|
|
119
|
+
created_at: timestamp,
|
|
120
|
+
wu_id: wuId,
|
|
121
|
+
session_id: sessionId,
|
|
122
|
+
metadata: {
|
|
123
|
+
agentType,
|
|
124
|
+
contextTier,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
// Persist to memory store
|
|
128
|
+
await appendNode(memoryDir, sessionNode);
|
|
129
|
+
return {
|
|
130
|
+
success: true,
|
|
131
|
+
session: sessionNode,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mem-start-core.js","sourceRoot":"","sources":["../src/mem-start-core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Summarize Core (WU-1471)
|
|
3
|
+
*
|
|
4
|
+
* Rollup older memory nodes into summary nodes for compaction.
|
|
5
|
+
* Implements forgetting as first-class feature.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Aggregate checkpoint/note/discovery nodes into summaries
|
|
9
|
+
* - Mark originals for cleanup after summary creation
|
|
10
|
+
* - Respect lifecycle TTL (ephemeral, session, wu, project)
|
|
11
|
+
* - Support dry-run mode for preview
|
|
12
|
+
*
|
|
13
|
+
* @see {@link tools/mem-summarize.mjs} - CLI wrapper
|
|
14
|
+
* @see {@link tools/__tests__/mem-summarize.test.mjs} - Tests
|
|
15
|
+
*/
|
|
16
|
+
import { type MemoryNode } from './memory-schema.js';
|
|
17
|
+
/**
|
|
18
|
+
* Summarize options
|
|
19
|
+
*/
|
|
20
|
+
export interface SummarizeOptions {
|
|
21
|
+
/** WU ID to summarize (e.g., 'WU-1234') */
|
|
22
|
+
wuId: string;
|
|
23
|
+
/** If true, preview without modifications */
|
|
24
|
+
dryRun?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Summary node structure
|
|
28
|
+
*/
|
|
29
|
+
interface SummaryNode {
|
|
30
|
+
id: string;
|
|
31
|
+
type: 'summary';
|
|
32
|
+
lifecycle: 'project';
|
|
33
|
+
content: string;
|
|
34
|
+
created_at: string;
|
|
35
|
+
wu_id: string;
|
|
36
|
+
metadata: {
|
|
37
|
+
source_nodes: string[];
|
|
38
|
+
source_count: number;
|
|
39
|
+
summarized_at: string;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Summarize result
|
|
44
|
+
*/
|
|
45
|
+
export interface SummarizeResult {
|
|
46
|
+
/** Whether summarization succeeded */
|
|
47
|
+
success: boolean;
|
|
48
|
+
/** Created summary node */
|
|
49
|
+
summary: SummaryNode;
|
|
50
|
+
/** Node IDs marked for cleanup */
|
|
51
|
+
markedForCleanup: string[];
|
|
52
|
+
/** True if in dry-run mode */
|
|
53
|
+
dryRun?: boolean;
|
|
54
|
+
/** Ratio of source nodes to summary */
|
|
55
|
+
compactionRatio: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Filter nodes that can be summarized for a given WU.
|
|
59
|
+
*
|
|
60
|
+
* Excludes:
|
|
61
|
+
* - Nodes from different WUs
|
|
62
|
+
* - Ephemeral lifecycle nodes (already transient)
|
|
63
|
+
* - Already-summarized nodes (have summarized_into metadata)
|
|
64
|
+
* - Summary nodes themselves
|
|
65
|
+
*
|
|
66
|
+
* @param nodes - All memory nodes
|
|
67
|
+
* @param wuId - WU ID to filter by
|
|
68
|
+
* @returns Summarizable nodes
|
|
69
|
+
*/
|
|
70
|
+
export declare function filterSummarizableNodes(nodes: MemoryNode[], wuId: string): MemoryNode[];
|
|
71
|
+
/**
|
|
72
|
+
* Calculate compaction ratio (source nodes / summary nodes).
|
|
73
|
+
*
|
|
74
|
+
* @param sourceCount - Number of source nodes
|
|
75
|
+
* @param summaryCount - Number of summary nodes created
|
|
76
|
+
* @returns Compaction ratio (0 if invalid input)
|
|
77
|
+
*/
|
|
78
|
+
export declare function getCompactionRatio(sourceCount: number, summaryCount: number): number;
|
|
79
|
+
/**
|
|
80
|
+
* Summarize memory nodes for a closed WU.
|
|
81
|
+
*
|
|
82
|
+
* Aggregates checkpoint, note, and discovery nodes into a single
|
|
83
|
+
* summary node. Original nodes are marked for cleanup (unless
|
|
84
|
+
* they have project lifecycle).
|
|
85
|
+
*
|
|
86
|
+
* @param baseDir - Base directory containing .beacon/memory/
|
|
87
|
+
* @param options - Summarization options
|
|
88
|
+
* @returns Result with summary and cleanup info
|
|
89
|
+
* @throws If no summarizable nodes found for WU
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* // Summarize nodes for a completed WU
|
|
93
|
+
* const result = await summarizeWu(baseDir, { wuId: 'WU-1234' });
|
|
94
|
+
* console.log(`Created summary ${result.summary.id}`);
|
|
95
|
+
* console.log(`Compaction ratio: ${result.compactionRatio}:1`);
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* // Preview without modifications
|
|
99
|
+
* const preview = await summarizeWu(baseDir, {
|
|
100
|
+
* wuId: 'WU-1234',
|
|
101
|
+
* dryRun: true,
|
|
102
|
+
* });
|
|
103
|
+
*/
|
|
104
|
+
export declare function summarizeWu(baseDir: string, options: SummarizeOptions): Promise<SummarizeResult>;
|
|
105
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mem-summarize-core.d.ts","sourceRoot":"","sources":["../src/mem-summarize-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAuBH;;GAEG;AAEH;;;;GAIG;AAEH;;;;;;;GAOG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,KAAA,EAAE,IAAI,KAAA,OAyBlD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,KAAA,EAAE,YAAY,KAAA,UAK3D;AAqID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,WAAW,CAAC,OAAO,KAAA,EAAE,OAAO,KAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDjD"}
|