imperal-sdk 4.2.12__tar.gz → 4.2.13__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 (210) hide show
  1. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/CHANGELOG.md +65 -18
  2. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/PKG-INFO +1 -1
  3. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/__init__.py +1 -1
  4. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/extension.py +11 -1
  5. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/handler.py +30 -1
  6. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/manifest.py +2 -0
  7. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/manifest_schema.py +6 -0
  8. imperal_sdk-4.2.13/tests/test_chat_function_background_flag.py +154 -0
  9. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/.github/workflows/identity-contract.yml +0 -0
  10. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/.github/workflows/publish.yml +0 -0
  11. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/.github/workflows/test.yml +0 -0
  12. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/.gitignore +0 -0
  13. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/LICENSE +0 -0
  14. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/README.md +0 -0
  15. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/api_surface.json +0 -0
  16. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/pyproject.toml +0 -0
  17. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/.codebase-index-cache.pkl +0 -0
  18. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ai/__init__.py +0 -0
  19. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ai/client.py +0 -0
  20. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/auth/__init__.py +0 -0
  21. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/auth/client.py +0 -0
  22. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/auth/middleware.py +0 -0
  23. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/billing/__init__.py +0 -0
  24. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/billing/client.py +0 -0
  25. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/cache/__init__.py +0 -0
  26. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/cache/client.py +0 -0
  27. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/cache/protocol.py +0 -0
  28. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/__init__.py +0 -0
  29. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/action_result.py +0 -0
  30. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/error_codes.py +0 -0
  31. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/filters.py +0 -0
  32. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/guards.py +0 -0
  33. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/kernel_primitives.py +0 -0
  34. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/narration.py +0 -0
  35. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/narration_guard.py +0 -0
  36. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/prompt.py +0 -0
  37. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/refusal.py +0 -0
  38. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/chat/retry.py +0 -0
  39. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/cli/__init__.py +0 -0
  40. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/cli/main.py +0 -0
  41. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/config/__init__.py +0 -0
  42. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/config/client.py +0 -0
  43. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/context.py +0 -0
  44. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/db/__init__.py +0 -0
  45. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/db/client.py +0 -0
  46. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/errors.py +0 -0
  47. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/extension.py +0 -0
  48. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/extensions/__init__.py +0 -0
  49. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/extensions/client.py +0 -0
  50. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/http/__init__.py +0 -0
  51. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/http/client.py +0 -0
  52. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/notify/__init__.py +0 -0
  53. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/notify/client.py +0 -0
  54. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/prompts/__init__.py +0 -0
  55. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/prompts/icnli_integrity_rules.txt +0 -0
  56. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/prompts/kernel_formatting_rule.txt +0 -0
  57. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/prompts/kernel_proactivity_rule.txt +0 -0
  58. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/protocols.py +0 -0
  59. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/rpc/__init__.py +0 -0
  60. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/rpc/codec.py +0 -0
  61. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/rpc/contract.py +0 -0
  62. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/runtime/__init__.py +0 -0
  63. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/runtime/executor.py +0 -0
  64. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/runtime/llm_provider.py +0 -0
  65. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/runtime/message_adapter.py +0 -0
  66. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/action_result.schema.json +0 -0
  67. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/balance_info.schema.json +0 -0
  68. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/chat_result.schema.json +0 -0
  69. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/completion_result.schema.json +0 -0
  70. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/document.schema.json +0 -0
  71. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/event.schema.json +0 -0
  72. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/file_info.schema.json +0 -0
  73. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/function_call.schema.json +0 -0
  74. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/http_response.schema.json +0 -0
  75. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/imperal.schema.json +0 -0
  76. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/limits_result.schema.json +0 -0
  77. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/schemas/subscription_info.schema.json +0 -0
  78. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/secrets/__init__.py +0 -0
  79. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/secrets/client.py +0 -0
  80. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/secrets/exceptions.py +0 -0
  81. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/secrets/panel_handler.py +0 -0
  82. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/secrets/spec.py +0 -0
  83. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/security/__init__.py +0 -0
  84. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/security/call_token.py +0 -0
  85. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/skeleton/__init__.py +0 -0
  86. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/skeleton/client.py +0 -0
  87. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/storage/__init__.py +0 -0
  88. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/storage/client.py +0 -0
  89. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/store/__init__.py +0 -0
  90. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/store/client.py +0 -0
  91. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/store/exceptions.py +0 -0
  92. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/testing/__init__.py +0 -0
  93. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/testing/mock_context.py +0 -0
  94. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/testing/mock_secrets.py +0 -0
  95. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/tools/__init__.py +0 -0
  96. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/tools/client.py +0 -0
  97. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/tools/generate_api_surface.py +0 -0
  98. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/tools/validate_identity_contract.py +0 -0
  99. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/__init__.py +0 -0
  100. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/action_result.py +0 -0
  101. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/chat_result.py +0 -0
  102. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/client_contracts.py +0 -0
  103. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/contracts.py +0 -0
  104. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/contributions.py +0 -0
  105. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/events.py +0 -0
  106. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/health.py +0 -0
  107. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/identity.py +0 -0
  108. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/models.py +0 -0
  109. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/pagination.py +0 -0
  110. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/types/store_contracts.py +0 -0
  111. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/__init__.py +0 -0
  112. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/actions.py +0 -0
  113. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/base.py +0 -0
  114. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/data.py +0 -0
  115. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/display.py +0 -0
  116. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/feedback.py +0 -0
  117. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/graph.py +0 -0
  118. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/input_components.py +0 -0
  119. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/interactive.py +0 -0
  120. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/layout.py +0 -0
  121. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/ui/theme.py +0 -0
  122. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/validator.py +0 -0
  123. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/src/imperal_sdk/validator_v1_6_0.py +0 -0
  124. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/conftest.py +0 -0
  125. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/contracts/__init__.py +0 -0
  126. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/contracts/test_store_contracts.py +0 -0
  127. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/fixtures/openapi/auth-gateway.json +0 -0
  128. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/fixtures/openapi/registry.json +0 -0
  129. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/fixtures/openapi/sharelock-cases.json +0 -0
  130. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/rpc/__init__.py +0 -0
  131. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/rpc/test_codec.py +0 -0
  132. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/rpc/test_contract.py +0 -0
  133. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/runtime/__init__.py +0 -0
  134. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/runtime/test_llm_provider_config_store.py +0 -0
  135. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/runtime/test_llm_provider_ctx_injection.py +0 -0
  136. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/store/__init__.py +0 -0
  137. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/store/test_list_users_client.py +0 -0
  138. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/store/test_query_all_client.py +0 -0
  139. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_action_result_typed.py +0 -0
  140. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_as_user.py +0 -0
  141. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_auth.py +0 -0
  142. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_billing.py +0 -0
  143. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_cache_client.py +0 -0
  144. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_cache_model.py +0 -0
  145. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_call_token.py +0 -0
  146. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_chat_extension_deprecation.py +0 -0
  147. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_chat_filters.py +0 -0
  148. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_chat_guards.py +0 -0
  149. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_chat_guards_bleed.py +0 -0
  150. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_chat_prompt.py +0 -0
  151. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_chat_pydantic_retry.py +0 -0
  152. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_chat_result.py +0 -0
  153. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_cli.py +0 -0
  154. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_client_contracts.py +0 -0
  155. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_config_client.py +0 -0
  156. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_context.py +0 -0
  157. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_context_background_task.py +0 -0
  158. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_context_deliver_chat_message.py +0 -0
  159. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_context_guards.py +0 -0
  160. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_contracts.py +0 -0
  161. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_contracts_live.py +0 -0
  162. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_contributions.py +0 -0
  163. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_document_contract.py +0 -0
  164. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_emits_decorator.py +0 -0
  165. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_error_codes.py +0 -0
  166. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_errors.py +0 -0
  167. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_event_schema_v2.py +0 -0
  168. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_events_health.py +0 -0
  169. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_extension.py +0 -0
  170. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_extension_v2.py +0 -0
  171. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_extensions_emit.py +0 -0
  172. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_handler_p2.py +0 -0
  173. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_http_timeout_override.py +0 -0
  174. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_id_shape_guard.py +0 -0
  175. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_identity_contract.py +0 -0
  176. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_imperal_schema_v2.py +0 -0
  177. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_kernel_primitives.py +0 -0
  178. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_manifest.py +0 -0
  179. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_manifest_roundtrip_gate.py +0 -0
  180. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_manifest_schema.py +0 -0
  181. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_manifest_v2_events.py +0 -0
  182. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_manifest_v2_other_sections.py +0 -0
  183. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_manifest_v2_webhooks.py +0 -0
  184. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_manifest_validator_v2.py +0 -0
  185. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_mock_context.py +0 -0
  186. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_models.py +0 -0
  187. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_narration_emission.py +0 -0
  188. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_narration_guard.py +0 -0
  189. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_openai_max_completion_tokens.py +0 -0
  190. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_pagination.py +0 -0
  191. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_panel_rendering_contract.py +0 -0
  192. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_panels.py +0 -0
  193. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_skeleton_decorator.py +0 -0
  194. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_spec_validation.py +0 -0
  195. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_tools_client.py +0 -0
  196. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_ui.py +0 -0
  197. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_ui_fileupload_enhanced.py +0 -0
  198. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_ui_html.py +0 -0
  199. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_ui_image_enhanced.py +0 -0
  200. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_ui_open.py +0 -0
  201. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_ui_theme.py +0 -0
  202. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_user.py +0 -0
  203. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_v7_emit_refusal.py +0 -0
  204. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_validator.py +0 -0
  205. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_validator_drift.py +0 -0
  206. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_validator_pep563.py +0 -0
  207. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_validator_v1_6_0_rules.py +0 -0
  208. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/test_write_arg_bleed.py +0 -0
  209. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/tools/__init__.py +0 -0
  210. {imperal_sdk-4.2.12 → imperal_sdk-4.2.13}/tests/tools/test_generate_api_surface.py +0 -0
