@bivy/bivy 0.16.25-staging.22 → 0.16.25-staging.23

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.
@@ -711,14 +711,41 @@ class ProtocolSession {
711
711
  return;
712
712
  }
713
713
  if (type === "session.error") {
714
+ const errorText = String(msg.error || "Protocol agent error");
715
+ // Preserve whatever the failed turn already streamed — a partial assistant
716
+ // reply and its tool calls/results — persisted exactly as session.done
717
+ // persists a clean turn. The old handler wiped turnContent here, so a mid-
718
+ // turn failure dropped all of that work from the reopened transcript.
719
+ const hadTools = this.turnContent.length > 0 || this.turnToolResults.length > 0;
720
+ if (hadTools) {
721
+ this.flushPendingTurnText();
722
+ if (this.turnContent.length)
723
+ this.messages.push({ role: "assistant", content: this.turnContent, timestamp: Date.now() });
724
+ if (this.turnToolResults.length)
725
+ this.messages.push({ role: "user", content: this.turnToolResults, timestamp: Date.now() });
726
+ }
727
+ else if (this.assistantText) {
728
+ this.messages.push({ role: "assistant", content: this.assistantText, timestamp: Date.now() });
729
+ }
730
+ // Append a terminal error marker in the shape store-render + terminalTurnError
731
+ // recognize (stopReason "error" + errorMessage), so the failure itself
732
+ // survives a reload as an inline error instead of the turn reopening blank
733
+ // ("looks done, no reply"). Matches the live session.error emitted just below.
734
+ const errored = { role: "assistant", content: "", stopReason: "error", errorMessage: errorText, timestamp: Date.now() };
735
+ this.messages.push(errored);
714
736
  this.streaming = false;
737
+ this.assistantText = "";
738
+ this.assistantItemBoundary = false;
715
739
  this.reasoningText = "";
716
740
  this.turnContent = [];
717
741
  this.turnTextFlushed = "";
718
742
  this.turnToolResults = [];
719
743
  this.toolDetailsByCallId.clear();
720
744
  this.openToolIds = [];
721
- this.emit({ type: "session.error", error: String(msg.error || "Protocol agent error") });
745
+ // message_end drives the daemon's base-transcript snapshot (agent_end does
746
+ // not), so the preserved content + error marker are durably persisted.
747
+ this.emit({ type: "message_end", message: errored });
748
+ this.emit({ type: "session.error", error: errorText });
722
749
  this.emit({ type: "agent_end" });
723
750
  return;
724
751
  }
@@ -872,7 +899,10 @@ class ProtocolSession {
872
899
  const preflightError = await this.preparePreflight();
873
900
  if (preflightError) {
874
901
  this.streaming = false;
875
- const message = { role: "assistant", content: "", errorMessage: preflightError };
902
+ // stopReason "error" is what store-render keys on to re-render this as an
903
+ // inline error on reload (without it the turn reopened blank); it also
904
+ // matches the terminal-error message shape every other failure path uses.
905
+ const message = { role: "assistant", content: "", stopReason: "error", errorMessage: preflightError };
876
906
  this.messages.push(message);
877
907
  this.emit({ type: "message_start", message: { role: "assistant", content: "" } });
878
908
  this.emit({ type: "session.error", error: preflightError });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.16.25-staging.22",
3
+ "version": "0.16.25-staging.23",
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.",