compact-agent 1.8.4 → 1.10.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/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/index.js +145 -5
- package/dist/index.js.map +1 -1
- package/dist/mempalace/index.d.ts +100 -0
- package/dist/mempalace/index.js +196 -0
- package/dist/mempalace/index.js.map +1 -0
- package/dist/mempalace/search.d.ts +38 -0
- package/dist/mempalace/search.js +133 -0
- package/dist/mempalace/search.js.map +1 -0
- package/dist/mempalace/store.d.ts +77 -0
- package/dist/mempalace/store.js +332 -0
- package/dist/mempalace/store.js.map +1 -0
- package/dist/mempalace/types.d.ts +140 -0
- package/dist/mempalace/types.js +27 -0
- package/dist/mempalace/types.js.map +1 -0
- package/dist/permissions.js +16 -3
- package/dist/permissions.js.map +1 -1
- package/dist/query.js +8 -0
- package/dist/query.js.map +1 -1
- package/dist/system-prompt.js +41 -0
- package/dist/system-prompt.js.map +1 -1
- package/dist/tools/index.js +3 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/memory.d.ts +30 -0
- package/dist/tools/memory.js +319 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/turn-context.d.ts +43 -0
- package/dist/turn-context.js +123 -0
- package/dist/turn-context.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +5 -2
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemPalace storage layer.
|
|
3
|
+
*
|
|
4
|
+
* Each store is a single JSON file written atomically (tmp file + rename)
|
|
5
|
+
* so a crashed write can't corrupt the existing state. The choice of JSON-
|
|
6
|
+
* over-SQLite is deliberate for v1: zero native dependencies, trivial to
|
|
7
|
+
* inspect by hand, no migration story needed for npm-published CLI.
|
|
8
|
+
*
|
|
9
|
+
* The Store interface is the swappable seam — when we outgrow JSON (>~10k
|
|
10
|
+
* drawers, slow search) we replace the implementation with SQLite/FTS5 or
|
|
11
|
+
* a vector store without touching callers.
|
|
12
|
+
*/
|
|
13
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync, unlinkSync } from 'node:fs';
|
|
14
|
+
import { join, dirname } from 'node:path';
|
|
15
|
+
import { homedir } from 'node:os';
|
|
16
|
+
import { randomBytes } from 'node:crypto';
|
|
17
|
+
import { SCHEMA_VERSION } from './types.js';
|
|
18
|
+
import { searchDrawers } from './search.js';
|
|
19
|
+
// ── Paths ─────────────────────────────────────────────────
|
|
20
|
+
/** ~/.crowcoder/memory/store.json — cross-project knowledge */
|
|
21
|
+
export function globalStorePath() {
|
|
22
|
+
return join(homedir(), '.crowcoder', 'memory', 'store.json');
|
|
23
|
+
}
|
|
24
|
+
/** <cwd>/.crowcoder/memory/store.json — per-repo knowledge */
|
|
25
|
+
export function projectStorePath(cwd) {
|
|
26
|
+
return join(cwd, '.crowcoder', 'memory', 'store.json');
|
|
27
|
+
}
|
|
28
|
+
// ── ID generation ─────────────────────────────────────────
|
|
29
|
+
/**
|
|
30
|
+
* Time-ordered ID: hex timestamp + 8 random hex chars. Sorts naturally by
|
|
31
|
+
* creation time, no UUID library needed. ~96 bits of entropy total which
|
|
32
|
+
* is overkill for a single-user store but keeps collision chances at
|
|
33
|
+
* effective zero even across machines.
|
|
34
|
+
*/
|
|
35
|
+
export function newId(prefix) {
|
|
36
|
+
const ts = Date.now().toString(16).padStart(11, '0');
|
|
37
|
+
const rand = randomBytes(4).toString('hex');
|
|
38
|
+
return `${prefix}_${ts}${rand}`;
|
|
39
|
+
}
|
|
40
|
+
// ── Atomic JSON read/write ────────────────────────────────
|
|
41
|
+
function readState(path) {
|
|
42
|
+
if (!existsSync(path)) {
|
|
43
|
+
return { schemaVersion: SCHEMA_VERSION, drawers: [], tunnels: [], triples: [] };
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const raw = readFileSync(path, 'utf-8');
|
|
47
|
+
const parsed = JSON.parse(raw);
|
|
48
|
+
// Defensive: future schema migrations would dispatch on parsed.schemaVersion here
|
|
49
|
+
return {
|
|
50
|
+
schemaVersion: parsed.schemaVersion ?? SCHEMA_VERSION,
|
|
51
|
+
drawers: parsed.drawers ?? [],
|
|
52
|
+
tunnels: parsed.tunnels ?? [],
|
|
53
|
+
triples: parsed.triples ?? [],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Corrupted store — log and return empty so we don't crash the agent.
|
|
58
|
+
// The bad file is preserved alongside as .corrupt for forensic recovery.
|
|
59
|
+
try {
|
|
60
|
+
renameSync(path, path + '.corrupt-' + Date.now());
|
|
61
|
+
}
|
|
62
|
+
catch { /* noop */ }
|
|
63
|
+
return { schemaVersion: SCHEMA_VERSION, drawers: [], tunnels: [], triples: [] };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function writeState(path, state) {
|
|
67
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
68
|
+
const tmp = path + '.tmp-' + process.pid;
|
|
69
|
+
writeFileSync(tmp, JSON.stringify(state, null, 2), 'utf-8');
|
|
70
|
+
try {
|
|
71
|
+
renameSync(tmp, path);
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
// On some Windows filesystems renaming over an existing file can fail.
|
|
75
|
+
// Fall back to unlink + rename.
|
|
76
|
+
try {
|
|
77
|
+
unlinkSync(path);
|
|
78
|
+
}
|
|
79
|
+
catch { /* noop */ }
|
|
80
|
+
renameSync(tmp, path);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// ── Store class ───────────────────────────────────────────
|
|
84
|
+
/**
|
|
85
|
+
* A single-file MemPalace store backed by JSON. Mutations are immediately
|
|
86
|
+
* persisted to disk — there's no in-memory cache to flush. Trades a small
|
|
87
|
+
* amount of throughput for crash safety, which matters more for a memory
|
|
88
|
+
* system.
|
|
89
|
+
*/
|
|
90
|
+
export class JsonStore {
|
|
91
|
+
path;
|
|
92
|
+
scope;
|
|
93
|
+
constructor(path, scope) {
|
|
94
|
+
this.path = path;
|
|
95
|
+
this.scope = scope;
|
|
96
|
+
}
|
|
97
|
+
read() { return readState(this.path); }
|
|
98
|
+
write(s) { writeState(this.path, s); }
|
|
99
|
+
// ── Drawers ───────────────────────────────────────────
|
|
100
|
+
addDrawer(input) {
|
|
101
|
+
const now = new Date().toISOString();
|
|
102
|
+
const drawer = {
|
|
103
|
+
id: newId('drw'),
|
|
104
|
+
createdAt: now,
|
|
105
|
+
updatedAt: now,
|
|
106
|
+
scope: this.scope,
|
|
107
|
+
...input,
|
|
108
|
+
// Defensive normalization
|
|
109
|
+
tags: (input.tags || []).map((t) => t.toLowerCase().trim()).filter(Boolean),
|
|
110
|
+
importance: clamp01(input.importance ?? 0.5),
|
|
111
|
+
wing: input.wing.toLowerCase().trim(),
|
|
112
|
+
room: input.room.toLowerCase().trim(),
|
|
113
|
+
};
|
|
114
|
+
const state = this.read();
|
|
115
|
+
state.drawers.push(drawer);
|
|
116
|
+
this.write(state);
|
|
117
|
+
return drawer;
|
|
118
|
+
}
|
|
119
|
+
getDrawer(id) {
|
|
120
|
+
return this.read().drawers.find((d) => d.id === id) || null;
|
|
121
|
+
}
|
|
122
|
+
updateDrawer(id, patch) {
|
|
123
|
+
const state = this.read();
|
|
124
|
+
const idx = state.drawers.findIndex((d) => d.id === id);
|
|
125
|
+
if (idx < 0)
|
|
126
|
+
return null;
|
|
127
|
+
const updated = {
|
|
128
|
+
...state.drawers[idx],
|
|
129
|
+
...patch,
|
|
130
|
+
updatedAt: new Date().toISOString(),
|
|
131
|
+
tags: patch.tags
|
|
132
|
+
? patch.tags.map((t) => t.toLowerCase().trim()).filter(Boolean)
|
|
133
|
+
: state.drawers[idx].tags,
|
|
134
|
+
importance: patch.importance !== undefined ? clamp01(patch.importance) : state.drawers[idx].importance,
|
|
135
|
+
};
|
|
136
|
+
state.drawers[idx] = updated;
|
|
137
|
+
this.write(state);
|
|
138
|
+
return updated;
|
|
139
|
+
}
|
|
140
|
+
deleteDrawer(id) {
|
|
141
|
+
const state = this.read();
|
|
142
|
+
const before = state.drawers.length;
|
|
143
|
+
state.drawers = state.drawers.filter((d) => d.id !== id);
|
|
144
|
+
// Cascade: drop tunnels touching this drawer + triples sourced from it
|
|
145
|
+
state.tunnels = state.tunnels.filter((t) => t.fromDrawerId !== id && t.toDrawerId !== id);
|
|
146
|
+
state.triples = state.triples.filter((t) => t.sourceDrawerId !== id);
|
|
147
|
+
const removed = state.drawers.length < before;
|
|
148
|
+
if (removed)
|
|
149
|
+
this.write(state);
|
|
150
|
+
return removed;
|
|
151
|
+
}
|
|
152
|
+
listDrawers(filter = {}) {
|
|
153
|
+
let drawers = this.read().drawers;
|
|
154
|
+
if (filter.wing)
|
|
155
|
+
drawers = drawers.filter((d) => d.wing === filter.wing.toLowerCase());
|
|
156
|
+
if (filter.room)
|
|
157
|
+
drawers = drawers.filter((d) => d.room === filter.room.toLowerCase());
|
|
158
|
+
if (filter.tag)
|
|
159
|
+
drawers = drawers.filter((d) => d.tags.includes(filter.tag.toLowerCase()));
|
|
160
|
+
return drawers;
|
|
161
|
+
}
|
|
162
|
+
// ── Wings + Rooms (derived views) ─────────────────────
|
|
163
|
+
listWings() {
|
|
164
|
+
const drawers = this.read().drawers;
|
|
165
|
+
const byWing = new Map();
|
|
166
|
+
for (const d of drawers) {
|
|
167
|
+
const entry = byWing.get(d.wing) ?? { rooms: new Set(), count: 0 };
|
|
168
|
+
entry.rooms.add(d.room);
|
|
169
|
+
entry.count++;
|
|
170
|
+
byWing.set(d.wing, entry);
|
|
171
|
+
}
|
|
172
|
+
return [...byWing.entries()]
|
|
173
|
+
.map(([name, v]) => ({ name, rooms: [...v.rooms].sort(), drawerCount: v.count }))
|
|
174
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
175
|
+
}
|
|
176
|
+
listRooms(wing) {
|
|
177
|
+
const drawers = this.read().drawers;
|
|
178
|
+
const filtered = wing ? drawers.filter((d) => d.wing === wing.toLowerCase()) : drawers;
|
|
179
|
+
const byRoom = new Map();
|
|
180
|
+
for (const d of filtered) {
|
|
181
|
+
const key = `${d.wing}/${d.room}`;
|
|
182
|
+
const entry = byRoom.get(key) ?? { wing: d.wing, count: 0, lastTouched: d.updatedAt };
|
|
183
|
+
entry.count++;
|
|
184
|
+
if (d.updatedAt > entry.lastTouched)
|
|
185
|
+
entry.lastTouched = d.updatedAt;
|
|
186
|
+
byRoom.set(key, entry);
|
|
187
|
+
}
|
|
188
|
+
return [...byRoom.entries()]
|
|
189
|
+
.map(([key, v]) => ({
|
|
190
|
+
wing: v.wing,
|
|
191
|
+
name: key.split('/')[1],
|
|
192
|
+
drawerCount: v.count,
|
|
193
|
+
lastTouched: v.lastTouched,
|
|
194
|
+
}))
|
|
195
|
+
.sort((a, b) => b.lastTouched.localeCompare(a.lastTouched));
|
|
196
|
+
}
|
|
197
|
+
// ── Tunnels (drawer relationships) ────────────────────
|
|
198
|
+
addTunnel(fromDrawerId, toDrawerId, relation) {
|
|
199
|
+
const tunnel = {
|
|
200
|
+
id: newId('tun'),
|
|
201
|
+
fromDrawerId,
|
|
202
|
+
toDrawerId,
|
|
203
|
+
relation: relation.toLowerCase().trim(),
|
|
204
|
+
createdAt: new Date().toISOString(),
|
|
205
|
+
scope: this.scope,
|
|
206
|
+
};
|
|
207
|
+
const state = this.read();
|
|
208
|
+
state.tunnels.push(tunnel);
|
|
209
|
+
this.write(state);
|
|
210
|
+
return tunnel;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Find all tunnels touching a drawer, in either direction. Useful for
|
|
214
|
+
* "what is this drawer related to?" queries.
|
|
215
|
+
*/
|
|
216
|
+
findTunnels(drawerId) {
|
|
217
|
+
const tunnels = this.read().tunnels;
|
|
218
|
+
return {
|
|
219
|
+
outgoing: tunnels.filter((t) => t.fromDrawerId === drawerId),
|
|
220
|
+
incoming: tunnels.filter((t) => t.toDrawerId === drawerId),
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Walk outgoing tunnels from a start drawer for up to maxDepth hops,
|
|
225
|
+
* returning every drawer reached and the path that got us there.
|
|
226
|
+
* Bounded by visited-set so cycles don't loop forever.
|
|
227
|
+
*/
|
|
228
|
+
traverse(startId, maxDepth = 3) {
|
|
229
|
+
const state = this.read();
|
|
230
|
+
const drawerById = new Map(state.drawers.map((d) => [d.id, d]));
|
|
231
|
+
const tunnelsByFrom = new Map();
|
|
232
|
+
for (const t of state.tunnels) {
|
|
233
|
+
const arr = tunnelsByFrom.get(t.fromDrawerId) ?? [];
|
|
234
|
+
arr.push(t);
|
|
235
|
+
tunnelsByFrom.set(t.fromDrawerId, arr);
|
|
236
|
+
}
|
|
237
|
+
const visited = new Set();
|
|
238
|
+
const results = [];
|
|
239
|
+
const queue = [{ id: startId, depth: 0, via: [] }];
|
|
240
|
+
while (queue.length > 0) {
|
|
241
|
+
const cur = queue.shift();
|
|
242
|
+
if (visited.has(cur.id))
|
|
243
|
+
continue;
|
|
244
|
+
visited.add(cur.id);
|
|
245
|
+
const drawer = drawerById.get(cur.id);
|
|
246
|
+
if (drawer && cur.depth > 0) {
|
|
247
|
+
results.push({ drawer, depth: cur.depth, via: cur.via });
|
|
248
|
+
}
|
|
249
|
+
if (cur.depth >= maxDepth)
|
|
250
|
+
continue;
|
|
251
|
+
const outgoing = tunnelsByFrom.get(cur.id) ?? [];
|
|
252
|
+
for (const t of outgoing) {
|
|
253
|
+
if (!visited.has(t.toDrawerId)) {
|
|
254
|
+
queue.push({ id: t.toDrawerId, depth: cur.depth + 1, via: [...cur.via, t.relation] });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return results;
|
|
259
|
+
}
|
|
260
|
+
deleteTunnel(id) {
|
|
261
|
+
const state = this.read();
|
|
262
|
+
const before = state.tunnels.length;
|
|
263
|
+
state.tunnels = state.tunnels.filter((t) => t.id !== id);
|
|
264
|
+
const removed = state.tunnels.length < before;
|
|
265
|
+
if (removed)
|
|
266
|
+
this.write(state);
|
|
267
|
+
return removed;
|
|
268
|
+
}
|
|
269
|
+
// ── Knowledge graph triples ───────────────────────────
|
|
270
|
+
addTriple(t) {
|
|
271
|
+
const triple = {
|
|
272
|
+
...t,
|
|
273
|
+
id: newId('kg'),
|
|
274
|
+
createdAt: new Date().toISOString(),
|
|
275
|
+
scope: this.scope,
|
|
276
|
+
confidence: clamp01(t.confidence ?? 1.0),
|
|
277
|
+
};
|
|
278
|
+
const state = this.read();
|
|
279
|
+
state.triples.push(triple);
|
|
280
|
+
this.write(state);
|
|
281
|
+
return triple;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Query triples with optional s/p/o filters. Any field left undefined
|
|
285
|
+
* acts as a wildcard. Matching is case-insensitive equality on each
|
|
286
|
+
* specified field.
|
|
287
|
+
*/
|
|
288
|
+
queryTriples(q) {
|
|
289
|
+
const triples = this.read().triples;
|
|
290
|
+
const lc = (s) => s?.toLowerCase();
|
|
291
|
+
const s = lc(q.subject);
|
|
292
|
+
const p = lc(q.predicate);
|
|
293
|
+
const o = lc(q.object);
|
|
294
|
+
return triples.filter((t) => (s === undefined || t.subject.toLowerCase() === s) &&
|
|
295
|
+
(p === undefined || t.predicate.toLowerCase() === p) &&
|
|
296
|
+
(o === undefined || t.object.toLowerCase() === o));
|
|
297
|
+
}
|
|
298
|
+
/** Most-recent triples first. For "what have I been learning?" views. */
|
|
299
|
+
recentTriples(limit = 20) {
|
|
300
|
+
return [...this.read().triples]
|
|
301
|
+
.sort((a, b) => b.createdAt.localeCompare(a.createdAt))
|
|
302
|
+
.slice(0, limit);
|
|
303
|
+
}
|
|
304
|
+
// ── Search ────────────────────────────────────────────
|
|
305
|
+
search(query, opts = {}) {
|
|
306
|
+
const drawers = this.read().drawers;
|
|
307
|
+
return searchDrawers(drawers, query, opts);
|
|
308
|
+
}
|
|
309
|
+
// ── Stats ─────────────────────────────────────────────
|
|
310
|
+
stats() {
|
|
311
|
+
const state = this.read();
|
|
312
|
+
const wings = new Set(state.drawers.map((d) => d.wing));
|
|
313
|
+
const rooms = new Set(state.drawers.map((d) => `${d.wing}/${d.room}`));
|
|
314
|
+
return {
|
|
315
|
+
drawers: state.drawers.length,
|
|
316
|
+
tunnels: state.tunnels.length,
|
|
317
|
+
triples: state.triples.length,
|
|
318
|
+
wings: wings.size,
|
|
319
|
+
rooms: rooms.size,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
function clamp01(n) {
|
|
324
|
+
if (Number.isNaN(n))
|
|
325
|
+
return 0.5;
|
|
326
|
+
if (n < 0)
|
|
327
|
+
return 0;
|
|
328
|
+
if (n > 1)
|
|
329
|
+
return 1;
|
|
330
|
+
return n;
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/mempalace/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemPalace data model — TypeScript port of the core MemPalace concepts.
|
|
3
|
+
*
|
|
4
|
+
* Mental model:
|
|
5
|
+
*
|
|
6
|
+
* Wing ─ a top-level domain ("projects", "people", "code", "wisdom")
|
|
7
|
+
* Room ─ a category inside a wing ("crowcoder", "abc-reborn", ...)
|
|
8
|
+
* Drawer ─ an individual memory item: a chunk of text + tags + metadata
|
|
9
|
+
* Tunnel ─ a directed link between two drawers, typed by relation
|
|
10
|
+
* Triple ─ a knowledge-graph fact: (subject, predicate, object)
|
|
11
|
+
*
|
|
12
|
+
* Drawers are the atomic unit of memory. Wings + rooms give them addressable
|
|
13
|
+
* structure. Tunnels and KG triples give them relational structure.
|
|
14
|
+
*
|
|
15
|
+
* Two stores live side-by-side:
|
|
16
|
+
* GLOBAL ~/.crowcoder/memory/ cross-project knowledge (user prefs,
|
|
17
|
+
* recurring patterns, skills)
|
|
18
|
+
* PROJECT <cwd>/.crowcoder/memory/ this-codebase-specific (e.g. "build
|
|
19
|
+
* is broken because X", "the queue lives
|
|
20
|
+
* in services/queue/...")
|
|
21
|
+
*
|
|
22
|
+
* The agent picks which store to query based on the request. User-modeling
|
|
23
|
+
* queries hit global; codebase queries hit project. Search APIs accept a
|
|
24
|
+
* Scope hint or 'both' to search across.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Which memory store an operation targets.
|
|
28
|
+
*
|
|
29
|
+
* 'global' — ~/.crowcoder/memory/ (cross-project)
|
|
30
|
+
* 'project' — <cwd>/.crowcoder/memory/ (per-repo)
|
|
31
|
+
* 'both' — search both; writes pick based on content (global for user
|
|
32
|
+
* preferences, project for codebase facts)
|
|
33
|
+
*/
|
|
34
|
+
export type Scope = 'global' | 'project' | 'both';
|
|
35
|
+
/**
|
|
36
|
+
* A drawer is one memory item — a chunk of text living at wing/room. Tags
|
|
37
|
+
* are free-form lowercase strings used for filtering. Importance is a 0–1
|
|
38
|
+
* heuristic the agent or user can set to bias search ordering.
|
|
39
|
+
*/
|
|
40
|
+
export interface Drawer {
|
|
41
|
+
id: string;
|
|
42
|
+
wing: string;
|
|
43
|
+
room: string;
|
|
44
|
+
content: string;
|
|
45
|
+
tags: string[];
|
|
46
|
+
importance: number;
|
|
47
|
+
createdAt: string;
|
|
48
|
+
updatedAt: string;
|
|
49
|
+
scope: Scope;
|
|
50
|
+
sourceSessionId?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Convenience metadata about a wing — populated by `listWings` for UI/
|
|
54
|
+
* status output. Not stored separately; derived from drawer counts.
|
|
55
|
+
*/
|
|
56
|
+
export interface WingMeta {
|
|
57
|
+
name: string;
|
|
58
|
+
rooms: string[];
|
|
59
|
+
drawerCount: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Same for rooms.
|
|
63
|
+
*/
|
|
64
|
+
export interface RoomMeta {
|
|
65
|
+
wing: string;
|
|
66
|
+
name: string;
|
|
67
|
+
drawerCount: number;
|
|
68
|
+
lastTouched: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* A tunnel is a directed link from one drawer to another with a labelled
|
|
72
|
+
* relation. Use cases:
|
|
73
|
+
* - "drawer A inspired drawer B" (relation: "inspired")
|
|
74
|
+
* - "drawer A supersedes drawer B" (relation: "supersedes")
|
|
75
|
+
* - "drawer A is part of drawer B's project" (relation: "in-project")
|
|
76
|
+
*
|
|
77
|
+
* Bidirectional traversal is supported by following tunnels in reverse.
|
|
78
|
+
*/
|
|
79
|
+
export interface Tunnel {
|
|
80
|
+
id: string;
|
|
81
|
+
fromDrawerId: string;
|
|
82
|
+
toDrawerId: string;
|
|
83
|
+
relation: string;
|
|
84
|
+
createdAt: string;
|
|
85
|
+
scope: Scope;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A knowledge-graph triple — semantic-web style. Stored separately from
|
|
89
|
+
* drawers because triples express *facts* (small, atomic, queryable in
|
|
90
|
+
* aggregate) whereas drawers express *content* (larger, narrative).
|
|
91
|
+
*
|
|
92
|
+
* Example: ("rsfit", "owns", "Crowcoder") or ("compact-agent", "uses",
|
|
93
|
+
* "OpenRouter").
|
|
94
|
+
*/
|
|
95
|
+
export interface KGTriple {
|
|
96
|
+
id: string;
|
|
97
|
+
subject: string;
|
|
98
|
+
predicate: string;
|
|
99
|
+
object: string;
|
|
100
|
+
confidence: number;
|
|
101
|
+
sourceDrawerId?: string;
|
|
102
|
+
sourceSessionId?: string;
|
|
103
|
+
createdAt: string;
|
|
104
|
+
scope: Scope;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Internal disk schema. One JSON file per store containing all drawers,
|
|
108
|
+
* tunnels, and triples. Simple, atomic-write-via-rename safe.
|
|
109
|
+
*
|
|
110
|
+
* For very large stores (>10k drawers) this approach will get slow; the
|
|
111
|
+
* intent is to swap to SQLite/FTS5 later behind the same Store interface.
|
|
112
|
+
*/
|
|
113
|
+
export interface StoreState {
|
|
114
|
+
schemaVersion: number;
|
|
115
|
+
drawers: Drawer[];
|
|
116
|
+
tunnels: Tunnel[];
|
|
117
|
+
triples: KGTriple[];
|
|
118
|
+
}
|
|
119
|
+
export declare const SCHEMA_VERSION = 1;
|
|
120
|
+
/**
|
|
121
|
+
* Search options shared across query APIs.
|
|
122
|
+
*/
|
|
123
|
+
export interface SearchOptions {
|
|
124
|
+
scope?: Scope;
|
|
125
|
+
wing?: string;
|
|
126
|
+
room?: string;
|
|
127
|
+
tags?: string[];
|
|
128
|
+
limit?: number;
|
|
129
|
+
minImportance?: number;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* A scored search hit — the drawer plus the relevance score the search
|
|
133
|
+
* function computed. Higher = more relevant. Score is unitless; only
|
|
134
|
+
* meaningful for ordering, not absolute comparison.
|
|
135
|
+
*/
|
|
136
|
+
export interface SearchHit {
|
|
137
|
+
drawer: Drawer;
|
|
138
|
+
score: number;
|
|
139
|
+
matchedFields: ('content' | 'tags' | 'wing' | 'room')[];
|
|
140
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemPalace data model — TypeScript port of the core MemPalace concepts.
|
|
3
|
+
*
|
|
4
|
+
* Mental model:
|
|
5
|
+
*
|
|
6
|
+
* Wing ─ a top-level domain ("projects", "people", "code", "wisdom")
|
|
7
|
+
* Room ─ a category inside a wing ("crowcoder", "abc-reborn", ...)
|
|
8
|
+
* Drawer ─ an individual memory item: a chunk of text + tags + metadata
|
|
9
|
+
* Tunnel ─ a directed link between two drawers, typed by relation
|
|
10
|
+
* Triple ─ a knowledge-graph fact: (subject, predicate, object)
|
|
11
|
+
*
|
|
12
|
+
* Drawers are the atomic unit of memory. Wings + rooms give them addressable
|
|
13
|
+
* structure. Tunnels and KG triples give them relational structure.
|
|
14
|
+
*
|
|
15
|
+
* Two stores live side-by-side:
|
|
16
|
+
* GLOBAL ~/.crowcoder/memory/ cross-project knowledge (user prefs,
|
|
17
|
+
* recurring patterns, skills)
|
|
18
|
+
* PROJECT <cwd>/.crowcoder/memory/ this-codebase-specific (e.g. "build
|
|
19
|
+
* is broken because X", "the queue lives
|
|
20
|
+
* in services/queue/...")
|
|
21
|
+
*
|
|
22
|
+
* The agent picks which store to query based on the request. User-modeling
|
|
23
|
+
* queries hit global; codebase queries hit project. Search APIs accept a
|
|
24
|
+
* Scope hint or 'both' to search across.
|
|
25
|
+
*/
|
|
26
|
+
export const SCHEMA_VERSION = 1;
|
|
27
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mempalace/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AA6GH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC"}
|
package/dist/permissions.js
CHANGED
|
@@ -17,6 +17,14 @@ export async function checkPermission(tool, input, config, rl) {
|
|
|
17
17
|
// Read-only tools always allowed
|
|
18
18
|
if (tool.isReadOnly)
|
|
19
19
|
return true;
|
|
20
|
+
// Per-tool persistent allowlist. Populated by the "always" answer
|
|
21
|
+
// below. Checked BEFORE the destructive branch so a previous "always"
|
|
22
|
+
// on bash or write_file actually stops the next prompt. The earlier
|
|
23
|
+
// implementation only flipped the global mode to 'auto', which still
|
|
24
|
+
// prompts for tools marked isDestructive — that was the "I keep typing
|
|
25
|
+
// always but it keeps asking" bug.
|
|
26
|
+
if (config.alwaysAllowedTools?.includes(tool.name))
|
|
27
|
+
return true;
|
|
20
28
|
// auto mode = allow non-destructive, ask for destructive
|
|
21
29
|
if (config.permissionMode === 'auto' && !tool.isDestructive)
|
|
22
30
|
return true;
|
|
@@ -27,10 +35,15 @@ export async function checkPermission(tool, input, config, rl) {
|
|
|
27
35
|
const answer = await rl.question(chalk.yellow('Allow? [Y/n/always] '));
|
|
28
36
|
const a = answer.trim().toLowerCase();
|
|
29
37
|
if (a === 'always') {
|
|
30
|
-
//
|
|
31
|
-
|
|
38
|
+
// Persist as a per-tool allow. Old behavior also flipped permissionMode
|
|
39
|
+
// to 'auto', but that only helps non-destructive tools; per-tool list
|
|
40
|
+
// is the actual fix for destructive tools like bash + write_file.
|
|
41
|
+
config.alwaysAllowedTools = config.alwaysAllowedTools || [];
|
|
42
|
+
if (!config.alwaysAllowedTools.includes(tool.name)) {
|
|
43
|
+
config.alwaysAllowedTools.push(tool.name);
|
|
44
|
+
}
|
|
32
45
|
saveConfig(config);
|
|
33
|
-
console.log(chalk.dim(
|
|
46
|
+
console.log(chalk.dim(` (always-allowing ${tool.name} for this session and future sessions — clear with /perm-reset)`));
|
|
34
47
|
return true;
|
|
35
48
|
}
|
|
36
49
|
return a === '' || a === 'y' || a === 'yes';
|
package/dist/permissions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAU,EACV,KAA8B,EAC9B,MAAuB,EACvB,EAAsB;IAEtB,iCAAiC;IACjC,IAAI,MAAM,CAAC,cAAc,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAElD,iCAAiC;IACjC,IAAI,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAEjC,yDAAyD;IACzD,IAAI,MAAM,CAAC,cAAc,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAEzE,qDAAqD;IACrD,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAE7B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC;IACvE,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEtC,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QACnB,
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAU,EACV,KAA8B,EAC9B,MAAuB,EACvB,EAAsB;IAEtB,iCAAiC;IACjC,IAAI,MAAM,CAAC,cAAc,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAElD,iCAAiC;IACjC,IAAI,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAEjC,kEAAkE;IAClE,sEAAsE;IACtE,oEAAoE;IACpE,qEAAqE;IACrE,uEAAuE;IACvE,mCAAmC;IACnC,IAAI,MAAM,CAAC,kBAAkB,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEhE,yDAAyD;IACzD,IAAI,MAAM,CAAC,cAAc,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAEzE,qDAAqD;IACrD,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAE7B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC;IACvE,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEtC,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QACnB,wEAAwE;QACxE,sEAAsE;QACtE,kEAAkE;QAClE,MAAM,CAAC,kBAAkB,GAAG,MAAM,CAAC,kBAAkB,IAAI,EAAE,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,UAAU,CAAC,MAAM,CAAC,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,IAAI,CAAC,IAAI,iEAAiE,CAAC,CAAC,CAAC;QACzH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,CAAC;AAC9C,CAAC;AAED,SAAS,cAAc,CAAC,IAAU,EAAE,KAA8B;IAChE,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,MAAM;YACT,OAAO,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC;QAChC,KAAK,YAAY;YACf,OAAO,eAAe,KAAK,CAAC,SAAS,KAAK,CAAE,KAAK,CAAC,OAAkB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC;QAC1G,KAAK,WAAW;YACd,OAAO,WAAW,KAAK,CAAC,SAAS,EAAE,CAAC;QACtC;YACE,OAAO,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IACtD,CAAC;AACH,CAAC"}
|
package/dist/query.js
CHANGED
|
@@ -11,6 +11,7 @@ import { isVoiceEnabled, getTtsConfig, getAccessibilityConfig, speakAssistantRes
|
|
|
11
11
|
import { isLikelyDestructive, describeDestructive, countWords, summarize } from './accessibility.js';
|
|
12
12
|
import { audioCue } from './audio.js';
|
|
13
13
|
import { setStatus } from './status.js';
|
|
14
|
+
import { collapseCompletedTurns } from './turn-context.js';
|
|
14
15
|
function startInputSuppression() {
|
|
15
16
|
const stdin = process.stdin;
|
|
16
17
|
if (!stdin.isTTY) {
|
|
@@ -141,6 +142,13 @@ export async function runQuery(ctx) {
|
|
|
141
142
|
// the guard is always cleaned up even if something throws unexpectedly.
|
|
142
143
|
const inputGuard = startInputSuppression();
|
|
143
144
|
try {
|
|
145
|
+
// Turn-boundary collapse runs BEFORE compaction. Every completed prior
|
|
146
|
+
// turn becomes [user, "<final text>\n[Completed: used X, Y]"] — the
|
|
147
|
+
// model no longer sees stale tool_calls that it might mistake for
|
|
148
|
+
// pending work (the "I'll handle BOTH requests" / "all THREE requests"
|
|
149
|
+
// bug). The current turn (latest user message forward) is left intact
|
|
150
|
+
// because its tool_calls and tool messages are still in flight.
|
|
151
|
+
ctx.messages = collapseCompletedTurns(ctx.messages);
|
|
144
152
|
// Auto-compact if context is getting large
|
|
145
153
|
if (shouldCompact(ctx.messages, DEFAULT_COMPACTION)) {
|
|
146
154
|
console.log(theme.dim(` ${sym.running} auto-compacting conversation context...`));
|