pi-mega-compact 0.21.2 → 0.21.4
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/extensions/dashboard-server/routes-rag-settings-helpers.js +1 -0
- package/dist/extensions/mega-compact-child.js +126 -0
- package/dist/extensions/mega-config.js +5 -0
- package/dist/extensions/mega-events/agent-handlers/turnEndHandler/recordTurnRow.js +12 -2
- package/dist/extensions/mega-events/context-handler/afterCompact.js +11 -0
- package/dist/extensions/mega-events/context-handler/dbMirrorAppend.js +8 -0
- package/dist/extensions/mega-events/health-handler.js +12 -2
- package/dist/extensions/mega-events/session-handlers.js +1 -0
- package/dist/extensions/mega-pipeline/compact/run.js +11 -0
- package/dist/extensions/mega-runtime/helpers.js +45 -0
- package/dist/extensions/mega-runtime/internal-errors.js +14 -0
- package/dist/extensions/mega-runtime/runtime-instrumentation.js +166 -0
- package/dist/extensions/mega-runtime/runtime.js +27 -193
- package/dist/extensions/mega-runtime/state.js +1 -1
- package/dist/extensions/mega-runtime/widget.js +1 -1
- package/dist/extensions/mega-turn-store.js +5 -0
- package/dist/src/bridge/factory.js +195 -0
- package/dist/src/bridge/types.js +10 -0
- package/dist/src/bridge.js +1 -0
- package/dist/src/contextHealth.js +13 -5
- package/dist/src/metrics/turns.js +6 -1
- package/dist/src/store/sqlite/context-health-cache-poison.js +60 -0
- package/dist/src/store/sqlite/context-health.js +6 -48
- package/dist/src/store/sqlite/embedding-cache.js +4 -0
- package/dist/src/store/sqlite/schema.js +4 -0
- package/dist/src/store/turns/memory-store/admin.js +119 -0
- package/dist/src/store/turns/memory-store/ctx.js +28 -0
- package/dist/src/store/turns/memory-store/read.js +110 -0
- package/dist/src/store/turns/memory-store/write.js +88 -0
- package/dist/src/store/turns/memory-store.js +44 -273
- package/dist/src/store/turns/migrations.js +4 -0
- package/dist/src/store/turns/schema.js +1 -0
- package/dist/src/store/turns/sqlite-store/read.js +13 -0
- package/dist/src/store/turns/sqlite-store/rows.js +4 -0
- package/dist/src/store/turns/sqlite-store/write.js +3 -3
- package/dist/src/store/turns/sqlite-store.js +4 -0
- package/extensions/dashboard-client/dist/assets/{AdminTab-BsA8-_bX.js → AdminTab-C4Y0_UVx.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AdminTab-BsA8-_bX.js.map → AdminTab-C4Y0_UVx.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{AreaChart-BRHEfWhc.js → AreaChart-MCWK9rn6.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-BRHEfWhc.js.map → AreaChart-MCWK9rn6.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-C-M0LaFc.js → BarChart-CvSGAiWV.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-C-M0LaFc.js.map → BarChart-CvSGAiWV.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-Cj3n59U3.js → CacheTab-DnMEVRro.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-Cj3n59U3.js.map → CacheTab-DnMEVRro.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ConfigTab-C016XTNC.js → ConfigTab-BExuZYy2.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ConfigTab-C016XTNC.js.map → ConfigTab-BExuZYy2.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-DE29fuqe.js → EventsTab-CspsEslY.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-DE29fuqe.js.map → EventsTab-CspsEslY.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/HealthTab-DiWzo2ML.js +2 -0
- package/extensions/dashboard-client/dist/assets/HealthTab-DiWzo2ML.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-4fJ7M4S4.js → MaintenanceTab-9NJuv3dB.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-4fJ7M4S4.js.map → MaintenanceTab-9NJuv3dB.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CDbcK9e4.js → MemoryMapTab-YpJK1h17.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CDbcK9e4.js.map → MemoryMapTab-YpJK1h17.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsCards-VUEcgGzo.js → MetricsCards-D2Mom1M7.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsCards-VUEcgGzo.js.map → MetricsCards-D2Mom1M7.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/MetricsTab-DqWF7wud.js +2 -0
- package/extensions/dashboard-client/dist/assets/{MetricsTab-CKqJ0Zl-.js.map → MetricsTab-DqWF7wud.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-9Kxo79mi.js → OverviewTab-YuRxjV9U.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-9Kxo79mi.js.map → OverviewTab-YuRxjV9U.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-C4iveqrP.js → ReposTab-sXMrR7je.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-C4iveqrP.js.map → ReposTab-sXMrR7je.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DSEwkMQm.js → SessionsTab-4YCXeGNR.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DSEwkMQm.js.map → SessionsTab-4YCXeGNR.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-CCyWgy4O.js → SetupTab-67pZcM_W.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-CCyWgy4O.js.map → SetupTab-67pZcM_W.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-CyD8e_e_.js → TimeSavedCard-DInjNETP.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-CyD8e_e_.js.map → TimeSavedCard-DInjNETP.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnMemoryView-5tLbWkRv.js → TurnMemoryView-C3Bif8ix.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnMemoryView-5tLbWkRv.js.map → TurnMemoryView-C3Bif8ix.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/TurnsTab-BUGfiANp.js +2 -0
- package/extensions/dashboard-client/dist/assets/{TurnsTab-C7pm92Hg.js.map → TurnsTab-BUGfiANp.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VcStatusBadge-ObhcIyfN.js → VcStatusBadge-DKU7qz9f.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{VcStatusBadge-ObhcIyfN.js.map → VcStatusBadge-DKU7qz9f.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-BtHZb7o7.js → VectorCortexTab-BsVSf4xm.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-BtHZb7o7.js.map → VectorCortexTab-BsVSf4xm.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{WikiTab-lQ4l3QIK.js → WikiTab-DZw9_Fwd.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-lQ4l3QIK.js.map → WikiTab-DZw9_Fwd.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-DhQQAJGm.js → button-BLRPN489.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-DhQQAJGm.js.map → button-BLRPN489.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-Cfhz9X31.js → card-BGkkcM4Q.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-Cfhz9X31.js.map → card-BGkkcM4Q.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{client-extra-CKNOGEz_.js → client-extra-0OJClxHD.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{client-extra-CKNOGEz_.js.map → client-extra-0OJClxHD.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-JKjK9_cB.js → generateCategoricalChart-Dl5lmrHF.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-JKjK9_cB.js.map → generateCategoricalChart-Dl5lmrHF.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/health-lSeDFTz7.js.map +1 -1
- package/extensions/dashboard-client/dist/assets/{index-iuxgtzEW.js → index-CH_AD-S_.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{index-iuxgtzEW.js.map → index-CH_AD-S_.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{switch-7EHEQMSP.js → switch-BPP2-d12.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-7EHEQMSP.js.map → switch-BPP2-d12.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-z1lWY4UM.js → toggle-Dez0JaMV.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-z1lWY4UM.js.map → toggle-Dez0JaMV.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-sctOZuRM.js → useSSE-Cx2W7BTo.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-sctOZuRM.js.map → useSSE-Cx2W7BTo.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/api/health.ts +1 -0
- package/extensions/dashboard-client/src/tabs/HealthTab.tsx +1 -0
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +6 -0
- package/extensions/mega-compact-child.ts +129 -0
- package/extensions/mega-config-types.ts +5 -0
- package/extensions/mega-config.ts +5 -0
- package/extensions/mega-events/agent-handlers/turnEndHandler/recordTurnRow.ts +12 -2
- package/extensions/mega-events/context-handler/afterCompact.ts +11 -0
- package/extensions/mega-events/context-handler/dbMirrorAppend.ts +8 -0
- package/extensions/mega-events/health-handler.ts +13 -3
- package/extensions/mega-events/session-handlers.ts +1 -0
- package/extensions/mega-pipeline/compact/run.ts +11 -0
- package/extensions/mega-runtime/helpers.ts +46 -0
- package/extensions/mega-runtime/internal-errors.ts +30 -0
- package/extensions/mega-runtime/runtime-instrumentation.ts +195 -0
- package/extensions/mega-runtime/runtime.ts +29 -209
- package/extensions/mega-runtime/state.ts +1 -1
- package/extensions/mega-runtime/widget.ts +1 -1
- package/extensions/mega-turn-store.ts +9 -0
- package/package.json +2 -2
- package/src/bridge/factory.ts +245 -0
- package/src/bridge/types.ts +140 -0
- package/src/bridge.ts +24 -0
- package/src/contextHealth.ts +26 -6
- package/src/metrics/turns.ts +6 -1
- package/src/store/sqlite/context-health-cache-poison.ts +97 -0
- package/src/store/sqlite/context-health.ts +12 -84
- package/src/store/sqlite/embedding-cache.ts +4 -0
- package/src/store/sqlite/schema.ts +4 -0
- package/src/store/turns/memory-store/admin.ts +171 -0
- package/src/store/turns/memory-store/ctx.ts +62 -0
- package/src/store/turns/memory-store/read.ts +172 -0
- package/src/store/turns/memory-store/write.ts +126 -0
- package/src/store/turns/memory-store.ts +51 -330
- package/src/store/turns/migrations.ts +4 -0
- package/src/store/turns/schema.ts +1 -0
- package/src/store/turns/sqlite-store/read.ts +19 -0
- package/src/store/turns/sqlite-store/rows.ts +5 -0
- package/src/store/turns/sqlite-store/write.ts +3 -2
- package/src/store/turns/sqlite-store.ts +5 -0
- package/src/store/turns/types.ts +15 -0
- package/extensions/dashboard-client/dist/assets/HealthTab-D4eVI8ar.js +0 -2
- package/extensions/dashboard-client/dist/assets/HealthTab-D4eVI8ar.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/MetricsTab-CKqJ0Zl-.js +0 -2
- package/extensions/dashboard-client/dist/assets/TurnsTab-C7pm92Hg.js +0 -2
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ctx.ts — internal context interface for InMemoryTurnStore method bodies
|
|
3
|
+
* (extracted from memory-store.ts). Each free function in this directory
|
|
4
|
+
* operates on a MemoryTurnStoreCtx so the shell class can delegate without
|
|
5
|
+
* exposing its private fields.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors sqlite-store/ctx.ts. The Map/array references are stable for the
|
|
8
|
+
* life of the store: arrays (recall, forks) are mutated IN PLACE
|
|
9
|
+
* (push/splice/length=0), never reassigned, so a ctx captured at any point
|
|
10
|
+
* sees the current contents. The id counter is module-scoped here so both the
|
|
11
|
+
* shell (writers) and admin.ts share one allocator.
|
|
12
|
+
*/
|
|
13
|
+
import { randomBytes } from "node:crypto";
|
|
14
|
+
import type {
|
|
15
|
+
ConversationFork,
|
|
16
|
+
ConversationId,
|
|
17
|
+
SessionId,
|
|
18
|
+
TurnEntry,
|
|
19
|
+
TurnRecallEntry,
|
|
20
|
+
} from "../types.js";
|
|
21
|
+
|
|
22
|
+
/** Internal row with numeric id. */
|
|
23
|
+
export interface TurnRow {
|
|
24
|
+
id: number;
|
|
25
|
+
entry: TurnEntry;
|
|
26
|
+
epochId?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Internal recall row keyed by numeric turn id. */
|
|
30
|
+
export interface RecallRow {
|
|
31
|
+
turnId: number;
|
|
32
|
+
entry: TurnRecallEntry;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The mutable in-memory state free functions operate on. */
|
|
36
|
+
export interface MemoryTurnStoreCtx {
|
|
37
|
+
turns: Map<number, TurnRow>;
|
|
38
|
+
recall: RecallRow[];
|
|
39
|
+
forks: ConversationFork[];
|
|
40
|
+
convIndex: Map<ConversationId, number[]>;
|
|
41
|
+
sessionConv: Map<SessionId, ConversationId>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Auto-increment counter — shared by writers (appendTurn/forkConversation) and
|
|
45
|
+
// admin (restore). Module-scoped so a single counter spans the store's life.
|
|
46
|
+
let nextId = 1;
|
|
47
|
+
|
|
48
|
+
export function allocId(): number {
|
|
49
|
+
return nextId++;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function resetIdCounter(): void {
|
|
53
|
+
nextId = 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function newConversationId(): ConversationId {
|
|
57
|
+
return `conv_${randomBytes(8).toString("hex")}`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function normalizeSessionId(sid: SessionId): SessionId {
|
|
61
|
+
return sid.replace(/-.*$/, "");
|
|
62
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* read.ts — TurnReader method bodies for InMemoryTurnStore (extracted from
|
|
3
|
+
* memory-store.ts). Free functions operating on a MemoryTurnStoreCtx; the
|
|
4
|
+
* shell class delegates here. Mirrors sqlite-store/read.ts.
|
|
5
|
+
*/
|
|
6
|
+
import type {
|
|
7
|
+
ConversationFork,
|
|
8
|
+
ConversationId,
|
|
9
|
+
ConversationStats,
|
|
10
|
+
TurnEntry,
|
|
11
|
+
TurnFilter,
|
|
12
|
+
TurnId,
|
|
13
|
+
TurnRecallEntry,
|
|
14
|
+
} from "../types.js";
|
|
15
|
+
import { normalizeSessionId, type MemoryTurnStoreCtx } from "./ctx.js";
|
|
16
|
+
|
|
17
|
+
export function query(ctx: MemoryTurnStoreCtx, filter: TurnFilter): TurnEntry[] {
|
|
18
|
+
let results = [...ctx.turns.values()].map((r) => r.entry);
|
|
19
|
+
|
|
20
|
+
if (filter.conversationId !== undefined) {
|
|
21
|
+
results = results.filter(
|
|
22
|
+
(t) => t.conversationId === filter.conversationId,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (filter.sessionId !== undefined) {
|
|
26
|
+
results = results.filter(
|
|
27
|
+
(t) =>
|
|
28
|
+
normalizeSessionId(t.sessionId) ===
|
|
29
|
+
normalizeSessionId(filter.sessionId!),
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
if (filter.sinceMs !== undefined) {
|
|
33
|
+
results = results.filter((t) => t.endedAt >= filter.sinceMs!);
|
|
34
|
+
}
|
|
35
|
+
if (filter.untilMs !== undefined) {
|
|
36
|
+
results = results.filter((t) => t.endedAt <= filter.untilMs!);
|
|
37
|
+
}
|
|
38
|
+
if (filter.pressureBand !== undefined) {
|
|
39
|
+
results = results.filter((t) => t.pressureBand === filter.pressureBand);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
results.sort((a, b) => a.endedAt - b.endedAt);
|
|
43
|
+
|
|
44
|
+
const offset = filter.offset ?? 0;
|
|
45
|
+
const limit = filter.limit ?? 1000;
|
|
46
|
+
return results.slice(offset, offset + limit);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function getTurn(
|
|
50
|
+
ctx: MemoryTurnStoreCtx,
|
|
51
|
+
turnId: TurnId,
|
|
52
|
+
): TurnEntry | undefined {
|
|
53
|
+
const row = ctx.turns.get(Number(turnId));
|
|
54
|
+
return row ? { ...row.entry, epochId: row.epochId } : undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function getTurnByIndex(
|
|
58
|
+
ctx: MemoryTurnStoreCtx,
|
|
59
|
+
conversationId: ConversationId,
|
|
60
|
+
turnIndex: number,
|
|
61
|
+
): TurnEntry | undefined {
|
|
62
|
+
const ids = ctx.convIndex.get(conversationId) ?? [];
|
|
63
|
+
for (const id of ids) {
|
|
64
|
+
const row = ctx.turns.get(id);
|
|
65
|
+
if (row && row.entry.turnIndex === turnIndex) {
|
|
66
|
+
return { ...row.entry, epochId: row.epochId };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function listRecall(
|
|
73
|
+
ctx: MemoryTurnStoreCtx,
|
|
74
|
+
turnId: TurnId,
|
|
75
|
+
): TurnRecallEntry[] {
|
|
76
|
+
return ctx.recall
|
|
77
|
+
.filter((r) => r.turnId === Number(turnId))
|
|
78
|
+
.map((r) => r.entry)
|
|
79
|
+
.sort((a, b) => b.score - a.score);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function listRecallByIndex(
|
|
83
|
+
ctx: MemoryTurnStoreCtx,
|
|
84
|
+
conversationId: ConversationId,
|
|
85
|
+
turnIndex: number,
|
|
86
|
+
): TurnRecallEntry[] {
|
|
87
|
+
const turn = getTurnByIndex(ctx, conversationId, turnIndex);
|
|
88
|
+
if (!turn) return [];
|
|
89
|
+
// Resolve the numeric row id for this turn via the convIndex.
|
|
90
|
+
const ids = ctx.convIndex.get(conversationId) ?? [];
|
|
91
|
+
for (const id of ids) {
|
|
92
|
+
const row = ctx.turns.get(id);
|
|
93
|
+
if (row && row.entry.turnIndex === turnIndex) {
|
|
94
|
+
return listRecall(ctx, String(id));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function listForks(
|
|
101
|
+
ctx: MemoryTurnStoreCtx,
|
|
102
|
+
conversationId: ConversationId,
|
|
103
|
+
): ConversationFork[] {
|
|
104
|
+
return ctx.forks
|
|
105
|
+
.filter((f) => f.parentConversationId === conversationId)
|
|
106
|
+
.sort((a, b) => a.createdAt - b.createdAt);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function countTurns(
|
|
110
|
+
ctx: MemoryTurnStoreCtx,
|
|
111
|
+
conversationId: ConversationId,
|
|
112
|
+
): number {
|
|
113
|
+
const ids = ctx.convIndex.get(conversationId);
|
|
114
|
+
return ids?.length ?? 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function conversationStats(
|
|
118
|
+
ctx: MemoryTurnStoreCtx,
|
|
119
|
+
conversationId: ConversationId,
|
|
120
|
+
): ConversationStats {
|
|
121
|
+
const ids = ctx.convIndex.get(conversationId) ?? [];
|
|
122
|
+
const entries = ids
|
|
123
|
+
.map((id) => ctx.turns.get(id)?.entry)
|
|
124
|
+
.filter((e): e is TurnEntry => e !== undefined);
|
|
125
|
+
|
|
126
|
+
if (entries.length === 0) {
|
|
127
|
+
return {
|
|
128
|
+
turnCount: 0,
|
|
129
|
+
firstTurnAt: 0,
|
|
130
|
+
lastTurnAt: 0,
|
|
131
|
+
avgCtxPercent: 0,
|
|
132
|
+
pressureBands: {},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
let ctxSum = 0;
|
|
137
|
+
let ctxCount = 0;
|
|
138
|
+
const bands: Record<string, number> = {};
|
|
139
|
+
|
|
140
|
+
for (const e of entries) {
|
|
141
|
+
if (e.ctxPercent !== undefined) {
|
|
142
|
+
ctxSum += e.ctxPercent;
|
|
143
|
+
ctxCount++;
|
|
144
|
+
}
|
|
145
|
+
if (e.pressureBand)
|
|
146
|
+
bands[e.pressureBand] = (bands[e.pressureBand] ?? 0) + 1;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
turnCount: entries.length,
|
|
151
|
+
firstTurnAt: entries[0].endedAt,
|
|
152
|
+
lastTurnAt: entries[entries.length - 1].endedAt,
|
|
153
|
+
avgCtxPercent: ctxCount > 0 ? ctxSum / ctxCount : 0,
|
|
154
|
+
pressureBands: bands,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function nextTurnIndexFor(
|
|
159
|
+
ctx: MemoryTurnStoreCtx,
|
|
160
|
+
conversationId: ConversationId,
|
|
161
|
+
): number {
|
|
162
|
+
let max = -1;
|
|
163
|
+
for (const [, row] of ctx.turns) {
|
|
164
|
+
if (
|
|
165
|
+
row.entry.conversationId === conversationId &&
|
|
166
|
+
row.entry.turnIndex > max
|
|
167
|
+
) {
|
|
168
|
+
max = row.entry.turnIndex;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return max + 1;
|
|
172
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* write.ts — TurnWriter method bodies for InMemoryTurnStore (extracted from
|
|
3
|
+
* memory-store.ts). Free functions operating on a MemoryTurnStoreCtx; the
|
|
4
|
+
* shell class delegates here. Mirrors sqlite-store/write.ts.
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
DuplicateTurnError,
|
|
8
|
+
type ConversationId,
|
|
9
|
+
type SessionId,
|
|
10
|
+
type TurnEntry,
|
|
11
|
+
type TurnId,
|
|
12
|
+
type TurnRecallEntry,
|
|
13
|
+
} from "../types.js";
|
|
14
|
+
import {
|
|
15
|
+
allocId,
|
|
16
|
+
newConversationId,
|
|
17
|
+
normalizeSessionId,
|
|
18
|
+
type MemoryTurnStoreCtx,
|
|
19
|
+
} from "./ctx.js";
|
|
20
|
+
|
|
21
|
+
export function appendTurn(
|
|
22
|
+
ctx: MemoryTurnStoreCtx,
|
|
23
|
+
entry: TurnEntry,
|
|
24
|
+
): TurnId {
|
|
25
|
+
// Check for duplicate (conversationId, turnIndex)
|
|
26
|
+
for (const [, row] of ctx.turns) {
|
|
27
|
+
if (
|
|
28
|
+
row.entry.conversationId === entry.conversationId &&
|
|
29
|
+
row.entry.turnIndex === entry.turnIndex
|
|
30
|
+
) {
|
|
31
|
+
throw new DuplicateTurnError(entry.conversationId, entry.turnIndex);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const id = allocId();
|
|
35
|
+
const sid = normalizeSessionId(entry.sessionId);
|
|
36
|
+
const normalized = { ...entry, sessionId: sid };
|
|
37
|
+
ctx.turns.set(id, { id, entry: normalized });
|
|
38
|
+
|
|
39
|
+
// Update indices
|
|
40
|
+
const convIds = ctx.convIndex.get(entry.conversationId) ?? [];
|
|
41
|
+
convIds.push(id);
|
|
42
|
+
ctx.convIndex.set(entry.conversationId, convIds);
|
|
43
|
+
|
|
44
|
+
ctx.sessionConv.set(sid, entry.conversationId);
|
|
45
|
+
|
|
46
|
+
return String(id);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function appendRecall(ctx: MemoryTurnStoreCtx, entry: TurnRecallEntry): void {
|
|
50
|
+
// De-dup by (turn_id, checkpoint_id)
|
|
51
|
+
const exists = ctx.recall.some(
|
|
52
|
+
(r) =>
|
|
53
|
+
r.turnId === Number(entry.turnId) &&
|
|
54
|
+
r.entry.checkpointId === entry.checkpointId,
|
|
55
|
+
);
|
|
56
|
+
if (!exists) {
|
|
57
|
+
ctx.recall.push({ turnId: Number(entry.turnId), entry });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function ensureConversationId(
|
|
62
|
+
ctx: MemoryTurnStoreCtx,
|
|
63
|
+
sessionId: SessionId,
|
|
64
|
+
): ConversationId {
|
|
65
|
+
const sid = normalizeSessionId(sessionId);
|
|
66
|
+
const existing = ctx.sessionConv.get(sid);
|
|
67
|
+
if (existing) return existing;
|
|
68
|
+
// Generate and store a new conversation ID for this session
|
|
69
|
+
const convId = newConversationId();
|
|
70
|
+
ctx.sessionConv.set(sid, convId);
|
|
71
|
+
return convId;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function forkConversation(
|
|
75
|
+
ctx: MemoryTurnStoreCtx,
|
|
76
|
+
parentId: ConversationId,
|
|
77
|
+
forkTurnIndex: number,
|
|
78
|
+
): ConversationId {
|
|
79
|
+
const childId = newConversationId();
|
|
80
|
+
const now = Date.now();
|
|
81
|
+
|
|
82
|
+
// 1. Record the fork lineage
|
|
83
|
+
ctx.forks.push({
|
|
84
|
+
parentConversationId: parentId,
|
|
85
|
+
childConversationId: childId,
|
|
86
|
+
forkTurnIndex,
|
|
87
|
+
createdAt: now,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// 2. Find the parent's turn at forkTurnIndex
|
|
91
|
+
const parentTurnIds = ctx.convIndex.get(parentId) ?? [];
|
|
92
|
+
const parentTurnRow = parentTurnIds
|
|
93
|
+
.map((id) => ctx.turns.get(id))
|
|
94
|
+
.find((r) => r?.entry.turnIndex === forkTurnIndex);
|
|
95
|
+
|
|
96
|
+
if (!parentTurnRow) return childId; // no parent turn — nothing to seed
|
|
97
|
+
|
|
98
|
+
// 3. Create a seed turn in the child conversation
|
|
99
|
+
const seedId = allocId();
|
|
100
|
+
const seedEntry: TurnEntry = {
|
|
101
|
+
conversationId: childId,
|
|
102
|
+
sessionId: `fork_${childId}`,
|
|
103
|
+
turnIndex: 0,
|
|
104
|
+
role: "system",
|
|
105
|
+
endedAt: now,
|
|
106
|
+
};
|
|
107
|
+
ctx.turns.set(seedId, { id: seedId, entry: seedEntry });
|
|
108
|
+
ctx.convIndex.set(childId, [seedId]);
|
|
109
|
+
|
|
110
|
+
// 4. Copy the parent's recall entries into the child's seed turn
|
|
111
|
+
const parentRecall = ctx.recall.filter((r) => r.turnId === parentTurnRow.id);
|
|
112
|
+
for (const r of parentRecall) {
|
|
113
|
+
ctx.recall.push({
|
|
114
|
+
turnId: seedId,
|
|
115
|
+
entry: {
|
|
116
|
+
turnId: String(seedId),
|
|
117
|
+
checkpointId: r.entry.checkpointId,
|
|
118
|
+
score: r.entry.score,
|
|
119
|
+
source: r.entry.source,
|
|
120
|
+
raptorLevel: r.entry.raptorLevel,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return childId;
|
|
126
|
+
}
|