@@ -2,6 +2,59 @@
2
2
 
3
3
  All notable changes to `imperal-sdk` are documented here.
4
4
 
5
+ ## 4.2.13 — 2026-05-14
6
+
7
+ **Feat: `@chat.function(background=True)` declarative flag**
8
+
9
+ Sugar over `ctx.background_task(coro, ...)` from v4.2.12 — author writes
10
+ one handler body, the SDK auto-wraps the call in `ctx.background_task()`
11
+ when the flag is set.
12
+
13
+ ### Added
14
+
15
+ - **`@chat.function(..., background=True, long_running=False)`** — when
16
+ `background=True`, the SDK chat handler wraps the function call in
17
+ `ctx.background_task()` instead of running the handler synchronously.
18
+ The LLM receives an immediate ack envelope carrying `task_id`; the
19
+ platform delivers the handler's returned `ActionResult` as a fresh
20
+ bot turn when the work finishes. `long_running=True` raises the
21
+ federal 180-second cap to 1800 seconds.
22
+
23
+ ```python
24
+ @chat.function(
25
+ "refine_output",
26
+ description="Refine the given text via AI completion.",
27
+ action_type="write",
28
+ event="text_refined",
29
+ background=True, # auto-wrap in ctx.background_task
30
+ long_running=False, # default cap 180s; True → 1800s
31
+ )
32
+ async def refine_output(ctx, params: RefineParams) -> ActionResult:
33
+ # Body runs detached. No inner _work() wrapper, no manual task_id.
34
+ await ctx.progress(50, "Generating with AI")
35
+ resp = await ctx.http.post(api_url, json={...}, timeout=120)
36
+ return ActionResult.success(
37
+ summary="Refined output ready!",
38
+ data={"text": resp.body["text"]},
39
+ )
40
+ ```
41
+
42
+ - **Manifest emission** — tools in `imperal.json` now carry `background`
43
+ and `long_running` booleans. Strict `Manifest.Tool` schema gains
44
+ matching optional fields.
45
+
46
+ ### Trade-offs vs. explicit `ctx.background_task(coro)`
47
+
48
+ - **Sugar** is best for handlers whose entire body is the long work.
49
+ - **Explicit** stays preferred when you need to return a custom
50
+ acknowledgement summary, choose `background_task()` conditionally at
51
+ runtime, or run mixed sync + background work in the same handler.
52
+
53
+ ### Migration
54
+
55
+ None required — `background` defaults to `False`. Existing
56
+ `@chat.function` handlers work unchanged.
57
+
5
58
  ## 4.2.12 — 2026-05-14
