discovery-engine-api 0.2.62__tar.gz → 0.2.64__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.
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/PKG-INFO +2 -1
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/SKILL.md +106 -5
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/__init__.py +1 -1
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/client.py +33 -6
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/pyproject.toml +2 -1
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/.gitignore +0 -0
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/README.md +0 -0
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/errors.py +0 -0
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/integrations/__init__.py +0 -0
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/integrations/crewai.py +0 -0
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/integrations/langchain.py +0 -0
- {discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: discovery-engine-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.64
|
|
4
4
|
Summary: Python SDK for the Discovery Engine API
|
|
5
5
|
Project-URL: Homepage, https://www.leap-labs.com
|
|
6
6
|
Project-URL: Documentation, https://disco.leap-labs.com/llms-full.txt
|
|
@@ -25,6 +25,7 @@ Requires-Python: >=3.10
|
|
|
25
25
|
Requires-Dist: httpx>=0.24.0
|
|
26
26
|
Requires-Dist: pydantic>=2.0.0
|
|
27
27
|
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: asyncpg>=0.27.0; extra == 'dev'
|
|
28
29
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
29
30
|
Requires-Dist: pytest-timeout>=2.2.0; extra == 'dev'
|
|
30
31
|
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
@@ -27,15 +27,24 @@ This is a computational pipeline, not prompt engineering over data. You cannot r
|
|
|
27
27
|
|
|
28
28
|
## Getting an API Key
|
|
29
29
|
|
|
30
|
-
**Programmatic (for agents):**
|
|
30
|
+
**Programmatic (for agents):** Two-step signup — send a verification code to the email, then submit it to receive the API key. The email must be real: the code is sent there and must be read to complete signup.
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
+
# Step 1 — send verification code
|
|
33
34
|
curl -X POST https://disco.leap-labs.com/v1/signup \
|
|
34
35
|
-H "Content-Type: application/json" \
|
|
35
36
|
-d '{"email": "agent@example.com"}'
|
|
37
|
+
# → {"status": "verification_required", "email": "agent@example.com"}
|
|
38
|
+
|
|
39
|
+
# Step 2 — submit code from email to get API key
|
|
40
|
+
curl -X POST https://disco.leap-labs.com/v1/signup/verify \
|
|
41
|
+
-H "Content-Type: application/json" \
|
|
42
|
+
-d '{"email": "agent@example.com", "code": "123456"}'
|
|
36
43
|
# → {"key": "disco_...", "key_id": "...", "organization_id": "...", "tier": "free_tier", "credits": 10}
|
|
37
44
|
```
|
|
38
45
|
|
|
46
|
+
Codes expire after 15 minutes. If the email service is unavailable, `POST /v1/signup` returns the API key directly (same shape as the verify response) with no verification step required.
|
|
47
|
+
|
|
39
48
|
**Manual (for humans):** Sign up at https://disco.leap-labs.com/sign-up, create key at https://disco.leap-labs.com/developers.
|
|
40
49
|
|
|
41
50
|
## Installation
|
|
@@ -54,7 +63,10 @@ from discovery import Engine
|
|
|
54
63
|
# If you already have an API key:
|
|
55
64
|
engine = Engine(api_key="disco_...")
|
|
56
65
|
|
|
57
|
-
# Or sign up for one
|
|
66
|
+
# Or sign up for one.
|
|
67
|
+
# Sends a code to the email address and prompts for it interactively.
|
|
68
|
+
# Requires a terminal — for fully automated agents, use the two-step REST API
|
|
69
|
+
# in the "Getting an API Key" section above instead.
|
|
58
70
|
engine = await Engine.signup(email="agent@example.com")
|
|
59
71
|
|
|
60
72
|
# One-call method: submit, poll, and return results automatically
|
|
@@ -74,8 +86,8 @@ for pattern in result.patterns:
|
|
|
74
86
|
If you need to do other work while Discovery Engine runs (recommended for agent workflows):
|
|
75
87
|
|
|
76
88
|
```python
|
|
77
|
-
# Submit
|
|
78
|
-
run = await engine.run_async(file="data.csv", target_column="outcome"
|
|
89
|
+
# Submit and return immediately (wait=False is the default for run_async)
|
|
90
|
+
run = await engine.run_async(file="data.csv", target_column="outcome")
|
|
79
91
|
print(f"Submitted run {run.run_id}, continuing with other work...")
|
|
80
92
|
|
|
81
93
|
# ... do other things ...
|
|
@@ -84,7 +96,9 @@ print(f"Submitted run {run.run_id}, continuing with other work...")
|
|
|
84
96
|
result = await engine.wait_for_completion(run.run_id, timeout=1800)
|
|
85
97
|
```
|
|
86
98
|
|
|
87
|
-
This is the preferred pattern for agents. `engine.discover()` is a convenience wrapper that does this internally
|
|
99
|
+
This is the preferred pattern for agents. `engine.discover()` is a convenience wrapper that does this internally with `wait=True`.
|
|
100
|
+
|
|
101
|
+
**Non-async contexts:** use `engine.discover_sync()` — same signature as `discover()`, runs in a managed event loop.
|
|
88
102
|
|
|
89
103
|
## Example Output
|
|
90
104
|
|
|
@@ -277,6 +291,93 @@ engine.discover(
|
|
|
277
291
|
- API keys: https://disco.leap-labs.com/developers
|
|
278
292
|
- Credits: https://disco.leap-labs.com/account
|
|
279
293
|
|
|
294
|
+
## Paying for Credits (Programmatic)
|
|
295
|
+
|
|
296
|
+
Agents can attach a payment method and purchase credits entirely via the API — no browser required.
|
|
297
|
+
|
|
298
|
+
**Step 1 — Get your Stripe publishable key**
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
account = await engine.get_account()
|
|
302
|
+
stripe_pk = account["stripe_publishable_key"]
|
|
303
|
+
stripe_customer_id = account["stripe_customer_id"]
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Or via REST:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
curl https://disco.leap-labs.com/v1/account \
|
|
310
|
+
-H "Authorization: Bearer disco_..."
|
|
311
|
+
# → { "stripe_publishable_key": "pk_live_...", "stripe_customer_id": "cus_...", "credits": {...}, ... }
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Step 2 — Tokenize a card using the Stripe API**
|
|
315
|
+
|
|
316
|
+
Use the publishable key to create a Stripe PaymentMethod. Card data goes directly to Stripe — Discovery Engine never sees it.
|
|
317
|
+
|
|
318
|
+
```python
|
|
319
|
+
import requests
|
|
320
|
+
|
|
321
|
+
pm_response = requests.post(
|
|
322
|
+
"https://api.stripe.com/v1/payment_methods",
|
|
323
|
+
auth=(stripe_pk, ""), # publishable key as username, empty password
|
|
324
|
+
data={
|
|
325
|
+
"type": "card",
|
|
326
|
+
"card[number]": "4242424242424242",
|
|
327
|
+
"card[exp_month]": "12",
|
|
328
|
+
"card[exp_year]": "2028",
|
|
329
|
+
"card[cvc]": "123",
|
|
330
|
+
},
|
|
331
|
+
)
|
|
332
|
+
payment_method_id = pm_response.json()["id"] # "pm_..."
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
**Step 3 — Attach the payment method**
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
result = await engine.add_payment_method(payment_method_id)
|
|
339
|
+
# → {"payment_method_attached": True, "card_last4": "4242", "card_brand": "visa"}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Or via REST:
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
curl -X POST https://disco.leap-labs.com/v1/account/payment-method \
|
|
346
|
+
-H "Authorization: Bearer disco_..." \
|
|
347
|
+
-H "Content-Type: application/json" \
|
|
348
|
+
-d '{"payment_method_id": "pm_..."}'
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**Step 4 — Purchase credits**
|
|
352
|
+
|
|
353
|
+
Credits are sold in packs of 20 ($20/pack, $1.00/credit).
|
|
354
|
+
|
|
355
|
+
```python
|
|
356
|
+
result = await engine.purchase_credits(packs=1)
|
|
357
|
+
# → {"purchased_credits": 20, "total_credits": 30, "charge_amount_usd": 20.0, "stripe_payment_id": "pi_..."}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Or via REST:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
curl -X POST https://disco.leap-labs.com/v1/account/credits/purchase \
|
|
364
|
+
-H "Authorization: Bearer disco_..." \
|
|
365
|
+
-H "Content-Type: application/json" \
|
|
366
|
+
-d '{"packs": 1}'
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
**Subscriptions (optional)**
|
|
370
|
+
|
|
371
|
+
For regular usage, subscribe to a paid plan instead of buying packs:
|
|
372
|
+
|
|
373
|
+
```python
|
|
374
|
+
# Plans: free_tier ($0, 10 cr/mo), tier_1 ($49, 50 cr/mo), tier_2 ($199, 200 cr/mo)
|
|
375
|
+
result = await engine.subscribe(plan="tier_1")
|
|
376
|
+
# → {"plan": "tier_1", "name": "Researcher", "monthly_credits": 50, "price_usd": 49}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Requires a payment method on file. See `GET /v1/plans` for full plan details.
|
|
380
|
+
|
|
280
381
|
## Estimate Before Running
|
|
281
382
|
|
|
282
383
|
Before submitting a private analysis, estimate the cost and time:
|
|
@@ -217,9 +217,12 @@ class Engine:
|
|
|
217
217
|
) -> "Engine":
|
|
218
218
|
"""Create an account and return a configured Engine instance.
|
|
219
219
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
Sends a 6-digit verification code to the email address. Prompts for
|
|
221
|
+
the code interactively, then provisions the account and returns a
|
|
222
|
+
configured Engine with a ``disco_`` API key.
|
|
223
|
+
|
|
224
|
+
If the email service is unavailable, falls back to direct provisioning
|
|
225
|
+
and returns immediately (no code required).
|
|
223
226
|
|
|
224
227
|
Args:
|
|
225
228
|
email: Email address for the new account.
|
|
@@ -235,16 +238,40 @@ class Engine:
|
|
|
235
238
|
body: Dict[str, Any] = {"email": email}
|
|
236
239
|
if name:
|
|
237
240
|
body["name"] = name
|
|
241
|
+
|
|
238
242
|
async with cls._make_anon_client() as client:
|
|
239
243
|
response = await client.post("/v1/signup", json=body)
|
|
240
244
|
cls._raise_for_status(response)
|
|
241
245
|
data = response.json()
|
|
242
246
|
|
|
243
|
-
|
|
247
|
+
# Direct provisioning fallback (Resend unavailable) — already have the key
|
|
248
|
+
if data.get("key"):
|
|
249
|
+
engine = cls(api_key=data["key"], quiet=quiet)
|
|
250
|
+
if not quiet:
|
|
251
|
+
print(
|
|
252
|
+
f"Account created. Tier: {data.get('tier', 'free_tier')}, "
|
|
253
|
+
f"Credits: {data.get('credits', 0)}"
|
|
254
|
+
)
|
|
255
|
+
return engine
|
|
256
|
+
|
|
257
|
+
# Verification required — prompt for the code
|
|
258
|
+
if not quiet:
|
|
259
|
+
print(f"A verification code has been sent to {data['email']}.")
|
|
260
|
+
code = input("Enter verification code: ").strip()
|
|
261
|
+
|
|
262
|
+
async with cls._make_anon_client() as client:
|
|
263
|
+
verify_response = await client.post(
|
|
264
|
+
"/v1/signup/verify",
|
|
265
|
+
json={"email": email, "code": code},
|
|
266
|
+
)
|
|
267
|
+
cls._raise_for_status(verify_response)
|
|
268
|
+
key_data = verify_response.json()
|
|
269
|
+
|
|
270
|
+
engine = cls(api_key=key_data["key"], quiet=quiet)
|
|
244
271
|
if not quiet:
|
|
245
272
|
print(
|
|
246
|
-
f"Account created. Tier: {
|
|
247
|
-
f"Credits: {
|
|
273
|
+
f"Account created. Tier: {key_data.get('tier', 'free_tier')}, "
|
|
274
|
+
f"Credits: {key_data.get('credits', 0)}"
|
|
248
275
|
)
|
|
249
276
|
return engine
|
|
250
277
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "discovery-engine-api"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.64"
|
|
4
4
|
description = "Python SDK for the Discovery Engine API"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -32,6 +32,7 @@ dev = [
|
|
|
32
32
|
"pytest>=7.0.0",
|
|
33
33
|
"pytest-asyncio>=0.21.0",
|
|
34
34
|
"pytest-timeout>=2.2.0",
|
|
35
|
+
"asyncpg>=0.27.0",
|
|
35
36
|
]
|
|
36
37
|
pandas = [
|
|
37
38
|
"pandas>=2.0.0",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/integrations/__init__.py
RENAMED
|
File without changes
|
{discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/integrations/crewai.py
RENAMED
|
File without changes
|
{discovery_engine_api-0.2.62 → discovery_engine_api-0.2.64}/discovery/integrations/langchain.py
RENAMED
|
File without changes
|
|
File without changes
|