imperal-sdk 4.2.2__tar.gz → 4.2.4__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 (206) hide show
  1. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/CHANGELOG.md +57 -0
  2. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/PKG-INFO +1 -1
  3. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/__init__.py +1 -1
  4. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/extension.py +35 -0
  5. imperal_sdk-4.2.4/src/imperal_sdk/secrets/panel_handler.py +133 -0
  6. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/.github/workflows/identity-contract.yml +0 -0
  7. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/.github/workflows/publish.yml +0 -0
  8. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/.github/workflows/test.yml +0 -0
  9. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/.gitignore +0 -0
  10. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/LICENSE +0 -0
  11. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/README.md +0 -0
  12. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/api_surface.json +0 -0
  13. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/pyproject.toml +0 -0
  14. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/.codebase-index-cache.pkl +0 -0
  15. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ai/__init__.py +0 -0
  16. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ai/client.py +0 -0
  17. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/auth/__init__.py +0 -0
  18. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/auth/client.py +0 -0
  19. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/auth/middleware.py +0 -0
  20. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/billing/__init__.py +0 -0
  21. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/billing/client.py +0 -0
  22. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/cache/__init__.py +0 -0
  23. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/cache/client.py +0 -0
  24. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/cache/protocol.py +0 -0
  25. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/__init__.py +0 -0
  26. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/action_result.py +0 -0
  27. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/error_codes.py +0 -0
  28. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/extension.py +0 -0
  29. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/filters.py +0 -0
  30. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/guards.py +0 -0
  31. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/handler.py +0 -0
  32. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/kernel_primitives.py +0 -0
  33. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/narration.py +0 -0
  34. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/narration_guard.py +0 -0
  35. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/prompt.py +0 -0
  36. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/refusal.py +0 -0
  37. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/chat/retry.py +0 -0
  38. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/cli/__init__.py +0 -0
  39. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/cli/main.py +0 -0
  40. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/config/__init__.py +0 -0
  41. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/config/client.py +0 -0
  42. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/context.py +0 -0
  43. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/db/__init__.py +0 -0
  44. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/db/client.py +0 -0
  45. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/errors.py +0 -0
  46. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/extensions/__init__.py +0 -0
  47. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/extensions/client.py +0 -0
  48. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/http/__init__.py +0 -0
  49. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/http/client.py +0 -0
  50. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/manifest.py +0 -0
  51. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/manifest_schema.py +0 -0
  52. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/notify/__init__.py +0 -0
  53. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/notify/client.py +0 -0
  54. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/prompts/__init__.py +0 -0
  55. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/prompts/icnli_integrity_rules.txt +0 -0
  56. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/prompts/kernel_formatting_rule.txt +0 -0
  57. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/prompts/kernel_proactivity_rule.txt +0 -0
  58. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/protocols.py +0 -0
  59. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/rpc/__init__.py +0 -0
  60. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/rpc/codec.py +0 -0
  61. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/rpc/contract.py +0 -0
  62. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/runtime/__init__.py +0 -0
  63. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/runtime/executor.py +0 -0
  64. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/runtime/llm_provider.py +0 -0
  65. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/runtime/message_adapter.py +0 -0
  66. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/action_result.schema.json +0 -0
  67. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/balance_info.schema.json +0 -0
  68. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/chat_result.schema.json +0 -0
  69. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/completion_result.schema.json +0 -0
  70. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/document.schema.json +0 -0
  71. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/event.schema.json +0 -0
  72. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/file_info.schema.json +0 -0
  73. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/function_call.schema.json +0 -0
  74. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/http_response.schema.json +0 -0
  75. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/imperal.schema.json +0 -0
  76. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/limits_result.schema.json +0 -0
  77. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/schemas/subscription_info.schema.json +0 -0
  78. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/secrets/__init__.py +0 -0
  79. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/secrets/client.py +0 -0
  80. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/secrets/exceptions.py +0 -0
  81. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/secrets/spec.py +0 -0
  82. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/security/__init__.py +0 -0
  83. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/security/call_token.py +0 -0
  84. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/skeleton/__init__.py +0 -0
  85. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/skeleton/client.py +0 -0
  86. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/storage/__init__.py +0 -0
  87. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/storage/client.py +0 -0
  88. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/store/__init__.py +0 -0
  89. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/store/client.py +0 -0
  90. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/store/exceptions.py +0 -0
  91. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/testing/__init__.py +0 -0
  92. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/testing/mock_context.py +0 -0
  93. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/testing/mock_secrets.py +0 -0
  94. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/tools/__init__.py +0 -0
  95. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/tools/client.py +0 -0
  96. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/tools/generate_api_surface.py +0 -0
  97. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/tools/validate_identity_contract.py +0 -0
  98. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/__init__.py +0 -0
  99. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/action_result.py +0 -0
  100. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/chat_result.py +0 -0
  101. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/client_contracts.py +0 -0
  102. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/contracts.py +0 -0
  103. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/contributions.py +0 -0
  104. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/events.py +0 -0
  105. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/health.py +0 -0
  106. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/identity.py +0 -0
  107. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/models.py +0 -0
  108. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/pagination.py +0 -0
  109. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/types/store_contracts.py +0 -0
  110. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/__init__.py +0 -0
  111. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/actions.py +0 -0
  112. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/base.py +0 -0
  113. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/data.py +0 -0
  114. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/display.py +0 -0
  115. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/feedback.py +0 -0
  116. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/graph.py +0 -0
  117. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/input_components.py +0 -0
  118. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/interactive.py +0 -0
  119. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/layout.py +0 -0
  120. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/ui/theme.py +0 -0
  121. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/validator.py +0 -0
  122. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/src/imperal_sdk/validator_v1_6_0.py +0 -0
  123. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/conftest.py +0 -0
  124. {imperal_sdk-4.2.2/tests/tools → imperal_sdk-4.2.4/tests/contracts}/__init__.py +0 -0
  125. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/contracts/test_store_contracts.py +0 -0
  126. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/fixtures/openapi/auth-gateway.json +0 -0
  127. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/fixtures/openapi/registry.json +0 -0
  128. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/fixtures/openapi/sharelock-cases.json +0 -0
  129. {imperal_sdk-4.2.2/tests/store → imperal_sdk-4.2.4/tests/rpc}/__init__.py +0 -0
  130. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/rpc/test_codec.py +0 -0
  131. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/rpc/test_contract.py +0 -0
  132. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/runtime/__init__.py +0 -0
  133. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/runtime/test_llm_provider_config_store.py +0 -0
  134. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/runtime/test_llm_provider_ctx_injection.py +0 -0
  135. {imperal_sdk-4.2.2/tests/rpc → imperal_sdk-4.2.4/tests/store}/__init__.py +0 -0
  136. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/store/test_list_users_client.py +0 -0
  137. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/store/test_query_all_client.py +0 -0
  138. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_action_result_typed.py +0 -0
  139. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_as_user.py +0 -0
  140. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_auth.py +0 -0
  141. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_billing.py +0 -0
  142. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_cache_client.py +0 -0
  143. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_cache_model.py +0 -0
  144. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_call_token.py +0 -0
  145. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_chat_extension_deprecation.py +0 -0
  146. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_chat_filters.py +0 -0
  147. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_chat_guards.py +0 -0
  148. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_chat_guards_bleed.py +0 -0
  149. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_chat_prompt.py +0 -0
  150. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_chat_pydantic_retry.py +0 -0
  151. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_chat_result.py +0 -0
  152. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_cli.py +0 -0
  153. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_client_contracts.py +0 -0
  154. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_config_client.py +0 -0
  155. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_context.py +0 -0
  156. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_context_guards.py +0 -0
  157. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_contracts.py +0 -0
  158. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_contracts_live.py +0 -0
  159. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_contributions.py +0 -0
  160. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_document_contract.py +0 -0
  161. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_emits_decorator.py +0 -0
  162. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_error_codes.py +0 -0
  163. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_errors.py +0 -0
  164. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_event_schema_v2.py +0 -0
  165. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_events_health.py +0 -0
  166. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_extension.py +0 -0
  167. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_extension_v2.py +0 -0
  168. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_extensions_emit.py +0 -0
  169. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_handler_p2.py +0 -0
  170. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_id_shape_guard.py +0 -0
  171. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_identity_contract.py +0 -0
  172. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_imperal_schema_v2.py +0 -0
  173. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_kernel_primitives.py +0 -0
  174. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_manifest.py +0 -0
  175. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_manifest_roundtrip_gate.py +0 -0
  176. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_manifest_schema.py +0 -0
  177. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_manifest_v2_events.py +0 -0
  178. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_manifest_v2_other_sections.py +0 -0
  179. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_manifest_v2_webhooks.py +0 -0
  180. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_manifest_validator_v2.py +0 -0
  181. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_mock_context.py +0 -0
  182. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_models.py +0 -0
  183. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_narration_emission.py +0 -0
  184. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_narration_guard.py +0 -0
  185. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_openai_max_completion_tokens.py +0 -0
  186. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_pagination.py +0 -0
  187. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_panel_rendering_contract.py +0 -0
  188. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_panels.py +0 -0
  189. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_skeleton_decorator.py +0 -0
  190. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_spec_validation.py +0 -0
  191. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_tools_client.py +0 -0
  192. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_ui.py +0 -0
  193. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_ui_fileupload_enhanced.py +0 -0
  194. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_ui_html.py +0 -0
  195. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_ui_image_enhanced.py +0 -0
  196. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_ui_open.py +0 -0
  197. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_ui_theme.py +0 -0
  198. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_user.py +0 -0
  199. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_v7_emit_refusal.py +0 -0
  200. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_validator.py +0 -0
  201. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_validator_drift.py +0 -0
  202. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_validator_pep563.py +0 -0
  203. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_validator_v1_6_0_rules.py +0 -0
  204. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/test_write_arg_bleed.py +0 -0
  205. {imperal_sdk-4.2.2/tests/contracts → imperal_sdk-4.2.4/tests/tools}/__init__.py +0 -0
  206. {imperal_sdk-4.2.2 → imperal_sdk-4.2.4}/tests/tools/test_generate_api_surface.py +0 -0
