@bivy/bivy 0.16.8 → 0.16.9-staging.10

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.25",
25
+ "testedVersion": "1.18.27",
26
26
  "headlessFlags": [
27
27
  "run",
28
28
  "-s"
package/bin/bivy.mjs CHANGED
@@ -41,7 +41,7 @@ import { renderManagedBlock, upsertManagedBlock, removeManagedBlock, rcFileForSh
41
41
  import { removeInstallAndState } from "./uninstall-paths.mjs";
42
42
  import { findAvailablePort, reconcilePort } from "./port-picker.mjs";
43
43
  import { resolveAttachSessionId } from "./attach-session-id.mjs";
44
- import { detectInstallKind as classifyInstallKind } from "./install-kind.mjs";
44
+ import { detectInstallKind as classifyInstallKind, npmGlobalPrefix } from "./install-kind.mjs";
45
45
  import { hasConfiguredService as configuredServiceExists } from "./service-state.mjs";
46
46
 
47
47
  const selfScript = fileURLToPath(import.meta.url);
@@ -4447,7 +4447,13 @@ async function runUpdate(args = []) {
4447
4447
 
4448
4448
  if (kind === "npm-global") {
4449
4449
  console.log(c.dim(`Updating the globally-installed bivy package (channel: ${channel})…`));
4450
- const code = await run("npm", ["install", "-g", `@bivy/bivy@${channel}`, "--no-audit", "--no-fund"]);
4450
+ // npm's configured global prefix may not be the prefix that owns this
4451
+ // executable (for example, `npm config get prefix` can remain /usr after
4452
+ // installing Bivy with --prefix ~/.local). Always update the installation
4453
+ // that is actually running this command.
4454
+ const prefix = npmGlobalPrefix(repoRoot);
4455
+ const prefixArgs = prefix ? ["--prefix", prefix] : [];
4456
+ const code = await run("npm", ["install", "-g", ...prefixArgs, `@bivy/bivy@${channel}`, "--no-audit", "--no-fund"]);
4451
4457
  if (code !== 0) {
4452
4458
  console.log(c.yellow(`npm reported an issue (exit ${code}). Try: sudo npm i -g @bivy/bivy@${channel}`));
4453
4459
  process.exit(code);
@@ -18,3 +18,23 @@ export function detectInstallKind(repoRoot, existsSync = fs.existsSync) {
18
18
  if (inNodeModules) return "npm-global";
19
19
  return "packaged";
20
20
  }
21
+
22
+ /**
23
+ * Return the npm prefix that owns a package installed below node_modules.
24
+ * npm uses <prefix>/lib/node_modules on Unix and <prefix>/node_modules on
25
+ * other platforms. The running npm process may have a different configured
26
+ * prefix, so deriving it from the package path is important for user-local
27
+ * installs.
28
+ */
29
+ export function npmGlobalPrefix(repoRoot) {
30
+ let current = path.resolve(repoRoot);
31
+ while (true) {
32
+ if (path.basename(current) === "node_modules") {
33
+ const parent = path.dirname(current);
34
+ return path.basename(parent) === "lib" ? path.dirname(parent) : parent;
35
+ }
36
+ const parent = path.dirname(current);
37
+ if (parent === current) return undefined;
38
+ current = parent;
39
+ }
40
+ }
@@ -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.252";
7
+ export const CLAUDE_TESTED_VERSION = "0.3.258";
8
8
  const CLAUDE_CAPABILITIES = withExactCapabilitySurface({
9
9
  toolInterception: true,
10
10
  modelSelection: 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.151.0";
12
+ export const CODEX_TESTED_VERSION = "0.152.1";
13
13
  const CODEX_AVAILABLE_CACHE = new Map();
14
14
  function codexCommand() {
15
15
  return process.env.BIVY_CODEX_BIN?.trim() || "codex";
@@ -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.25",
46
+ testedVersion: "1.18.27",
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.252", capabilities: ["toolInterception", "modelSelection", "resume"] },
7
- { id: "codex-approvals", status: "active", executionMode: "protocol", pinnedVersion: "0.151.0", capabilities: ["toolInterception", "modelSelection", "resume"] },
6
+ { id: "claude-code-sdk", status: "active", executionMode: "protocol", pinnedVersion: "0.3.258", capabilities: ["toolInterception", "modelSelection", "resume"] },
7
+ { id: "codex-approvals", status: "active", executionMode: "protocol", pinnedVersion: "0.152.1", capabilities: ["toolInterception", "modelSelection", "resume"] },
8
8
  { id: "pi", status: "active", executionMode: "protocol", pinnedVersion: "0.84.4", capabilities: ["toolInterception", "modelSelection", "resume"] },
9
- { id: "opencode", status: "active", executionMode: "protocol", pinnedVersion: "1.18.25", capabilities: ["toolInterception", "modelSelection", "resume"] },
9
+ { id: "opencode", status: "active", executionMode: "protocol", pinnedVersion: "1.18.27", capabilities: ["toolInterception", "modelSelection", "resume"] },
10
10
  ]
11
11
  };
@@ -16,6 +16,7 @@ const reference = { kind: "reference", label: "Password manager or environment"
16
16
  /** Authoritative common providers and the offline baseline models Bivy ships. */
17
17
  export const BIVY_PROVIDER_CATALOG = [
18
18
  { id: "anthropic", name: "Anthropic", authMethods: [oauth("Claude Pro / Max", "anthropic"), apiKey("Anthropic API key", "https://console.anthropic.com/settings/keys"), reference], env: ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"], compatibility: "anthropic", helpUrl: "https://docs.anthropic.com/", models: [
19
+ { id: "claude-opus-4-8", name: "Claude Opus 4.8", reasoning: true },
19
20
  { id: "claude-opus-4-1", name: "Claude Opus 4.1", reasoning: true },
20
21
  { id: "claude-sonnet-4-5", name: "Claude Sonnet 4.5", reasoning: true },
21
22
  { id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5" },
@@ -26,6 +27,7 @@ export const BIVY_PROVIDER_CATALOG = [
26
27
  { id: "gpt-4o", name: "GPT-4o" },
27
28
  ] },
28
29
  { id: "openai-codex", name: "OpenAI — ChatGPT subscription", aliases: ["codex"], authMethods: [oauth("ChatGPT Plus / Pro", "openai-codex")], compatibility: "openai", models: [
30
+ { id: "gpt-5.6-sol", name: "GPT-5.6 Sol", reasoning: true },
29
31
  { id: "gpt-5.3-codex-spark", name: "GPT-5.3 Codex Spark", reasoning: true },
30
32
  { id: "gpt-5-codex", name: "GPT-5 Codex", reasoning: true },
31
33
  ] },
@@ -45,6 +45,19 @@ function decorate(detail, toolName, input, context) {
45
45
  function canon(name) {
46
46
  return name.toLowerCase().replace(/[^a-z0-9]/g, "");
47
47
  }
48
+ /** Match both native names and namespaced MCP/ACP names. Providers commonly
49
+ * expose a tool as `mcp__server__read_file` or `functions.exec`; the final
50
+ * component still has the same portable meaning. Keep this exact (rather than
51
+ * substring) matching so `multitasker` cannot become a delegation by accident. */
52
+ function inToolSet(set, rawName, key) {
53
+ if (set.has(key))
54
+ return true;
55
+ const separator = rawName.lastIndexOf("__");
56
+ const dot = rawName.lastIndexOf(".");
57
+ const slash = rawName.lastIndexOf("/");
58
+ const index = Math.max(separator, dot, slash);
59
+ return index >= 0 && set.has(canon(rawName.slice(index + (separator === index ? 2 : 1))));
60
+ }
48
61
  function asRecord(input) {
49
62
  return input && typeof input === "object" && !Array.isArray(input)
50
63
  ? input
@@ -97,11 +110,11 @@ const PATH_KEYS = ["path", "file_path", "filePath", "filename", "fileName", "fil
97
110
  export function mapToolCall(toolName, input, context = {}) {
98
111
  const key = canon(toolName);
99
112
  const o = asRecord(input);
100
- if (SHELL.has(key)) {
113
+ if (inToolSet(SHELL, toolName, key)) {
101
114
  const command = str(o, "command", "cmd", "script", "input", "args");
102
115
  return command ? decorate({ kind: "shell", command, ...(str(o, "cwd", "workdir", "workingDir", "directory") ? { cwd: str(o, "cwd", "workdir", "workingDir", "directory") } : {}) }, toolName, input, context) : undefined;
103
116
  }
104
- if (EDIT.has(key)) {
117
+ if (inToolSet(EDIT, toolName, key)) {
105
118
  let path = str(o, ...PATH_KEYS);
106
119
  // Codex `apply_patch`/`file_change` carries a `changes` map keyed by path.
107
120
  if (!path) {
@@ -118,26 +131,26 @@ export function mapToolCall(toolName, input, context = {}) {
118
131
  const newText = str(o, "new_string", "newString", "new", "after", "replace", "replacement");
119
132
  return decorate({ kind: "edit", path, ...(oldText ? { oldText } : {}), ...(newText ? { newText } : {}) }, toolName, input, context);
120
133
  }
121
- if (WRITE.has(key)) {
134
+ if (inToolSet(WRITE, toolName, key)) {
122
135
  const path = str(o, ...PATH_KEYS);
123
136
  return path ? decorate({ kind: "write", path }, toolName, input, context) : undefined;
124
137
  }
125
- if (READ.has(key)) {
138
+ if (inToolSet(READ, toolName, key)) {
126
139
  const path = str(o, ...PATH_KEYS);
127
140
  return path ? decorate({ kind: "read", path }, toolName, input, context) : undefined;
128
141
  }
129
- if (SEARCH.has(key)) {
142
+ if (inToolSet(SEARCH, toolName, key)) {
130
143
  const query = str(o, "pattern", "query", "q", "search", "regex", "searchTerm");
131
144
  return query ? decorate({ kind: "search", query, ...(str(o, "path", "dir", "directory", "include") ? { path: str(o, "path", "dir", "directory", "include") } : {}) }, toolName, input, context) : undefined;
132
145
  }
133
- if (FETCH.has(key)) {
146
+ if (inToolSet(FETCH, toolName, key)) {
134
147
  const url = str(o, "url", "uri", "href", "link");
135
148
  return url ? decorate({ kind: "fetch", url }, toolName, input, context) : undefined;
136
149
  }
137
- if (PLAN.has(key)) {
150
+ if (inToolSet(PLAN, toolName, key)) {
138
151
  return decorate({ kind: "plan", ...(str(o, "plan", "text", "content", "message") ? { text: str(o, "plan", "text", "content", "message") } : {}) }, toolName, input, context);
139
152
  }
140
- if (DELEGATE.has(key)) {
153
+ if (inToolSet(DELEGATE, toolName, key)) {
141
154
  const label = str(o, "subagent_type", "subagentType", "agent", "agentType", "role", "name");
142
155
  const description = str(o, "description", "task", "prompt", "instructions", "goal", "message");
143
156
  return decorate({ kind: "delegation", ...(label ? { label } : {}), ...(description ? { description } : {}) }, toolName, input, context);
package/dist/server.js CHANGED
@@ -723,7 +723,12 @@ function runBivyUpdate() {
723
723
  const child = spawn(process.execPath, [script, "update"], {
724
724
  detached: true,
725
725
  stdio: "ignore",
726
- env: process.env,
726
+ // The daemon is commonly itself managed by systemd/launchd. Mark this
727
+ // invocation as terminal-style so the CLI moves the real update into a
728
+ // process that survives the service restart (systemd-run on Linux).
729
+ // Otherwise stopping bivy.service kills the updater before it can install
730
+ // anything, leaving the client stuck on “Updating…”.
731
+ env: { ...process.env, BIVY_TERMINAL: "1" },
727
732
  });
728
733
  child.unref();
729
734
  return { ok: true };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.16.8",
3
+ "version": "0.16.9-staging.10",
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.252",
53
+ "@anthropic-ai/claude-agent-sdk": "0.3.258",
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"
@@ -63,6 +63,7 @@
63
63
  "undici": "8.10.0"
64
64
  },
65
65
  "brace-expansion": "5.0.9",
66
+ "fast-uri": "4.1.4",
66
67
  "nanoid": "3.3.18",
67
68
  "undici": "8.10.0"
68
69
  },