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

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.
@@ -22,7 +22,7 @@
22
22
  "hidden": false,
23
23
  "supportTier": "supported",
24
24
  "certification": "release-tested",
25
- "testedVersion": "1.18.30",
25
+ "testedVersion": "1.18.31",
26
26
  "headlessFlags": [
27
27
  "run",
28
28
  "-s"
@@ -4,13 +4,21 @@ 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.270";
7
+ export const CLAUDE_TESTED_VERSION = "0.3.278";
8
8
  const CLAUDE_CAPABILITIES = withExactCapabilitySurface({
9
9
  toolInterception: true,
10
10
  modelSelection: true,
11
11
  packages: false,
12
12
  resume: true,
13
13
  fork: true,
14
+ // Must mirror ClaudeCodeRuntime.capabilities (runtime.ts): the catalog is a
15
+ // consumed source of truth (the fork-fidelity matrix and any fork-target
16
+ // fidelity preview read these), so under-reporting here makes Claude look
17
+ // like a seeded-only fork target when its runtime actually delivers a
18
+ // byte-exact same-runtime fork (forkTransport) and a full cross-runtime
19
+ // transcript replay INTO it (forkHistoryImport, via importHistoryForFork).
20
+ forkTransport: true,
21
+ forkHistoryImport: true,
14
22
  usageReporting: true,
15
23
  nativeSessionDiscovery: true,
16
24
  nativeSessionAdoption: true,
@@ -9,7 +9,7 @@ import { codexCredentialPreflight } from "../../runtime/codex-preflight.js";
9
9
  import { deleteCodexSession, discoverNativeCodexSessions, loadCodexTranscript, writeCodexRollout, exportCodexRollout, importCodexRollout, } from "../../runtime/codex-sessions.js";
10
10
  import { ProtocolRuntime } from "../../runtime/protocol.js";
11
11
  import { codexSlashCommands } from "../../runtime/slash-commands.js";
12
- export const CODEX_TESTED_VERSION = "0.154.0";
12
+ export const CODEX_TESTED_VERSION = "0.155.1";
13
13
  const CODEX_AVAILABLE_CACHE = new Map();
14
14
  function codexCommand() {
15
15
  return process.env.BIVY_CODEX_BIN?.trim() || "codex";
@@ -146,6 +146,14 @@ export function codexIntegration(origin) {
146
146
  resume: true,
147
147
  packages: false,
148
148
  fork: true,
149
+ // Mirror the ProtocolRuntime this integration builds (createCodexRuntime
150
+ // above wires exportForFork+importForFork and writeHistory, which flip
151
+ // capabilities.forkTransport/forkHistoryImport on). The catalog is a
152
+ // consumed source of truth (fork-fidelity matrix / fork-target preview),
153
+ // so omitting these made Codex look seeded-only when its runtime does a
154
+ // byte-exact codex→codex fork and a full transcript replay INTO it.
155
+ forkTransport: true,
156
+ forkHistoryImport: true,
149
157
  usageReporting: true,
150
158
  interactiveTui: installed,
151
159
  nativeSessionDiscovery: true,
@@ -5,7 +5,7 @@ import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { defineAgentIntegration } from "../definition.js";
7
7
  import { PI_CAPABILITIES } from "./capabilities.js";
8
- export const PI_TESTED_VERSION = "0.85.1";
8
+ export const PI_TESTED_VERSION = "0.86.1";
9
9
  export function piAgentDir() {
10
10
  return process.env.PI_CODING_AGENT_DIR?.trim() || path.join(os.homedir(), ".pi", "agent");
11
11
  }
@@ -43,7 +43,7 @@ export const AGENT_PROFILES = {
43
43
  // Approve/Deny + session/load resume + a real model picker), the same bar Pi,
44
44
  // Claude Code, and Codex clear. See `acp` below for the version fallback.
45
45
  supportTier: "supported",
46
- testedVersion: "1.18.30",
46
+ testedVersion: "1.18.31",
47
47
  blurb: "The most widely used open-source coding harness (OpenCode CLI).",
48
48
  // `opencode run -s <id> "<prompt>"` continues a prior session by its own id
49
49
  // (`-s, --session session id to continue`, per `opencode run --help`).
@@ -3,9 +3,9 @@
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.270", capabilities: ["toolInterception", "modelSelection", "resume"] },
7
- { id: "codex-approvals", status: "active", executionMode: "protocol", pinnedVersion: "0.154.0", capabilities: ["toolInterception", "modelSelection", "resume"] },
8
- { id: "pi", status: "active", executionMode: "protocol", pinnedVersion: "0.85.1", capabilities: ["toolInterception", "modelSelection", "resume"] },
9
- { id: "opencode", status: "active", executionMode: "protocol", pinnedVersion: "1.18.30", capabilities: ["toolInterception", "modelSelection", "resume"] },
6
+ { id: "claude-code-sdk", status: "active", executionMode: "protocol", pinnedVersion: "0.3.278", capabilities: ["toolInterception", "modelSelection", "resume"] },
7
+ { id: "codex-approvals", status: "active", executionMode: "protocol", pinnedVersion: "0.155.1", capabilities: ["toolInterception", "modelSelection", "resume"] },
8
+ { id: "pi", status: "active", executionMode: "protocol", pinnedVersion: "0.86.1", capabilities: ["toolInterception", "modelSelection", "resume"] },
9
+ { id: "opencode", status: "active", executionMode: "protocol", pinnedVersion: "1.18.31", capabilities: ["toolInterception", "modelSelection", "resume"] },
10
10
  ]
11
11
  };
@@ -696,6 +696,25 @@ function rawExitCode(raw) {
696
696
  const exit = o.exit_code ?? o.exitCode ?? o.code;
697
697
  return typeof exit === "number" ? exit : undefined;
698
698
  }
699
+ /** Decode a UTF-8 byte array carried as a JSON `number[]` (Grok's
700
+ * `rawOutput.output` transports command output this way). Returns the decoded
701
+ * string, or undefined when the value isn't a plausible byte array. Used only as
702
+ * a LAST resort — a clean ACP `content` block is always preferred — so a result
703
+ * frame with no display content still renders readable text instead of a raw
704
+ * number array (`[97,46,116,120,116]`). */
705
+ function decodeByteArray(v) {
706
+ if (!Array.isArray(v) || v.length === 0)
707
+ return undefined;
708
+ if (!v.every((n) => typeof n === "number" && Number.isInteger(n) && n >= 0 && n <= 255))
709
+ return undefined;
710
+ try {
711
+ const text = Buffer.from(v).toString("utf8");
712
+ return text.includes("\uFFFD") ? undefined : text;
713
+ }
714
+ catch {
715
+ return undefined;
716
+ }
717
+ }
699
718
  /** Extract an ACP-style tool update. Two transports converge here:
700
719
  * 1. A JSON-RPC `session/update` notification (`params.update`), the true ACP
701
720
  * wire form used by Gemini/Qwen/Copilot etc.
@@ -735,8 +754,16 @@ function acpToolUpdate(msg) {
735
754
  // the exit code from the raw payload when we take the content text instead.
736
755
  const contentText = flattenAcpContent(update.content);
737
756
  const exit = rawExitCode(raw);
738
- const output = contentText !== undefined
739
- ? (exit !== undefined ? { content: contentText, exit_code: exit } : contentText)
757
+ // Last-resort text when no clean ACP `content` block is present: decode a
758
+ // byte-array payload (Grok's rawOutput.output) so the card shows readable
759
+ // output instead of a raw `[97,46,…]` number array. Never overrides a real
760
+ // content block.
761
+ const decoded = contentText === undefined
762
+ ? (decodeByteArray(raw) ?? (raw && typeof raw === "object" && !Array.isArray(raw) ? decodeByteArray(raw.output) : undefined))
763
+ : undefined;
764
+ const text = contentText ?? decoded;
765
+ const output = text !== undefined
766
+ ? (exit !== undefined ? { content: text, exit_code: exit } : text)
740
767
  : (raw ?? update.content);
741
768
  return { kind: "result", id, output, error: status === "failed" || status === "error" };
742
769
  }
@@ -53,6 +53,7 @@ import { ProtocolRuntime, protocolRuntimeFromEnv, protocolCommandsFromEnv } from
53
53
  import { codexSlashCommands, opencodeSlashCommands } from "./slash-commands.js";
54
54
  import { withExactCapabilitySurface } from "./types.js";
55
55
  import { installedAgentContributions } from "../plugins/store.js";
56
+ import { forkCapsFromInfo } from "../session/fork-matrix.js";
56
57
  import { currentBivyVersion } from "../app-version.js";
57
58
  const PREFLIGHT_BEHAVIORS = {
58
59
  codex: (env) => codexCredentialPreflight(env),
@@ -552,6 +553,17 @@ function cliAgentInfo(id, spec) {
552
553
  }
553
554
  const authOwner = spec.authOwner ?? "agent";
554
555
  const credentialProviders = [...new Set((spec.model?.models ?? []).flatMap((model) => model.provider ? [model.provider] : []))];
556
+ // Fork fidelity, mirrored from what makeCliRuntime actually wires up. An
557
+ // ACP-promoted agent with a portable session store (OpenCode's SQLite) gets
558
+ // export/import + writeHistory hooks in acpRuntimeOptions, so its runtime
559
+ // advertises a byte-exact same-runtime fork (forkTransport) AND a full
560
+ // cross-runtime transcript replay INTO it (forkHistoryImport). Reporting a
561
+ // blanket fork:false here hid a full-fidelity fork target from the catalog
562
+ // and the generated fork matrix. Gated on the shipped default (acp.preferred)
563
+ // rather than a live binary probe so the capability is install-independent —
564
+ // the honest "what this adapter does by default", matching how resume/model
565
+ // are described before the optional BIVY_AGENT_PROBE refinement.
566
+ const nativeStoreFork = spec.behaviors?.sessionStore === "opencode" && spec.acp?.preferred === true;
555
567
  return {
556
568
  id,
557
569
  executionMode,
@@ -570,7 +582,8 @@ function cliAgentInfo(id, spec) {
570
582
  modelSelection,
571
583
  resume,
572
584
  packages: false,
573
- fork: false,
585
+ fork: nativeStoreFork,
586
+ ...(nativeStoreFork ? { forkTransport: true, forkHistoryImport: true } : {}),
574
587
  usageReporting,
575
588
  // Any agent with a readable on-disk session store (Codex, OpenCode) or
576
589
  // native-session behavior (Grok) can locate the session a `bivy run`
@@ -1009,6 +1022,22 @@ function agentRegistry(pluginDataDir) {
1009
1022
  export function listRegisteredAgents() {
1010
1023
  return agentRegistry().list().map((entry) => applyCertification(entry.describe()));
1011
1024
  }
1025
+ // Meta/host rows that are not concrete coding agents (they describe the generic
1026
+ // transports themselves), plus the hidden plain-`codex` exec runtime, which is a
1027
+ // duplicate of the governed `codex-approvals` we surface as "Codex".
1028
+ const FORK_MATRIX_EXCLUDE = new Set(["generic-cli", "bivy-agent-protocol", "acp", "codex"]);
1029
+ /** The built-in coding agents and their fork capabilities, derived from the live
1030
+ * registry, for docs/fork-matrix.md and its drift-guard test. Restricted to the
1031
+ * maintained (distribution) integrations so the generated doc is deterministic
1032
+ * regardless of which agents happen to be installed or which plugins are present. */
1033
+ export function forkMatrixAgents() {
1034
+ return listRegisteredAgents()
1035
+ .filter((info) => info.status !== "planned" &&
1036
+ !FORK_MATRIX_EXCLUDE.has(info.id) &&
1037
+ info.source?.kind === "package" &&
1038
+ info.source.location === "distribution")
1039
+ .map(forkCapsFromInfo);
1040
+ }
1012
1041
  /** Resolve an id or historical alias through the authoritative registry. */
1013
1042
  export function canonicalAgentId(id) {
1014
1043
  return agentRegistry().get(id.toLowerCase())?.id;
@@ -28,6 +28,18 @@ export function forkTier(source, dest) {
28
28
  return "replayed";
29
29
  return "seeded";
30
30
  }
31
+ /** Project a registry RuntimeInfo onto the two flags that decide fork fidelity.
32
+ * Keeps the registry the single source of truth: an agent that declares its
33
+ * real fork capabilities (see the maintained integrations + cliAgentInfo)
34
+ * appears with the correct tier automatically. */
35
+ export function forkCapsFromInfo(info) {
36
+ return {
37
+ id: info.id,
38
+ ...(info.displayName ? { displayName: info.displayName } : {}),
39
+ forkTransport: info.capabilities.forkTransport === true,
40
+ forkHistoryImport: info.capabilities.forkHistoryImport === true,
41
+ };
42
+ }
31
43
  /** Every ordered (source, dest) pair and its tier. */
32
44
  export function forkMatrix(agents) {
33
45
  const cells = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.16.25-staging.23",
3
+ "version": "0.16.25-staging.25",
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.",
@@ -51,9 +51,9 @@
51
51
  "zod": "^4.0.0"
52
52
  },
53
53
  "optionalDependencies": {
54
- "@anthropic-ai/claude-agent-sdk": "0.3.270",
55
- "@earendil-works/pi-ai": "0.85.1",
56
- "@earendil-works/pi-coding-agent": "0.85.1"
54
+ "@anthropic-ai/claude-agent-sdk": "0.3.278",
55
+ "@earendil-works/pi-ai": "0.86.1",
56
+ "@earendil-works/pi-coding-agent": "0.86.1"
57
57
  },
58
58
  "overrides": {
59
59
  "fast-uri": "3.1.6",