6
59
 
7
60
  **Feat: LONGRUN-V1 Session 1 — long-running operations primitives**
@@ -23,27 +76,21 @@ Three new SDK surfaces for ops that exceed the 30s `ctx.http` ceiling:
23
76
  (`LONG_RUNNING_TASK_S`). Returns task_id immediately.
24
77
 
25
78
  - **`ctx.deliver_chat_message(text, *, msg_type="response", refresh_panels=None)`**
26
- — public API for extension-initiated bot turn injection. Posts to
27
- auth-gw `/v1/internal/chat/inject`. Text truncated to 64KB with marker.
28
- `msg_type` ∈ `{response, system, tool_result}`.
79
+ — public API for extension-initiated bot turn injection. Text truncated
80
+ to 64KB with marker. `msg_type` ∈ `{response, system, tool_result}`.
29
81
 
30
82
  ### Federal invariants (new)
31
83
 
32
- - `I-LONGRUN-HTTP-CAP-180S` — per-call timeout federal cap
33
- - `I-LONGRUN-BG-CORO-RETURNS-ACTIONRESULT` — coro contract enforced
34
- kernel-side via `_explicit_background_task_completion` isinstance
35
- check; violation writes critical audit row + delivers fallback error.
36
- - `I-LONGRUN-BG-USER-SCOPED` — task bound to `(ext_id, user_id)` at
37
- creation (existing `util/task_manager.py` invariant).
38
- - `I-LONGRUN-CHAT-INJECT-USER-SCOPED` — `X-Acting-User` header must
39
- match `body.user_id` (auth-gw 403 on mismatch).
40
- - `I-LONGRUN-CHAT-INJECT-AUDIT-EVERY` — every inject writes an
41
- `action_ledger` row through the `write_audit` chokepoint.
42
-
43
- ### Spec
44
-
45
- `superpowers/specs/2026-05-13-longrun-v1-design.md`. Sessions 2 (Sharelock
46
- canary migration) and 3 (docs + observability) ship after 24h soak.
84
+ - `I-LONGRUN-HTTP-CAP-180S` — per-call timeout federal cap.
85
+ - `I-LONGRUN-BG-CORO-RETURNS-ACTIONRESULT` — the coroutine MUST return
86
+ `ActionResult`; non-ActionResult return triggers a critical audit row
87
+ and delivers a fallback error to chat.
88
+ - `I-LONGRUN-BG-USER-SCOPED` — every background task is bound to
89
+ `(ext_id, user_id)` at creation; cross-user cancel/status returns 403.
90
+ - `I-LONGRUN-CHAT-INJECT-USER-SCOPED` — chat inject scoped to
91
+ `(ext_id, user_id)`; cross-user inject returns 403.
92
+ - `I-LONGRUN-CHAT-INJECT-AUDIT-EVERY` — every chat inject writes an
93
+ audit row.
47
94
 
