dominus-sdk-python 9.0.9__tar.gz → 9.0.11__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 (84) hide show
  1. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/PKG-INFO +4 -4
  2. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/README.md +3 -3
  3. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/__init__.py +1 -1
  4. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/ai.py +30 -12
  5. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/artifacts.py +12 -1
  6. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus_sdk_python.egg-info/PKG-INFO +4 -4
  7. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus_sdk_python.egg-info/SOURCES.txt +3 -0
  8. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/pyproject.toml +1 -1
  9. dominus_sdk_python-9.0.11/tests/test_ai_namespace.py +75 -0
  10. dominus_sdk_python-9.0.11/tests/test_artifacts_namespace.py +93 -0
  11. dominus_sdk_python-9.0.11/tests/test_version_consistency.py +38 -0
  12. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/config/__init__.py +0 -0
  13. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/config/endpoints.py +0 -0
  14. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/contract/__init__.py +0 -0
  15. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/contract/envelope.py +0 -0
  16. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/contract/projections.py +0 -0
  17. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/errors.py +0 -0
  18. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/helpers/__init__.py +0 -0
  19. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/helpers/auth.py +0 -0
  20. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/helpers/cache.py +0 -0
  21. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/helpers/console_capture.py +0 -0
  22. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/helpers/core.py +0 -0
  23. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/helpers/crypto.py +0 -0
  24. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/helpers/sse.py +0 -0
  25. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/helpers/trace.py +0 -0
  26. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/__init__.py +0 -0
  27. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/admin.py +0 -0
  28. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/auth.py +0 -0
  29. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/authority.py +0 -0
  30. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/browser.py +0 -0
  31. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/coder.py +0 -0
  32. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/courier.py +0 -0
  33. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/db.py +0 -0
  34. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/ddl.py +0 -0
  35. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/deployer.py +0 -0
  36. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/fastapi.py +0 -0
  37. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/files.py +0 -0
  38. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/health.py +0 -0
  39. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/jobs.py +0 -0
  40. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/logs.py +0 -0
  41. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/platform.py +0 -0
  42. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/portal.py +0 -0
  43. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/processor.py +0 -0
  44. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/publisher.py +0 -0
  45. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/recipes.py +0 -0
  46. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/redis.py +0 -0
  47. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/secrets.py +0 -0
  48. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/secure.py +0 -0
  49. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/stash.py +0 -0
  50. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/sync.py +0 -0
  51. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/warden.py +0 -0
  52. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/namespaces/workflow.py +0 -0
  53. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/py.typed +0 -0
  54. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/services/__init__.py +0 -0
  55. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus/start.py +0 -0
  56. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus_sdk_python.egg-info/dependency_links.txt +0 -0
  57. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus_sdk_python.egg-info/requires.txt +0 -0
  58. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/dominus_sdk_python.egg-info/top_level.txt +0 -0
  59. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/setup.cfg +0 -0
  60. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_auth.py +0 -0
  61. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_authority_public_vocabulary.py +0 -0
  62. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_browser_namespace.py +0 -0
  63. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_contract.py +0 -0
  64. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_control_plane_namespaces.py +0 -0
  65. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_error_recovery_action.py +0 -0
  66. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_errors.py +0 -0
  67. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_errors_aliases.py +0 -0
  68. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_flat_commands.py +0 -0
  69. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_health.py +0 -0
  70. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_logs.py +0 -0
  71. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_namespace_barrel_exports.py +0 -0
  72. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_platform_coder_namespaces.py +0 -0
  73. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_provisioning_parity.py +0 -0
  74. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_public_exports.py +0 -0
  75. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_publisher_namespace.py +0 -0
  76. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_readme_quickstart_catalog.py +0 -0
  77. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_recipes_namespace.py +0 -0
  78. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_recipes_stash_routing.py +0 -0
  79. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_secrets_presence_contract.py +0 -0
  80. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_stash_artifact_facade.py +0 -0
  81. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_stash_tables_namespace.py +0 -0
  82. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_transport_compat.py +0 -0
  83. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_workflow_lifecycle.py +0 -0
  84. {dominus_sdk_python-9.0.9 → dominus_sdk_python-9.0.11}/tests/test_workflow_refs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dominus-sdk-python
