antechamber 0.2.11 → 0.2.12

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/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project uses [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.12] - 2026-10-16
11
+
12
+ ### Fixed
13
+
14
+ - Preserve recorded conversation progress when the agent process exits before
15
+ `agent_end`, and retain successful background compaction across revival.
16
+ Checkpoints respect reverted selections and do not switch to sibling branches.
17
+
10
18
  ## [0.2.11] - 2026-10-16
11
19
 
12
20
  ### Fixed
@@ -544,6 +544,7 @@ export class PiEventTranslator {
544
544
  },
545
545
  });
546
546
  if (ev.aborted !== true && typeof result?.summary === "string" && typeof result.firstKeptEntryId === "string") {
547
+ recordTurn(s);
547
548
  const messages = this.services.ensureMessages(s);
548
549
  let key;
549
550
  // compaction_end follows persistence, but its result omits the entry ID.
@@ -563,6 +564,7 @@ export class PiEventTranslator {
563
564
  for (const part of message.parts)
564
565
  this.emitPart(s, part);
565
566
  }
567
+ this.services.persistMeta(s);
566
568
  }
567
569
  this.services.emit(s.info.directory, { type: "session.updated", properties: { info: s.info } });
568
570
  if (s.compactingFromIdle) {
@@ -52,7 +52,7 @@ export declare class SessionTreeError extends Error {
52
52
  export declare function durableShellTree(tree: SessionTreeState): SessionTreeState;
53
53
  export declare function getEntries(pi: PiRpcClient, signal?: AbortSignal): Promise<Entries>;
54
54
  export declare function readSessionTree(piPath: string): Entries;
55
- /** agent_end runs after message persistence; no async lease or timing race. */
55
+ /** Checkpoint persisted progress after agent_end, successful compaction, or process exit. */
56
56
  export declare function recordTurn(s: ManagedSession): void;
57
57
  export declare function branchEntries(tree: Entries, leafId?: string | null): TreeEntry[];
58
58
  /** Live ids belong to the UI; restored ids belong to JSONL offsets. Save both. */
@@ -44,10 +44,19 @@ export function readSessionTree(piPath) {
44
44
  }
45
45
  return { entries, leafId: entries.at(-1)?.id ?? null };
46
46
  }
47
- /** agent_end runs after message persistence; no async lease or timing race. */
47
+ /** Checkpoint persisted progress after agent_end, successful compaction, or process exit. */
48
48
  export function recordTurn(s) {
49
- if (s.piPath)
50
- bindMessageEntries(s, readSessionTree(s.piPath));
49
+ if (!s.piPath)
50
+ return;
51
+ const tree = readSessionTree(s.piPath);
52
+ // Disk order is not navigation: only a descendant can advance a saved selection.
53
+ // An ancestor, missing selection, or newer sibling must leave its bindings intact.
54
+ if (!s.tree.revert &&
55
+ s.tree.leafId !== undefined &&
56
+ s.tree.leafId !== null &&
57
+ !branchEntries(tree).some((entry) => entry.id === s.tree.leafId))
58
+ return;
59
+ bindMessageEntries(s, tree);
51
60
  }
52
61
  export function branchEntries(tree, leafId = tree.leafId) {
53
62
  const byId = new Map(tree.entries.map((entry) => [entry.id, entry]));
package/dist/sessions.js CHANGED
@@ -14,7 +14,7 @@ import { SessionLifecycle } from "./lifecycle.js";
14
14
  import { ApprovalBridge, extensionUiRequestFrom } from "./approvals.js";
15
15
  import { getAgentName, getExposedAgentNames } from "./agent-name.js";
16
16
  import { RequestBodyError } from "./http.js";
17
- import { bindMessageEntries, durableShellTree, forkConversation, getEntries, navigate, readSessionTree, revertConversation, SessionTreeError, unrevertConversation, } from "./session-tree.js";
17
+ import { bindMessageEntries, durableShellTree, forkConversation, getEntries, navigate, recordTurn, readSessionTree, revertConversation, SessionTreeError, unrevertConversation, } from "./session-tree.js";
18
18
  import { SubagentBridge } from "./subagents.js";
19
19
  import { MonitorSessions } from "./monitor-sessions.js";
20
20
  import { sessionDiff } from "./session-diff.js";
@@ -239,6 +239,13 @@ export class SessionManager {
239
239
  name: "UnknownError",
240
240
  data: { message: `pi process exited (code=${code})` },
241
241
  });
242
+ try {
243
+ recordTurn(s);
244
+ this.persistMeta(s);
245
+ }
246
+ catch (error) {
247
+ this.reportPersistenceError(s, error);
248
+ }
242
249
  delete s.interruptRequested;
243
250
  this.subagents.stopParent(s.info.id);
244
251
  this.monitors.stopParent(s.info.id);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-graph",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "OpenChamber extension: live, interactive graph of the OmO sub-agents behind the current session",
5
5
  "private": true,
6
6
  "type": "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "OpenCode-compatible HTTP/SSE server that lets OpenChamber drive the pi coding agent (and OmO) over RPC",
5
5
  "type": "module",
6
6
  "license": "MIT",