@bivy/bivy 0.16.1-staging.5 → 0.16.1-staging.7

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.
@@ -4,7 +4,7 @@ import { defineAgentIntegration } from "../definition.js";
4
4
  import { withExactCapabilitySurface } from "../../runtime/types.js";
5
5
  import { createCredentialStore } from "../../runtime/credentials.js";
6
6
  import { ClaudeCodeRuntime, claudeRuntimeFromEnv, claudeSdkInstalled, } from "./runtime.js";
7
- export const CLAUDE_TESTED_VERSION = "0.3.251";
7
+ export const CLAUDE_TESTED_VERSION = "0.3.252";
8
8
  const CLAUDE_CAPABILITIES = withExactCapabilitySurface({
9
9
  toolInterception: true,
10
10
  modelSelection: true,
@@ -3,7 +3,7 @@
3
3
  export const CERTIFICATION_MATRIX = {
4
4
  schemaVersion: 1,
5
5
  agents: [
6
- { id: "claude-code-sdk", status: "active", executionMode: "protocol", pinnedVersion: "0.3.251", capabilities: ["toolInterception", "modelSelection", "resume"] },
6
+ { id: "claude-code-sdk", status: "active", executionMode: "protocol", pinnedVersion: "0.3.252", capabilities: ["toolInterception", "modelSelection", "resume"] },
7
7
  { id: "codex-approvals", status: "active", executionMode: "protocol", pinnedVersion: "0.151.0", capabilities: ["toolInterception", "modelSelection", "resume"] },
8
8
  { id: "pi", status: "active", executionMode: "protocol", pinnedVersion: "0.84.4", capabilities: ["toolInterception", "modelSelection", "resume"] },
9
9
  { id: "opencode", status: "active", executionMode: "protocol", pinnedVersion: "1.18.25", capabilities: ["toolInterception", "modelSelection", "resume"] },
@@ -90,6 +90,12 @@ class TurnAccumulator {
90
90
  textFlushed = "";
91
91
  out = [];
92
92
  details = new Map();
93
+ // Not every CLI includes a stable id on both halves of a tool exchange.
94
+ // Keep a small FIFO of open calls so the universal parser can still pair an
95
+ // anonymous result with its call instead of creating a second, forever-running
96
+ // card in the transcript.
97
+ openToolIds = [];
98
+ anonymousToolId = 0;
93
99
  flushPendingText() {
94
100
  const pending = this.text.slice(this.textFlushed.length);
95
101
  this.textFlushed = this.text;
@@ -131,25 +137,35 @@ class TurnAccumulator {
131
137
  events.push({ type: "message_update", message: { role: "assistant", content: this.text } });
132
138
  }
133
139
  addToolUse(id, name, input, events) {
134
- traceToolPayload({ phase: "call", context: this.toolContext, name, callId: id, payload: input });
140
+ const callId = id || `cli-tool-${++this.anonymousToolId}`;
141
+ this.openToolIds.push(callId);
142
+ traceToolPayload({ phase: "call", context: this.toolContext, name, callId, payload: input });
135
143
  // Attach a normalized ToolCallDetail (display-only) so the PWA renders this
136
144
  // call the same way it renders every other agent's equivalent call. Absent
137
145
  // when unrecognized — the block stays opaque and renders as before.
138
146
  const detail = mapToolCall(name, input, this.toolContext);
139
- if (detail && id)
140
- this.details.set(id, detail);
147
+ if (detail)
148
+ this.details.set(callId, detail);
141
149
  this.flushPendingText();
142
- this.content.push({ type: "tool_use", id, name, input: input ?? {}, ...(detail ? { detail } : {}) });
143
- events.push({ type: "tool_call", toolName: name, input, toolCallId: id, ...(detail ? { detail } : {}) });
150
+ this.content.push({ type: "tool_use", id: callId, name, input: input ?? {}, ...(detail ? { detail } : {}) });
151
+ events.push({ type: "tool_call", toolName: name, input, toolCallId: callId, ...(detail ? { detail } : {}) });
144
152
  }
145
153
  addToolResult(toolUseId, name, content, events, isError = false) {
146
- traceToolPayload({ phase: "result", context: this.toolContext, name, callId: toolUseId, payload: content });
147
- const prior = this.details.get(toolUseId);
154
+ // Prefer the explicit id. Otherwise close the oldest open call, which is
155
+ // the only generally safe correlation available from an id-less stream.
156
+ const callId = toolUseId || this.openToolIds.shift() || `cli-tool-result-${++this.anonymousToolId}`;
157
+ if (toolUseId) {
158
+ const index = this.openToolIds.indexOf(toolUseId);
159
+ if (index >= 0)
160
+ this.openToolIds.splice(index, 1);
161
+ }
162
+ traceToolPayload({ phase: "result", context: this.toolContext, name, callId, payload: content });
163
+ const prior = this.details.get(callId);
148
164
  const detail = prior ? { ...prior, result: mapToolResult(content, isError) } : undefined;
149
165
  if (detail)
150
- this.details.set(toolUseId, detail);
151
- this.toolResults.push({ type: "tool_result", tool_use_id: toolUseId, content: content ?? "", ...(detail ? { detail } : {}) });
152
- events.push({ type: "tool_result", toolName: name, result: { toolCallId: toolUseId, content }, ...(detail ? { detail } : {}) });
166
+ this.details.set(callId, detail);
167
+ this.toolResults.push({ type: "tool_result", tool_use_id: callId, content: content ?? "", ...(detail ? { detail } : {}) });
168
+ events.push({ type: "tool_result", toolName: name, result: { toolCallId: callId, content }, ...(detail ? { detail } : {}) });
153
169
  }
154
170
  /** Finalize the turn: emit message_end/turn_end/agent_end and record history. */
155
171
  finish(events) {
@@ -193,6 +193,25 @@ class ProtocolSession {
193
193
  // toolCallId -> the node's normalized classification, so a later tool.result
194
194
  // (or tool.update) can attach/refresh `detail` on the already-pushed block.
195
195
  toolDetailsByCallId = new Map();
196
+ openToolIds = [];
197
+ anonymousToolId = 0;
198
+ /** Protocol is intentionally agent-neutral: if an upstream omits ids, give
199
+ * the exchange a local identity so live and persisted views can still pair it. */
200
+ resolveToolId(raw, result = false) {
201
+ if (raw) {
202
+ if (result) {
203
+ const index = this.openToolIds.indexOf(raw);
204
+ if (index >= 0)
205
+ this.openToolIds.splice(index, 1);
206
+ }
207
+ return raw;
208
+ }
209
+ if (result)
210
+ return this.openToolIds.shift() || `protocol-tool-result-${++this.anonymousToolId}`;
211
+ const id = `protocol-tool-${++this.anonymousToolId}`;
212
+ this.openToolIds.push(id);
213
+ return id;
214
+ }
196
215
  constructor(runtimeOptions, cwd, capabilitiesRef, toolInterceptor,
197
216
  // When resuming, the agent's own session ref (e.g. a Codex thread id). Passed
198
217
  // back to the shim via the generic session.resume primitive so it reconnects
@@ -686,6 +705,7 @@ class ProtocolSession {
686
705
  this.turnTextFlushed = "";
687
706
  this.turnToolResults = [];
688
707
  this.toolDetailsByCallId.clear();
708
+ this.openToolIds = [];
689
709
  this.emit({ type: "agent_end" });
690
710
  return;
691
711
  }
@@ -696,12 +716,13 @@ class ProtocolSession {
696
716
  this.turnTextFlushed = "";
697
717
  this.turnToolResults = [];
698
718
  this.toolDetailsByCallId.clear();
719
+ this.openToolIds = [];
699
720
  this.emit({ type: "session.error", error: String(msg.error || "Protocol agent error") });
700
721
  this.emit({ type: "agent_end" });
701
722
  return;
702
723
  }
703
724
  if (type === "tool.call" || type === "tool.observe") {
704
- const toolCallId = String(msg.toolCallId || msg.id || "");
725
+ const toolCallId = this.resolveToolId(String(msg.toolCallId || msg.id || ""));
705
726
  const toolName = String(msg.name || "tool");
706
727
  const detail = mapToolCall(toolName, msg.input, { provider: this.runtimeOptions.id || "acp", protocol: "protocol" });
707
728
  if (detail)
@@ -763,7 +784,7 @@ class ProtocolSession {
763
784
  return;
764
785
  }
765
786
  if (type === "tool.result") {
766
- const toolCallId = String(msg.toolCallId || msg.tool_use_id || msg.id || "");
787
+ const toolCallId = this.resolveToolId(String(msg.toolCallId || msg.tool_use_id || msg.id || ""), true);
767
788
  const result = msg.result ?? msg.output ?? msg.content ?? msg.text ?? msg.summary ?? "";
768
789
  const isError = Boolean(msg.isError || msg.is_error);
769
790
  this.turnToolResults.push({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.16.1-staging.5",
3
+ "version": "0.16.1-staging.7",
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.",
@@ -50,7 +50,7 @@
50
50
  "zod": "^4.0.0"
51
51
  },
52
52
  "optionalDependencies": {
53
- "@anthropic-ai/claude-agent-sdk": "0.3.251",
53
+ "@anthropic-ai/claude-agent-sdk": "0.3.252",
54
54
  "@earendil-works/pi-ai": "0.84.4",
55
55
  "@earendil-works/pi-coding-agent": "0.84.4",
56
56
  "node-pty": "^1.1.0"