@persistmemory/cli 0.5.0 → 0.6.0

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/index.js CHANGED
@@ -342,7 +342,7 @@ var SignalFired = class extends Error {
342
342
  };
343
343
  function untilAborted(work, signal) {
344
344
  work.catch(() => void 0);
345
- return new Promise((resolve9, reject) => {
345
+ return new Promise((resolve8, reject) => {
346
346
  if (signal.aborted) {
347
347
  reject(new SignalFired());
348
348
  return;
@@ -352,7 +352,7 @@ function untilAborted(work, signal) {
352
352
  work.then(
353
353
  (value) => {
354
354
  signal.removeEventListener("abort", onAbort);
355
- resolve9(value);
355
+ resolve8(value);
356
356
  },
357
357
  (error) => {
358
358
  signal.removeEventListener("abort", onAbort);
@@ -362,14 +362,14 @@ function untilAborted(work, signal) {
362
362
  });
363
363
  }
364
364
  function defaultSleep(ms, signal) {
365
- return new Promise((resolve9, reject) => {
365
+ return new Promise((resolve8, reject) => {
366
366
  if (signal?.aborted) {
367
367
  reject(new AbortError());
368
368
  return;
369
369
  }
370
370
  const timer = setTimeout(() => {
371
371
  signal?.removeEventListener("abort", onAbort);
372
- resolve9();
372
+ resolve8();
373
373
  }, ms);
374
374
  function onAbort() {
375
375
  clearTimeout(timer);
@@ -1402,7 +1402,7 @@ function shortDate(iso) {
1402
1402
  }
1403
1403
 
1404
1404
  // src/help.ts
1405
- var VERSION = true ? "0.5.0" : versionFromManifest();
1405
+ var VERSION = true ? "0.6.0" : versionFromManifest();
1406
1406
  var PACKAGE = "@persistmemory/cli";
1407
1407
  var HELP = `
1408
1408
  pm \u2014 PersistMemory from your terminal
@@ -1445,23 +1445,17 @@ var HELP = `
1445
1445
  remember --file <path> capture a file's contents
1446
1446
 
1447
1447
  agent answer file and command requests from this
1448
- machine. Reads the folders in your home
1449
- directory \u2014 never anything hidden \u2014 and
1450
- nothing outside them. It says which ones
1451
- when it starts. Stays in the foreground;
1452
- background it and stop it later with:
1448
+ machine. Reads anywhere on it \u2014 you
1449
+ approve every request first, and see the
1450
+ exact path or command before you do.
1451
+ Stays in the foreground; background it
1452
+ and stop it later with:
1453
1453
  nohup pm agent > ~/agent.log 2>&1 &
1454
1454
  pkill -f "pm agent"
1455
- agent --root <dir> [--root ...] choose the folders for this run
1455
+ agent --root <dir> [--root ...] narrow it to these folders, for this run
1456
1456
 
1457
- Settings live in ~/.persistmemory/agent.json, and apply every time:
1458
-
1459
- {
1460
- "roots": ["~/code", "~/Documents"],
1461
- "mode": "ask", ask | auto-read | plan
1462
- "allow": ["swift"], programs this machine treats as reads
1463
- "deny": ["rm"] programs it refuses, whatever is approved
1464
- }
1457
+ A command that reaches the network, or that runs a language, is refused by
1458
+ this machine whatever anybody approves.
1465
1459
 
1466
1460
  search <query> search your memory
1467
1461
  list memories the most recent memories
@@ -1620,8 +1614,8 @@ async function startLoopback(options = {}) {
1620
1614
  const timeoutMs = options.timeoutMs ?? 5 * 60 * 1e3;
1621
1615
  let resolveCallback;
1622
1616
  let rejectCallback;
1623
- const received = new Promise((resolve9, reject) => {
1624
- resolveCallback = resolve9;
1617
+ const received = new Promise((resolve8, reject) => {
1618
+ resolveCallback = resolve8;
1625
1619
  rejectCallback = reject;
1626
1620
  });
1627
1621
  const server = createServer((request, response) => {
@@ -1657,9 +1651,9 @@ async function startLoopback(options = {}) {
1657
1651
  response.end(donePage(callback));
1658
1652
  resolveCallback?.(callback);
1659
1653
  });
1660
- await new Promise((resolve9, reject) => {
1654
+ await new Promise((resolve8, reject) => {
1661
1655
  server.once("error", reject);
1662
- server.listen(0, "127.0.0.1", resolve9);
1656
+ server.listen(0, "127.0.0.1", resolve8);
1663
1657
  });
1664
1658
  const address = server.address();
1665
1659
  if (address === null || typeof address === "string") {
@@ -1923,7 +1917,7 @@ function safeEqual(a, b) {
1923
1917
  }
1924
1918
  async function openBrowser(url) {
1925
1919
  const [command, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
1926
- await new Promise((resolve9, reject) => {
1920
+ await new Promise((resolve8, reject) => {
1927
1921
  const child = spawn(command, args, {
1928
1922
  stdio: "ignore",
1929
1923
  // Detached so closing the terminal does not close the browser, and so
@@ -1932,7 +1926,7 @@ async function openBrowser(url) {
1932
1926
  });
1933
1927
  child.once("error", reject);
1934
1928
  child.unref();
1935
- resolve9();
1929
+ resolve8();
1936
1930
  });
1937
1931
  }
1938
1932
  async function describe(response) {
@@ -1994,16 +1988,16 @@ async function currentCredential(resolved, deps) {
1994
1988
  // src/context.ts
1995
1989
  import { createInterface } from "node:readline";
1996
1990
  async function askOnTty(prompt, input = process.stdin, output = process.stdout) {
1997
- return new Promise((resolve9) => {
1991
+ return new Promise((resolve8) => {
1998
1992
  const readline = createInterface({ input, output });
1999
1993
  let answered = false;
2000
1994
  readline.question(prompt, (answer3) => {
2001
1995
  answered = true;
2002
- resolve9(answer3.trim());
1996
+ resolve8(answer3.trim());
2003
1997
  readline.close();
2004
1998
  });
2005
1999
  readline.once("close", () => {
2006
- if (!answered) resolve9("");
2000
+ if (!answered) resolve8("");
2007
2001
  });
2008
2002
  });
2009
2003
  }
@@ -2013,16 +2007,16 @@ var BACKSPACE = "\b";
2013
2007
  async function readSecretFromTty(prompt) {
2014
2008
  const input = process.stdin;
2015
2009
  if (!input.isTTY) {
2016
- return new Promise((resolve9) => {
2010
+ return new Promise((resolve8) => {
2017
2011
  const readline = createInterface({ input });
2018
2012
  let answered = false;
2019
2013
  readline.once("line", (line) => {
2020
2014
  answered = true;
2021
- resolve9(line.trim());
2015
+ resolve8(line.trim());
2022
2016
  readline.close();
2023
2017
  });
2024
2018
  readline.once("close", () => {
2025
- if (!answered) resolve9("");
2019
+ if (!answered) resolve8("");
2026
2020
  });
2027
2021
  });
2028
2022
  }
@@ -2031,14 +2025,14 @@ async function readSecretFromTty(prompt) {
2031
2025
  input.setRawMode?.(true);
2032
2026
  input.resume();
2033
2027
  input.setEncoding("utf8");
2034
- return new Promise((resolve9) => {
2028
+ return new Promise((resolve8) => {
2035
2029
  let value = "";
2036
2030
  const finish2 = () => {
2037
2031
  input.removeListener("data", onData);
2038
2032
  input.setRawMode?.(previouslyRaw);
2039
2033
  input.pause();
2040
2034
  process.stdout.write("\n");
2041
- resolve9(value.trim());
2035
+ resolve8(value.trim());
2042
2036
  };
2043
2037
  const onData = (chunk) => {
2044
2038
  for (const character of chunk) {
@@ -2074,9 +2068,9 @@ async function readStdin() {
2074
2068
 
2075
2069
  // src/commands/agent.ts
2076
2070
  import { hostname } from "node:os";
2077
- import { homedir as homedir3 } from "node:os";
2078
- import { basename, join as join6, resolve as resolve4 } from "node:path";
2079
- import { existsSync as existsSync6, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
2071
+ import { homedir as homedir2 } from "node:os";
2072
+ import { basename, join as join5, resolve as resolve3 } from "node:path";
2073
+ import { existsSync as existsSync5, readFileSync as readFileSync5, readdirSync, statSync as statSync3, writeFileSync as writeFileSync4 } from "node:fs";
2080
2074
 
2081
2075
  // src/files.ts
2082
2076
  import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync, statSync, writeFileSync as writeFileSync3 } from "node:fs";
@@ -2374,7 +2368,7 @@ async function runCommand(argv, policy) {
2374
2368
  } catch {
2375
2369
  return { ok: false, text: `${cwd} does not exist.` };
2376
2370
  }
2377
- return new Promise((resolve9) => {
2371
+ return new Promise((resolve8) => {
2378
2372
  const child = spawn2(argv[0], argv.slice(1), {
2379
2373
  cwd,
2380
2374
  // NO shell. With one, every character a model can produce is a character
@@ -2409,7 +2403,7 @@ async function runCommand(argv, policy) {
2409
2403
  const timer = setTimeout(() => child.kill("SIGKILL"), TIMEOUT_MS);
2410
2404
  child.on("error", (error) => {
2411
2405
  clearTimeout(timer);
2412
- resolve9({ ok: false, text: `Could not run it: ${error.message}` });
2406
+ resolve8({ ok: false, text: `Could not run it: ${error.message}` });
2413
2407
  });
2414
2408
  child.on("close", (code) => {
2415
2409
  clearTimeout(timer);
@@ -2421,98 +2415,13 @@ async function runCommand(argv, policy) {
2421
2415
 
2422
2416
  [exit code ${code}]` : ""
2423
2417
  ].join("");
2424
- resolve9({ ok: code === 0, text: `$ ${describe2(argv)}
2418
+ resolve8({ ok: code === 0, text: `$ ${describe2(argv)}
2425
2419
 
2426
2420
  ${output}${notes}` });
2427
2421
  });
2428
2422
  });
2429
2423
  }
2430
2424
 
2431
- // src/commands/agent-config.ts
2432
- import { existsSync as existsSync5, readFileSync as readFileSync5, readdirSync, statSync as statSync3 } from "node:fs";
2433
- import { homedir as homedir2 } from "node:os";
2434
- import { join as join5, resolve as resolve3 } from "node:path";
2435
- var NOT_MATERIAL = /* @__PURE__ */ new Set([
2436
- "Library",
2437
- "Applications",
2438
- "System",
2439
- "Public",
2440
- "node_modules",
2441
- "go",
2442
- "Parallels",
2443
- "VirtualBox VMs"
2444
- ]);
2445
- function discoverRoots(home = homedir2(), list = (path) => {
2446
- try {
2447
- return readdirSync(path);
2448
- } catch {
2449
- return [];
2450
- }
2451
- }, isDirectory = (path) => {
2452
- try {
2453
- return statSync3(path).isDirectory();
2454
- } catch {
2455
- return false;
2456
- }
2457
- }) {
2458
- return list(home).filter((name) => !name.startsWith(".")).filter((name) => !NOT_MATERIAL.has(name)).map((name) => join5(home, name)).filter(isDirectory).sort();
2459
- }
2460
- function expandHome(path, home = homedir2()) {
2461
- return path.startsWith("~") ? resolve3(home, path.slice(1).replace(/^[/\\]/, "")) : resolve3(path);
2462
- }
2463
- var MODES = /* @__PURE__ */ new Set(["ask", "auto-read", "plan"]);
2464
- function readAgentConfig(path, read2 = (at) => readFileSync5(at, "utf8"), exists = (at) => existsSync5(at), home = homedir2()) {
2465
- if (!exists(path)) return {};
2466
- let parsed;
2467
- try {
2468
- parsed = JSON.parse(read2(path));
2469
- } catch (error) {
2470
- return { error: `${path} is not valid JSON: ${error instanceof Error ? error.message : ""}` };
2471
- }
2472
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
2473
- return { error: `${path} should hold an object, like {"roots": ["~/code"]}.` };
2474
- }
2475
- const held = parsed;
2476
- const config = {};
2477
- if (held["roots"] !== void 0) {
2478
- if (!Array.isArray(held["roots"]) || held["roots"].some((one) => typeof one !== "string")) {
2479
- return { error: `${path}: "roots" should be a list of folders.` };
2480
- }
2481
- config.roots = held["roots"].map((one) => expandHome(one, home));
2482
- }
2483
- if (held["mode"] !== void 0) {
2484
- if (typeof held["mode"] !== "string" || !MODES.has(held["mode"])) {
2485
- return { error: `${path}: "mode" should be "ask", "auto-read" or "plan".` };
2486
- }
2487
- config.mode = held["mode"];
2488
- }
2489
- for (const key of ["allow", "deny"]) {
2490
- if (held[key] === void 0) continue;
2491
- if (!Array.isArray(held[key]) || held[key].some((one) => typeof one !== "string")) {
2492
- return { error: `${path}: "${key}" should be a list of program names.` };
2493
- }
2494
- config[key] = held[key];
2495
- }
2496
- return { config };
2497
- }
2498
- function resolveAgentConfig(args) {
2499
- const roots = args.flagRoots && args.flagRoots.length > 0 ? args.flagRoots : args.stored?.roots && args.stored.roots.length > 0 ? args.stored.roots : args.discovered ?? [];
2500
- return {
2501
- roots,
2502
- /*
2503
- `ask` unless the owner said otherwise.
2504
-
2505
- The mode decides how much happens with nobody watching, so the default
2506
- is the one that does least. `auto-read` is a reasonable thing to choose
2507
- and an unreasonable thing to be given.
2508
- */
2509
- mode: args.stored?.mode ?? "ask",
2510
- allow: args.stored?.allow ?? [],
2511
- deny: args.stored?.deny ?? [],
2512
- source: args.flagRoots && args.flagRoots.length > 0 ? "flags" : args.stored?.roots && args.stored.roots.length > 0 ? "config" : "discovered"
2513
- };
2514
- }
2515
-
2516
2425
  // src/commands/agent.ts
2517
2426
  async function said(response, fallback) {
2518
2427
  const body = await response.json().catch(() => void 0);
@@ -2520,7 +2429,7 @@ async function said(response, fallback) {
2520
2429
  return message2 ?? `${fallback} (${response.status})`;
2521
2430
  }
2522
2431
  function locate(roots, requested) {
2523
- const expanded = requested.startsWith("~") ? resolve4(homedir3(), requested.slice(1).replace(/^[/\\]/, "")) : requested;
2432
+ const expanded = requested.startsWith("~") ? resolve3(homedir2(), requested.slice(1).replace(/^[/\\]/, "")) : requested;
2524
2433
  if (!expanded.includes("/") && !expanded.includes("\\")) {
2525
2434
  const wanted2 = expanded.trim().toLowerCase();
2526
2435
  const named = roots.find((root) => basename(root).toLowerCase() === wanted2);
@@ -2536,29 +2445,23 @@ function locate(roots, requested) {
2536
2445
  throw new Error(`${requested} is not inside any allowed folder (${roots.join(", ")})`);
2537
2446
  }
2538
2447
  function uncontested(target) {
2539
- if (!existsSync6(target)) return target;
2448
+ if (!existsSync5(target)) return target;
2540
2449
  const dot = target.lastIndexOf(".");
2541
2450
  const stem = dot > target.lastIndexOf("/") && dot !== -1 ? target.slice(0, dot) : target;
2542
2451
  const extension = stem === target ? "" : target.slice(dot);
2543
2452
  for (let n = 1; n < 1e3; n += 1) {
2544
2453
  const candidate = `${stem} (${n})${extension}`;
2545
- if (!existsSync6(candidate)) return candidate;
2454
+ if (!existsSync5(candidate)) return candidate;
2546
2455
  }
2547
2456
  throw new Error(`${target} and a thousand names beside it are taken.`);
2548
2457
  }
2549
- async function answer(context, apiUrl, token, settings, request) {
2550
- const roots = settings.roots;
2458
+ async function answer(context, apiUrl, token, roots, request) {
2551
2459
  let located;
2552
2460
  if (request.kind === "run_command") {
2553
2461
  if (!request.argv || request.argv.length === 0) {
2554
2462
  return { ok: false, error: "No command was given." };
2555
2463
  }
2556
- const policy = {
2557
- mode: settings.mode,
2558
- allow: settings.allow,
2559
- deny: settings.deny,
2560
- roots
2561
- };
2464
+ const policy = { mode: "ask", allow: [], deny: [], roots };
2562
2465
  const outcome = await runCommand(request.argv, policy);
2563
2466
  if (!outcome.ok) return { ok: false, error: outcome.text };
2564
2467
  return upload(
@@ -2588,10 +2491,10 @@ async function answer(context, apiUrl, token, settings, request) {
2588
2491
  }
2589
2492
  try {
2590
2493
  let target = located;
2591
- if (existsSync6(located) && statSync4(located).isDirectory()) {
2494
+ if (existsSync5(located) && statSync3(located).isDirectory()) {
2592
2495
  const disposition = fetched.headers.get("content-disposition") ?? "";
2593
2496
  const named = /filename="([^"]+)"/.exec(disposition)?.[1];
2594
- target = join6(located, basename(named ?? "file"));
2497
+ target = join5(located, basename(named ?? "file"));
2595
2498
  }
2596
2499
  target = uncontested(target);
2597
2500
  writeFileSync4(target, downloaded, { flag: "wx" });
@@ -2614,12 +2517,12 @@ ${downloaded.length} bytes
2614
2517
  let filename = request.path.split("/").pop() ?? "file";
2615
2518
  if (request.kind === "list_dir") {
2616
2519
  try {
2617
- const stats = statSync4(located);
2520
+ const stats = statSync3(located);
2618
2521
  if (!stats.isDirectory()) return { ok: false, error: `${request.path} is not a folder.` };
2619
- const entries = readdirSync2(located, { withFileTypes: true }).filter((entry) => !entry.name.startsWith(".")).slice(0, MAX_LISTED).map((entry) => {
2522
+ const entries = readdirSync(located, { withFileTypes: true }).filter((entry) => !entry.name.startsWith(".")).slice(0, MAX_LISTED).map((entry) => {
2620
2523
  if (entry.isDirectory()) return `${entry.name}/`;
2621
2524
  try {
2622
- return `${entry.name} ${sizeOf(join6(located, entry.name))}`;
2525
+ return `${entry.name} ${sizeOf(join5(located, entry.name))}`;
2623
2526
  } catch {
2624
2527
  return entry.name;
2625
2528
  }
@@ -2637,9 +2540,9 @@ ${listing}
2637
2540
  }
2638
2541
  }
2639
2542
  try {
2640
- const stats = statSync4(located);
2543
+ const stats = statSync3(located);
2641
2544
  if (!stats.isFile()) return { ok: false, error: `${request.path} is not a file.` };
2642
- bytes = readFileSync6(located);
2545
+ bytes = readFileSync5(located);
2643
2546
  } catch (error) {
2644
2547
  return { ok: false, error: error instanceof Error ? error.message : "could not read it" };
2645
2548
  }
@@ -2681,7 +2584,7 @@ async function upload(apiUrl, token, filename, bytes) {
2681
2584
  }
2682
2585
  var MAX_LISTED = 200;
2683
2586
  function sizeOf(path) {
2684
- const size = statSync4(path).size;
2587
+ const size = statSync3(path).size;
2685
2588
  if (size < 1024) return `${size} B`;
2686
2589
  if (size < 1024 * 1024) return `${Math.round(size / 1024)} KB`;
2687
2590
  return `${(size / (1024 * 1024)).toFixed(1)} MB`;
@@ -2693,41 +2596,16 @@ async function agentCommand(context) {
2693
2596
  return 1;
2694
2597
  }
2695
2598
  const roots = (listFlag(context.args, "root") ?? []).map(
2696
- (one) => resolve4(one.startsWith("~") ? resolve4(homedir3(), one.slice(1).replace(/^[/\\]/, "")) : one)
2599
+ (one) => resolve3(one.startsWith("~") ? resolve3(homedir2(), one.slice(1).replace(/^[/\\]/, "")) : one)
2697
2600
  );
2698
- const configPath = join6(context.paths.dir, "agent.json");
2699
- const stored = readAgentConfig(configPath);
2700
- if (stored.error) {
2701
- context.error(stored.error);
2702
- return 1;
2703
- }
2704
- const settings = resolveAgentConfig({
2705
- flagRoots: roots,
2706
- ...stored.config ? { stored: stored.config } : {},
2707
- discovered: discoverRoots()
2708
- });
2709
- if (settings.roots.length === 0) {
2710
- context.error(
2711
- "There is nothing in your home directory this machine would offer, so say which folders it may read from:"
2712
- );
2713
- context.error("");
2714
- context.error(" pm agent --root ~/projects");
2715
- context.error("");
2716
- context.error(`Or write them once in ${configPath}:`);
2717
- context.error("");
2718
- context.error(' { "roots": ["~/projects"], "mode": "ask" }');
2719
- return 1;
2720
- }
2721
- roots.length = 0;
2722
- roots.push(...settings.roots);
2723
- const shown = settings.roots.map((path) => path.replace(homedir3(), "~"));
2724
- const where = settings.source === "flags" ? "" : settings.source === "config" ? ` (from ${configPath})` : " (found in your home directory)";
2601
+ const everywhere = roots.length === 0;
2602
+ if (everywhere) roots.push("/");
2725
2603
  context.print(
2726
- `Reading ${shown.join(", ")} \u2014 nothing outside them${where}. Mode: ${settings.mode}.`
2604
+ everywhere ? "Reading anywhere on this machine. You approve every request first, and see the exact path or command before you do. Narrow it with --root if you want to." : `Reading ${roots.map((path) => path.replace(homedir2(), "~")).join(", ")} \u2014 nothing outside them.`
2727
2605
  );
2728
2606
  for (const root of roots) {
2729
2607
  try {
2730
- if (!statSync4(root).isDirectory()) {
2608
+ if (!statSync3(root).isDirectory()) {
2731
2609
  context.error(`${root} is not a folder.`);
2732
2610
  return 1;
2733
2611
  }
@@ -2801,7 +2679,7 @@ async function agentCommand(context) {
2801
2679
  const { items } = await claimed.json();
2802
2680
  for (const request of items) {
2803
2681
  context.print(`Reading ${request.path}`);
2804
- const outcome = await answer(context, apiUrl, await authorization(), settings, request);
2682
+ const outcome = await answer(context, apiUrl, await authorization(), roots, request);
2805
2683
  const done = await call(
2806
2684
  `complete/${encodeURIComponent(request.id)}`,
2807
2685
  outcome.ok ? { result: { attachToken: outcome.attachToken } } : { error: outcome.error }
@@ -2823,8 +2701,8 @@ async function agentCommand(context) {
2823
2701
 
2824
2702
  // src/commands/google.ts
2825
2703
  import { writeFileSync as writeFileSync5 } from "node:fs";
2826
- import { basename as basename2, resolve as resolve5 } from "node:path";
2827
- import { readFileSync as readFileSync7 } from "node:fs";
2704
+ import { basename as basename2, resolve as resolve4 } from "node:path";
2705
+ import { readFileSync as readFileSync6 } from "node:fs";
2828
2706
  async function callApi(context, path, init = {}) {
2829
2707
  const credential = context.resolved.credential;
2830
2708
  if (!credential) {
@@ -2889,7 +2767,7 @@ async function driveGet(context, fileId) {
2889
2767
  const disposition = response.headers.get("content-disposition") ?? "";
2890
2768
  const named = /filename="([^"]+)"/.exec(disposition)?.[1];
2891
2769
  const out = stringFlag(context.args, "out");
2892
- const target = resolve5(out ?? basename2(named ?? fileId));
2770
+ const target = resolve4(out ?? basename2(named ?? fileId));
2893
2771
  writeFileSync5(target, Buffer.from(await response.arrayBuffer()));
2894
2772
  context.print(target);
2895
2773
  return 0;
@@ -2901,7 +2779,7 @@ async function drivePut(context, path) {
2901
2779
  }
2902
2780
  let bytes;
2903
2781
  try {
2904
- bytes = readFileSync7(resolve5(path));
2782
+ bytes = readFileSync6(resolve4(path));
2905
2783
  } catch {
2906
2784
  context.error(`Cannot read ${path}.`);
2907
2785
  return 1;
@@ -2985,8 +2863,8 @@ async function mailCommand(context) {
2985
2863
  }
2986
2864
 
2987
2865
  // src/commands/requests.ts
2988
- import { existsSync as existsSync7, writeFileSync as writeFileSync6 } from "node:fs";
2989
- import { resolve as resolve6 } from "node:path";
2866
+ import { existsSync as existsSync6, writeFileSync as writeFileSync6 } from "node:fs";
2867
+ import { resolve as resolve5 } from "node:path";
2990
2868
  async function requestsCommand(context) {
2991
2869
  if (context.args.words[1] === "get") return collectCommand(context);
2992
2870
  const credential = context.resolved.credential;
@@ -3054,8 +2932,8 @@ async function collectCommand(context) {
3054
2932
  return 1;
3055
2933
  }
3056
2934
  const name = stringFlag(context.args, "output", "o") ?? filename;
3057
- const target = resolve6(name);
3058
- if (existsSync7(target)) {
2935
+ const target = resolve5(name);
2936
+ if (existsSync6(target)) {
3059
2937
  context.error(`${target} already exists. Pass --output to write somewhere else.`);
3060
2938
  return 1;
3061
2939
  }
@@ -3065,14 +2943,14 @@ async function collectCommand(context) {
3065
2943
  }
3066
2944
 
3067
2945
  // src/workspace.ts
3068
- import { existsSync as existsSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "node:fs";
3069
- import { dirname as dirname3, join as join7, resolve as resolvePath2 } from "node:path";
2946
+ import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "node:fs";
2947
+ import { dirname as dirname3, join as join6, resolve as resolvePath2 } from "node:path";
3070
2948
  var WORKSPACE_FILE = ".persistmemory.json";
3071
2949
  function findWorkspace(from = process.cwd()) {
3072
2950
  let dir = resolvePath2(from);
3073
2951
  for (; ; ) {
3074
- const file = join7(dir, WORKSPACE_FILE);
3075
- if (existsSync8(file)) {
2952
+ const file = join6(dir, WORKSPACE_FILE);
2953
+ if (existsSync7(file)) {
3076
2954
  const config = readWorkspace(file);
3077
2955
  if (config) return { file, dir, config };
3078
2956
  }
@@ -3083,7 +2961,7 @@ function findWorkspace(from = process.cwd()) {
3083
2961
  }
3084
2962
  function readWorkspace(file) {
3085
2963
  try {
3086
- const parsed = JSON.parse(readFileSync8(file, "utf8"));
2964
+ const parsed = JSON.parse(readFileSync7(file, "utf8"));
3087
2965
  const space = parsed.space;
3088
2966
  if (space && typeof space === "object" && typeof space.id === "string" && space.id !== "" && typeof space.name === "string") {
3089
2967
  return { space: { id: space.id, name: space.name } };
@@ -3094,7 +2972,7 @@ function readWorkspace(file) {
3094
2972
  }
3095
2973
  }
3096
2974
  function writeWorkspace(dir, config) {
3097
- const file = join7(dir, WORKSPACE_FILE);
2975
+ const file = join6(dir, WORKSPACE_FILE);
3098
2976
  writeFileSync7(file, `${JSON.stringify(config, null, 2)}
3099
2977
  `, "utf8");
3100
2978
  return file;
@@ -3364,9 +3242,9 @@ function message(error) {
3364
3242
  }
3365
3243
 
3366
3244
  // src/commands/maintain.ts
3367
- import { existsSync as existsSync9, rmSync } from "node:fs";
3245
+ import { existsSync as existsSync8, rmSync } from "node:fs";
3368
3246
  import { spawnSync } from "node:child_process";
3369
- import { dirname as dirname4, resolve as resolve8 } from "node:path";
3247
+ import { dirname as dirname4, resolve as resolve7 } from "node:path";
3370
3248
  import { fileURLToPath } from "node:url";
3371
3249
  function installArgs(pkg = PACKAGE) {
3372
3250
  return ["install", "-g", "--prefer-online", `${pkg}@latest`];
@@ -3430,7 +3308,7 @@ Delete the file it runs from: ${processPath()}`
3430
3308
  return 0;
3431
3309
  }
3432
3310
  async function deleteCommand(context) {
3433
- if (!existsSync9(context.paths.dir)) {
3311
+ if (!existsSync8(context.paths.dir)) {
3434
3312
  context.print(`Nothing to delete: ${context.paths.dir} does not exist.`);
3435
3313
  return 0;
3436
3314
  }
@@ -3459,7 +3337,7 @@ async function deleteCommand(context) {
3459
3337
  return 0;
3460
3338
  }
3461
3339
  function removeEverything(context) {
3462
- const dir = resolve8(context.paths.dir);
3340
+ const dir = resolve7(context.paths.dir);
3463
3341
  if (dir === "/" || dir.split("/").filter(Boolean).length < 2) {
3464
3342
  context.error(`Refusing to delete ${dir}: that does not look like a data directory.`);
3465
3343
  return;
@@ -3471,7 +3349,7 @@ function installer() {
3471
3349
  }
3472
3350
  function processPath() {
3473
3351
  try {
3474
- return resolve8(dirname4(fileURLToPath(import.meta.url)));
3352
+ return resolve7(dirname4(fileURLToPath(import.meta.url)));
3475
3353
  } catch {
3476
3354
  return process.argv[1] ?? "";
3477
3355
  }
@@ -3483,12 +3361,12 @@ import { randomUUID } from "node:crypto";
3483
3361
  import { relative as relative2 } from "node:path";
3484
3362
 
3485
3363
  // src/events.ts
3486
- import { appendFileSync, existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync9 } from "node:fs";
3487
- import { join as join8 } from "node:path";
3364
+ import { appendFileSync, existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync8 } from "node:fs";
3365
+ import { join as join7 } from "node:path";
3488
3366
  function openSessionLog(paths, id) {
3489
- const directory = join8(paths.dir, "sessions");
3367
+ const directory = join7(paths.dir, "sessions");
3490
3368
  mkdirSync3(directory, { recursive: true, mode: 448 });
3491
- const path = join8(directory, `${id}.jsonl`);
3369
+ const path = join7(directory, `${id}.jsonl`);
3492
3370
  return {
3493
3371
  id,
3494
3372
  path,
@@ -3500,8 +3378,8 @@ function openSessionLog(paths, id) {
3500
3378
  }
3501
3379
  },
3502
3380
  read() {
3503
- if (!existsSync10(path)) return [];
3504
- return readFileSync9(path, "utf8").split("\n").filter((line) => line.trim() !== "").flatMap((line) => {
3381
+ if (!existsSync9(path)) return [];
3382
+ return readFileSync8(path, "utf8").split("\n").filter((line) => line.trim() !== "").flatMap((line) => {
3505
3383
  try {
3506
3384
  return [JSON.parse(line)];
3507
3385
  } catch {
@@ -3578,9 +3456,9 @@ async function sessionCommand(context) {
3578
3456
  context.print(` Ask anything. /help for commands, /exit to leave.
3579
3457
  `);
3580
3458
  const readline = createInterface2({ input: process.stdin, output: process.stdout });
3581
- const ask = (prompt) => new Promise((resolve9) => {
3582
- readline.question(prompt, resolve9);
3583
- readline.once("close", () => resolve9(void 0));
3459
+ const ask = (prompt) => new Promise((resolve8) => {
3460
+ readline.question(prompt, resolve8);
3461
+ readline.once("close", () => resolve8(void 0));
3584
3462
  });
3585
3463
  const root = process.cwd();
3586
3464
  let running = true;
@@ -3764,7 +3642,7 @@ async function write2(args) {
3764
3642
  }
3765
3643
 
3766
3644
  // src/commands/memory.ts
3767
- import { readFileSync as readFileSync10 } from "node:fs";
3645
+ import { readFileSync as readFileSync9 } from "node:fs";
3768
3646
 
3769
3647
  // src/spaces.ts
3770
3648
  async function spacesFor(context, client, env = process.env) {
@@ -3828,7 +3706,7 @@ async function rememberCommand(context) {
3828
3706
  let text;
3829
3707
  if (file) {
3830
3708
  try {
3831
- text = readFileSync10(file, "utf8");
3709
+ text = readFileSync9(file, "utf8");
3832
3710
  } catch {
3833
3711
  context.error(`Could not read ${file}.`);
3834
3712
  return 1;