claude-launchpad 1.15.0 → 1.17.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/{chunk-IPGNXDJF.js → chunk-IIOY56ZE.js} +2 -2
- package/dist/{chunk-DLDVXHI3.js → chunk-JKDFOKHD.js} +2 -2
- package/dist/{chunk-U2TFIUGE.js → chunk-KYGWNN5F.js} +38 -7
- package/dist/chunk-KYGWNN5F.js.map +1 -0
- package/dist/{chunk-IDH3M4EI.js → chunk-MRW63LDL.js} +6 -1
- package/dist/chunk-MRW63LDL.js.map +1 -0
- package/dist/{chunk-LCKV24Q3.js → chunk-ROQI7RKM.js} +4 -4
- package/dist/{chunk-MX3T2VEX.js → chunk-ULECXQFX.js} +3 -3
- package/dist/{chunk-7KB5YGQZ.js → chunk-YLIV5WBW.js} +2 -2
- package/dist/cli.js +69 -29
- package/dist/cli.js.map +1 -1
- package/dist/commands/memory/server.js +5 -5
- package/dist/{context-3GHG7KW6.js → context-K5B43NEI.js} +7 -7
- package/dist/{doctor-EKGJ2YAO.js → doctor-ESIQYNE4.js} +5 -5
- package/dist/{install-543ZKMXX.js → install-VREFJNLF.js} +9 -7
- package/dist/install-VREFJNLF.js.map +1 -0
- package/dist/{pull-ULSZEVCR.js → pull-H6ARY6DG.js} +9 -9
- package/dist/{push-JXCWX4NY.js → push-JDHT6AMD.js} +9 -9
- package/dist/{require-deps-AEDO5YRM.js → require-deps-GVBWF5PB.js} +3 -3
- package/dist/{stats-63L7C24W.js → stats-TWIVFA4I.js} +8 -8
- package/dist/{sync-QTJ6BXQ4.js → sync-WG7OOWOX.js} +5 -5
- package/dist/{sync-clean-OJEK4XH4.js → sync-clean-GQUFTYG2.js} +3 -3
- package/dist/{sync-status-EAX527SC.js → sync-status-B3DKLET4.js} +9 -9
- package/dist/{tui-3KITZCNS.js → tui-ZINEA7TI.js} +240 -74
- package/dist/tui-ZINEA7TI.js.map +1 -0
- package/package.json +2 -1
- package/dist/chunk-IDH3M4EI.js.map +0 -1
- package/dist/chunk-U2TFIUGE.js.map +0 -1
- package/dist/install-543ZKMXX.js.map +0 -1
- package/dist/tui-3KITZCNS.js.map +0 -1
- /package/dist/{chunk-IPGNXDJF.js.map → chunk-IIOY56ZE.js.map} +0 -0
- /package/dist/{chunk-DLDVXHI3.js.map → chunk-JKDFOKHD.js.map} +0 -0
- /package/dist/{chunk-LCKV24Q3.js.map → chunk-ROQI7RKM.js.map} +0 -0
- /package/dist/{chunk-MX3T2VEX.js.map → chunk-ULECXQFX.js.map} +0 -0
- /package/dist/{chunk-7KB5YGQZ.js.map → chunk-YLIV5WBW.js.map} +0 -0
- /package/dist/{context-3GHG7KW6.js.map → context-K5B43NEI.js.map} +0 -0
- /package/dist/{doctor-EKGJ2YAO.js.map → doctor-ESIQYNE4.js.map} +0 -0
- /package/dist/{pull-ULSZEVCR.js.map → pull-H6ARY6DG.js.map} +0 -0
- /package/dist/{push-JXCWX4NY.js.map → push-JDHT6AMD.js.map} +0 -0
- /package/dist/{require-deps-AEDO5YRM.js.map → require-deps-GVBWF5PB.js.map} +0 -0
- /package/dist/{stats-63L7C24W.js.map → stats-TWIVFA4I.js.map} +0 -0
- /package/dist/{sync-QTJ6BXQ4.js.map → sync-WG7OOWOX.js.map} +0 -0
- /package/dist/{sync-clean-OJEK4XH4.js.map → sync-clean-GQUFTYG2.js.map} +0 -0
- /package/dist/{sync-status-EAX527SC.js.map → sync-status-B3DKLET4.js.map} +0 -0
|
@@ -5,19 +5,19 @@ import {
|
|
|
5
5
|
} from "./chunk-HSGSTSVN.js";
|
|
6
6
|
import {
|
|
7
7
|
migrate
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ULECXQFX.js";
|
|
9
9
|
import {
|
|
10
10
|
MemoryRepo
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-MRW63LDL.js";
|
|
12
12
|
import {
|
|
13
13
|
DEFAULT_DECAY_PARAMS,
|
|
14
14
|
closeDatabase,
|
|
15
15
|
createDatabase,
|
|
16
16
|
loadConfig,
|
|
17
17
|
resolveDataDir
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-JKDFOKHD.js";
|
|
19
|
+
import "./chunk-YLIV5WBW.js";
|
|
20
|
+
import "./chunk-KYGWNN5F.js";
|
|
21
21
|
|
|
22
22
|
// src/commands/memory/dashboard/tui.tsx
|
|
23
23
|
import { render } from "ink";
|
|
@@ -31,6 +31,7 @@ var DashboardDataSource = class {
|
|
|
31
31
|
#searchRepo;
|
|
32
32
|
#dbPath;
|
|
33
33
|
#cachedMemories = [];
|
|
34
|
+
#relationsByMemory = /* @__PURE__ */ new Map();
|
|
34
35
|
constructor(memoryRepo, relationRepo, searchRepo, dataDir) {
|
|
35
36
|
this.#memoryRepo = memoryRepo;
|
|
36
37
|
this.#relationRepo = relationRepo;
|
|
@@ -40,6 +41,15 @@ var DashboardDataSource = class {
|
|
|
40
41
|
/** Re-query all memories from DB and cache them. Excludes soft-deleted (importance=0). */
|
|
41
42
|
refresh() {
|
|
42
43
|
this.#cachedMemories = this.#memoryRepo.getAll().filter((m) => m.importance > 0);
|
|
44
|
+
const byMemory = /* @__PURE__ */ new Map();
|
|
45
|
+
for (const r of this.#relationRepo.getAll()) {
|
|
46
|
+
for (const id of /* @__PURE__ */ new Set([r.sourceId, r.targetId])) {
|
|
47
|
+
const list = byMemory.get(id) ?? [];
|
|
48
|
+
list.push(r);
|
|
49
|
+
byMemory.set(id, list);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
this.#relationsByMemory = byMemory;
|
|
43
53
|
}
|
|
44
54
|
/** Return cached memories, optionally filtered by type, project, or FTS query. */
|
|
45
55
|
getMemories(filter) {
|
|
@@ -63,9 +73,13 @@ var DashboardDataSource = class {
|
|
|
63
73
|
}
|
|
64
74
|
return results;
|
|
65
75
|
}
|
|
66
|
-
/**
|
|
76
|
+
/** Resolve a memory id to its title for relation display (cache-only, no I/O). */
|
|
77
|
+
getMemoryTitle(id) {
|
|
78
|
+
const m = this.#cachedMemories.find((mem) => mem.id === id);
|
|
79
|
+
return m?.title ?? void 0;
|
|
80
|
+
}
|
|
67
81
|
getRelationsForMemory(id) {
|
|
68
|
-
return this.#
|
|
82
|
+
return this.#relationsByMemory.get(id) ?? [];
|
|
69
83
|
}
|
|
70
84
|
/** Compute aggregate stats from cached data + DB queries. */
|
|
71
85
|
getStats() {
|
|
@@ -98,9 +112,23 @@ var DashboardDataSource = class {
|
|
|
98
112
|
onChange();
|
|
99
113
|
});
|
|
100
114
|
}
|
|
101
|
-
/**
|
|
115
|
+
/** Soft-delete a memory; returns a snapshot for undo (null if not found). */
|
|
102
116
|
deleteMemory(id) {
|
|
103
|
-
|
|
117
|
+
const snapshot = this.#memoryRepo.getById(id);
|
|
118
|
+
if (!snapshot) return null;
|
|
119
|
+
this.#memoryRepo.softDelete(id);
|
|
120
|
+
return snapshot;
|
|
121
|
+
}
|
|
122
|
+
/** Undo a soft delete using the snapshot taken at delete time. */
|
|
123
|
+
restoreMemory(snapshot) {
|
|
124
|
+
return this.#memoryRepo.restoreImportance(snapshot.id, snapshot.importance, snapshot.baseImportance);
|
|
125
|
+
}
|
|
126
|
+
/** Curation edits from the TUI: explicit re-rate re-anchors the decay base. */
|
|
127
|
+
updateMemory(id, updates) {
|
|
128
|
+
return this.#memoryRepo.updateContent(id, {
|
|
129
|
+
...updates.importance !== void 0 ? { importance: updates.importance } : {},
|
|
130
|
+
...updates.tags !== void 0 ? { tags: updates.tags } : {}
|
|
131
|
+
});
|
|
104
132
|
}
|
|
105
133
|
/** Count memories for a project (unfiltered). */
|
|
106
134
|
countByProject(project) {
|
|
@@ -133,7 +161,7 @@ var DashboardDataSource = class {
|
|
|
133
161
|
};
|
|
134
162
|
|
|
135
163
|
// src/commands/memory/dashboard/app.tsx
|
|
136
|
-
import { Box as
|
|
164
|
+
import { Box as Box14, Text as Text14, useApp } from "ink";
|
|
137
165
|
|
|
138
166
|
// src/commands/memory/dashboard/hooks/use-dashboard-state.ts
|
|
139
167
|
import { useState, useMemo, useEffect, useCallback } from "react";
|
|
@@ -230,12 +258,15 @@ function useDashboardState(dataSource) {
|
|
|
230
258
|
const [currentProject, setCurrentProject] = useState();
|
|
231
259
|
const [sortMode, setSortMode] = useState("importance");
|
|
232
260
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
233
|
-
const [focusedPane, setFocusedPane] = useState("list");
|
|
234
261
|
const [showHelp, setShowHelp] = useState(false);
|
|
235
262
|
const [showProjectPicker, setShowProjectPicker] = useState(false);
|
|
236
263
|
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
|
237
264
|
const [showPurgeConfirm, setShowPurgeConfirm] = useState(false);
|
|
238
265
|
const [showExpand, setShowExpand] = useState(false);
|
|
266
|
+
const [showTagEditor, setShowTagEditor] = useState(false);
|
|
267
|
+
const [tagDraft, setTagDraft] = useState("");
|
|
268
|
+
const [lastDeleted, setLastDeleted] = useState(null);
|
|
269
|
+
const [notice, setNotice] = useState(null);
|
|
239
270
|
useEffect(() => {
|
|
240
271
|
dataSource.refresh();
|
|
241
272
|
setRevision((r) => r + 1);
|
|
@@ -251,14 +282,12 @@ function useDashboardState(dataSource) {
|
|
|
251
282
|
}, [dataSource, revision]);
|
|
252
283
|
const filteredMemories = useMemo(() => {
|
|
253
284
|
void revision;
|
|
254
|
-
const raw = dataSource.getMemories({ type: typeFilter, project: currentProject });
|
|
285
|
+
const raw = dataSource.getMemories({ type: typeFilter, project: currentProject, query: searchQuery || void 0 });
|
|
255
286
|
const withLife = lifespanFilter ? raw.filter((m) => computeLifespan(m).status === lifespanFilter) : raw;
|
|
256
|
-
|
|
257
|
-
(m) => (m.title?.toLowerCase().includes(searchQuery.toLowerCase()) ?? false) || m.content.toLowerCase().includes(searchQuery.toLowerCase()) || m.tags.some((t) => t.toLowerCase().includes(searchQuery.toLowerCase()))
|
|
258
|
-
) : withLife;
|
|
259
|
-
return sortMemories(withSearch, sortMode);
|
|
287
|
+
return sortMemories(withLife, sortMode);
|
|
260
288
|
}, [dataSource, revision, typeFilter, lifespanFilter, searchQuery, currentProject, sortMode]);
|
|
261
|
-
const
|
|
289
|
+
const clampedIndex = Math.max(0, Math.min(selectedIndex, Math.max(0, filteredMemories.length - 1)));
|
|
290
|
+
const selectedMemory = filteredMemories[clampedIndex];
|
|
262
291
|
const relations = useMemo(
|
|
263
292
|
() => selectedMemory ? dataSource.getRelationsForMemory(selectedMemory.id) : [],
|
|
264
293
|
[dataSource, selectedMemory, revision]
|
|
@@ -268,10 +297,12 @@ function useDashboardState(dataSource) {
|
|
|
268
297
|
return dataSource.getStats();
|
|
269
298
|
}, [dataSource, revision]);
|
|
270
299
|
const navigateUp = useCallback(() => {
|
|
271
|
-
|
|
272
|
-
|
|
300
|
+
const last = filteredMemories.length - 1;
|
|
301
|
+
setSelectedIndex((i) => Math.max(0, Math.min(i, last) - 1));
|
|
302
|
+
}, [filteredMemories.length]);
|
|
273
303
|
const navigateDown = useCallback(() => {
|
|
274
|
-
|
|
304
|
+
const last = filteredMemories.length - 1;
|
|
305
|
+
setSelectedIndex((i) => Math.max(0, Math.min(last, Math.min(i, last) + 1)));
|
|
275
306
|
}, [filteredMemories.length]);
|
|
276
307
|
const cycleSort = useCallback(() => {
|
|
277
308
|
setSortMode((m) => SORT_MODES[(SORT_MODES.indexOf(m) + 1) % SORT_MODES.length]);
|
|
@@ -296,14 +327,15 @@ function useDashboardState(dataSource) {
|
|
|
296
327
|
});
|
|
297
328
|
setSelectedIndex(0);
|
|
298
329
|
}, [projects]);
|
|
299
|
-
const focusNext = useCallback(() => {
|
|
300
|
-
setFocusedPane((p) => p === "list" ? "projects" : p === "projects" ? "detail" : "list");
|
|
301
|
-
}, []);
|
|
302
330
|
const filterByType = useCallback((type) => {
|
|
303
331
|
setTypeFilter(type);
|
|
304
332
|
setSelectedIndex(0);
|
|
305
333
|
}, []);
|
|
306
334
|
const openSearch = useCallback(() => setSearchActive(true), []);
|
|
335
|
+
const submitSearch = useCallback(() => {
|
|
336
|
+
setSearchActive(false);
|
|
337
|
+
setSelectedIndex(0);
|
|
338
|
+
}, []);
|
|
307
339
|
const closeSearch = useCallback(() => {
|
|
308
340
|
setSearchActive(false);
|
|
309
341
|
setSearchQuery("");
|
|
@@ -314,12 +346,48 @@ function useDashboardState(dataSource) {
|
|
|
314
346
|
}, [selectedMemory]);
|
|
315
347
|
const confirmDelete = useCallback(() => {
|
|
316
348
|
if (!selectedMemory) return;
|
|
317
|
-
dataSource.deleteMemory(selectedMemory.id);
|
|
349
|
+
const snapshot = dataSource.deleteMemory(selectedMemory.id);
|
|
350
|
+
if (snapshot) {
|
|
351
|
+
setLastDeleted(snapshot);
|
|
352
|
+
setNotice(`Deleted "${snapshot.title ?? snapshot.id.slice(0, 8)}" \u2014 press u to undo`);
|
|
353
|
+
}
|
|
318
354
|
setShowDeleteConfirm(false);
|
|
319
355
|
setSelectedIndex((i) => Math.max(0, i - 1));
|
|
320
356
|
dataSource.refresh();
|
|
321
357
|
setRevision((r) => r + 1);
|
|
322
358
|
}, [dataSource, selectedMemory]);
|
|
359
|
+
const undoDelete = useCallback(() => {
|
|
360
|
+
if (!lastDeleted) return;
|
|
361
|
+
const ok = dataSource.restoreMemory(lastDeleted);
|
|
362
|
+
setNotice(ok ? `Restored "${lastDeleted.title ?? lastDeleted.id.slice(0, 8)}"` : `Could not restore "${lastDeleted.title ?? lastDeleted.id.slice(0, 8)}" \u2014 it was purged or removed by sync`);
|
|
363
|
+
setLastDeleted(null);
|
|
364
|
+
dataSource.refresh();
|
|
365
|
+
setRevision((r) => r + 1);
|
|
366
|
+
}, [dataSource, lastDeleted]);
|
|
367
|
+
const adjustImportance = useCallback((delta) => {
|
|
368
|
+
if (!selectedMemory) return;
|
|
369
|
+
const next = Math.min(1, Math.max(0.05, Math.round((selectedMemory.importance + delta) * 100) / 100));
|
|
370
|
+
dataSource.updateMemory(selectedMemory.id, { importance: next });
|
|
371
|
+
setNotice(`Importance ${next.toFixed(2)} (re-anchored)`);
|
|
372
|
+
dataSource.refresh();
|
|
373
|
+
setRevision((r) => r + 1);
|
|
374
|
+
}, [dataSource, selectedMemory]);
|
|
375
|
+
const openTagEditor = useCallback(() => {
|
|
376
|
+
if (!selectedMemory) return;
|
|
377
|
+
setTagDraft(selectedMemory.tags.join(", "));
|
|
378
|
+
setShowTagEditor(true);
|
|
379
|
+
}, [selectedMemory]);
|
|
380
|
+
const submitTags = useCallback(() => {
|
|
381
|
+
if (selectedMemory) {
|
|
382
|
+
const tags = tagDraft.split(",").map((t) => t.trim()).filter(Boolean);
|
|
383
|
+
dataSource.updateMemory(selectedMemory.id, { tags });
|
|
384
|
+
setNotice(`Tags updated (${tags.length})`);
|
|
385
|
+
dataSource.refresh();
|
|
386
|
+
setRevision((r) => r + 1);
|
|
387
|
+
}
|
|
388
|
+
setShowTagEditor(false);
|
|
389
|
+
}, [dataSource, selectedMemory, tagDraft]);
|
|
390
|
+
const cancelTagEditor = useCallback(() => setShowTagEditor(false), []);
|
|
323
391
|
const cancelDelete = useCallback(() => setShowDeleteConfirm(false), []);
|
|
324
392
|
const promptPurge = useCallback(() => {
|
|
325
393
|
if (currentProject) setShowPurgeConfirm(true);
|
|
@@ -344,9 +412,12 @@ function useDashboardState(dataSource) {
|
|
|
344
412
|
searchQuery,
|
|
345
413
|
searchActive,
|
|
346
414
|
currentProject,
|
|
415
|
+
showTagEditor,
|
|
416
|
+
tagDraft,
|
|
417
|
+
setTagDraft,
|
|
418
|
+
notice,
|
|
419
|
+
lastDeleted,
|
|
347
420
|
sortMode,
|
|
348
|
-
selectedIndex,
|
|
349
|
-
focusedPane,
|
|
350
421
|
showHelp,
|
|
351
422
|
showProjectPicker,
|
|
352
423
|
showDeleteConfirm,
|
|
@@ -357,6 +428,7 @@ function useDashboardState(dataSource) {
|
|
|
357
428
|
relations,
|
|
358
429
|
projects,
|
|
359
430
|
stats,
|
|
431
|
+
selectedIndex: clampedIndex,
|
|
360
432
|
setSearchQuery,
|
|
361
433
|
setCurrentProject,
|
|
362
434
|
setSelectedIndex,
|
|
@@ -368,9 +440,9 @@ function useDashboardState(dataSource) {
|
|
|
368
440
|
cycleLifespan,
|
|
369
441
|
cycleProjectNext,
|
|
370
442
|
cycleProjectPrev,
|
|
371
|
-
focusNext,
|
|
372
443
|
filterByType,
|
|
373
444
|
openSearch,
|
|
445
|
+
submitSearch,
|
|
374
446
|
closeSearch,
|
|
375
447
|
promptDelete,
|
|
376
448
|
confirmDelete,
|
|
@@ -379,7 +451,12 @@ function useDashboardState(dataSource) {
|
|
|
379
451
|
confirmPurge,
|
|
380
452
|
cancelPurge,
|
|
381
453
|
expandMemory,
|
|
382
|
-
closeExpand
|
|
454
|
+
closeExpand,
|
|
455
|
+
undoDelete,
|
|
456
|
+
adjustImportance,
|
|
457
|
+
openTagEditor,
|
|
458
|
+
submitTags,
|
|
459
|
+
cancelTagEditor
|
|
383
460
|
};
|
|
384
461
|
}
|
|
385
462
|
function sortMemories(memories, mode) {
|
|
@@ -405,6 +482,11 @@ var TYPE_KEYS = {
|
|
|
405
482
|
};
|
|
406
483
|
function useKeybindings(actions, opts) {
|
|
407
484
|
useInput((input, key) => {
|
|
485
|
+
if (opts.modalOpen) return;
|
|
486
|
+
if (opts.tagEditorOpen) {
|
|
487
|
+
if (key.escape) actions.cancelTagEditor();
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
408
490
|
if (opts.expandOpen) return;
|
|
409
491
|
if (opts.searchActive) {
|
|
410
492
|
if (key.escape) actions.closeSearch();
|
|
@@ -425,9 +507,12 @@ function useKeybindings(actions, opts) {
|
|
|
425
507
|
if (input === "p") actions.openProjectPicker();
|
|
426
508
|
if (input === "]" || key.rightArrow) actions.cycleProjectNext();
|
|
427
509
|
if (input === "[" || key.leftArrow) actions.cycleProjectPrev();
|
|
428
|
-
if (
|
|
429
|
-
if (input === "
|
|
430
|
-
if (input === "
|
|
510
|
+
if (input === "r" || input === "d") actions.removeMemory();
|
|
511
|
+
if (input === "X") actions.purgeProject();
|
|
512
|
+
if (input === "u") actions.undoDelete();
|
|
513
|
+
if (input === "+" || input === "=") actions.adjustImportanceUp();
|
|
514
|
+
if (input === "-") actions.adjustImportanceDown();
|
|
515
|
+
if (input === "t") actions.openTagEditor();
|
|
431
516
|
if (input === "?") actions.showHelp();
|
|
432
517
|
if (key.return) actions.expandMemory();
|
|
433
518
|
if (input === "q") actions.quit();
|
|
@@ -466,14 +551,16 @@ var HINTS = [
|
|
|
466
551
|
["1-5", "type"],
|
|
467
552
|
["l", "life"],
|
|
468
553
|
["s", "sort"],
|
|
469
|
-
["
|
|
470
|
-
["
|
|
471
|
-
["
|
|
554
|
+
["d", "delete"],
|
|
555
|
+
["u", "undo"],
|
|
556
|
+
["t", "tags"],
|
|
557
|
+
["+/-", "rate"],
|
|
558
|
+
["X", "purge"],
|
|
472
559
|
["?", "help"],
|
|
473
560
|
["q", "quit"]
|
|
474
561
|
];
|
|
475
562
|
function KeybindingBar() {
|
|
476
|
-
return /* @__PURE__ */ jsx(Box, { children: HINTS.map(([key, label], i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
563
|
+
return /* @__PURE__ */ jsx(Box, { overflow: "hidden", children: HINTS.map(([key, label], i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
477
564
|
i > 0 && /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
|
|
478
565
|
/* @__PURE__ */ jsx(Text, { color: "cyan", children: key }),
|
|
479
566
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
@@ -519,11 +606,11 @@ function Header({ project, typeFilter, lifespanFilter, sortMode, searchQuery, la
|
|
|
519
606
|
import { Box as Box3, Text as Text3 } from "ink";
|
|
520
607
|
import TextInput from "ink-text-input";
|
|
521
608
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
522
|
-
function SearchBar({ query, onChange,
|
|
609
|
+
function SearchBar({ query, onChange, onSubmit }) {
|
|
523
610
|
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
524
611
|
/* @__PURE__ */ jsx3(Text3, { color: "yellow", children: "Search: " }),
|
|
525
|
-
/* @__PURE__ */ jsx3(TextInput, { value: query, onChange, onSubmit
|
|
526
|
-
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: " (
|
|
612
|
+
/* @__PURE__ */ jsx3(TextInput, { value: query, onChange, onSubmit }),
|
|
613
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: " (Enter apply \xB7 Esc cancel)" })
|
|
527
614
|
] });
|
|
528
615
|
}
|
|
529
616
|
|
|
@@ -646,7 +733,7 @@ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
|
646
733
|
var METADATA_ROWS = 18;
|
|
647
734
|
var BORDER_ROWS = 2;
|
|
648
735
|
var MIN_CONTENT_ROWS = 2;
|
|
649
|
-
function MemoryDetail({ memory, relations, isFocused, height, width }) {
|
|
736
|
+
function MemoryDetail({ memory, relations, isFocused, height, width, resolveTitle }) {
|
|
650
737
|
return /* @__PURE__ */ jsxs5(
|
|
651
738
|
Box5,
|
|
652
739
|
{
|
|
@@ -657,12 +744,12 @@ function MemoryDetail({ memory, relations, isFocused, height, width }) {
|
|
|
657
744
|
height,
|
|
658
745
|
children: [
|
|
659
746
|
/* @__PURE__ */ jsx5(Text5, { bold: true, color: isFocused ? "blue" : "gray", children: " Detail " }),
|
|
660
|
-
!memory ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Select a memory to view details" }) : /* @__PURE__ */ jsx5(DetailContent, { memory, relations, height, width })
|
|
747
|
+
!memory ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Select a memory to view details" }) : /* @__PURE__ */ jsx5(DetailContent, { resolveTitle, memory, relations, height, width })
|
|
661
748
|
]
|
|
662
749
|
}
|
|
663
750
|
);
|
|
664
751
|
}
|
|
665
|
-
function DetailContent({ memory, relations, height, width }) {
|
|
752
|
+
function DetailContent({ memory, relations, height, width, resolveTitle }) {
|
|
666
753
|
const life = computeLifespan(memory);
|
|
667
754
|
const typeColor = TYPE_COLORS[memory.type] ?? "white";
|
|
668
755
|
const relationRows = relations.length > 0 ? relations.length + 2 : 0;
|
|
@@ -734,6 +821,10 @@ function DetailContent({ memory, relations, height, width }) {
|
|
|
734
821
|
/* @__PURE__ */ jsx5(Text5, { bold: true, children: "Content" }),
|
|
735
822
|
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "\u2500".repeat(Math.min(contentWidth, 40)) }),
|
|
736
823
|
preview.lines.map((line, i) => /* @__PURE__ */ jsx5(Text5, { children: line === "" ? " " : line }, `line-${i}`)),
|
|
824
|
+
memory.context && /* @__PURE__ */ jsxs5(Text5, { dimColor: true, wrap: "truncate", children: [
|
|
825
|
+
"ctx: ",
|
|
826
|
+
memory.context.slice(0, 120)
|
|
827
|
+
] }),
|
|
737
828
|
preview.truncated && /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
738
829
|
"\u2026 +",
|
|
739
830
|
preview.remainingLines,
|
|
@@ -741,7 +832,7 @@ function DetailContent({ memory, relations, height, width }) {
|
|
|
741
832
|
preview.remainingLines === 1 ? "" : "s",
|
|
742
833
|
" \xB7 press Enter to view full"
|
|
743
834
|
] }),
|
|
744
|
-
relations.length > 0 && /* @__PURE__ */ jsx5(RelationsList, { relations, memoryId: memory.id })
|
|
835
|
+
relations.length > 0 && /* @__PURE__ */ jsx5(RelationsList, { resolveTitle, relations, memoryId: memory.id })
|
|
745
836
|
] });
|
|
746
837
|
}
|
|
747
838
|
function truncateContent(content, maxRows, wrapWidth) {
|
|
@@ -756,7 +847,7 @@ function truncateContent(content, maxRows, wrapWidth) {
|
|
|
756
847
|
remainingLines: allLines.length - visible
|
|
757
848
|
};
|
|
758
849
|
}
|
|
759
|
-
function RelationsList({ relations, memoryId }) {
|
|
850
|
+
function RelationsList({ relations, memoryId, resolveTitle }) {
|
|
760
851
|
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
761
852
|
/* @__PURE__ */ jsx5(Text5, { bold: true, children: "Relations" }),
|
|
762
853
|
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "\u2500".repeat(40) }),
|
|
@@ -764,13 +855,14 @@ function RelationsList({ relations, memoryId }) {
|
|
|
764
855
|
const relColor = RELATION_COLORS[r.relationType] ?? "white";
|
|
765
856
|
const direction = r.sourceId === memoryId ? "\u2192" : "\u2190";
|
|
766
857
|
const otherId = r.sourceId === memoryId ? r.targetId : r.sourceId;
|
|
858
|
+
const label = resolveTitle?.(otherId) ?? otherId.slice(0, 8);
|
|
767
859
|
return /* @__PURE__ */ jsxs5(Text5, { children: [
|
|
768
860
|
" ",
|
|
769
861
|
direction,
|
|
770
862
|
" ",
|
|
771
863
|
/* @__PURE__ */ jsx5(Text5, { color: relColor, children: r.relationType }),
|
|
772
864
|
" ",
|
|
773
|
-
|
|
865
|
+
label
|
|
774
866
|
] }, i);
|
|
775
867
|
})
|
|
776
868
|
] });
|
|
@@ -916,9 +1008,11 @@ var BINDINGS = [
|
|
|
916
1008
|
["s", "Cycle sort mode"],
|
|
917
1009
|
["p", "Open project picker"],
|
|
918
1010
|
["[ / ]", "Previous / next project"],
|
|
919
|
-
["r", "
|
|
920
|
-
["
|
|
921
|
-
["
|
|
1011
|
+
["d / r", "Delete selected memory (soft \u2014 u restores)"],
|
|
1012
|
+
["u", "Undo last delete"],
|
|
1013
|
+
["t", "Edit tags of selected memory"],
|
|
1014
|
+
["+ / -", "Raise / lower importance (re-anchors decay)"],
|
|
1015
|
+
["X", "Purge all memories for current project"],
|
|
922
1016
|
["?", "Show this help"],
|
|
923
1017
|
["q", "Quit"]
|
|
924
1018
|
];
|
|
@@ -1050,7 +1144,7 @@ function PurgeConfirm({ project, memoryCount, onConfirm, onCancel }) {
|
|
|
1050
1144
|
import { useState as useState3, useEffect as useEffect3 } from "react";
|
|
1051
1145
|
import { Box as Box12, Text as Text12, useInput as useInput6 } from "ink";
|
|
1052
1146
|
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1053
|
-
function ExpandMemory({ memory, relations, onClose }) {
|
|
1147
|
+
function ExpandMemory({ memory, relations, onClose, resolveTitle }) {
|
|
1054
1148
|
const { columns, rows } = useTerminalSize();
|
|
1055
1149
|
const [scroll, setScroll] = useState3(0);
|
|
1056
1150
|
const contentWidth = Math.max(20, columns - 6);
|
|
@@ -1108,13 +1202,14 @@ function ExpandMemory({ memory, relations, onClose }) {
|
|
|
1108
1202
|
const relColor = RELATION_COLORS[r.relationType] ?? "white";
|
|
1109
1203
|
const direction = r.sourceId === memory.id ? "\u2192" : "\u2190";
|
|
1110
1204
|
const otherId = r.sourceId === memory.id ? r.targetId : r.sourceId;
|
|
1205
|
+
const label = resolveTitle?.(otherId) ?? otherId.slice(0, 8);
|
|
1111
1206
|
return /* @__PURE__ */ jsxs12(Text12, { children: [
|
|
1112
1207
|
" ",
|
|
1113
1208
|
direction,
|
|
1114
1209
|
" ",
|
|
1115
1210
|
/* @__PURE__ */ jsx12(Text12, { color: relColor, children: r.relationType }),
|
|
1116
1211
|
" ",
|
|
1117
|
-
|
|
1212
|
+
label
|
|
1118
1213
|
] }, i);
|
|
1119
1214
|
})
|
|
1120
1215
|
] }),
|
|
@@ -1126,8 +1221,20 @@ function ExpandMemory({ memory, relations, onClose }) {
|
|
|
1126
1221
|
] });
|
|
1127
1222
|
}
|
|
1128
1223
|
|
|
1129
|
-
// src/commands/memory/dashboard/
|
|
1224
|
+
// src/commands/memory/dashboard/components/tag-editor.tsx
|
|
1225
|
+
import { Box as Box13, Text as Text13 } from "ink";
|
|
1226
|
+
import TextInput2 from "ink-text-input";
|
|
1130
1227
|
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1228
|
+
function TagEditor({ value, onChange, onSubmit }) {
|
|
1229
|
+
return /* @__PURE__ */ jsxs13(Box13, { children: [
|
|
1230
|
+
/* @__PURE__ */ jsx13(Text13, { color: "cyan", children: "Tags (comma-separated): " }),
|
|
1231
|
+
/* @__PURE__ */ jsx13(TextInput2, { value, onChange, onSubmit }),
|
|
1232
|
+
/* @__PURE__ */ jsx13(Text13, { dimColor: true, children: " (Enter save \xB7 Esc cancel)" })
|
|
1233
|
+
] });
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
// src/commands/memory/dashboard/app.tsx
|
|
1237
|
+
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1131
1238
|
function App({ dataSource }) {
|
|
1132
1239
|
const { exit } = useApp();
|
|
1133
1240
|
const { columns, rows, layout } = useTerminalSize();
|
|
@@ -1142,33 +1249,40 @@ function App({ dataSource }) {
|
|
|
1142
1249
|
cycleProjectNext: state.cycleProjectNext,
|
|
1143
1250
|
cycleProjectPrev: state.cycleProjectPrev,
|
|
1144
1251
|
cycleSort: state.cycleSort,
|
|
1145
|
-
focusNext: state.focusNext,
|
|
1146
1252
|
removeMemory: state.promptDelete,
|
|
1147
1253
|
purgeProject: state.promptPurge,
|
|
1148
1254
|
openProjectPicker: () => state.setShowProjectPicker((v) => !v),
|
|
1149
1255
|
showHelp: () => state.setShowHelp((v) => !v),
|
|
1150
1256
|
expandMemory: state.expandMemory,
|
|
1257
|
+
undoDelete: state.undoDelete,
|
|
1258
|
+
adjustImportanceUp: () => state.adjustImportance(0.1),
|
|
1259
|
+
adjustImportanceDown: () => state.adjustImportance(-0.1),
|
|
1260
|
+
openTagEditor: state.openTagEditor,
|
|
1261
|
+
cancelTagEditor: state.cancelTagEditor,
|
|
1151
1262
|
quit: exit
|
|
1152
1263
|
}, {
|
|
1153
1264
|
searchActive: state.searchActive,
|
|
1154
1265
|
pickerOpen: state.showProjectPicker,
|
|
1155
|
-
expandOpen: state.showExpand
|
|
1266
|
+
expandOpen: state.showExpand,
|
|
1267
|
+
modalOpen: state.showDeleteConfirm || state.showPurgeConfirm || state.showHelp,
|
|
1268
|
+
tagEditorOpen: state.showTagEditor
|
|
1156
1269
|
});
|
|
1157
1270
|
if (state.showHelp) {
|
|
1158
|
-
return /* @__PURE__ */
|
|
1271
|
+
return /* @__PURE__ */ jsx14(HelpOverlay, { onClose: () => state.setShowHelp(false) });
|
|
1159
1272
|
}
|
|
1160
1273
|
if (state.showExpand && state.selectedMemory) {
|
|
1161
|
-
return /* @__PURE__ */
|
|
1274
|
+
return /* @__PURE__ */ jsx14(
|
|
1162
1275
|
ExpandMemory,
|
|
1163
1276
|
{
|
|
1164
1277
|
memory: state.selectedMemory,
|
|
1165
1278
|
relations: state.relations,
|
|
1279
|
+
resolveTitle: (id) => dataSource.getMemoryTitle(id),
|
|
1166
1280
|
onClose: state.closeExpand
|
|
1167
1281
|
}
|
|
1168
1282
|
);
|
|
1169
1283
|
}
|
|
1170
1284
|
if (state.showProjectPicker) {
|
|
1171
|
-
return /* @__PURE__ */
|
|
1285
|
+
return /* @__PURE__ */ jsx14(
|
|
1172
1286
|
ProjectPicker,
|
|
1173
1287
|
{
|
|
1174
1288
|
projects: [...state.projects],
|
|
@@ -1182,7 +1296,7 @@ function App({ dataSource }) {
|
|
|
1182
1296
|
);
|
|
1183
1297
|
}
|
|
1184
1298
|
if (state.showDeleteConfirm && state.selectedMemory) {
|
|
1185
|
-
return /* @__PURE__ */
|
|
1299
|
+
return /* @__PURE__ */ jsx14(
|
|
1186
1300
|
DeleteConfirm,
|
|
1187
1301
|
{
|
|
1188
1302
|
memory: state.selectedMemory,
|
|
@@ -1192,7 +1306,7 @@ function App({ dataSource }) {
|
|
|
1192
1306
|
);
|
|
1193
1307
|
}
|
|
1194
1308
|
if (state.showPurgeConfirm && state.currentProject) {
|
|
1195
|
-
return /* @__PURE__ */
|
|
1309
|
+
return /* @__PURE__ */ jsx14(
|
|
1196
1310
|
PurgeConfirm,
|
|
1197
1311
|
{
|
|
1198
1312
|
project: state.currentProject,
|
|
@@ -1210,9 +1324,9 @@ function App({ dataSource }) {
|
|
|
1210
1324
|
const projectListHeight = isNarrow ? 0 : Math.min(Math.max(4, Math.floor(contentHeight / 3)), projectsCount + 3, 12);
|
|
1211
1325
|
const listHeight = isNarrow ? Math.max(6, Math.floor(contentHeight * 0.6)) : contentHeight;
|
|
1212
1326
|
const detailHeight = isNarrow ? Math.max(6, contentHeight - listHeight) : Math.max(6, contentHeight - projectListHeight);
|
|
1213
|
-
return /* @__PURE__ */
|
|
1214
|
-
/* @__PURE__ */
|
|
1215
|
-
/* @__PURE__ */
|
|
1327
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
1328
|
+
/* @__PURE__ */ jsx14(KeybindingBar, {}),
|
|
1329
|
+
/* @__PURE__ */ jsx14(
|
|
1216
1330
|
Header,
|
|
1217
1331
|
{
|
|
1218
1332
|
project: state.currentProject,
|
|
@@ -1223,52 +1337,104 @@ function App({ dataSource }) {
|
|
|
1223
1337
|
layout
|
|
1224
1338
|
}
|
|
1225
1339
|
),
|
|
1226
|
-
state.
|
|
1340
|
+
state.showTagEditor && /* @__PURE__ */ jsx14(
|
|
1341
|
+
TagEditor,
|
|
1342
|
+
{
|
|
1343
|
+
value: state.tagDraft,
|
|
1344
|
+
onChange: state.setTagDraft,
|
|
1345
|
+
onSubmit: state.submitTags
|
|
1346
|
+
}
|
|
1347
|
+
),
|
|
1348
|
+
state.notice && !state.searchActive && !state.showTagEditor && /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
1349
|
+
" ",
|
|
1350
|
+
state.notice
|
|
1351
|
+
] }),
|
|
1352
|
+
state.searchActive && /* @__PURE__ */ jsx14(
|
|
1227
1353
|
SearchBar,
|
|
1228
1354
|
{
|
|
1229
1355
|
query: state.searchQuery,
|
|
1230
1356
|
onChange: state.setSearchQuery,
|
|
1231
|
-
|
|
1357
|
+
onSubmit: state.submitSearch
|
|
1232
1358
|
}
|
|
1233
1359
|
),
|
|
1234
|
-
/* @__PURE__ */
|
|
1235
|
-
/* @__PURE__ */
|
|
1360
|
+
/* @__PURE__ */ jsxs14(Box14, { flexDirection: isNarrow ? "column" : "row", height: isNarrow ? void 0 : contentHeight, children: [
|
|
1361
|
+
/* @__PURE__ */ jsx14(Box14, { width: isNarrow ? "100%" : "60%", children: /* @__PURE__ */ jsx14(
|
|
1236
1362
|
MemoryList,
|
|
1237
1363
|
{
|
|
1238
1364
|
memories: state.filteredMemories,
|
|
1239
1365
|
selectedIndex: state.selectedIndex,
|
|
1240
|
-
isFocused:
|
|
1366
|
+
isFocused: true,
|
|
1241
1367
|
height: listHeight
|
|
1242
1368
|
}
|
|
1243
1369
|
) }),
|
|
1244
|
-
/* @__PURE__ */
|
|
1245
|
-
!isNarrow && /* @__PURE__ */
|
|
1370
|
+
/* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", width: isNarrow ? "100%" : "40%", children: [
|
|
1371
|
+
!isNarrow && /* @__PURE__ */ jsx14(
|
|
1246
1372
|
ProjectList,
|
|
1247
1373
|
{
|
|
1248
1374
|
memories: state.filteredMemories,
|
|
1249
1375
|
activeProject: state.currentProject,
|
|
1250
|
-
isFocused:
|
|
1376
|
+
isFocused: false,
|
|
1251
1377
|
height: projectListHeight
|
|
1252
1378
|
}
|
|
1253
1379
|
),
|
|
1254
|
-
/* @__PURE__ */
|
|
1380
|
+
/* @__PURE__ */ jsx14(
|
|
1255
1381
|
MemoryDetail,
|
|
1256
1382
|
{
|
|
1257
1383
|
memory: state.selectedMemory,
|
|
1258
1384
|
relations: state.relations,
|
|
1259
|
-
|
|
1385
|
+
resolveTitle: (id) => dataSource.getMemoryTitle(id),
|
|
1386
|
+
isFocused: false,
|
|
1260
1387
|
height: detailHeight,
|
|
1261
1388
|
width: rightWidth
|
|
1262
1389
|
}
|
|
1263
1390
|
)
|
|
1264
1391
|
] })
|
|
1265
1392
|
] }),
|
|
1266
|
-
/* @__PURE__ */
|
|
1393
|
+
/* @__PURE__ */ jsx14(StatsBar, { stats: state.stats, visible: state.filteredMemories })
|
|
1267
1394
|
] });
|
|
1268
1395
|
}
|
|
1269
1396
|
|
|
1397
|
+
// src/commands/memory/dashboard/components/error-boundary.tsx
|
|
1398
|
+
import React6 from "react";
|
|
1399
|
+
import { Box as Box15, Text as Text15, useApp as useApp2, useInput as useInput7 } from "ink";
|
|
1400
|
+
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1401
|
+
function CrashScreen({
|
|
1402
|
+
message
|
|
1403
|
+
}) {
|
|
1404
|
+
const { exit } = useApp2();
|
|
1405
|
+
useInput7((input) => {
|
|
1406
|
+
if (input === "q") exit();
|
|
1407
|
+
});
|
|
1408
|
+
return /* @__PURE__ */ jsxs15(
|
|
1409
|
+
Box15,
|
|
1410
|
+
{
|
|
1411
|
+
flexDirection: "column",
|
|
1412
|
+
borderStyle: "round",
|
|
1413
|
+
borderColor: "red",
|
|
1414
|
+
padding: 1,
|
|
1415
|
+
children: [
|
|
1416
|
+
/* @__PURE__ */ jsx15(Text15, { bold: true, color: "red", children: "Dashboard crashed" }),
|
|
1417
|
+
/* @__PURE__ */ jsx15(Text15, { children: message }),
|
|
1418
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Your data is untouched. Press q to quit." })
|
|
1419
|
+
]
|
|
1420
|
+
}
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
var DashboardErrorBoundary = class extends React6.Component {
|
|
1424
|
+
state = { error: null };
|
|
1425
|
+
static getDerivedStateFromError(error) {
|
|
1426
|
+
return { error };
|
|
1427
|
+
}
|
|
1428
|
+
render() {
|
|
1429
|
+
if (this.state.error) {
|
|
1430
|
+
return /* @__PURE__ */ jsx15(CrashScreen, { message: this.state.error.message });
|
|
1431
|
+
}
|
|
1432
|
+
return this.props.children;
|
|
1433
|
+
}
|
|
1434
|
+
};
|
|
1435
|
+
|
|
1270
1436
|
// src/commands/memory/dashboard/tui.tsx
|
|
1271
|
-
import { jsx as
|
|
1437
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1272
1438
|
async function startTui(options) {
|
|
1273
1439
|
const config = loadConfig(
|
|
1274
1440
|
options?.dbPath ? { dataDir: options.dbPath } : void 0
|
|
@@ -1287,7 +1453,7 @@ async function startTui(options) {
|
|
|
1287
1453
|
);
|
|
1288
1454
|
let shuttingDown = false;
|
|
1289
1455
|
const { waitUntilExit, unmount } = render(
|
|
1290
|
-
/* @__PURE__ */
|
|
1456
|
+
/* @__PURE__ */ jsx16(DashboardErrorBoundary, { children: /* @__PURE__ */ jsx16(App, { dataSource }) })
|
|
1291
1457
|
);
|
|
1292
1458
|
function shutdown() {
|
|
1293
1459
|
if (shuttingDown) return;
|
|
@@ -1310,4 +1476,4 @@ async function startTui(options) {
|
|
|
1310
1476
|
export {
|
|
1311
1477
|
startTui
|
|
1312
1478
|
};
|
|
1313
|
-
//# sourceMappingURL=tui-
|
|
1479
|
+
//# sourceMappingURL=tui-ZINEA7TI.js.map
|