cloacina-client 0.8.0__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.
Files changed (94) hide show
  1. cloacina_client-0.8.0/.gitignore +79 -0
  2. cloacina_client-0.8.0/PKG-INFO +85 -0
  3. cloacina_client-0.8.0/README.md +70 -0
  4. cloacina_client-0.8.0/generator-config.yaml +3 -0
  5. cloacina_client-0.8.0/pyproject.toml +37 -0
  6. cloacina_client-0.8.0/src/cloacina_client/__init__.py +52 -0
  7. cloacina_client-0.8.0/src/cloacina_client/_client.py +496 -0
  8. cloacina_client-0.8.0/src/cloacina_client/_generated/__init__.py +8 -0
  9. cloacina_client-0.8.0/src/cloacina_client/_generated/api/__init__.py +1 -0
  10. cloacina_client-0.8.0/src/cloacina_client/_generated/api/agents/__init__.py +1 -0
  11. cloacina_client-0.8.0/src/cloacina_client/_generated/api/agents/list_agents.py +131 -0
  12. cloacina_client-0.8.0/src/cloacina_client/_generated/api/compiler/__init__.py +1 -0
  13. cloacina_client-0.8.0/src/cloacina_client/_generated/api/compiler/compiler_status.py +131 -0
  14. cloacina_client-0.8.0/src/cloacina_client/_generated/api/executions/__init__.py +1 -0
  15. cloacina_client-0.8.0/src/cloacina_client/_generated/api/executions/execute_workflow.py +235 -0
  16. cloacina_client-0.8.0/src/cloacina_client/_generated/api/executions/get_execution.py +190 -0
  17. cloacina_client-0.8.0/src/cloacina_client/_generated/api/executions/get_execution_events.py +190 -0
  18. cloacina_client-0.8.0/src/cloacina_client/_generated/api/executions/get_execution_tasks.py +187 -0
  19. cloacina_client-0.8.0/src/cloacina_client/_generated/api/executions/list_executions.py +260 -0
  20. cloacina_client-0.8.0/src/cloacina_client/_generated/api/graph_health/__init__.py +1 -0
  21. cloacina_client-0.8.0/src/cloacina_client/_generated/api/graph_health/get_graph.py +174 -0
  22. cloacina_client-0.8.0/src/cloacina_client/_generated/api/graph_health/list_accumulators.py +138 -0
  23. cloacina_client-0.8.0/src/cloacina_client/_generated/api/graph_health/list_graphs.py +138 -0
  24. cloacina_client-0.8.0/src/cloacina_client/_generated/api/graph_health/list_reactors.py +135 -0
  25. cloacina_client-0.8.0/src/cloacina_client/_generated/api/keys/__init__.py +1 -0
  26. cloacina_client-0.8.0/src/cloacina_client/_generated/api/keys/create_key.py +196 -0
  27. cloacina_client-0.8.0/src/cloacina_client/_generated/api/keys/create_tenant_key.py +200 -0
  28. cloacina_client-0.8.0/src/cloacina_client/_generated/api/keys/create_ws_ticket.py +146 -0
  29. cloacina_client-0.8.0/src/cloacina_client/_generated/api/keys/list_keys.py +148 -0
  30. cloacina_client-0.8.0/src/cloacina_client/_generated/api/keys/revoke_key.py +180 -0
  31. cloacina_client-0.8.0/src/cloacina_client/_generated/api/operational/__init__.py +1 -0
  32. cloacina_client-0.8.0/src/cloacina_client/_generated/api/operational/health.py +85 -0
  33. cloacina_client-0.8.0/src/cloacina_client/_generated/api/operational/ready.py +88 -0
  34. cloacina_client-0.8.0/src/cloacina_client/_generated/api/tenants/__init__.py +1 -0
  35. cloacina_client-0.8.0/src/cloacina_client/_generated/api/tenants/create_tenant.py +180 -0
  36. cloacina_client-0.8.0/src/cloacina_client/_generated/api/tenants/list_tenants.py +148 -0
  37. cloacina_client-0.8.0/src/cloacina_client/_generated/api/tenants/remove_tenant.py +244 -0
  38. cloacina_client-0.8.0/src/cloacina_client/_generated/api/triggers/__init__.py +1 -0
  39. cloacina_client-0.8.0/src/cloacina_client/_generated/api/triggers/get_trigger.py +210 -0
  40. cloacina_client-0.8.0/src/cloacina_client/_generated/api/triggers/list_triggers.py +232 -0
  41. cloacina_client-0.8.0/src/cloacina_client/_generated/api/workflows/__init__.py +1 -0
  42. cloacina_client-0.8.0/src/cloacina_client/_generated/api/workflows/delete_workflow.py +204 -0
  43. cloacina_client-0.8.0/src/cloacina_client/_generated/api/workflows/get_workflow.py +190 -0
  44. cloacina_client-0.8.0/src/cloacina_client/_generated/api/workflows/list_workflows.py +173 -0
  45. cloacina_client-0.8.0/src/cloacina_client/_generated/api/workflows/upload_workflow.py +209 -0
  46. cloacina_client-0.8.0/src/cloacina_client/_generated/client.py +282 -0
  47. cloacina_client-0.8.0/src/cloacina_client/_generated/errors.py +16 -0
  48. cloacina_client-0.8.0/src/cloacina_client/_generated/models/__init__.py +99 -0
  49. cloacina_client-0.8.0/src/cloacina_client/_generated/models/accumulator_status.py +71 -0
  50. cloacina_client-0.8.0/src/cloacina_client/_generated/models/create_key_request.py +81 -0
  51. cloacina_client-0.8.0/src/cloacina_client/_generated/models/create_tenant_request.py +105 -0
  52. cloacina_client-0.8.0/src/cloacina_client/_generated/models/error_body.py +73 -0
  53. cloacina_client-0.8.0/src/cloacina_client/_generated/models/execute_request.py +62 -0
  54. cloacina_client-0.8.0/src/cloacina_client/_generated/models/execute_response.py +86 -0
  55. cloacina_client-0.8.0/src/cloacina_client/_generated/models/execution_detail.py +78 -0
  56. cloacina_client-0.8.0/src/cloacina_client/_generated/models/execution_event.py +108 -0
  57. cloacina_client-0.8.0/src/cloacina_client/_generated/models/execution_events_response.py +92 -0
  58. cloacina_client-0.8.0/src/cloacina_client/_generated/models/execution_summary.py +108 -0
  59. cloacina_client-0.8.0/src/cloacina_client/_generated/models/graph_status.py +88 -0
  60. cloacina_client-0.8.0/src/cloacina_client/_generated/models/key_created_response.py +125 -0
  61. cloacina_client-0.8.0/src/cloacina_client/_generated/models/key_info.py +124 -0
  62. cloacina_client-0.8.0/src/cloacina_client/_generated/models/key_revoked_response.py +70 -0
  63. cloacina_client-0.8.0/src/cloacina_client/_generated/models/key_role.py +10 -0
  64. cloacina_client-0.8.0/src/cloacina_client/_generated/models/list_response_accumulator_status.py +92 -0
  65. cloacina_client-0.8.0/src/cloacina_client/_generated/models/list_response_accumulator_status_items_item.py +71 -0
  66. cloacina_client-0.8.0/src/cloacina_client/_generated/models/list_response_graph_status.py +90 -0
  67. cloacina_client-0.8.0/src/cloacina_client/_generated/models/list_response_graph_status_items_item.py +88 -0
  68. cloacina_client-0.8.0/src/cloacina_client/_generated/models/list_response_key_info.py +88 -0
  69. cloacina_client-0.8.0/src/cloacina_client/_generated/models/list_response_key_info_items_item.py +124 -0
  70. cloacina_client-0.8.0/src/cloacina_client/_generated/models/list_response_tenant_summary.py +90 -0
  71. cloacina_client-0.8.0/src/cloacina_client/_generated/models/list_response_tenant_summary_items_item.py +62 -0
  72. cloacina_client-0.8.0/src/cloacina_client/_generated/models/package_upload_form.py +78 -0
  73. cloacina_client-0.8.0/src/cloacina_client/_generated/models/tenant_created_response.py +93 -0
  74. cloacina_client-0.8.0/src/cloacina_client/_generated/models/tenant_list_response_execution_summary.py +100 -0
  75. cloacina_client-0.8.0/src/cloacina_client/_generated/models/tenant_list_response_execution_summary_items_item.py +108 -0
  76. cloacina_client-0.8.0/src/cloacina_client/_generated/models/tenant_list_response_trigger_schedule_summary.py +100 -0
  77. cloacina_client-0.8.0/src/cloacina_client/_generated/models/tenant_list_response_trigger_schedule_summary_items_item.py +196 -0
  78. cloacina_client-0.8.0/src/cloacina_client/_generated/models/tenant_list_response_workflow_summary.py +100 -0
  79. cloacina_client-0.8.0/src/cloacina_client/_generated/models/tenant_list_response_workflow_summary_items_item.py +116 -0
  80. cloacina_client-0.8.0/src/cloacina_client/_generated/models/tenant_removed_response.py +94 -0
  81. cloacina_client-0.8.0/src/cloacina_client/_generated/models/tenant_summary.py +62 -0
  82. cloacina_client-0.8.0/src/cloacina_client/_generated/models/trigger_detail_response.py +96 -0
  83. cloacina_client-0.8.0/src/cloacina_client/_generated/models/trigger_execution.py +112 -0
  84. cloacina_client-0.8.0/src/cloacina_client/_generated/models/trigger_schedule_info.py +128 -0
  85. cloacina_client-0.8.0/src/cloacina_client/_generated/models/trigger_schedule_summary.py +196 -0
  86. cloacina_client-0.8.0/src/cloacina_client/_generated/models/workflow_deleted_response.py +78 -0
  87. cloacina_client-0.8.0/src/cloacina_client/_generated/models/workflow_detail.py +153 -0
  88. cloacina_client-0.8.0/src/cloacina_client/_generated/models/workflow_summary.py +116 -0
  89. cloacina_client-0.8.0/src/cloacina_client/_generated/models/workflow_uploaded_response.py +71 -0
  90. cloacina_client-0.8.0/src/cloacina_client/_generated/models/ws_ticket_response.py +71 -0
  91. cloacina_client-0.8.0/src/cloacina_client/_generated/types.py +54 -0
  92. cloacina_client-0.8.0/src/cloacina_client/_ws.py +156 -0
  93. cloacina_client-0.8.0/tests/test_contract.py +259 -0
  94. cloacina_client-0.8.0/uv.lock +353 -0
