antechamber 1.0.38 → 1.0.40

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,12 +7,27 @@ and this project uses [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.40] - 2026-11-06
11
+
12
+ ### Fixed
13
+
14
+ - Keep the conversation in order after a `!` shell command. The history refresh that follows a shell command sent
15
+ every earlier reply to OpenChamber again with the current time as its creation time, so OpenChamber moved those
16
+ replies after the prompts they answered and placed the shell card among them. Replies now keep their own times.
17
+
18
+ ## [1.0.39] - 2026-11-04
19
+
20
+ - fix(v2): give each task batch card its own tool id (#90)
21
+
10
22
  ## [1.0.38] - 2026-11-03
11
23
 
12
24
  ### Fixed
13
25
 
14
26
  - Reverting a `/compact` message works again. The revert was rejected as an unknown message and OpenChamber 2.x
15
27
  dropped the error silently. It now returns the conversation to where it was before the compaction.
28
+ - Batched `task` calls (`tasks: [...]`) no longer show as interrupted in OpenChamber 2.x. Every card went out under
29
+ the same tool id, so OpenChamber merged them into one, showed the wrong titles, and marked the leftovers
30
+ "Interrupted" when the message completed. Each card now has its own id.
16
31
 
17
32
  ## [1.0.37] - 2026-11-03
18
33
 
package/dist/v2.js CHANGED
@@ -203,17 +203,28 @@ function backgroundShell(part) {
203
203
  return undefined;
204
204
  return { output: typeof output === "string" ? output : "", metadata: { ...metadata, status: "running", shellID } };
205
205
  }
206
+ /**
207
+ * OpenChamber 2.x keys a tool part by this id alone, but one `task` call with `tasks` expands into a card per item
208
+ * (`taskParts`), all sharing the call id. Items after the first get their own id, or the cards merge into one and
209
+ * the leftovers are marked "Interrupted" when the message completes.
210
+ */
211
+ function v2ToolId(part) {
212
+ const prefix = `prt_task_${part.callID}_`;
213
+ const index = part.id.startsWith(prefix) ? part.id.slice(prefix.length) : "0";
214
+ return index === "0" ? part.callID : `${part.callID}#${index}`;
215
+ }
206
216
  function toolContent(part) {
207
217
  const st = part.state;
208
218
  const name = v2ToolName(part.tool);
209
219
  const start = st.status === "pending" ? undefined : st.time.start;
210
220
  const end = st.status === "pending" || st.status === "running" ? undefined : st.time.end;
221
+ const id = v2ToolId(part);
211
222
  const base = {
212
223
  type: "tool",
213
- id: part.callID,
224
+ id,
214
225
  name,
215
226
  // keep the SDK v1 spellings too — harmless and tolerates older readers
216
- callID: part.callID,
227
+ callID: id,
217
228
  tool: name,
218
229
  executed: false,
219
230
  time: {
@@ -478,12 +489,10 @@ export class V2EventTranslator {
478
489
  step.error = info.error ?? { name: "UnknownError", data: { message: "Provider error" } };
479
490
  }
480
491
  st.step = step;
481
- frames.push(this.frame(directory, "session.step.started", {
482
- sessionID: info.sessionID,
483
- assistantMessageID: info.id,
484
- agent: step.agent,
485
- model: step.model,
486
- }));
492
+ // OpenChamber 2.x takes the message's creation time from this frame (events.ts `session.step.started`) and
493
+ // reorders by it. A history refresh re-announces every reply, so `Date.now()` would move them all after the
494
+ // prompts they answer.
495
+ frames.push(this.frame(directory, "session.step.started", { sessionID: info.sessionID, assistantMessageID: info.id, agent: step.agent, model: step.model }, info.time.created));
487
496
  }
488
497
  else if (st.step) {
489
498
  st.step.cost = info.cost;
@@ -501,11 +510,11 @@ export class V2EventTranslator {
501
510
  if (st.step && !st.step.ended && info.time.completed !== undefined) {
502
511
  if (info.finish !== undefined)
503
512
  st.step.finish = info.finish;
504
- frames.push(...this.finalizeStep(directory, st.step));
513
+ frames.push(...this.finalizeStep(directory, st.step, info.time.completed));
505
514
  }
506
515
  return frames;
507
516
  }
508
- finalizeStep(directory, st) {
517
+ finalizeStep(directory, st, completed) {
509
518
  if (st.ended)
510
519
  return [];
511
520
  st.ended = true;
@@ -518,14 +527,14 @@ export class V2EventTranslator {
518
527
  error: st.error ?? { name: "UnknownError", data: { message: "Provider error" } },
519
528
  cost: st.cost,
520
529
  tokens: st.tokens,
521
- })
530
+ }, completed)
522
531
  : this.frame(directory, "session.step.ended", {
523
532
  sessionID: st.sessionID,
524
533
  assistantMessageID: st.messageID,
525
534
  ...(st.finish !== undefined ? { finish: st.finish } : {}),
526
535
  cost: st.cost,
527
536
  tokens: st.tokens,
528
- }),
537
+ }, completed),
529
538
  ];
530
539
  }
531
540
  onPartUpdated(directory, part, delta) {
@@ -610,7 +619,7 @@ export class V2EventTranslator {
610
619
  }
611
620
  ts.callID = part.callID;
612
621
  const frames = [];
613
- const base = { sessionID: part.sessionID, assistantMessageID: part.messageID, id: part.callID };
622
+ const base = { sessionID: part.sessionID, assistantMessageID: part.messageID, id: v2ToolId(part) };
614
623
  const state = part.state;
615
624
  if (state.status === "pending") {
616
625
  if (!ts.started) {
@@ -693,14 +702,14 @@ export class V2EventTranslator {
693
702
  }
694
703
  return st;
695
704
  }
696
- frame(directory, type, data) {
705
+ frame(directory, type, data, created = Date.now()) {
697
706
  const aggregateID = typeof data.sessionID === "string" ? data.sessionID : undefined;
698
707
  const seq = aggregateID === undefined ? undefined : (this.sequences.get(aggregateID) ?? 0) + 1;
699
708
  if (aggregateID !== undefined && seq !== undefined)
700
709
  this.sequences.set(aggregateID, seq);
701
710
  return {
702
711
  id: genId("evt"),
703
- created: Date.now(),
712
+ created,
704
713
  type,
705
714
  location: { directory },
706
715
  data,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-compat",
3
- "version": "1.0.38",
3
+ "version": "1.0.40",
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.38",
3
+ "version": "1.0.40",
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.38",
3
+ "version": "1.0.40",
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.38",
3
+ "version": "1.0.40",
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",