@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);
|
package/dist/runtime/protocol.js
CHANGED
|
@@ -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