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.
Files changed (131) hide show
  1. package/dist/extensions/mega-events/agent-handlers/turnEndHandler/recordTurnRow.js +12 -2
  2. package/dist/extensions/mega-events/context-handler/afterCompact.js +11 -0
  3. package/dist/extensions/mega-events/context-handler/dbMirrorAppend.js +8 -0
  4. package/dist/extensions/mega-events/health-handler.js +12 -2
  5. package/dist/extensions/mega-events/session-handlers.js +1 -0
  6. package/dist/extensions/mega-pipeline/compact/run.js +11 -0
  7. package/dist/extensions/mega-runtime/helpers.js +45 -0
  8. package/dist/extensions/mega-runtime/internal-errors.js +14 -0
  9. package/dist/extensions/mega-runtime/runtime-instrumentation.js +166 -0
  10. package/dist/extensions/mega-runtime/runtime.js +27 -193
  11. package/dist/extensions/mega-runtime/state.js +1 -1
  12. package/dist/extensions/mega-runtime/widget.js +1 -1
  13. package/dist/extensions/mega-turn-store.js +5 -0
  14. package/dist/src/bridge/factory.js +15 -1
  15. package/dist/src/contextHealth.js +13 -5
  16. package/dist/src/metrics/turns.js +6 -1
  17. package/dist/src/store/sqlite/context-health-cache-poison.js +60 -0
  18. package/dist/src/store/sqlite/context-health.js +6 -48
  19. package/dist/src/store/sqlite/embedding-cache.js +4 -0
  20. package/dist/src/store/sqlite/schema.js +4 -0
  21. package/dist/src/store/turns/memory-store/admin.js +119 -0
  22. package/dist/src/store/turns/memory-store/ctx.js +28 -0
  23. package/dist/src/store/turns/memory-store/read.js +110 -0
  24. package/dist/src/store/turns/memory-store/write.js +88 -0
  25. package/dist/src/store/turns/memory-store.js +44 -273
  26. package/dist/src/store/turns/migrations.js +4 -0
  27. package/dist/src/store/turns/schema.js +1 -0
  28. package/dist/src/store/turns/sqlite-store/read.js +13 -0
  29. package/dist/src/store/turns/sqlite-store/rows.js +4 -0
  30. package/dist/src/store/turns/sqlite-store/write.js +3 -3
  31. package/dist/src/store/turns/sqlite-store.js +4 -0
  32. package/extensions/dashboard-client/dist/assets/{AdminTab-BsA8-_bX.js → AdminTab-C4Y0_UVx.js} +2 -2
  33. package/extensions/dashboard-client/dist/assets/{AdminTab-BsA8-_bX.js.map → AdminTab-C4Y0_UVx.js.map} +1 -1
  34. package/extensions/dashboard-client/dist/assets/{AreaChart-BRHEfWhc.js → AreaChart-MCWK9rn6.js} +2 -2
  35. package/extensions/dashboard-client/dist/assets/{AreaChart-BRHEfWhc.js.map → AreaChart-MCWK9rn6.js.map} +1 -1
  36. package/extensions/dashboard-client/dist/assets/{BarChart-C-M0LaFc.js → BarChart-CvSGAiWV.js} +2 -2
  37. package/extensions/dashboard-client/dist/assets/{BarChart-C-M0LaFc.js.map → BarChart-CvSGAiWV.js.map} +1 -1
  38. package/extensions/dashboard-client/dist/assets/{CacheTab-Cj3n59U3.js → CacheTab-DnMEVRro.js} +2 -2
  39. package/extensions/dashboard-client/dist/assets/{CacheTab-Cj3n59U3.js.map → CacheTab-DnMEVRro.js.map} +1 -1
  40. package/extensions/dashboard-client/dist/assets/{ConfigTab-C016XTNC.js → ConfigTab-BExuZYy2.js} +2 -2
  41. package/extensions/dashboard-client/dist/assets/{ConfigTab-C016XTNC.js.map → ConfigTab-BExuZYy2.js.map} +1 -1
  42. package/extensions/dashboard-client/dist/assets/{EventsTab-DE29fuqe.js → EventsTab-CspsEslY.js} +2 -2
  43. package/extensions/dashboard-client/dist/assets/{EventsTab-DE29fuqe.js.map → EventsTab-CspsEslY.js.map} +1 -1
  44. package/extensions/dashboard-client/dist/assets/HealthTab-DiWzo2ML.js +2 -0
  45. package/extensions/dashboard-client/dist/assets/HealthTab-DiWzo2ML.js.map +1 -0
  46. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-4fJ7M4S4.js → MaintenanceTab-9NJuv3dB.js} +2 -2
  47. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-4fJ7M4S4.js.map → MaintenanceTab-9NJuv3dB.js.map} +1 -1
  48. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CDbcK9e4.js → MemoryMapTab-YpJK1h17.js} +2 -2
  49. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CDbcK9e4.js.map → MemoryMapTab-YpJK1h17.js.map} +1 -1
  50. package/extensions/dashboard-client/dist/assets/{MetricsCards-VUEcgGzo.js → MetricsCards-D2Mom1M7.js} +2 -2
  51. package/extensions/dashboard-client/dist/assets/{MetricsCards-VUEcgGzo.js.map → MetricsCards-D2Mom1M7.js.map} +1 -1
  52. package/extensions/dashboard-client/dist/assets/MetricsTab-DqWF7wud.js +2 -0
  53. package/extensions/dashboard-client/dist/assets/{MetricsTab-CKqJ0Zl-.js.map → MetricsTab-DqWF7wud.js.map} +1 -1
  54. package/extensions/dashboard-client/dist/assets/{OverviewTab-9Kxo79mi.js → OverviewTab-YuRxjV9U.js} +2 -2
  55. package/extensions/dashboard-client/dist/assets/{OverviewTab-9Kxo79mi.js.map → OverviewTab-YuRxjV9U.js.map} +1 -1
  56. package/extensions/dashboard-client/dist/assets/{ReposTab-C4iveqrP.js → ReposTab-sXMrR7je.js} +2 -2
  57. package/extensions/dashboard-client/dist/assets/{ReposTab-C4iveqrP.js.map → ReposTab-sXMrR7je.js.map} +1 -1
  58. package/extensions/dashboard-client/dist/assets/{SessionsTab-DSEwkMQm.js → SessionsTab-4YCXeGNR.js} +2 -2
  59. package/extensions/dashboard-client/dist/assets/{SessionsTab-DSEwkMQm.js.map → SessionsTab-4YCXeGNR.js.map} +1 -1
  60. package/extensions/dashboard-client/dist/assets/{SetupTab-CCyWgy4O.js → SetupTab-67pZcM_W.js} +2 -2
  61. package/extensions/dashboard-client/dist/assets/{SetupTab-CCyWgy4O.js.map → SetupTab-67pZcM_W.js.map} +1 -1
  62. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-CyD8e_e_.js → TimeSavedCard-DInjNETP.js} +2 -2
  63. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-CyD8e_e_.js.map → TimeSavedCard-DInjNETP.js.map} +1 -1
  64. package/extensions/dashboard-client/dist/assets/{TurnMemoryView-5tLbWkRv.js → TurnMemoryView-C3Bif8ix.js} +2 -2
  65. package/extensions/dashboard-client/dist/assets/{TurnMemoryView-5tLbWkRv.js.map → TurnMemoryView-C3Bif8ix.js.map} +1 -1
  66. package/extensions/dashboard-client/dist/assets/TurnsTab-BUGfiANp.js +2 -0
  67. package/extensions/dashboard-client/dist/assets/{TurnsTab-C7pm92Hg.js.map → TurnsTab-BUGfiANp.js.map} +1 -1
  68. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-ObhcIyfN.js → VcStatusBadge-DKU7qz9f.js} +2 -2
  69. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-ObhcIyfN.js.map → VcStatusBadge-DKU7qz9f.js.map} +1 -1
  70. package/extensions/dashboard-client/dist/assets/{VectorCortexTab-BtHZb7o7.js → VectorCortexTab-BsVSf4xm.js} +2 -2
  71. package/extensions/dashboard-client/dist/assets/{VectorCortexTab-BtHZb7o7.js.map → VectorCortexTab-BsVSf4xm.js.map} +1 -1
  72. package/extensions/dashboard-client/dist/assets/{WikiTab-lQ4l3QIK.js → WikiTab-DZw9_Fwd.js} +2 -2
  73. package/extensions/dashboard-client/dist/assets/{WikiTab-lQ4l3QIK.js.map → WikiTab-DZw9_Fwd.js.map} +1 -1
  74. package/extensions/dashboard-client/dist/assets/{button-DhQQAJGm.js → button-BLRPN489.js} +2 -2
  75. package/extensions/dashboard-client/dist/assets/{button-DhQQAJGm.js.map → button-BLRPN489.js.map} +1 -1
  76. package/extensions/dashboard-client/dist/assets/{card-Cfhz9X31.js → card-BGkkcM4Q.js} +2 -2
  77. package/extensions/dashboard-client/dist/assets/{card-Cfhz9X31.js.map → card-BGkkcM4Q.js.map} +1 -1
  78. package/extensions/dashboard-client/dist/assets/{client-extra-CKNOGEz_.js → client-extra-0OJClxHD.js} +2 -2
  79. package/extensions/dashboard-client/dist/assets/{client-extra-CKNOGEz_.js.map → client-extra-0OJClxHD.js.map} +1 -1
  80. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-JKjK9_cB.js → generateCategoricalChart-Dl5lmrHF.js} +2 -2
  81. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-JKjK9_cB.js.map → generateCategoricalChart-Dl5lmrHF.js.map} +1 -1
  82. package/extensions/dashboard-client/dist/assets/health-lSeDFTz7.js.map +1 -1
  83. package/extensions/dashboard-client/dist/assets/{index-iuxgtzEW.js → index-CH_AD-S_.js} +3 -3
  84. package/extensions/dashboard-client/dist/assets/{index-iuxgtzEW.js.map → index-CH_AD-S_.js.map} +1 -1
  85. package/extensions/dashboard-client/dist/assets/{switch-7EHEQMSP.js → switch-BPP2-d12.js} +2 -2
  86. package/extensions/dashboard-client/dist/assets/{switch-7EHEQMSP.js.map → switch-BPP2-d12.js.map} +1 -1
  87. package/extensions/dashboard-client/dist/assets/{toggle-z1lWY4UM.js → toggle-Dez0JaMV.js} +2 -2
  88. package/extensions/dashboard-client/dist/assets/{toggle-z1lWY4UM.js.map → toggle-Dez0JaMV.js.map} +1 -1
  89. package/extensions/dashboard-client/dist/assets/{useSSE-sctOZuRM.js → useSSE-Cx2W7BTo.js} +2 -2
  90. package/extensions/dashboard-client/dist/assets/{useSSE-sctOZuRM.js.map → useSSE-Cx2W7BTo.js.map} +1 -1
  91. package/extensions/dashboard-client/dist/index.html +1 -1
  92. package/extensions/dashboard-client/src/api/health.ts +1 -0
  93. package/extensions/dashboard-client/src/tabs/HealthTab.tsx +1 -0
  94. package/extensions/mega-events/agent-handlers/turnEndHandler/recordTurnRow.ts +12 -2
  95. package/extensions/mega-events/context-handler/afterCompact.ts +11 -0
  96. package/extensions/mega-events/context-handler/dbMirrorAppend.ts +8 -0
  97. package/extensions/mega-events/health-handler.ts +13 -3
  98. package/extensions/mega-events/session-handlers.ts +1 -0
  99. package/extensions/mega-pipeline/compact/run.ts +11 -0
  100. package/extensions/mega-runtime/helpers.ts +46 -0
  101. package/extensions/mega-runtime/internal-errors.ts +30 -0
  102. package/extensions/mega-runtime/runtime-instrumentation.ts +195 -0
  103. package/extensions/mega-runtime/runtime.ts +29 -209
  104. package/extensions/mega-runtime/state.ts +1 -1
  105. package/extensions/mega-runtime/widget.ts +1 -1
  106. package/extensions/mega-turn-store.ts +9 -0
  107. package/package.json +2 -2
  108. package/src/bridge/factory.ts +15 -1
  109. package/src/bridge/types.ts +2 -0
  110. package/src/contextHealth.ts +26 -6
  111. package/src/metrics/turns.ts +6 -1
  112. package/src/store/sqlite/context-health-cache-poison.ts +97 -0
  113. package/src/store/sqlite/context-health.ts +12 -84
  114. package/src/store/sqlite/embedding-cache.ts +4 -0
  115. package/src/store/sqlite/schema.ts +4 -0
  116. package/src/store/turns/memory-store/admin.ts +171 -0
  117. package/src/store/turns/memory-store/ctx.ts +62 -0
  118. package/src/store/turns/memory-store/read.ts +172 -0
  119. package/src/store/turns/memory-store/write.ts +126 -0
  120. package/src/store/turns/memory-store.ts +51 -330
  121. package/src/store/turns/migrations.ts +4 -0
  122. package/src/store/turns/schema.ts +1 -0
  123. package/src/store/turns/sqlite-store/read.ts +19 -0
  124. package/src/store/turns/sqlite-store/rows.ts +5 -0
  125. package/src/store/turns/sqlite-store/write.ts +3 -2
  126. package/src/store/turns/sqlite-store.ts +5 -0
  127. package/src/store/turns/types.ts +15 -0
  128. package/extensions/dashboard-client/dist/assets/HealthTab-D4eVI8ar.js +0 -2
  129. package/extensions/dashboard-client/dist/assets/HealthTab-D4eVI8ar.js.map +0 -1
  130. package/extensions/dashboard-client/dist/assets/MetricsTab-CKqJ0Zl-.js +0 -2
  131. 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
+ }