3
- Version: 9.0.9
3
+ Version: 9.0.11
4
4
  Summary: Python SDK for the Dominus gateway-first platform
5
5
  Author-email: CareBridge Systems <dev@carebridge.io>
6
6
  License-Expression: LicenseRef-Proprietary
@@ -38,8 +38,8 @@ Async Python SDK for the Dominus gateway-first service plane.
38
38
  ## Agent Guide
39
39
 
40
40
  Start with `docs/agent-guide/INDEX.md`. The current snapshot is
41
- `docs/agent-guide/2026-09-07-1135-sdk-python/00-reading-order.md`; the latest
42
- cleanup audit is `docs/janitor/2026-09-07-1135-sdk-python-cleanup-audit.md`.
41
+ `docs/agent-guide/2026-09-14-1300-sdk-python/00-reading-order.md`; the latest
42
+ cleanup audit is `docs/janitor/2026-09-14-1300-sdk-python-cleanup-audit.md`.
43
43
 
44
44
  ## What This Repo Ships
45
45
 
@@ -48,7 +48,7 @@ cleanup audit is `docs/janitor/2026-09-07-1135-sdk-python-cleanup-audit.md`.
48
48
  - Gateway-scoped client mode for MCP and other user-JWT sessions
49
49
  - Transport compatibility for wrapped `{success,data}` responses and unwrapped Warden/control-plane success objects
50
50
  - Local helpers for JWT verification, trace propagation, retries, and console capture
51
- - Current package version: `9.0.8`
51
+ - Current package version: `9.0.11`
52
52
 
53
53
  ## Install
54
54
 
@@ -5,8 +5,8 @@ Async Python SDK for the Dominus gateway-first service plane.
5
5
  ## Agent Guide
6
6
 
7
7
  Start with `docs/agent-guide/INDEX.md`. The current snapshot is
8
- `docs/agent-guide/2026-09-07-1135-sdk-python/00-reading-order.md`; the latest
9
- cleanup audit is `docs/janitor/2026-09-07-1135-sdk-python-cleanup-audit.md`.
8
+ `docs/agent-guide/2026-09-14-1300-sdk-python/00-reading-order.md`; the latest
9
+ cleanup audit is `docs/janitor/2026-09-14-1300-sdk-python-cleanup-audit.md`.
10
10
 
11
11
  ## What This Repo Ships
12
12
 
@@ -15,7 +15,7 @@ cleanup audit is `docs/janitor/2026-09-07-1135-sdk-python-cleanup-audit.md`.
15
15
  - Gateway-scoped client mode for MCP and other user-JWT sessions
16
16
  - Transport compatibility for wrapped `{success,data}` responses and unwrapped Warden/control-plane success objects
17
17
  - Local helpers for JWT verification, trace propagation, retries, and console capture
18
- - Current package version: `9.0.8`
18
+ - Current package version: `9.0.11`
19
19
 
20
20
  ## Install
21
21
 
@@ -190,7 +190,7 @@ from .errors import (
190
190
  TimeoutError as DominusTimeoutError,
191
191
  )
192
192
 
193
- __version__ = "9.0.8"
193
+ __version__ = "9.0.11"
194
194
  __all__ = [
195
195
  # Main SDK instance
196
196
  "dominus",
@@ -969,9 +969,10 @@ class AiNamespace(GatewayMixin):
969
969
  tool_allowlist: Optional[List[str]] = None,
970
970
  guardrails: Optional[Dict[str, Any]] = None,
971
971
  output_schema: Optional[Dict[str, Any]] = None,
972
- model: str = "claude-sonnet-4-5",
972
+ model: Optional[str] = None,
973
973
  tool_endpoint: Optional[str] = None,
974
- timeout: float = 300.0
974
+ timeout: float = 300.0,
975
+ provider: str = "claude"
975
976
  ) -> Dict[str, Any]:
