imperal-sdk 5.2.0__tar.gz → 5.2.2__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 (279) hide show
  1. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/CHANGELOG.md +44 -7
  2. imperal_sdk-5.2.2/PKG-INFO +148 -0
  3. imperal_sdk-5.2.2/README.md +111 -0
  4. imperal_sdk-5.2.2/src/imperal_sdk/__init__.py +188 -0
  5. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/extension.py +14 -15
  6. imperal_sdk-5.2.2/tests/test_import_light.py +103 -0
  7. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_manifest_no_orchestrator_tool.py +29 -12
  8. imperal_sdk-5.2.0/PKG-INFO +0 -264
  9. imperal_sdk-5.2.0/README.md +0 -227
  10. imperal_sdk-5.2.0/src/imperal_sdk/__init__.py +0 -73
  11. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/.github/workflows/identity-contract.yml +0 -0
  12. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/.github/workflows/publish.yml +0 -0
  13. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/.github/workflows/test.yml +0 -0
  14. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/.gitignore +0 -0
  15. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/LICENSE +0 -0
  16. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/api_surface.json +0 -0
  17. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/docs/sdl-facets.md +0 -0
  18. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/pyproject.toml +0 -0
  19. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/sdk_claims.json +0 -0
  20. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/sdl_roles.json +0 -0
  21. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/.codebase-index-cache.pkl +0 -0
  22. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ai/__init__.py +0 -0
  23. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ai/client.py +0 -0
  24. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/auth/__init__.py +0 -0
  25. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/auth/client.py +0 -0
  26. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/auth/middleware.py +0 -0
  27. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/billing/__init__.py +0 -0
  28. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/billing/client.py +0 -0
  29. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/cache/__init__.py +0 -0
  30. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/cache/client.py +0 -0
  31. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/cache/protocol.py +0 -0
  32. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/__init__.py +0 -0
  33. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/action_result.py +0 -0
  34. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/error_codes.py +0 -0
  35. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/exceptions.py +0 -0
  36. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/filters.py +0 -0
  37. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/guards.py +0 -0
  38. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/kernel_primitives.py +0 -0
  39. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/narration.py +0 -0
  40. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/narration_guard.py +0 -0
  41. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/prompt.py +0 -0
  42. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/chat/refusal.py +0 -0
  43. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/cli/__init__.py +0 -0
  44. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/cli/main.py +0 -0
  45. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/config/__init__.py +0 -0
  46. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/config/client.py +0 -0
  47. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/context.py +0 -0
  48. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/devtools/__init__.py +0 -0
  49. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/devtools/contract_checks.py +0 -0
  50. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/devtools/generate_api_surface.py +0 -0
  51. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/devtools/generate_sdk_claims.py +0 -0
  52. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/devtools/validate_identity_contract.py +0 -0
  53. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/errors.py +0 -0
  54. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/extension.py +0 -0
  55. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/extensions/__init__.py +0 -0
  56. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/extensions/client.py +0 -0
  57. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/http/__init__.py +0 -0
  58. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/http/client.py +0 -0
  59. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/manifest.py +0 -0
  60. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/manifest_schema.py +0 -0
  61. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/notify/__init__.py +0 -0
  62. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/notify/client.py +0 -0
  63. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/prompts/__init__.py +0 -0
  64. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/prompts/icnli_integrity_rules.txt +0 -0
  65. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/prompts/kernel_formatting_rule.txt +0 -0
  66. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/prompts/kernel_proactivity_rule.txt +0 -0
  67. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/protocols.py +0 -0
  68. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/rpc/__init__.py +0 -0
  69. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/rpc/codec.py +0 -0
  70. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/rpc/contract.py +0 -0
  71. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/runtime/__init__.py +0 -0
  72. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/runtime/executor.py +0 -0
  73. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/runtime/llm_provider.py +0 -0
  74. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/runtime/message_adapter.py +0 -0
  75. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/action_result.schema.json +0 -0
  76. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/balance_info.schema.json +0 -0
  77. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/chat_result.schema.json +0 -0
  78. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/completion_result.schema.json +0 -0
  79. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/document.schema.json +0 -0
  80. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/event.schema.json +0 -0
  81. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/file_info.schema.json +0 -0
  82. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/function_call.schema.json +0 -0
  83. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/http_response.schema.json +0 -0
  84. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/imperal.schema.json +0 -0
  85. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/limits_result.schema.json +0 -0
  86. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/schemas/subscription_info.schema.json +0 -0
  87. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/__init__.py +0 -0
  88. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/_generate_roles_json.py +0 -0
  89. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/entity.py +0 -0
  90. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/__init__.py +0 -0
  91. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/catalog.py +0 -0
  92. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/comm.py +0 -0
  93. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/content.py +0 -0
  94. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/device.py +0 -0
  95. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/event.py +0 -0
  96. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/geo.py +0 -0
  97. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/identity.py +0 -0
  98. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/media.py +0 -0
  99. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/metric.py +0 -0
  100. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/money.py +0 -0
  101. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/net.py +0 -0
  102. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/people.py +0 -0
  103. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/quantity.py +0 -0
  104. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/rating.py +0 -0
  105. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/security.py +0 -0
  106. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/task.py +0 -0
  107. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/facets/time.py +0 -0
  108. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/field.py +0 -0
  109. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/sdl/roles.py +0 -0
  110. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/secrets/__init__.py +0 -0
  111. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/secrets/client.py +0 -0
  112. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/secrets/exceptions.py +0 -0
  113. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/secrets/panel_handler.py +0 -0
  114. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/secrets/spec.py +0 -0
  115. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/security/__init__.py +0 -0
  116. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/security/call_token.py +0 -0
  117. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/skeleton/__init__.py +0 -0
  118. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/skeleton/client.py +0 -0
  119. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/storage/__init__.py +0 -0
  120. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/storage/client.py +0 -0
  121. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/store/__init__.py +0 -0
  122. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/store/client.py +0 -0
  123. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/store/exceptions.py +0 -0
  124. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/testing/__init__.py +0 -0
  125. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/testing/mock_context.py +0 -0
  126. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/testing/mock_secrets.py +0 -0
  127. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/__init__.py +0 -0
  128. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/action_result.py +0 -0
  129. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/chat_result.py +0 -0
  130. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/client_contracts.py +0 -0
  131. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/contracts.py +0 -0
  132. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/contributions.py +0 -0
  133. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/events.py +0 -0
  134. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/health.py +0 -0
  135. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/identity.py +0 -0
  136. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/models.py +0 -0
  137. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/pagination.py +0 -0
  138. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/types/store_contracts.py +0 -0
  139. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/__init__.py +0 -0
  140. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/actions.py +0 -0
  141. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/base.py +0 -0
  142. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/data.py +0 -0
  143. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/display.py +0 -0
  144. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/feedback.py +0 -0
  145. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/graph.py +0 -0
  146. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/input_components.py +0 -0
  147. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/interactive.py +0 -0
  148. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/layout.py +0 -0
  149. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/ui/theme.py +0 -0
  150. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/validator.py +0 -0
  151. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/src/imperal_sdk/validator_v1_6_0.py +0 -0
  152. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/conftest.py +0 -0
  153. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/contract/__init__.py +0 -0
  154. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/contract/test_contract_checks_selftest.py +0 -0
  155. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/contract/test_generate_sdk_claims.py +0 -0
  156. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/contract/test_sample_contract_shape.py +0 -0
  157. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/contract/test_sdk_matches_kernel_contract.py +0 -0
  158. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/contracts/__init__.py +0 -0
  159. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/contracts/test_store_contracts.py +0 -0
  160. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/fixtures/contract/kernel-contract.sample.json +0 -0
  161. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/fixtures/openapi/auth-gateway.json +0 -0
  162. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/fixtures/openapi/registry.json +0 -0
  163. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/fixtures/openapi/sharelock-cases.json +0 -0
  164. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/rpc/__init__.py +0 -0
  165. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/rpc/test_codec.py +0 -0
  166. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/rpc/test_contract.py +0 -0
  167. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/runtime/__init__.py +0 -0
  168. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/runtime/test_llm_provider_config_store.py +0 -0
  169. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/runtime/test_llm_provider_ctx_injection.py +0 -0
  170. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/store/__init__.py +0 -0
  171. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/store/test_list_users_client.py +0 -0
  172. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/store/test_query_all_client.py +0 -0
  173. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_action_result_typed.py +0 -0
  174. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_as_user.py +0 -0
  175. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_auth.py +0 -0
  176. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_billing.py +0 -0
  177. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_cache_client.py +0 -0
  178. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_cache_model.py +0 -0
  179. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_call_token.py +0 -0
  180. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_chat_extension_deprecation.py +0 -0
  181. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_chat_extension_no_llm_router.py +0 -0
  182. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_chat_filters.py +0 -0
  183. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_chat_function_background_flag.py +0 -0
  184. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_chat_guards.py +0 -0
  185. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_chat_guards_bleed.py +0 -0
  186. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_chat_prompt.py +0 -0
  187. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_chat_result.py +0 -0
  188. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_cli.py +0 -0
  189. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_client_contracts.py +0 -0
  190. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_config_client.py +0 -0
  191. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_context.py +0 -0
  192. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_context_background_task.py +0 -0
  193. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_context_deliver_chat_message.py +0 -0
  194. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_context_guards.py +0 -0
  195. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_contracts.py +0 -0
  196. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_contracts_live.py +0 -0
  197. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_contributions.py +0 -0
  198. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_data_model_kwarg.py +0 -0
  199. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_document_contract.py +0 -0
  200. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_emits_decorator.py +0 -0
  201. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_error_codes.py +0 -0
  202. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_errors.py +0 -0
  203. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_event_schema_v2.py +0 -0
  204. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_events_health.py +0 -0
  205. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_extension.py +0 -0
  206. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_extension_v2.py +0 -0
  207. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_extensions_emit.py +0 -0
  208. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_http_timeout_override.py +0 -0
  209. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_id_shape_guard.py +0 -0
  210. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_identity_contract.py +0 -0
  211. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_imperal_schema_v2.py +0 -0
  212. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_kernel_primitives.py +0 -0
  213. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_manifest.py +0 -0
  214. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_manifest_roundtrip_gate.py +0 -0
  215. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_manifest_schema.py +0 -0
  216. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_manifest_v2_events.py +0 -0
  217. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_manifest_v2_other_sections.py +0 -0
  218. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_manifest_v2_webhooks.py +0 -0
  219. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_manifest_validator_v2.py +0 -0
  220. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_mock_context.py +0 -0
  221. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_models.py +0 -0
  222. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_narration_emission.py +0 -0
  223. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_narration_guard.py +0 -0
  224. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_openai_max_completion_tokens.py +0 -0
  225. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_pagination.py +0 -0
  226. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_panel_rendering_contract.py +0 -0
  227. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_panels.py +0 -0
  228. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_phase_a_dead_removal.py +0 -0
  229. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_phase_a_drift.py +0 -0
  230. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_phase_a_text.py +0 -0
  231. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdk_version_stamp.py +0 -0
  232. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_entity.py +0 -0
  233. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_entity_marker.py +0 -0
  234. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_exports.py +0 -0
  235. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_catalog.py +0 -0
  236. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_collisions.py +0 -0
  237. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_comm.py +0 -0
  238. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_content.py +0 -0
  239. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_device.py +0 -0
  240. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_event.py +0 -0
  241. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_exports.py +0 -0
  242. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_field.py +0 -0
  243. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_geo.py +0 -0
  244. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_identity.py +0 -0
  245. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_media.py +0 -0
  246. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_metric.py +0 -0
  247. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_money.py +0 -0
  248. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_net.py +0 -0
  249. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_people.py +0 -0
  250. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_quantity.py +0 -0
  251. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_rating.py +0 -0
  252. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_security.py +0 -0
  253. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_task.py +0 -0
  254. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facet_time.py +0 -0
  255. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facets_catalog.py +0 -0
  256. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facets_doc.py +0 -0
  257. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_facets_pkg.py +0 -0
  258. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_field.py +0 -0
  259. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_roles.py +0 -0
  260. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_roles_json.py +0 -0
  261. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_sdl_roles_of_facets.py +0 -0
  262. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_skeleton_decorator.py +0 -0
  263. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_spec_validation.py +0 -0
  264. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_ui.py +0 -0
  265. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_ui_fileupload_enhanced.py +0 -0
  266. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_ui_html.py +0 -0
  267. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_ui_image_enhanced.py +0 -0
  268. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_ui_open.py +0 -0
  269. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_ui_theme.py +0 -0
  270. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_user.py +0 -0
  271. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_v7_emit_refusal.py +0 -0
  272. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_validator.py +0 -0
  273. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_validator_drift.py +0 -0
  274. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_validator_pep563.py +0 -0
  275. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_validator_v1_6_0_rules.py +0 -0
  276. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_validator_v25.py +0 -0
  277. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/test_write_arg_bleed.py +0 -0
  278. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/tools/__init__.py +0 -0
  279. {imperal_sdk-5.2.0 → imperal_sdk-5.2.2}/tests/tools/test_generate_api_surface.py +0 -0
