@code-yeongyu/senpi 2026.8.30-3 → 2026.8.31

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 (188) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +3 -0
  3. package/dist/core/agent-session.d.ts +26 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +67 -0
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts +9 -1
  8. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts.map +1 -1
  9. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js +10 -3
  10. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js.map +1 -1
  11. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +1 -1
  12. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  13. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +4 -1
  14. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  15. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +1 -0
  16. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -1
  17. package/dist/core/extensions/builtin/compaction/speculative-summary.js +1 -0
  18. package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -1
  19. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  20. package/dist/core/extensions/builtin/compaction/speculative.js +14 -1
  21. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  22. package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts +5 -0
  23. package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts.map +1 -0
  24. package/dist/core/extensions/builtin/hooks/trust-state-json.js +76 -0
  25. package/dist/core/extensions/builtin/hooks/trust-state-json.js.map +1 -0
  26. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts +7 -1
  27. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts.map +1 -1
  28. package/dist/core/extensions/builtin/hooks/trust-storage.js +60 -8
  29. package/dist/core/extensions/builtin/hooks/trust-storage.js.map +1 -1
  30. package/dist/core/extensions/builtin/hooks/trust.d.ts +1 -2
  31. package/dist/core/extensions/builtin/hooks/trust.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/hooks/trust.js +1 -72
  33. package/dist/core/extensions/builtin/hooks/trust.js.map +1 -1
  34. package/dist/core/extensions/builtin/ttsr/index.d.ts.map +1 -1
  35. package/dist/core/extensions/builtin/ttsr/index.js +4 -0
  36. package/dist/core/extensions/builtin/ttsr/index.js.map +1 -1
  37. package/dist/core/extensions/builtin/ttsr/manager.d.ts +2 -0
  38. package/dist/core/extensions/builtin/ttsr/manager.d.ts.map +1 -1
  39. package/dist/core/extensions/builtin/ttsr/manager.js +28 -1
  40. package/dist/core/extensions/builtin/ttsr/manager.js.map +1 -1
  41. package/dist/core/extensions/runner.d.ts +5 -0
  42. package/dist/core/extensions/runner.d.ts.map +1 -1
  43. package/dist/core/extensions/runner.js +7 -0
  44. package/dist/core/extensions/runner.js.map +1 -1
  45. package/dist/core/retry-fallback/controller.d.ts +14 -0
  46. package/dist/core/retry-fallback/controller.d.ts.map +1 -1
  47. package/dist/core/retry-fallback/controller.js +33 -3
  48. package/dist/core/retry-fallback/controller.js.map +1 -1
  49. package/dist/core/retry-fallback/log.js +1 -1
  50. package/dist/core/retry-fallback/log.js.map +1 -1
  51. package/dist/core/session-activity.d.ts +47 -0
  52. package/dist/core/session-activity.d.ts.map +1 -0
  53. package/dist/core/session-activity.js +58 -0
  54. package/dist/core/session-activity.js.map +1 -0
  55. package/dist/core/session-manager.d.ts +8 -12
  56. package/dist/core/session-manager.d.ts.map +1 -1
  57. package/dist/core/session-manager.js +118 -7
  58. package/dist/core/session-manager.js.map +1 -1
  59. package/dist/core/session-resident-store.d.ts +8 -1
  60. package/dist/core/session-resident-store.d.ts.map +1 -1
  61. package/dist/core/session-resident-store.js +12 -5
  62. package/dist/core/session-resident-store.js.map +1 -1
  63. package/dist/modes/app-server/daemon.js +3 -3
  64. package/dist/modes/app-server/daemon.js.map +1 -1
  65. package/dist/modes/interactive/interactive-host-runtime.d.ts +3 -1
  66. package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
  67. package/dist/modes/interactive/interactive-host-runtime.js +26 -4
  68. package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
  69. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  70. package/dist/modes/interactive/interactive-mode.js +24 -0
  71. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  72. package/dist/modes/rpc/connection-handler.d.ts +12 -5
  73. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  74. package/dist/modes/rpc/connection-handler.js +149 -12
  75. package/dist/modes/rpc/connection-handler.js.map +1 -1
  76. package/dist/modes/rpc/custom-capability.d.ts +1 -0
  77. package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
  78. package/dist/modes/rpc/custom-capability.js +1 -0
  79. package/dist/modes/rpc/custom-capability.js.map +1 -1
  80. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  81. package/dist/modes/rpc/host-ensure.js +3 -3
  82. package/dist/modes/rpc/host-ensure.js.map +1 -1
  83. package/dist/modes/rpc/host-lifecycle.d.ts +10 -0
  84. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  85. package/dist/modes/rpc/host-lifecycle.js +15 -2
  86. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  87. package/dist/modes/rpc/multi-session-host.d.ts +38 -0
  88. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  89. package/dist/modes/rpc/multi-session-host.js +55 -5
  90. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  91. package/dist/modes/rpc/ownership-safe-lock.d.ts +14 -0
  92. package/dist/modes/rpc/ownership-safe-lock.d.ts.map +1 -0
  93. package/dist/modes/rpc/ownership-safe-lock.js +87 -0
  94. package/dist/modes/rpc/ownership-safe-lock.js.map +1 -0
  95. package/dist/modes/rpc/rpc-client.d.ts +1 -0
  96. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  97. package/dist/modes/rpc/rpc-client.js +3 -0
  98. package/dist/modes/rpc/rpc-client.js.map +1 -1
  99. package/dist/modes/rpc/rpc-types.d.ts +12 -1
  100. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  101. package/dist/modes/rpc/rpc-types.js +1 -0
  102. package/dist/modes/rpc/rpc-types.js.map +1 -1
  103. package/dist/modes/rpc/session-binding.d.ts +2 -1
  104. package/dist/modes/rpc/session-binding.d.ts.map +1 -1
  105. package/dist/modes/rpc/session-binding.js +1 -0
  106. package/dist/modes/rpc/session-binding.js.map +1 -1
  107. package/dist/modes/rpc/session-command-router.d.ts +54 -1
  108. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  109. package/dist/modes/rpc/session-command-router.js +174 -2
  110. package/dist/modes/rpc/session-command-router.js.map +1 -1
  111. package/dist/modes/rpc/session-event-writer.d.ts +18 -0
  112. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  113. package/dist/modes/rpc/session-event-writer.js +88 -8
  114. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  115. package/dist/modes/rpc/session-registry.d.ts +11 -1
  116. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  117. package/dist/modes/rpc/session-registry.js +25 -0
  118. package/dist/modes/rpc/session-registry.js.map +1 -1
  119. package/dist/modes/rpc/widget-line-renderer.d.ts +17 -0
  120. package/dist/modes/rpc/widget-line-renderer.d.ts.map +1 -0
  121. package/dist/modes/rpc/widget-line-renderer.js +73 -0
  122. package/dist/modes/rpc/widget-line-renderer.js.map +1 -0
  123. package/dist/utils/fs-watch.d.ts.map +1 -1
  124. package/dist/utils/fs-watch.js +11 -2
  125. package/dist/utils/fs-watch.js.map +1 -1
  126. package/docs/app-server.md +2 -2
  127. package/docs/containerization.md +2 -2
  128. package/docs/development.md +7 -7
  129. package/docs/extensions.md +4 -4
  130. package/docs/grok-neo.md +1 -1
  131. package/docs/index.md +1 -1
  132. package/docs/packages.md +2 -2
  133. package/docs/quickstart.md +4 -4
  134. package/docs/release-guide.md +21 -21
  135. package/docs/rpc.md +59 -4
  136. package/docs/sdk.md +1 -1
  137. package/docs/skills.md +2 -2
  138. package/docs/terminal-tools.md +1 -1
  139. package/docs/termux.md +1 -1
  140. package/docs/tui.md +1 -1
  141. package/examples/AGENTS.md +1 -1
  142. package/examples/sdk/README.md +1 -1
  143. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +16 -0
  144. package/node_modules/@code-yeongyu/senpi-codemode/README.md +2 -2
  145. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  146. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/skill-contribution.ts +71 -0
  147. package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +3 -1
  148. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/SKILL.md +44 -0
  149. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/breaking-changes.md +75 -0
  150. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/build.md +114 -0
  151. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/dev-tooling.md +34 -0
  152. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/http-networking.md +113 -0
  153. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/install.md +93 -0
  154. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/node-compat-platforms.md +36 -0
  155. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/performance.md +33 -0
  156. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/runtime-apis.md +156 -0
  157. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/security.md +52 -0
  158. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/test.md +103 -0
  159. package/node_modules/@earendil-works/pi-agent-core/README.md +3 -0
  160. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  161. package/node_modules/@earendil-works/pi-ai/README.md +6 -3
  162. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  163. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +15 -0
  164. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  165. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +7 -0
  166. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
  167. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +316 -2
  168. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
  169. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts +4 -0
  170. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts.map +1 -1
  171. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js +23 -0
  172. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js.map +1 -1
  173. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +24 -0
  174. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  175. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +20 -2
  176. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  177. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  178. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  179. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  180. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  181. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  182. package/node_modules/@earendil-works/pi-telemetry/README.md +6 -3
  183. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  184. package/node_modules/@earendil-works/pi-tui/README.md +5 -4
  185. package/node_modules/@earendil-works/pi-tui/native/darwin/README.md +2 -2
  186. package/node_modules/@earendil-works/pi-tui/native/win32/README.md +2 -2
  187. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  188. package/package.json +7 -7
