@rol1n/memory-log 0.0.0-stage → 0.1.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/README.md +53 -2
- package/extensions/memory-log/README.md +54 -0
- package/extensions/memory-log/agent/consolidator/prompt.ts +47 -0
- package/extensions/memory-log/agent/consolidator/tools.ts +160 -0
- package/extensions/memory-log/agent/cost.ts +32 -0
- package/extensions/memory-log/agent/index.ts +42 -0
- package/extensions/memory-log/agent/observer/prompt.ts +73 -0
- package/extensions/memory-log/agent/observer/tool.ts +73 -0
- package/extensions/memory-log/commands/compact.ts +35 -0
- package/extensions/memory-log/commands/consolidate.ts +47 -0
- package/extensions/memory-log/commands/status.ts +50 -0
- package/extensions/memory-log/config.ts +253 -0
- package/extensions/memory-log/debug-log.ts +76 -0
- package/extensions/memory-log/hooks/compaction-hook.ts +161 -0
- package/extensions/memory-log/hooks/compaction-trigger.ts +160 -0
- package/extensions/memory-log/hooks/consolidator-trigger.ts +143 -0
- package/extensions/memory-log/hooks/observer-trigger.ts +176 -0
- package/extensions/memory-log/ids.ts +78 -0
- package/extensions/memory-log/index.ts +149 -0
- package/extensions/memory-log/ledger/fold.ts +77 -0
- package/extensions/memory-log/ledger/index.ts +7 -0
- package/extensions/memory-log/ledger/pool.ts +38 -0
- package/extensions/memory-log/ledger/progress.ts +181 -0
- package/extensions/memory-log/ledger/projection.ts +115 -0
- package/extensions/memory-log/ledger/render.ts +38 -0
- package/extensions/memory-log/ledger/serialize.ts +161 -0
- package/extensions/memory-log/ledger/types.ts +201 -0
- package/extensions/memory-log/memory/index-render.ts +45 -0
- package/extensions/memory-log/memory/paths.ts +120 -0
- package/extensions/memory-log/memory/session.ts +64 -0
- package/extensions/memory-log/runtime.ts +127 -0
- package/extensions/memory-log/spawn/launch.ts +133 -0
- package/extensions/memory-log/spawn/runs.ts +83 -0
- package/extensions/memory-log/tokens.ts +66 -0
- package/extensions/memory-log/ui/status-controller.ts +225 -0
- package/extensions/memory-log/ui/timeline.ts +103 -0
- package/package.json +41 -4
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { Config } from "../config.ts";
|
|
2
|
+
import {
|
|
3
|
+
entryIndexById,
|
|
4
|
+
foldLedger,
|
|
5
|
+
isObservationsRecordedEntry,
|
|
6
|
+
rawTokensAfterIndex,
|
|
7
|
+
rawTokensSinceObservationCoverage,
|
|
8
|
+
type Entry,
|
|
9
|
+
} from "../ledger/index.ts";
|
|
10
|
+
|
|
11
|
+
/** Glyphs for the timeline strip. */
|
|
12
|
+
const GLYPH = {
|
|
13
|
+
consolidated: "▓", // observations promoted to .memory (long-term)
|
|
14
|
+
partial: "▚", // chunk straddling the pool-target boundary (some obs promoted)
|
|
15
|
+
pool: "▒", // observed, still in the short-term buffer
|
|
16
|
+
raw: "░", // raw history not yet distilled into observations
|
|
17
|
+
cut: "┊", // compaction cutoff (verbatim tail began here)
|
|
18
|
+
tip: "▶", // live branch tip
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
/** A committed observation chunk, in branch order. */
|
|
22
|
+
type Chunk = { coversUpToIndex: number; timestamps: string[] };
|
|
23
|
+
|
|
24
|
+
function fmtK(tokens: number): string {
|
|
25
|
+
if (tokens < 1000) return `${tokens}`;
|
|
26
|
+
return `${(tokens / 1000).toFixed(1)}k`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function collectChunks(branch: Entry[]): Chunk[] {
|
|
30
|
+
const indexById = entryIndexById(branch);
|
|
31
|
+
const chunks: Chunk[] = [];
|
|
32
|
+
for (const entry of branch) {
|
|
33
|
+
if (!isObservationsRecordedEntry(entry)) continue;
|
|
34
|
+
const coversUpToIndex = indexById.get(entry.data.coversUpToId);
|
|
35
|
+
if (coversUpToIndex === undefined) continue;
|
|
36
|
+
chunks.push({ coversUpToIndex, timestamps: entry.data.observations.map((o) => o.timestamp) });
|
|
37
|
+
}
|
|
38
|
+
return chunks;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Branch indices of every compaction entry's `firstKeptEntryId` (the verbatim-tail cutoffs). */
|
|
42
|
+
function compactionCutIndices(branch: Entry[]): number[] {
|
|
43
|
+
const indexById = entryIndexById(branch);
|
|
44
|
+
const cuts: number[] = [];
|
|
45
|
+
for (const entry of branch) {
|
|
46
|
+
if (entry.type !== "compaction") continue;
|
|
47
|
+
const idx = entry.firstKeptEntryId ? indexById.get(entry.firstKeptEntryId) : undefined;
|
|
48
|
+
if (idx !== undefined) cuts.push(idx);
|
|
49
|
+
}
|
|
50
|
+
return cuts;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function chunkGlyph(chunk: Chunk, dropped: Set<string>): string {
|
|
54
|
+
let droppedCount = 0;
|
|
55
|
+
for (const ts of chunk.timestamps) if (dropped.has(ts)) droppedCount++;
|
|
56
|
+
if (droppedCount === 0) return GLYPH.pool;
|
|
57
|
+
if (droppedCount === chunk.timestamps.length) return GLYPH.consolidated;
|
|
58
|
+
return GLYPH.partial;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function wrap(cells: string[], width: number): string {
|
|
62
|
+
if (cells.length === 0) return "";
|
|
63
|
+
const rows: string[] = [];
|
|
64
|
+
for (let i = 0; i < cells.length; i += width) rows.push(cells.slice(i, i + width).join(""));
|
|
65
|
+
return rows.join("\n");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Render the full session as a horizontal strip.
|
|
70
|
+
*/
|
|
71
|
+
export function renderTimeline(branch: Entry[], config: Config, width = 60): string {
|
|
72
|
+
const folded = foldLedger(branch);
|
|
73
|
+
const dropped = folded.droppedObservationTimestamps;
|
|
74
|
+
const chunks = collectChunks(branch);
|
|
75
|
+
|
|
76
|
+
const cells: string[] = chunks.map((chunk) => chunkGlyph(chunk, dropped));
|
|
77
|
+
const tailTokens = rawTokensSinceObservationCoverage(branch);
|
|
78
|
+
const tailCells = tailTokens > 0 ? Math.ceil(tailTokens / config.chunkTokens) : 0;
|
|
79
|
+
for (let i = 0; i < tailCells; i++) cells.push(GLYPH.raw);
|
|
80
|
+
|
|
81
|
+
const cutPositions = compactionCutIndices(branch)
|
|
82
|
+
.map((cutIdx) => {
|
|
83
|
+
let pos = 0;
|
|
84
|
+
for (const chunk of chunks) if (chunk.coversUpToIndex < cutIdx) pos++;
|
|
85
|
+
return Math.min(pos, cells.length);
|
|
86
|
+
})
|
|
87
|
+
.sort((a, b) => b - a);
|
|
88
|
+
for (const pos of cutPositions) cells.splice(pos, 0, GLYPH.cut);
|
|
89
|
+
|
|
90
|
+
const consolidatedChunks = chunks.filter((c) => chunkGlyph(c, dropped) === GLYPH.consolidated).length;
|
|
91
|
+
const poolChunks = chunks.filter((c) => chunkGlyph(c, dropped) === GLYPH.pool).length;
|
|
92
|
+
const rawTotal = rawTokensAfterIndex(branch, -1);
|
|
93
|
+
const compactions = cutPositions.length;
|
|
94
|
+
|
|
95
|
+
const strip = cells.length > 0 ? `${wrap(cells, width)}${GLYPH.tip}` : "(timeline empty)";
|
|
96
|
+
|
|
97
|
+
return [
|
|
98
|
+
`memory-log timeline · 1 cell ≈ ${fmtK(config.chunkTokens)} tok · cumulative ${fmtK(rawTotal)} raw · ${compactions} compaction${compactions === 1 ? "" : "s"}`,
|
|
99
|
+
strip,
|
|
100
|
+
``,
|
|
101
|
+
` ${GLYPH.consolidated} .memory (${consolidatedChunks}) ${GLYPH.pool} pool (${poolChunks}) ${GLYPH.raw} raw ${GLYPH.cut} compaction cut ${GLYPH.tip} tip`,
|
|
102
|
+
].join("\n");
|
|
103
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rol1n/memory-log",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "memory-log extension from pi-kit",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"pi-package"
|
|
8
|
+
],
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+ssh://git@github.com/RolinShmily/pi-kit.git",
|
|
12
|
+
"directory": "extensions/memory-log"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/RolinShmily/pi-kit#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/RolinShmily/pi-kit/issues"
|
|
17
|
+
},
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=22.19.0"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"extensions/memory-log",
|
|
26
|
+
"extensions/memory-log/README.md"
|
|
27
|
+
],
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@earendil-works/pi-ai": "*",
|
|
30
|
+
"@earendil-works/pi-agent-core": "*",
|
|
31
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
32
|
+
"@earendil-works/pi-tui": "*",
|
|
33
|
+
"typebox": "*"
|
|
34
|
+
},
|
|
35
|
+
"pi": {
|
|
36
|
+
"extensions": [
|
|
37
|
+
"./extensions/memory-log/index.ts"
|
|
38
|
+
],
|
|
39
|
+
"skills": [],
|
|
40
|
+
"prompts": [],
|
|
41
|
+
"themes": []
|
|
42
|
+
}
|
|
43
|
+
}
|