databar 2.0.7__tar.gz → 2.0.9__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.
- {databar-2.0.7/src/databar.egg-info → databar-2.0.9}/PKG-INFO +1 -1
- {databar-2.0.7 → databar-2.0.9}/pyproject.toml +1 -1
- {databar-2.0.7 → databar-2.0.9}/src/databar/__init__.py +1 -1
- databar-2.0.9/src/databar/cli/_guide.py +219 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar/cli/_onboard.py +76 -5
- {databar-2.0.7 → databar-2.0.9}/src/databar/cli/app.py +4 -1
- {databar-2.0.7 → databar-2.0.9}/src/databar/client.py +8 -1
- {databar-2.0.7 → databar-2.0.9/src/databar.egg-info}/PKG-INFO +1 -1
- {databar-2.0.7 → databar-2.0.9}/tests/test_cli.py +1 -1
- databar-2.0.7/src/databar/cli/_guide.py +0 -237
- {databar-2.0.7 → databar-2.0.9}/LICENSE +0 -0
- {databar-2.0.7 → databar-2.0.9}/README.md +0 -0
- {databar-2.0.7 → databar-2.0.9}/setup.cfg +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar/cli/__init__.py +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar/cli/_auth.py +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar/cli/_output.py +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar/cli/enrichments.py +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar/cli/tables.py +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar/cli/tasks.py +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar/cli/waterfalls.py +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar/exceptions.py +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar/models.py +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar.egg-info/SOURCES.txt +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar.egg-info/dependency_links.txt +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar.egg-info/entry_points.txt +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar.egg-info/requires.txt +0 -0
- {databar-2.0.7 → databar-2.0.9}/src/databar.egg-info/top_level.txt +0 -0
- {databar-2.0.7 → databar-2.0.9}/tests/test_client.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "databar"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.9"
|
|
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" }
|
|
@@ -0,0 +1,219 @@
|
|
|
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. Given an input (email, LinkedIn URL, company
|
|
6
|
+
domain, etc.) it returns enriched data from dozens of providers. The `databar` package
|
|
7
|
+
ships three interfaces: a **CLI**, a **Python SDK**, and an **MCP server**.
|
|
8
|
+
|
|
9
|
+
Databar supports two enrichment workflows:
|
|
10
|
+
|
|
11
|
+
- **Direct** — submit inputs and get results back immediately. Best for one-off lookups
|
|
12
|
+
or bulk CSV processing where you just need the output.
|
|
13
|
+
- **Table-based** — create a table, upload rows, attach enrichments, run them. Results
|
|
14
|
+
appear as new columns on each row. Best when you want observability (see results in
|
|
15
|
+
the Databar UI), re-run enrichments on the same data, or build a persistent dataset.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## DECISION MATRIX — read this first
|
|
20
|
+
|
|
21
|
+
+----------------------------------+--------------------+
|
|
22
|
+
| Situation | Use |
|
|
23
|
+
+----------------------------------+--------------------+
|
|
24
|
+
| MCP tools available this session | MCP (best option) |
|
|
25
|
+
| Single operation, no branching | CLI |
|
|
26
|
+
| Conditional logic / loops / | Python SDK |
|
|
27
|
+
| multi-step pipeline with | |
|
|
28
|
+
| decisions per row | |
|
|
29
|
+
+----------------------------------+--------------------+
|
|
30
|
+
|
|
31
|
+
**Default: CLI.** Use Python SDK only when you need to branch on results or loop
|
|
32
|
+
with per-row decisions. Use MCP when it is configured — it requires zero setup.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## STEP 1 — Check authentication
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
echo $DATABAR_API_KEY # check env var
|
|
40
|
+
cat ~/.databar/config # check saved config (file has no extension)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
If neither exists, ask the user in chat:
|
|
44
|
+
"Please provide your Databar API key (databar.ai → Settings → API Keys)."
|
|
45
|
+
|
|
46
|
+
Then save it non-interactively:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
databar login --api-key <key>
|
|
50
|
+
databar whoami --format json # verify
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Never run `databar onboard` — interactive wizard, not for agents.
|
|
54
|
+
Never run `databar login` without `--api-key` — will hang on terminal input.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## STEP 2 — Ask the user their preferred interface AND workflow
|
|
59
|
+
|
|
60
|
+
Unless ~/.databar/config already contains `preferred_interface=`, ask:
|
|
61
|
+
|
|
62
|
+
"Databar has three interfaces — which do you prefer?
|
|
63
|
+
- CLI (default) — terminal commands, no code, pipeable JSON. Best for single operations.
|
|
64
|
+
- Python SDK — required for conditional logic, loops, multi-step pipelines with branching.
|
|
65
|
+
- MCP — if configured in your Claude session, it's the most agent-native option.
|
|
66
|
+
Which do you prefer?"
|
|
67
|
+
|
|
68
|
+
Also ask about workflow preference:
|
|
69
|
+
|
|
70
|
+
"Databar supports two enrichment workflows — which fits your use case?
|
|
71
|
+
- Direct (default) — submit inputs, get results back immediately. Good for one-off
|
|
72
|
+
lookups or bulk CSV jobs where you just need the output fast.
|
|
73
|
+
- Table-based — create a table, upload rows, attach enrichments, then run them.
|
|
74
|
+
Results appear as new columns in the Databar UI. Best when you want observability,
|
|
75
|
+
plan to re-run enrichments, or want to pair with the Databar web interface.
|
|
76
|
+
Which do you prefer?"
|
|
77
|
+
|
|
78
|
+
Save their answers:
|
|
79
|
+
```bash
|
|
80
|
+
echo "preferred_interface=cli" >> ~/.databar/config # or: python, mcp, both
|
|
81
|
+
echo "preferred_workflow=direct" >> ~/.databar/config # or: table
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## STEP 3 — Fix PATH before using the CLI
|
|
87
|
+
|
|
88
|
+
After `pip install databar`, the binary is NOT on PATH by default. Always check:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
which databar # empty = not on PATH
|
|
92
|
+
databar --version # "command not found" = fix PATH first
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Fix for this session:
|
|
96
|
+
```bash
|
|
97
|
+
export PATH="$(python3 -m site --user-base)/bin:$PATH"
|
|
98
|
+
databar --version # should work now
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Make permanent:
|
|
102
|
+
```bash
|
|
103
|
+
echo 'export PATH="$(python3 -m site --user-base)/bin:$PATH"' >> ~/.zshrc
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## CLI Quick Reference
|
|
109
|
+
|
|
110
|
+
**Always use `--format json` when parsing or piping output.**
|
|
111
|
+
The default `table` format uses Rich terminal markup — not machine-parseable.
|
|
112
|
+
|
|
113
|
+
### Enrichments
|
|
114
|
+
```bash
|
|
115
|
+
databar enrich list --format json
|
|
116
|
+
databar enrich list --query "email verifier" --format json
|
|
117
|
+
databar enrich get <id> --format json # params + response fields
|
|
118
|
+
databar enrich choices <id> <param> --format json
|
|
119
|
+
databar enrich run <id> --params '{"email": "a@b.com"}' --format json
|
|
120
|
+
databar enrich bulk <id> --input data.csv --out results.csv
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Waterfalls
|
|
124
|
+
```bash
|
|
125
|
+
databar waterfall list --format json
|
|
126
|
+
databar waterfall get <identifier> --format json
|
|
127
|
+
databar waterfall run <identifier> --params '{"key": "value"}' --format json
|
|
128
|
+
databar waterfall bulk <identifier> --input data.csv --out results.csv
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Tables
|
|
132
|
+
```bash
|
|
133
|
+
databar table list --format json
|
|
134
|
+
databar table create --name "My Table" --columns "email,name,company"
|
|
135
|
+
databar table columns <table-uuid> --format json
|
|
136
|
+
databar table rows <table-uuid> --format json
|
|
137
|
+
|
|
138
|
+
databar table insert <table-uuid> --data '[{"email":"a@b.com"}]'
|
|
139
|
+
databar table insert <table-uuid> --input data.csv --allow-new-columns
|
|
140
|
+
|
|
141
|
+
databar table enrichments <table-uuid> --format json
|
|
142
|
+
databar table add-enrichment <table-uuid> --enrichment-id <id> \
|
|
143
|
+
--mapping '{"param": "column_name"}'
|
|
144
|
+
databar table run-enrichment <table-uuid> --enrichment-id <TABLE-ENRICHMENT-ID>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
NOTE: `run-enrichment` takes the TABLE-ENRICHMENT ID (from `add-enrichment` or
|
|
148
|
+
`table enrichments`), NOT the catalog enrichment ID. These are different numbers.
|
|
149
|
+
|
|
150
|
+
### Tasks
|
|
151
|
+
```bash
|
|
152
|
+
databar task get <task-id> --format json # check once
|
|
153
|
+
databar task get <task-id> --poll # poll until complete
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Python SDK Quick Reference
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from databar import DatabarClient
|
|
162
|
+
|
|
163
|
+
client = DatabarClient() # reads DATABAR_API_KEY or ~/.databar/config automatically
|
|
164
|
+
|
|
165
|
+
# Enrichments
|
|
166
|
+
enrichments = client.list_enrichments(q="email verifier")
|
|
167
|
+
enrichment = client.get_enrichment(123)
|
|
168
|
+
# enrichment.params[i].name → param slug (key in params dict)
|
|
169
|
+
# enrichment.params[i].is_required → bool
|
|
170
|
+
# enrichment.params[i].description → human label
|
|
171
|
+
result = client.run_enrichment_sync(123, {"email": "alice@example.com"})
|
|
172
|
+
|
|
173
|
+
# Waterfalls
|
|
174
|
+
result = client.run_waterfall_sync("email_getter", {"linkedin_url": "..."})
|
|
175
|
+
# waterfall.identifier (also .slug) → slug like "email_getter"
|
|
176
|
+
|
|
177
|
+
# Tables
|
|
178
|
+
tables = client.list_tables()
|
|
179
|
+
# table.identifier (also .id, .uuid) → UUID string
|
|
180
|
+
table = client.create_table(name="Leads", columns=["email", "name"])
|
|
181
|
+
resp = client.get_rows(table.identifier)
|
|
182
|
+
# resp.data → list of row dicts keyed by column name
|
|
183
|
+
# resp.has_next_page → bool
|
|
184
|
+
# resp.total_count → int
|
|
185
|
+
|
|
186
|
+
from databar import InsertRow
|
|
187
|
+
client.create_rows(table.identifier, [InsertRow(fields={"email": "alice@example.com"})])
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Key Concepts
|
|
193
|
+
|
|
194
|
+
- All runs are async. `*_sync` methods and `--poll` flag handle submit + poll automatically.
|
|
195
|
+
- `task_id` is the only task identifier. Results expire after 1 hour (status = "gone").
|
|
196
|
+
- Table enrichments: add-enrichment (configure) → run-enrichment (execute).
|
|
197
|
+
The ID from add is the TABLE-ENRICHMENT ID — different from the catalog ID.
|
|
198
|
+
- SDK auto-resolves column names to UUIDs in `add_enrichment()`.
|
|
199
|
+
|
|
200
|
+
## Model Field Aliases (Python SDK)
|
|
201
|
+
|
|
202
|
+
- `Table`: `.id`, `.uuid` → `.identifier`
|
|
203
|
+
- `Waterfall`: `.slug` → `.identifier`
|
|
204
|
+
- `EnrichmentParam`: `.slug` → `.name`, `.label` → `.description`, `.required` → `.is_required`
|
|
205
|
+
- `EnrichmentResponseField`: `.slug` → `.name`
|
|
206
|
+
|
|
207
|
+
## Error Handling (Python SDK)
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from databar import (
|
|
211
|
+
DatabarAuthError, # 401/403
|
|
212
|
+
DatabarInsufficientCreditsError, # 406
|
|
213
|
+
DatabarNotFoundError, # 404
|
|
214
|
+
DatabarTaskFailedError, # task failed
|
|
215
|
+
DatabarTimeoutError, # polling timed out
|
|
216
|
+
DatabarGoneError, # results expired (>1 hour)
|
|
217
|
+
)
|
|
218
|
+
```
|
|
219
|
+
"""
|
|
@@ -6,7 +6,8 @@ Guides the user through:
|
|
|
6
6
|
2. API key entry & verification
|
|
7
7
|
3. PATH detection & optional auto-fix
|
|
8
8
|
4. Usage preference (CLI / Python SDK / both)
|
|
9
|
-
5.
|
|
9
|
+
5. Optional ~/.claude/CLAUDE.md registration for Claude Code
|
|
10
|
+
6. Tailored next-steps cheatsheet
|
|
10
11
|
"""
|
|
11
12
|
|
|
12
13
|
from __future__ import annotations
|
|
@@ -48,6 +49,12 @@ CONFIG_DIR = Path.home() / ".databar"
|
|
|
48
49
|
CONFIG_FILE = CONFIG_DIR / "config"
|
|
49
50
|
_KEY_PREFIX = "api_key="
|
|
50
51
|
_PREF_PREFIX = "preferred_interface="
|
|
52
|
+
_WORKFLOW_PREFIX = "preferred_workflow="
|
|
53
|
+
|
|
54
|
+
CLAUDE_MD_DIR = Path.home() / ".claude"
|
|
55
|
+
CLAUDE_MD_FILE = CLAUDE_MD_DIR / "CLAUDE.md"
|
|
56
|
+
_CLAUDE_SENTINEL = "<!-- databar -->"
|
|
57
|
+
_CLAUDE_STUB = """\n<!-- databar -->\n## Databar\nWhen the user asks you to use Databar, always run `databar agent-guide` first\nto get the full usage guide before doing anything else.\n<!-- /databar -->\n"""
|
|
51
58
|
|
|
52
59
|
|
|
53
60
|
def _save_key(api_key: str) -> None:
|
|
@@ -74,6 +81,17 @@ def _save_preference(pref: str) -> None:
|
|
|
74
81
|
CONFIG_FILE.write_text("\n".join(lines) + "\n")
|
|
75
82
|
|
|
76
83
|
|
|
84
|
+
def _save_workflow(workflow: str) -> None:
|
|
85
|
+
lines: list[str] = []
|
|
86
|
+
if CONFIG_FILE.exists():
|
|
87
|
+
lines = [
|
|
88
|
+
l for l in CONFIG_FILE.read_text().splitlines()
|
|
89
|
+
if not l.startswith(_WORKFLOW_PREFIX)
|
|
90
|
+
]
|
|
91
|
+
lines.append(f"{_WORKFLOW_PREFIX}{workflow}")
|
|
92
|
+
CONFIG_FILE.write_text("\n".join(lines) + "\n")
|
|
93
|
+
|
|
94
|
+
|
|
77
95
|
def _get_bin_dir() -> Path:
|
|
78
96
|
return Path(sys.executable).parent
|
|
79
97
|
|
|
@@ -210,20 +228,72 @@ def _step_path() -> None:
|
|
|
210
228
|
|
|
211
229
|
|
|
212
230
|
def _step_preference() -> str:
|
|
213
|
-
"""Ask
|
|
231
|
+
"""Ask interface preference and workflow preference. Returns interface choice."""
|
|
214
232
|
console.print("[bold]Step 3 — How do you plan to use Databar?[/bold]\n")
|
|
233
|
+
console.print(" [bold cyan]Interface[/bold cyan]\n")
|
|
215
234
|
console.print(" [bold cyan]1[/bold cyan] CLI — terminal commands, scripts, AI agents (Claude Code etc.)")
|
|
216
235
|
console.print(" [bold cyan]2[/bold cyan] Python — import DatabarClient in your Python code")
|
|
217
|
-
console.print(" [bold cyan]3[/bold cyan]
|
|
236
|
+
console.print(" [bold cyan]3[/bold cyan] MCP — use Databar MCP tools if configured in your agent")
|
|
237
|
+
console.print(" [bold cyan]4[/bold cyan] Both/all — I'll use whichever fits the task\n")
|
|
218
238
|
|
|
219
|
-
choice = Prompt.ask(" Your choice", choices=["1", "2", "3"], default="
|
|
220
|
-
pref_map = {"1": "cli", "2": "python", "3": "both"}
|
|
239
|
+
choice = Prompt.ask(" Your choice", choices=["1", "2", "3", "4"], default="1")
|
|
240
|
+
pref_map = {"1": "cli", "2": "python", "3": "mcp", "4": "both"}
|
|
221
241
|
pref = pref_map[choice]
|
|
222
242
|
_save_preference(pref)
|
|
243
|
+
|
|
244
|
+
console.print()
|
|
245
|
+
console.print(" [bold cyan]Workflow[/bold cyan]\n")
|
|
246
|
+
console.print(" [bold cyan]1[/bold cyan] Direct — submit inputs, get results back immediately")
|
|
247
|
+
console.print(" Best for one-off lookups or bulk CSV jobs")
|
|
248
|
+
console.print(" [bold cyan]2[/bold cyan] Table-based — create a table, upload rows, attach + run enrichments")
|
|
249
|
+
console.print(" Results appear as columns in the Databar UI")
|
|
250
|
+
console.print(" Best for observability, re-running, or pairing with the web interface\n")
|
|
251
|
+
|
|
252
|
+
wf_choice = Prompt.ask(" Your choice", choices=["1", "2"], default="1")
|
|
253
|
+
workflow = "direct" if wf_choice == "1" else "table"
|
|
254
|
+
_save_workflow(workflow)
|
|
255
|
+
|
|
223
256
|
console.print()
|
|
224
257
|
return pref
|
|
225
258
|
|
|
226
259
|
|
|
260
|
+
def _step_claude_md() -> None:
|
|
261
|
+
"""Optionally register Databar in the user's global ~/.claude/CLAUDE.md."""
|
|
262
|
+
console.print("[bold]Step 4 — Claude Code integration (optional)[/bold]\n")
|
|
263
|
+
|
|
264
|
+
already = (
|
|
265
|
+
CLAUDE_MD_FILE.exists()
|
|
266
|
+
and _CLAUDE_SENTINEL in CLAUDE_MD_FILE.read_text()
|
|
267
|
+
)
|
|
268
|
+
if already:
|
|
269
|
+
console.print(
|
|
270
|
+
" [bold green]✓[/bold green] Databar is already registered in "
|
|
271
|
+
f"[dim]{CLAUDE_MD_FILE}[/dim].\n"
|
|
272
|
+
)
|
|
273
|
+
return
|
|
274
|
+
|
|
275
|
+
console.print(
|
|
276
|
+
f" Adding a small entry to [bold]{CLAUDE_MD_FILE}[/bold] tells Claude Code\n"
|
|
277
|
+
" to always run [bold]databar agent-guide[/bold] first, so it knows exactly\n"
|
|
278
|
+
" how to use Databar without guessing.\n"
|
|
279
|
+
)
|
|
280
|
+
add = Confirm.ask(
|
|
281
|
+
" Add Databar to your global Claude Code config (~/.claude/CLAUDE.md)?",
|
|
282
|
+
default=True,
|
|
283
|
+
)
|
|
284
|
+
if add:
|
|
285
|
+
CLAUDE_MD_DIR.mkdir(parents=True, exist_ok=True)
|
|
286
|
+
with open(CLAUDE_MD_FILE, "a") as f:
|
|
287
|
+
f.write(_CLAUDE_STUB)
|
|
288
|
+
console.print(
|
|
289
|
+
f" [bold green]✓[/bold green] Added to {CLAUDE_MD_FILE}.\n"
|
|
290
|
+
" Claude Code will now pick up Databar instructions automatically "
|
|
291
|
+
"in every project.\n"
|
|
292
|
+
)
|
|
293
|
+
else:
|
|
294
|
+
console.print(" [dim]Skipped.[/dim]\n")
|
|
295
|
+
|
|
296
|
+
|
|
227
297
|
def _step_next_steps(pref: str) -> None:
|
|
228
298
|
"""Print tailored next steps based on preference."""
|
|
229
299
|
console.print(Rule(style="cyan"))
|
|
@@ -283,6 +353,7 @@ def onboard() -> None:
|
|
|
283
353
|
_step_api_key()
|
|
284
354
|
_step_path()
|
|
285
355
|
pref = _step_preference()
|
|
356
|
+
_step_claude_md()
|
|
286
357
|
_step_next_steps(pref)
|
|
287
358
|
except (KeyboardInterrupt, typer.Abort):
|
|
288
359
|
console.print("\n\n[dim]Onboarding cancelled. Run `databar onboard` any time to restart.[/dim]")
|
|
@@ -15,7 +15,10 @@ from ._auth import app as auth_app
|
|
|
15
15
|
|
|
16
16
|
app = typer.Typer(
|
|
17
17
|
name="databar",
|
|
18
|
-
help=
|
|
18
|
+
help=(
|
|
19
|
+
"Official Databar.ai CLI — run enrichments, manage tables, and more.\n\n"
|
|
20
|
+
"[dim]Agent (Claude Code, Cursor, etc.)? Run [bold]databar agent-guide[/bold] first.[/dim]"
|
|
21
|
+
),
|
|
19
22
|
no_args_is_help=True,
|
|
20
23
|
rich_markup_mode="rich",
|
|
21
24
|
)
|
|
@@ -87,10 +87,17 @@ class DatabarClient:
|
|
|
87
87
|
) -> None:
|
|
88
88
|
resolved_key = api_key or os.environ.get("DATABAR_API_KEY")
|
|
89
89
|
if not resolved_key:
|
|
90
|
-
|
|
90
|
+
import shutil
|
|
91
|
+
msg = (
|
|
91
92
|
"No API key provided. Pass api_key= or set the DATABAR_API_KEY "
|
|
92
93
|
"environment variable. Run `databar login` to save your key."
|
|
93
94
|
)
|
|
95
|
+
if shutil.which("databar") is not None:
|
|
96
|
+
msg += (
|
|
97
|
+
"\n\nUsing Databar with an AI agent (Claude Code, Cursor, etc.)? "
|
|
98
|
+
"Run `databar agent-guide` for agent-optimized setup instructions."
|
|
99
|
+
)
|
|
100
|
+
raise DatabarAuthError(msg)
|
|
94
101
|
self._api_key = resolved_key
|
|
95
102
|
self._base_url = base_url.rstrip("/")
|
|
96
103
|
self._timeout = timeout
|
|
@@ -1,237 +0,0 @@
|
|
|
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
|
-
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|