@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/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 r}from"node:url";import{spawnSync as w}from"node:child_process";import{constants as N,accessSync as f}from"node:fs";import{homedir as S}from"node:os";import{basename as y,delimiter as _,dirname as v,join as $}from"node:path";import{fileURLToPath as x}from"node:url";var W="rove",Y="kobe";var A="ROVE_INVOKED_AS";function V(z=process.env){return z[A]===W?W:Y}var U="ROVE_BUN",p="ROVE_NO_BUN_BOOTSTRAP",E=(z)=>{try{return f(z,N.X_OK),!0}catch{return!1}},m=(z)=>z==="win32"?"bun.exe":"bun";function d(z={}){let H=z.env??process.env,J=z.platform??process.platform,Z=z.home??H.HOME??H.USERPROFILE??S(),Q=m(J),X=[],G=H[U]?.trim();if(G)X.push(G);for(let L of(H.PATH??H.Path??"").split(_))if(L)X.push($(L,Q));let j=H.BUN_INSTALL?.trim();if(j)X.push($(j,"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 d(z).find((J)=>H(J))??null}function b(z){return v(x(z))}function B(z){return y(x(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=V(),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: ${U}=/path/to/bun`,""].join(`
3
- `)}function M(z=process.env,H=process.stdin,J=process.stdout){if(z[p]==="1")return!1;if(z.CI==="true"||z.CI==="1")return!1;return Boolean(H.isTTY&&J.isTTY)}function k(z={},H=w){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(K,z.signal)?K[z.signal]:0);return 1}var K={SIGINT:2,SIGQUIT:3,SIGKILL:9,SIGTERM:15};function C(z,H,J,Z=w){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 T=b(import.meta.url),P=B(import.meta.url),g=l(T,`${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 o(){let z={launcherDir:T},H=F(z);if(H)return H;if(!M())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 k(z)}if(typeof globalThis.Bun<"u")await import(r(g).href);else{let z=await o();if(!z)process.stderr.write(D(P)),process.exit(1);process.exit(C(z,g,process.argv.slice(2)))}
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 dirname2 } from "node:path";
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(join(explicit, COMPAT_STATE_DIR_BASENAME, "pty.sock"), explicit, "pty");
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(join(home, COMPAT_STATE_DIR_BASENAME, "pty.sock"), home, "pty");
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 join(homeDir, COMPAT_STATE_DIR_BASENAME, "pty.pid");
314
+ return runtimePath(homeDir, "pty.pid", "pty.pid");
248
315
  }
249
316
  function defaultPtyExitsPath(homeDir = readRoveEnv("HOME_DIR") ?? homedir()) {
250
- return join(homeDir, COMPAT_STATE_DIR_BASENAME, "pty-exits.json");
317
+ return runtimeDataPath(homeDir, "pty-exits.json");
251
318
  }
252
319
  function defaultPtyFreezeDir(homeDir = readRoveEnv("HOME_DIR") ?? homedir()) {
253
- return join(homeDir, COMPAT_STATE_DIR_BASENAME, "pty-sessions");
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(readFileSync(path, "utf8"));
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(dirname(path), { recursive: true });
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 readFileSync2, readdirSync, renameSync, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
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(readFileSync2(join2(dir, name), "utf8"));
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 ?? existsSync;
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 mkdir(dirname2(socketPath), { recursive: true });
1118
- await mkdir(dirname2(pidPath), { recursive: true });
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 unlink(socketPath).catch(() => {});
1158
- await unlink(pidPath).catch(() => {});
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;