48
95
  ### Migration
49
96
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: imperal-sdk
3
- Version: 4.2.12
3
+ Version: 4.2.13
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.12"
42
+ __version__ = "4.2.13"
43
43
 
44
44
  __all__ = [
45
45
  # Core
@@ -58,6 +58,12 @@ class FunctionDef:
58
58
  chain_callable: bool = True # federal v4.0.0 — kernel uses typed dispatch
59
59
  effects: list[str] = field(default_factory=list) # ["create:note", "delete:folder", ...]
60
60
  id_projection: str = "" # federal v4.1.2 — params field carrying resolved target id
61
+ # LONGRUN-V1 Component D (v4.2.13+) — declarative sugar over ctx.background_task.
62
+ # When background=True, the SDK chat handler auto-wraps the function call in
63
+ # ctx.background_task(); the LLM sees an immediate ack with task_id and the
64
+ # platform delivers the handler's ActionResult as a fresh bot turn when done.
65
+ background: bool = False
66
+ long_running: bool = False
61
67
  _pydantic_model: type | None = None # auto-detected Pydantic BaseModel class
62
68
  _pydantic_param: str = "" # parameter name that receives the model instance
63
69
  _return_model: type | None = None # auto-detected return Pydantic model
@@ -115,7 +121,9 @@ class ChatExtension:
115
121
  event_schema: type | None = None,
116
122
  chain_callable: bool | None = None,
117
123
  effects: list[str] | None = None,
118
- id_projection: str | None = None):
124
+ id_projection: str | None = None,
125
+ background: bool = False,
126
+ long_running: bool = False):
119
127
  """Register a chat function (federal v4.0.0 contract).
120
128
 
121
129
  Args:
@@ -218,6 +226,8 @@ class ChatExtension:
218
226
  chain_callable=chain_callable,
219
227
  effects=list(effects or []),
220
228
  id_projection=id_projection or "",
229
+ background=background,
230
+ long_running=long_running,
221
231
  _pydantic_model=_detected_model, _pydantic_param=_detected_param,
222
232
  _return_model=_detected_return_model,
223
233
  )
@@ -236,7 +236,36 @@ async def _execute_function(
236
236
 
237
237
  while True:
238
238
  try:
239
- if _func_def._pydantic_model and _func_def._pydantic_param:
239
+ # LONGRUN-V1 Component D (v4.2.13+) declarative background-task sugar.
240
+ # When the handler is decorated with @chat.function(background=True),
241
+ # the SDK auto-wraps the call in ctx.background_task() and returns an
242
+ # immediate ack envelope to the LLM. The actual handler runs detached;
243
+ # the platform delivers its returned ActionResult as a fresh bot turn.
244
+ if getattr(_func_def, "background", False):
245
+ _bg_pydantic_model = _func_def._pydantic_model
246
+ _bg_pydantic_param = _func_def._pydantic_param
247
+ _bg_input = current_tu.input or {}
248
+ _bg_fn = _func_def.func
249
+
250
+ async def _bg_coro():
251
+ if _bg_pydantic_model and _bg_pydantic_param:
252
+ _mi = _bg_pydantic_model(**_bg_input)
253
+ return await _bg_fn(ctx, **{_bg_pydantic_param: _mi})
254
+ return await _bg_fn(ctx, **_bg_input)
255
+
256
+ _bg_task_id = await ctx.background_task(
257
+ _bg_coro(),
258
+ long_running=bool(getattr(_func_def, "long_running", False)),
259
+ name=current_tu.name,
260
+ )
261
+ result = ActionResult.success(
262
+ summary=(
263
+ f"Started '{current_tu.name}' in background — "
264
+ "the result will be sent to chat when it finishes."
265
+ ),
266
+ data={"task_id": _bg_task_id, "background": True},
267
+ )
268
+ elif _func_def._pydantic_model and _func_def._pydantic_param:
240
269
  _model_instance = _func_def._pydantic_model(**(current_tu.input or {}))
241
270
  result = await _func_def.func(ctx, **{_func_def._pydantic_param: _model_instance})
242
271
  else:
@@ -102,6 +102,8 @@ def generate_manifest(ext: Extension) -> dict:
102
102
  "params_schema": params_schema,
103
103
  "return_schema": return_schema,
104
104
  "event": fn_def.event or "",
105
+ "background": bool(getattr(fn_def, "background", False)),
106
+ "long_running": bool(getattr(fn_def, "long_running", False)),
105
107
  "scopes": [],
106
108
  "owner_chat_tool": chat_tool_name,
107
109
  })
@@ -102,6 +102,12 @@ class Tool(BaseModel):
102
102
  effects: List[str] = Field(default_factory=list)
103
103
  params_schema: Optional[Dict[str, Any]] = None
104
104
  return_schema: Optional[Dict[str, Any]] = None
105
+ # LONGRUN-V1 Component D (v4.2.13+) — declarative background-task sugar.
106
+ # When background=True, the SDK chat handler auto-wraps invocations of
107
+ # this tool in ctx.background_task(). long_running=True raises the
108
+ # federal 180s cap to 1800s.
109
+ background: Optional[bool] = None
110
+ long_running: Optional[bool] = None
105
111
  event: Optional[str] = None
106
112
  owner_chat_tool: Optional[str] = None
107
113
  synthetic: Optional[bool] = None
@@ -0,0 +1,154 @@
1
+ """Component D — @chat.function(background=True, long_running=True) decorator flag.
2
+
3
+ Sugar over ctx.background_task(coro) — the kernel auto-wraps the handler call
4
+ in ctx.background_task() under the hood; author writes one handler body, no
5
+ explicit inner coro wrapper.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import pytest
10
+ from pydantic import BaseModel
11
+
12
+ from imperal_sdk import ActionResult, Extension
13
+ from imperal_sdk.chat import ChatExtension
14
+
15
+
16
+ class _RefineParams(BaseModel):
17
+ text: str
18
+
19
+
20
+ def test_decorator_accepts_background_and_long_running_kwargs():
21
+ ext = Extension("ext-bg-test", display_name="Bg Test",
22
+ description="Background flag smoke test extension.",
23
+ actions_explicit=True)
24
+ chat = ChatExtension(ext, tool_name="ext_bg_test_chat",
25
+ description="bg test")
26
+
27
+ @chat.function(
28
+ "refine_output",
29
+ "Refine some text",
30
+ action_type="write",
31
+ event="refined",
32
+ background=True,
33
+ long_running=True,
34
+ )
35
+ async def refine_output(ctx, params: _RefineParams) -> ActionResult:
36
+ return ActionResult.success(data={"out": params.text.upper()})
37
+
38
+ fn = chat.functions["refine_output"]
39
+ assert fn.background is True
40
+ assert fn.long_running is True
41
+
42
+
43
+ def test_decorator_defaults_background_false():
44
+ ext = Extension("ext-bg-default", display_name="Bg Default",
45
+ description="Background flag default-False smoke test.",
46
+ actions_explicit=True)
47
+ chat = ChatExtension(ext, tool_name="ext_bg_default_chat",
48
+ description="default")
49
+
50
+ @chat.function("plain", "Plain handler", action_type="read")
51
+ async def plain(ctx, params: _RefineParams) -> ActionResult:
52
+ return ActionResult.success(data={"echo": params.text})
53
+
54
+ fn = chat.functions["plain"]
55
+ assert fn.background is False
56
+ assert fn.long_running is False
57
+
58
+
59
+ def test_manifest_emits_background_and_long_running():
60
+ """Tool entry in imperal.json carries the new fields."""
61
+ from imperal_sdk.manifest import generate_manifest
62
+
63
+ ext = Extension("ext-bg-manifest", display_name="Bg Manifest",
64
+ description="Background flag manifest emission test.",
65
+ actions_explicit=True)
66
+ chat = ChatExtension(ext, tool_name="ext_bg_manifest_chat",
67
+ description="manifest")
68
+
69
+ @chat.function(
70
+ "do_long_work",
71
+ "Do long work",
72
+ action_type="write",
73
+ event="work_done",
74
+ background=True,
75
+ long_running=True,
76
+ )
77
+ async def do_long_work(ctx, params: _RefineParams) -> ActionResult:
78
+ return ActionResult.success()
79
+
80
+ manifest = generate_manifest(ext)
81
+ tool_entry = next(t for t in manifest["tools"] if t["name"] == "do_long_work")
82
+ assert tool_entry["background"] is True
83
+ assert tool_entry["long_running"] is True
84
+
85
+
86
+ @pytest.mark.asyncio
87
+ async def test_handler_wraps_in_background_task_when_flag_set():
88
+ """When background=True, the SDK handler MUST call ctx.background_task
89
+ instead of running the handler synchronously. The tool result returned
90
+ to the LLM should be an ack with task_id, not the handler's return value.
91
+ """
92
+ from imperal_sdk.chat.handler import _execute_function
93
+ from imperal_sdk.context import Context
94
+ from imperal_sdk.types.identity import UserContext
95
+
96
+ # Counter to verify spawn hook was called, not the handler synchronously.
97
+ spawn_calls: list = []
98
+
99
+ async def _spawn_hook(coro, *, long_running, name):
100
+ spawn_calls.append({"long_running": long_running, "name": name})
101
+ coro.close()
102
+ return "task_bg_abc"
103
+
104
+ ext = Extension("ext-bg-runtime", display_name="Bg Runtime",
105
+ description="Background runtime wrap smoke test.",
106
+ actions_explicit=True)
107
+ chat = ChatExtension(ext, tool_name="ext_bg_runtime_chat",
108
+ description="runtime")
109
+
110
+ handler_ran = []
111
+
112
+ @chat.function(
113
+ "long_refine",
114
+ "Refine text long-running",
115
+ action_type="write",
116
+ event="refined_long",
117
+ background=True,
118
+ long_running=True,
119
+ )
120
+ async def long_refine(ctx, params: _RefineParams) -> ActionResult:
121
+ handler_ran.append(True)
122
+ return ActionResult.success(data={"result": params.text.upper()})
123
+
124
+ ctx = Context(user=UserContext(
125
+ imperal_id="imp_u_t", email="t@t.com", tenant_id="t", role="user",
126
+ ))
127
+ ctx._background_task_spawn = _spawn_hook # type: ignore[attr-defined]
128
+
129
+ # Simulate one tool call from the LLM
130
+ from types import SimpleNamespace
131
+ tu = SimpleNamespace(name="long_refine", input={"text": "hello"})
132
+
133
+ cfg = {
134
+ "max_result_tokens": 4096,
135
+ "list_truncate_items": 50,
136
+ "string_truncate_chars": 200,
137
+ }
138
+ chat._functions_called = []
139
+ result_str = await _execute_function(
140
+ chat_ext=chat, ctx=ctx, tu=tu,
141
+ action_type="write", cfg=cfg, retry_ctx=None,
142
+ )
143
+
144
+ # Spawn hook was called → handler is detached
145
+ assert len(spawn_calls) == 1
146
+ assert spawn_calls[0]["long_running"] is True
147
+ assert spawn_calls[0]["name"] == "long_refine"
148
+ # Handler body did NOT run synchronously (the coro was closed by spawn hook)
149
+ assert handler_ran == []
150
+ # Tool result returned to LLM is the background-ack envelope
151
+ import json as _j
152
+ res = _j.loads(result_str)
153
+ assert res.get("status") == "success"
154
+ assert "task_id" in (res.get("data") or {})
File without changes
File without changes
File without changes