feat(cli): add Bun compiled binary runtime asset management

Introduce runtime path abstraction for Bun-compiled binaries that extracts
assets to ~/.happy/runtime/{version} instead of using project paths. This
enables proper distribution of CLI as a self-contained binary with embedded
tools (ripgrep, difftastic) and scripts that are extracted at runtime.
This commit is contained in:
weishu
2025-12-20 16:44:58 +08:00
parent 80725a2d34
commit f0493ce68d
11 changed files with 276 additions and 25 deletions
+3 -3
View File
@@ -5,7 +5,7 @@
import { spawn } from 'child_process';
import { join, resolve } from 'path';
import { platform, arch } from 'os';
import { projectPath } from '@/projectPath';
import { runtimePath } from '@/projectPath';
export interface DifftasticResult {
exitCode: number
@@ -23,7 +23,7 @@ export interface DifftasticOptions {
function getBinaryPath(): string {
const platformName = platform();
const binaryName = platformName === 'win32' ? 'difft.exe' : 'difft';
return resolve(join(projectPath(), 'tools', 'unpacked', binaryName));
return resolve(join(runtimePath(), 'tools', 'unpacked', binaryName));
}
/**
@@ -69,4 +69,4 @@ export function run(args: string[], options?: DifftasticOptions): Promise<Diffta
reject(err);
});
});
}
}
+2 -2
View File
@@ -4,7 +4,7 @@
import { spawn } from 'child_process';
import { join, resolve } from 'path';
import { projectPath } from '@/projectPath';
import { runtimePath } from '@/projectPath';
export interface RipgrepResult {
exitCode: number
@@ -17,7 +17,7 @@ export interface RipgrepOptions {
}
export function run(args: string[], options?: RipgrepOptions): Promise<RipgrepResult> {
const runnerPath = resolve(join(projectPath(), 'scripts', 'ripgrep_launcher.cjs'));
const runnerPath = resolve(join(runtimePath(), 'scripts', 'ripgrep_launcher.cjs'));
return new Promise((resolve, reject) => {
const child = spawn(process.execPath, [runnerPath, JSON.stringify(args)], {
stdio: ['pipe', 'pipe', 'pipe'],