@@ -2,6 +2,63 @@
2
2
 
3
3
  All notable changes to `imperal-sdk` are documented here.
4
4
 
5
+ ## 4.2.4 — 2026-05-13
6
+
7
+ **EXT-SECRETS-V1 — unconditional synthetic Secrets panel**
8
+
9
+ In v4.2.3 the synthetic Secrets panel was registered conditionally on the
10
+ first `@ext.secret(...)` call, which meant extensions that did not declare
11
+ secrets had no menu entry — leaving end-users without a discoverable place
12
+ to manage credentials when developers later add declarations.
13
+
14
+ This release flips the registration to **unconditional**: every Extension
15
+ instance auto-registers the synthetic `secrets` panel in `__init__` (slot
16
+ `right`, title `Secrets`, icon `KeyRound`). When the manifest has zero
17
+ declared secrets, the panel renders an empty state with developer guidance
18
+ (`@ext.secret(...)` code example + link to docs). When declarations exist,
19
+ it renders one card per secret with `is_set` status + Manage button.
20
+
21
+ ### Migration notes
22
+
23
+ - **No code changes required**. Bump your ext's SDK pin to `>= 4.2.4` and
24
+ redeploy via Dev Portal — the Secrets tab appears automatically.
25
+ - Extensions that genuinely never need credentials still get the tab; this
26
+ is intentional for UX consistency. Federal V32 contract still requires
27
+ `@ext.secret` for any real credential access at runtime.
28
+
29
+ ## 4.2.3 — 2026-05-13
30
+
31
+ **EXT-SECRETS-V1 UX polish — synthetic `secrets` panel auto-injected**
32
+
33
+ When an extension declares one or more `@ext.secret(...)` entries, the SDK
34
+ now auto-registers a synthetic `secrets` panel (slot=`right`, title=`Secrets`,
35
+ icon=`KeyRound`) so the user-facing Secrets manager appears alongside the
36
+ extension's own tabs without the author writing any panel code.
37
+
38
+ ### Added
39
+
40
+ - **Auto-injected `secrets` panel**: `Extension.secret(...)` on first call
41
+ registers a built-in handler from `imperal_sdk.secrets.panel_handler`. The
42
+ handler reads declared secrets + live is_set state from `ctx.secrets.list()`
43
+ and renders `ui.Card` rows with status badges + a `Manage` button that
44
+ routes to the dedicated `/ext/{ext_id}/secrets` page.
45
+ - The synthetic panel uses **slot=`right`** defensively — most extensions use
46
+ `left` (sidebar nav) and `center` (main content); `right` is rarely-used so
47
+ the panel-sync logic in `imperal-ext-developer` won't overwrite it. If your
48
+ extension already declares a `right`-slot panel, your panel wins; users
49
+ still reach the Secrets UI via the chat-top ribbon and the direct
50
+ `/ext/{ext_id}/secrets` route.
51
+ - Panel idempotent — multiple `@ext.secret(...)` calls register the panel
52
+ only once.
53
+
54
+ ### Migration notes
55
+
56
+ - **No code changes required** to receive the synthetic panel. Bump your
57
+ ext's SDK pin to `>= 4.2.3` and redeploy via Dev Portal.
58
+ - Once your extension is on v4.2.3+, the chat-top ribbon (added in Panel for
59
+ v4.2.2 discoverability) becomes redundant for that ext — synthetic panel
60
+ appears in the `right` slot as a proper tab.
61
+
5
62
  ## 4.2.2 — 2026-05-13