@@ -0,0 +1,79 @@
1
+ wip/
2
+ /target/
3
+ # Ignore all target directories (including in examples and subdirectories)
4
+ **/target/
5
+
6
+ # Cargo.lock is committed: this workspace ships binaries (cloacina-server,
7
+ # cloacinactl, cloacina-compiler). Library consumers ignore our lockfile
8
+ # anyway, so committing it just gives our own builds + Docker --locked the
9
+ # reproducibility they need.
10
+ # https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
11
+
12
+ # Each example/fixture/tutorial crate declares its own [workspace] and
13
+ # therefore gets its own Cargo.lock when built. These are transient
14
+ # build artifacts — committing them clutters PRs with churn whenever an
15
+ # example is rebuilt locally. The root Cargo.lock (above) still applies
16
+ # to the actual shipping workspace.
17
+ examples/**/Cargo.lock
18
+
19
+ # These are backup files generated by rustfmt
20
+ **/*.rs.bk
21
+
22
+ # MSVC Windows builds of rustc generate these, which store debugging information
23
+ *.pdb
24
+
25
+ # IDE files
26
+ .idea/
27
+ .vscode/
28
+ *.swp
29
+ *.swo
30
+
31
+ # Mac OS files
32
+ .DS_Store
33
+
34
+ # Exclude working-docs directory
35
+ /working-docs/
36
+
37
+ # Hugo documentation
38
+ /docs/public/
39
+ /docs/.hugo_build.lock
40
+ /docs/static/api/
41
+
42
+ # Python files
43
+ *.pyc
44
+ __pycache__/
45
+
46
+ # Python egg-info directories (generated during development installs)
47
+ *.egg-info/
48
+ # Python build directories
49
+ build/
50
+ dist/
51
+ .cursorignore
52
+
53
+ # SQLite database files created by tests and tutorials
54
+ *.db
55
+ *.db-shm
56
+ *.db-wal
57
+ *.db\?*
58
+
59
+ # Packaged workflow files
60
+ *.cloacina
61
+ test-quick/
62
+ .claude/*
63
+ .claude_handovers/
64
+ diataxis/
65
+ run_demos.sh
66
+ docs/content/api-reference/_nav.yml
67
+
68
+ # Transient test output (don't commit)
69
+ integration-test.log
70
+ .metis/*.log
71
+ # Auto-generated Metis code index — regenerated on every edit by the indexer,
72
+ # so it churns constantly and shouldn't be tracked.
73
+ .metis/code-index.md
74
+ .metis/code-index-hashes.json
75
+ .metis/code-index-symbols.json
76
+ .metis/.index-dirty
77
+ node_modules/
78
+ clients/python/.venv/
79
+ clients/python/dist/
@@ -0,0 +1,85 @@
1
+ Metadata-Version: 2.4
2
+ Name: cloacina-client
3
+ Version: 0.8.0
4
+ Summary: Python SDK for cloacina-server — typed REST client and WebSocket execution-event streams. Version-locked to the cloacina server release. (Service client; the embedded runtime is the separate `cloaca` package.)
5
+ Project-URL: Repository, https://github.com/colliery-io/cloacina
6
+ Project-URL: Documentation, https://colliery-io.github.io/cloacina/
7
+ Author-email: Dylan Storey <dylan.storey@gmail.com>
8
+ License-Expression: Apache-2.0
9
+ Requires-Python: >=3.10
10
+ Requires-Dist: attrs>=22.2.0
11
+ Requires-Dist: httpx<1,>=0.27
12
+ Requires-Dist: python-dateutil>=2.8.0
13
+ Requires-Dist: websockets<16,>=13
14
+ Description-Content-Type: text/markdown
15
+
16
+ # cloacina-client
17
+
18
+ Python SDK for [cloacina-server](https://github.com/colliery-io/cloacina) — a typed REST client plus WebSocket execution-event streaming, for Python 3.10+.
19
+
20
+ > **This is the service client.** It talks to a running cloacina-server over HTTP/WebSocket. The embedded workflow runtime is the separate [`cloaca`](https://pypi.org/project/cloaca/) package — the two are deliberately distinct.
21
+
22
+ **Version lockstep:** `cloacina-client X.Y.Z` is generated from, tested against, and only supported on `cloacina-server X.Y.Z`.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pip install cloacina-client
28
+ ```
29
+
30
+ ## Quickstart
31
+
32
+ ```python
33
+ from cloacina_client import Client
34
+
35
+ client = Client("http://localhost:8080", api_key="clk_...", tenant="public")
36
+
37
+ accepted = client.execute_workflow("my_workflow", {"input": 42})
38
+ print(accepted.execution_id)
39
+
40
+ for execution in client.iterate_executions(status="Failed"):
41
+ print(execution.id, execution.workflow_name)
42
+ ```
43
+
44
+ Every helper raises `CloacinaApiError` (with `.status` and the server's machine-readable `.code`) on non-2xx responses. The generated [`openapi-python-client`](https://github.com/openapi-generators/openapi-python-client) client is available as `client.generated` for anything the shim doesn't cover.
45
+
46
+ ## Async + live execution events
47
+
48
+ ```python
49
+ import asyncio
50
+ from cloacina_client import AsyncClient
51
+
52
+ async def main():
53
+ client = AsyncClient("http://localhost:8080", api_key="clk_...")
54
+ accepted = await client.execute_workflow("my_workflow", {"input": 42})
55
+ # Reconnect, dedup, and acks are handled for you.
56
+ async for event in client.follow_execution_events(accepted.execution_id):
57
+ print(event)
58
+
59
+ asyncio.run(main())
60
+ ```
61
+
62
+ WebSocket connections never carry the long-lived key: the SDK mints a single-use, 60-second ticket (`POST /v1/auth/ws-ticket`) per connection. A `4426` close (protocol version mismatch) raises `ProtocolVersionError` — upgrade the SDK.
63
+
64
+ ## Regenerating
65
+
66
+ `src/cloacina_client/_generated/` is produced by a pinned generator from the committed server contract:
67
+
68
+ ```bash
69
+ uvx openapi-python-client@0.29.0 generate \
70
+ --path ../../docs/static/openapi.json \
71
+ --config generator-config.yaml --meta none \
72
+ --output-path src/cloacina_client/_generated --overwrite
73
+ ```
74
+
75
+ ## Contract tests
76
+
77
+ `tests/test_contract.py` exercises every documented endpoint plus the WebSocket lifecycle against a live server:
78
+
79
+ ```bash
80
+ CLOACINA_SERVER_URL=http://localhost:8080 \
81
+ CLOACINA_API_KEY=<bootstrap-key> \
82
+ uv run pytest
83
+ ```
84
+
85
+ The full execute→event-stream flow (which needs a compiled `.cloacina` package) runs in the repo's `angreal test sdk-contract` harness.
@@ -0,0 +1,70 @@
1
+ # cloacina-client
2
+
3
+ Python SDK for [cloacina-server](https://github.com/colliery-io/cloacina) — a typed REST client plus WebSocket execution-event streaming, for Python 3.10+.
4
+
5
+ > **This is the service client.** It talks to a running cloacina-server over HTTP/WebSocket. The embedded workflow runtime is the separate [`cloaca`](https://pypi.org/project/cloaca/) package — the two are deliberately distinct.
6
+
7
+ **Version lockstep:** `cloacina-client X.Y.Z` is generated from, tested against, and only supported on `cloacina-server X.Y.Z`.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pip install cloacina-client
13
+ ```
14
+
15
+ ## Quickstart
16
+
17
+ ```python
18
+ from cloacina_client import Client
19
+
20
+ client = Client("http://localhost:8080", api_key="clk_...", tenant="public")
21
+
22
+ accepted = client.execute_workflow("my_workflow", {"input": 42})
23
+ print(accepted.execution_id)
24
+
25
+ for execution in client.iterate_executions(status="Failed"):
26
+ print(execution.id, execution.workflow_name)
27
+ ```
28
+
29
+ Every helper raises `CloacinaApiError` (with `.status` and the server's machine-readable `.code`) on non-2xx responses. The generated [`openapi-python-client`](https://github.com/openapi-generators/openapi-python-client) client is available as `client.generated` for anything the shim doesn't cover.
30
+
31
+ ## Async + live execution events
32
+
33
+ ```python
34
+ import asyncio
35
+ from cloacina_client import AsyncClient
36
+
37
+ async def main():
38
+ client = AsyncClient("http://localhost:8080", api_key="clk_...")
39
+ accepted = await client.execute_workflow("my_workflow", {"input": 42})
40
+ # Reconnect, dedup, and acks are handled for you.
41
+ async for event in client.follow_execution_events(accepted.execution_id):
42
+ print(event)
43
+
44
+ asyncio.run(main())
45
+ ```
46
+
47
+ WebSocket connections never carry the long-lived key: the SDK mints a single-use, 60-second ticket (`POST /v1/auth/ws-ticket`) per connection. A `4426` close (protocol version mismatch) raises `ProtocolVersionError` — upgrade the SDK.
48
+
49
+ ## Regenerating
50
+
51
+ `src/cloacina_client/_generated/` is produced by a pinned generator from the committed server contract:
52
+
53
+ ```bash
54
+ uvx openapi-python-client@0.29.0 generate \
55
+ --path ../../docs/static/openapi.json \
56
+ --config generator-config.yaml --meta none \
57
+ --output-path src/cloacina_client/_generated --overwrite
58
+ ```
59
+
60
+ ## Contract tests
61
+
62
+ `tests/test_contract.py` exercises every documented endpoint plus the WebSocket lifecycle against a live server:
63
+
64
+ ```bash
65
+ CLOACINA_SERVER_URL=http://localhost:8080 \
66
+ CLOACINA_API_KEY=<bootstrap-key> \
67
+ uv run pytest
68
+ ```
69
+
70
+ The full execute→event-stream flow (which needs a compiled `.cloacina` package) runs in the repo's `angreal test sdk-contract` harness.
@@ -0,0 +1,3 @@
1
+ ---
2
+ package_name_override: "_generated"
3
+ project_name_override: "cloacina-client-generated"
@@ -0,0 +1,37 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "cloacina-client"
7
+ version = "0.8.0"
8
+ description = "Python SDK for cloacina-server — typed REST client and WebSocket execution-event streams. Version-locked to the cloacina server release. (Service client; the embedded runtime is the separate `cloaca` package.)"
9
+ readme = "README.md"
10
+ license = "Apache-2.0"
11
+ requires-python = ">=3.10"
12
+ authors = [{ name = "Dylan Storey", email = "dylan.storey@gmail.com" }]
13
+ dependencies = [
14
+ "httpx>=0.27,<1",
15
+ "attrs>=22.2.0",
16
+ "python-dateutil>=2.8.0",
17
+ "websockets>=13,<16",
18
+ ]
19
+
20
+ [project.urls]
21
+ Repository = "https://github.com/colliery-io/cloacina"
22
+ Documentation = "https://colliery-io.github.io/cloacina/"
23
+
24
+ [dependency-groups]
25
+ dev = ["pytest>=8", "pytest-asyncio>=0.24"]
26
+
27
+ [tool.hatch.build.targets.wheel]
28
+ packages = ["src/cloacina_client"]
29
+
30
+ [tool.pytest.ini_options]
31
+ asyncio_mode = "auto"
32
+
33
+ # Regenerating the vendored client (pinned generator — CI diffs this):
34
+ # uvx openapi-python-client@0.29.0 generate \
35
+ # --path ../../docs/static/openapi.json \
36
+ # --config generator-config.yaml --meta none \
37
+ # --output-path src/cloacina_client/_generated --overwrite
@@ -0,0 +1,52 @@
1
+ # Copyright 2025-2026 Colliery Software
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Python SDK for cloacina-server (CLOACI-I-0113 / T-0647).
16
+
17
+ This is the *service client* — it talks to a running cloacina-server over
18
+ HTTP/WebSocket. The embedded workflow runtime is the separate ``cloaca``
19
+ package; the two are deliberately distinct.
20
+
21
+ Quickstart::
22
+
23
+ from cloacina_client import Client
24
+
25
+ client = Client("http://localhost:8080", api_key="clk_...", tenant="public")
26
+ accepted = client.execute_workflow("my_workflow", {"input": 42})
27
+
28
+ import asyncio
29
+ from cloacina_client import AsyncClient
30
+
31
+ async def follow():
32
+ aclient = AsyncClient("http://localhost:8080", api_key="clk_...")
33
+ async for event in aclient.follow_execution_events(accepted.execution_id):
34
+ print(event)
35
+
36
+ asyncio.run(follow())
37
+ """
38
+
39
+ from ._client import AsyncClient, Client, CloacinaApiError
40
+ from ._generated import models
41
+ from ._ws import DELIVERY_PROTOCOL_VERSION, DeliveryPush
42
+
43
+ __all__ = [
44
+ "AsyncClient",
45
+ "Client",
46
+ "CloacinaApiError",
47
+ "DeliveryPush",
48
+ "DELIVERY_PROTOCOL_VERSION",
49
+ "models",
50
+ ]
51
+
52
+ __version__ = "0.8.0"