ai-memory-cli 0.1.6__tar.gz → 0.1.7__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ai-memory-cli
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Summary: Python CLI for AI Memory terminal capture and offline sync.
5
5
  Author: AI Memory
6
6
  License-Expression: MIT
@@ -57,6 +57,9 @@ The `auth` command verifies the website-issued token with FastAPI before it is s
57
57
  the CLI stores a SHA-512 user hash for this computer, binds the token to that hash on the server, and starts the
58
58
  background sync agent once on Windows.
59
59
 
60
+ If you run `watch` before auth, it will prompt for the website CLI token and FastAPI URL, then continue into
61
+ terminal capture after verification.
62
+
60
63
  `watch` is a shortcut for `python -m ai_memory_cli watch`. If Windows Device Guard blocks the generated launcher, keep using `python -m ai_memory_cli watch`.
61
64
  On Windows the shortcut is installed as `watch.cmd`; the Python Scripts folder must be on `PATH` for bare `watch` to resolve.
62
65
 
@@ -35,6 +35,9 @@ The `auth` command verifies the website-issued token with FastAPI before it is s
35
35
  the CLI stores a SHA-512 user hash for this computer, binds the token to that hash on the server, and starts the
36
36
  background sync agent once on Windows.
37
37
 
38
+ If you run `watch` before auth, it will prompt for the website CLI token and FastAPI URL, then continue into
39
+ terminal capture after verification.
40
+
38
41
  `watch` is a shortcut for `python -m ai_memory_cli watch`. If Windows Device Guard blocks the generated launcher, keep using `python -m ai_memory_cli watch`.
39
42
  On Windows the shortcut is installed as `watch.cmd`; the Python Scripts folder must be on `PATH` for bare `watch` to resolve.
40
43
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ai-memory-cli"
7
- version = "0.1.6"
7
+ version = "0.1.7"
8
8
  description = "Python CLI for AI Memory terminal capture and offline sync."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """AI Memory terminal capture CLI."""
2
2
 
3
- __version__ = "0.1.6"
3
+ __version__ = "0.1.7"
@@ -174,6 +174,10 @@ def client_identity(home: Path, config: dict[str, Any]) -> dict[str, Any]:
174
174
  }
175
175
 
176
176
 
177
+ def has_verified_auth(config: dict[str, Any]) -> bool:
178
+ return bool(config.get("token") and config.get("auth_verified_at") and config.get("user_hash") and config.get("local_user_hash"))
179
+
180
+
177
181
  def agent_state_path(home: Path) -> Path:
178
182
  return home / "agent.json"
179
183
 
