New:Socket for Asana Is Now Available.Learn more
Sign In

yaver-cli

Package Overview
Dependencies
Maintainers
1
Versions
390
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

yaver-cli - npm Package Compare versions

Comparing version
1.99.411
to
1.99.415
+378
src/commands/desktop.js
"use strict";
/**
* Optional native desktop companion for the unified npm CLI.
*
* The npm package intentionally does not contain Electron itself. `yaver
* desktop install` downloads the architecture-specific canonical `electron/`
* release, verifies the release checksum, verifies the OS signature where the
* host provides one, and installs per-user. The Go agent remains independently
* usable through the console and an already-running agent is adopted by the
* GUI instead of duplicated.
*/
const crypto = require("node:crypto");
const fs = require("node:fs");
const https = require("node:https");
const os = require("node:os");
const path = require("node:path");
const { spawn, spawnSync } = require("node:child_process");
const { pipeline } = require("node:stream/promises");
const DEFAULT_REPO = "yaver-io/yaver.io";
const WINDOWS_PUBLISHER_PATTERN = "Simkab";
const DESKTOP_HELP = `
yaver desktop — optional native Yaver GUI (the console remains available as \`yaver\`)
Commands:
yaver desktop Open the installed desktop app
yaver desktop install Download, verify, install per-user, and open
yaver desktop update Install the latest verified desktop release
yaver desktop status Show platform, installed path, and release state
yaver desktop path Print the installed application path
yaver desktop download [--format] Download a verified installer without running it
Options:
--no-open Install without launching (used by npm bootstrap)
Formats:
macOS: dmg (default)
Linux: appimage (default), deb, rpm
Windows: exe (default)
The GUI is downloaded as a separately signed, checksum-verified artifact; npm
does not embed Electron in the CLI tarball. Global installs bootstrap it on an
interactive desktop unless YAVER_SKIP_POSTINSTALL_DESKTOP=1 is set. Headless
Linux/CI stays console-only. Runner bootstrap can independently be disabled
with YAVER_SKIP_POSTINSTALL_RUNNERS=1.
`;
function normalizedArch(arch = process.arch) {
if (arch === "x64" || arch === "amd64") return "x64";
if (arch === "arm64" || arch === "aarch64") return "arm64";
throw new Error(`Yaver Desktop is not published for architecture ${arch}.`);
}
function defaultFormat(platform = process.platform) {
if (platform === "darwin") return "dmg";
if (platform === "linux") return "appimage";
if (platform === "win32") return "exe";
throw new Error(`Yaver Desktop is not published for platform ${platform}.`);
}
function assetName(version, platform = process.platform, arch = process.arch, format = defaultFormat(platform)) {
const cpu = normalizedArch(arch);
const ext = String(format).toLowerCase();
if (platform === "darwin" && ext === "dmg") return `yaver-gui-${version}-mac-${cpu}.dmg`;
if (platform === "linux" && ["appimage", "deb", "rpm"].includes(ext)) {
const suffix = ext === "appimage" ? "AppImage" : ext;
return `yaver-gui-${version}-linux-${cpu}.${suffix}`;
}
if (platform === "win32" && ext === "exe") return `yaver-gui-${version}-win-${cpu}-setup.exe`;
throw new Error(`Desktop format ${format} is not supported on ${platform}.`);
}
function parseGuiRelease(releases, requestedVersion = "") {
const rows = Array.isArray(releases) ? releases : [];
const wanted = String(requestedVersion || "").replace(/^gui\/v/, "").replace(/^v/, "");
const release = rows.find((row) => {
if (!row || row.draft || row.prerelease) return false;
const match = String(row.tag_name || "").match(/^gui\/v(\d+\.\d+\.\d+)$/);
return match && (!wanted || match[1] === wanted);
});
if (!release) throw new Error(wanted ? `No published GUI release exists for ${wanted}.` : "No published GUI release exists.");
return { ...release, version: String(release.tag_name).slice("gui/v".length) };
}
function checksumFor(text, filename) {
for (const line of String(text || "").split(/\r?\n/)) {
const match = line.trim().match(/^([a-fA-F0-9]{64})\s+\*?(.+)$/);
if (match && match[2] === filename) return match[1].toLowerCase();
}
throw new Error(`checksums.txt has no SHA-256 entry for ${filename}.`);
}
function installedDesktopCandidates(platform = process.platform, env = process.env, home = os.homedir()) {
if (platform === "darwin") {
return [path.join(home, "Applications", "Yaver.app"), "/Applications/Yaver.app"];
}
if (platform === "linux") {
return [
path.join(home, ".local", "opt", "yaver", "Yaver.AppImage"),
"/opt/Yaver/yaver-desktop",
"/usr/bin/yaver-desktop",
"/usr/local/bin/yaver-desktop",
];
}
if (platform === "win32") {
const local = env.LOCALAPPDATA || path.join(home, "AppData", "Local");
return [
path.join(local, "Programs", "Yaver", "Yaver.exe"),
path.join(local, "Yaver", "Yaver.exe"),
];
}
return [];
}
function installedDesktopPath(platform = process.platform) {
return installedDesktopCandidates(platform).find((candidate) => fs.existsSync(candidate)) || "";
}
function request(url, options = {}) {
return new Promise((resolve, reject) => {
const req = https.get(url, {
headers: { "User-Agent": "yaver-cli-desktop", Accept: "application/vnd.github+json", ...(options.headers || {}) },
}, (response) => {
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
response.resume();
resolve(request(response.headers.location, options));
return;
}
resolve(response);
});
req.setTimeout(30_000, () => req.destroy(new Error(`Desktop release request timed out: ${url}`)));
req.on("error", reject);
});
}
async function responseText(response) {
let body = "";
response.setEncoding("utf8");
for await (const chunk of response) body += chunk;
return body;
}
async function download(url, destination) {
const response = await request(url, { headers: { Accept: "application/octet-stream" } });
if (response.statusCode !== 200) {
const body = await responseText(response);
throw new Error(`Desktop download failed (HTTP ${response.statusCode}) from ${url}${body ? `: ${body.slice(0, 160)}` : ""}`);
}
await pipeline(response, fs.createWriteStream(destination, { mode: 0o700 }));
}
function sha256(file) {
const hash = crypto.createHash("sha256");
const fd = fs.openSync(file, "r");
const buffer = Buffer.allocUnsafe(1024 * 1024);
try {
let count = 0;
while ((count = fs.readSync(fd, buffer, 0, buffer.length, null)) > 0) hash.update(buffer.subarray(0, count));
} finally {
fs.closeSync(fd);
}
return hash.digest("hex");
}
async function resolveDownload({ platform, arch, format, version = "" }) {
const repo = process.env.YAVER_DESKTOP_REPO || DEFAULT_REPO;
const response = await request(`https://api.github.com/repos/${repo}/releases?per_page=100`);
if (response.statusCode !== 200) throw new Error(`Desktop release lookup failed (HTTP ${response.statusCode}).`);
const release = parseGuiRelease(JSON.parse(await responseText(response)), version || process.env.YAVER_DESKTOP_VERSION);
const filename = assetName(release.version, platform, arch, format);
const assets = new Map((release.assets || []).map((entry) => [entry.name, entry]));
const artifact = assets.get(filename);
const checksums = assets.get("checksums.txt");
if (!artifact) throw new Error(`Release ${release.tag_name} does not contain ${filename}.`);
if (!checksums) throw new Error(`Release ${release.tag_name} has no checksums.txt; refusing an unverified desktop download.`);
return { release, artifact, checksums, filename };
}
async function downloadVerified(options) {
const resolved = await resolveDownload(options);
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "yaver-desktop-"));
const artifactPath = path.join(dir, resolved.filename);
const checksumsPath = path.join(dir, "checksums.txt");
try {
await download(resolved.artifact.browser_download_url, artifactPath);
await download(resolved.checksums.browser_download_url, checksumsPath);
const expected = checksumFor(fs.readFileSync(checksumsPath, "utf8"), resolved.filename);
const actual = sha256(artifactPath);
if (actual !== expected) throw new Error(`SHA-256 mismatch for ${resolved.filename}: expected ${expected}, downloaded ${actual}.`);
return { ...resolved, artifactPath, tempDir: dir, sha256: actual };
} catch (error) {
fs.rmSync(dir, { recursive: true, force: true });
throw error;
}
}
function runChecked(command, args, message) {
const result = spawnSync(command, args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
if (result.status !== 0) throw new Error(`${message}: ${(result.stderr || result.stdout || `exit ${result.status}`).trim()}`);
return result.stdout || result.stderr || "";
}
function verifyMacApp(appPath) {
runChecked("codesign", ["--verify", "--deep", "--strict", "--verbose=2", appPath], "macOS code-sign verification failed");
const details = runChecked("codesign", ["-dv", "--verbose=4", appPath], "Could not inspect the macOS signature");
if (!details.includes("Identifier=io.yaver.gui")) throw new Error("The signed macOS app has an unexpected bundle identifier.");
runChecked("spctl", ["--assess", "--type", "exec", "--verbose=2", appPath], "macOS Gatekeeper rejected Yaver");
runChecked("xcrun", ["stapler", "validate", appPath], "The macOS notarization ticket is missing or invalid");
}
function installMac(downloaded) {
const mount = path.join(downloaded.tempDir, "mount");
fs.mkdirSync(mount);
runChecked("hdiutil", ["attach", "-nobrowse", "-readonly", "-mountpoint", mount, downloaded.artifactPath], "Could not mount the Yaver DMG");
try {
const source = path.join(mount, "Yaver.app");
if (!fs.existsSync(source)) throw new Error("The verified DMG does not contain Yaver.app.");
verifyMacApp(source);
const applications = path.join(os.homedir(), "Applications");
fs.mkdirSync(applications, { recursive: true });
const target = path.join(applications, "Yaver.app");
const staging = path.join(applications, `.Yaver.app.install-${process.pid}`);
const backup = path.join(applications, `.Yaver.app.backup-${process.pid}`);
fs.rmSync(staging, { recursive: true, force: true });
fs.cpSync(source, staging, { recursive: true, force: false, preserveTimestamps: true });
verifyMacApp(staging);
let backedUp = false;
try {
if (fs.existsSync(target)) { fs.renameSync(target, backup); backedUp = true; }
fs.renameSync(staging, target);
if (backedUp) fs.rmSync(backup, { recursive: true, force: true });
} catch (error) {
if (!fs.existsSync(target) && backedUp && fs.existsSync(backup)) fs.renameSync(backup, target);
throw error;
} finally {
fs.rmSync(staging, { recursive: true, force: true });
}
return target;
} finally {
spawnSync("hdiutil", ["detach", mount], { stdio: "ignore" });
}
}
function installLinuxAppImage(downloaded) {
const root = path.join(os.homedir(), ".local", "opt", "yaver");
const target = path.join(root, "Yaver.AppImage");
const staging = path.join(root, `.Yaver.AppImage.install-${process.pid}`);
fs.mkdirSync(root, { recursive: true });
fs.copyFileSync(downloaded.artifactPath, staging);
fs.chmodSync(staging, 0o755);
fs.renameSync(staging, target);
const applications = path.join(os.homedir(), ".local", "share", "applications");
fs.mkdirSync(applications, { recursive: true });
const execPath = `"${target.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/%/g, "%%")}"`;
fs.writeFileSync(path.join(applications, "io.yaver.gui.desktop"), [
"[Desktop Entry]", "Name=Yaver", "Comment=AI development workspace and remote node",
`Exec=${execPath} %U`, "Terminal=false", "Type=Application", "Categories=Development;Utility;",
"StartupWMClass=Yaver", "MimeType=x-scheme-handler/yaver;", "",
].join("\n"));
const binDir = path.join(os.homedir(), ".local", "bin");
const link = path.join(binDir, "yaver-desktop");
fs.mkdirSync(binDir, { recursive: true });
try {
const stat = fs.lstatSync(link);
if (!stat.isSymbolicLink()) throw new Error(`${link} already exists and is not a Yaver-managed symlink.`);
const priorTarget = path.resolve(path.dirname(link), fs.readlinkSync(link));
if (!priorTarget.startsWith(root + path.sep) && priorTarget !== target) {
throw new Error(`${link} points outside the Yaver install directory; refusing to replace it.`);
}
fs.unlinkSync(link);
} catch (error) {
if (error.code !== "ENOENT") throw error;
}
fs.symlinkSync(target, link);
return target;
}
function verifyWindowsInstaller(installer) {
const escaped = installer.replace(/'/g, "''");
const script = `$s=Get-AuthenticodeSignature -LiteralPath '${escaped}'; if ($s.Status -ne 'Valid') { throw \"Authenticode status: $($s.Status) $($s.StatusMessage)\" }; if ($s.SignerCertificate.Subject -notmatch '(?i)${WINDOWS_PUBLISHER_PATTERN}') { throw \"Unexpected publisher: $($s.SignerCertificate.Subject)\" }`;
runChecked("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], "Windows Authenticode verification failed");
}
function openDesktop(appPath, platform = process.platform) {
let command;
let args;
if (platform === "darwin") { command = "open"; args = [appPath]; }
else { command = appPath; args = []; }
const child = spawn(command, args, { detached: true, stdio: "ignore", env: process.env });
child.once("error", (error) => console.error(`Could not open Yaver Desktop: ${error.message}`));
child.unref();
}
function parseDesktopArgs(args) {
const command = !args[0] || args[0].startsWith("-") ? "open" : args[0];
let format = "";
let destination = "";
let noOpen = false;
for (let i = command === "open" && args[0]?.startsWith("-") ? 0 : 1; i < args.length; i++) {
if (args[i] === "--format" && args[i + 1]) format = args[++i].toLowerCase();
else if (args[i] === "--output" && args[i + 1]) destination = args[++i];
else if (args[i] === "--no-open") noOpen = true;
}
return { command, format: format || defaultFormat(), destination, noOpen };
}
async function desktop(args = []) {
if (args.includes("--help") || args.includes("-h") || args[0] === "help") {
console.log(DESKTOP_HELP);
return;
}
const options = parseDesktopArgs(args);
const existing = installedDesktopPath();
if (options.command === "status") {
console.log(JSON.stringify({ installed: Boolean(existing), path: existing || null, platform: process.platform, arch: normalizedArch() }, null, 2));
return;
}
if (options.command === "path") {
if (!existing) throw new Error("Yaver Desktop is not installed. Run `yaver desktop install`.");
console.log(existing);
return;
}
if (options.command === "open") {
if (!existing) throw new Error("Yaver Desktop is not installed. Run `yaver desktop install` (the console remains available as `yaver`).");
openDesktop(existing);
return;
}
if (!["install", "update", "download"].includes(options.command)) throw new Error(`Unknown desktop command: ${options.command}\n${DESKTOP_HELP}`);
const downloaded = await downloadVerified({ platform: process.platform, arch: process.arch, format: options.format });
if (options.command === "download" || (process.platform === "linux" && options.format !== "appimage")) {
const destination = path.resolve(options.destination || path.join(process.cwd(), downloaded.filename));
fs.copyFileSync(downloaded.artifactPath, destination);
fs.rmSync(downloaded.tempDir, { recursive: true, force: true });
console.log(`Verified ${downloaded.filename} → ${destination}`);
if (process.platform === "linux" && options.format === "deb") console.log(`Install with: sudo apt-get install ${JSON.stringify(destination)}`);
if (process.platform === "linux" && options.format === "rpm") console.log(`Install with: sudo dnf install ${JSON.stringify(destination)}`);
return;
}
let installed = "";
try {
if (process.platform === "darwin") installed = installMac(downloaded);
else if (process.platform === "linux") installed = installLinuxAppImage(downloaded);
else if (process.platform === "win32") {
verifyWindowsInstaller(downloaded.artifactPath);
const child = spawn(downloaded.artifactPath, options.noOpen ? ["/S"] : [], { detached: true, stdio: "ignore" });
child.once("error", (error) => console.error(`Could not open the verified Yaver installer: ${error.message}`));
child.unref();
console.log(options.noOpen
? "Verified installer started in per-user silent mode."
: "Verified installer opened. Complete the per-user installation in the Yaver setup window.");
return;
}
} finally {
if (process.platform !== "win32") fs.rmSync(downloaded.tempDir, { recursive: true, force: true });
}
console.log(`Yaver Desktop ${downloaded.release.version} installed at ${installed}`);
if (!options.noOpen) openDesktop(installed);
}
module.exports = {
DESKTOP_HELP,
assetName,
checksumFor,
defaultFormat,
desktop,
installedDesktopCandidates,
normalizedArch,
parseDesktopArgs,
parseGuiRelease,
WINDOWS_PUBLISHER_PATTERN,
};
"use strict";
/**
* A machine that already has a supported coding runner has made its choice.
* Yaver should wire that runner, not install competitors beside it. This is
* especially important for existing OpenCode/BYOK setups: provider and model
* configuration belong to OpenCode and must remain untouched.
*
* Fresh machines retain the existing bootstrap behaviour so the global npm
* install still produces a usable development node.
*/
function codingRunnerBootstrapPlan(entries, commandExists) {
const installed = entries.filter((entry) => commandExists(entry.command));
return {
installed,
toInstall: installed.length > 0 ? [] : entries,
};
}
module.exports = { codingRunnerBootstrapPlan };
+4
-3
{
"name": "yaver-cli",
"version": "1.99.411",
"version": "1.99.415",
"mcpName": "io.github.yaver-io/yaver",

@@ -14,2 +14,3 @@ "description": "Unified npm bootstrap for the Yaver agent, SDK injection, and local-first developer runtime",

"scripts": {
"test": "node --test test/*.test.js",
"postinstall": "node src/postinstall.js",

@@ -43,3 +44,3 @@ "preuninstall": "node src/preuninstall.js"

"type": "git",
"url": "git+https://github.com/kivanccakmak/yaver.io.git"
"url": "git+https://github.com/yaver-io/yaver.io.git"
},

@@ -54,2 +55,2 @@ "homepage": "https://yaver.io",

}
}
}

@@ -7,3 +7,3 @@ {

"hermes": {
"version": "1.99.410",
"version": "1.99.415",
"bytecodeVersion": 96

@@ -129,3 +129,3 @@ },

"@amplitude/analytics-react-native": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -137,3 +137,3 @@ "cliPush": true,

"@intercom/intercom-react-native": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -145,3 +145,3 @@ "cliPush": true,

"@notifee/react-native": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -153,3 +153,3 @@ "cliPush": true,

"@react-native-async-storage/async-storage": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -161,3 +161,3 @@ "cliPush": true,

"@react-native-community/datetimepicker": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -169,3 +169,3 @@ "cliPush": true,

"@react-native-community/netinfo": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -177,3 +177,3 @@ "cliPush": true,

"@react-native-community/slider": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -185,3 +185,3 @@ "cliPush": true,

"@react-native-google-signin/google-signin": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -193,3 +193,3 @@ "cliPush": true,

"@react-native-masked-view/masked-view": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -201,3 +201,3 @@ "cliPush": true,

"@react-native-menu/menu": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -209,3 +209,3 @@ "cliPush": true,

"@react-native-ml-kit/text-recognition": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -217,3 +217,3 @@ "cliPush": true,

"@react-native-picker/picker": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -225,3 +225,3 @@ "cliPush": true,

"@react-native-segmented-control/segmented-control": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -233,3 +233,3 @@ "cliPush": true,

"@sentry/react-native": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -241,3 +241,3 @@ "cliPush": true,

"@shopify/react-native-skia": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -249,3 +249,3 @@ "cliPush": true,

"@stripe/stripe-react-native": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -257,3 +257,3 @@ "cliPush": true,

"expo-apple-authentication": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -265,3 +265,3 @@ "cliPush": true,

"expo-asset": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -273,3 +273,3 @@ "cliPush": true,

"expo-av": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -281,3 +281,3 @@ "cliPush": true,

"expo-background-fetch": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -289,3 +289,3 @@ "cliPush": true,

"expo-battery": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -297,3 +297,3 @@ "cliPush": true,

"expo-blur": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -305,3 +305,3 @@ "cliPush": true,

"expo-brightness": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -313,3 +313,3 @@ "cliPush": true,

"expo-calendar": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -321,3 +321,3 @@ "cliPush": true,

"expo-camera": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -329,3 +329,3 @@ "cliPush": true,

"expo-clipboard": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -337,3 +337,3 @@ "cliPush": true,

"expo-constants": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -345,3 +345,3 @@ "cliPush": true,

"expo-contacts": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -353,3 +353,3 @@ "cliPush": true,

"expo-crypto": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -361,3 +361,3 @@ "cliPush": true,

"expo-device": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -369,3 +369,3 @@ "cliPush": true,

"expo-document-picker": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -377,3 +377,3 @@ "cliPush": true,

"expo-file-system": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -385,3 +385,3 @@ "cliPush": true,

"expo-font": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -393,3 +393,3 @@ "cliPush": true,

"expo-haptics": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -401,3 +401,3 @@ "cliPush": true,

"expo-image": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -409,3 +409,3 @@ "cliPush": true,

"expo-image-manipulator": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -417,3 +417,3 @@ "cliPush": true,

"expo-image-picker": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -425,3 +425,3 @@ "cliPush": true,

"expo-keep-awake": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -433,3 +433,3 @@ "cliPush": true,

"expo-linear-gradient": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -441,3 +441,3 @@ "cliPush": true,

"expo-linking": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -449,3 +449,3 @@ "cliPush": true,

"expo-local-authentication": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -457,3 +457,3 @@ "cliPush": true,

"expo-localization": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -465,3 +465,3 @@ "cliPush": true,

"expo-location": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -473,3 +473,3 @@ "cliPush": true,

"expo-mail-composer": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -481,3 +481,3 @@ "cliPush": true,

"expo-media-library": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -489,3 +489,3 @@ "cliPush": true,

"expo-notifications": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -497,3 +497,3 @@ "cliPush": true,

"expo-print": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -505,3 +505,3 @@ "cliPush": true,

"expo-screen-orientation": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -513,3 +513,3 @@ "cliPush": true,

"expo-secure-store": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -521,3 +521,3 @@ "cliPush": true,

"expo-sensors": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -529,3 +529,3 @@ "cliPush": true,

"expo-share-intent": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -537,3 +537,3 @@ "cliPush": true,

"expo-sharing": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -545,3 +545,3 @@ "cliPush": true,

"expo-speech": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -553,3 +553,3 @@ "cliPush": true,

"expo-splash-screen": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -561,3 +561,3 @@ "cliPush": true,

"expo-sqlite": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -569,3 +569,3 @@ "cliPush": true,

"expo-status-bar": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -577,3 +577,3 @@ "cliPush": true,

"expo-system-ui": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -585,3 +585,3 @@ "cliPush": true,

"expo-task-manager": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -593,3 +593,3 @@ "cliPush": true,

"expo-updates": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -601,3 +601,3 @@ "cliPush": true,

"expo-video": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -609,3 +609,3 @@ "cliPush": true,

"expo-video-thumbnails": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -617,3 +617,3 @@ "cliPush": true,

"expo-web-browser": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -625,3 +625,3 @@ "cliPush": true,

"lottie-react-native": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -633,3 +633,3 @@ "cliPush": true,

"react-native-audio-api": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -641,3 +641,3 @@ "cliPush": true,

"react-native-ble-plx": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -649,3 +649,3 @@ "cliPush": true,

"react-native-device-info": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -657,3 +657,3 @@ "cliPush": true,

"react-native-gesture-handler": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -665,3 +665,3 @@ "cliPush": true,

"react-native-get-random-values": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -673,3 +673,3 @@ "cliPush": true,

"react-native-iap": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -681,3 +681,3 @@ "cliPush": true,

"react-native-keyboard-controller": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -689,3 +689,3 @@ "cliPush": true,

"react-native-maps": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -697,3 +697,3 @@ "cliPush": true,

"react-native-mmkv": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -705,3 +705,3 @@ "cliPush": true,

"react-native-nitro-image": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -713,3 +713,3 @@ "cliPush": true,

"react-native-nitro-modules": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -721,3 +721,3 @@ "cliPush": true,

"react-native-pager-view": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -729,3 +729,3 @@ "cliPush": true,

"react-native-passkey": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -737,3 +737,3 @@ "cliPush": true,

"react-native-pdf": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -745,3 +745,3 @@ "cliPush": true,

"react-native-permissions": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -753,3 +753,3 @@ "cliPush": true,

"react-native-purchases": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -761,3 +761,3 @@ "cliPush": true,

"react-native-reanimated": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -769,3 +769,3 @@ "cliPush": true,

"react-native-safe-area-context": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -777,3 +777,3 @@ "cliPush": true,

"react-native-screens": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -785,3 +785,3 @@ "cliPush": true,

"react-native-share": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -793,3 +793,3 @@ "cliPush": true,

"react-native-svg": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -801,3 +801,3 @@ "cliPush": true,

"react-native-udp": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -809,3 +809,3 @@ "cliPush": true,

"react-native-video": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -817,3 +817,3 @@ "cliPush": true,

"react-native-view-shot": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -825,3 +825,3 @@ "cliPush": true,

"react-native-vision-camera": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -833,3 +833,3 @@ "cliPush": true,

"react-native-webview": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -841,3 +841,3 @@ "cliPush": true,

"react-native-worklets": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -849,3 +849,3 @@ "cliPush": true,

"whisper.rn": {
"version": "1.99.410",
"version": "1.99.415",
"hostApp": true,

@@ -852,0 +852,0 @@ "cliPush": true,

@@ -16,3 +16,6 @@ const fs = require('fs');

const DEFAULT_REPO = process.env.YAVER_AGENT_REPO || 'yaver-io/yaver.io';
const WINDOWS_REPO = process.env.YAVER_WINDOWS_AGENT_REPO || 'kivanccakmak/yaver-cli';
// Windows is released beside every other agent build in the canonical repo.
// The historical yaver-cli repo stopped at v1.37.0; resolving from it made a
// current npm wrapper silently install a years-old Windows agent.
const WINDOWS_REPO = process.env.YAVER_WINDOWS_AGENT_REPO || DEFAULT_REPO;
const CACHE_ROOT = process.env.YAVER_AGENT_CACHE_DIR || path.join(os.homedir(), '.yaver', 'bin');

@@ -19,0 +22,0 @@ let resolvedAgentVersionPromise = null;

@@ -11,2 +11,3 @@ const PACKAGE = require('../package.json');

const { feedback } = require('./commands/feedback');
const { desktop } = require('./commands/desktop');
const { deploy, isLocalDeployToken } = require('./commands/deploy');

@@ -55,2 +56,8 @@ const { run, isLocalRunToken } = require('./commands/run');

Optional desktop GUI (same account, agent, tasks, and remote-node state):
yaver desktop Open the installed native GUI
yaver desktop install Download, verify, and install it per-user
yaver desktop update Update from the latest verified GUI release
yaver desktop status Show whether and where the GUI is installed
Push-to-device commands:

@@ -222,2 +229,7 @@ yaver push Bundle + validate + push current RN/Expo project

if (command === 'desktop' || command === 'gui') {
await desktop(args.slice(1));
return;
}
if (command === 'run') {

@@ -224,0 +236,0 @@ // Local-handle `yaver run dev[:target]`. Anything else (future

@@ -11,6 +11,8 @@ #!/usr/bin/env node

const { ensureHermesc } = require("./hermesc-runtime");
const { execSync } = require("child_process");
const { execFileSync, execSync, spawnSync } = require("child_process");
const fs = require("fs");
const os = require("os");
const path = require("path");
const { desktop, installedDesktopCandidates } = require("./commands/desktop");
const { codingRunnerBootstrapPlan } = require("./runner-bootstrap-policy");

@@ -49,8 +51,6 @@ const CODING_RUNNER_BOOTSTRAP = [

function commandExists(name) {
try {
execSync(`command -v ${name}`, { stdio: ["ignore", "pipe", "ignore"] });
return true;
} catch (_) {
return false;
}
const probe = process.platform === "win32"
? spawnSync("where.exe", [name], { stdio: "ignore", windowsHide: true })
: spawnSync("/bin/sh", ["-c", `command -v ${name}`], { stdio: "ignore" });
return !probe.error && probe.status === 0;
}

@@ -61,5 +61,18 @@

if (!prefix) return "";
return path.join(prefix, "bin");
return process.platform === "win32" ? prefix : path.join(prefix, "bin");
}
function installGlobalNpmPackages(packages) {
const args = ["install", "-g", "--no-fund", "--no-audit", ...packages];
const npmExecPath = String(process.env.npm_execpath || "").trim();
if (npmExecPath && /\.[cm]?js$/i.test(npmExecPath)) {
execFileSync(process.execPath, [npmExecPath, ...args], { stdio: "inherit", windowsHide: true });
return;
}
execFileSync(process.platform === "win32" ? "npm.cmd" : "npm", args, {
stdio: "inherit",
windowsHide: true,
});
}
function addNpmGlobalBinToProcessPath() {

@@ -75,16 +88,13 @@ const binDir = npmGlobalBinDir();

function installMissingCodingRunners() {
const missing = CODING_RUNNER_BOOTSTRAP.filter((entry) => !commandExists(entry.command));
if (missing.length === 0) {
log("Claude Code, Codex, and OpenCode already exist on PATH.");
const plan = codingRunnerBootstrapPlan(CODING_RUNNER_BOOTSTRAP, commandExists);
if (plan.installed.length > 0) {
const labels = plan.installed.map((entry) => entry.label).join(", ");
log(`Using existing coding runner${plan.installed.length === 1 ? "" : "s"}: ${labels}. Other runners were not installed.`);
return;
}
const npmCmd = (process.env.npm_execpath || "npm").trim() || "npm";
const packages = missing.map((entry) => entry.pkg);
const labels = missing.map((entry) => entry.label).join(", ");
const packages = plan.toInstall.map((entry) => entry.pkg);
const labels = plan.toInstall.map((entry) => entry.label).join(", ");
try {
execSync(
`"${npmCmd}" install -g --no-fund --no-audit ${packages.join(" ")}`,
{ stdio: "inherit" },
);
installGlobalNpmPackages(packages);
addNpmGlobalBinToProcessPath();

@@ -118,2 +128,20 @@ log(`Installed missing coding runners: ${labels}.`);

function desktopBootstrapEligible() {
if (envEnabled("YAVER_SKIP_POSTINSTALL_DESKTOP")) return false;
if (envEnabled("CI") && !envEnabled("YAVER_FORCE_POSTINSTALL_DESKTOP")) return false;
if (installedDesktopCandidates().some((candidate) => fs.existsSync(candidate))) return false;
if (process.platform === "linux") return Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
return process.platform === "darwin" || process.platform === "win32";
}
async function installDesktopCompanion() {
if (!desktopBootstrapEligible()) return;
try {
await desktop(["install", "--no-open"]);
log("Installed the verified Yaver Desktop companion (set YAVER_SKIP_POSTINSTALL_DESKTOP=1 to opt out).");
} catch (error) {
log(`Skipping desktop companion bootstrap: ${error.message}`);
}
}
// ensureLinuxHermescBuildDeps installs the apt packages required to

@@ -522,2 +550,14 @@ // compile hermesc from facebook/hermes sources on linux/arm64 (no

if (process.platform === "win32") {
// Windows is a first-class Yaver node. The mobile/remote-runtime bootstrap
// below still has Unix-only recipes, but the three supported coding
// runners are ordinary npm globals and must not disappear merely because
// the install came from PowerShell.
if (!envEnabled("YAVER_SKIP_POSTINSTALL_RUNNERS")) {
installMissingCodingRunners();
await setupMCPForInstalledRunners();
}
await installDesktopCompanion();
return;
}
if (process.platform !== "linux" && process.platform !== "darwin") {

@@ -531,2 +571,3 @@ return;

}
await installDesktopCompanion();
return;

@@ -560,2 +601,4 @@ }

await installDesktopCompanion();
// Vibe Preview tool stack — best-effort provisioning so a fresh

@@ -562,0 +605,0 @@ // global npm install gives the user a working chromium-based frame