@sma1lboy/kobe 0.8.188 → 0.8.190
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/index.js +428 -428
- package/dist/cli/kobe-run.js +428 -428
- package/dist/cli/kobe.js +3 -3
- package/dist/cli/pty-host-node.mjs +91 -19
- package/dist/cli/rove-run.js +428 -428
- package/dist/cli/rove.js +3 -3
- package/package.json +4 -3
package/dist/cli/kobe.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{join as l}from"node:path";import{createInterface as s}from"node:readline/promises";import{pathToFileURL as
|
|
3
|
-
`)}function
|
|
4
|
-
`),1;return u(Q)}var
|
|
2
|
+
import{join as l}from"node:path";import{createInterface as s}from"node:readline/promises";import{pathToFileURL as o}from"node:url";import{spawnSync as U}from"node:child_process";import{constants as f,accessSync as A}from"node:fs";import{homedir as y}from"node:os";import{basename as S,delimiter as _,dirname as p,join as $}from"node:path";import{fileURLToPath as w}from"node:url";var W="rove",Y="kobe";var N="ROVE_INVOKED_AS";function K(z=process.env){return z[N]===W?W:Y}var x="ROVE_BUN",v="ROVE_NO_BUN_BOOTSTRAP",E=(z)=>{try{return A(z,f.X_OK),!0}catch{return!1}},d=(z)=>z==="win32"?"bun.exe":"bun";function m(z={}){let H=z.env??process.env,J=z.platform??process.platform,Z=z.home??H.HOME??H.USERPROFILE??y(),Q=d(J),X=[],G=H[x]?.trim();if(G)X.push(G);for(let L of(H.PATH??H.Path??"").split(_))if(L)X.push($(L,Q));let V=H.BUN_INSTALL?.trim();if(V)X.push($(V,"bin",Q));if(Z)X.push($(Z,".bun","bin",Q));let q=z.launcherDir;if(q)X.push($(q,"..","..","node_modules","bun","bin",Q)),X.push($(q,"..","..","..","bun","bin",Q));return X}function F(z={}){let H=z.isExecutable??E;return m(z).find((J)=>H(J))??null}function b(z){return p(w(z))}function B(z){return S(w(z)).replace(/\.[cm]?[jt]s$/,"")}function c(z=process.platform){return z==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function D(z=K(),H=process.platform){let J=H==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${z}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${J}`," npm install -g bun # any platform, if you already have npm","","Or install Bun and Rove together in one step:"," curl -fsSL https://rove.sma1lboy.me/install.sh | sh","",`Already have Bun somewhere unusual? Point Rove at it: ${x}=/path/to/bun`,""].join(`
|
|
3
|
+
`)}function C(z=process.env,H=process.stdin,J=process.stdout){if(z[v]==="1")return!1;if(z.CI==="true"||z.CI==="1")return!1;return Boolean(H.isTTY&&J.isTTY)}function M(z={},H=U){let J=z.platform??process.platform,[Z,...Q]=c(J);if(!Z)return null;let X=H(Z,Q,{stdio:"inherit"});if(X.error||X.status!==0)return null;return F(z)}function u(z){if(typeof z.status==="number")return z.status;if(z.signal)return 128+(Object.hasOwn(j,z.signal)?j[z.signal]:0);return 1}var j={SIGINT:2,SIGQUIT:3,SIGKILL:9,SIGTERM:15};function k(z,H,J,Z=U){let Q=Z(z,[H,...J],{stdio:"inherit"});if(Q.error)return process.stderr.write(`rove: could not start Bun at ${z}: ${Q.error.message}
|
|
4
|
+
`),1;return u(Q)}var O=b(import.meta.url),P=B(import.meta.url),T=l(O,`${P}-run.js`);async function i(z){let H=s({input:process.stdin,output:process.stdout});try{let J=(await H.question(z)).trim().toLowerCase();return J===""||J==="y"||J==="yes"}finally{H.close()}}async function a(){let z={launcherDir:O},H=F(z);if(H)return H;if(!C())return null;let J=`${P}: Rove runs on the Bun runtime, and none is installed. Install Bun now? [Y/n] `;if(!await i(J))return null;return M(z)}if(typeof globalThis.Bun<"u")await import(o(T).href);else{let z=await a();if(!z)process.stderr.write(D(P)),process.exit(1);process.exit(k(z,T,process.argv.slice(2)))}
|
|
@@ -55,9 +55,9 @@ async function nodePtyDriver(spawn) {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// ../kobe-daemon/src/daemon/pty-server.ts
|
|
58
|
-
import { mkdir, unlink, writeFile } from "node:fs/promises";
|
|
58
|
+
import { mkdir as mkdir2, unlink as unlink2, writeFile } from "node:fs/promises";
|
|
59
59
|
import { createServer } from "node:net";
|
|
60
|
-
import { dirname as
|
|
60
|
+
import { dirname as dirname3 } from "node:path";
|
|
61
61
|
import { StringDecoder as StringDecoder3 } from "node:string_decoder";
|
|
62
62
|
|
|
63
63
|
// ../kobe-daemon/src/daemon/client-writer.ts
|
|
@@ -155,6 +155,26 @@ class ClientWriter {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
// ../kobe-daemon/src/daemon/compat-link.ts
|
|
159
|
+
import { lstat, mkdir, symlink, unlink } from "node:fs/promises";
|
|
160
|
+
import { dirname } from "node:path";
|
|
161
|
+
async function linkLegacyRuntimePath(canonical, legacy) {
|
|
162
|
+
if (canonical === legacy)
|
|
163
|
+
return false;
|
|
164
|
+
try {
|
|
165
|
+
const existing = await lstat(legacy).catch(() => null);
|
|
166
|
+
if (existing && !existing.isSymbolicLink())
|
|
167
|
+
return false;
|
|
168
|
+
if (existing)
|
|
169
|
+
await unlink(legacy).catch(() => {});
|
|
170
|
+
await mkdir(dirname(legacy), { recursive: true });
|
|
171
|
+
await symlink(canonical, legacy);
|
|
172
|
+
return true;
|
|
173
|
+
} catch {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
158
178
|
// ../kobe-daemon/src/daemon/crash-log.ts
|
|
159
179
|
function toError(err) {
|
|
160
180
|
if (err instanceof Error)
|
|
@@ -191,18 +211,61 @@ function requireString(payload, key) {
|
|
|
191
211
|
|
|
192
212
|
// ../kobe-daemon/src/daemon/paths.ts
|
|
193
213
|
import { createHash } from "node:crypto";
|
|
214
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
194
215
|
import { homedir, tmpdir } from "node:os";
|
|
195
216
|
import { join } from "node:path";
|
|
196
217
|
|
|
197
218
|
// ../kobe-daemon/src/compat-env.ts
|
|
198
219
|
var ROVE_ENV_PREFIX = "ROVE_";
|
|
199
220
|
var LEGACY_KOBE_ENV_PREFIX = "KOBE_";
|
|
221
|
+
var ROVE_STATE_DIR_BASENAME = ".rove";
|
|
200
222
|
var COMPAT_STATE_DIR_BASENAME = ".kobe";
|
|
201
223
|
function readRoveEnv(suffix, env = process.env) {
|
|
202
224
|
return env[`${ROVE_ENV_PREFIX}${suffix}`] ?? env[`${LEGACY_KOBE_ENV_PREFIX}${suffix}`];
|
|
203
225
|
}
|
|
204
226
|
|
|
205
227
|
// ../kobe-daemon/src/daemon/paths.ts
|
|
228
|
+
function stateDirs(homeDir) {
|
|
229
|
+
return { canonical: join(homeDir, ROVE_STATE_DIR_BASENAME), legacy: join(homeDir, COMPAT_STATE_DIR_BASENAME) };
|
|
230
|
+
}
|
|
231
|
+
function pidIsLive(pidPath) {
|
|
232
|
+
try {
|
|
233
|
+
const pid = Number.parseInt(readFileSync(pidPath, "utf8").trim(), 10);
|
|
234
|
+
if (!Number.isInteger(pid) || pid <= 1)
|
|
235
|
+
return false;
|
|
236
|
+
process.kill(pid, 0);
|
|
237
|
+
return true;
|
|
238
|
+
} catch {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function runtimePath(homeDir, name, pidName) {
|
|
243
|
+
const { canonical, legacy } = stateDirs(homeDir);
|
|
244
|
+
const canonicalPath = join(canonical, name);
|
|
245
|
+
if (existsSync(canonicalPath))
|
|
246
|
+
return canonicalPath;
|
|
247
|
+
const legacyPath = join(legacy, name);
|
|
248
|
+
if (existsSync(legacyPath) && pidIsLive(join(legacy, pidName)))
|
|
249
|
+
return legacyPath;
|
|
250
|
+
return canonicalPath;
|
|
251
|
+
}
|
|
252
|
+
function legacyRuntimePath(homeDir, name) {
|
|
253
|
+
return join(homeDir, COMPAT_STATE_DIR_BASENAME, name);
|
|
254
|
+
}
|
|
255
|
+
function legacyPtyHostSocketPath(homeDir) {
|
|
256
|
+
return legacyRuntimePath(homeDir, "pty.sock");
|
|
257
|
+
}
|
|
258
|
+
function legacyPtyHostPidPath(homeDir) {
|
|
259
|
+
return legacyRuntimePath(homeDir, "pty.pid");
|
|
260
|
+
}
|
|
261
|
+
function runtimeDataPath(homeDir, name) {
|
|
262
|
+
const { canonical, legacy } = stateDirs(homeDir);
|
|
263
|
+
const canonicalPath = join(canonical, name);
|
|
264
|
+
if (existsSync(canonicalPath))
|
|
265
|
+
return canonicalPath;
|
|
266
|
+
const legacyPath = join(legacy, name);
|
|
267
|
+
return existsSync(legacyPath) ? legacyPath : canonicalPath;
|
|
268
|
+
}
|
|
206
269
|
var SOCKET_PATH_SAFETY_LIMIT = 100;
|
|
207
270
|
function shortHomeTag(homeDir) {
|
|
208
271
|
return createHash("sha1").update(homeDir).digest("hex").slice(0, 8);
|
|
@@ -217,6 +280,10 @@ function fitSocketPath(naturalPath, homeDir, role, pidTag) {
|
|
|
217
280
|
return fallback;
|
|
218
281
|
throw new Error(`daemon socket path exceeds ${SOCKET_PATH_SAFETY_LIMIT} bytes even after fallback: ${fallback}`);
|
|
219
282
|
}
|
|
283
|
+
function resolveDaemonHomeDir(homeDir) {
|
|
284
|
+
const explicit = homeDir ?? readRoveEnv("HOME_DIR");
|
|
285
|
+
return explicit && explicit.length > 0 ? explicit : homedir();
|
|
286
|
+
}
|
|
220
287
|
function isWindowsPipePath(path) {
|
|
221
288
|
return path.startsWith("\\\\.\\pipe\\") || path.startsWith("//./pipe/");
|
|
222
289
|
}
|
|
@@ -231,26 +298,26 @@ function defaultPtyHostSocketPath(homeDir, platform = process.platform) {
|
|
|
231
298
|
if (platform === "win32")
|
|
232
299
|
return windowsPipePath(explicit || homedir(), "pty");
|
|
233
300
|
if (explicit && explicit.length > 0) {
|
|
234
|
-
return fitSocketPath(
|
|
301
|
+
return fitSocketPath(runtimePath(explicit, "pty.sock", "pty.pid"), explicit, "pty");
|
|
235
302
|
}
|
|
236
303
|
const runtimeDir = process.env.XDG_RUNTIME_DIR;
|
|
237
304
|
if (runtimeDir && runtimeDir.length > 0) {
|
|
238
305
|
return fitSocketPath(join(runtimeDir, "kobe-pty.sock"), runtimeDir, "pty");
|
|
239
306
|
}
|
|
240
307
|
const home = homedir();
|
|
241
|
-
return fitSocketPath(
|
|
308
|
+
return fitSocketPath(runtimePath(home, "pty.sock", "pty.pid"), home, "pty");
|
|
242
309
|
}
|
|
243
310
|
function defaultPtyHostPidPath(homeDir = readRoveEnv("HOME_DIR") ?? homedir()) {
|
|
244
311
|
const override = readRoveEnv("PTY_PID_PATH");
|
|
245
312
|
if (override && override.length > 0)
|
|
246
313
|
return override;
|
|
247
|
-
return
|
|
314
|
+
return runtimePath(homeDir, "pty.pid", "pty.pid");
|
|
248
315
|
}
|
|
249
316
|
function defaultPtyExitsPath(homeDir = readRoveEnv("HOME_DIR") ?? homedir()) {
|
|
250
|
-
return
|
|
317
|
+
return runtimeDataPath(homeDir, "pty-exits.json");
|
|
251
318
|
}
|
|
252
319
|
function defaultPtyFreezeDir(homeDir = readRoveEnv("HOME_DIR") ?? homedir()) {
|
|
253
|
-
return
|
|
320
|
+
return runtimeDataPath(homeDir, "pty-sessions");
|
|
254
321
|
}
|
|
255
322
|
// ../kobe-plugin-sdk/dist/contract.js
|
|
256
323
|
var DAEMON_CHANNELS = [
|
|
@@ -286,8 +353,8 @@ function frameToLine(frame) {
|
|
|
286
353
|
}
|
|
287
354
|
|
|
288
355
|
// ../kobe-daemon/src/daemon/pty-exit-store.ts
|
|
289
|
-
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
290
|
-
import { dirname } from "node:path";
|
|
356
|
+
import { mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
357
|
+
import { dirname as dirname2 } from "node:path";
|
|
291
358
|
var MAX_RECORDS = 50;
|
|
292
359
|
var TAIL_LINES = 40;
|
|
293
360
|
var TAIL_LINE_CHARS = 500;
|
|
@@ -303,7 +370,7 @@ function plainTail(raw) {
|
|
|
303
370
|
}
|
|
304
371
|
function readPtyExitRecords(path = defaultPtyExitsPath()) {
|
|
305
372
|
try {
|
|
306
|
-
const parsed = JSON.parse(
|
|
373
|
+
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
307
374
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
308
375
|
return {};
|
|
309
376
|
return parsed;
|
|
@@ -326,12 +393,12 @@ function recordPtyExit(info, path = defaultPtyExitsPath()) {
|
|
|
326
393
|
tail: plainTail(info.tail)
|
|
327
394
|
};
|
|
328
395
|
const newest = Object.values(records).sort((a, b) => a.at < b.at ? 1 : -1).slice(0, MAX_RECORDS);
|
|
329
|
-
mkdirSync(
|
|
396
|
+
mkdirSync(dirname2(path), { recursive: true });
|
|
330
397
|
writeFileSync(path, JSON.stringify(Object.fromEntries(newest.map((r) => [r.key, r])), null, 2), "utf8");
|
|
331
398
|
}
|
|
332
399
|
|
|
333
400
|
// ../kobe-daemon/src/daemon/pty-freeze-store.ts
|
|
334
|
-
import { mkdirSync as mkdirSync2, readFileSync as
|
|
401
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync, renameSync, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
335
402
|
import { join as join2 } from "node:path";
|
|
336
403
|
import { StringDecoder } from "node:string_decoder";
|
|
337
404
|
var FREEZE_VERSION = 1;
|
|
@@ -419,7 +486,7 @@ function loadFrozenSessions(dir = defaultPtyFreezeDir()) {
|
|
|
419
486
|
if (!name.endsWith(".json"))
|
|
420
487
|
continue;
|
|
421
488
|
try {
|
|
422
|
-
const record = parseRecord(
|
|
489
|
+
const record = parseRecord(readFileSync3(join2(dir, name), "utf8"));
|
|
423
490
|
if (record)
|
|
424
491
|
out.push(record);
|
|
425
492
|
} catch {}
|
|
@@ -451,7 +518,7 @@ function clearFrozenSessions(dir = defaultPtyFreezeDir()) {
|
|
|
451
518
|
}
|
|
452
519
|
|
|
453
520
|
// ../kobe-daemon/src/daemon/platform-shell.js
|
|
454
|
-
import { existsSync } from "node:fs";
|
|
521
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
455
522
|
function windowsBashCandidates(env) {
|
|
456
523
|
const roots = [env.ProgramFiles, env["ProgramFiles(x86)"], env.LOCALAPPDATA && `${env.LOCALAPPDATA}\\Programs`];
|
|
457
524
|
return roots.filter(Boolean).map((root) => `${root}\\Git\\bin\\bash.exe`);
|
|
@@ -465,7 +532,7 @@ function resolveLoginShell(options = {}) {
|
|
|
465
532
|
const fallback = options.fallback ?? "/bin/bash";
|
|
466
533
|
const platform = options.platform ?? process.platform;
|
|
467
534
|
const env = options.env ?? process.env;
|
|
468
|
-
const exists = options.exists ??
|
|
535
|
+
const exists = options.exists ?? existsSync2;
|
|
469
536
|
const cacheable = platform === process.platform && env === process.env && options.exists === undefined;
|
|
470
537
|
if (cacheable) {
|
|
471
538
|
const hit = cache.get(fallback);
|
|
@@ -1114,8 +1181,8 @@ async function startPtyHostServer(options = {}) {
|
|
|
1114
1181
|
ptys.restoreFrozen(loadFrozenSessions(freezeDir));
|
|
1115
1182
|
const pipeSocket = isWindowsPipePath(socketPath);
|
|
1116
1183
|
if (!pipeSocket)
|
|
1117
|
-
await
|
|
1118
|
-
await
|
|
1184
|
+
await mkdir2(dirname3(socketPath), { recursive: true });
|
|
1185
|
+
await mkdir2(dirname3(pidPath), { recursive: true });
|
|
1119
1186
|
const server = createServer((socket) => {
|
|
1120
1187
|
const client = {
|
|
1121
1188
|
socket,
|
|
@@ -1154,8 +1221,8 @@ async function startPtyHostServer(options = {}) {
|
|
|
1154
1221
|
client.socket.destroy();
|
|
1155
1222
|
await new Promise((resolve) => server.close(() => resolve()));
|
|
1156
1223
|
if (!pipeSocket)
|
|
1157
|
-
await
|
|
1158
|
-
await
|
|
1224
|
+
await unlink2(socketPath).catch(() => {});
|
|
1225
|
+
await unlink2(pidPath).catch(() => {});
|
|
1159
1226
|
}
|
|
1160
1227
|
};
|
|
1161
1228
|
async function stop() {
|
|
@@ -1264,6 +1331,11 @@ async function startPtyHostServer(options = {}) {
|
|
|
1264
1331
|
});
|
|
1265
1332
|
await writeFile(pidPath, `${process.pid}
|
|
1266
1333
|
`, "utf8");
|
|
1334
|
+
if (!pipeSocket) {
|
|
1335
|
+
const home = resolveDaemonHomeDir();
|
|
1336
|
+
await linkLegacyRuntimePath(socketPath, legacyPtyHostSocketPath(home));
|
|
1337
|
+
await linkLegacyRuntimePath(pidPath, legacyPtyHostPidPath(home));
|
|
1338
|
+
}
|
|
1267
1339
|
armIdle();
|
|
1268
1340
|
log("boot", `pty host listening on ${socketPath}`);
|
|
1269
1341
|
return api;
|