antechamber 1.0.16 → 1.0.18
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 +15 -0
- package/dist/pi-rpc.d.ts +2 -0
- package/dist/pi-rpc.js +2 -0
- package/dist/session-tree.d.ts +6 -0
- package/dist/session-tree.js +18 -0
- package/dist/sessions.js +3 -3
- package/dist/work-status.d.ts +8 -1
- package/dist/work-status.js +18 -2
- package/extensions/omo-compat/package.json +1 -1
- package/extensions/omo-dag/package.json +1 -1
- package/extensions/omo-work/package.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,21 @@ and this project uses [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.0.18] - 2026-10-25
|
|
11
|
+
|
|
12
|
+
- fix(session): accept late OmO extension entries after a fork refresh (#68)
|
|
13
|
+
|
|
14
|
+
## [1.0.17] - 2026-10-24
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Keep a session's agent out of idle eviction while a background terminal session (`bash` run in the background)
|
|
19
|
+
is still running. The reaper killed it with the agent 15 minutes after the turn ended, so a CI poller or long
|
|
20
|
+
build died silently and the session never woke up with its result.
|
|
21
|
+
- Fork (and `/btw`) on large sessions no longer fails with "Native tree refresh did not restore the saved
|
|
22
|
+
navigation". OmO's session-start hooks append extension entries (rules scan, session bindings) on top of the
|
|
23
|
+
restored branch right after the adapter reloads the session, and the check treated those as a lost navigation.
|
|
24
|
+
|
|
10
25
|
## [1.0.16] - 2026-10-23
|
|
11
26
|
|
|
12
27
|
### Fixed
|
package/dist/pi-rpc.d.ts
CHANGED
|
@@ -101,6 +101,8 @@ export declare class PiRpcClient extends EventEmitter {
|
|
|
101
101
|
private agentActive;
|
|
102
102
|
private compacting;
|
|
103
103
|
private sessionPath;
|
|
104
|
+
/** Wall-clock spawn time; work OmO records before it belongs to an earlier agent process. */
|
|
105
|
+
readonly startedAtMs: number;
|
|
104
106
|
get pid(): number | undefined;
|
|
105
107
|
get isBusy(): boolean;
|
|
106
108
|
get sessionFile(): string | undefined;
|
package/dist/pi-rpc.js
CHANGED
|
@@ -114,6 +114,8 @@ export class PiRpcClient extends EventEmitter {
|
|
|
114
114
|
agentActive = false;
|
|
115
115
|
compacting = false;
|
|
116
116
|
sessionPath;
|
|
117
|
+
/** Wall-clock spawn time; work OmO records before it belongs to an earlier agent process. */
|
|
118
|
+
startedAtMs = Date.now();
|
|
117
119
|
get pid() {
|
|
118
120
|
return this.proc.pid;
|
|
119
121
|
}
|
package/dist/session-tree.d.ts
CHANGED
|
@@ -56,6 +56,12 @@ export declare class SessionTreeError extends Error {
|
|
|
56
56
|
}
|
|
57
57
|
export declare function durableShellTree(tree: SessionTreeState): SessionTreeState;
|
|
58
58
|
export declare function getEntries(pi: PiRpcClient, signal?: AbortSignal): Promise<Entries>;
|
|
59
|
+
/**
|
|
60
|
+
* Whether the native leaf is the navigated leaf. OmO session_start hooks (pi-rules.scan,
|
|
61
|
+
* session bindings) can append extension `custom` entries on top of it after a switch;
|
|
62
|
+
* those carry no conversation, so they do not undo the navigation.
|
|
63
|
+
*/
|
|
64
|
+
export declare function restoredLeaf(tree: Entries, leaf: string | null): boolean;
|
|
59
65
|
export declare function readSessionTree(piPath: string): Entries;
|
|
60
66
|
/** Checkpoint persisted progress after agent_end, successful compaction, or process exit. */
|
|
61
67
|
export declare function recordTurn(s: ManagedSession): void;
|
package/dist/session-tree.js
CHANGED
|
@@ -34,6 +34,24 @@ export async function getEntries(pi, signal) {
|
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Whether the native leaf is the navigated leaf. OmO session_start hooks (pi-rules.scan,
|
|
39
|
+
* session bindings) can append extension `custom` entries on top of it after a switch;
|
|
40
|
+
* those carry no conversation, so they do not undo the navigation.
|
|
41
|
+
*/
|
|
42
|
+
export function restoredLeaf(tree, leaf) {
|
|
43
|
+
let id = tree.leafId;
|
|
44
|
+
// Bounded so a corrupt parent loop cannot hang the operation.
|
|
45
|
+
for (let steps = 0; id !== leaf; steps++) {
|
|
46
|
+
if (steps >= tree.entries.length)
|
|
47
|
+
return false;
|
|
48
|
+
const entry = tree.entries.find((candidate) => candidate.id === id);
|
|
49
|
+
if (entry?.type !== "custom")
|
|
50
|
+
return false;
|
|
51
|
+
id = entry.parentId;
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
37
55
|
export function readSessionTree(piPath) {
|
|
38
56
|
const lines = readFileSync(piPath, "utf8").trimEnd().split("\n");
|
|
39
57
|
const entries = [];
|
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, branchEntries, durableShellTree, followExternalAppends, forkConversation, getEntries, navigate, recordTurn, readSessionTree, revertConversation, SessionTreeError, unrevertConversation, } from "./session-tree.js";
|
|
17
|
+
import { bindMessageEntries, branchEntries, durableShellTree, followExternalAppends, forkConversation, getEntries, navigate, recordTurn, readSessionTree, restoredLeaf, 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 { WorkStatusBridge } from "./work-status.js";
|
|
@@ -532,7 +532,7 @@ export class SessionManager {
|
|
|
532
532
|
try {
|
|
533
533
|
const leaf = saved === undefined ? undefined : await navigate(pi, saved);
|
|
534
534
|
tree = await getEntries(pi);
|
|
535
|
-
if (leaf !== undefined && tree
|
|
535
|
+
if (leaf !== undefined && !restoredLeaf(tree, leaf))
|
|
536
536
|
throw new SessionTreeError("Native tree refresh did not restore the saved navigation");
|
|
537
537
|
if (leaf !== undefined)
|
|
538
538
|
s.tree.leafId = leaf;
|
|
@@ -1239,7 +1239,7 @@ export class SessionManager {
|
|
|
1239
1239
|
(s.tree.revert || resumedLeaf !== saved || !branchEntries(tree).some((entry) => entry.id === saved))) {
|
|
1240
1240
|
const leaf = await navigate(pi, saved);
|
|
1241
1241
|
tree = await getEntries(pi);
|
|
1242
|
-
if (tree
|
|
1242
|
+
if (!restoredLeaf(tree, leaf))
|
|
1243
1243
|
throw new SessionTreeError("Revival did not restore the saved navigation");
|
|
1244
1244
|
s.tree.leafId = leaf;
|
|
1245
1245
|
}
|
package/dist/work-status.d.ts
CHANGED
|
@@ -70,7 +70,14 @@ export declare class WorkStatusBridge {
|
|
|
70
70
|
private readonly work;
|
|
71
71
|
constructor(monitors: MonitorSessions);
|
|
72
72
|
private state;
|
|
73
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* Evicting the agent process kills its detached eval cells and background terminal sessions (a
|
|
75
|
+
* `bash` run_in_background shell is owned by the agent, whose PTY closes when it exits, so its exit
|
|
76
|
+
* never wakes the session). A live wake source keeps it, and so does a manifest entry whose recorded
|
|
77
|
+
* process is alive and that this agent process started: a crashed or evicted agent never records
|
|
78
|
+
* its shells' exits, and such a leftover pid may since belong to an unrelated process. OmO itself
|
|
79
|
+
* counts an entry without `runtime` as not alive (terminal restore, `defaultBackgroundAlive`).
|
|
80
|
+
*/
|
|
74
81
|
wire(s: ManagedSession): void;
|
|
75
82
|
observe(s: ManagedSession, ev: Record<string, unknown>): void;
|
|
76
83
|
/** The agent process exited: its in-process wake sources and timers died with it. */
|
package/dist/work-status.js
CHANGED
|
@@ -138,9 +138,25 @@ export class WorkStatusBridge {
|
|
|
138
138
|
}
|
|
139
139
|
return work;
|
|
140
140
|
}
|
|
141
|
-
/**
|
|
141
|
+
/**
|
|
142
|
+
* Evicting the agent process kills its detached eval cells and background terminal sessions (a
|
|
143
|
+
* `bash` run_in_background shell is owned by the agent, whose PTY closes when it exits, so its exit
|
|
144
|
+
* never wakes the session). A live wake source keeps it, and so does a manifest entry whose recorded
|
|
145
|
+
* process is alive and that this agent process started: a crashed or evicted agent never records
|
|
146
|
+
* its shells' exits, and such a leftover pid may since belong to an unrelated process. OmO itself
|
|
147
|
+
* counts an entry without `runtime` as not alive (terminal restore, `defaultBackgroundAlive`).
|
|
148
|
+
*/
|
|
142
149
|
wire(s) {
|
|
143
|
-
s.hasWakeSources = () =>
|
|
150
|
+
s.hasWakeSources = () => {
|
|
151
|
+
if ((this.work.get(s.info.id)?.wakeSources.size ?? 0) > 0)
|
|
152
|
+
return true;
|
|
153
|
+
const sessionFile = s.piPath;
|
|
154
|
+
const piSessionId = s.piSessionId;
|
|
155
|
+
const spawnedAt = s.pi?.startedAtMs;
|
|
156
|
+
if (sessionFile === undefined || piSessionId === undefined || spawnedAt === undefined)
|
|
157
|
+
return false;
|
|
158
|
+
return readBackgroundSessions(sessionFile, piSessionId).some((shell) => shell.pid !== undefined && shell.startedAtMs >= spawnedAt);
|
|
159
|
+
};
|
|
144
160
|
}
|
|
145
161
|
observe(s, ev) {
|
|
146
162
|
if (ev.name === WAKE_SOURCE_STATE_EVENT) {
|