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