@@ -2,14 +2,52 @@
2
2
 
3
3
  All notable changes to `imperal-sdk` are documented here.
4
4
 
5
+ ## 5.2.2 — 2026-06-11 — Import-light package root
6
+
7
+ Performance / robustness release. **Zero API changes** — every public name,
8
+ submodule attribute, star-import and `dir()` entry resolves exactly as before
9
+ (verified by an eager-parity test over the whole surface).
10
+
11
+ ### Changed
12
+
13
+ - **The package root is now import-light (PEP 562 lazy surface).**
14
+ `import imperal_sdk` — and importing transport-free helpers such as
15
+ `imperal_sdk.chat.filters` or `imperal_sdk.chat.error_codes` — no longer
16
+ loads the HTTP client stack. Heavy dependencies load on first use of the
17
+ names that actually need them (`Context`, the service clients,
18
+ `get_llm_provider`, …). Benefits: faster cold imports, and helper modules
19
+ are now safe to import from restricted/sandboxed execution contexts that
20
+ forbid network-stack loading.
21
+
22
+ Nothing to migrate — rebuild against `imperal-sdk>=5.2.2` at your convenience.
23
+
24
+ ## 5.2.1 — 2026-06-01 — ChatExtension ergonomics & honest deprecations
25
+
26
+ Small, fully backward-compatible cleanup of `ChatExtension`. No API removals;
27
+ existing extensions are unaffected.
28
+
29
+ ### Changed
30
+
31
+ - `ChatExtension(tool_name=...)` no longer emits a `DeprecationWarning`. The
32
+ kwarg is the **canonical** chat-registration key — it groups your
33
+ `@chat.function` tools in the manifest, anchors the per-turn prompt, and
34
+ labels scope-guard audit lines. It is load-bearing and not going away; the
35
+ prior "removed in 5.1.0" warning was incorrect and has been removed.
36
+
37
+ ### Added
38
+
39
+ - `ChatExtension(...)` now accepts an **optional** `tool_name`. When omitted it
40
+ defaults to `f"tool_{ext.app_id}_chat"`. Pass it explicitly to pin a stable
41
+ routing name (recommended for production extensions). `description=` is now
42
+ optional as well.
43
+
5
44
  ## 5.2.0 — 2026-05-31 — Structured Data Layer (SDL) foundation
