pi-mega-compact 0.21.3 → 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/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 +15 -1
- 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/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 +15 -1
- package/src/bridge/types.ts +2 -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,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
|
+
}
|