databar 2.0.5__tar.gz → 2.0.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.
Files changed (28) hide show
  1. {databar-2.0.5/src/databar.egg-info → databar-2.0.7}/PKG-INFO +1 -1
  2. {databar-2.0.5 → databar-2.0.7}/pyproject.toml +1 -1
  3. {databar-2.0.5 → databar-2.0.7}/src/databar/__init__.py +1 -1
  4. databar-2.0.7/src/databar/cli/_guide.py +237 -0
  5. databar-2.0.7/src/databar/cli/_onboard.py +289 -0
  6. {databar-2.0.5 → databar-2.0.7}/src/databar/cli/app.py +8 -0
  7. {databar-2.0.5 → databar-2.0.7/src/databar.egg-info}/PKG-INFO +1 -1
  8. {databar-2.0.5 → databar-2.0.7}/src/databar.egg-info/SOURCES.txt +1 -0
  9. {databar-2.0.5 → databar-2.0.7}/tests/test_cli.py +1 -1
  10. databar-2.0.5/src/databar/cli/_guide.py +0 -137
  11. {databar-2.0.5 → databar-2.0.7}/LICENSE +0 -0
  12. {databar-2.0.5 → databar-2.0.7}/README.md +0 -0
  13. {databar-2.0.5 → databar-2.0.7}/setup.cfg +0 -0
  14. {databar-2.0.5 → databar-2.0.7}/src/databar/cli/__init__.py +0 -0
  15. {databar-2.0.5 → databar-2.0.7}/src/databar/cli/_auth.py +0 -0
  16. {databar-2.0.5 → databar-2.0.7}/src/databar/cli/_output.py +0 -0
  17. {databar-2.0.5 → databar-2.0.7}/src/databar/cli/enrichments.py +0 -0
  18. {databar-2.0.5 → databar-2.0.7}/src/databar/cli/tables.py +0 -0
  19. {databar-2.0.5 → databar-2.0.7}/src/databar/cli/tasks.py +0 -0
  20. {databar-2.0.5 → databar-2.0.7}/src/databar/cli/waterfalls.py +0 -0
  21. {databar-2.0.5 → databar-2.0.7}/src/databar/client.py +0 -0
  22. {databar-2.0.5 → databar-2.0.7}/src/databar/exceptions.py +0 -0
  23. {databar-2.0.5 → databar-2.0.7}/src/databar/models.py +0 -0
  24. {databar-2.0.5 → databar-2.0.7}/src/databar.egg-info/dependency_links.txt +0 -0
  25. {databar-2.0.5 → databar-2.0.7}/src/databar.egg-info/entry_points.txt +0 -0
  26. {databar-2.0.5 → databar-2.0.7}/src/databar.egg-info/requires.txt +0 -0
  27. {databar-2.0.5 → databar-2.0.7}/src/databar.egg-info/top_level.txt +0 -0
  28. {databar-2.0.5 → databar-2.0.7}/tests/test_client.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: databar
3
- Version: 2.0.5
3
+ Version: 2.0.7
4
4
  Summary: Official Databar.ai Python SDK and CLI — connect to enrichments, waterfalls, and tables via api.databar.ai
5
5
  Author-email: "Databar.ai Team" <info@databar.ai>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "databar"
7
- version = "2.0.5"
7
+ version = "2.0.7"
8
8
  description = "Official Databar.ai Python SDK and CLI — connect to enrichments, waterfalls, and tables via api.databar.ai"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -58,7 +58,7 @@ from .models import (
58
58
  WaterfallEnrichment,
59
59
  )
60
60
 
