@bivy/bivy 0.10.1-staging.280 → 0.10.1-staging.282

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.
@@ -178,6 +178,11 @@ function handleCompletedItem(params) {
178
178
  agentMessageItems.add(itemId);
179
179
  bivy({ type: "message.delta", text: String(item.text) });
180
180
  }
181
+ // An agentMessage is a real prose item, not merely another token in one
182
+ // turn-wide answer. Tell the protocol host it ended so commentary and tool
183
+ // activity render in source order (message → tools → message → tools)
184
+ // instead of one concatenated bubble followed by a single tool block.
185
+ bivy({ type: "message.boundary", itemId });
181
186
  return;
182
187
  case "plan":
183
188
  if (!reasoningItems.has(itemId) && item.text) emitReasoning(itemId, item.text);
@@ -168,6 +168,11 @@ class ProtocolSession {
168
168
  resumeRef;
169
169
  started = false;
170
170
  assistantText = "";
171
+ /** A protocol agent can produce several discrete assistant messages in one
172
+ * turn (Codex commentary items are the common case). After a
173
+ * `message.boundary`, separate the next item's text in the cumulative stream
174
+ * instead of welding `"first." + "Second"` into `"first.Second"`. */
175
+ assistantItemBoundary = false;
171
176
  reasoningText = "";
172
177
  stderrOutput = "";
173
178
  lastUsage;
@@ -512,6 +517,16 @@ class ProtocolSession {
512
517
  if (this.streaming) {
513
518
  if (!this.assistantText)
514
519
  this.emit({ type: "message_start", message: { role: "assistant", content: "" } });
520
+ if (this.assistantItemBoundary && this.assistantText) {
521
+ // If a tool already flushed the preceding item, advance the persisted
522
+ // prefix over this display-only separator too; the next turnContent
523
+ // block should contain `Second message`, not `\n\nSecond message`.
524
+ const wasFullyFlushed = this.turnTextFlushed === this.assistantText;
525
+ this.assistantText += "\n\n";
526
+ if (wasFullyFlushed)
527
+ this.turnTextFlushed = this.assistantText;
528
+ }
529
+ this.assistantItemBoundary = false;
515
530
  this.assistantText += text;
516
531
  this.emit({ type: "message_update", message: { role: "assistant", content: this.assistantText } });
517
532
  return;
@@ -525,6 +540,26 @@ class ProtocolSession {
525
540
  this.foldLateAssistantDelta(text);
526
541
  return;
527
542
  }
543
+ if (type === "message.boundary") {
544
+ // Codex emits multiple agentMessage items during one turn: commentary,
545
+ // then tools, then more commentary. Seal the prose item now so the client
546
+ // can place the next tool card AFTER it. Waiting for session.done flattens
547
+ // every item into one growing bubble and leaves all tools in a block below.
548
+ // Keep assistantText cumulative: SessionStore uses the committed prefix to
549
+ // derive each new run, and session.done still persists the complete turn.
550
+ if (this.streaming && this.assistantText) {
551
+ // Keep the boundary durable too. The marker is display-only, but it lets
552
+ // renderHistory split adjacent prose items after reload even when no tool
553
+ // happened between them.
554
+ this.flushPendingTurnText();
555
+ if (this.turnContent[this.turnContent.length - 1]?.type !== "bivy_message_boundary") {
556
+ this.turnContent.push({ type: "bivy_message_boundary" });
557
+ }
558
+ this.emit({ type: "message_boundary", message: { role: "assistant", content: this.assistantText } });
559
+ this.assistantItemBoundary = true;
560
+ }
561
+ return;
562
+ }
528
563
  if (type === "message.reasoning" || type === "reasoning.delta") {
529
564
  // Reasoning/thinking stream → the same intermediate thinking block the
530
565
  // daemon renders for Pi/Claude (display-only, kept out of the transcript).
@@ -574,6 +609,7 @@ class ProtocolSession {
574
609
  this.emit({ type: "message_end", message });
575
610
  this.streaming = false;
576
611
  this.assistantText = "";
612
+ this.assistantItemBoundary = false;
577
613
  this.reasoningText = "";
578
614
  this.turnContent = [];
579
615
  this.turnTextFlushed = "";
@@ -787,6 +823,7 @@ class ProtocolSession {
787
823
  this.messages.push({ role: "user", content: prompt, timestamp: Date.now() });
788
824
  this.streaming = true;
789
825
  this.assistantText = "";
826
+ this.assistantItemBoundary = false;
790
827
  this.reasoningText = "";
791
828
  this.stderrOutput = "";
792
829
  this.turnContent = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.10.1-staging.280",
3
+ "version": "0.10.1-staging.282",
4
4
  "type": "module",
5
5
  "license": "AGPL-3.0-only",
6
6
  "description": "Run coding agents on machines you own. Open-source, self-hostable agent workspace.",