ctxprotocol 0.19.0__tar.gz → 0.19.1__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.
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/CHANGELOG.md +4 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/PKG-INFO +1 -1
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/__init__.py +1 -1
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/client/resources/query.py +4 -2
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/pyproject.toml +1 -1
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/tests/test_query.py +33 -4
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/uv.lock +1 -1
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/.codexignore +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/.gitignore +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/README.md +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/auth/__init__.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/client/__init__.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/client/client.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/client/resources/__init__.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/client/resources/developer.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/client/resources/discovery.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/client/resources/tools.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/client/types.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/context/__init__.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/context/hyperliquid.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/context/polymarket.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/context/wallet.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/contrib/__init__.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/contrib/search/__init__.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/contrib/search/core.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/contrib/search/trace.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/contrib/search/types.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/contrib/search/validation.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/handshake/__init__.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/ctxprotocol/py.typed +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/docs/README.md +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/execute_client.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/polymarket_query_trace_validation.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/query_client.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/test_favorites_only.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/test_get_tool.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/two_surfaces_client.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/validation/generate_contributor_search_validation_artifacts.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/validation/named-regression-iran-boots-on-ground.json +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/validation/named-regression-supreme-court-tariffs.json +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/validation/shared-capability-miss-unsupported-venue.json +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/validation/shared-generic-overlap-best-match.json +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/validation/shared-still-ambiguous-shortlist.json +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/server/hummingbot-contributor/README.md +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/server/hummingbot-contributor/env.example +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/server/hummingbot-contributor/requirements.txt +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/server/hummingbot-contributor/server.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/polymarket-query-trace-results-py.json +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/tests/__init__.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/tests/contrib_search_validation_cases.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/tests/test_client.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/tests/test_contrib_search.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/tests/test_discovery.py +0 -0
- {ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/tests/test_tools.py +0 -0
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.1
|
|
4
|
+
|
|
5
|
+
- Fixed `client.query.start()` returning `400 "Invalid query job request"` when called without explicit `tools`. The request body builder now omits optional fields (notably `tools`) when unset instead of serializing them as JSON `null`; the durable jobs endpoint's Zod schema rejects `null` for optional fields. `client.query.run()` and `client.query.stream()` were not failing (the `/api/v1/query` endpoint tolerates `null`), but are now consistent with the TS SDK and MCP behavior.
|
|
6
|
+
|
|
3
7
|
## 0.19.0
|
|
4
8
|
|
|
5
9
|
- Fixed `client.query.run()`/`client.query.stream()` raising a `ValidationError` on queries that returned a rendered image artifact (e.g. server-rendered chart PNGs). `computedArtifacts` now accepts both `chart` (structured spec + data) and `image` (hosted URL) variants.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ctxprotocol
|
|
3
|
-
Version: 0.19.
|
|
3
|
+
Version: 0.19.1
|
|
4
4
|
Summary: Official Python SDK for the Context Protocol - Discover and execute AI tools programmatically
|
|
5
5
|
Project-URL: Homepage, https://ctxprotocol.com
|
|
6
6
|
Project-URL: Documentation, https://docs.ctxprotocol.com
|
|
@@ -62,8 +62,9 @@ class Query:
|
|
|
62
62
|
) -> dict[str, Any]:
|
|
63
63
|
request_body: dict[str, Any] = {
|
|
64
64
|
"query": query,
|
|
65
|
-
"tools": tools,
|
|
66
65
|
}
|
|
66
|
+
if tools is not None:
|
|
67
|
+
request_body["tools"] = tools
|
|
67
68
|
if stream is not None:
|
|
68
69
|
request_body["stream"] = stream
|
|
69
70
|
if resume_from is not None:
|
|
@@ -443,9 +444,10 @@ class Query:
|
|
|
443
444
|
"""
|
|
444
445
|
request_body: dict[str, Any] = {
|
|
445
446
|
"query": query,
|
|
446
|
-
"tools": tools,
|
|
447
447
|
"stream": True,
|
|
448
448
|
}
|
|
449
|
+
if tools is not None:
|
|
450
|
+
request_body["tools"] = tools
|
|
449
451
|
if resume_from is not None:
|
|
450
452
|
request_body["resumeFrom"] = (
|
|
451
453
|
resume_from.model_dump(by_alias=True, exclude_none=True)
|
|
@@ -420,7 +420,6 @@ class TestQueryRun:
|
|
|
420
420
|
method="POST",
|
|
421
421
|
json_body={
|
|
422
422
|
"query": "What are the top whale movements?",
|
|
423
|
-
"tools": None,
|
|
424
423
|
"stream": True,
|
|
425
424
|
},
|
|
426
425
|
extra_headers=None,
|
|
@@ -480,7 +479,6 @@ class TestQueryRun:
|
|
|
480
479
|
method="POST",
|
|
481
480
|
json_body={
|
|
482
481
|
"query": "Analyze whale activity",
|
|
483
|
-
"tools": None,
|
|
484
482
|
"stream": True,
|
|
485
483
|
"agentModelId": "kimi-k2.6-model",
|
|
486
484
|
"responseShape": "answer_with_evidence",
|
|
@@ -1091,7 +1089,6 @@ class TestQueryStream:
|
|
|
1091
1089
|
method="POST",
|
|
1092
1090
|
json_body={
|
|
1093
1091
|
"query": "What are whale movements?",
|
|
1094
|
-
"tools": None,
|
|
1095
1092
|
"stream": True,
|
|
1096
1093
|
},
|
|
1097
1094
|
extra_headers=None,
|
|
@@ -1534,7 +1531,6 @@ class TestQueryJobs:
|
|
|
1534
1531
|
method="POST",
|
|
1535
1532
|
json_body={
|
|
1536
1533
|
"query": "long query",
|
|
1537
|
-
"tools": None,
|
|
1538
1534
|
"stream": False,
|
|
1539
1535
|
"responseShape": "evidence_only",
|
|
1540
1536
|
"includeDataUrl": True,
|
|
@@ -1544,6 +1540,39 @@ class TestQueryJobs:
|
|
|
1544
1540
|
},
|
|
1545
1541
|
)
|
|
1546
1542
|
|
|
1543
|
+
async def test_start_omits_null_optional_fields(self) -> None:
|
|
1544
|
+
"""Regression: optional fields must be absent (not JSON null) in the job body.
|
|
1545
|
+
|
|
1546
|
+
The /api/v1/query/jobs endpoint validates the body with a Zod schema whose
|
|
1547
|
+
optional fields accept `undefined`/absent but reject `null`. Sending
|
|
1548
|
+
`"tools": null` (as the SDK previously did) made query.start() 400 with
|
|
1549
|
+
"Invalid query job request". Optional fields must be omitted when unset,
|
|
1550
|
+
matching the TS SDK (JSON.stringify drops undefined keys).
|
|
1551
|
+
"""
|
|
1552
|
+
client = ContextClient(api_key="ctx_test_key_1234567890abcdef12345678")
|
|
1553
|
+
payload = {
|
|
1554
|
+
"status": "running",
|
|
1555
|
+
"jobId": "11111111-1111-4111-8111-111111111111",
|
|
1556
|
+
"pollingTool": "context_query_status",
|
|
1557
|
+
"message": "running",
|
|
1558
|
+
"progress": None,
|
|
1559
|
+
"querySession": None,
|
|
1560
|
+
"createdAt": "2026-06-14T00:00:00.000Z",
|
|
1561
|
+
"updatedAt": "2026-06-14T00:00:00.000Z",
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
with patch.object(client, "fetch", new_callable=AsyncMock) as mock_fetch:
|
|
1565
|
+
mock_fetch.return_value = payload
|
|
1566
|
+
await client.query.start(query="long query")
|
|
1567
|
+
|
|
1568
|
+
body = mock_fetch.call_args.kwargs["json_body"]
|
|
1569
|
+
# No optional field may serialize to JSON null.
|
|
1570
|
+
assert all(value is not None for value in body.values()), body
|
|
1571
|
+
# tools specifically must be omitted when not supplied (was the 400 trigger).
|
|
1572
|
+
assert "tools" not in body, body
|
|
1573
|
+
# query is always present and non-null.
|
|
1574
|
+
assert body["query"] == "long query"
|
|
1575
|
+
|
|
1547
1576
|
async def test_get_status_fetches_query_job(self) -> None:
|
|
1548
1577
|
client = ContextClient(api_key="ctx_test_key_1234567890abcdef12345678")
|
|
1549
1578
|
payload = {
|
|
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
|
|
File without changes
|
{ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/client/polymarket_query_trace_validation.py
RENAMED
|
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
|
{ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/server/hummingbot-contributor/env.example
RENAMED
|
File without changes
|
{ctxprotocol-0.19.0 → ctxprotocol-0.19.1}/examples/server/hummingbot-contributor/requirements.txt
RENAMED
|
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
|