everestapi 0.3.2__tar.gz → 0.3.5__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.
- {everestapi-0.3.2/src/everestapi.egg-info → everestapi-0.3.5}/PKG-INFO +1 -1
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi/__init__.py +1 -1
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi/client.py +13 -6
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi/mcp/server.py +84 -15
- {everestapi-0.3.2 → everestapi-0.3.5/src/everestapi.egg-info}/PKG-INFO +1 -1
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_client.py +1 -1
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_eve1087_cpu_tier.py +1 -1
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_eve959_toolsets.py +17 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_mcp_and_models.py +6 -6
- {everestapi-0.3.2 → everestapi-0.3.5}/LICENSE +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/README.md +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/pyproject.toml +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/setup.cfg +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi/__main__.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi/cli.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi/mcp/__init__.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi/mcp/__main__.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi/plots.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi/scoring.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi/types.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi.egg-info/SOURCES.txt +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi.egg-info/dependency_links.txt +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi.egg-info/entry_points.txt +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi.egg-info/requires.txt +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/src/everestapi.egg-info/top_level.txt +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_cli.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_diagnostics.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_eve953_mcp_progress.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_eve957_mcp_annotations_resources.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_eve967_mcp_discoverability.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_json_or_raise.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_prediction_range.py +0 -0
- {everestapi-0.3.2 → everestapi-0.3.5}/tests/test_scoring.py +0 -0
|
@@ -662,9 +662,10 @@ class EverestAPI:
|
|
|
662
662
|
The download route is version-scoped
|
|
663
663
|
(``/api/v1/data/download/{version}/{universe}/{split}``). Pass
|
|
664
664
|
``version="latest"`` (the default) to resolve the current version from
|
|
665
|
-
``/api/v1/data/versions`` automatically, or an explicit version
|
|
666
|
-
(
|
|
667
|
-
404 the current version is resolved and the
|
|
665
|
+
``/api/v1/data/versions`` automatically, or an explicit version string
|
|
666
|
+
(as returned by :meth:`list_versions`) to pin it. A stale pinned
|
|
667
|
+
version self-heals: on a 404 the current version is resolved and the
|
|
668
|
+
download retried once.
|
|
668
669
|
|
|
669
670
|
Splits: ``train`` / ``validation`` (features + targets), ``live``
|
|
670
671
|
(features only, no targets). In hackathon mode, ``train`` is the LABELED
|
|
@@ -677,8 +678,8 @@ class EverestAPI:
|
|
|
677
678
|
404s for hackathon keys.
|
|
678
679
|
|
|
679
680
|
Futures is served by the futures endpoint (``version`` is a no-op):
|
|
680
|
-
it returns the
|
|
681
|
-
tree (labeled ``train`` + blank-target ``validation``) to
|
|
681
|
+
it returns the current production dataset to full-scope keys and the
|
|
682
|
+
hackathon tree (labeled ``train`` + blank-target ``validation``) to
|
|
682
683
|
hackathon-scoped keys.
|
|
683
684
|
|
|
684
685
|
Value semantics: observed feature values are cross-sectional
|
|
@@ -895,12 +896,18 @@ class EverestAPI:
|
|
|
895
896
|
|
|
896
897
|
# -- data discovery ---------------------------------------------------
|
|
897
898
|
|
|
898
|
-
def get_dataset_schema(self, version: str = "
|
|
899
|
+
def get_dataset_schema(self, version: str = "latest", verbose: bool = False) -> dict:
|
|
899
900
|
"""Get the dataset schema for a version.
|
|
900
901
|
|
|
902
|
+
``version="latest"`` (the default) resolves the current version from
|
|
903
|
+
``/api/v1/data/versions`` automatically, or pass an explicit version
|
|
904
|
+
string (as returned by :meth:`list_versions`) to pin it.
|
|
905
|
+
|
|
901
906
|
Default is a compact summary (feature-set counts, target list, which splits
|
|
902
907
|
are labeled, the CV embargo, distinct feature count, active version). Pass
|
|
903
908
|
``verbose=True`` for the full per-feature listing."""
|
|
909
|
+
if version in (None, "latest", "current"):
|
|
910
|
+
version = self._current_dataset_version("futures") or "v0"
|
|
904
911
|
path = f"/api/v1/data/{version}/schema"
|
|
905
912
|
if verbose:
|
|
906
913
|
path += "?verbose=true"
|
|
@@ -298,8 +298,8 @@ TOOLS = [
|
|
|
298
298
|
"properties": {
|
|
299
299
|
"version": {
|
|
300
300
|
"type": "string",
|
|
301
|
-
"description": "Dataset version (default:
|
|
302
|
-
"default": "
|
|
301
|
+
"description": "Dataset version (default: latest, resolved from /api/v1/data/versions)",
|
|
302
|
+
"default": "latest",
|
|
303
303
|
},
|
|
304
304
|
},
|
|
305
305
|
"required": [],
|
|
@@ -340,7 +340,7 @@ TOOLS = [
|
|
|
340
340
|
},
|
|
341
341
|
{
|
|
342
342
|
"name": "train",
|
|
343
|
-
"description": "Train a model on Everesteer
|
|
343
|
+
"description": "Train a model REMOTELY on Everesteer's hosted compute — nothing executes on your machine. The call returns immediately with a job id and may run for up to 45 minutes. Poll get_job_status and get_job_log every 10–15 seconds for a reconnect-safe estimated percentage, stage, and fold-level messages. The platform loads its obfuscated data, runs purged CV, computes canonical metrics, and returns downloadable model/prediction artifacts; it does not submit or host the model for you. Custom code runs in an isolated network-denied sandbox without filesystem access or held-out targets. Call get_compute_credits for the live rate card and balance.",
|
|
344
344
|
"inputSchema": {
|
|
345
345
|
"type": "object",
|
|
346
346
|
"properties": {
|
|
@@ -404,7 +404,7 @@ TOOLS = [
|
|
|
404
404
|
},
|
|
405
405
|
{
|
|
406
406
|
"name": "get_job_status",
|
|
407
|
-
"description": "Check status
|
|
407
|
+
"description": "Check status plus reconnect-safe estimated percentage, stage, message, and update time. Poll every 10–15 seconds while running; use get_job_log for the full fold-level trail.",
|
|
408
408
|
"inputSchema": {
|
|
409
409
|
"type": "object",
|
|
410
410
|
"properties": {
|
|
@@ -416,6 +416,17 @@ TOOLS = [
|
|
|
416
416
|
"required": ["job_id"],
|
|
417
417
|
},
|
|
418
418
|
},
|
|
419
|
+
{
|
|
420
|
+
"name": "get_job_log",
|
|
421
|
+
"description": "Return the estimated progress summary and lifecycle/per-fold event trail for one training job. Poll every 10–15 seconds while running. Percentages are workflow estimates, not an ETA.",
|
|
422
|
+
"inputSchema": {
|
|
423
|
+
"type": "object",
|
|
424
|
+
"properties": {
|
|
425
|
+
"job_id": {"type": "string", "description": "Job ID returned by train"},
|
|
426
|
+
},
|
|
427
|
+
"required": ["job_id"],
|
|
428
|
+
},
|
|
429
|
+
},
|
|
419
430
|
{
|
|
420
431
|
"name": "get_model_download_url",
|
|
421
432
|
"description": "Get a presigned download URL for a trained model from a completed job. URL valid for 1 hour. Only you can download your own models.",
|
|
@@ -430,6 +441,38 @@ TOOLS = [
|
|
|
430
441
|
"required": ["job_id"],
|
|
431
442
|
},
|
|
432
443
|
},
|
|
444
|
+
{
|
|
445
|
+
"name": "get_job_predictions_url",
|
|
446
|
+
"description": "Get a presigned download URL for the prediction files (validation + live parquet) produced by a completed train job. URL valid for ~1 hour. Only you can download your own job's predictions. Fetch the model .pkl separately with get_model_download_url.",
|
|
447
|
+
"inputSchema": {
|
|
448
|
+
"type": "object",
|
|
449
|
+
"properties": {
|
|
450
|
+
"job_id": {
|
|
451
|
+
"type": "string",
|
|
452
|
+
"description": "Job ID from a train job",
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
"required": ["job_id"],
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
"name": "list_compute_jobs",
|
|
460
|
+
"description": "List your compute training jobs, newest first. Rows carry status, GPU, cost and the provider job id but exclude the large config/output payloads — use get_job_status for one job's full record. Optionally filter by status.",
|
|
461
|
+
"inputSchema": {
|
|
462
|
+
"type": "object",
|
|
463
|
+
"properties": {
|
|
464
|
+
"limit": {
|
|
465
|
+
"type": "integer",
|
|
466
|
+
"description": "Max rows (default 50, capped at 200)",
|
|
467
|
+
},
|
|
468
|
+
"status": {
|
|
469
|
+
"type": "string",
|
|
470
|
+
"description": "Filter to one status",
|
|
471
|
+
"enum": ["pending", "running", "completed", "failed", "timeout", "cancelled"],
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
},
|
|
433
476
|
{
|
|
434
477
|
"name": "get_compute_credits",
|
|
435
478
|
"description": "Check your compute credit balance and usage. Purchase credits with USDC before using GPU resources.",
|
|
@@ -994,7 +1037,10 @@ READ_ONLY_TOOLS = frozenset(
|
|
|
994
1037
|
"download_dataset",
|
|
995
1038
|
"download_benchmark",
|
|
996
1039
|
"get_job_status",
|
|
1040
|
+
"get_job_log",
|
|
1041
|
+
"list_compute_jobs",
|
|
997
1042
|
"get_model_download_url",
|
|
1043
|
+
"get_job_predictions_url",
|
|
998
1044
|
"get_compute_credits",
|
|
999
1045
|
"get_rounds",
|
|
1000
1046
|
"get_current_round",
|
|
@@ -1077,10 +1123,19 @@ TOOLSETS: dict[str, set[str]] = {
|
|
|
1077
1123
|
# EVE-970: hosted training is a first-class flow now that every account
|
|
1078
1124
|
# carries a compute grant — advertise train + get_compute_credits by
|
|
1079
1125
|
# default so agents discover the hosted-training entry point without
|
|
1080
|
-
# setting EIQ_MCP_TOOLSETS.
|
|
1081
|
-
#
|
|
1126
|
+
# setting EIQ_MCP_TOOLSETS. EVE-1145 (platform parity): the whole
|
|
1127
|
+
# job-lifecycle group is core too. train's description tells the caller
|
|
1128
|
+
# to poll get_job_status()/get_job_log() and fetch artifacts via
|
|
1129
|
+
# get_model_download_url()/get_job_predictions_url() — hiding those in a
|
|
1130
|
+
# non-default group made hosted training an unfinishable dead end for an
|
|
1131
|
+
# agent that only sees the default toolset. Mirrors the platform MCP server.
|
|
1082
1132
|
"train",
|
|
1083
1133
|
"get_compute_credits",
|
|
1134
|
+
"get_job_status",
|
|
1135
|
+
"get_job_log",
|
|
1136
|
+
"list_compute_jobs",
|
|
1137
|
+
"get_model_download_url",
|
|
1138
|
+
"get_job_predictions_url",
|
|
1084
1139
|
},
|
|
1085
1140
|
"data": {
|
|
1086
1141
|
"get_universe",
|
|
@@ -1093,7 +1148,6 @@ TOOLSETS: dict[str, set[str]] = {
|
|
|
1093
1148
|
"get_benchmarks",
|
|
1094
1149
|
"download_benchmark",
|
|
1095
1150
|
"get_models",
|
|
1096
|
-
"get_model_download_url",
|
|
1097
1151
|
"get_model_per_exped_breakdown",
|
|
1098
1152
|
},
|
|
1099
1153
|
"submit": {"submit_predictions", "upload_model", "get_upload_status"},
|
|
@@ -1102,9 +1156,10 @@ TOOLSETS: dict[str, set[str]] = {
|
|
|
1102
1156
|
# "core" (EVE-967) — every name still lives in exactly one group.
|
|
1103
1157
|
"run_validation_diagnostics",
|
|
1104
1158
|
},
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1159
|
+
# EVE-1145: the job-lifecycle tools (get_job_status/get_job_log/
|
|
1160
|
+
# list_compute_jobs/get_model_download_url/get_job_predictions_url) were
|
|
1161
|
+
# promoted to "core". Kept as a stable, addressable EIQ_MCP_TOOLSETS name.
|
|
1162
|
+
"compute": set(),
|
|
1108
1163
|
"staking": {
|
|
1109
1164
|
"stake_on_model",
|
|
1110
1165
|
"unstake_from_model",
|
|
@@ -1263,7 +1318,7 @@ def _dispatch(name: str, arguments: dict) -> str:
|
|
|
1263
1318
|
elif name == "get_leaderboard":
|
|
1264
1319
|
result = client.get_leaderboard(period=arguments.get("period", "30d"))
|
|
1265
1320
|
elif name == "get_dataset_schema":
|
|
1266
|
-
result = client.get_dataset_schema(version=arguments.get("version", "
|
|
1321
|
+
result = client.get_dataset_schema(version=arguments.get("version", "latest"))
|
|
1267
1322
|
elif name == "download_dataset":
|
|
1268
1323
|
path = client.download_dataset(
|
|
1269
1324
|
universe=arguments.get("universe", "futures"),
|
|
@@ -1282,8 +1337,17 @@ def _dispatch(name: str, arguments: dict) -> str:
|
|
|
1282
1337
|
result = client.train(**arguments)
|
|
1283
1338
|
elif name == "get_job_status":
|
|
1284
1339
|
result = client.get_job_status(job_id=arguments["job_id"])
|
|
1340
|
+
elif name == "get_job_log":
|
|
1341
|
+
result = client.get_job_log(job_id=arguments["job_id"])
|
|
1285
1342
|
elif name == "get_model_download_url":
|
|
1286
1343
|
result = client.get_model_download_url(job_id=arguments["job_id"])
|
|
1344
|
+
elif name == "get_job_predictions_url":
|
|
1345
|
+
result = client.get_job_predictions_url(job_id=arguments["job_id"])
|
|
1346
|
+
elif name == "list_compute_jobs":
|
|
1347
|
+
result = client.list_compute_jobs(
|
|
1348
|
+
limit=arguments.get("limit", 50),
|
|
1349
|
+
status=arguments.get("status"),
|
|
1350
|
+
)
|
|
1287
1351
|
elif name == "get_compute_credits":
|
|
1288
1352
|
result = client.get_compute_credits()
|
|
1289
1353
|
elif name == "get_rounds":
|
|
@@ -1649,9 +1713,12 @@ _NEXT_ACTIONS: dict[str, list[str]] = {
|
|
|
1649
1713
|
"download_dataset": ["create_model", "submit_futures_predictions"],
|
|
1650
1714
|
"download_benchmark": ["submit_futures_predictions"],
|
|
1651
1715
|
"get_benchmarks": ["download_benchmark"],
|
|
1652
|
-
"train": ["get_job_status"],
|
|
1653
|
-
"get_job_status": ["get_model_download_url"], # conditional
|
|
1716
|
+
"train": ["get_job_status", "get_job_log"],
|
|
1717
|
+
"get_job_status": ["get_model_download_url", "get_job_predictions_url"], # conditional
|
|
1718
|
+
"get_job_log": ["get_job_status", "train"],
|
|
1719
|
+
"list_compute_jobs": ["get_job_status", "get_job_log"],
|
|
1654
1720
|
"get_model_download_url": ["upload_model", "create_model"],
|
|
1721
|
+
"get_job_predictions_url": ["submit_futures_predictions", "create_model"],
|
|
1655
1722
|
"create_model": ["submit_futures_predictions", "upload_model"],
|
|
1656
1723
|
"upload_model": ["get_upload_status"],
|
|
1657
1724
|
"get_upload_status": ["submit_futures_predictions"], # conditional
|
|
@@ -1714,6 +1781,8 @@ _NARRATION: dict[str, str] = {
|
|
|
1714
1781
|
"train": "Training job queued — returns downloadable artifacts + metrics, not a submission.",
|
|
1715
1782
|
"get_job_status": "Training job status: {status}.",
|
|
1716
1783
|
"get_model_download_url": "Generated a download URL for the trained model (valid ~1h).",
|
|
1784
|
+
"get_job_predictions_url": "Generated a download URL for the job's predictions (valid ~1h).",
|
|
1785
|
+
"list_compute_jobs": "Returned your compute jobs.",
|
|
1717
1786
|
"upload_model": "Model artifact uploaded; validation runs asynchronously.",
|
|
1718
1787
|
"get_upload_status": "Model upload status: {status}.",
|
|
1719
1788
|
"get_scores": "Returned the score history for model '{model_id}'.",
|
|
@@ -1771,8 +1840,8 @@ def _next_actions_for(name: str, arguments: dict, data: dict) -> list[str]:
|
|
|
1771
1840
|
if status in ("completed", "done", "succeeded", "success"):
|
|
1772
1841
|
return ["get_model_download_url", "create_model"]
|
|
1773
1842
|
if status in ("failed", "error"):
|
|
1774
|
-
return ["train"]
|
|
1775
|
-
return ["get_job_status"]
|
|
1843
|
+
return ["get_job_log", "train"]
|
|
1844
|
+
return ["get_job_status", "get_job_log"]
|
|
1776
1845
|
if name == "get_upload_status":
|
|
1777
1846
|
if status in ("validated", "done", "success", "ready", "active"):
|
|
1778
1847
|
return ["submit_futures_predictions", "get_scores"]
|
|
@@ -130,7 +130,7 @@ def test_download_dataset_futures_uses_futures_endpoint(httpx_mock, api, tmp_pat
|
|
|
130
130
|
universe="futures",
|
|
131
131
|
split="validation",
|
|
132
132
|
output_path=str(tmp_path / "f.parquet"),
|
|
133
|
-
version="
|
|
133
|
+
version="some-version",
|
|
134
134
|
)
|
|
135
135
|
assert out == str(tmp_path / "f.parquet")
|
|
136
136
|
paths = [r.url.path for r in httpx_mock.get_requests()]
|
|
@@ -32,6 +32,23 @@ def test_toolset_coverage_both_directions():
|
|
|
32
32
|
assert len(grouped) == len(grouped_set), "a tool name appears in more than one toolset"
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
def test_job_lifecycle_tools_are_core():
|
|
36
|
+
"""Regression: the hosted-train lifecycle tools must be discoverable in the
|
|
37
|
+
DEFAULT toolset. train's own description points the caller at get_job_status/
|
|
38
|
+
get_job_log/get_model_download_url/get_job_predictions_url, so hiding them in
|
|
39
|
+
a non-default group made hosted training an unfinishable dead end — the very
|
|
40
|
+
gap that the everestapi package lagged eiq-platform (EVE-1145) on."""
|
|
41
|
+
core = S.TOOLSETS["core"]
|
|
42
|
+
for name in (
|
|
43
|
+
"get_job_status",
|
|
44
|
+
"get_job_log",
|
|
45
|
+
"list_compute_jobs",
|
|
46
|
+
"get_model_download_url",
|
|
47
|
+
"get_job_predictions_url",
|
|
48
|
+
):
|
|
49
|
+
assert name in core, f"{name} must be in core (default toolset) to finish a train job"
|
|
50
|
+
|
|
51
|
+
|
|
35
52
|
def test_default_advertises_core_only(monkeypatch):
|
|
36
53
|
monkeypatch.delenv("EIQ_MCP_TOOLSETS", raising=False)
|
|
37
54
|
assert S._enabled_tool_names() == set(S.TOOLSETS["core"])
|
|
@@ -79,16 +79,16 @@ def test_get_models(httpx_mock, api):
|
|
|
79
79
|
# via the futures endpoint, EVE-931 — see test_client.py).
|
|
80
80
|
def test_download_dataset_uses_versioned_route(httpx_mock, api, tmp_path):
|
|
81
81
|
httpx_mock.add_response(
|
|
82
|
-
url="http://test/api/v1/data/download/
|
|
82
|
+
url="http://test/api/v1/data/download/test-version/equities/train",
|
|
83
83
|
content=b"PAR1data",
|
|
84
84
|
)
|
|
85
85
|
out = api.download_dataset(
|
|
86
86
|
universe="equities",
|
|
87
87
|
split="train",
|
|
88
|
-
version="
|
|
88
|
+
version="test-version",
|
|
89
89
|
output_path=str(tmp_path / "t.parquet"),
|
|
90
90
|
)
|
|
91
|
-
assert httpx_mock.get_request().url.path == "/api/v1/data/download/
|
|
91
|
+
assert httpx_mock.get_request().url.path == "/api/v1/data/download/test-version/equities/train"
|
|
92
92
|
with open(out, "rb") as f:
|
|
93
93
|
assert f.read() == b"PAR1data"
|
|
94
94
|
|
|
@@ -96,10 +96,10 @@ def test_download_dataset_uses_versioned_route(httpx_mock, api, tmp_path):
|
|
|
96
96
|
def test_download_dataset_latest_resolves_version(httpx_mock, api, tmp_path):
|
|
97
97
|
httpx_mock.add_response(
|
|
98
98
|
url="http://test/api/v1/data/versions",
|
|
99
|
-
json={"versions": [{"version": "
|
|
99
|
+
json={"versions": [{"version": "test-version", "universes": ["equities"]}]},
|
|
100
100
|
)
|
|
101
101
|
httpx_mock.add_response(
|
|
102
|
-
url="http://test/api/v1/data/download/
|
|
102
|
+
url="http://test/api/v1/data/download/test-version/equities/live",
|
|
103
103
|
content=b"PAR1live",
|
|
104
104
|
)
|
|
105
105
|
out = api.download_dataset(
|
|
@@ -327,7 +327,7 @@ def test_enrich_next_actions_are_result_conditional():
|
|
|
327
327
|
_, running = server._enrich_result(
|
|
328
328
|
"get_job_status", {"job_id": "j"}, json.dumps({"status": "running"})
|
|
329
329
|
)
|
|
330
|
-
assert running["next_actions"] == ["get_job_status"]
|
|
330
|
+
assert running["next_actions"] == ["get_job_status", "get_job_log"]
|
|
331
331
|
_, done = server._enrich_result(
|
|
332
332
|
"get_job_status", {"job_id": "j"}, json.dumps({"status": "completed"})
|
|
333
333
|
)
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|