@bivy/bivy 0.16.24-staging.1 → 0.16.24-staging.2

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/bin/acp-shim.mjs CHANGED
@@ -346,7 +346,14 @@ function onSessionUpdate(params) {
346
346
  type: "tool.result",
347
347
  toolCallId,
348
348
  name: toolCallName(state),
349
- result: textOf(u.content) || status,
349
+ // Use the ACCUMULATED content (mergeToolCallState keeps the fullest
350
+ // seen across the call's lifecycle), not just this terminal frame's.
351
+ // Agents like opencode stream a command's stdout in an earlier
352
+ // (in_progress) tool_call_update and leave `content` empty on the
353
+ // closing frame — reading only `u.content` there collapsed the result
354
+ // to the bare status ("completed"), dropping the real output. Prefer
355
+ // the terminal frame's content when it has some, else the accumulated.
356
+ result: textOf(u.content) || textOf(state.content) || status,
350
357
  isError: status === "failed",
351
358
  });
352
359
  } else {
@@ -72,6 +72,7 @@ export function extractTokenUsage(raw) {
72
72
  * persisted transcript shape matches the live-streaming shape (see protocol.ts). */
73
73
  class TurnAccumulator {
74
74
  toolContext;
75
+ inferSegmentBoundaries;
75
76
  text = "";
76
77
  started = false;
77
78
  ended = false;
@@ -88,6 +89,16 @@ class TurnAccumulator {
88
89
  // already sealed into `content` as its own block.
89
90
  content = [];
90
91
  textFlushed = "";
92
+ // A tool call interrupts the assistant's prose/reasoning: the text that
93
+ // resumes after it is a NEW message segment, not a continuation of the last
94
+ // token. Without a separator the two run together ("…what it does.The next…",
95
+ // "…shell commandI have…") — exactly the seam the governed ProtocolRuntime
96
+ // guards with its `assistantItemBoundary` \n\n insertion. Mirror that here so
97
+ // every CliParser agent (Grok, Goose, Gemini, the generic streams) gets the
98
+ // same clean paragraph break instead of a concatenated blob. Tracked per
99
+ // stream because text and reasoning accumulate into separate buffers.
100
+ pendingTextBoundary = false;
101
+ pendingReasoningBoundary = false;
91
102
  out = [];
92
103
  details = new Map();
93
104
  // Not every CLI includes a stable id on both halves of a tool exchange.
@@ -102,8 +113,15 @@ class TurnAccumulator {
102
113
  if (pending)
103
114
  this.content.push({ type: "text", text: pending });
104
115
  }
105
- constructor(toolContext) {
116
+ constructor(toolContext,
117
+ // Native CLI streams (Grok, Goose, Claude/Codex JSON, …) start a fresh
118
+ // prose/reasoning segment after each tool call without re-emitting a
119
+ // separator, so we infer the paragraph break. The bivy-agent-protocol path
120
+ // instead carries continuation faithfully (a shim can emit an explicit
121
+ // boundary when it wants one), so it opts out.
122
+ inferSegmentBoundaries = true) {
106
123
  this.toolContext = toolContext;
124
+ this.inferSegmentBoundaries = inferSegmentBoundaries;
107
125
  }
108
126
  ensureStart(events) {
109
127
  if (!this.started) {
@@ -121,6 +139,9 @@ class TurnAccumulator {
121
139
  appendReasoning(text, events) {
122
140
  if (!text)
123
141
  return;
142
+ if (this.pendingReasoningBoundary && this.reasoning)
143
+ this.reasoning += "\n\n";
144
+ this.pendingReasoningBoundary = false;
124
145
  this.reasoning += text;
125
146
  events.push({ type: "message_update", message: { role: "assistant", content: [{ type: "thinking", thinking: this.reasoning }] } });
126
147
  }
@@ -133,6 +154,18 @@ class TurnAccumulator {
133
154
  if (!text)
134
155
  return;
135
156
  this.ensureStart(events);
157
+ if (this.pendingTextBoundary && this.text) {
158
+ // Advance the sealed prefix over the display-only separator when the prior
159
+ // segment was already flushed to a content block, so the next persisted
160
+ // block holds `Second message`, not `\n\nSecond message` (matching
161
+ // ProtocolRuntime). The cumulative `text` still carries the break for the
162
+ // live stream and the final answer.
163
+ const wasFullyFlushed = this.textFlushed === this.text;
164
+ this.text += "\n\n";
165
+ if (wasFullyFlushed)
166
+ this.textFlushed = this.text;
167
+ }
168
+ this.pendingTextBoundary = false;
136
169
  this.text += text;
137
170
  events.push({ type: "message_update", message: { role: "assistant", content: this.text } });
138
171
  }
@@ -147,6 +180,12 @@ class TurnAccumulator {
147
180
  if (detail)
148
181
  this.details.set(callId, detail);
149
182
  this.flushPendingText();
183
+ // Prose/reasoning that resumes after this call is a fresh segment — arm the
184
+ // boundary so the next appendText/appendReasoning inserts a separator.
185
+ if (this.inferSegmentBoundaries) {
186
+ this.pendingTextBoundary = true;
187
+ this.pendingReasoningBoundary = true;
188
+ }
150
189
  this.content.push({ type: "tool_use", id: callId, name, input: input ?? {}, ...(detail ? { detail } : {}) });
151
190
  events.push({ type: "tool_call", toolName: name, input, toolCallId: callId, ...(detail ? { detail } : {}) });
152
191
  }
@@ -198,7 +237,10 @@ class TurnAccumulator {
198
237
  }
199
238
  /** Parser for the bivy-agent-protocol JSONL event vocabulary (the universal path). */
200
239
  export function bivyProtocolParser() {
201
- const acc = new TurnAccumulator({ provider: "bivy-protocol", protocol: "protocol" });
240
+ // The universal protocol carries continuation faithfully: text after a tool is
241
+ // appended verbatim (a shim emits an explicit break when it wants one), so it
242
+ // opts out of inferred segment boundaries.
243
+ const acc = new TurnAccumulator({ provider: "bivy-protocol", protocol: "protocol" }, false);
202
244
  return {
203
245
  onLine(line) {
204
246
  const events = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.16.24-staging.1",
3
+ "version": "0.16.24-staging.2",
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.",