6
63
 
7
64
  ### Added — EXT-SECRETS-V1 (closes ARCH-D1 in compliance-posture.md)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: imperal-sdk
3
- Version: 4.2.2
3
+ Version: 4.2.4
4
4
  Summary: SDK for building Imperal Cloud extensions
5
5
  Author: Valentin Scerbacov, Imperal, Inc.
6
6
  License-Expression: AGPL-3.0-or-later
@@ -39,7 +39,7 @@ from imperal_sdk.secrets import (
39
39
  SecretValueTooLarge, SecretDeclarationConflict,
40
40
  )
41
41
 
42
- __version__ = "4.2.2"
42
+ __version__ = "4.2.4"
43
43
 
44
44
  __all__ = [
45
45
  # Core
@@ -142,6 +142,36 @@ class Extension:
142
142
  # EXT-SECRETS-V1 (v4.2.2) — declared secrets emitted into manifest.secrets[]
143
143
  self._secrets: dict[str, "SecretSpec"] = {}
144
144
 
145
+ # EXT-SECRETS-V1 (v4.2.4) — auto-register synthetic 'secrets' panel
146
+ # unconditionally for every Extension. Empty state (no @ext.secret
147
+ # declared) renders developer guidance with code example. Federal
148
+ # contract enforced platform-side regardless of UI presence.
149
+ self._auto_register_secrets_panel()
150
+
151
+ def _auto_register_secrets_panel(self) -> None:
152
+ """Register the platform-provided 'secrets' panel.
153
+
154
+ Idempotent — only registers once per Extension instance. Slot
155
+ defaults to 'right' (least-used by typical extensions, lowest
156
+ collision risk with deploy-sync logic that keeps one panel per slot).
157
+ """
158
+ if "secrets" in self._panels:
159
+ return
160
+ try:
161
+ from imperal_sdk.secrets.panel_handler import (
162
+ builtin_secrets_panel_handler,
163
+ )
164
+ except Exception:
165
+ # If secrets package import fails, don't break Extension init.
166
+ return
167
+ self.panel(
168
+ "secrets",
169
+ slot="right",
170
+ title="Secrets",
171
+ icon="KeyRound",
172
+ refresh="manual",
173
+ )(builtin_secrets_panel_handler)
174
+
145
175
  def secret(
146
176
  self,
147
177
  name: str,
@@ -195,6 +225,11 @@ class Extension:
195
225
  )
196
226
  self._secrets[name] = spec
197
227
 
228
+ # EXT-SECRETS-V1 (v4.2.4): synthetic Secrets panel is now registered
229
+ # unconditionally in Extension.__init__ via _auto_register_secrets_panel.
230
+ # This call site is a no-op safety net for older bytecode paths.
231
+ self._auto_register_secrets_panel()
232
+
198
233
  def _decorator(target):
199
234
  return target # syntactic anchor only — decorator is a no-op wrapper
200
235
 
@@ -0,0 +1,133 @@
1
+ """Built-in handler for the synthetic ``secrets`` panel.
2
+
3
+ When an Extension declares one or more ``@ext.secret(...)`` entries, the SDK
4
+ auto-registers a panel with ``panel_id='secrets'`` so the user-facing
5
+ Secrets manager appears among the extension's other tabs (Overview /
6
+ Analytics / Transactions / ...). The extension author doesn't write any
7
+ panel code — the SDK provides this canonical handler.
8
+
9
+ Federal contract: the handler renders a summary of declared secrets +
10
+ links to the full /ext/{ext_id}/secrets page where Panel UI handles
11
+ PUT/DELETE through type=password input + cleared-on-submit state. We
12
+ do NOT inline the input form here because the canonical UI lives in
13
+ Panel React (SecretManagerCard) — duplicating it in declarative ui.*
14
+ primitives would split the federal contract (I-SECRETS-NEVER-LOGGED,
15
+ no-echo, no-clipboard) across two implementations.
16
+ """
17
+ from __future__ import annotations
18
+
19
+ from typing import Any
20
+
21
+
22
+ async def builtin_secrets_panel_handler(ctx: Any, **_params: Any) -> dict:
23
+ """Render the synthetic secrets panel.
24
+
25
+ Returns a UINode dict (post-``.to_dict()``) that the kernel relays to
26
+ Imperal Panel. The panel shows one card per declared secret with
27
+ is_set status badge and a primary action that navigates to
28
+ /ext/{ext_id}/secrets — the full SecretManagerCard route.
29
+ """
30
+ # Import inside the handler to keep SDK init light and avoid
31
+ # circular imports if ui.* itself imports anything from secrets.
32
+ from imperal_sdk import ui
33
+
34
+ ext_id = getattr(ctx, "ext_id", "") or getattr(ctx, "extension_id", "") or ""
35
+
36
+ # Pull declared secrets from ctx if the kernel populated them; fall
37
+ # back to an empty list so the panel still renders cleanly.
38
+ declared = list(getattr(ctx, "_declared_secrets", {}).values()) if getattr(
39
+ ctx, "_declared_secrets", None
40
+ ) else []
41
+
42
+ # Try to fetch live is_set state per declared name (cheap meta read).
43
+ statuses: dict[str, dict] = {}
44
+ if hasattr(ctx, "secrets") and ctx.secrets is not None:
45
+ try:
46
+ live = await ctx.secrets.list()
47
+ for s in live:
48
+ # SecretStatus or dict — handle both.
49
+ name = getattr(s, "name", None) or (s.get("name") if isinstance(s, dict) else None)
50
+ if name is None:
51
+ continue
52
+ statuses[name] = {
53
+ "is_set": bool(getattr(s, "is_set", None) if not isinstance(s, dict) else s.get("is_set", False)),
54
+ "last_accessed_at": (
55
+ getattr(s, "last_accessed_at", None)
56
+ if not isinstance(s, dict)
57
+ else s.get("last_accessed_at")
58
+ ),
59
+ }
60
+ except Exception:
61
+ statuses = {}
62
+
63
+ cards = []
64
+ for spec in declared:
65
+ name = getattr(spec, "name", None) or (spec.get("name") if isinstance(spec, dict) else None)
66
+ if not name:
67
+ continue
68
+ desc = getattr(spec, "description", "") or (spec.get("description", "") if isinstance(spec, dict) else "")
69
+ write_mode = (
70
+ getattr(spec, "write_mode", "user")
71
+ if not isinstance(spec, dict)
72
+ else spec.get("write_mode", "user")
73
+ )
74
+ status = statuses.get(name, {"is_set": False, "last_accessed_at": None})
75
+ is_set = bool(status.get("is_set"))
76
+ last_read = status.get("last_accessed_at")
77
+
78
+ # One card per secret with status + Manage button.
79
+ rows = [ui.Text(desc) if desc else None]
80
+ if is_set:
81
+ rows.append(ui.Badge("Set", color="green"))
82
+ if last_read:
83
+ rows.append(ui.Text(f"Last read: {last_read}", color="muted"))
84
+ else:
85
+ rows.append(ui.Badge("Not set", color="gray"))
86
+ if write_mode == "extension":
87
+ rows.append(ui.Text("(extension-write only — written after authorize)", color="muted"))
88
+
89
+ rows.append(ui.Button(
90
+ label="Manage" if is_set else "Set value",
91
+ variant="primary" if not is_set else "secondary",
92
+ on_click=ui.Navigate(path=f"/ext/{ext_id}/secrets#{name}"),
93
+ ))
94
+
95
+ cards.append(ui.Card(
96
+ title=name,
97
+ content=ui.Stack(children=[r for r in rows if r is not None]),
98
+ ))
99
+
100
+ if not cards:
101
+ cards.append(ui.Card(
102
+ title="No secrets declared",
103
+ content=ui.Stack(children=[
104
+ ui.Text(
105
+ "This extension does not declare any secrets. If you are "
106
+ "the developer, add an @ext.secret(...) declaration to "
107
+ "your app.py and redeploy."
108
+ ),
109
+ ui.Link(
110
+ text="Read @ext.secret reference →",
111
+ href="https://docs.imperal.io/en/sdk/decorator-secret-reference/",
112
+ ),
113
+ ]),
114
+ ))
115
+
116
+ root = ui.Stack(children=[
117
+ ui.Heading(f"Secrets · {ext_id}", level=2),
118
+ ui.Text(
119
+ "Credentials this extension needs — API keys, OAuth tokens. "
120
+ "Stored encrypted in Vault; never visible to admins or in logs."
121
+ ),
122
+ *cards,
123
+ ui.Link(
124
+ text=f"Open full Secrets manager →",
125
+ href=f"/ext/{ext_id}/secrets",
126
+ ),
127
+ ])
128
+
129
+ # Match the wrapper contract from @ext.panel decorator — return .to_dict()
130
+ # of the root. The kernel wraps {"ui": ..., "panel_id": "secrets"}.
131
+ if hasattr(root, "to_dict"):
132
+ return root.to_dict()
133
+ return root
File without changes
File without changes
File without changes
File without changes