mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
pkg/hanzoai/cloud goes +2186 -2126 ~175: 1700 paths / 2354 operations / 2186 schemas, 182 api modules and 2172 model modules, against the 239/1116 it carried from hanzo.yaml. The document is hanzoai/cloud's own emission now, pinned in a new .spec-lock by commit and sha256, and generate.py reaches it by value — --skip-validate-spec means the 1012 missing-`responses` errors no longer write zero files, so a client can be cut from the authority instead of a projection of it. Two renamings come with that, and both are the fix rather than the damage. IAM's types are namespace-qualified (iam.Role, iam.Application, 95 of them) because a bare `Role` was two unrelated shapes wearing one name. And the <svc>_ prefix is gone from every operationId, so every generated method lost it. The prefix is what broke the examples, and the gate saw only two thirds of it. Four flows failed on their imports; `money` and `tools` PASSED while every call in them named a method that no longer existed — an import resolves the names in the `from … import` line and a method is looked up at call time. All five flows now name operations that exist, checked by resolving each one as an attribute, and hanzo.yml records that ceiling so the next reader does not trust the gate for more than it says. `chat` is removed, which is a measurement and not a preference: cloud declares POST /v1/chat/completions with no requestBody and no responses at all, so the generated method takes no body and returns None — the one call a chat example exists to make cannot be expressed. Inventing the type, or hand-rolling the HTTP inside a generated client, is the drift these SDKs exist to prevent; js-sdk dropped its own chat flow at 2.0.7 for exactly this. It returns the release cloud gives that route a body. Two smoke assertions were already red before this regeneration and are now true again: they pinned AIApi/APIKeysApi/MCPApi and AdminApi.plugin_admin_*, names from the retired lineage. The surface is all still there under AiApi/KeysApi/ McpApi and AdminApi.admin_plugins. tests/test_zap_transport.py still errors, exactly as it did before: it imports `Hanzo` from hanzoai, which the hand-written package does not define. That is not this document's business and is untouched. Minor rather than patch: every generated method changed name. Co-authored-by: Hanzo Dev <[email protected]>
87 lines
3.3 KiB
Python
87 lines
3.3 KiB
Python
"""Smoke tests for the generated `hanzoai` client.
|
|
|
|
The client is generated from hanzoai/openapi `hanzo.yaml` (openapi-generator,
|
|
urllib3). These assert the package imports and the unified api.hanzo.ai/v1
|
|
product surface is present — not network behaviour.
|
|
"""
|
|
import hanzoai
|
|
|
|
|
|
def test_client_constructs():
|
|
cfg = hanzoai.Configuration(host="https://api.hanzo.ai")
|
|
cfg.access_token = "hk-test"
|
|
client = hanzoai.ApiClient(cfg)
|
|
assert client is not None
|
|
assert cfg.host == "https://api.hanzo.ai"
|
|
|
|
|
|
def test_product_apis_present():
|
|
from hanzoai.api.tracker_projects_api import TrackerProjectsApi
|
|
from hanzoai.api.chat_agents_api import ChatAgentsApi
|
|
from hanzoai.api.crm_opportunities_api import CrmOpportunitiesApi
|
|
|
|
client = hanzoai.ApiClient(hanzoai.Configuration(host="https://api.hanzo.ai"))
|
|
for cls in (TrackerProjectsApi, ChatAgentsApi, CrmOpportunitiesApi):
|
|
assert cls(client) is not None
|
|
|
|
|
|
def test_full_surface_breadth():
|
|
import glob
|
|
import os
|
|
|
|
api_dir = os.path.dirname(hanzoai.api.__file__)
|
|
modules = glob.glob(os.path.join(api_dir, "*_api.py"))
|
|
# The full unified surface is hundreds of API groups, not the ~40 of the
|
|
# legacy LLM-gateway-only client.
|
|
assert len(modules) > 300, f"only {len(modules)} api modules — surface too small"
|
|
|
|
|
|
def test_version_is_single_sourced():
|
|
"""`hanzoai.__version__` must be the installed distribution, never a literal.
|
|
|
|
The generator writes `__version__ = "1.0.0"` (its default) into the package
|
|
__init__; that literal disagreed with pyproject for every release.
|
|
"""
|
|
from importlib.metadata import version
|
|
|
|
assert hanzoai.__version__ == version("hanzoai")
|
|
|
|
|
|
def test_cloud_package_imports():
|
|
"""`hanzoai.cloud` is the generated client — it must import cleanly.
|
|
|
|
This guarded a tag-casing collision in the retired hanzo.yaml lineage: tags
|
|
differing only by case (`AI`/`ai`, `API Keys`/`api-keys`, `MCP`/`mcp`) made
|
|
openapi-generator emit imports for classes it never wrote, so
|
|
`import hanzoai.cloud` raised ImportError. The client is a projection of
|
|
hanzoai/cloud's own emission now, which carries ONE spelling per tag, so the
|
|
class names lost their all-caps variants: `AIApi`/`APIKeysApi`/`MCPApi` are
|
|
`AiApi`/`KeysApi`/`McpApi`. The collision cannot recur while one document
|
|
with one spelling per tag is the only input; what this still pins is that
|
|
the top-level names resolve at all.
|
|
"""
|
|
import hanzoai.cloud
|
|
|
|
for name in ("AiApi", "KeysApi", "McpApi", "AdminApi"):
|
|
assert hasattr(hanzoai.cloud, name), f"hanzoai.cloud.{name} missing"
|
|
|
|
|
|
def test_admin_plugin_operator_surface():
|
|
"""The /v1/admin/plugins operator surface must be reachable from the SDK.
|
|
|
|
Four served routes: GET /v1/admin/plugins and POST
|
|
/v1/admin/plugins/{name}/{enable,disable,reload}. The `plugin_` prefix these
|
|
once carried came from the hand-merged master's `<svc>_` operationId
|
|
namespacing; cloud's emission names them `adminPlugins`,
|
|
`adminEnablePlugin`, `adminDisablePlugin`, `adminReloadPlugin`.
|
|
"""
|
|
from hanzoai.cloud.api.admin_api import AdminApi
|
|
|
|
for op in (
|
|
"admin_plugins",
|
|
"admin_enable_plugin",
|
|
"admin_disable_plugin",
|
|
"admin_reload_plugin",
|
|
):
|
|
assert callable(getattr(AdminApi, op, None)), f"AdminApi.{op} missing"
|