6
45
 
7
46
  Introduces the **SDL (`imperal_sdk.sdl`)** — a typed, semantic vocabulary for the
8
47
  data an extension returns, so the platform can read an entity's id / title / kind
9
48
  and its facets directly instead of inferring them from field names. This release
10
49
  ships the SDK foundation (canonical types + the standard facet library + a schema
11
- marker for platform detection); the platform begins reading SDL behind a rollout
12
- flag in a later release. Fully **additive** — the existing API and existing
50
+ marker for platform detection). **The platform reads SDL in production today.** Fully **additive** — the existing API and existing
13
51
  extensions are unchanged; adopting SDL is opt-in via `data_model=`.
14
52
 
15
53
  ### Added
@@ -28,8 +66,8 @@ extensions are unchanged; adopting SDL is opt-in via `data_model=`.
28
66
  - `sdl.roles_of(model)` — introspect a model's field→role map.
29
67
 
30
68
  Use it via `data_model=` on `@chat.function` (e.g.
31
- `class Note(sdl.Entity): ...` → `data_model=Note`). Full platform integration
32
- arrives in a later phase. Not yet wired into the platform.
69
+ `class Note(sdl.Entity): ...` → `data_model=Note`). **The platform reads SDL
70
+ entities in production today.**
33
71
  - **SDL — Standard Facet Library (Phase 2).** 123 composable facet mixins across
