@persistmemory/cli 0.2.3 → 0.3.1

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
@@ -1527,7 +1527,7 @@ function shortDate(iso) {
1527
1527
  }
1528
1528
 
1529
1529
  // src/help.ts
1530
- var VERSION = true ? "0.2.3" : versionFromManifest();
1530
+ var VERSION = true ? "0.3.1" : versionFromManifest();
1531
1531
  var PACKAGE = "@persistmemory/cli";
1532
1532
  var HELP = `
1533
1533
  pm \u2014 PersistMemory from your terminal
@@ -1548,8 +1548,6 @@ var HELP = `
1548
1548
  auth login sign in through the browser
1549
1549
  auth login --api-key sign in with a key, for CI and headless machines
1550
1550
 
1551
- agent --root <dir> answer file requests from your assistants,
1552
- reading only inside the folders you name
1553
1551
  auth status who am I, and does the server still accept it
1554
1552
  auth logout forget the stored credential
1555
1553
 
@@ -1561,12 +1559,23 @@ var HELP = `
1561
1559
  setup --new-space "Acme" create one and use it
1562
1560
 
1563
1561
  spaces list your Spaces
1564
- spaces create <name> make a new one
1562
+ spaces create "Acme" make a new one
1563
+ spaces delete "Acme" --memories keep|delete
1564
+ delete one \u2014 you must say what happens
1565
+ to what is in it
1566
+ spaces merge "A" "B" --name "C" a new Space holding both, originals kept
1565
1567
 
1566
1568
  remember <text> capture text
1567
1569
  remember - capture whatever is piped in
1568
1570
  remember --file <path> capture a file's contents
1569
1571
 
1572
+ agent --root <dir> [--root ...] answer file requests from this machine \u2014
1573
+ nothing outside those folders is read.
1574
+ It stays in the foreground. Background it,
1575
+ and stop it later, with:
1576
+ nohup pm agent --root ~/Desktop &
1577
+ pkill -f "pm agent"
1578
+
1570
1579
  search <query> search your memory
1571
1580
  list memories the most recent memories
1572
1581
  list spaces your Spaces
@@ -2449,7 +2458,14 @@ async function agentCommand(context) {
2449
2458
  context.error(
2450
2459
  "Say which folders this machine may read from, and nothing outside them will be:"
2451
2460
  );
2452
- context.error(" pm agent --root ~/notes --root ~/projects");
2461
+ context.error("");
2462
+ context.error(" pm agent --root ~/Desktop --root ~/Documents");
2463
+ context.error("");
2464
+ context.error("It stays in the foreground. To leave it running:");
2465
+ context.error("");
2466
+ context.error(" nohup pm agent --root ~/Desktop > ~/agent.log 2>&1 &");
2467
+ context.error("");
2468
+ context.error('And to stop it later: pkill -f "pm agent"');
2453
2469
  return 1;
2454
2470
  }
2455
2471
  for (const root of roots) {
@@ -2480,10 +2496,14 @@ async function agentCommand(context) {
2480
2496
  };
2481
2497
  process.on("SIGINT", stop);
2482
2498
  process.on("SIGTERM", stop);
2499
+ const authorization = async () => {
2500
+ const held = await currentCredential(context.resolved, context.session);
2501
+ return held.token;
2502
+ };
2483
2503
  const call = async (path, body) => fetch(`${apiUrl}/api/v1/agent/${path}`, {
2484
2504
  method: "POST",
2485
2505
  headers: {
2486
- authorization: `Bearer ${credential.token}`,
2506
+ authorization: `Bearer ${await authorization()}`,
2487
2507
  "content-type": "application/json"
2488
2508
  },
2489
2509
  body: JSON.stringify(body)
@@ -2524,7 +2544,7 @@ async function agentCommand(context) {
2524
2544
  const { items } = await claimed.json();
2525
2545
  for (const request of items) {
2526
2546
  context.print(`Reading ${request.path}`);
2527
- const outcome = await answer(context, apiUrl, credential.token, roots, request);
2547
+ const outcome = await answer(context, apiUrl, await authorization(), roots, request);
2528
2548
  const done = await call(
2529
2549
  `complete/${encodeURIComponent(request.id)}`,
2530
2550
  outcome.ok ? { result: { attachToken: outcome.attachToken } } : { error: outcome.error }
@@ -3715,6 +3735,67 @@ var spaceFields = [
3715
3735
  { header: "name", value: (s) => s.name },
3716
3736
  { header: "kind", value: (s) => s.kind }
3717
3737
  ];
3738
+ async function deleteSpaceCommand(context) {
3739
+ const named = context.args.words.slice(2).join(" ").trim();
3740
+ if (named === "") {
3741
+ context.error('Which Space? Try `pm spaces delete "Acme" --memories keep`.');
3742
+ return 2;
3743
+ }
3744
+ const memories = stringFlag(context.args, "memories");
3745
+ if (memories !== "keep" && memories !== "delete") {
3746
+ context.error("Say what happens to what is in it \u2014 there is no default:");
3747
+ context.error("");
3748
+ context.error(` pm spaces delete "${named}" --memories keep the memories survive`);
3749
+ context.error(` pm spaces delete "${named}" --memories delete they go with it`);
3750
+ return 2;
3751
+ }
3752
+ const client = await context.client();
3753
+ const { data } = await client.spaces.list({ limit: 200 }).first();
3754
+ const found = named.startsWith("space_") ? data.find((one) => one.id === named) : data.find((one) => one.name.toLowerCase() === named.toLowerCase());
3755
+ if (!found) {
3756
+ context.error(`No Space called "${named}". Run \`pm spaces list\` to see them.`);
3757
+ return 1;
3758
+ }
3759
+ const result = await client.spaces.delete(found.id, { memories });
3760
+ if (context.flags.output !== "table") {
3761
+ context.print(JSON.stringify({ id: found.id, ...result }, void 0, 2));
3762
+ return 0;
3763
+ }
3764
+ context.print(`Deleted "${found.name}".`);
3765
+ context.print(` ${result.deleted} memories deleted, ${result.kept} kept`);
3766
+ return 0;
3767
+ }
3768
+ async function mergeSpacesCommand(context) {
3769
+ const named = context.args.words.slice(2);
3770
+ const name = stringFlag(context.args, "name");
3771
+ if (named.length < 2 || !name) {
3772
+ context.error("Two or more Spaces, and a name for the one this makes:");
3773
+ context.error("");
3774
+ context.error(' pm spaces merge "Work" "Personal" --name "Everything"');
3775
+ return 2;
3776
+ }
3777
+ const client = await context.client();
3778
+ const { data } = await client.spaces.list({ limit: 200 }).first();
3779
+ const ids = [];
3780
+ for (const one of named) {
3781
+ const found = one.startsWith("space_") ? data.find((space2) => space2.id === one) : data.find((space2) => space2.name.toLowerCase() === one.toLowerCase());
3782
+ if (!found) {
3783
+ context.error(`No Space called "${one}". Run \`pm spaces list\` to see them.`);
3784
+ return 1;
3785
+ }
3786
+ ids.push(found.id);
3787
+ }
3788
+ const { space, added } = await client.spaces.merge({ sourceIds: ids, name });
3789
+ if (context.flags.output !== "table") {
3790
+ context.print(renderOne(space, spaceFields, { format: context.flags.output }));
3791
+ return 0;
3792
+ }
3793
+ context.print(`Created "${space.name}" from ${ids.length} Spaces, holding ${added} memories.`);
3794
+ context.print(` id ${space.id}`);
3795
+ context.print("");
3796
+ context.print("The Spaces it drew from are unchanged \u2014 nothing was moved or deleted.");
3797
+ return 0;
3798
+ }
3718
3799
 
3719
3800
  // src/index.ts
3720
3801
  async function run(deps) {
@@ -3870,8 +3951,10 @@ async function dispatch(context) {
3870
3951
  case "spaces":
3871
3952
  case "space":
3872
3953
  if (noun === "create" || noun === "new") return createSpaceCommand(context);
3954
+ if (noun === "delete" || noun === "remove") return deleteSpaceCommand(context);
3955
+ if (noun === "merge") return mergeSpacesCommand(context);
3873
3956
  if (noun === void 0 || noun === "list") return listSpacesCommand(context);
3874
- context.error(`Cannot "pm spaces ${noun}". Try list or create.`);
3957
+ context.error(`Cannot "pm spaces ${noun}". Try list, create, delete or merge.`);
3875
3958
  return 2;
3876
3959
  case "list":
3877
3960
  if (noun === "memories" || noun === "memory") return listMemoriesCommand(context);