@persistmemory/cli 0.1.1 → 0.1.2

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((resolve6, reject) => {
347
+ return new Promise((resolve7, 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
- resolve6(value);
357
+ resolve7(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((resolve6, reject) => {
367
+ return new Promise((resolve7, 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
- resolve6();
374
+ resolve7();
375
375
  }, ms);
376
376
  function onAbort() {
377
377
  clearTimeout(timer);
@@ -558,6 +558,58 @@ var Spaces = class {
558
558
  async create(params, options) {
559
559
  return this.#http.post("/api/v1/spaces", params, options);
560
560
  }
561
+ /**
562
+ * Deletes a Space. You must say what happens to what is in it.
563
+ *
564
+ * There is no default, here or in the API, and that is deliberate: "delete
565
+ * this Space" means the label to some people and everything inside it to
566
+ * others, and a client that guessed would destroy or keep somebody's
567
+ * material without being asked.
568
+ *
569
+ * `delete` never destroys a memory that is filed in another Space as well —
570
+ * that one is detached and left alone. `deleted` and `kept` come back so you
571
+ * can say what actually happened.
572
+ */
573
+ async delete(id, params, options) {
574
+ return this.#http.delete(
575
+ `/api/v1/spaces/${encodeURIComponent(id)}`,
576
+ params,
577
+ options
578
+ );
579
+ }
580
+ /**
581
+ * Merges Spaces into a NEW one, leaving every source exactly as it was.
582
+ *
583
+ * Additive, not destructive: a memory ends up in the sources AND the result,
584
+ * every existing search over a source returns what it did before, and
585
+ * undoing it is deleting the Space this returns. A memory in two sources is
586
+ * filed once.
587
+ */
588
+ async merge(params, options) {
589
+ return this.#http.post(
590
+ "/api/v1/spaces/merge",
591
+ params,
592
+ options
593
+ );
594
+ }
595
+ /**
596
+ * The Space this account files into when a capture names none.
597
+ *
598
+ * `{}` — an object with no `space` — means there is no default, which is the
599
+ * normal state rather than a gap. It is also what comes back after the Space
600
+ * somebody chose has been deleted.
601
+ */
602
+ async getDefault(options) {
603
+ return this.#http.get("/api/v1/spaces/default", void 0, options);
604
+ }
605
+ /** `null` clears it. Not the same as omitting it, which is why the type says so. */
606
+ async setDefault(spaceId, options) {
607
+ return this.#http.patch(
608
+ "/api/v1/spaces/default",
609
+ { spaceId },
610
+ options
611
+ );
612
+ }
561
613
  /** Renaming, retention, and archiving - `archived` is a field, not a verb. */
562
614
  async update(id, params, options) {
563
615
  return this.#http.patch(`/api/v1/spaces/${encodeURIComponent(id)}`, params, options);
@@ -920,6 +972,42 @@ var Health = class {
920
972
  return this.#http.get("/health/ready", void 0, options);
921
973
  }
922
974
  };
975
+ var Agent = class {
976
+ #http;
977
+ constructor(http) {
978
+ this.#http = http;
979
+ }
980
+ /** The row, including whether it finished and how large the result is. */
981
+ async request(id, options) {
982
+ return this.#http.get(
983
+ `/api/v1/agent/request/${encodeURIComponent(id)}`,
984
+ void 0,
985
+ options
986
+ );
987
+ }
988
+ /**
989
+ * A short-lived link to the bytes of a finished request.
990
+ *
991
+ * Returns the URL rather than the file, and that is a deliberate limit of
992
+ * this package rather than an oversight. The transport under every other
993
+ * method parses JSON, retries, and attaches the API key; none of those is
994
+ * right for a hundred-megabyte binary body, and building a second request
995
+ * path inside the SDK to serve one method is how a client ends up with two
996
+ * retry policies that differ only during an outage. Fetch the URL with
997
+ * whatever already streams in your runtime - it needs no credential, which
998
+ * is the whole reason it is signed.
999
+ *
1000
+ * Treat the URL as the file. It is a bearer credential for exactly one
1001
+ * object, it expires in minutes, and it should not be logged or stored.
1002
+ */
1003
+ async downloadLink(id, options) {
1004
+ return this.#http.get(
1005
+ `/api/v1/agent/request/${encodeURIComponent(id)}/download`,
1006
+ void 0,
1007
+ options
1008
+ );
1009
+ }
1010
+ };
923
1011
  var PersistMemory = class {
924
1012
  memories;
925
1013
  search;
@@ -933,6 +1021,7 @@ var PersistMemory = class {
933
1021
  conversations;
934
1022
  integrations;
935
1023
  health;
1024
+ agent;
936
1025
  #http;
937
1026
  constructor(options) {
938
1027
  this.#http = new HttpClient(options);
@@ -948,6 +1037,7 @@ var PersistMemory = class {
948
1037
  this.conversations = new Conversations(this.#http);
949
1038
  this.integrations = new Integrations(this.#http);
950
1039
  this.health = new Health(this.#http);
1040
+ this.agent = new Agent(this.#http);
951
1041
  }
952
1042
  /**
953
1043
  * An escape hatch for an endpoint this package has not caught up with.
@@ -1289,7 +1379,7 @@ function shortDate(iso) {
1289
1379
  }
1290
1380
 
1291
1381
  // src/help.ts
1292
- var VERSION = "0.1.1";
1382
+ var VERSION = "0.1.2";
1293
1383
  var PACKAGE = "@persistmemory/cli";
1294
1384
  var HELP = `
1295
1385
  pm \u2014 PersistMemory from your terminal
@@ -1336,6 +1426,7 @@ var HELP = `
1336
1426
 
1337
1427
  status is the service healthy
1338
1428
  requests file requests waiting for you to approve
1429
+ requests get <id> write a finished one to a file here
1339
1430
 
1340
1431
  update install the newest version
1341
1432
  uninstall remove pm from this machine
@@ -1479,8 +1570,8 @@ async function startLoopback(options = {}) {
1479
1570
  const timeoutMs = options.timeoutMs ?? 5 * 60 * 1e3;
1480
1571
  let resolveCallback;
1481
1572
  let rejectCallback;
1482
- const received = new Promise((resolve6, reject) => {
1483
- resolveCallback = resolve6;
1573
+ const received = new Promise((resolve7, reject) => {
1574
+ resolveCallback = resolve7;
1484
1575
  rejectCallback = reject;
1485
1576
  });
1486
1577
  const server = createServer((request, response) => {
@@ -1506,9 +1597,9 @@ async function startLoopback(options = {}) {
1506
1597
  response.end(donePage(callback));
1507
1598
  resolveCallback?.(callback);
1508
1599
  });
1509
- await new Promise((resolve6, reject) => {
1600
+ await new Promise((resolve7, reject) => {
1510
1601
  server.once("error", reject);
1511
- server.listen(0, "127.0.0.1", resolve6);
1602
+ server.listen(0, "127.0.0.1", resolve7);
1512
1603
  });
1513
1604
  const address = server.address();
1514
1605
  if (address === null || typeof address === "string") {
@@ -1770,7 +1861,7 @@ function safeEqual(a, b) {
1770
1861
  }
1771
1862
  async function openBrowser(url) {
1772
1863
  const [command, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
1773
- await new Promise((resolve6, reject) => {
1864
+ await new Promise((resolve7, reject) => {
1774
1865
  const child = spawn(command, args, {
1775
1866
  stdio: "ignore",
1776
1867
  // Detached so closing the terminal does not close the browser, and so
@@ -1779,7 +1870,7 @@ async function openBrowser(url) {
1779
1870
  });
1780
1871
  child.once("error", reject);
1781
1872
  child.unref();
1782
- resolve6();
1873
+ resolve7();
1783
1874
  });
1784
1875
  }
1785
1876
  async function describe(response) {
@@ -1841,13 +1932,13 @@ async function currentCredential(resolved, deps) {
1841
1932
  // src/context.ts
1842
1933
  import { createInterface } from "node:readline";
1843
1934
  async function askOnTty(prompt) {
1844
- return new Promise((resolve6) => {
1935
+ return new Promise((resolve7) => {
1845
1936
  const readline = createInterface({ input: process.stdin, output: process.stdout });
1846
1937
  readline.question(prompt, (answer3) => {
1847
1938
  readline.close();
1848
- resolve6(answer3.trim());
1939
+ resolve7(answer3.trim());
1849
1940
  });
1850
- readline.once("close", () => resolve6(""));
1941
+ readline.once("close", () => resolve7(""));
1851
1942
  });
1852
1943
  }
1853
1944
  var ETX = "";
@@ -1856,13 +1947,13 @@ var BACKSPACE = "\b";
1856
1947
  async function readSecretFromTty(prompt) {
1857
1948
  const input = process.stdin;
1858
1949
  if (!input.isTTY) {
1859
- return new Promise((resolve6) => {
1950
+ return new Promise((resolve7) => {
1860
1951
  const readline = createInterface({ input });
1861
1952
  readline.once("line", (line) => {
1862
1953
  readline.close();
1863
- resolve6(line.trim());
1954
+ resolve7(line.trim());
1864
1955
  });
1865
- readline.once("close", () => resolve6(""));
1956
+ readline.once("close", () => resolve7(""));
1866
1957
  });
1867
1958
  }
1868
1959
  process.stdout.write(prompt);
@@ -1870,14 +1961,14 @@ async function readSecretFromTty(prompt) {
1870
1961
  input.setRawMode?.(true);
1871
1962
  input.resume();
1872
1963
  input.setEncoding("utf8");
1873
- return new Promise((resolve6) => {
1964
+ return new Promise((resolve7) => {
1874
1965
  let value = "";
1875
1966
  const finish2 = () => {
1876
1967
  input.removeListener("data", onData);
1877
1968
  input.setRawMode?.(previouslyRaw);
1878
1969
  input.pause();
1879
1970
  process.stdout.write("\n");
1880
- resolve6(value.trim());
1971
+ resolve7(value.trim());
1881
1972
  };
1882
1973
  const onData = (chunk) => {
1883
1974
  for (const character of chunk) {
@@ -1914,8 +2005,8 @@ async function readStdin() {
1914
2005
  // src/commands/agent.ts
1915
2006
  import { hostname } from "node:os";
1916
2007
  import { homedir as homedir2 } from "node:os";
1917
- import { resolve as resolve3 } from "node:path";
1918
- import { readFileSync as readFileSync4, statSync as statSync2 } from "node:fs";
2008
+ import { join as join4, resolve as resolve3 } from "node:path";
2009
+ import { readFileSync as readFileSync4, readdirSync, statSync as statSync2 } from "node:fs";
1919
2010
 
1920
2011
  // src/files.ts
1921
2012
  import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync, statSync, writeFileSync as writeFileSync3 } from "node:fs";
@@ -1928,11 +2019,13 @@ var OutsideWorkspace = class extends Error {
1928
2019
  };
1929
2020
  var TooLarge = class extends Error {
1930
2021
  constructor(path, bytes, limit) {
1931
- super(`${path} is ${Math.round(bytes / 1024)} KB, over the ${Math.round(limit / 1024)} KB limit.`);
2022
+ const say = (value) => value >= 1024 * 1024 ? `${(value / (1024 * 1024)).toFixed(1)} MB` : `${Math.round(value / 1024)} KB`;
2023
+ super(`${path} is ${say(bytes)}, over the ${say(limit)} limit.`);
1932
2024
  this.name = "TooLarge";
1933
2025
  }
1934
2026
  };
1935
2027
  var MAX_READ_BYTES = 512 * 1024;
2028
+ var MAX_TRANSFER_BYTES = 100 * 1024 * 1024;
1936
2029
  function realLocation(absolute) {
1937
2030
  let existing = absolute;
1938
2031
  const trailing = [];
@@ -2046,19 +2139,41 @@ async function answer(context, apiUrl, token, roots, request) {
2046
2139
  return { ok: false, error: error instanceof Error ? error.message : "refused" };
2047
2140
  }
2048
2141
  let bytes;
2142
+ let filename = request.path.split("/").pop() ?? "file";
2143
+ if (request.kind === "list_dir") {
2144
+ try {
2145
+ const stats = statSync2(located);
2146
+ if (!stats.isDirectory()) return { ok: false, error: `${request.path} is not a folder.` };
2147
+ const entries = readdirSync(located, { withFileTypes: true }).filter((entry) => !entry.name.startsWith(".")).slice(0, MAX_LISTED).map((entry) => {
2148
+ if (entry.isDirectory()) return `${entry.name}/`;
2149
+ try {
2150
+ return `${entry.name} ${sizeOf(join4(located, entry.name))}`;
2151
+ } catch {
2152
+ return entry.name;
2153
+ }
2154
+ }).sort();
2155
+ const listing = entries.length > 0 ? entries.join("\n") : "(empty)";
2156
+ bytes = Buffer.from(`${request.path}
2157
+
2158
+ ${listing}
2159
+ `, "utf8");
2160
+ filename = `${request.path.split("/").filter(Boolean).pop() ?? "listing"}.txt`;
2161
+ const grant = await upload(apiUrl, token, filename, bytes);
2162
+ return grant;
2163
+ } catch (error) {
2164
+ return { ok: false, error: error instanceof Error ? error.message : "could not list it" };
2165
+ }
2166
+ }
2049
2167
  try {
2050
2168
  const stats = statSync2(located);
2051
2169
  if (!stats.isFile()) return { ok: false, error: `${request.path} is not a file.` };
2052
- if (stats.size > MAX_READ_BYTES) {
2053
- return {
2054
- ok: false,
2055
- error: new TooLarge(request.path, stats.size, MAX_READ_BYTES).message
2056
- };
2057
- }
2058
2170
  bytes = readFileSync4(located);
2059
2171
  } catch (error) {
2060
2172
  return { ok: false, error: error instanceof Error ? error.message : "could not read it" };
2061
2173
  }
2174
+ return upload(apiUrl, token, filename, bytes);
2175
+ }
2176
+ async function upload(apiUrl, token, filename, bytes) {
2062
2177
  const grant = await fetch(`${apiUrl}/api/v1/agent/upload-url`, {
2063
2178
  method: "POST",
2064
2179
  headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
@@ -2070,13 +2185,17 @@ async function answer(context, apiUrl, token, roots, request) {
2070
2185
  // No content type is sent: this machine has a path, not a declaration.
2071
2186
  // The server resolves it from the name against the one table that knows
2072
2187
  // which types it can read, and tells us below what it decided.
2073
- filename: request.path.split("/").pop() ?? "file"
2188
+ filename
2074
2189
  })
2075
2190
  });
2076
2191
  if (!grant.ok) {
2077
2192
  return { ok: false, error: await said(grant, "could not get an upload url") };
2078
2193
  }
2079
- const { uploadUrl, contentType } = await grant.json();
2194
+ const { uploadUrl, contentType, maxBytes } = await grant.json();
2195
+ const limit = maxBytes ?? MAX_TRANSFER_BYTES;
2196
+ if (bytes.length > limit) {
2197
+ return { ok: false, error: new TooLarge(filename, bytes.length, limit).message };
2198
+ }
2080
2199
  const put = await fetch(uploadUrl, {
2081
2200
  method: "PUT",
2082
2201
  // The type the grant was signed for. Anything else is refused.
@@ -2088,6 +2207,13 @@ async function answer(context, apiUrl, token, roots, request) {
2088
2207
  if (!stored.attachToken) return { ok: false, error: "the upload returned no reference" };
2089
2208
  return { ok: true, attachToken: stored.attachToken, bytes: bytes.length };
2090
2209
  }
2210
+ var MAX_LISTED = 200;
2211
+ function sizeOf(path) {
2212
+ const size = statSync2(path).size;
2213
+ if (size < 1024) return `${size} B`;
2214
+ if (size < 1024 * 1024) return `${Math.round(size / 1024)} KB`;
2215
+ return `${(size / (1024 * 1024)).toFixed(1)} MB`;
2216
+ }
2091
2217
  async function agentCommand(context) {
2092
2218
  const credential = context.resolved.credential;
2093
2219
  if (!credential) {
@@ -2197,7 +2323,10 @@ async function agentCommand(context) {
2197
2323
  }
2198
2324
 
2199
2325
  // src/commands/requests.ts
2326
+ import { existsSync as existsSync4, writeFileSync as writeFileSync4 } from "node:fs";
2327
+ import { resolve as resolve4 } from "node:path";
2200
2328
  async function requestsCommand(context) {
2329
+ if (context.args.words[1] === "get") return collectCommand(context);
2201
2330
  const credential = context.resolved.credential;
2202
2331
  if (!credential) {
2203
2332
  context.error("Sign in first: pm auth login");
@@ -2235,16 +2364,53 @@ async function requestsCommand(context) {
2235
2364
  context.print("They cannot be approved from here \u2014 see `pm help requests`.");
2236
2365
  return 0;
2237
2366
  }
2367
+ async function collectCommand(context) {
2368
+ const credential = context.resolved.credential;
2369
+ if (!credential) {
2370
+ context.error("Sign in first: pm auth login");
2371
+ return 1;
2372
+ }
2373
+ const id = context.args.words[2];
2374
+ if (!id) {
2375
+ context.error("Which request? `pm requests` lists them with their ids.");
2376
+ return 2;
2377
+ }
2378
+ const apiUrl = context.resolved.apiUrl.replace(/\/+$/, "");
2379
+ const link = await fetch(
2380
+ `${apiUrl}/api/v1/agent/request/${encodeURIComponent(id)}/download`,
2381
+ { headers: { authorization: `Bearer ${credential.token}` } }
2382
+ );
2383
+ if (!link.ok) {
2384
+ const body = await link.json().catch(() => void 0);
2385
+ context.error(body?.error?.message ?? `Could not prepare that file (${link.status}).`);
2386
+ return 1;
2387
+ }
2388
+ const { downloadUrl, filename } = await link.json();
2389
+ const file = await fetch(downloadUrl);
2390
+ if (!file.ok) {
2391
+ context.error(`The download refused it (${file.status}). Links expire in minutes \u2014 try again.`);
2392
+ return 1;
2393
+ }
2394
+ const name = stringFlag(context.args, "output", "o") ?? filename;
2395
+ const target = resolve4(name);
2396
+ if (existsSync4(target)) {
2397
+ context.error(`${target} already exists. Pass --output to write somewhere else.`);
2398
+ return 1;
2399
+ }
2400
+ writeFileSync4(target, new Uint8Array(await file.arrayBuffer()));
2401
+ context.print(`Wrote ${target}`);
2402
+ return 0;
2403
+ }
2238
2404
 
2239
2405
  // src/workspace.ts
2240
- import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
2241
- import { dirname as dirname3, join as join4, resolve as resolvePath } from "node:path";
2406
+ import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
2407
+ import { dirname as dirname3, join as join5, resolve as resolvePath } from "node:path";
2242
2408
  var WORKSPACE_FILE = ".persistmemory.json";
2243
2409
  function findWorkspace(from = process.cwd()) {
2244
2410
  let dir = resolvePath(from);
2245
2411
  for (; ; ) {
2246
- const file = join4(dir, WORKSPACE_FILE);
2247
- if (existsSync4(file)) {
2412
+ const file = join5(dir, WORKSPACE_FILE);
2413
+ if (existsSync5(file)) {
2248
2414
  const config = readWorkspace(file);
2249
2415
  if (config) return { file, dir, config };
2250
2416
  }
@@ -2266,8 +2432,8 @@ function readWorkspace(file) {
2266
2432
  }
2267
2433
  }
2268
2434
  function writeWorkspace(dir, config) {
2269
- const file = join4(dir, WORKSPACE_FILE);
2270
- writeFileSync4(file, `${JSON.stringify(config, null, 2)}
2435
+ const file = join5(dir, WORKSPACE_FILE);
2436
+ writeFileSync5(file, `${JSON.stringify(config, null, 2)}
2271
2437
  `, "utf8");
2272
2438
  return file;
2273
2439
  }
@@ -2536,9 +2702,9 @@ function message(error) {
2536
2702
  }
2537
2703
 
2538
2704
  // src/commands/maintain.ts
2539
- import { existsSync as existsSync5, rmSync } from "node:fs";
2705
+ import { existsSync as existsSync6, rmSync } from "node:fs";
2540
2706
  import { spawnSync } from "node:child_process";
2541
- import { dirname as dirname4, resolve as resolve5 } from "node:path";
2707
+ import { dirname as dirname4, resolve as resolve6 } from "node:path";
2542
2708
  import { fileURLToPath } from "node:url";
2543
2709
  async function updateCommand(context) {
2544
2710
  const manager = installer();
@@ -2580,7 +2746,7 @@ Delete the file it runs from: ${processPath()}`
2580
2746
  return 0;
2581
2747
  }
2582
2748
  async function deleteCommand(context) {
2583
- if (!existsSync5(context.paths.dir)) {
2749
+ if (!existsSync6(context.paths.dir)) {
2584
2750
  context.print(`Nothing to delete: ${context.paths.dir} does not exist.`);
2585
2751
  return 0;
2586
2752
  }
@@ -2609,7 +2775,7 @@ async function deleteCommand(context) {
2609
2775
  return 0;
2610
2776
  }
2611
2777
  function removeEverything(context) {
2612
- const dir = resolve5(context.paths.dir);
2778
+ const dir = resolve6(context.paths.dir);
2613
2779
  if (dir === "/" || dir.split("/").filter(Boolean).length < 2) {
2614
2780
  context.error(`Refusing to delete ${dir}: that does not look like a data directory.`);
2615
2781
  return;
@@ -2621,7 +2787,7 @@ function installer() {
2621
2787
  }
2622
2788
  function processPath() {
2623
2789
  try {
2624
- return resolve5(dirname4(fileURLToPath(import.meta.url)));
2790
+ return resolve6(dirname4(fileURLToPath(import.meta.url)));
2625
2791
  } catch {
2626
2792
  return process.argv[1] ?? "";
2627
2793
  }
@@ -2633,12 +2799,12 @@ import { randomUUID } from "node:crypto";
2633
2799
  import { relative as relative2 } from "node:path";
2634
2800
 
2635
2801
  // src/events.ts
2636
- import { appendFileSync, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6 } from "node:fs";
2637
- import { join as join5 } from "node:path";
2802
+ import { appendFileSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync6 } from "node:fs";
2803
+ import { join as join6 } from "node:path";
2638
2804
  function openSessionLog(paths, id) {
2639
- const directory = join5(paths.dir, "sessions");
2805
+ const directory = join6(paths.dir, "sessions");
2640
2806
  mkdirSync3(directory, { recursive: true, mode: 448 });
2641
- const path = join5(directory, `${id}.jsonl`);
2807
+ const path = join6(directory, `${id}.jsonl`);
2642
2808
  return {
2643
2809
  id,
2644
2810
  path,
@@ -2650,7 +2816,7 @@ function openSessionLog(paths, id) {
2650
2816
  }
2651
2817
  },
2652
2818
  read() {
2653
- if (!existsSync6(path)) return [];
2819
+ if (!existsSync7(path)) return [];
2654
2820
  return readFileSync6(path, "utf8").split("\n").filter((line) => line.trim() !== "").flatMap((line) => {
2655
2821
  try {
2656
2822
  return [JSON.parse(line)];
@@ -2728,9 +2894,9 @@ async function sessionCommand(context) {
2728
2894
  context.print(` Ask anything. /help for commands, /exit to leave.
2729
2895
  `);
2730
2896
  const readline = createInterface2({ input: process.stdin, output: process.stdout });
2731
- const ask = (prompt) => new Promise((resolve6) => {
2732
- readline.question(prompt, resolve6);
2733
- readline.once("close", () => resolve6(void 0));
2897
+ const ask = (prompt) => new Promise((resolve7) => {
2898
+ readline.question(prompt, resolve7);
2899
+ readline.once("close", () => resolve7(void 0));
2734
2900
  });
2735
2901
  const root = process.cwd();
2736
2902
  let running = true;