976
977
  """
977
978
  Execute agent with blocking wait.
@@ -987,9 +988,10 @@ class AiNamespace(GatewayMixin):
987
988
  tool_allowlist: Optional list of tool names to enable
988
989
  guardrails: Optional guardrails config (max_steps, max_tool_calls, etc.)
989
990
  output_schema: Optional JSON Schema for structured output
990
- model: Model to use (default: claude-sonnet-4-5)
991
+ model: Model to use (provider default when omitted)
991
992
  tool_endpoint: Optional custom tool endpoint URL
992
993
  timeout: Request timeout in seconds (default: 300s)
994
+ provider: Agent provider to use (default: claude)
993
995
 
994
996
  Returns:
995
997
  Dict with "conversation_id", "final_response", "machine_output",
@@ -1000,8 +1002,12 @@ class AiNamespace(GatewayMixin):
1000
1002
  "system_prompt": system_prompt,
1001
1003
  "user_prompt": user_prompt,
1002
1004
  "history_source": history_source,
1003
- "model": model
1005
+ "provider": provider
1004
1006
  }
1007
+ if model:
1008
+ body["model"] = model
1009
+ elif provider == "claude":
1010
+ body["model"] = "claude-sonnet-4-5"
1005
1011
  if inline_history:
1006
1012
  body["inline_history"] = inline_history
1007
1013
  if preloaded_context:
@@ -1034,10 +1040,11 @@ class AiNamespace(GatewayMixin):
1034
1040
  tool_allowlist: Optional[List[str]] = None,
1035
1041
  guardrails: Optional[Dict[str, Any]] = None,
1036
1042
  output_schema: Optional[Dict[str, Any]] = None,
1037
- model: str = "claude-sonnet-4-5",
1043
+ model: Optional[str] = None,
1038
1044
  tool_endpoint: Optional[str] = None,
1039
1045
  on_chunk: Optional[Callable[[Dict[str, Any]], None]] = None,
1040
- timeout: float = 300.0
1046
+ timeout: float = 300.0,
1047
+ provider: str = "claude"
1041
1048
  ) -> AsyncGenerator[Dict[str, Any], None]:
1042
1049
  """
1043
1050
  Execute agent with SSE streaming.
@@ -1053,10 +1060,11 @@ class AiNamespace(GatewayMixin):
1053
1060
  tool_allowlist: Optional list of tool names
1054
1061
  guardrails: Optional guardrails config
1055
1062
  output_schema: Optional JSON Schema for structured output
1056
- model: Model to use
1063
+ model: Model to use (provider default when omitted)
1057
1064
  tool_endpoint: Optional custom tool endpoint URL
1058
1065
  on_chunk: Optional callback for each chunk
1059
1066
  timeout: Request timeout in seconds
1067
+ provider: Agent provider to use (default: claude)
1060
1068
 
1061
1069
  Yields:
1062
1070
  Streaming chunks with "type" and content
@@ -1066,8 +1074,12 @@ class AiNamespace(GatewayMixin):
1066
1074
  "system_prompt": system_prompt,
1067
1075
  "user_prompt": user_prompt,
1068
1076
  "history_source": history_source,
1069
- "model": model
1077
+ "provider": provider
1070
1078
  }
1079
+ if model:
1080
+ body["model"] = model
1081
+ elif provider == "claude":
1082
+ body["model"] = "claude-sonnet-4-5"
1071
1083
  if inline_history:
1072
1084
  body["inline_history"] = inline_history
1073
1085
  if preloaded_context:
@@ -1104,9 +1116,10 @@ class AiNamespace(GatewayMixin):
1104
1116
  tool_allowlist: Optional[List[str]] = None,
1105
1117
  guardrails: Optional[Dict[str, Any]] = None,
1106
1118
  output_schema: Optional[Dict[str, Any]] = None,
1107
- model: str = "claude-sonnet-4-5",
1119
+ model: Optional[str] = None,
1108
1120
  tool_endpoint: Optional[str] = None,
1109
- webhook_url: Optional[str] = None
1121
+ webhook_url: Optional[str] = None,
1122
+ provider: str = "claude"
1110
1123
  ) -> Dict[str, Any]:
