@todoforai/tfa-memory 0.2.1 → 0.4.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.
Files changed (2) hide show
  1. package/dist/cli.js +36 -13
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -462,8 +462,8 @@ function checkForUpdates(pkg) {
462
462
  // package.json
463
463
  var package_default = {
464
464
  name: "@todoforai/tfa-memory",
465
- version: "0.2.1",
466
- description: "Zero-config TODOforAI memory CLI — add/search/ls/get/rm text memory rows addressed as source/ref, with full-text and semantic search. Reuses bridge credentials.",
465
+ version: "0.4.0",
466
+ description: "Zero-config TODOforAI memory CLI — add/search/ls/get/rm text memory rows addressed as source/ref, plus federated search over every message of every past TODO (read-only `todo` source), with full-text and semantic search. Reuses bridge credentials.",
467
467
  type: "module",
468
468
  bin: {
469
469
  "tfa-memory": "dist/cli.js"
@@ -497,7 +497,12 @@ function printHelp() {
497
497
 
498
498
  Every row's address is \`source/ref\` — sources are directories, refs are
499
499
  filenames. A source exists once the first row names it. Re-adding the same
500
- address updates in place; identical content is skipped (no re-embed).
500
+ address updates in place; identical content+meta is skipped (no re-embed).
501
+
502
+ \`search\` covers two corpora at once: rows you saved, plus every message of
503
+ every TODO under the read-only \`todo\` source (\`todo/<todoId>:<messageId>\`,
504
+ live from the backend index, nothing separate to sync). \`--source todo\` searches
505
+ past TODOs only; \`get todo/<todoId>:<messageId>\` prints the whole message.
501
506
 
502
507
  Usage:
503
508
  tfa-memory <command> [options] [args...]
@@ -505,8 +510,8 @@ Usage:
505
510
  Commands:
506
511
  add [source/ref] <text|-> Save a row. Without an address → manual/<timestamp>.
507
512
  "-" reads stdin.
508
- search <query> Full-text search (newest first)
509
- ls List rows, newest first
513
+ search <query> Full-text search over saved rows + past TODO messages
514
+ ls List saved rows, newest first (todo messages excluded)
510
515
  get <source/ref> Print full content of one row
511
516
  rm <source/ref> Delete one row
512
517
  rm --source <name> Delete every row in a source
@@ -515,9 +520,11 @@ Commands:
515
520
  whoami Print resolved auth context
516
521
 
517
522
  Options:
518
- -s, --source <a,b> Restrict search/ls to sources (comma-separated)
523
+ -s, --source <a,b> Restrict search/ls to sources (comma-separated; "todo" = TODO messages)
524
+ --todo <id> Restrict a todo-message search to one TODO
519
525
  --semantic Embedding KNN search (meaning, not keywords)
520
- -n, --limit <n> Max rows (default 10, max 50)
526
+ --meta <json> Attach JSON metadata to the row (e.g. '{"todoId":"..."}')
527
+ -n, --limit <n> Max rows (default 5, max 50)
521
528
  -j, --json Machine-readable output
522
529
  --api-token <token> Override API token
523
530
  --api-url <url> Override backend URL (used to derive memory URL)
@@ -531,6 +538,8 @@ Examples:
531
538
  cat docs/auth.md | tfa-memory add acme/docs/auth.md -
532
539
  tfa-memory search "rollback procedure"
533
540
  tfa-memory search "how do we deploy" --semantic
541
+ tfa-memory search "android build" --source todo
542
+ tfa-memory get todo/<todoId>:<messageId>
534
543
  tfa-memory ls --source deploy-notes
535
544
  tfa-memory get deploy-notes/rollback
536
545
  tfa-memory rm deploy-notes/rollback
@@ -604,6 +613,8 @@ async function main() {
604
613
  args: process.argv.slice(2),
605
614
  options: {
606
615
  source: { type: "string", short: "s" },
616
+ todo: { type: "string" },
617
+ meta: { type: "string" },
607
618
  semantic: { type: "boolean", default: false },
608
619
  limit: { type: "string", short: "n" },
609
620
  json: { type: "boolean", short: "j", default: false },
@@ -647,8 +658,8 @@ async function main() {
647
658
  }
648
659
  const json = values.json;
649
660
  const limit = values.limit !== undefined ? Number(values.limit) : undefined;
650
- if (limit !== undefined && (!Number.isInteger(limit) || limit < 1))
651
- die(`--limit must be a positive integer`, 2);
661
+ if (limit !== undefined && (!Number.isInteger(limit) || limit < 1 || limit > 50))
662
+ die(`--limit must be an integer from 1 to 50`, 2);
652
663
  const sources = values.source;
653
664
  switch (cmd) {
654
665
  case "add": {
@@ -665,13 +676,25 @@ async function main() {
665
676
  text = text.trim();
666
677
  if (!text)
667
678
  die("empty content");
668
- const res = await api(ctx, "POST", "/memory", { source, ref, content: text });
679
+ let meta;
680
+ if (values.meta !== undefined) {
681
+ try {
682
+ meta = JSON.parse(values.meta);
683
+ } catch {
684
+ die(`--meta must be valid JSON`, 2);
685
+ }
686
+ if (typeof meta !== "object" || meta === null || Array.isArray(meta))
687
+ die(`--meta must be a JSON object`, 2);
688
+ }
689
+ const res = await api(ctx, "POST", "/memory", { source, ref, content: text, meta });
669
690
  console.log(json ? JSON.stringify(res) : `${res.status} ${res.address}`);
670
691
  break;
671
692
  }
672
693
  case "search": {
673
694
  const query = rest[0] ?? die(`usage: tfa-memory search "query"`, 2);
674
- const res = await api(ctx, "GET", `/memory/search${qs({ query, semantic: values.semantic ? true : undefined, sources, limit })}`);
695
+ const res = await api(ctx, "GET", `/memory/search${qs({ query, semantic: values.semantic ? true : undefined, sources, limit, todoId: values.todo })}`);
696
+ for (const w of res.warnings ?? [])
697
+ console.error(`Warning: ${w}`);
675
698
  printRows(res.rows, json, 200);
676
699
  break;
677
700
  }
@@ -716,8 +739,8 @@ async function main() {
716
739
  break;
717
740
  }
718
741
  const w = Math.max(...res.sources.map((s) => s.source.length));
719
- for (const s of res.sources.sort((a, b) => b.lastWrite - a.lastWrite))
720
- console.log(`${s.source.padEnd(w)} ${String(s.count).padStart(4)} ${new Date(s.lastWrite).toISOString().slice(0, 16)}`);
742
+ for (const s of res.sources.sort((a, b) => (b.lastWrite ?? Infinity) - (a.lastWrite ?? Infinity)))
743
+ console.log(`${s.source.padEnd(w)} ${String(s.count ?? "live").padStart(4)} ${s.lastWrite ? new Date(s.lastWrite).toISOString().slice(0, 16) : "live"}`);
721
744
  break;
722
745
  }
723
746
  default:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@todoforai/tfa-memory",
3
- "version": "0.2.1",
4
- "description": "Zero-config TODOforAI memory CLI \u2014 add/search/ls/get/rm text memory rows addressed as source/ref, with full-text and semantic search. Reuses bridge credentials.",
3
+ "version": "0.4.0",
4
+ "description": "Zero-config TODOforAI memory CLI — add/search/ls/get/rm text memory rows addressed as source/ref, plus federated search over every message of every past TODO (read-only `todo` source), with full-text and semantic search. Reuses bridge credentials.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "tfa-memory": "dist/cli.js"