antechamber 1.0.18 → 1.0.19

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,15 @@ and this project uses [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.19] - 2026-10-25
11
+
12
+ ### Fixed
13
+
14
+ - Keep the parent's last reply in a `/btw` side thread. OpenChamber forks `/btw` at the last completed assistant
15
+ reply, and the adapter cut strictly before it, so the fork ended mid-turn on the reply's tool calls and the side
16
+ agent never saw the answer the main thread had just given. An assistant boundary now keeps that reply and the
17
+ results of its own tool calls.
18
+
10
19
  ## [1.0.18] - 2026-10-25
11
20
 
12
21
  - fix(session): accept late OmO extension entries after a fork refresh (#68)
@@ -36,9 +36,11 @@ export interface TreeEntry {
36
36
  message?: {
37
37
  role: string;
38
38
  clientMessageId?: string;
39
+ toolCallId?: string;
39
40
  content?: string | Array<{
40
41
  type: string;
41
42
  text?: string;
43
+ id?: string;
42
44
  }>;
43
45
  command?: string;
44
46
  output?: string;
@@ -318,24 +318,56 @@ function entryForMessage(s, tree, messageID) {
318
318
  }
319
319
  return entry;
320
320
  }
321
+ /**
322
+ * The last entry of an assistant reply: the reply, or the latest result of its own tool calls.
323
+ * OpenChamber 2.x /btw names a final reply (no tool calls); 1.24's /btw can name any completed
324
+ * step, whose tool results belong to the same OpenChamber message.
325
+ */
326
+ function replyEnd(tree, reply, leafId) {
327
+ const content = reply.message?.content;
328
+ const calls = new Set(Array.isArray(content) ? content.flatMap((part) => (part.type === "toolCall" && part.id ? [part.id] : [])) : []);
329
+ const branch = branchEntries(tree, leafId);
330
+ const start = branch.indexOf(reply);
331
+ if (calls.size === 0 || start < 0)
332
+ return reply.id;
333
+ let end = reply.id;
334
+ for (const entry of branch.slice(start + 1)) {
335
+ const role = entry.message?.role;
336
+ if (role === "toolResult" && entry.message?.toolCallId !== undefined && calls.has(entry.message.toolCallId))
337
+ end = entry.id;
338
+ else if (role === "assistant" || role === "user")
339
+ break;
340
+ }
341
+ return end;
342
+ }
321
343
  export async function forkConversation(s, pi, tree, messageID) {
322
344
  const entry = messageID === undefined ? branchEntries(tree).at(-1) : entryForMessage(s, tree, messageID);
323
345
  if (!entry)
324
346
  throw new SessionTreeError("Cannot fork an empty conversation");
325
347
  const shellUser = entry.message?.role === "bashExecution" &&
326
348
  s.messages?.find((message) => message.info.id === messageID)?.info.role === "user";
327
- // OpenCode forks strictly before any selected message. OmO's default "before"
328
- // position only accepts user entries, so other boundaries (an assistant reply,
329
- // as /btw sends) fork "at" the entry preceding them.
330
- const beforeOther = messageID !== undefined && entry.message?.role !== "user" && entry.message?.role !== "bashExecution";
331
- const forkEntryId = shellUser || beforeOther ? entry.parentId : entry.id;
349
+ // OpenCode forks strictly before any selected message, but OpenChamber only names an
350
+ // assistant reply as the boundary from /btw, which forks at the last completed reply
351
+ // so the side thread starts from a settled conversation: keep that reply. OmO's
352
+ // default "before" position only accepts user entries, so other non-user boundaries
353
+ // fork "at" the entry preceding them.
354
+ const reply = messageID !== undefined && entry.message?.role === "assistant";
355
+ const beforeOther = messageID !== undefined && !reply && entry.message?.role !== "user" && entry.message?.role !== "bashExecution";
356
+ const forkEntryId = reply
357
+ ? // A staged revert hides the reply's results from the live leaf.
358
+ replyEnd(tree, entry, s.tree.revert?.previousLeafId ?? tree.leafId)
359
+ : shellUser || beforeOther
360
+ ? entry.parentId
361
+ : entry.id;
332
362
  if (forkEntryId === null) {
333
363
  throw new SessionTreeError(shellUser ? "Cannot fork before a root shell entry" : "Cannot fork before the first entry");
334
364
  }
335
365
  const response = await pi.command({
336
366
  type: "fork",
337
367
  entryId: forkEntryId,
338
- ...(messageID === undefined || beforeOther || entry.message?.role === "bashExecution" ? { position: "at" } : {}),
368
+ ...(messageID === undefined || reply || beforeOther || entry.message?.role === "bashExecution"
369
+ ? { position: "at" }
370
+ : {}),
339
371
  });
340
372
  if (!response.success)
341
373
  throw new SessionTreeError(response.error ?? "OmO fork failed");
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-compat",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "description": "OpenChamber extension: displays OmO tool calls the way OmO means them when OpenChamber runs on antechamber",
5
5
  "private": true,
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-graph",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
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",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-work",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "description": "OpenChamber 2.x Work Status section: OmO todo phases, monitors, eval cells and background work of 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": "1.0.18",
3
+ "version": "1.0.19",
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",