buildai-cli 0.1.0__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.
Files changed (44) hide show
  1. buildai_cli-0.1.0/.gitignore +78 -0
  2. buildai_cli-0.1.0/AGENTS.md +1 -0
  3. buildai_cli-0.1.0/CLAUDE.md +96 -0
  4. buildai_cli-0.1.0/PKG-INFO +21 -0
  5. buildai_cli-0.1.0/cli/__init__.py +1 -0
  6. buildai_cli-0.1.0/cli/_has_core.py +29 -0
  7. buildai_cli-0.1.0/cli/commands/__init__.py +1 -0
  8. buildai_cli-0.1.0/cli/commands/auth_lite.py +79 -0
  9. buildai_cli-0.1.0/cli/commands/auth_ops.py +432 -0
  10. buildai_cli-0.1.0/cli/commands/clips.py +78 -0
  11. buildai_cli-0.1.0/cli/commands/collections.py +57 -0
  12. buildai_cli-0.1.0/cli/commands/database.py +2040 -0
  13. buildai_cli-0.1.0/cli/commands/embed.py +638 -0
  14. buildai_cli-0.1.0/cli/commands/external.py +276 -0
  15. buildai_cli-0.1.0/cli/commands/ingest.py +480 -0
  16. buildai_cli-0.1.0/cli/commands/jobs.py +134 -0
  17. buildai_cli-0.1.0/cli/commands/keys.py +68 -0
  18. buildai_cli-0.1.0/cli/commands/medoid.py +341 -0
  19. buildai_cli-0.1.0/cli/commands/migrate.py +295 -0
  20. buildai_cli-0.1.0/cli/commands/operations.py +48 -0
  21. buildai_cli-0.1.0/cli/commands/partners.py +48 -0
  22. buildai_cli-0.1.0/cli/commands/permissions.py +174 -0
  23. buildai_cli-0.1.0/cli/commands/projection.py +242 -0
  24. buildai_cli-0.1.0/cli/commands/query.py +213 -0
  25. buildai_cli-0.1.0/cli/commands/schema.py +420 -0
  26. buildai_cli-0.1.0/cli/commands/stats.py +44 -0
  27. buildai_cli-0.1.0/cli/commands/sync/__init__.py +104 -0
  28. buildai_cli-0.1.0/cli/commands/sync/apply.py +363 -0
  29. buildai_cli-0.1.0/cli/commands/sync/data.py +437 -0
  30. buildai_cli-0.1.0/cli/commands/sync/ddl.py +327 -0
  31. buildai_cli-0.1.0/cli/commands/sync/diff.py +386 -0
  32. buildai_cli-0.1.0/cli/commands/sync/models.py +216 -0
  33. buildai_cli-0.1.0/cli/commands/sync/queries.py +356 -0
  34. buildai_cli-0.1.0/cli/config.py +67 -0
  35. buildai_cli-0.1.0/cli/console.py +84 -0
  36. buildai_cli-0.1.0/cli/context.py +216 -0
  37. buildai_cli-0.1.0/cli/guard.py +26 -0
  38. buildai_cli-0.1.0/cli/main.py +279 -0
  39. buildai_cli-0.1.0/cli/nl_query/__init__.py +5 -0
  40. buildai_cli-0.1.0/cli/nl_query/dataset_tools.py +191 -0
  41. buildai_cli-0.1.0/cli/ops_init.py +147 -0
  42. buildai_cli-0.1.0/cli/output.py +117 -0
  43. buildai_cli-0.1.0/cli/sdk_client.py +28 -0
  44. buildai_cli-0.1.0/pyproject.toml +41 -0