@@ -497,6 +497,15 @@ export function findMostRecentSession(sessionDir, cwd) {
497
497
  * Use buildSessionContext() to get the resolved message list for the LLM, which
498
498
  * handles compaction summaries and follows the path from root to current leaf.
499
499
  */
500
+ let sessionEntryLoader = loadEntriesFromFile;
501
+ /** Test seam for observing disk reloads without mocking ESM filesystem exports. */
502
+ export function setSessionEntryLoaderForTesting(loader) {
503
+ const previous = sessionEntryLoader;
504
+ sessionEntryLoader = loader;
505
+ return () => {
506
+ sessionEntryLoader = previous;
507
+ };
508
+ }
500
509
  export class SessionManager {
501
510
  constructor(cwd, sessionDir, sessionFile, persist, newSessionOptions, preloadedFileEntries) {
502
511
  this.sessionId = "";
@@ -513,6 +522,8 @@ export class SessionManager {
513
522
  this.labelTimestampsById = new Map();
514
523
  this.leafId = null;
515
524
  this.residentStore = new ResidentStringStore();
525
+ this.mirrorTrimmed = false;
526
+ this.compactEntriesCache = null;
516
527
  // Monotonic counter bumped by every mutator; memoized materialized views are
517
528
  // keyed on it so read hot paths (footer, RPC) never re-materialize unchanged sessions.
518
529
  this.mutationCount = 0;
@@ -567,6 +578,7 @@ export class SessionManager {
567
578
  }
568
579
  _setSessionFile(sessionFile, preloadedFileEntries) {
569
580
  this.sessionFile = resolvePath(sessionFile);
581
+ this.mirrorTrimmed = false;
570
582
  this.residentStore.clear();
571
583
  if (existsSync(this.sessionFile)) {
572
584
  this.fileEntries = preloadedFileEntries ?? loadEntriesFromFile(this.sessionFile);
@@ -614,6 +626,7 @@ export class SessionManager {
614
626
  parentSession: options?.parentSession,
615
627
  };
616
628
  this.fileEntries = [header];
629
+ this.mirrorTrimmed = false;
617
630
  this.residentStore.clear();
618
631
  this.byId.clear();
619
632
  this.entryOrdersById.clear();
@@ -776,7 +789,18 @@ export class SessionManager {
776
789
  }
777
790
  }
778
791
  _materializeEntry(entry) {
779
- const materialized = this.residentStore.materialize(entry);
792
+ let missingResidentString = false;
793
+ const materialized = this.residentStore.materialize(entry, () => {
794
+ missingResidentString = true;
795
+ return undefined;
796
+ });
797
+ // The resident store is a bounded cache. The JSONL remains authoritative
798
+ // when an evicted blob is needed by a branch or read operation.
799
+ if (missingResidentString && this.sessionFile) {
800
+ const persisted = loadEntriesFromFile(this.sessionFile).find((candidate) => candidate.id === entry.id);
801
+ if (persisted)
802
+ return persisted;
803
+ }
780
804
  if (materialized.type === "message") {
781
805
  const order = this.entryOrdersById.get(materialized.id);
782
806
  if (order !== undefined) {
@@ -886,9 +910,36 @@ export class SessionManager {
886
910
  fromHook,
887
911
  };
888
912
  this._appendEntry(entry);
913
+ this._trimMirrorAfterCompaction(entry);
889
914
  return entry.id;
890
915
  }
891
- /** Append a custom entry (for extensions) as child of current leaf, then advance leaf. Returns entry id. */
916
+ _trimMirrorAfterCompaction(compaction) {
917
+ if (!this.persist)
918
+ return;
919
+ const firstKeptIndex = this.fileEntries.findIndex((entry) => entry.id === compaction.firstKeptEntryId);
920
+ const compactionIndex = this.fileEntries.findIndex((entry) => entry.id === compaction.id);
921
+ if (firstKeptIndex < 0 || compactionIndex < firstKeptIndex)
922
+ return;
923
+ const header = this.fileEntries.find((entry) => entry.type === "session");
924
+ const retained = [
925
+ ...this.fileEntries.slice(0, firstKeptIndex).filter((entry) => entry.type !== "message"),
926
+ ...this.fileEntries.slice(firstKeptIndex, compactionIndex + 1),
927
+ ];
928
+ let parentId = null;
929
+ for (const entry of retained) {
930
+ if (entry.type !== "session")
931
+ entry.parentId = parentId;
932
+ parentId = entry.type === "session" ? null : entry.id;
933
+ }
934
+ this.residentStore.clear();
935
+ this.mirrorTrimmed = true;
936
+ this.fileEntries = [header, ...retained]
937
+ .filter((entry) => entry !== undefined)
938
+ .map((entry) => this.residentStore.externalize(entry));
939
+ this._buildIndex();
940
+ this.mutationCount++;
941
+ }
942
+ /** Append a custom entry (for extensions) as child of current leaf, then advance leaf. */
892
943
  appendCustomEntry(customType, data) {
893
944
  const entry = {
894
945
  type: "custom",
@@ -956,7 +1007,13 @@ export class SessionManager {
956
1007
  }
957
1008
  getEntry(id) {
958
1009
  const entry = this.byId.get(id);
959
- return entry ? this._materializeEntry(entry) : undefined;
1010
+ if (entry)
1011
+ return this._materializeEntry(entry);
1012
+ if (this.mirrorTrimmed && this.sessionFile) {
1013
+ const persisted = this._loadFullHistoryEntries().find((candidate) => candidate.id === id);
1014
+ return persisted ? this.residentStore.materialize(persisted) : undefined;
1015
+ }
1016
+ return undefined;
960
1017
  }
961
1018
  /**
962
1019
  * Get all direct children of an entry.
@@ -1020,10 +1077,16 @@ export class SessionManager {
1020
1077
  }
1021
1078
  const path = [];
1022
1079
  const startId = fromId ?? this.leafId;
1023
- let current = startId ? this.byId.get(startId) : undefined;
1080
+ let entriesById = this.byId;
1081
+ if (fromId !== undefined && !entriesById.has(fromId) && this.mirrorTrimmed && this.sessionFile) {
1082
+ entriesById = new Map(this._loadFullHistoryEntries()
1083
+ .filter((entry) => entry.type !== "session")
1084
+ .map((entry) => [entry.id, this.residentStore.materialize(entry)]));
1085
+ }
1086
+ let current = startId ? entriesById.get(startId) : undefined;
1024
1087
  while (current) {
1025
1088
  path.unshift(this._materializeEntry(current));
1026
- current = current.parentId ? this.byId.get(current.parentId) : undefined;
1089
+ current = current.parentId ? entriesById.get(current.parentId) : undefined;
1027
1090
  }
1028
1091
  if (fromId === undefined) {
1029
1092
  this.branchCache = { leafId: this.leafId, mutation: this.mutationCount, entries: path };
@@ -1035,14 +1098,14 @@ export class SessionManager {
1035
1098
  * Uses tree traversal from current leaf.
1036
1099
  */
1037
1100
  buildContextEntries() {
1038
- return buildContextEntries(this.getEntries(), this.leafId);
1101
+ return buildContextEntries(this._getCompactEntries(), this.leafId);
1039
1102
  }
1040
1103
  /**
1041
1104
  * Build the session context (what gets sent to the LLM).
1042
1105
  * Uses tree traversal from current leaf.
1043
1106
  */
1044
1107
  buildSessionContext() {
1045
- return buildSessionContext(this.getEntries(), this.leafId);
1108
+ return buildSessionContext(this._getCompactEntries(), this.leafId);
1046
1109
  }
1047
1110
  hasContextMessages() {
1048
1111
  return this.hasBranchEntry((entry) => entry.type === "message" ||
@@ -1088,6 +1151,11 @@ export class SessionManager {
1088
1151
  * you need to filter/reorder.
1089
1152
  */
1090
1153
  getEntries() {
1154
+ if (this.mirrorTrimmed && this.sessionFile) {
1155
+ return this._loadFullHistoryEntries()
1156
+ .filter((e) => e.type !== "session")
1157
+ .map((entry) => this.residentStore.materialize(entry));
1158
+ }
1091
1159
  if (this.entriesCache !== null && this.entriesCache.mutation === this.mutationCount) {
1092
1160
  return this.entriesCache.entries;
1093
1161
  }
@@ -1097,6 +1165,45 @@ export class SessionManager {
1097
1165
  this.entriesCache = { mutation: this.mutationCount, entries };
1098
1166
  return entries;
1099
1167
  }
1168
+ _getCompactEntries() {
1169
+ if (this.compactEntriesCache?.mutation !== this.mutationCount) {
1170
+ this.compactEntriesCache = {
1171
+ mutation: this.mutationCount,
1172
+ entries: this.fileEntries.filter((e) => e.type !== "session"),
1173
+ };
1174
+ }
1175
+ const entries = this.compactEntriesCache.entries;
1176
+ const missingEntryIds = new Set();
1177
+ for (const entry of entries) {
1178
+ this.residentStore.materialize(entry, () => {
1179
+ missingEntryIds.add(entry.id);
1180
+ return undefined;
1181
+ });
1182
+ }
1183
+ if (missingEntryIds.size > 0 && this.sessionFile) {
1184
+ const persistedById = new Map(this._loadFullHistoryEntries().map((entry) => [entry.id, entry]));
1185
+ for (let index = 0; index < entries.length; index++) {
1186
+ const entry = entries[index];
1187
+ if (!missingEntryIds.has(entry.id))
1188
+ continue;
1189
+ const persisted = persistedById.get(entry.id);
1190
+ if (persisted)
1191
+ entries[index] = this.residentStore.externalize(persisted);
1192
+ }
1193
+ }
1194
+ const materialized = entries.map((entry) => this.residentStore.materialize(entry));
1195
+ for (const entry of materialized) {
1196
+ if (entry.type !== "message")
1197
+ continue;
1198
+ const order = this.entryOrdersById.get(entry.id);
1199
+ if (order !== undefined)
1200
+ this.messageEntryPositions.set(entry.message, { entryId: entry.id, order });
1201
+ }
1202
+ return materialized;
1203
+ }
1204
+ _loadFullHistoryEntries() {
1205
+ return this.sessionFile ? sessionEntryLoader(this.sessionFile) : this.fileEntries;
1206
+ }
1100
1207
  /**
1101
1208
  * Get the session as a tree structure. Returns a shallow defensive copy of all entries.
1102
1209
  * A well-formed session has exactly one root (first entry with parentId === null).
@@ -1149,6 +1256,9 @@ export class SessionManager {
1149
1256
  * are not modified or deleted.
1150
1257
  */
1151
1258
  branch(branchFromId) {
1259
+ if (!this.byId.has(branchFromId) && this.sessionFile) {
1260
+ this.reloadFromDisk();
1261
+ }
1152
1262
  if (!this.byId.has(branchFromId)) {
1153
1263
  throw new Error(`Entry ${branchFromId} not found`);
1154
1264
  }
@@ -1250,6 +1360,7 @@ export class SessionManager {
1250
1360
  parentId = labelEntry.id;
1251
1361
  }
1252
1362
  this.residentStore.clear();
1363
+ this.mirrorTrimmed = false;
1253
1364
  this.fileEntries = [header, ...pathWithoutLabels, ...labelEntries].map((entry) => this.residentStore.externalize(entry));
1254
1365
  this.sessionId = newSessionId;
1255
1366
  this.sessionFile = newSessionFile;