@@ -425,9 +429,56 @@ def verify_cli_auth(home: Path, config: dict[str, Any], token: str) -> dict[str,
425
429
  return response
426
430
 
427
431
 
432
+ def finish_auth(home: Path, config: dict[str, Any], token: str, start_agent: bool = True) -> dict[str, Any]:
433
+ config["pending_token_hash"] = sha256_text(token)
434
+ response = verify_cli_auth(home, config, token)
435
+ config["authed_at"] = utc_now()
436
+ save_config(home, config)
437
+
438
+ print(f"Saved CLI auth in {config_path(home)}")
439
+ print(f"GitHub account: {response.get('github_user') or config.get('github_user') or '-'}")
440
+ print(f"Local user hash: {str(config.get('user_hash') or '')[:24]}...")
441
+ if response.get("account_storage_dir"):
442
+ print(f"Server account storage: {response['account_storage_dir']}")
443
+
444
+ if start_agent:
445
+ ensure_agent_started_once(home, config)
446
+
447
+ try:
448
+ synced = sync_events(home, config, quiet=True)
449
+ if synced:
450
+ print(f"Synced {synced} queued terminal event(s).")
451
+ except Exception as exc:
452
+ print(f"Auth saved. Sync will retry later: {exc}", file=sys.stderr)
453
+
454
+ return response
455
+
456
+
457
+ def prompt_for_auth(home: Path, config: dict[str, Any]) -> dict[str, Any]:
458
+ print("AI Memory needs website auth before watch can capture and sync.")
459
+ print("Generate a CLI token from the website Integrations page, then paste it here.")
460
+ token = getpass.getpass("Website CLI token: ").strip()
461
+ if not token:
462
+ raise SystemExit("No token entered. Generate a CLI token from the website and run watch again.")
463
+
464
+ current_api_url = api_url(config)
465
+ entered_api_url = input(f"FastAPI URL [{current_api_url}]: ").strip()
466
+ if entered_api_url:
467
+ config["api_url"] = entered_api_url.rstrip("/")
468
+
469
+ try:
470
+ return finish_auth(home, config, token, start_agent=True)
471
+ except urllib.error.HTTPError as exc:
472
+ save_config(home, config)
473
+ raise SystemExit(f"CLI auth failed: {describe_http_error(exc)}") from exc
474
+ except Exception as exc:
475
+ save_config(home, config)
476
+ raise SystemExit(f"CLI auth failed. Keep the local FastAPI server running and generate a fresh website token: {exc}") from exc
477
+
478
+
428
479
  def require_verified_auth(home: Path, config: dict[str, Any]) -> str:
429
480
  token = require_token(config)
430
- if config.get("auth_verified_at") and config.get("user_hash") and config.get("local_user_hash"):
481
+ if has_verified_auth(config):
431
482
  return token
432
483
 
433
484
  try:
@@ -545,7 +596,7 @@ def sync_events(home: Path, config: dict[str, Any], limit: int = 50, quiet: bool
545
596
  if not quiet:
546
597
  print("No CLI token saved. Events remain queued until python -m ai_memory_cli auth is configured.")
547
598
  return 0
548
- if not (config.get("auth_verified_at") and config.get("user_hash")):
599
+ if not has_verified_auth(config):
549
600
  try:
550
601
  verify_cli_auth(home, config, token)
551
602
  save_config(home, config)
@@ -661,31 +712,14 @@ def command_auth(args: argparse.Namespace) -> int:
661
712
  config["api_url"] = args.api_url.rstrip("/")
662
713
 
663
714
  token = args.token.strip()
664
- config["pending_token_hash"] = sha256_text(token)
665
715
  try:
666
- response = verify_cli_auth(home, config, token)
716
+ finish_auth(home, config, token, start_agent=not args.no_agent)
667
717
  except urllib.error.HTTPError as exc:
668
718
  save_config(home, config)
669
719
  raise SystemExit(f"CLI auth failed: {describe_http_error(exc)}") from exc
670
720
  except Exception as exc:
671
721
  save_config(home, config)
672
722
  raise SystemExit(f"CLI auth failed. Keep the local FastAPI server running and generate a fresh website token: {exc}") from exc
673
-
674
- config["authed_at"] = utc_now()
675
- save_config(home, config)
676
- print(f"Saved CLI auth in {config_path(home)}")
677
- print(f"GitHub account: {response.get('github_user') or config.get('github_user') or '-'}")
678
- print(f"Local user hash: {str(config.get('user_hash') or '')[:24]}...")
679
- if response.get("account_storage_dir"):
680
- print(f"Server account storage: {response['account_storage_dir']}")
681
-
682
- if not args.no_agent:
683
- ensure_agent_started_once(home, config)
684
-
685
- try:
686
- sync_events(home, config, quiet=True)
687
- except Exception as exc:
688
- print(f"Auth saved. Sync will retry later: {exc}", file=sys.stderr)
689
723
  return 0
690
724
 
691
725
 
@@ -812,6 +846,10 @@ def command_run(args: argparse.Namespace) -> int:
812
846
  def command_watch(args: argparse.Namespace) -> int:
813
847
  home = cli_home()
814
848
  config = load_config(home)
849
+ if not has_verified_auth(config):
850
+ prompt_for_auth(home, config)
851
+ config = load_config(home)
852
+
815
853
  print("AI Memory watch mode. Type commands to run and capture. Type exit to stop.")
816
854
  while True:
817
855
  try:
@@ -1120,7 +1158,7 @@ def command_status(_: argparse.Namespace) -> int:
1120
1158
  print(f"Project: {config.get('project') or '-'}")
1121
1159
  print(f"Repository: {config.get('repository') or '-'}")
1122
1160
  print(f"Workspace: {config.get('workspace_path') or '.'}")
1123
- print(f"Token: {'verified' if config.get('auth_verified_at') and config.get('user_hash') else 'saved' if config.get('token') else 'missing'}")
1161
+ print(f"Token: {'verified' if has_verified_auth(config) else 'saved' if config.get('token') else 'missing'}")
1124
1162
  print(f"GitHub account: {config.get('github_user') or '-'}")
1125
1163
  print(f"User hash: {str(config.get('user_hash') or '-')[:24]}{'...' if config.get('user_hash') else ''}")
1126
1164
  print(f"Events: {event_count} total, {outbox_count} queued, {sent_count} synced receipts")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ai-memory-cli
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Summary: Python CLI for AI Memory terminal capture and offline sync.
5
5
  Author: AI Memory
6
6
  License-Expression: MIT
@@ -57,6 +57,9 @@ The `auth` command verifies the website-issued token with FastAPI before it is s
57
57
  the CLI stores a SHA-512 user hash for this computer, binds the token to that hash on the server, and starts the
58
58
  background sync agent once on Windows.
59
59
 
60
+ If you run `watch` before auth, it will prompt for the website CLI token and FastAPI URL, then continue into
61
+ terminal capture after verification.
62
+
60
63
  `watch` is a shortcut for `python -m ai_memory_cli watch`. If Windows Device Guard blocks the generated launcher, keep using `python -m ai_memory_cli watch`.
61
64
  On Windows the shortcut is installed as `watch.cmd`; the Python Scripts folder must be on `PATH` for bare `watch` to resolve.
62
65
 
File without changes
File without changes