Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@valyu/cli",
"version": "1.0.7",
"version": "1.0.8",
"description": "The search CLI for knowledge workers",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion skills/valyu-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ description: >
license: MIT
metadata:
author: valyu
version: "1.0.7"
version: "1.0.8"
homepage: https://valyu.ai
source: https://github.com/valyuAI/valyu-cli
inputs:
Expand Down
66 changes: 66 additions & 0 deletions src/__tests__/install-source.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

// The function under test depends on process.argv + process.execPath.
// We import fresh each test so any module-level caching (none today, but
// future-proof) doesn't leak between scenarios.
async function loadDetect() {
vi.resetModules();
const mod = await import('../lib/install-source.js');
return mod.detectInstallSource;
}

describe('detectInstallSource', () => {
let origArgv: string[];
let origExecPath: string;

beforeEach(() => {
origArgv = process.argv;
origExecPath = process.execPath;
});

afterEach(() => {
process.argv = origArgv;
Object.defineProperty(process, 'execPath', { value: origExecPath, configurable: true });
});

function setExec(path: string) {
Object.defineProperty(process, 'execPath', { value: path, configurable: true });
}

it('classifies a pkg-bundled Homebrew binary via process.execPath even when argv[1] is a /snapshot/ path', async () => {
setExec('/opt/homebrew/Cellar/valyu/1.0.6/bin/valyu');
process.argv = ['/opt/homebrew/Cellar/valyu/1.0.6/bin/valyu', '/snapshot/valyu-cli/dist/cli.cjs'];
const detect = await loadDetect();
const src = detect();
expect(src.kind).toBe('homebrew');
});

it('classifies a standalone user-local binary via process.execPath', async () => {
setExec('/Users/example/.local/bin/valyu');
process.argv = ['/Users/example/.local/bin/valyu', '/snapshot/valyu-cli/dist/cli.cjs'];
const detect = await loadDetect();
const src = detect();
expect(src.kind).toBe('binary');
if (src.kind === 'binary') expect(src.location).toBe('user-local');
});

it('classifies an npm global install via argv[1] (execPath is node, not valyu)', async () => {
setExec('/usr/local/bin/node');
process.argv = [
'/usr/local/bin/node',
'/usr/local/lib/node_modules/@valyu/cli/dist/cli.cjs',
];
const detect = await loadDetect();
const src = detect();
expect(src.kind).toBe('npm-global');
if (src.kind === 'npm-global') expect(src.manager).toBe('npm');
});

it('falls back to "unknown" for paths that do not match any known install', async () => {
setExec('/usr/local/bin/node');
process.argv = ['/usr/local/bin/node', '/some/random/place/cli.cjs'];
const detect = await loadDetect();
const src = detect();
expect(src.kind).toBe('unknown');
});
});
31 changes: 30 additions & 1 deletion src/lib/install-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,38 @@ export type InstallSource =
| { kind: 'dev'; path: string }
| { kind: 'unknown'; path: string };

// For `pkg`-compiled standalone binaries (Homebrew, the curl installer,
// the Windows PowerShell installer), `process.argv[1]` resolves to a
// virtual snapshot path like `/snapshot/valyu-cli/dist/cli.cjs` that
// lives inside the bundle - useless for install-source detection. The
// real binary path is `process.execPath` in that case.
//
// For Node-script invocations (npm global install, dev via tsx/node),
// `process.execPath` is just `node` itself, so the script path in
// `process.argv[1]` is what we want.
//
// Heuristic: if `process.execPath` has a `valyu`-shaped basename, we're
// running a compiled binary and should trust it. Otherwise fall back
// to argv[1].
function executablePath(): string {
const exe = process.execPath;
const exeLower = exe.toLowerCase();
const looksLikeCompiledBinary =
exeLower.endsWith('/valyu') ||
exeLower.endsWith('\\valyu.exe') ||
exeLower.endsWith('/valyu.exe') ||
/\/cellar\/valyu\//.test(exeLower);

if (looksLikeCompiledBinary) {
try {
return realpathSync(exe);
} catch {
return exe;
}
}

const script = process.argv[1];
if (!script) return process.execPath;
if (!script) return exe;
try {
return realpathSync(script);
} catch {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/version.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export const VERSION = '1.0.7';
export const VERSION = '1.0.8';
export const PACKAGE_NAME = '@valyu/cli';