@@ -0,0 +1,78 @@
1
+ # Worktrees
2
+ .worktrees/
3
+
4
+ # Ralph status files
5
+ .ralph-status
6
+
7
+ # Python
8
+ __pycache__/
9
+ *.py[cod]
10
+ *$py.class
11
+ *.so
12
+ .Python
13
+ .venv/
14
+ venv/
15
+ ENV/
16
+ .eggs/
17
+ *.egg-info/
18
+ dist/
19
+ build/
20
+ .pytest_cache/
21
+ .mypy_cache/
22
+
23
+ # Node
24
+ node_modules/
25
+ .next/
26
+ out/
27
+
28
+ # IDE
29
+ .idea/
30
+ .vscode/
31
+ *.swp
32
+ *.swo
33
+
34
+
35
+ _productivity_inference/
36
+
37
+
38
+ # OS
39
+ .DS_Store
40
+ Thumbs.db
41
+
42
+ # Environment
43
+ .env
44
+ .env.*
45
+ !.env.op
46
+ .env.local
47
+ .env.*.local
48
+ .env-archive/
49
+ .vercel
50
+
51
+ # Benchmark results (large files)
52
+ backend/benchmark-results/
53
+
54
+ # Large binary feature files
55
+ *.npy
56
+
57
+ # V-JEPA2 frame features (39GB+)
58
+ backend/results/vjepa2_frame_features/
59
+
60
+ dashboard-legacy/
61
+ .mcp.json
62
+
63
+ # Reference materials
64
+ reference/
65
+ sd-to-storage/
66
+ .dmux/
67
+ .hypothesis/
68
+
69
+ # Local data cache (frames, manifests, labels)
70
+ .cache/
71
+
72
+ # Generated data artifacts & reports
73
+ scripts/dead_assets.json
74
+ scripts/dead_assets.ids.txt
75
+ scripts/sample_preview.html
76
+ scripts/sample_dataset_report.html
77
+ outputs/
78
+ reference_mobile.png
@@ -0,0 +1 @@
1
+ CLAUDE.md
@@ -0,0 +1,96 @@
1
+ # apps/buildai-cli/
2
+
3
+ Typer CLI with two planes, distributable as a standalone package:
4
+ - **Data plane**: SDK-backed commands (clips, jobs, collections, partners, operations, keys, stats). Requires `BUILDAI_API_KEY`. Works with just `pip install buildai-cli`.
5
+ - **Ops plane**: DAL-direct commands (database, schema, auth CRUD, permissions, ingest, projection, medoid, external). Requires DB access. Install with `pip install 'buildai-cli[ops]'`.
6
+
7
+ ## Architecture
8
+
9
+ - `cli/_has_core.py` — detects if `buildai-core` is installed
10
+ - `cli/ops_init.py` — lazy DB/auth/observability setup (called by ops commands, NOT at startup)
11
+ - `cli/main.py` — lightweight callback, conditional ops registration, stubs when core absent
12
+ - `cli/commands/auth_lite.py` — login + status (no core deps)
13
+ - `cli/commands/auth_ops.py` — API key CRUD (ops-plane, requires core)
14
+
15
+ ## Rules
16
+
17
+ 1. Always run from repo root (`uv run buildai`), never from inside the app directory.
18
+ 2. Default profile is read-only. Mutations require `--profile admin --write`.
19
+ 3. Missing `--write` on mutating commands now errors (not silent no-op).
20
+ 4. All DB access goes through `core/data/` DAL with a `CLIContext`. No raw SQL in commands.
21
+ 5. The `query` command only permits SELECT/WITH/EXPLAIN — it blocks mutations at parse time (via sqlparse AST).
22
+ 6. Data-plane commands go through the SDK — they need an API key, not DB credentials.
23
+ 7. **No `infra` imports at module level** in main.py or data-plane modules.
24
+
25
+ ## Data Plane (SDK-backed)
26
+
27
+ These commands wrap `buildai` SDK resources. Set `BUILDAI_API_KEY` or `buildai auth login <key>`.
28
+
29
+ ```bash
30
+ uv run buildai clips list --factory <id> --limit 5
31
+ uv run buildai jobs list --status running
32
+ uv run buildai jobs retry <id> --write
33
+ uv run buildai collections list
34
+ uv run buildai stats overview
35
+ uv run buildai partners list # internal mode
36
+ uv run buildai operations hours # internal mode
37
+ uv run buildai keys list # internal mode
38
+ ```
39
+
40
+ ## Ops Plane (DAL-direct)
41
+
42
+ ```bash
43
+ uv run buildai --profile readonly database status
44
+ uv run buildai --profile readonly schema tables
45
+ uv run buildai auth status
46
+ ```
47
+
48
+ ## Output
49
+
50
+ - TTY detected: table format (Rich tables)
51
+ - Piped: JSON format (machine-readable)
52
+ - Override: `--format json|table|csv|jsonl`
53
+ - Status/errors go to stderr, data to stdout
54
+
55
+ ## Install
56
+
57
+ ```bash
58
+ # Workspace (all commands — ops + data plane)
59
+ uv pip install -e "apps/buildai-cli[ops]" -e core -e services -e apps/buildai-sdk
60
+
61
+ # Standalone data-plane only
62
+ pip install buildai-cli # or: uv tool install -e ./apps/buildai-cli
63
+
64
+ # Global install
65
+ uv tool install -e ./apps/buildai-cli
66
+ ```
67
+
68
+ ## Run
69
+
70
+ ```bash
71
+ uv run buildai --profile readonly <command>
72
+ uv run buildai --profile admin --write <command>
73
+ ```
74
+
75
+ ## Things That Will Bite You
76
+
77
+ - `uv run buildai` fails with `ModuleNotFoundError` after pulling — reinstall with: `uv pip install -e "apps/buildai-cli[ops]" -e core -e services -e apps/buildai-sdk`
78
+ - `--env production` requires valid production DB credentials.
79
+ - New data-plane command groups: register in `cli/main.py` in the data-plane section.
80
+ - New ops-plane command groups: register in `cli/main.py` via `_register_ops_typer()` inside `if has_core():`, and add to `_OPS_GROUPS` in the else branch.
81
+ - Data-plane commands fail without `BUILDAI_API_KEY` — use `buildai auth login` to configure.
82
+ - `--dry-run` is available on all mutating data-plane commands.
83
+ - Shell completion: `uv run buildai --install-completion`
84
+ - Auth ops commands (create-key, list-keys, show-key, revoke-key) call `init_ops_context()` themselves — they're registered onto the auth_lite app, not via `_register_ops_typer`.
85
+
86
+ ## Closing the Loop
87
+
88
+ When adding a command group: register it in `cli/main.py`. Data-plane = always imported. Ops-plane = behind `has_core()` guard.
89
+
90
+ ## See Also
91
+
92
+ | Topic | File |
93
+ |-------|------|
94
+ | DAL patterns, profiles, Context | `core/CLAUDE.md` |
95
+ | SDK resources | `apps/buildai-sdk/CLAUDE.md` |
96
+ | Common failure modes | `docs/gotchas.md` |
@@ -0,0 +1,21 @@
1
+ Metadata-Version: 2.4
2
+ Name: buildai-cli
3
+ Version: 0.1.0
4
+ Summary: Build AI CLI (Typer)
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: buildai-sdk
7
+ Requires-Dist: python-dotenv>=1.0.0
8
+ Requires-Dist: rich>=13.0.0
9
+ Requires-Dist: typer>=0.12.0
10
+ Provides-Extra: ops
11
+ Requires-Dist: anthropic>=0.73.0; extra == 'ops'
12
+ Requires-Dist: anyio>=4.0.0; extra == 'ops'
13
+ Requires-Dist: buildai-core; extra == 'ops'
14
+ Requires-Dist: buildai-services; extra == 'ops'
15
+ Requires-Dist: claude-agent-sdk>=0.1.6; extra == 'ops'
16
+ Requires-Dist: google-genai>=1.0.0; extra == 'ops'
17
+ Requires-Dist: matplotlib>=3.10.7; extra == 'ops'
18
+ Requires-Dist: questionary>=2.0.1; extra == 'ops'
19
+ Requires-Dist: sqlparse>=0.4.4; extra == 'ops'
20
+ Requires-Dist: textual-plotext>=1.0.1; extra == 'ops'
21
+ Requires-Dist: textual>=6.6.0; extra == 'ops'
@@ -0,0 +1 @@
1
+ """BuildAI Backend CLI."""
@@ -0,0 +1,29 @@
1
+ """Detect whether buildai-core is available."""
2
+
3
+ _cached: bool | None = None
4
+
5
+
6
+ def has_core() -> bool:
7
+ global _cached
8
+ if _cached is None:
9
+ try:
10
+ import infra # noqa: F401
11
+
12
+ _cached = True
13
+ except ImportError:
14
+ _cached = False
15
+ return _cached
16
+
17
+
18
+ def require_core(command_name: str) -> None:
19
+ if not has_core():
20
+ import typer
21
+
22
+ from cli.console import error
23
+
24
+ error(
25
+ f"'{command_name}' requires ops-plane deps.\n"
26
+ f" Install with: pip install 'buildai-cli[ops]'\n"
27
+ f" Or workspace: uv pip install -e 'apps/buildai-cli[ops]' -e core"
28
+ )
29
+ raise typer.Exit(1)
@@ -0,0 +1 @@
1
+ """CLI commands — use direct imports, not this barrel."""
@@ -0,0 +1,79 @@
1
+ """Lightweight auth commands — no core/infra deps."""
2
+
3
+ from typing_extensions import Annotated
4
+
5
+ import typer
6
+
7
+ from cli.config import resolve_cli_api_key, save_cli_config
8
+ from cli.console import console, success
9
+
10
+ app = typer.Typer(
11
+ name="auth",
12
+ help="Authentication and API key management",
13
+ no_args_is_help=True,
14
+ )
15
+
16
+
17
+ @app.command("login")
18
+ def login(
19
+ api_key: Annotated[str, typer.Argument(help="API key to store locally")],
20
+ profile: Annotated[
21
+ str | None,
22
+ typer.Option(
23
+ "--profile",
24
+ "-p",
25
+ help="Default CLI profile (e.g., readonly, mcp, svc_embedder)",
26
+ ),
27
+ ] = None,
28
+ ) -> None:
29
+ """Store an API key and optional profile in ~/.buildai/config.toml."""
30
+ save_cli_config(api_key=api_key, profile=profile)
31
+ success("Saved CLI credentials to ~/.buildai/config.toml")
32
+
33
+
34
+ @app.command("status")
35
+ def auth_status(ctx: typer.Context) -> None:
36
+ """Show current authentication state — gcloud account, API key, profile."""
37
+ import subprocess
38
+
39
+ cli_profile = (ctx.obj or {}).get("cli_profile", "readonly")
40
+
41
+ # gcloud active account
42
+ try:
43
+ result = subprocess.run(
44
+ [
45
+ "gcloud",
46
+ "auth",
47
+ "list",
48
+ "--filter=status=ACTIVE",
49
+ "--format=value(account)",
50
+ ],
51
+ capture_output=True,
52
+ text=True,
53
+ timeout=5,
54
+ )
55
+ gcloud_account = result.stdout.strip() or "not authenticated"
56
+ except Exception:
57
+ gcloud_account = "gcloud not available"
58
+
59
+ console.print(f" gcloud account : [cyan]{gcloud_account}[/cyan]")
60
+ console.print(f" profile : {cli_profile}")
61
+
62
+ # DB environment (only if core available)
63
+ from cli._has_core import has_core
64
+
65
+ if has_core() and ctx.obj and ctx.obj.get("_ops_ready"):
66
+ settings = ctx.obj.get("settings")
67
+ if settings:
68
+ env_color = "yellow" if settings.is_production else "green"
69
+ console.print(f" DB environment : [{env_color}]{settings.app_env.value}[/]")
70
+ else:
71
+ console.print(" DB environment : [dim]n/a (ops-plane not loaded)[/dim]")
72
+
73
+ # API key status
74
+ api_key = resolve_cli_api_key()
75
+ if api_key:
76
+ prefix = api_key[:12] + "..."
77
+ console.print(f" API key : [green]{prefix}[/green]")
78
+ else:
79
+ console.print(" API key : [dim]not configured (set BUILDAI_API_KEY)[/dim]")