@ogpoyraz/wtx 0.8.5 → 0.8.6
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/dist/cli.mjs +122 -13
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -32912,21 +32912,130 @@ function registerSkillCommand(program2) {
|
|
|
32912
32912
|
}
|
|
32913
32913
|
|
|
32914
32914
|
// src/commands/terminal.ts
|
|
32915
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
32916
|
+
import fs33 from "node:fs";
|
|
32917
|
+
import path37 from "node:path";
|
|
32918
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
32919
|
+
function findEntry() {
|
|
32920
|
+
const candidates = [];
|
|
32921
|
+
if (process.argv[1])
|
|
32922
|
+
candidates.push(process.argv[1]);
|
|
32923
|
+
try {
|
|
32924
|
+
const thisPath = fileURLToPath4(import.meta.url);
|
|
32925
|
+
candidates.push(thisPath);
|
|
32926
|
+
candidates.push(path37.resolve(path37.dirname(thisPath), "../../dist/cli.mjs"));
|
|
32927
|
+
candidates.push(path37.resolve(path37.dirname(thisPath), "../cli.mjs"));
|
|
32928
|
+
} catch {}
|
|
32929
|
+
for (const p of candidates) {
|
|
32930
|
+
try {
|
|
32931
|
+
if (p.endsWith(".mjs") || p.endsWith(".js")) {
|
|
32932
|
+
if (fs33.existsSync(p) && fs33.statSync(p).isFile())
|
|
32933
|
+
return p;
|
|
32934
|
+
} else if (fs33.existsSync(p)) {
|
|
32935
|
+
const stat = fs33.statSync(p);
|
|
32936
|
+
if (stat.isFile()) {
|
|
32937
|
+
const head = fs33.readFileSync(p, "utf8").slice(0, 1024);
|
|
32938
|
+
if (head.includes("cli.mjs") || head.includes("#!/usr/bin/env node")) {
|
|
32939
|
+
if (p.endsWith("wtx") || p.endsWith("cli.mjs")) {
|
|
32940
|
+
const dir = path37.dirname(fs33.realpathSync(p));
|
|
32941
|
+
const cli = path37.join(dir, "cli.mjs");
|
|
32942
|
+
if (fs33.existsSync(cli))
|
|
32943
|
+
return cli;
|
|
32944
|
+
const cli2 = path37.resolve(dir, "../dist/cli.mjs");
|
|
32945
|
+
if (fs33.existsSync(cli2))
|
|
32946
|
+
return cli2;
|
|
32947
|
+
if (head.includes("import") || head.includes("commander"))
|
|
32948
|
+
return p;
|
|
32949
|
+
}
|
|
32950
|
+
}
|
|
32951
|
+
}
|
|
32952
|
+
}
|
|
32953
|
+
} catch {}
|
|
32954
|
+
}
|
|
32955
|
+
try {
|
|
32956
|
+
const thisPath = fileURLToPath4(import.meta.url);
|
|
32957
|
+
const pkgRoot = path37.resolve(path37.dirname(thisPath), "../..");
|
|
32958
|
+
const cli = path37.join(pkgRoot, "dist", "cli.mjs");
|
|
32959
|
+
if (fs33.existsSync(cli))
|
|
32960
|
+
return cli;
|
|
32961
|
+
} catch {}
|
|
32962
|
+
return null;
|
|
32963
|
+
}
|
|
32964
|
+
function tryRelaunchViaBun(forwardedArgs) {
|
|
32965
|
+
if (process.env.WTX_BUN_RERUN === "1")
|
|
32966
|
+
return null;
|
|
32967
|
+
const env2 = { ...process.env, WTX_BUN_RERUN: "1" };
|
|
32968
|
+
const entry = findEntry();
|
|
32969
|
+
if (entry) {
|
|
32970
|
+
const result = spawnSync3("bun", [entry, ...forwardedArgs], {
|
|
32971
|
+
stdio: "inherit",
|
|
32972
|
+
env: env2
|
|
32973
|
+
});
|
|
32974
|
+
if (!result.error) {
|
|
32975
|
+
process.exit(result.status ?? 0);
|
|
32976
|
+
}
|
|
32977
|
+
if (result.error.code !== "ENOENT") {
|
|
32978
|
+
process.stderr.write(`✗ Failed to relaunch via Bun: ${result.error.message}
|
|
32979
|
+
`);
|
|
32980
|
+
process.exit(1);
|
|
32981
|
+
}
|
|
32982
|
+
}
|
|
32983
|
+
const attempts = [
|
|
32984
|
+
{ cmd: "bunx", args: ["--bun", "wtx", ...forwardedArgs] },
|
|
32985
|
+
{ cmd: "bun", args: ["x", "--bun", "wtx", ...forwardedArgs] }
|
|
32986
|
+
];
|
|
32987
|
+
for (const { cmd, args } of attempts) {
|
|
32988
|
+
const result = spawnSync3(cmd, args, { stdio: "inherit", env: env2 });
|
|
32989
|
+
if (!result.error) {
|
|
32990
|
+
process.exit(result.status ?? 0);
|
|
32991
|
+
}
|
|
32992
|
+
if (result.error.code !== "ENOENT") {
|
|
32993
|
+
process.stderr.write(`✗ Failed to relaunch via ${cmd}: ${result.error.message}
|
|
32994
|
+
`);
|
|
32995
|
+
process.exit(1);
|
|
32996
|
+
}
|
|
32997
|
+
}
|
|
32998
|
+
return null;
|
|
32999
|
+
}
|
|
32915
33000
|
function registerTerminalCommand(program2) {
|
|
32916
33001
|
program2.command("terminal").description("Interactive worktree dashboard (requires Bun)").action(async () => {
|
|
32917
33002
|
const opts = program2.optsWithGlobals();
|
|
32918
33003
|
if (typeof Bun === "undefined") {
|
|
32919
|
-
process.
|
|
33004
|
+
const forwarded = process.argv.slice(2);
|
|
33005
|
+
const relaunched = tryRelaunchViaBun(forwarded);
|
|
33006
|
+
if (relaunched === null) {
|
|
33007
|
+
const probe2 = spawnSync3("bun", ["--version"], { stdio: "ignore" });
|
|
33008
|
+
const hasBun = !probe2.error && probe2.status === 0;
|
|
33009
|
+
if (!hasBun) {
|
|
33010
|
+
process.stderr.write(`✗ wtx terminal dashboard requires the Bun runtime
|
|
32920
33011
|
`);
|
|
32921
|
-
|
|
33012
|
+
process.stderr.write(` The TUI relies on Bun's FFI and React renderer which cannot run in Node/compiled binary.
|
|
32922
33013
|
`);
|
|
32923
|
-
|
|
33014
|
+
process.stderr.write(` Bun was not found on your PATH. Install it from https://bun.sh, then run:
|
|
32924
33015
|
`);
|
|
32925
|
-
|
|
33016
|
+
process.stderr.write(` wtx terminal
|
|
32926
33017
|
|
|
32927
33018
|
`);
|
|
32928
|
-
|
|
32929
|
-
|
|
33019
|
+
process.stderr.write(" Note: `wtx ls` provides a fast list view and works everywhere.\n");
|
|
33020
|
+
process.exit(1);
|
|
33021
|
+
}
|
|
33022
|
+
process.stderr.write(`✗ wtx terminal dashboard requires the Bun runtime
|
|
33023
|
+
`);
|
|
33024
|
+
process.stderr.write(` The TUI relies on Bun's FFI and React renderer which cannot run in Node/compiled binary.
|
|
33025
|
+
`);
|
|
33026
|
+
process.stderr.write(` Automatic relaunch via Bun failed. Try running directly:
|
|
33027
|
+
`);
|
|
33028
|
+
process.stderr.write(` bunx --bun wtx terminal
|
|
33029
|
+
`);
|
|
33030
|
+
const entry = findEntry();
|
|
33031
|
+
if (entry) {
|
|
33032
|
+
process.stderr.write(` bun ${entry} terminal
|
|
33033
|
+
`);
|
|
33034
|
+
}
|
|
33035
|
+
process.stderr.write("\n Note: `wtx ls` provides a fast list view and works everywhere.\n");
|
|
33036
|
+
process.exit(1);
|
|
33037
|
+
}
|
|
33038
|
+
return;
|
|
32930
33039
|
}
|
|
32931
33040
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
32932
33041
|
process.stderr.write(`✗ wtx terminal requires an interactive terminal
|
|
@@ -32947,7 +33056,7 @@ init_deps();
|
|
|
32947
33056
|
import readline3 from "readline";
|
|
32948
33057
|
init_path_safety();
|
|
32949
33058
|
init_stack();
|
|
32950
|
-
import
|
|
33059
|
+
import fs34 from "fs";
|
|
32951
33060
|
async function runMcpServer(opts = {}) {
|
|
32952
33061
|
const input = opts.input ?? process.stdin;
|
|
32953
33062
|
const output = opts.output ?? process.stdout;
|
|
@@ -33130,7 +33239,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
33130
33239
|
for (const wt of wts) {
|
|
33131
33240
|
if (!wt.path.startsWith(repo.wtRoot))
|
|
33132
33241
|
continue;
|
|
33133
|
-
const dirtyCount =
|
|
33242
|
+
const dirtyCount = fs34.existsSync(wt.path) ? (await getDirtyFiles(wt.path)).length : 0;
|
|
33134
33243
|
items.push({
|
|
33135
33244
|
repo: repo.name,
|
|
33136
33245
|
branch: wt.branch || null,
|
|
@@ -33158,7 +33267,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
33158
33267
|
}
|
|
33159
33268
|
const repo = resolveRepos(config2, [args.repo])[0];
|
|
33160
33269
|
const wtPath = getWorktreePath(repo, args.branch);
|
|
33161
|
-
if (!
|
|
33270
|
+
if (!fs34.existsSync(wtPath)) {
|
|
33162
33271
|
throw { isToolError: true, message: `Worktree not found for branch ${args.branch}` };
|
|
33163
33272
|
}
|
|
33164
33273
|
const mainBranch = await resolveMainBranch(repo, config2);
|
|
@@ -33277,7 +33386,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
33277
33386
|
if (children.length > 0 && args.force !== true) {
|
|
33278
33387
|
throw { isToolError: true, message: `Branch has dependent worktrees: ${children.join(", ")}. Use force:true to override.` };
|
|
33279
33388
|
}
|
|
33280
|
-
if (!args.force &&
|
|
33389
|
+
if (!args.force && fs34.existsSync(wtPath)) {
|
|
33281
33390
|
const dirty = await getDirtyFiles(wtPath);
|
|
33282
33391
|
if (dirty.length > 0) {
|
|
33283
33392
|
throw { isToolError: true, message: `Worktree is dirty. Use force:true to remove it.` };
|
|
@@ -33296,7 +33405,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
33296
33405
|
}
|
|
33297
33406
|
const repo = resolveRepos(config2, [args.repo])[0];
|
|
33298
33407
|
const wtPath = getWorktreePath(repo, args.branch);
|
|
33299
|
-
if (!
|
|
33408
|
+
if (!fs34.existsSync(wtPath)) {
|
|
33300
33409
|
throw { isToolError: true, message: `Worktree not found for branch ${args.branch}` };
|
|
33301
33410
|
}
|
|
33302
33411
|
const mainBranch = await resolveMainBranch(repo, config2);
|
|
@@ -33518,7 +33627,7 @@ init_config();
|
|
|
33518
33627
|
init_resolver();
|
|
33519
33628
|
init_log();
|
|
33520
33629
|
init_history();
|
|
33521
|
-
import
|
|
33630
|
+
import fs35 from "fs";
|
|
33522
33631
|
var program2 = new Command;
|
|
33523
33632
|
program2.name("wtx").description("Multi-repo git worktree manager").version(VERSION).option("-q, --quiet", "Suppress progress indicators", false).option("--verbose", "Show git commands as they run", false).option("--dry-run", "Show what would happen", false);
|
|
33524
33633
|
var MUTATING_COMMANDS = new Set([
|
|
@@ -33622,7 +33731,7 @@ program2.command("_resolve-path <repo> <branch>", { hidden: true }).description(
|
|
|
33622
33731
|
}
|
|
33623
33732
|
const repo = repos[0];
|
|
33624
33733
|
const wtPath = getWorktreePath(repo, branch);
|
|
33625
|
-
if (!
|
|
33734
|
+
if (!fs35.existsSync(wtPath)) {
|
|
33626
33735
|
process.stderr.write(`✗ No worktree at ${wtPath}
|
|
33627
33736
|
`);
|
|
33628
33737
|
process.exit(1);
|