devez-vibe 1.7.13 → 1.7.14

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/dvz.exe CHANGED
Binary file
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { randomUUID } from "node:crypto";
4
- import { spawn } from "node:child_process";
5
- import { createReadStream, existsSync, readdirSync } from "node:fs";
4
+ import { execFile, spawn } from "node:child_process";
5
+ import { createReadStream, existsSync, readFileSync, readdirSync } from "node:fs";
6
6
  import { mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
7
7
  import { homedir } from "node:os";
8
8
  import { dirname, join } from "node:path";
9
9
  import { createInterface } from "node:readline";
10
+ import { fileURLToPath } from "node:url";
10
11
  import {
11
12
  deleteSession,
12
13
  forkSession,
@@ -120,13 +121,76 @@ function sanitizedEnvironment() {
120
121
  return env;
121
122
  }
122
123
 
124
+ // Per executable path: `true` once the installed Claude Code proved newer than
125
+ // the SDK's bundle, `false` or a pending promise otherwise.
126
+ const externalCliChoices = new Map();
127
+
128
+ function parseVersion(text) {
129
+ const match = String(text || "").match(/([0-9]+)[.]([0-9]+)[.]([0-9]+)/);
130
+ return match ? match.slice(1, 4).map(Number) : null;
131
+ }
132
+
133
+ function isNewerVersion(candidate, baseline) {
134
+ const a = parseVersion(candidate);
135
+ const b = parseVersion(baseline);
136
+ if (!a || !b) return false;
137
+ for (let index = 0; index < 3; index++) {
138
+ if (a[index] !== b[index]) return a[index] > b[index];
139
+ }
140
+ return false;
141
+ }
142
+
143
+ // The installed Claude Code wins only when it is a real executable — a .cmd
144
+ // shim fails with EINVAL — and strictly newer than the CLI the SDK bundles, so
145
+ // updating Claude Code alone surfaces new models without a DevezVibe release
146
+ // while an equal or older install keeps the bundle the SDK was tested with.
147
+ function prefersInstalledCli(executable, installedVersion, bundledVersion) {
148
+ if (!String(executable || "").toLowerCase().endsWith(".exe")) return false;
149
+ return isNewerVersion(installedVersion, bundledVersion);
150
+ }
151
+
152
+ function bundledCliVersion() {
153
+ try {
154
+ const entry = fileURLToPath(import.meta.resolve("@anthropic-ai/claude-agent-sdk"));
155
+ const manifest = JSON.parse(readFileSync(join(dirname(entry), "manifest.json"), "utf8"));
156
+ return String(manifest.version || "");
157
+ } catch {
158
+ return "";
159
+ }
160
+ }
161
+
162
+ function installedCliVersion(executable) {
163
+ return new Promise((resolve) => {
164
+ execFile(executable, ["--version"], { timeout: 5000, windowsHide: true }, (error, stdout) => {
165
+ resolve(error ? "" : String(stdout || ""));
166
+ });
167
+ });
168
+ }
169
+
170
+ /** Decide once per executable, before the first session or catalog query. */
171
+ async function ensureClaudeExecutableChoice(params) {
172
+ const executable = String(params?.claudePath || "").trim();
173
+ if (process.platform !== "win32" || !executable || externalCliChoices.has(executable)) return;
174
+ const pending = (async () => {
175
+ if (!existsSync(executable)) return false;
176
+ const installed = await installedCliVersion(executable);
177
+ return prefersInstalledCli(executable, installed, bundledCliVersion());
178
+ })().catch(() => false);
179
+ externalCliChoices.set(executable, pending);
180
+ externalCliChoices.set(executable, await pending);
181
+ }
182
+
123
183
  function applyClaudeExecutable(options, params) {
124
184
  const executable = String(params.claudePath || "").trim();
125
185
  if (!executable) return;
126
- // On Windows use the SDK's matching native CLI bundle. It reads the same
127
- // ~/.claude credentials, settings, hooks, skills, and plugins, while avoiding
128
- // EINVAL from command shims and incompatible separately-installed CLI builds.
129
- if (process.platform === "win32") return;
186
+ // On Windows the SDK's matching native CLI bundle is the default: it reads
187
+ // the same ~/.claude credentials, settings, hooks, skills, and plugins, and
188
+ // avoids EINVAL from command shims. A newer installed Claude Code overrides
189
+ // it see prefersInstalledCli.
190
+ if (process.platform === "win32") {
191
+ if (externalCliChoices.get(executable) === true) options.pathToClaudeCodeExecutable = executable;
192
+ return;
193
+ }
130
194
  options.pathToClaudeCodeExecutable = executable;
131
195
  }
132
196
 
@@ -296,6 +360,7 @@ async function loadModelCatalog(params) {
296
360
  const cacheKey = catalogCacheKey(params);
297
361
  if (modelCatalogs.has(cacheKey)) return modelCatalogs.get(cacheKey);
298
362
  const pending = (async () => {
363
+ await ensureClaudeExecutableChoice(params);
299
364
  const input = new AsyncQueue();
300
365
  const options = {
301
366
  cwd: params.cwd || process.cwd(),
@@ -1215,6 +1280,7 @@ async function createSession(params, resumeId) {
1215
1280
  lastContextUsage: null,
1216
1281
  lastContextWindow: 0,
1217
1282
  };
1283
+ await ensureClaudeExecutableChoice(params);
1218
1284
  const agentQuery = await startAgentQuery(queue, makeOptions(params, id, resumeId));
1219
1285
  session.query = agentQuery;
1220
1286
  sessions.set(id, session);
@@ -3429,6 +3495,16 @@ async function runSelfTest() {
3429
3495
  || familyCapabilities(successorModels, "gpt-5.6") !== undefined) {
3430
3496
  throw new Error("Claude model successor self-test failed");
3431
3497
  }
3498
+ // Only a real, strictly newer installed CLI replaces the SDK bundle.
3499
+ if (!prefersInstalledCli("C:/Users/me/.local/bin/claude.exe", "2.1.260 (Claude Code)", "2.1.258")
3500
+ || prefersInstalledCli("C:/Users/me/.local/bin/claude.exe", "2.1.258 (Claude Code)", "2.1.258")
3501
+ || prefersInstalledCli("C:/Users/me/.local/bin/claude.exe", "2.1.9", "2.1.258")
3502
+ || prefersInstalledCli("C:/Users/me/AppData/Roaming/npm/claude.cmd", "2.1.260", "2.1.258")
3503
+ || prefersInstalledCli("C:/Users/me/.local/bin/claude.exe", "", "2.1.258")
3504
+ || prefersInstalledCli("C:/Users/me/.local/bin/claude.exe", "2.1.260", "")
3505
+ || !isNewerVersion("2.2.0", "2.1.999")) {
3506
+ throw new Error("Claude installed CLI preference self-test failed");
3507
+ }
3432
3508
  const latestOptions = makeOptions({ cwd: process.cwd(), permissionMode: "plan" }, "00000000-0000-4000-8000-000000000000");
3433
3509
  if (latestOptions.permissionMode !== BOOTSTRAP_PERMISSION_MODE
3434
3510
  || latestOptions.perTaskStopAffordance !== true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devez-vibe",
3
- "version": "1.7.13",
3
+ "version": "1.7.14",
4
4
  "description": "Stable terminal UI for Codex and Claude Agent SDK",
5
5
  "keywords": [
6
6
  "codex",