1111
1124
  """
1112
1125
  Fire-and-forget async execution.
@@ -1125,9 +1138,10 @@ class AiNamespace(GatewayMixin):
1125
1138
  tool_allowlist: Optional list of tool names
1126
1139
  guardrails: Optional guardrails config
1127
1140
  output_schema: Optional JSON Schema
1128
- model: Model to use
1141
+ model: Model to use (provider default when omitted)
1129
1142
  tool_endpoint: Optional custom tool endpoint URL
1130
1143
  webhook_url: Optional webhook for completion notification
1144
+ provider: Agent provider to use (default: claude)
1131
1145
 
1132
1146
  Returns:
1133
1147
  Dict with "result_key" for polling
@@ -1138,8 +1152,12 @@ class AiNamespace(GatewayMixin):
1138
1152
  "user_prompt": user_prompt,
1139
1153
  "result_key": result_key,
1140
1154
  "history_source": history_source,
1141
- "model": model
1155
+ "provider": provider
1142
1156
  }
1157
+ if model:
1158
+ body["model"] = model
1159
+ elif provider == "claude":
1160
+ body["model"] = "claude-sonnet-4-5"
1143
1161
  if inline_history:
1144
1162
  body["inline_history"] = inline_history
1145
1163
  if preloaded_context:
@@ -624,11 +624,22 @@ class ArtifactsNamespace:
624
624
  async def unwatch(self, *, watcher_name: str, **selector: Any) -> Dict[str, Any]:
625
625
  return await self.unwatch_v2(watcher_name=watcher_name, **selector)
626
626
 
627
- async def list_v2(self, limit: int = 100, include_tombstoned: bool = False, **selector: Any) -> Dict[str, Any]:
627
+ async def list_v2(
628
+ self,
629
+ limit: int = 100,
630
+ include_tombstoned: bool = False,
631
+ cursor: Optional[str] = None,
632
+ include_versions: bool = False,
633
+ **selector: Any,
634
+ ) -> Dict[str, Any]:
628
635
  body = self._selector_body(selector)
629
636
  body["limit"] = limit
630
637
  if include_tombstoned:
631
638
  body["include_tombstoned"] = True
639
+ if cursor:
640
+ body["cursor"] = cursor
641
+ if include_versions:
642
+ body["include_versions"] = True
632
643
  return await self._api("/api/artifact/v2/list", body=body)
633
644
 
634
645
  async def delete_v2(self, *, tombstone: bool = False, delete_bookmarks: bool = False, actor_context: Optional[Dict[str, str]] = None, **selector: Any) -> Dict[str, Any]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dominus-sdk-python
3
- Version: 9.0.9
3
+ Version: 9.0.11
4
4
  Summary: Python SDK for the Dominus gateway-first platform
5
5
  Author-email: CareBridge Systems <dev@carebridge.io>
6
6
  License-Expression: LicenseRef-Proprietary
@@ -38,8 +38,8 @@ Async Python SDK for the Dominus gateway-first service plane.
38
38
  ## Agent Guide
39
39
 
40
40
  Start with `docs/agent-guide/INDEX.md`. The current snapshot is
41
- `docs/agent-guide/2026-09-07-1135-sdk-python/00-reading-order.md`; the latest
42
- cleanup audit is `docs/janitor/2026-09-07-1135-sdk-python-cleanup-audit.md`.
41
+ `docs/agent-guide/2026-09-14-1300-sdk-python/00-reading-order.md`; the latest
42
+ cleanup audit is `docs/janitor/2026-09-14-1300-sdk-python-cleanup-audit.md`.
43
43
 
44
44
  ## What This Repo Ships
45
45
 
@@ -48,7 +48,7 @@ cleanup audit is `docs/janitor/2026-09-07-1135-sdk-python-cleanup-audit.md`.
48
48
  - Gateway-scoped client mode for MCP and other user-JWT sessions
49
49
  - Transport compatibility for wrapped `{success,data}` responses and unwrapped Warden/control-plane success objects
50
50
  - Local helpers for JWT verification, trace propagation, retries, and console capture
51
- - Current package version: `9.0.8`
51
+ - Current package version: `9.0.11`
52
52
 
53
53
  ## Install
54
54
 
@@ -52,6 +52,8 @@ dominus_sdk_python.egg-info/SOURCES.txt
52
52
  dominus_sdk_python.egg-info/dependency_links.txt
53
53
  dominus_sdk_python.egg-info/requires.txt
54
54
  dominus_sdk_python.egg-info/top_level.txt
55
+ tests/test_ai_namespace.py
56
+ tests/test_artifacts_namespace.py
55
57
  tests/test_auth.py
56
58
  tests/test_authority_public_vocabulary.py
57
59
  tests/test_browser_namespace.py
@@ -75,5 +77,6 @@ tests/test_secrets_presence_contract.py
75
77
  tests/test_stash_artifact_facade.py
76
78
  tests/test_stash_tables_namespace.py
77
79
  tests/test_transport_compat.py
80
+ tests/test_version_consistency.py
78
81
  tests/test_workflow_lifecycle.py
79
82
  tests/test_workflow_refs.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dominus-sdk-python"
7
- version = "9.0.9"
7
+ version = "9.0.11"
8
8
  description = "Python SDK for the Dominus gateway-first platform"
9
9
  readme = "README.md"
10
10
  license = "LicenseRef-Proprietary"
@@ -0,0 +1,75 @@
1
+ import pytest
2
+
3
+ from dominus.namespaces.ai import AiNamespace
4
+
5
+
6
+ class FakeClient:
7
+ def __init__(self):
8
+ self.calls = []
9
+ self.stream_calls = []
10
+
11
+ async def _request(self, endpoint, method="POST", body=None, use_gateway=False):
12
+ self.calls.append(
13
+ {
14
+ "endpoint": endpoint,
15
+ "method": method,
16
+ "body": body,
17
+ "use_gateway": use_gateway,
18
+ }
19
+ )
20
+ return {"ok": True}
21
+
22
+ async def _stream_request(
23
+ self, endpoint, body=None, on_chunk=None, timeout=300.0, use_gateway=False
24
+ ):
25
+ self.stream_calls.append(
26
+ {
27
+ "endpoint": endpoint,
28
+ "body": body,
29
+ "timeout": timeout,
30
+ "use_gateway": use_gateway,
31
+ }
32
+ )
33
+ yield {"type": "complete"}
34
+
35
+
36
+ @pytest.mark.asyncio
37
+ async def test_agent_methods_forward_provider_to_each_agent_route():
38
+ client = FakeClient()
39
+ namespace = AiNamespace(client)
40
+
41
+ await namespace.run_agent(
42
+ "conv-1", "system", "user", provider="openai", model="gpt-4o"
43
+ )
44
+ [chunk async for chunk in namespace.stream_agent(
45
+ "conv-2", "system", "user", provider="openai", model="gpt-4o"
46
+ )]
47
+ await namespace.run_agent_async(
48
+ "conv-3",
49
+ "system",
50
+ "user",
51
+ "result-3",
52
+ provider="openai",
53
+ model="gpt-4o",
54
+ )
55
+
56
+ assert [call["body"]["provider"] for call in client.calls] == [
57
+ "openai",
58
+ "openai",
59
+ ]
60
+ assert client.stream_calls[0]["body"]["provider"] == "openai"
61
+
62
+
63
+ @pytest.mark.asyncio
64
+ async def test_provider_only_agent_call_leaves_model_for_server_default():
65
+ client = FakeClient()
66
+ namespace = AiNamespace(client)
67
+
68
+ await namespace.run_agent(
69
+ "conv-provider-only",
70
+ "system",
71
+ "user",
72
+ provider="openai",
73
+ )
74
+
75
+ assert "model" not in client.calls[0]["body"]
@@ -0,0 +1,93 @@
1
+ import pytest
2
+
3
+ import dominus.start as start_module
4
+
5
+
6
+ @pytest.fixture()
7
+ def sdk(monkeypatch):
8
+ monkeypatch.setattr(start_module, "_VALIDATION_ERROR", None)
9
+ monkeypatch.setattr(start_module, "_TOKEN", "a" * 64)
10
+ monkeypatch.setattr(start_module, "_VALIDATED", False)
11
+ monkeypatch.setattr(start_module, "_BASE_URL", "https://gateway.example")
12
+ monkeypatch.setattr(start_module, "_GATEWAY_URL", "https://gateway.example")
13
+ return start_module.Dominus()
14
+
15
+
16
+ @pytest.mark.asyncio
17
+ async def test_list_v2_forwards_cursor_and_include_versions(monkeypatch, sdk):
18
+ calls = []
19
+
20
+ async def fake_request(**kwargs):
21
+ calls.append(kwargs)
22
+ return {"artifacts": [], "count": 0, "total_size_bytes": 0, "next_cursor": "cursor-2"}
23
+
24
+ monkeypatch.setattr(sdk, "_request", fake_request)
25
+
26
+ result = await sdk.artifacts.list_v2(
27
+ cursor="cursor-1",
28
+ include_versions=True,
29
+ owner="project:00000000-0000-0000-0000-000000000000",
30
+ )
31
+
32
+ assert result["next_cursor"] == "cursor-2"
33
+ assert calls == [
34
+ {
35
+ "endpoint": "/api/artifact/v2/list",
36
+ "method": "POST",
37
+ "body": {
38
+ "owner": "project:00000000-0000-0000-0000-000000000000",
39
+ "limit": 100,
40
+ "cursor": "cursor-1",
41
+ "include_versions": True,
42
+ },
43
+ "use_gateway": True,
44
+ "timeout": 30.0,
45
+ "actor": None,
46
+ }
47
+ ]
48
+
49
+
50
+ @pytest.mark.asyncio
51
+ async def test_list_v2_omits_unset_cursor_and_include_versions(monkeypatch, sdk):
52
+ calls = []
53
+
54
+ async def fake_request(**kwargs):
55
+ calls.append(kwargs)
56
+ return {"artifacts": [], "count": 0, "total_size_bytes": 0, "next_cursor": None}
57
+
58
+ monkeypatch.setattr(sdk, "_request", fake_request)
59
+
60
+ await sdk.artifacts.list_v2(group="dominus", owner="project:p", environment="production", kind="legacy")
61
+
62
+ assert calls == [
63
+ {
64
+ "endpoint": "/api/artifact/v2/list",
65
+ "method": "POST",
66
+ "body": {
67
+ "group": "dominus",
68
+ "owner": "project:p",
69
+ "environment": "production",
70
+ "kind": "legacy",
71
+ "limit": 100,
72
+ },
73
+ "use_gateway": True,
74
+ "timeout": 30.0,
75
+ "actor": None,
76
+ }
77
+ ]
78
+
79
+
80
+ @pytest.mark.asyncio
81
+ async def test_list_v2_empty_cursor_is_not_forwarded(monkeypatch, sdk):
82
+ """An empty cursor is falsy and must not be sent: the worker rejects a malformed cursor with 400."""
83
+ calls = []
84
+
85
+ async def fake_request(**kwargs):
86
+ calls.append(kwargs)
87
+ return {"artifacts": [], "count": 0, "total_size_bytes": 0, "next_cursor": None}
88
+
89
+ monkeypatch.setattr(sdk, "_request", fake_request)
90
+
91
+ await sdk.artifacts.list_v2(cursor="", owner="project:p")
92
+
93
+ assert "cursor" not in calls[0]["body"]
@@ -0,0 +1,38 @@
1
+ """Executable contract for Non-Negotiable #7: the two version authorities agree.
2
+
3
+ `pyproject.toml` is what the production publish workflow stamps on the artifact
4
+ (and what PyPI is queried with); `dominus/__init__.py` is what the installed
5
+ package reports at runtime. When they drift, a production push publishes a
6
+ package that misreports its own version. The drift has recurred twice
7
+ (9.0.7/9.0.6, then 9.0.9/9.0.8), so it is asserted mechanically here.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import re
13
+ from pathlib import Path
14
+
15
+ import dominus
16
+
17
+ ROOT = Path(__file__).resolve().parents[1]
18
+ PYPROJECT = ROOT / "pyproject.toml"
19
+
20
+ _VERSION_LINE = re.compile(r'^version\s*=\s*"([^"]+)"', re.MULTILINE)
21
+
22
+
23
+ def _pyproject_version() -> str:
24
+ raw = PYPROJECT.read_bytes()
25
+ try:
26
+ import tomllib
27
+ except ModuleNotFoundError: # Python 3.9/3.10
28
+ match = _VERSION_LINE.search(raw.decode("utf-8"))
29
+ assert match is not None, "pyproject.toml declares no [project] version"
30
+ return match.group(1)
31
+ return tomllib.loads(raw.decode("utf-8"))["project"]["version"]
32
+
33
+
34
+ def test_pyproject_and_package_version_match() -> None:
35
+ assert _pyproject_version() == dominus.__version__, (
36
+ "pyproject.toml and dominus/__init__.py versions have drifted: "
37
+ f"pyproject={_pyproject_version()!r}, dominus.__version__={dominus.__version__!r}"
38
+ )