34
72
  17 families (Identity, Time, People, Content, Communication, Media, Quantities,
35
73
  Money, Catalog, Tasks, Location, Tech/Network, Analytics, Events, Ratings,
@@ -43,9 +81,8 @@ extensions are unchanged; adopting SDL is opt-in via `data_model=`.
43
81
 
44
82
  564 standard roles are catalogued in `sdl_roles.json`. Every facet field is
45
83
  optional; for anything not covered, use `sdl.field(role="yourapp.x")` with a
46
- non-reserved namespace. Full guide: `docs/sdl-facets.md`. Still not wired into
47
- the platform — extensions can adopt the types now; the platform begins reading
48
- them in a later phase.
84
+ non-reserved namespace. Full guide: `docs/sdl-facets.md`. **Live in production**
85
+ extensions adopt the types and the platform reads them today.
49
86
  - **SDL — schema marker on `Entity` / `EntityList`.** Both stamp
50
87
  `x-sdl: "entity"` / `"entity-list"` into their JSON schema so the platform can
51
88
  detect an SDL-typed result from a function's return schema alone. Inherited by
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: imperal-sdk
3
+ Version: 5.2.2
4
+ Summary: SDK for building Imperal Cloud extensions
5
+ Author: Valentin Scerbacov, Imperal, Inc.
6
+ License-Expression: AGPL-3.0-or-later
7
+ License-File: LICENSE
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Framework :: FastAPI
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Classifier: Typing :: Typed
18
+ Requires-Python: >=3.11
19
+ Requires-Dist: click>=8.1.0
20
+ Requires-Dist: httpx>=0.28.0
21
+ Requires-Dist: pydantic>=2.10.0
22
+ Requires-Dist: pyjwt[crypto]>=2.10.0
23
+ Provides-Extra: contract
24
+ Requires-Dist: schemathesis>=3.30.0; extra == 'contract'
25
+ Provides-Extra: db
26
+ Requires-Dist: aiomysql>=0.2.0; extra == 'db'
27
+ Requires-Dist: sqlalchemy[asyncio]>=2.0.30; extra == 'db'
28
+ Provides-Extra: dev
29
+ Requires-Dist: jsonschema>=4.21.0; extra == 'dev'
30
+ Requires-Dist: openapi-spec-validator>=0.7.1; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.25.0; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
33
+ Requires-Dist: respx>=0.22.0; extra == 'dev'
34
+ Provides-Extra: fastapi
35
+ Requires-Dist: fastapi>=0.115.0; extra == 'fastapi'
36
+ Description-Content-Type: text/markdown
37
+
38
+ <div align="center">
39
+
40
+ # Imperal SDK
41
+
42
+ ### Build extensions for Webbee 🐝 — the agent of Imperal Cloud, the world's first AI Cloud OS.
43
+
44
+ **Write a small Python function. Webbee calls it when a user asks for it — in their own words. Ship it to the Marketplace and get paid.**
45
+
46
+ [![PyPI](https://img.shields.io/pypi/v/imperal-sdk?color=blue&label=PyPI)](https://pypi.org/project/imperal-sdk/)
47
+ [![Python](https://img.shields.io/pypi/pyversions/imperal-sdk)](https://pypi.org/project/imperal-sdk/)
48
+ [![License](https://img.shields.io/badge/license-AGPL--3.0-blue)](LICENSE)
49
+
50
+ [Documentation](https://docs.imperal.io) · [Quickstart](https://docs.imperal.io/en/getting-started/quick-start/) · [PyPI](https://pypi.org/project/imperal-sdk/) · [imperal.io](https://imperal.io)
51
+
52
+ </div>
53
+
54
+ ---
55
+
56
+ ## What this is
57
+
58
+ **Imperal Cloud** is the world's first AI Cloud OS — a cloud you connect the contexts of your life into (mail, money, projects, servers, notes, anything) and then run entirely in your own native language. **Webbee 🐝** is the AI agent that lives inside it and does the work for you, safely.
59
+
60
+ **The Imperal SDK is how you give Webbee a new skill.** You write a small, typed Python *extension*; Webbee picks it up and calls it whenever a user asks for what it does — in plain language. The platform handles the hard parts — authentication, billing, multi-tenancy, audit, recovery, LLM routing — so your code stays small.
61
+
62
+ ```bash
63
+ pip install imperal-sdk
64
+ ```
65
+
66
+ > Python 3.11+ · AGPL-3.0-or-later
67
+
68
+ ## Why build here
69
+
70
+ - **Webbee calls your function directly.** Typed, structured calls — no LLM guessing your arguments, no silent write failures.
71
+ - **The platform does the plumbing.** Auth, per-user isolation, billing, audit, retries and recovery, multi-tenant safety — handled for you.
72
+ - **You get paid.** Publish to the Imperal Marketplace, price your extension, earn on every use.
73
+ - **Bring any LLM.** Users connect their own model keys — Anthropic, OpenAI, Google, Ollama, any OpenAI-compatible API.
74
+
75
+ ## A 60-second extension
76
+
77
+ ```python
78
+ from imperal_sdk import Extension, ChatExtension, ActionResult
79
+ from pydantic import BaseModel, Field
80
+
81
+ ext = Extension(
82
+ "hello-world",
83
+ version="1.0.0",
84
+ display_name="Hello World",
85
+ description="Greets people by name with a friendly message.",
86
+ icon="icon.svg",
87
+ actions_explicit=True,
88
+ )
89
+
90
+ chat = ChatExtension(ext, tool_name="hello_world", description="Friendly greetings.")
91
+
92
+
93
+ class GreetParams(BaseModel):
94
+ name: str = Field(..., description="Person to greet")
95
+
96
+
97
+ @chat.function("greet", description="Greet someone by name.", action_type="read")
98
+ async def greet(ctx, params: GreetParams) -> ActionResult:
99
+ return ActionResult.success(
100
+ data={"message": f"Hello, {params.name}! 🐝"},
101
+ summary=f"Greeted {params.name}",
102
+ )
103
+ ```
104
+
105
+ That's a real, working extension. When a user types *"say hi to Alex"*, Webbee calls `greet(name="Alex")`.
106
+
107
+ → Full walkthrough, from zero to published: **[docs.imperal.io](https://docs.imperal.io/en/getting-started/quick-start/)**
108
+
109
+ ## What you can build
110
+
111
+ - **Chat tools** — typed `@chat.function`s Webbee calls straight from natural language.
112
+ - **Panels** — UI surfaces rendered inside the Imperal Panel.
113
+ - **Skeletons** — live data feeds that keep Webbee aware of a user's state.
114
+ - **Scheduled jobs & webhooks** — act on a timer, or react to outside events.
115
+ - **Typed entities (SDL)** — return `sdl.Entity` objects and the platform reads their meaning (id, title, kind, …) directly instead of guessing field names. Live in production.
116
+
117
+ Every published extension passes the **federal contract** — the validators that let Webbee call your code safely. The SDK checks it locally before you ship.
118
+
119
+ ## Test without a server
120
+
121
+ ```python
122
+ from imperal_sdk.testing import MockContext
123
+
124
+ async def test_greet():
125
+ ctx = MockContext()
126
+ result = await greet(ctx, GreetParams(name="Alex"))
127
+ assert result.status == "success"
128
+ ```
129
+
130
+ ## Documentation
131
+
132
+ The full API, the manifest schema, every validator, recipes, and the federal contract live at **[docs.imperal.io](https://docs.imperal.io)** — that's the source of truth; this README is just the doorway.
133
+
134
+ | | |
135
+ |---|---|
136
+ | Documentation | [docs.imperal.io](https://docs.imperal.io) |
137
+ | Quickstart | [docs.imperal.io/en/getting-started/quick-start](https://docs.imperal.io/en/getting-started/quick-start/) |
138
+ | PyPI | [pypi.org/project/imperal-sdk](https://pypi.org/project/imperal-sdk/) |
139
+ | Changelog | [CHANGELOG.md](CHANGELOG.md) |
140
+ | License | [AGPL-3.0-or-later](LICENSE) |
141
+
142
+ ---
143
+
144
+ <div align="center">
145
+
146
+ **Built by [Imperal, Inc.](https://imperal.io) — Webbee 🐝 is its agent.**
147
+
148
+ </div>
@@ -0,0 +1,111 @@
1
+ <div align="center">
2
+
3
+ # Imperal SDK
4
+
5
+ ### Build extensions for Webbee 🐝 — the agent of Imperal Cloud, the world's first AI Cloud OS.
6
+
7
+ **Write a small Python function. Webbee calls it when a user asks for it — in their own words. Ship it to the Marketplace and get paid.**
8
+
9
+ [![PyPI](https://img.shields.io/pypi/v/imperal-sdk?color=blue&label=PyPI)](https://pypi.org/project/imperal-sdk/)
10
+ [![Python](https://img.shields.io/pypi/pyversions/imperal-sdk)](https://pypi.org/project/imperal-sdk/)
11
+ [![License](https://img.shields.io/badge/license-AGPL--3.0-blue)](LICENSE)
12
+
13
+ [Documentation](https://docs.imperal.io) · [Quickstart](https://docs.imperal.io/en/getting-started/quick-start/) · [PyPI](https://pypi.org/project/imperal-sdk/) · [imperal.io](https://imperal.io)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## What this is
20
+
21
+ **Imperal Cloud** is the world's first AI Cloud OS — a cloud you connect the contexts of your life into (mail, money, projects, servers, notes, anything) and then run entirely in your own native language. **Webbee 🐝** is the AI agent that lives inside it and does the work for you, safely.
22
+
23
+ **The Imperal SDK is how you give Webbee a new skill.** You write a small, typed Python *extension*; Webbee picks it up and calls it whenever a user asks for what it does — in plain language. The platform handles the hard parts — authentication, billing, multi-tenancy, audit, recovery, LLM routing — so your code stays small.
24
+
25
+ ```bash
26
+ pip install imperal-sdk
27
+ ```
28
+
29
+ > Python 3.11+ · AGPL-3.0-or-later
30
+
31
+ ## Why build here
32
+
33
+ - **Webbee calls your function directly.** Typed, structured calls — no LLM guessing your arguments, no silent write failures.
34
+ - **The platform does the plumbing.** Auth, per-user isolation, billing, audit, retries and recovery, multi-tenant safety — handled for you.
35
+ - **You get paid.** Publish to the Imperal Marketplace, price your extension, earn on every use.
36
+ - **Bring any LLM.** Users connect their own model keys — Anthropic, OpenAI, Google, Ollama, any OpenAI-compatible API.
37
+
38
+ ## A 60-second extension
39
+
40
+ ```python
41
+ from imperal_sdk import Extension, ChatExtension, ActionResult
42
+ from pydantic import BaseModel, Field
43
+
44
+ ext = Extension(
45
+ "hello-world",
46
+ version="1.0.0",
47
+ display_name="Hello World",
48
+ description="Greets people by name with a friendly message.",
49
+ icon="icon.svg",
50
+ actions_explicit=True,
51
+ )
52
+
53
+ chat = ChatExtension(ext, tool_name="hello_world", description="Friendly greetings.")
54
+
55
+
56
+ class GreetParams(BaseModel):
57
+ name: str = Field(..., description="Person to greet")
58
+
59
+
60
+ @chat.function("greet", description="Greet someone by name.", action_type="read")
61
+ async def greet(ctx, params: GreetParams) -> ActionResult:
62
+ return ActionResult.success(
63
+ data={"message": f"Hello, {params.name}! 🐝"},
64
+ summary=f"Greeted {params.name}",
65
+ )
66
+ ```
67
+
68
+ That's a real, working extension. When a user types *"say hi to Alex"*, Webbee calls `greet(name="Alex")`.
69
+
70
+ → Full walkthrough, from zero to published: **[docs.imperal.io](https://docs.imperal.io/en/getting-started/quick-start/)**
71
+
72
+ ## What you can build
73
+
74
+ - **Chat tools** — typed `@chat.function`s Webbee calls straight from natural language.
75
+ - **Panels** — UI surfaces rendered inside the Imperal Panel.
76
+ - **Skeletons** — live data feeds that keep Webbee aware of a user's state.
77
+ - **Scheduled jobs & webhooks** — act on a timer, or react to outside events.
78
+ - **Typed entities (SDL)** — return `sdl.Entity` objects and the platform reads their meaning (id, title, kind, …) directly instead of guessing field names. Live in production.
79
+
80
+ Every published extension passes the **federal contract** — the validators that let Webbee call your code safely. The SDK checks it locally before you ship.
81
+
82
+ ## Test without a server
83
+
84
+ ```python
85
+ from imperal_sdk.testing import MockContext
86
+
87
+ async def test_greet():
88
+ ctx = MockContext()
89
+ result = await greet(ctx, GreetParams(name="Alex"))
90
+ assert result.status == "success"
91
+ ```
92
+
93
+ ## Documentation
94
+
95
+ The full API, the manifest schema, every validator, recipes, and the federal contract live at **[docs.imperal.io](https://docs.imperal.io)** — that's the source of truth; this README is just the doorway.
96
+
97
+ | | |
98
+ |---|---|
99
+ | Documentation | [docs.imperal.io](https://docs.imperal.io) |
100
+ | Quickstart | [docs.imperal.io/en/getting-started/quick-start](https://docs.imperal.io/en/getting-started/quick-start/) |
101
+ | PyPI | [pypi.org/project/imperal-sdk](https://pypi.org/project/imperal-sdk/) |
102
+ | Changelog | [CHANGELOG.md](CHANGELOG.md) |
103
+ | License | [AGPL-3.0-or-later](LICENSE) |
104
+
105
+ ---
106
+
107
+ <div align="center">
108
+
109
+ **Built by [Imperal, Inc.](https://imperal.io) — Webbee 🐝 is its agent.**
110
+
111
+ </div>
@@ -0,0 +1,188 @@
1
+ """Imperal Cloud SDK — build extensions for the Imperal platform."""
2
+ from typing import TYPE_CHECKING
3
+
4
+ __version__ = "5.2.2"
5
+
6
+ # 5.2.2 (2026-06-11): the package root resolves its public surface lazily
7
+ # (PEP 562). The eager imports pulled the HTTP transport (Context / client
8
+ # modules -> httpx) into EVERY consumer of ANY submodule — including
9
+ # Temporal workflow code that lazily imports transport-free helpers such as
10
+ # ``imperal_sdk.chat.filters`` (httpx subclasses urllib.request.Request,
11
+ # which the workflow sandbox restricts; kernel federal
12
+ # I-SANDBOX-SAFE-LAZY-IMPORTS, live incident 2026-06-10). The public
13
+ # surface is unchanged: every name resolves to the same object, star-import
14
+ # honors __all__, and resolved names are cached back into module globals.
15
+
16
+ # name -> defining module (resolved on first attribute access)
17
+ _LAZY_ATTRS = {
18
+ # Core
19
+ "Extension": "imperal_sdk.extension",
20
+ "ToolDef": "imperal_sdk.extension",
21
+ "SignalDef": "imperal_sdk.extension",
22
+ "ScheduleDef": "imperal_sdk.extension",
23
+ "LifecycleHook": "imperal_sdk.extension",
24
+ "HealthCheckDef": "imperal_sdk.extension",
25
+ "WebhookDef": "imperal_sdk.extension",
26
+ "EventHandlerDef": "imperal_sdk.extension",
27
+ "ExposedMethod": "imperal_sdk.extension",
28
+ "TrayDef": "imperal_sdk.extension",
29
+ "Context": "imperal_sdk.context",
30
+ "ImperalAuth": "imperal_sdk.auth",
31
+ "AuthError": "imperal_sdk.auth",
32
+ "User": "imperal_sdk.types.identity",
33
+ "UserContext": "imperal_sdk.types.identity",
34
+ "Tenant": "imperal_sdk.types.identity",
35
+ "TenantContext": "imperal_sdk.types.identity",
36
+ "generate_manifest": "imperal_sdk.manifest",
37
+ "save_manifest": "imperal_sdk.manifest",
38
+ "ChatExtension": "imperal_sdk.chat",
39
+ "ActionResult": "imperal_sdk.chat.action_result",
40
+ # LLM
41
+ "get_llm_provider": "imperal_sdk.runtime.llm_provider",
42
+ "LLMProvider": "imperal_sdk.runtime.llm_provider",
43
+ "LLMConfig": "imperal_sdk.runtime.llm_provider",
44
+ "LLMUsage": "imperal_sdk.runtime.llm_provider",
45
+ "MessageAdapter": "imperal_sdk.runtime.message_adapter",
46
+ # IPC
47
+ "ExtensionsClient": "imperal_sdk.extensions.client",
48
+ "CircularCallError": "imperal_sdk.extensions.client",
49
+ # Errors
50
+ "ImperalError": "imperal_sdk.errors",
51
+ "APIError": "imperal_sdk.errors",
52
+ "NotFoundError": "imperal_sdk.errors",
53
+ "RateLimitError": "imperal_sdk.errors",
54
+ "ValidationError": "imperal_sdk.errors",
55
+ "ExtensionError": "imperal_sdk.errors",
56
+ "QuotaExceededError": "imperal_sdk.errors",
57
+ "SkeletonAccessForbidden": "imperal_sdk.errors",
58
+ # Types
59
+ "Page": "imperal_sdk.types",
60
+ "ChatResult": "imperal_sdk.types",
61
+ "FunctionCall": "imperal_sdk.types",
62
+ "Document": "imperal_sdk.types",
63
+ "CompletionResult": "imperal_sdk.types",
64
+ "LimitsResult": "imperal_sdk.types",
65
+ "SubscriptionInfo": "imperal_sdk.types",
66
+ "BalanceInfo": "imperal_sdk.types",
67
+ "FileInfo": "imperal_sdk.types",
68
+ "HTTPResponse": "imperal_sdk.types",
69
+ "Event": "imperal_sdk.types",
70
+ "WebhookRequest": "imperal_sdk.types",
71
+ "WebhookResponse": "imperal_sdk.types",
72
+ "HealthStatus": "imperal_sdk.types",
73
+ # Protocol + Validator
74
+ "ExtensionProtocol": "imperal_sdk.protocols",
75
+ "validate_extension": "imperal_sdk.validator",
76
+ "ValidationReport": "imperal_sdk.validator",
77
+ "ValidationIssue": "imperal_sdk.validator",
78
+ "validate_source_tree": "imperal_sdk.validator_v1_6_0",
79
+ "validate_manifest_v1_6_0": "imperal_sdk.validator_v1_6_0",
80
+ # Secrets (importable from the root since 5.1.0; not in __all__ —
81
+ # preserved as-is)
82
+ "SecretSpec": "imperal_sdk.secrets",
83
+ "SecretClient": "imperal_sdk.secrets",
84
+ "SecretStatus": "imperal_sdk.secrets",
85
+ "SecretNotDeclaredError": "imperal_sdk.secrets",
86
+ "SecretWriteForbidden": "imperal_sdk.secrets",
87
+ "SecretVaultUnavailable": "imperal_sdk.secrets",
88
+ "SecretValueTooLarge": "imperal_sdk.secrets",
89
+ "SecretDeclarationConflict": "imperal_sdk.secrets",
90
+ }
91
+
92
+ # Any imperal_sdk submodule also resolves as a root attribute (the eager
93
+ # imports used to expose chat/context/errors/ui/sdl/... as side effects;
94
+ # the generic fallback in __getattr__ preserves that surface).
95
+
96
+ if TYPE_CHECKING: # pragma: no cover — IDE / type-checker surface only
97
+ from imperal_sdk.extension import (
98
+ Extension, ToolDef, SignalDef, ScheduleDef,
99
+ LifecycleHook, HealthCheckDef, WebhookDef, EventHandlerDef, ExposedMethod, TrayDef,
100
+ )
101
+ from imperal_sdk.context import Context
102
+ from imperal_sdk.auth import ImperalAuth, AuthError
103
+ from imperal_sdk.types.identity import User, UserContext, Tenant, TenantContext
104
+ from imperal_sdk.manifest import generate_manifest, save_manifest
105
+ from imperal_sdk.chat import ChatExtension
106
+ from imperal_sdk.chat.action_result import ActionResult
107
+ from imperal_sdk import ui
108
+ from imperal_sdk import sdl
109
+ from imperal_sdk.runtime.llm_provider import get_llm_provider, LLMProvider, LLMConfig, LLMUsage
110
+ from imperal_sdk.runtime.message_adapter import MessageAdapter
111
+ from imperal_sdk.extensions.client import ExtensionsClient, CircularCallError
112
+ from imperal_sdk.errors import (
113
+ ImperalError, APIError, NotFoundError, RateLimitError,
114
+ ValidationError, ExtensionError, QuotaExceededError,
115
+ SkeletonAccessForbidden,
116
+ )
117
+ from imperal_sdk.types import (
118
+ Page, ChatResult, FunctionCall,
119
+ Document, CompletionResult, LimitsResult, SubscriptionInfo,
120
+ BalanceInfo, FileInfo, HTTPResponse,
121
+ Event, WebhookRequest, WebhookResponse, HealthStatus,
122
+ )
123
+ from imperal_sdk.protocols import ExtensionProtocol
124
+ from imperal_sdk.validator import validate_extension, ValidationReport, ValidationIssue
125
+ from imperal_sdk.validator_v1_6_0 import (
126
+ validate_source_tree,
127
+ validate_manifest_v1_6_0,
128
+ )
129
+ from imperal_sdk.secrets import (
130
+ SecretSpec, SecretClient, SecretStatus,
131
+ SecretNotDeclaredError, SecretWriteForbidden, SecretVaultUnavailable,
132
+ SecretValueTooLarge, SecretDeclarationConflict,
133
+ )
134
+
135
+
136
+ def __getattr__(name: str):
137
+ import importlib
138
+
139
+ src = _LAZY_ATTRS.get(name)
140
+ if src is not None:
141
+ obj = getattr(importlib.import_module(src), name)
142
+ globals()[name] = obj
143
+ return obj
144
+ if name.startswith("_"):
145
+ raise AttributeError(f"module 'imperal_sdk' has no attribute {name!r}")
146
+ try:
147
+ mod = importlib.import_module(f"imperal_sdk.{name}")
148
+ except ImportError:
149
+ raise AttributeError(
150
+ f"module 'imperal_sdk' has no attribute {name!r}"
151
+ ) from None
152
+ globals()[name] = mod
153
+ return mod
154
+
155
+
156
+ def __dir__():
157
+ return sorted(set(globals()) | set(_LAZY_ATTRS) | {"ui", "sdl"})
158
+
159
+
160
+ __all__ = [
161
+ # Core
162
+ "Extension", "ToolDef", "SignalDef", "ScheduleDef",
163
+ "LifecycleHook", "HealthCheckDef", "WebhookDef", "EventHandlerDef", "ExposedMethod", "TrayDef",
164
+ "Context", "ImperalAuth", "AuthError",
165
+ "User", "UserContext", "Tenant", "TenantContext",
166
+ "ChatExtension", "ActionResult",
167
+ "generate_manifest", "save_manifest",
168
+ # IPC
169
+ "ExtensionsClient", "CircularCallError",
170
+ # LLM
171
+ "get_llm_provider", "LLMProvider", "LLMConfig", "LLMUsage", "MessageAdapter",
172
+ # Errors
173
+ "ImperalError", "APIError", "NotFoundError", "RateLimitError",
174
+ "ValidationError", "ExtensionError", "QuotaExceededError",
175
+ "SkeletonAccessForbidden",
176
+ # Types
177
+ "Page", "ChatResult", "FunctionCall",
178
+ "Document", "CompletionResult", "LimitsResult", "SubscriptionInfo",
179
+ "BalanceInfo", "FileInfo", "HTTPResponse",
180
+ "Event", "WebhookRequest", "WebhookResponse", "HealthStatus",
181
+ # Protocol + Validator
182
+ "ExtensionProtocol", "validate_extension", "ValidationReport", "ValidationIssue",
183
+ "validate_source_tree", "validate_manifest_v1_6_0",
184
+ # UI
185
+ "ui",
186
+ # SDL — Structured Data Layer
187
+ "sdl",
188
+ ]
@@ -64,9 +64,16 @@ class FunctionDef:
64
64
 
65
65
 
66
66
  class ChatExtension:
67
- def __init__(self, ext, tool_name: str, description: str, system_prompt: str = "",
67
+ def __init__(self, ext, tool_name: str | None = None, description: str = "",
68
+ system_prompt: str = "",
68
69
  model: "str | None" = None, max_rounds: int = 10):
69
70
  self.ext = ext
71
+ # tool_name is the canonical chat-registration key: it groups the
72
+ # extension's @chat.function tools in the manifest, anchors the per-turn
73
+ # system prompt, and labels scope-guard audit lines. Optional — derived
74
+ # from the extension app_id (``tool_<app_id>_chat``) when omitted; pass
75
+ # it explicitly to pin a production-stable routing name.
76
+ tool_name = tool_name or f"tool_{ext.app_id}_chat"
70
77
  self.tool_name = tool_name
71
78
  self.description = description
72
79
  self.system_prompt = system_prompt
@@ -94,20 +101,12 @@ class ChatExtension:
94
101
  "Example: 'Notes module — manage user notes and folders.'"
95
102
  )
96
103
 
97
- # v5.0.0: orchestrator-tool auto-registration REMOVED. ChatExtension
98
- # is now purely a @chat.function bundle declaration the platform
99
- # chain executor dispatches each function directly via typed dispatch.
100
- # tool_name kwarg retained for back-compat but emits DeprecationWarning.
101
- # Will be removed in 5.1.0.
102
- import warnings as _warnings
103
- _warnings.warn(
104
- f"ChatExtension(tool_name={tool_name!r}): kwarg deprecated in SDK 5.0.0 "
105
- "(orchestrator-tool auto-registration removed). Move classifier-readable "
106
- "text into Extension(description=...) + per-@chat.function(description=...). "
107
- "Will be removed in 5.1.0.",
108
- DeprecationWarning,
109
- stacklevel=2,
110
- )
104
+ # v5.0.0 removed orchestrator-tool auto-registration: ChatExtension is
105
+ # purely a @chat.function bundle declaration, and the platform chain
106
+ # executor dispatches each function directly via typed dispatch — the
107
+ # host LLM no longer sees a single ``tool_<app_id>_chat`` umbrella tool.
108
+ # ``tool_name`` is retained as the canonical registration key (see the
109
+ # __init__ note above) — it is NOT deprecated.
111
110
  ext._chat_extensions = getattr(ext, "_chat_extensions", {})
112
111
  ext._chat_extensions[tool_name] = self
113
112
 
@@ -0,0 +1,103 @@
1
+ # -*- coding: utf-8 -*-
2
+ """5.2.2 — the package root is import-light (PEP 562 lazy surface).
3
+
4
+ Kernel federal I-SANDBOX-SAFE-LAZY-IMPORTS (live incident 2026-06-10): the
5
+ eager root imports pulled httpx (Context / client modules) into EVERY
6
+ consumer of ANY submodule — including Temporal workflow code lazily
7
+ importing transport-free helpers like ``imperal_sdk.chat.filters``
8
+ (httpx._models subclasses urllib.request.Request, restricted inside the
9
+ workflow sandbox -> RestrictedWorkflowAccessError -> whole chat turns
10
+ crashed).
11
+
12
+ Contracts:
13
+ 1. ``import imperal_sdk`` and ``import imperal_sdk.chat.filters`` must NOT
14
+ load httpx.
15
+ 2. The public surface is unchanged: every ``__all__`` name (and the
16
+ root-importable secrets names) resolves lazily to the SAME object the
17
+ defining module exports; submodules stay reachable as root attributes;
18
+ star-import works; unknown names raise AttributeError.
19
+ """
20
+ import subprocess
21
+ import sys
22
+
23
+ import imperal_sdk
24
+
25
+
26
+ def _probe(code: str) -> str:
27
+ r = subprocess.run(
28
+ [sys.executable, "-c", code],
29
+ capture_output=True, text=True, timeout=120,
30
+ )
31
+ out = (r.stdout or "").strip()
32
+ if r.returncode != 0 and not out:
33
+ out = "PROBE_ERROR: " + (r.stderr or "").strip()[-400:]
34
+ return out
35
+
36
+
37
+ def test_root_import_is_transport_free():
38
+ out = _probe(
39
+ "import imperal_sdk, sys; "
40
+ "print('HTTPX' if 'httpx' in sys.modules else 'CLEAN')"
41
+ )
42
+ assert out == "CLEAN"
43
+
44
+
45
+ def test_chat_filters_import_is_transport_free():
46
+ out = _probe(
47
+ "from imperal_sdk.chat.filters import enforce_os_identity, enforce_response_style; "
48
+ "import sys; print('HTTPX' if 'httpx' in sys.modules else 'CLEAN')"
49
+ )
50
+ assert out == "CLEAN"
51
+
52
+
53
+ def test_version():
54
+ assert imperal_sdk.__version__ == "5.2.2"
55
+
56
+
57
+ _SECRETS_NAMES = [
58
+ "SecretSpec", "SecretClient", "SecretStatus",
59
+ "SecretNotDeclaredError", "SecretWriteForbidden", "SecretVaultUnavailable",
60
+ "SecretValueTooLarge", "SecretDeclarationConflict",
61
+ ]
62
+
63
+
64
+ def test_every_public_name_resolves_to_the_defining_object():
65
+ import importlib
66
+
67
+ from imperal_sdk import _LAZY_ATTRS
68
+
69
+ for name in list(imperal_sdk.__all__) + _SECRETS_NAMES:
70
+ obj = getattr(imperal_sdk, name)
71
+ if name in ("ui", "sdl"):
72
+ assert obj is importlib.import_module(f"imperal_sdk.{name}")
73
+ continue
74
+ src = _LAZY_ATTRS[name]
75
+ assert obj is getattr(importlib.import_module(src), name), name
76
+
77
+
78
+ def test_submodules_reachable_as_root_attributes():
79
+ for sub in ("chat", "context", "errors", "types", "ui", "sdl", "manifest"):
80
+ mod = getattr(imperal_sdk, sub)
81
+ assert mod.__name__ == f"imperal_sdk.{sub}"
82
+
83
+
84
+ def test_star_import_covers_all():
85
+ ns: dict = {}
86
+ exec("from imperal_sdk import *", ns) # noqa: S102 — surface test
87
+ missing = [n for n in imperal_sdk.__all__ if n not in ns]
88
+ assert not missing, missing
89
+
90
+
91
+ def test_unknown_attribute_raises_attribute_error():
92
+ try:
93
+ imperal_sdk.definitely_not_a_real_name
94
+ except AttributeError:
95
+ pass
96
+ else:
97
+ raise AssertionError("expected AttributeError")
98
+
99
+
100
+ def test_dir_lists_the_surface():
101
+ d = dir(imperal_sdk)
102
+ for name in ("ChatExtension", "Context", "ui", "sdl", "SecretClient"):
103
+ assert name in d