61
- __version__ = "2.0.5"
61
+ __version__ = "2.0.7"
62
62
  __all__ = [
63
63
  "DatabarClient",
64
64
  # exceptions
@@ -0,0 +1,237 @@
1
+ """Embedded agent guide — printed by `databar agent-guide`."""
2
+
3
+ AGENT_GUIDE = r"""# Databar — Agent Guide
4
+
5
+ Databar is a data enrichment platform. The `databar` package ships both a
6
+ **CLI** and a **Python SDK**. This guide tells you exactly how to set up and
7
+ use each, including common pitfalls.
8
+
9
+ ---
10
+
11
+ ## STEP 1 — Check authentication
12
+
13
+ Before doing anything else, check whether the user is already authenticated:
14
+
15
+ ```bash
16
+ # Check 1: env var
17
+ echo $DATABAR_API_KEY
18
+
19
+ # Check 2: saved config
20
+ cat ~/.databar/config
21
+ ```
22
+
23
+ If neither exists, the user is not authenticated. Ask them in chat:
24
+
25
+ "Please provide your Databar API key. You can find it at databar.ai → Settings → API Keys."
26
+
27
+ Once they give it to you, save it non-interactively:
28
+
29
+ ```bash
30
+ databar login --api-key <key they provided>
31
+ databar whoami --format json # verify it works
32
+ ```
33
+
34
+ Never run `databar onboard` — that is an interactive wizard for humans, not agents.
35
+ Never run `databar login` without `--api-key` — it will hang waiting for terminal input.
36
+
37
+ ---
38
+
39
+ ## STEP 2 — Ask the user which interface they prefer
40
+
41
+ **Always ask this before starting work** (unless ~/.databar/config already contains
42
+ `preferred_interface=`):
43
+
44
+ "Databar has two interfaces:
45
+ - **CLI** — terminal commands, great for single operations, pipeable JSON output,
46
+ no code to write. Best for straightforward tasks.
47
+ - **Python SDK** — import DatabarClient, full control, required for conditional
48
+ logic (e.g. 'only enrich rows where email is verified') and multi-step pipelines
49
+ with branching.
50
+ - **Both** — use CLI for simple lookups, Python for complex workflows.
51
+
52
+ Which do you prefer? (default: CLI)"
53
+
54
+ Save their preference:
55
+
56
+ ```bash
57
+ # After they answer, append to config:
58
+ echo "preferred_interface=cli" >> ~/.databar/config # or: python, both
59
+ ```
60
+
61
+ Default to CLI if they don't answer or say they don't mind.
62
+
63
+ ---
64
+
65
+ ## STEP 3 — Set up the CLI (IMPORTANT — read carefully)
66
+
67
+ ### The PATH problem
68
+
69
+ After `pip install databar`, the `databar` binary is installed to the Python
70
+ user bin directory — but this directory is NOT on PATH by default on most systems.
71
+
72
+ **Always check this first:**
73
+
74
+ ```bash
75
+ which databar # if this prints nothing, databar is not on PATH
76
+ databar --version # if this says "command not found", fix PATH before continuing
77
+ ```
78
+
79
+ **If databar is not on PATH, fix it:**
80
+
81
+ ```bash
82
+ # Find where it's installed
83
+ python3 -m site --user-base # e.g. /Users/alice/Library/Python/3.9
84
+
85
+ # The binary is at <user-base>/bin/databar
86
+ # Add to PATH for this session:
87
+ export PATH="$(python3 -m site --user-base)/bin:$PATH"
88
+
89
+ # Verify it works now:
90
+ databar --version
91
+ ```
92
+
93
+ Tell the user to add that export line to their `~/.zshrc` or `~/.bashrc` to make
94
+ it permanent. You can offer to do it:
95
+
96
+ ```bash
97
+ echo 'export PATH="$(python3 -m site --user-base)/bin:$PATH"' >> ~/.zshrc
98
+ ```
99
+
100
+ ### CLI vs Python — when to use each
101
+
102
+ Use CLI when:
103
+ - Running a single enrichment or waterfall on known inputs
104
+ - Listing/searching enrichments, waterfalls, or tables
105
+ - Creating tables, inserting rows from CSV or JSON
106
+ - Running table enrichments
107
+ - The task is straightforward with no branching logic
108
+
109
+ Use Python SDK when:
110
+ - You need to branch on results (e.g. only process rows where a field matches)
111
+ - You're building a multi-step pipeline where step N depends on step N-1's output
112
+ - You need to loop over results and make decisions per row
113
+ - The task requires data transformation between steps
114
+
115
+ ---
116
+
117
+ ## CLI Quick Reference
118
+
119
+ All commands support `--format table|json|csv` (default: table).
120
+ **Always use `--format json` when you need to parse or pipe the output.**
121
+ The default `table` format uses Rich terminal formatting that is not machine-parseable.
122
+
123
+ ### Enrichments
124
+ ```bash
125
+ databar enrich list --format json # list all enrichments
126
+ databar enrich list --query "email verifier" --format json # search
127
+ databar enrich get <id> --format json # params + response fields
128
+ databar enrich choices <id> <param> --format json # choices for a select param
129
+ databar enrich run <id> --params '{"email": "a@b.com"}' --format json
130
+ databar enrich bulk <id> --input data.csv --out results.csv
131
+ ```
132
+
133
+ ### Waterfalls
134
+ ```bash
135
+ databar waterfall list --format json
136
+ databar waterfall get <identifier> --format json
137
+ databar waterfall run <identifier> --params '{"linkedin_url": "..."}' --format json
138
+ databar waterfall bulk <identifier> --input data.csv --out results.csv
139
+ ```
140
+
141
+ ### Tables
142
+ ```bash
143
+ databar table list --format json
144
+ databar table create --name "My Table" --columns "email,name,company"
145
+ databar table columns <table-uuid> --format json
146
+ databar table rows <table-uuid> --format json
147
+
148
+ databar table insert <table-uuid> --data '[{"email":"a@b.com"}]'
149
+ databar table insert <table-uuid> --input data.csv --allow-new-columns
150
+
151
+ databar table enrichments <table-uuid> --format json
152
+ databar table add-enrichment <table-uuid> --enrichment-id <id> --mapping '{"param": "col_name"}'
153
+ databar table run-enrichment <table-uuid> --enrichment-id <TABLE-ENRICHMENT-ID>
154
+ ```
155
+
156
+ IMPORTANT: `run-enrichment` takes the TABLE-ENRICHMENT ID (from `add-enrichment` output or
157
+ `table enrichments`), NOT the catalog enrichment ID. These are different numbers.
158
+
159
+ ### Tasks
160
+ ```bash
161
+ databar task get <task-id> --format json # check status once
162
+ databar task get <task-id> --poll # poll until complete
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Python SDK Quick Reference
168
+
169
+ ```python
170
+ from databar import DatabarClient
171
+
172
+ client = DatabarClient() # reads DATABAR_API_KEY or ~/.databar/config automatically
173
+
174
+ # Enrichments
175
+ enrichments = client.list_enrichments(q="email verifier")
176
+ enrichment = client.get_enrichment(123)
177
+ # enrichment.params[i].name → parameter slug (use as key in params dict)
178
+ # enrichment.params[i].is_required → bool
179
+ # enrichment.params[i].description → human label
180
+ # enrichment.response_fields[i].name → output field name
181
+
182
+ result = client.run_enrichment_sync(123, {"email": "alice@example.com"})
183
+ # result["data"] contains the enrichment output
184
+
185
+ # Waterfalls
186
+ waterfalls = client.list_waterfalls()
187
+ # waterfall.identifier (also .slug) → slug like "email_getter"
188
+ result = client.run_waterfall_sync("email_getter", {"linkedin_url": "..."})
189
+
190
+ # Tables
191
+ tables = client.list_tables()
192
+ # table.identifier (also .id, .uuid) → UUID string
193
+
194
+ table = client.create_table(name="Leads", columns=["email", "name"])
195
+ resp = client.get_rows(table.identifier)
196
+ # resp.data → list of row dicts keyed by column name
197
+ # resp.has_next_page → bool
198
+ # resp.total_count → int
199
+ # resp.page → int
200
+
201
+ from databar import InsertRow
202
+ client.create_rows(table.identifier, [
203
+ InsertRow(fields={"email": "alice@example.com", "name": "Alice"}),
204
+ ])
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Key Concepts
210
+
211
+ - All enrichment/waterfall runs are async. The `*_sync` CLI and SDK methods handle
212
+ submit + poll automatically. For manual polling use `task get --poll` or `poll_task()`.
213
+ - `task_id` is the only task identifier. Results expire after 1 hour (status = "gone").
214
+ - Table enrichments are two steps: add (links enrichment to table) → run (triggers execution).
215
+ The ID returned by add is the TABLE-ENRICHMENT ID — different from the catalog ID.
216
+ - The SDK auto-resolves column names to UUIDs in `add_enrichment()`.
217
+
218
+ ## Model Field Aliases (Python SDK)
219
+
220
+ - `Table`: `.id`, `.uuid` → `.identifier`
221
+ - `Waterfall`: `.slug` → `.identifier`
222
+ - `EnrichmentParam`: `.slug` → `.name`, `.label` → `.description`, `.required` → `.is_required`
223
+ - `EnrichmentResponseField`: `.slug` → `.name`
224
+
225
+ ## Error Handling (Python SDK)
226
+
227
+ ```python
228
+ from databar import (
229
+ DatabarAuthError, # 401/403 — bad or missing API key
230
+ DatabarInsufficientCreditsError, # 406 — not enough credits
231
+ DatabarNotFoundError, # 404 — enrichment/table not found
232
+ DatabarTaskFailedError, # task completed with error
233
+ DatabarTimeoutError, # polling timed out
234
+ DatabarGoneError, # task data expired (>1 hour)
235
+ )
236
+ ```
237
+ """
@@ -0,0 +1,289 @@
1
+ """
2
+ `databar onboard` — interactive first-run setup wizard.
3
+
4
+ Guides the user through:
5
+ 1. Displaying the Databar welcome banner
6
+ 2. API key entry & verification
7
+ 3. PATH detection & optional auto-fix
8
+ 4. Usage preference (CLI / Python SDK / both)
9
+ 5. Tailored next-steps cheatsheet
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import os
15
+ import shutil
16
+ import sys
17
+ from pathlib import Path
18
+
19
+ import typer
20
+ from rich.console import Console
21
+ from rich.panel import Panel
22
+ from rich.prompt import Confirm, Prompt
23
+ from rich.rule import Rule
24
+ from rich.text import Text
25
+
26
+ console = Console()
27
+
28
+ # ---------------------------------------------------------------------------
29
+ # ASCII banner
30
+ # ---------------------------------------------------------------------------
31
+
32
+ BANNER = r"""
33
+ ____ _ _
34
+ | _ \ __ _| |_ __ _| |__ __ _ _ __
35
+ | | | |/ _` | __/ _` | '_ \ / _` | '__|
36
+ | |_| | (_| | || (_| | |_) | (_| | |
37
+ |____/ \__,_|\__\__,_|_.__/ \__,_|_|
38
+
39
+ """
40
+
41
+ TAGLINE = "Data enrichment at your fingertips."
42
+
43
+ # ---------------------------------------------------------------------------
44
+ # Config helpers (mirrors _auth.py)
45
+ # ---------------------------------------------------------------------------
46
+
47
+ CONFIG_DIR = Path.home() / ".databar"
48
+ CONFIG_FILE = CONFIG_DIR / "config"
49
+ _KEY_PREFIX = "api_key="
50
+ _PREF_PREFIX = "preferred_interface="
51
+
52
+
53
+ def _save_key(api_key: str) -> None:
54
+ CONFIG_DIR.mkdir(parents=True, exist_ok=True)
55
+ lines: list[str] = []
56
+ if CONFIG_FILE.exists():
57
+ lines = [
58
+ l for l in CONFIG_FILE.read_text().splitlines()
59
+ if not l.startswith(_KEY_PREFIX)
60
+ ]
61
+ lines.append(f"{_KEY_PREFIX}{api_key}")
62
+ CONFIG_FILE.write_text("\n".join(lines) + "\n")
63
+ CONFIG_FILE.chmod(0o600)
64
+
65
+
66
+ def _save_preference(pref: str) -> None:
67
+ lines: list[str] = []
68
+ if CONFIG_FILE.exists():
69
+ lines = [
70
+ l for l in CONFIG_FILE.read_text().splitlines()
71
+ if not l.startswith(_PREF_PREFIX)
72
+ ]
73
+ lines.append(f"{_PREF_PREFIX}{pref}")
74
+ CONFIG_FILE.write_text("\n".join(lines) + "\n")
75
+
76
+
77
+ def _get_bin_dir() -> Path:
78
+ return Path(sys.executable).parent
79
+
80
+
81
+ def _databar_on_path() -> bool:
82
+ return shutil.which("databar") is not None
83
+
84
+
85
+ def _detect_shell_profile() -> Path | None:
86
+ shell = os.environ.get("SHELL", "")
87
+ home = Path.home()
88
+ if "zsh" in shell:
89
+ return home / ".zshrc"
90
+ if "bash" in shell:
91
+ profile = home / ".bash_profile"
92
+ return profile if profile.exists() else home / ".bashrc"
93
+ return None
94
+
95
+
96
+ def _add_to_path(bin_dir: Path) -> bool:
97
+ """Append export PATH line to the detected shell profile. Returns True on success."""
98
+ profile = _detect_shell_profile()
99
+ if profile is None:
100
+ return False
101
+ export_line = f'\nexport PATH="{bin_dir}:$PATH" # added by databar onboard\n'
102
+ with open(profile, "a") as f:
103
+ f.write(export_line)
104
+ return True
105
+
106
+
107
+ # ---------------------------------------------------------------------------
108
+ # Onboard steps
109
+ # ---------------------------------------------------------------------------
110
+
111
+ def _print_banner() -> None:
112
+ banner_text = Text(BANNER, style="bold cyan")
113
+ tagline_text = Text(f" {TAGLINE}\n", style="dim")
114
+ console.print(banner_text, end="")
115
+ console.print(tagline_text)
116
+ console.print(Rule(style="cyan"))
117
+ console.print()
118
+
119
+
120
+ def _step_api_key() -> str | None:
121
+ """Prompt for API key, save it, and verify with a whoami call."""
122
+ console.print("[bold]Step 1 — Connect your account[/bold]")
123
+ console.print(
124
+ "[dim]Get your API key at [link=https://databar.ai]databar.ai[/link] "
125
+ "→ Settings → API Keys[/dim]\n"
126
+ )
127
+
128
+ existing_key: str | None = None
129
+ if CONFIG_FILE.exists():
130
+ for line in CONFIG_FILE.read_text().splitlines():
131
+ if line.startswith(_KEY_PREFIX):
132
+ existing_key = line[len(_KEY_PREFIX):].strip()
133
+ break
134
+ if not existing_key:
135
+ existing_key = os.environ.get("DATABAR_API_KEY", "").strip() or None
136
+
137
+ if existing_key:
138
+ masked = existing_key[:6] + "•" * (len(existing_key) - 10) + existing_key[-4:]
139
+ use_existing = Confirm.ask(
140
+ f" Found existing key [bold]{masked}[/bold] — use it?",
141
+ default=True,
142
+ )
143
+ if use_existing:
144
+ api_key = existing_key
145
+ else:
146
+ api_key = Prompt.ask(" Enter your Databar API key", password=True).strip()
147
+ else:
148
+ api_key = Prompt.ask(" Enter your Databar API key", password=True).strip()
149
+
150
+ if not api_key:
151
+ console.print("[yellow] Skipped — you can run `databar login` later.[/yellow]\n")
152
+ return None
153
+
154
+ console.print(" [dim]Verifying…[/dim]", end="")
155
+ try:
156
+ from databar.client import DatabarClient
157
+ client = DatabarClient(api_key=api_key)
158
+ user = client.get_user()
159
+ client.close()
160
+ _save_key(api_key)
161
+ console.print(
162
+ f"\r [bold green]✓[/bold green] Authenticated as "
163
+ f"[bold]{user.first_name or user.email}[/bold] "
164
+ f"([dim]{user.balance:.0f} credits[/dim])\n"
165
+ )
166
+ return api_key
167
+ except Exception as e:
168
+ console.print(f"\r [bold red]✗[/bold red] Could not verify key: {e}\n")
169
+ console.print(" [dim]Key not saved. Run `databar login` to try again.[/dim]\n")
170
+ return None
171
+
172
+
173
+ def _step_path() -> None:
174
+ """Check PATH and offer to fix it."""
175
+ console.print("[bold]Step 2 — Fix PATH (so `databar` works anywhere)[/bold]")
176
+
177
+ if _databar_on_path():
178
+ console.print(" [bold green]✓[/bold green] `databar` is already on your PATH.\n")
179
+ return
180
+
181
+ bin_dir = _get_bin_dir()
182
+ console.print(
183
+ f" [yellow]![/yellow] `databar` is not on PATH.\n"
184
+ f" It's installed at: [bold]{bin_dir}/databar[/bold]\n"
185
+ )
186
+
187
+ profile = _detect_shell_profile()
188
+ profile_label = str(profile) if profile else "your shell profile"
189
+ fix = Confirm.ask(
190
+ f" Add `{bin_dir}` to PATH in {profile_label} automatically?",
191
+ default=True,
192
+ )
193
+ if fix:
194
+ ok = _add_to_path(bin_dir)
195
+ if ok:
196
+ console.print(
197
+ f" [bold green]✓[/bold green] Added to {profile_label}.\n"
198
+ f" Run [bold]source {profile_label}[/bold] or open a new terminal to apply.\n"
199
+ )
200
+ else:
201
+ console.print(
202
+ f" [yellow]Could not detect your shell profile.[/yellow]\n"
203
+ f" Add this manually:\n\n"
204
+ f" [bold]export PATH=\"{bin_dir}:$PATH\"[/bold]\n"
205
+ )
206
+ else:
207
+ console.print(
208
+ f" [dim]Skipped. Use the full path for now: [bold]{bin_dir}/databar[/bold][/dim]\n"
209
+ )
210
+
211
+
212
+ def _step_preference() -> str:
213
+ """Ask how the user plans to use Databar and return their choice."""
214
+ console.print("[bold]Step 3 — How do you plan to use Databar?[/bold]\n")
215
+ console.print(" [bold cyan]1[/bold cyan] CLI — terminal commands, scripts, AI agents (Claude Code etc.)")
216
+ console.print(" [bold cyan]2[/bold cyan] Python — import DatabarClient in your Python code")
217
+ console.print(" [bold cyan]3[/bold cyan] Both — I'll use whichever fits the task\n")
218
+
219
+ choice = Prompt.ask(" Your choice", choices=["1", "2", "3"], default="3")
220
+ pref_map = {"1": "cli", "2": "python", "3": "both"}
221
+ pref = pref_map[choice]
222
+ _save_preference(pref)
223
+ console.print()
224
+ return pref
225
+
226
+
227
+ def _step_next_steps(pref: str) -> None:
228
+ """Print tailored next steps based on preference."""
229
+ console.print(Rule(style="cyan"))
230
+ console.print()
231
+ console.print("[bold green]You're all set![/bold green] Here's where to start:\n")
232
+
233
+ if pref in ("cli", "both"):
234
+ console.print(Panel(
235
+ "[bold]CLI Quick Start[/bold]\n\n"
236
+ " databar enrich list [dim]# browse enrichments[/dim]\n"
237
+ " databar enrich get <id> [dim]# inspect params[/dim]\n"
238
+ " databar enrich run <id> --params '{...}' [dim]# run one row[/dim]\n"
239
+ " databar enrich bulk <id> --input data.csv [dim]# bulk from CSV[/dim]\n\n"
240
+ " databar waterfall list\n"
241
+ " databar waterfall run <identifier> --params '{...}'\n\n"
242
+ " databar table create --name 'Leads' --columns 'email,name'\n"
243
+ " databar table rows <uuid> --format json\n\n"
244
+ " [dim]Tip: always use --format json when piping output.[/dim]",
245
+ border_style="cyan",
246
+ title="[cyan]CLI[/cyan]",
247
+ ))
248
+
249
+ if pref in ("python", "both"):
250
+ console.print(Panel(
251
+ "[bold]Python SDK Quick Start[/bold]\n\n"
252
+ " from databar import DatabarClient\n\n"
253
+ " client = DatabarClient() [dim]# reads DATABAR_API_KEY from env or ~/.databar/config[/dim]\n\n"
254
+ " enrichments = client.list_enrichments(q='email')\n"
255
+ " result = client.run_enrichment_sync(123, {'email': 'alice@example.com'})\n\n"
256
+ " tables = client.list_tables()\n"
257
+ " rows = client.get_rows(table.identifier) [dim]# returns RowsResponse[/dim]\n"
258
+ " rows.data [dim]# list of row dicts[/dim]",
259
+ border_style="cyan",
260
+ title="[cyan]Python[/cyan]",
261
+ ))
262
+
263
+ console.print(
264
+ "\n [dim]Full reference: [bold]databar agent-guide[/bold] | "
265
+ "Docs: [link=https://build.databar.ai]build.databar.ai[/link][/dim]\n"
266
+ )
267
+
268
+
269
+ # ---------------------------------------------------------------------------
270
+ # Command entry point
271
+ # ---------------------------------------------------------------------------
272
+
273
+ def onboard() -> None:
274
+ """Interactive setup wizard — configure auth, PATH, and get started."""
275
+ _print_banner()
276
+ console.print(
277
+ " Welcome to [bold cyan]Databar[/bold cyan]! This wizard takes ~1 minute "
278
+ "and sets up everything you need.\n"
279
+ " [dim]Press Ctrl+C at any time to exit.[/dim]\n"
280
+ )
281
+
282
+ try:
283
+ _step_api_key()
284
+ _step_path()
285
+ pref = _step_preference()
286
+ _step_next_steps(pref)
287
+ except (KeyboardInterrupt, typer.Abort):
288
+ console.print("\n\n[dim]Onboarding cancelled. Run `databar onboard` any time to restart.[/dim]")
289
+ raise typer.Exit(0)
@@ -30,6 +30,14 @@ app.add_typer(tables.app, name="table")
30
30
  app.add_typer(tasks.app, name="task")
31
31
 
32
32
 
33
+ @app.command("onboard")
34
+ def onboard() -> None:
35
+ """Interactive setup wizard — configure auth, PATH, and get started."""
36
+ from ._onboard import onboard as _run_onboard
37
+
38
+ _run_onboard()
39
+
40
+
33
41
  @app.command("agent-guide")
34
42
  def agent_guide() -> None:
35
43
  """Print the full agent usage guide (SDK + CLI reference for AI agents)."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: databar
3
- Version: 2.0.5
3
+ Version: 2.0.7
4
4
  Summary: Official Databar.ai Python SDK and CLI — connect to enrichments, waterfalls, and tables via api.databar.ai
5
5
  Author-email: "Databar.ai Team" <info@databar.ai>
6
6
  License: MIT License
@@ -14,6 +14,7 @@ src/databar.egg-info/top_level.txt
14
14
  src/databar/cli/__init__.py
15
15
  src/databar/cli/_auth.py
16
16
  src/databar/cli/_guide.py
17
+ src/databar/cli/_onboard.py
17
18
  src/databar/cli/_output.py
18
19
  src/databar/cli/app.py
19
20
  src/databar/cli/enrichments.py
@@ -329,4 +329,4 @@ def test_task_get_poll(monkeypatch):
329
329
  def test_version_flag():
330
330
  result = runner.invoke(app, ["--version"])
331
331
  assert result.exit_code == 0
332
- assert "2.0.5" in result.output
332
+ assert "2.0.7" in result.output
@@ -1,137 +0,0 @@
1
- """Embedded agent guide — printed by `databar agent-guide`."""
2
-
3
- AGENT_GUIDE = r"""# Databar SDK & CLI — Agent Guide
4
-
5
- Official Databar Python SDK and CLI (`pip install databar`).
6
- Run data enrichments, waterfall lookups, and manage tables via api.databar.ai/v1.
7
-
8
- ## Setup
9
-
10
- ```bash
11
- pip install databar
12
- export DATABAR_API_KEY=YOUR_API_KEY # or: databar login --api-key YOUR_API_KEY
13
- databar whoami # verify auth
14
- ```
15
-
16
- If `databar` command not found after install:
17
- ```bash
18
- export PATH="$(python3 -m site --user-base)/bin:$PATH"
19
- ```
20
-
21
- ## CLI Quick Reference
22
-
23
- All commands support `--format table|json|csv` (default: table) and `--help`.
24
- **For machine-parseable output, always use `--format json`.**
25
-
26
- ### Enrichments
27
- ```
28
- databar enrich list # list all enrichments
29
- databar enrich list --query "linkedin" # search enrichments
30
- databar enrich get <id> # get enrichment details (params, response fields)
31
- databar enrich choices <id> <param> # list choices for a select param
32
- databar enrich run <id> --params '{"key": "value"}' # run single
33
- databar enrich bulk <id> --input data.csv --out results.csv
34
- ```
35
-
36
- ### Waterfalls
37
- ```
38
- databar waterfall list
39
- databar waterfall get <identifier> # e.g. email_getter
40
- databar waterfall run <identifier> --params '{"key": "value"}'
41
- databar waterfall bulk <identifier> --input data.csv --out results.csv
42
- ```
43
-
44
- ### Tables
45
- ```
46
- databar table list
47
- databar table create --name "My Table" --columns "email,name,company"
48
- databar table columns <table-uuid>
49
- databar table rows <table-uuid>
50
- databar table rows <table-uuid> --format json
51
-
52
- databar table insert <table-uuid> --data '[{"email":"a@b.com","name":"Alice"}]'
53
- databar table insert <table-uuid> --input data.csv --allow-new-columns
54
-
55
- databar table enrichments <table-uuid>
56
- databar table add-enrichment <table-uuid> --enrichment-id <id> --mapping '{"param": "column_name"}'
57
- databar table run-enrichment <table-uuid> --enrichment-id <TABLE-ENRICHMENT-ID>
58
- ```
59
-
60
- Note: `run-enrichment` uses the TABLE-ENRICHMENT ID (from `add-enrichment` or `table enrichments`), NOT the catalog enrichment ID.
61
-
62
- ### Tasks
63
- ```
64
- databar task get <task-id> # check status once
65
- databar task get <task-id> --poll # poll until complete
66
- ```
67
-
68
- ### Account
69
- ```
70
- databar whoami
71
- databar whoami --format json
72
- ```
73
-
74
- ## Python SDK Quick Reference
75
-
76
- ```python
77
- from databar import DatabarClient
78
-
79
- client = DatabarClient() # reads DATABAR_API_KEY from env
80
-
81
- # Enrichments
82
- enrichments = client.list_enrichments(q="linkedin")
83
- enrichment = client.get_enrichment(123)
84
- # enrichment.params → list of EnrichmentParam (fields: .name, .is_required, .description)
85
- # enrichment.response_fields → list of EnrichmentResponseField (fields: .name, .type_field)
86
-
87
- result = client.run_enrichment_sync(123, {"email": "alice@example.com"})
88
-
89
- # Waterfalls
90
- waterfalls = client.list_waterfalls()
91
- # waterfall.identifier → slug like "email_getter" (also available as .slug)
92
- result = client.run_waterfall_sync("email_getter", {"linkedin_url": "..."})
93
-
94
- # Tables
95
- tables = client.list_tables()
96
- # table.identifier → UUID (also available as .id and .uuid)
97
- table = client.create_table(name="Leads", columns=["email", "name"])
98
- resp = client.get_rows(table.identifier)
99
- # resp.data → list of row dicts, resp.has_next_page, resp.total_count, resp.page
100
-
101
- from databar import InsertRow
102
- client.create_rows(table.identifier, [
103
- InsertRow(fields={"email": "alice@example.com", "name": "Alice"}),
104
- ])
105
- ```
106
-
107
- ## Key Concepts
108
-
109
- - All enrichment/waterfall runs are async: submit → get task_id → poll until completed.
110
- The `*_sync` methods handle this automatically.
111
- - task_id is the universal identifier for polling. Use it with poll_task() or `databar task get`.
112
- - Results expire after 1 hour (status becomes "gone").
113
- - Table enrichments are a two-step process: add_enrichment() then run_table_enrichment().
114
- The ID from add_enrichment is a TABLE-ENRICHMENT ID, different from the catalog enrichment ID.
115
- - The SDK auto-resolves column names to UUIDs in add_enrichment().
116
-
117
- ## Model Field Aliases
118
-
119
- Common aliases that work on all models:
120
- - Table: .id, .uuid → .identifier
121
- - Waterfall: .slug → .identifier
122
- - EnrichmentParam: .slug → .name, .label → .description, .required → .is_required
123
- - EnrichmentResponseField: .slug → .name, .label → .name
124
-
125
- ## Error Handling
126
-
127
- ```python
128
- from databar import (
129
- DatabarAuthError, # 401/403
130
- DatabarInsufficientCreditsError, # 406
131
- DatabarNotFoundError, # 404
132
- DatabarTaskFailedError, # task completed with error
133
- DatabarTimeoutError, # polling timed out
134
- DatabarGoneError, # task data expired (>1 hour)
135
- )
136
- ```
137
- """
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes