discovery-engine-api 0.2.104__tar.gz → 0.2.106__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.104 → discovery_engine_api-0.2.106}/PKG-INFO +3 -3
- {discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/README.md +2 -2
- {discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/discovery/__init__.py +1 -1
- {discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/discovery/client.py +85 -14
- {discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/pyproject.toml +1 -1
- {discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/.gitignore +0 -0
- {discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/discovery/errors.py +0 -0
- {discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/discovery/integrations/__init__.py +0 -0
- {discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/discovery/integrations/crewai.py +0 -0
- {discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/discovery/integrations/langchain.py +0 -0
- {discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/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.106
|
|
4
4
|
Summary: Python SDK for Disco API
|
|
5
5
|
Project-URL: Homepage, https://www.leap-labs.com
|
|
6
6
|
Project-URL: Documentation, https://disco.leap-labs.com/llms-full.txt
|
|
@@ -37,7 +37,7 @@ Description-Content-Type: text/markdown
|
|
|
37
37
|
|
|
38
38
|
# Disco Python SDK
|
|
39
39
|
|
|
40
|
-
Find novel, statistically validated patterns in tabular data — feature interactions, subgroup effects, and conditional relationships that
|
|
40
|
+
Find novel, statistically validated patterns in tabular data — feature interactions, subgroup effects, and conditional relationships that humans and agents miss.
|
|
41
41
|
|
|
42
42
|
## Installation
|
|
43
43
|
|
|
@@ -124,7 +124,7 @@ result = await engine.discover(
|
|
|
124
124
|
|
|
125
125
|
### Running in the Background
|
|
126
126
|
|
|
127
|
-
Runs take
|
|
127
|
+
Runs take a few minutes. While waiting, the SDK logs progress automatically:
|
|
128
128
|
|
|
129
129
|
```
|
|
130
130
|
Waiting for run abc123 to complete...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Disco Python SDK
|
|
2
2
|
|
|
3
|
-
Find novel, statistically validated patterns in tabular data — feature interactions, subgroup effects, and conditional relationships that
|
|
3
|
+
Find novel, statistically validated patterns in tabular data — feature interactions, subgroup effects, and conditional relationships that humans and agents miss.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -87,7 +87,7 @@ result = await engine.discover(
|
|
|
87
87
|
|
|
88
88
|
### Running in the Background
|
|
89
89
|
|
|
90
|
-
Runs take
|
|
90
|
+
Runs take a few minutes. While waiting, the SDK logs progress automatically:
|
|
91
91
|
|
|
92
92
|
```
|
|
93
93
|
Waiting for run abc123 to complete...
|
|
@@ -239,6 +239,15 @@ class Engine:
|
|
|
239
239
|
cls._raise_for_status(response)
|
|
240
240
|
data = response.json()
|
|
241
241
|
|
|
242
|
+
# Server may return a fresh key directly (short-circuit when OTP isn't
|
|
243
|
+
# required) — mirror Engine.signup() and use it if present. Only fall
|
|
244
|
+
# back to the OTP prompt when the server explicitly asks for verification.
|
|
245
|
+
if data.get("key"):
|
|
246
|
+
engine = cls(api_key=data["key"], quiet=quiet)
|
|
247
|
+
if not quiet:
|
|
248
|
+
print(f"Logged in. Tier: {data.get('tier', 'free_tier')}")
|
|
249
|
+
return engine
|
|
250
|
+
|
|
242
251
|
if data.get("status") != "verification_required":
|
|
243
252
|
raise ValueError(f"Unexpected login response: {data}")
|
|
244
253
|
|
|
@@ -437,25 +446,24 @@ class Engine:
|
|
|
437
446
|
file_size_mb: float,
|
|
438
447
|
num_columns: int,
|
|
439
448
|
analysis_depth: int = 2,
|
|
440
|
-
visibility: str = "public",
|
|
441
|
-
use_llms: bool = False,
|
|
442
449
|
) -> Dict[str, Any]:
|
|
443
|
-
"""Estimate the
|
|
450
|
+
"""Estimate the credits required for an analysis run.
|
|
444
451
|
|
|
445
|
-
|
|
446
|
-
|
|
452
|
+
Returns ``required_credits`` for public (always 0) and private, with
|
|
453
|
+
private split by whether LLMs are enabled (``without_llms`` /
|
|
454
|
+
``with_llms``). Works with or without authentication; when
|
|
455
|
+
authenticated, the response also includes ``account.available_credits``.
|
|
447
456
|
|
|
448
457
|
Args:
|
|
449
458
|
file_size_mb: Size of the data file in megabytes.
|
|
450
459
|
num_columns: Number of columns in the dataset.
|
|
451
|
-
analysis_depth: Depth iterations (1=fast, higher=deeper).
|
|
452
|
-
|
|
453
|
-
use_llms: Slower and more expensive, but you get smarter pre-processing,
|
|
454
|
-
literature context and novelty assessment. Default False. Public runs
|
|
455
|
-
always use LLMs.
|
|
460
|
+
analysis_depth: Depth iterations (1=fast, higher=deeper). Used to
|
|
461
|
+
compute the private-run cost.
|
|
456
462
|
|
|
457
463
|
Returns:
|
|
458
|
-
Dict with ``
|
|
464
|
+
Dict with ``required_credits`` (public / private.without_llms /
|
|
465
|
+
private.with_llms), ``limits`` (including per-visibility
|
|
466
|
+
``max_depth``), ``note``, and ``account`` info when authenticated.
|
|
459
467
|
"""
|
|
460
468
|
client = await self._get_dashboard_client()
|
|
461
469
|
response = await client.post(
|
|
@@ -464,8 +472,6 @@ class Engine:
|
|
|
464
472
|
"file_size_mb": file_size_mb,
|
|
465
473
|
"num_columns": num_columns,
|
|
466
474
|
"analysis_depth": analysis_depth,
|
|
467
|
-
"visibility": visibility,
|
|
468
|
-
"use_llms": use_llms,
|
|
469
475
|
},
|
|
470
476
|
)
|
|
471
477
|
self._raise_for_status(response)
|
|
@@ -740,6 +746,38 @@ class Engine:
|
|
|
740
746
|
)
|
|
741
747
|
return finalize_data
|
|
742
748
|
|
|
749
|
+
@staticmethod
|
|
750
|
+
def _looks_like_url(file: Any) -> bool:
|
|
751
|
+
"""True iff ``file`` is a string that names an http(s) URL.
|
|
752
|
+
|
|
753
|
+
Lets the SDK match the MCP ``file_url`` contract — agents can pass URLs
|
|
754
|
+
directly to ``upload_file()`` / ``discover()`` instead of needing to
|
|
755
|
+
download the file first.
|
|
756
|
+
"""
|
|
757
|
+
return isinstance(file, str) and (file.startswith("http://") or file.startswith("https://"))
|
|
758
|
+
|
|
759
|
+
async def _upload_from_url(self, url: str) -> Dict[str, Any]:
|
|
760
|
+
"""Hand a remote URL to the server's from-url endpoint and return the
|
|
761
|
+
same finalize-shaped dict that ``_upload_file_direct`` produces.
|
|
762
|
+
|
|
763
|
+
The server downloads the file directly — nothing passes through the
|
|
764
|
+
SDK process or the model context.
|
|
765
|
+
"""
|
|
766
|
+
client = await self._get_dashboard_client()
|
|
767
|
+
response = await client.post(
|
|
768
|
+
"/api/data/upload/from-url",
|
|
769
|
+
json={"url": url},
|
|
770
|
+
timeout=httpx.Timeout(connect=30.0, read=300.0, write=300.0, pool=30.0),
|
|
771
|
+
)
|
|
772
|
+
if response.status_code >= 400:
|
|
773
|
+
try:
|
|
774
|
+
error_data = response.json()
|
|
775
|
+
error_message = error_data.get("error", response.text)
|
|
776
|
+
except Exception:
|
|
777
|
+
error_message = response.text
|
|
778
|
+
raise ValueError(f"URL upload error ({response.status_code}): {error_message}")
|
|
779
|
+
return response.json()
|
|
780
|
+
|
|
743
781
|
def _prepare_upload(
|
|
744
782
|
self,
|
|
745
783
|
file: Union[str, Path, "pd.DataFrame"],
|
|
@@ -806,10 +844,27 @@ class Engine:
|
|
|
806
844
|
creating a run (e.g. to choose a target column). Pass the result
|
|
807
845
|
to ``run_async(upload_result=...)`` to avoid re-uploading.
|
|
808
846
|
|
|
847
|
+
``file`` may be a local path, a pandas DataFrame, or an http(s) URL.
|
|
848
|
+
URLs are downloaded server-side — nothing passes through the SDK or
|
|
849
|
+
the model context.
|
|
850
|
+
|
|
809
851
|
Returns:
|
|
810
852
|
Dict with ``file`` (key, name, size, fileHash) and ``columns``
|
|
811
853
|
(list of dicts with ``name``, ``type``, ``enabled``).
|
|
812
854
|
"""
|
|
855
|
+
if self._looks_like_url(file):
|
|
856
|
+
self._log(f"Uploading from URL: {file}")
|
|
857
|
+
result = await self._upload_from_url(file) # type: ignore[arg-type]
|
|
858
|
+
if not result.get("ok"):
|
|
859
|
+
errors = result.get("issues", {}).get("errors", [])
|
|
860
|
+
error_msg = errors[0].get("message") if errors else "Upload failed"
|
|
861
|
+
raise ValueError(f"Upload failed: {error_msg}")
|
|
862
|
+
return {
|
|
863
|
+
"file": result["file"],
|
|
864
|
+
"columns": result.get("columns", []),
|
|
865
|
+
"rowCount": result.get("rowCount"),
|
|
866
|
+
}
|
|
867
|
+
|
|
813
868
|
file_source, filename, mime_type, _ = self._prepare_upload(
|
|
814
869
|
file=file,
|
|
815
870
|
title=title,
|
|
@@ -892,6 +947,17 @@ class Engine:
|
|
|
892
947
|
self._log(
|
|
893
948
|
f"Creating run from pre-uploaded file (depth: {analysis_depth}, target: {target_column})..."
|
|
894
949
|
)
|
|
950
|
+
elif self._looks_like_url(file):
|
|
951
|
+
self._log(f"Uploading from URL: {file}")
|
|
952
|
+
raw_result = await self._upload_from_url(file) # type: ignore[arg-type]
|
|
953
|
+
|
|
954
|
+
if not raw_result.get("ok"):
|
|
955
|
+
errors = raw_result.get("issues", {}).get("errors", [])
|
|
956
|
+
error_msg = errors[0].get("message") if errors else "Upload failed"
|
|
957
|
+
raise ValueError(f"Upload failed: {error_msg}")
|
|
958
|
+
|
|
959
|
+
uploaded_file = raw_result["file"]
|
|
960
|
+
columns = raw_result.get("columns", [])
|
|
895
961
|
else:
|
|
896
962
|
file_source, filename, mime_type, _ = self._prepare_upload(
|
|
897
963
|
file=file,
|
|
@@ -980,7 +1046,12 @@ class Engine:
|
|
|
980
1046
|
|
|
981
1047
|
if wait:
|
|
982
1048
|
return await self.get_results(run_id)
|
|
983
|
-
return EngineResult(
|
|
1049
|
+
return EngineResult(
|
|
1050
|
+
run_id=run_id,
|
|
1051
|
+
status="completed",
|
|
1052
|
+
report_id=report_id,
|
|
1053
|
+
report_url=f"{self.dashboard_url}/reports/{report_id}",
|
|
1054
|
+
)
|
|
984
1055
|
|
|
985
1056
|
run_id = result_data["run_id"]
|
|
986
1057
|
self._log(f"Run created: {run_id}")
|
|
File without changes
|
|
File without changes
|
{discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/discovery/integrations/__init__.py
RENAMED
|
File without changes
|
{discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/discovery/integrations/crewai.py
RENAMED
|
File without changes
|
{discovery_engine_api-0.2.104 → discovery_engine_api-0.2.106}/discovery/integrations/langchain.py
RENAMED
|
File without changes
|
|
File without changes
|