imperal-sdk 6.0.2__tar.gz → 6.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (453) hide show
  1. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/CHANGELOG.md +8 -0
  2. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/PKG-INFO +10 -1
  3. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/pyproject.toml +12 -0
  4. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/sdk-reference.json +1 -1
  5. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/sdk_claims.json +1 -1
  6. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/__init__.py +1 -1
  7. imperal_sdk-6.1.0/src/imperal_sdk/code_index.py +429 -0
  8. imperal_sdk-6.1.0/tests/test_code_index_contracts.py +82 -0
  9. imperal_sdk-6.1.0/tests/test_code_index_indexer.py +53 -0
  10. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/.cm.txt +0 -0
  11. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/.github/workflows/identity-contract.yml +0 -0
  12. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/.github/workflows/publish.yml +0 -0
  13. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/.github/workflows/test.yml +0 -0
  14. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/.gitignore +0 -0
  15. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/LICENSE +0 -0
  16. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/README.md +0 -0
  17. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/docs/sdl-facets.md +0 -0
  18. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/sdl_roles.json +0 -0
  19. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/.codebase-index-cache.pkl +0 -0
  20. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/_gateway.py +0 -0
  21. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/_http_retry.py +0 -0
  22. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/_shared_http.py +0 -0
  23. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/adversarial_oracle.py +0 -0
  24. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ai/__init__.py +0 -0
  25. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ai/client.py +0 -0
  26. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/app.py +0 -0
  27. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/apps/__init__.py +0 -0
  28. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/apps/client.py +0 -0
  29. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/auth/__init__.py +0 -0
  30. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/auth/client.py +0 -0
  31. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/auth/middleware.py +0 -0
  32. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/auto_ui.py +0 -0
  33. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/billing/__init__.py +0 -0
  34. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/billing/client.py +0 -0
  35. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/bom_extractor.py +0 -0
  36. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/cache/__init__.py +0 -0
  37. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/cache/client.py +0 -0
  38. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/cache/protocol.py +0 -0
  39. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/catalog.py +0 -0
  40. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/__init__.py +0 -0
  41. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/action_result.py +0 -0
  42. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/error_codes.py +0 -0
  43. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/exceptions.py +0 -0
  44. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/extension.py +0 -0
  45. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/filters.py +0 -0
  46. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/guards.py +0 -0
  47. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/kernel_primitives.py +0 -0
  48. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/narration.py +0 -0
  49. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/narration_guard.py +0 -0
  50. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/prompt.py +0 -0
  51. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/chat/refusal.py +0 -0
  52. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/cli/__init__.py +0 -0
  53. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/cli/linter.py +0 -0
  54. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/cli/main.py +0 -0
  55. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/config/__init__.py +0 -0
  56. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/config/client.py +0 -0
  57. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/context.py +0 -0
  58. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/conversations/__init__.py +0 -0
  59. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/conversations/client.py +0 -0
  60. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/core.py +0 -0
  61. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/cross_surface_bus.py +0 -0
  62. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/__init__.py +0 -0
  63. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/contract_checks.py +0 -0
  64. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/generate_api_surface.py +0 -0
  65. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/generate_reference.py +0 -0
  66. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/generate_sdk_claims.py +0 -0
  67. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/reference/__init__.py +0 -0
  68. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/reference/_flags.py +0 -0
  69. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/reference/_introspect.py +0 -0
  70. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/reference/client_methods.py +0 -0
  71. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/reference/dataclasses_kind.py +0 -0
  72. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/reference/decorators.py +0 -0
  73. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/reference/sdl_funcs.py +0 -0
  74. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/reference/sdl_roles.py +0 -0
  75. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/reference/ui_components.py +0 -0
  76. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/devtools/validate_identity_contract.py +0 -0
  77. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/errors.py +0 -0
  78. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/extension.py +0 -0
  79. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/extensions/__init__.py +0 -0
  80. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/extensions/client.py +0 -0
  81. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/gnc_guard.py +0 -0
  82. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/http/__init__.py +0 -0
  83. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/http/client.py +0 -0
  84. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/__init__.py +0 -0
  85. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/_impl.py +0 -0
  86. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/actions.py +0 -0
  87. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/custom_roles.py +0 -0
  88. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/migrate.py +0 -0
  89. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/produce.py +0 -0
  90. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/schema.py +0 -0
  91. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/skeleton.py +0 -0
  92. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/ui.py +0 -0
  93. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/ui_children.py +0 -0
  94. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/ui_template.py +0 -0
  95. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ir/validator.py +0 -0
  96. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/manifest.py +0 -0
  97. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/manifest_schema.py +0 -0
  98. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/manifest_schema_ui.py +0 -0
  99. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/notify/__init__.py +0 -0
  100. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/notify/client.py +0 -0
  101. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/oauth_state.py +0 -0
  102. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/oauth_tokens.py +0 -0
  103. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/pipes.py +0 -0
  104. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/prompts/__init__.py +0 -0
  105. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/prompts/icnli_integrity_rules.txt +0 -0
  106. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/prompts/kernel_formatting_rule.txt +0 -0
  107. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/prompts/kernel_proactivity_rule.txt +0 -0
  108. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/protocols.py +0 -0
  109. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/rbac/__init__.py +0 -0
  110. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/rbac/client.py +0 -0
  111. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/rpc/__init__.py +0 -0
  112. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/rpc/codec.py +0 -0
  113. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/rpc/contract.py +0 -0
  114. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/__init__.py +0 -0
  115. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/_platform.py +0 -0
  116. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/canon.py +0 -0
  117. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/engine.py +0 -0
  118. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/executor.py +0 -0
  119. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/hosted_client.py +0 -0
  120. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/interpreter.py +0 -0
  121. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/llm_provider.py +0 -0
  122. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/local_engine.py +0 -0
  123. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/message_adapter.py +0 -0
  124. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/template.py +0 -0
  125. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/runtime/verbs.py +0 -0
  126. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schema/marathon_ram.sql +0 -0
  127. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/action_result.schema.json +0 -0
  128. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/__init__.py +0 -0
  129. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/ai_complete.json +0 -0
  130. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/call.json +0 -0
  131. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/conditional.json +0 -0
  132. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/navigate.json +0 -0
  133. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/open.json +0 -0
  134. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/send.json +0 -0
  135. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/store_create.json +0 -0
  136. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/store_delete.json +0 -0
  137. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/store_get.json +0 -0
  138. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/store_list.json +0 -0
  139. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/actions/store_update.json +0 -0
  140. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/balance_info.schema.json +0 -0
  141. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/chat_result.schema.json +0 -0
  142. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/completion_result.schema.json +0 -0
  143. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/document.schema.json +0 -0
  144. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/event.schema.json +0 -0
  145. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/file_info.schema.json +0 -0
  146. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/function_call.schema.json +0 -0
  147. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/http_response.schema.json +0 -0
  148. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/imperal.schema.json +0 -0
  149. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/ir.schema.json +0 -0
  150. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/limits_result.schema.json +0 -0
  151. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/metered_event.schema.json +0 -0
  152. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/subscription_info.schema.json +0 -0
  153. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/ui_children/__init__.py +0 -0
  154. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/ui_children/accordion.json +0 -0
  155. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/ui_children/datatable_columns.json +0 -0
  156. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/ui_children/datatable_rows.json +0 -0
  157. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/ui_children/menu.json +0 -0
  158. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/ui_children/select.json +0 -0
  159. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/ui_children/tabs.json +0 -0
  160. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/ui_children/timeline.json +0 -0
  161. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/schemas/ui_children/tree.json +0 -0
  162. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/__init__.py +0 -0
  163. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/_generate_roles_json.py +0 -0
  164. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/entity.py +0 -0
  165. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facet_resolve.py +0 -0
  166. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/__init__.py +0 -0
  167. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/catalog.py +0 -0
  168. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/comm.py +0 -0
  169. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/content.py +0 -0
  170. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/device.py +0 -0
  171. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/event.py +0 -0
  172. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/geo.py +0 -0
  173. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/identity.py +0 -0
  174. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/media.py +0 -0
  175. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/metric.py +0 -0
  176. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/money.py +0 -0
  177. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/net.py +0 -0
  178. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/people.py +0 -0
  179. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/quantity.py +0 -0
  180. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/rating.py +0 -0
  181. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/security.py +0 -0
  182. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/task.py +0 -0
  183. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/facets/time.py +0 -0
  184. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/field.py +0 -0
  185. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/sdl/roles.py +0 -0
  186. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/search.py +0 -0
  187. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/secrets/__init__.py +0 -0
  188. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/secrets/client.py +0 -0
  189. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/secrets/exceptions.py +0 -0
  190. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/secrets/panel_handler.py +0 -0
  191. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/secrets/spec.py +0 -0
  192. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/security/__init__.py +0 -0
  193. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/security/call_token.py +0 -0
  194. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/security/deactivation_guard.py +0 -0
  195. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/signals/__init__.py +0 -0
  196. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/signals/client.py +0 -0
  197. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/skeleton/__init__.py +0 -0
  198. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/skeleton/client.py +0 -0
  199. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/storage/__init__.py +0 -0
  200. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/storage/client.py +0 -0
  201. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/store/__init__.py +0 -0
  202. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/store/client.py +0 -0
  203. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/store/exceptions.py +0 -0
  204. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/testing/__init__.py +0 -0
  205. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/testing/autonomous_mock.py +0 -0
  206. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/testing/mock_context.py +0 -0
  207. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/testing/mock_secrets.py +0 -0
  208. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/transport.py +0 -0
  209. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/typed_context.py +0 -0
  210. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/__init__.py +0 -0
  211. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/action_result.py +0 -0
  212. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/chat_result.py +0 -0
  213. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/client_contracts.py +0 -0
  214. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/contracts.py +0 -0
  215. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/contributions.py +0 -0
  216. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/events.py +0 -0
  217. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/health.py +0 -0
  218. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/identity.py +0 -0
  219. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/metered_event.py +0 -0
  220. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/models.py +0 -0
  221. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/pagination.py +0 -0
  222. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/types/store_contracts.py +0 -0
  223. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/__init__.py +0 -0
  224. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/actions.py +0 -0
  225. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/base.py +0 -0
  226. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/canvas.py +0 -0
  227. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/data.py +0 -0
  228. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/display.py +0 -0
  229. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/feedback.py +0 -0
  230. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/graph.py +0 -0
  231. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/input_components.py +0 -0
  232. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/interactive.py +0 -0
  233. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/layout.py +0 -0
  234. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/liquid.py +0 -0
  235. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/signals.py +0 -0
  236. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/stage.py +0 -0
  237. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/ui/theme.py +0 -0
  238. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/users/__init__.py +0 -0
  239. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/users/client.py +0 -0
  240. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/validator.py +0 -0
  241. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/validator_v1_6_0.py +0 -0
  242. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/src/imperal_sdk/vault_ram_client.py +0 -0
  243. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/conftest.py +0 -0
  244. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/__init__.py +0 -0
  245. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_action_schemas.py +0 -0
  246. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_artifacts_freshness.py +0 -0
  247. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_contract_checks_selftest.py +0 -0
  248. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_generate_sdk_claims.py +0 -0
  249. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_identity_nonempty.py +0 -0
  250. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_ir_schema_fresh.py +0 -0
  251. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_meter_lua_contract.py +0 -0
  252. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_metered_event_contract.py +0 -0
  253. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_notify_wire_payload.py +0 -0
  254. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_public_docstrings_engine_neutral.py +0 -0
  255. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_reference_completeness.py +0 -0
  256. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_reference_no_leak.py +0 -0
  257. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_sample_contract_shape.py +0 -0
  258. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contract/test_sdk_matches_kernel_contract.py +0 -0
  259. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contracts/__init__.py +0 -0
  260. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/contracts/test_store_contracts.py +0 -0
  261. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/fixtures/contract/kernel-contract.sample.json +0 -0
  262. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/fixtures/ir/README.md +0 -0
  263. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/fixtures/ir/archive_ended.ir.json +0 -0
  264. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/fixtures/ir/link_saver.ir.json +0 -0
  265. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/fixtures/ir/test_fixtures_valid.py +0 -0
  266. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/fixtures/openapi/auth-gateway.json +0 -0
  267. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/fixtures/openapi/registry.json +0 -0
  268. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/fixtures/openapi/sharelock-cases.json +0 -0
  269. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/__init__.py +0 -0
  270. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_custom_roles.py +0 -0
  271. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ir_impl.py +0 -0
  272. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ir_mapping_real_ext.py +0 -0
  273. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ir_migrate.py +0 -0
  274. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ir_produce.py +0 -0
  275. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ir_schema.py +0 -0
  276. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ir_skeleton.py +0 -0
  277. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ir_ui.py +0 -0
  278. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ir_ui_produce.py +0 -0
  279. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ir_validator.py +0 -0
  280. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ir_versions.py +0 -0
  281. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ui_children.py +0 -0
  282. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ir/test_ui_template.py +0 -0
  283. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/rpc/__init__.py +0 -0
  284. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/rpc/test_boundary_seal.py +0 -0
  285. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/rpc/test_codec.py +0 -0
  286. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/rpc/test_contract.py +0 -0
  287. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/__init__.py +0 -0
  288. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_canon.py +0 -0
  289. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_canon_template.py +0 -0
  290. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_engine_abc.py +0 -0
  291. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_engine_parity.py +0 -0
  292. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_executor_neutral.py +0 -0
  293. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_hosted_client.py +0 -0
  294. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_interpreter.py +0 -0
  295. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_llm_provider_config_store.py +0 -0
  296. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_llm_provider_ctx_injection.py +0 -0
  297. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_local_engine.py +0 -0
  298. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_platform_shim.py +0 -0
  299. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_template.py +0 -0
  300. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_verb_ai.py +0 -0
  301. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_verb_call_directives.py +0 -0
  302. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_verb_conditional.py +0 -0
  303. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/runtime/test_verb_store.py +0 -0
  304. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/store/__init__.py +0 -0
  305. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/store/test_list_users_client.py +0 -0
  306. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/store/test_query_all_client.py +0 -0
  307. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_action_result_time_travel.py +0 -0
  308. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_action_result_typed.py +0 -0
  309. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_agent_presence.py +0 -0
  310. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_as_user.py +0 -0
  311. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_auth.py +0 -0
  312. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_autonomous_mock.py +0 -0
  313. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_billing.py +0 -0
  314. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_cache_client.py +0 -0
  315. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_cache_model.py +0 -0
  316. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_call_token.py +0 -0
  317. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_callable_surface_single_source.py +0 -0
  318. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_chat_extension_deprecation.py +0 -0
  319. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_chat_extension_no_llm_router.py +0 -0
  320. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_chat_filters.py +0 -0
  321. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_chat_function_background_flag.py +0 -0
  322. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_chat_guards.py +0 -0
  323. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_chat_guards_bleed.py +0 -0
  324. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_chat_prompt.py +0 -0
  325. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_chat_result.py +0 -0
  326. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_cli.py +0 -0
  327. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_cli_sdk_commands.py +0 -0
  328. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_client_contracts.py +0 -0
  329. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_client_emit_neutral.py +0 -0
  330. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_config_client.py +0 -0
  331. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_context.py +0 -0
  332. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_context_background_task.py +0 -0
  333. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_context_deliver_chat_message.py +0 -0
  334. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_context_guards.py +0 -0
  335. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_contracts.py +0 -0
  336. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_contracts_live.py +0 -0
  337. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_contributions.py +0 -0
  338. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_core_primitives.py +0 -0
  339. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_data_model_kwarg.py +0 -0
  340. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_document_contract.py +0 -0
  341. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_emits_decorator.py +0 -0
  342. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_error_codes.py +0 -0
  343. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_errors.py +0 -0
  344. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_event_schema_v2.py +0 -0
  345. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_events_health.py +0 -0
  346. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_extension.py +0 -0
  347. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_extension_pipes.py +0 -0
  348. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_extension_v2.py +0 -0
  349. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_extensions_emit.py +0 -0
  350. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_gateway_namespaces.py +0 -0
  351. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_http_json_and_mock.py +0 -0
  352. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_http_retry.py +0 -0
  353. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_http_timeout_override.py +0 -0
  354. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_id_shape_guard.py +0 -0
  355. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_identity_contract.py +0 -0
  356. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_imperal_schema_v2.py +0 -0
  357. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_import_light.py +0 -0
  358. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_init_onboarding.py +0 -0
  359. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_kernel_primitives.py +0 -0
  360. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_liquid_ui.py +0 -0
  361. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest.py +0 -0
  362. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_file_sinks.py +0 -0
  363. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_linter.py +0 -0
  364. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_no_orchestrator_tool.py +0 -0
  365. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_oauth.py +0 -0
  366. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_panels.py +0 -0
  367. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_roundtrip_gate.py +0 -0
  368. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_schema.py +0 -0
  369. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_v2_events.py +0 -0
  370. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_v2_other_sections.py +0 -0
  371. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_v2_webhooks.py +0 -0
  372. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_manifest_validator_v2.py +0 -0
  373. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_mock_context.py +0 -0
  374. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_models.py +0 -0
  375. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_narration_emission.py +0 -0
  376. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_narration_guard.py +0 -0
  377. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_oauth_authorize_url.py +0 -0
  378. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_oauth_tokens_shared.py +0 -0
  379. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_openai_max_completion_tokens.py +0 -0
  380. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_pagination.py +0 -0
  381. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_panel_rendering_contract.py +0 -0
  382. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_panel_swr_caching.py +0 -0
  383. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_panels.py +0 -0
  384. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_phase_a_dead_removal.py +0 -0
  385. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_phase_a_drift.py +0 -0
  386. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_phase_a_text.py +0 -0
  387. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_quantum_app.py +0 -0
  388. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdk_version_stamp.py +0 -0
  389. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_entity.py +0 -0
  390. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_entity_marker.py +0 -0
  391. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_exports.py +0 -0
  392. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_catalog.py +0 -0
  393. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_collisions.py +0 -0
  394. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_comm.py +0 -0
  395. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_content.py +0 -0
  396. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_device.py +0 -0
  397. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_event.py +0 -0
  398. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_exports.py +0 -0
  399. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_field.py +0 -0
  400. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_geo.py +0 -0
  401. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_identity.py +0 -0
  402. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_media.py +0 -0
  403. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_metric.py +0 -0
  404. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_money.py +0 -0
  405. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_net.py +0 -0
  406. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_people.py +0 -0
  407. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_quantity.py +0 -0
  408. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_rating.py +0 -0
  409. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_resolve.py +0 -0
  410. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_security.py +0 -0
  411. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_task.py +0 -0
  412. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facet_time.py +0 -0
  413. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facets_catalog.py +0 -0
  414. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facets_doc.py +0 -0
  415. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_facets_pkg.py +0 -0
  416. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_field.py +0 -0
  417. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_roles.py +0 -0
  418. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_roles_json.py +0 -0
  419. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_roles_of_facets.py +0 -0
  420. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sdl_vocab_version.py +0 -0
  421. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_search_provider.py +0 -0
  422. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_secret_scope_decorator.py +0 -0
  423. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_secret_spec_scope.py +0 -0
  424. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_skeleton_decorator.py +0 -0
  425. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_spec_validation.py +0 -0
  426. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_stage.py +0 -0
  427. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_surface_adaptation.py +0 -0
  428. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_sync_async_parity.py +0 -0
  429. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_transport_isolation.py +0 -0
  430. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_ui.py +0 -0
  431. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_ui_canvas.py +0 -0
  432. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_ui_fileupload_enhanced.py +0 -0
  433. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_ui_html.py +0 -0
  434. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_ui_image_enhanced.py +0 -0
  435. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_ui_modal.py +0 -0
  436. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_ui_open.py +0 -0
  437. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_ui_signals.py +0 -0
  438. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_ui_theme.py +0 -0
  439. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_user.py +0 -0
  440. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_v7_emit_refusal.py +0 -0
  441. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_validator.py +0 -0
  442. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_validator_drift.py +0 -0
  443. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_validator_pep563.py +0 -0
  444. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_validator_v1_6_0_rules.py +0 -0
  445. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_validator_v25.py +0 -0
  446. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/test_write_arg_bleed.py +0 -0
  447. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/tools/__init__.py +0 -0
  448. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/tools/test_generate_api_surface.py +0 -0
  449. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/tools/test_generate_reference.py +0 -0
  450. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/tools/test_reference_description.py +0 -0
  451. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/tools/test_reference_flags.py +0 -0
  452. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/tools/test_reference_typegraph.py +0 -0
  453. {imperal_sdk-6.0.2 → imperal_sdk-6.1.0}/tests/ui/test_input_type_enum.py +0 -0
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to `imperal-sdk` are documented here.
4
4
 
5
+ ## 6.1.0 — 2026-10-20
6
+
7
+ ### Added
8
+ - **`imperal_sdk.code_index`** — the code index extractor (one code file -> its symbols,
9
+ imports, references, endpoints and schemas), moved here unchanged from the Webbee Code client
10
+ (`webbee/intel/models.py`, `contracts.py`, `indexer.py`) so the client and the Imperal kernel
11
+ share one extractor. Parsing needs the new optional extra `code-index` (tree-sitter).
12
+
5
13
  ## 6.0.1 — 2026-09-26
6
14
 
7
15
  ### Added & Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: imperal-sdk
3
- Version: 6.0.2
3
+ Version: 6.1.0
4
4
  Summary: SDK for building Imperal Cloud extensions
5
5
  Author: Valentin Scerbacov, Imperal, Inc.
6
6
  License-Expression: Apache-2.0
@@ -27,6 +27,11 @@ Requires-Dist: click>=8.1.0
27
27
  Requires-Dist: httpx>=0.28.0
28
28
  Requires-Dist: pydantic>=2.10.0
29
29
  Requires-Dist: pyjwt[crypto]>=2.10.0
30
+ Provides-Extra: code-index
31
+ Requires-Dist: tree-sitter-javascript>=0.23; (sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13') and extra == 'code-index'
32
+ Requires-Dist: tree-sitter-python>=0.23; (sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13') and extra == 'code-index'
33
+ Requires-Dist: tree-sitter-typescript>=0.23; (sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13') and extra == 'code-index'
34
+ Requires-Dist: tree-sitter>=0.23; (sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13') and extra == 'code-index'
30
35
  Provides-Extra: contract
31
36
  Requires-Dist: schemathesis>=3.30.0; extra == 'contract'
32
37
  Provides-Extra: db
@@ -38,6 +43,10 @@ Requires-Dist: openapi-spec-validator>=0.7.1; extra == 'dev'
38
43
  Requires-Dist: pytest-asyncio>=0.25.0; extra == 'dev'
39
44
  Requires-Dist: pytest>=8.0.0; extra == 'dev'
40
45
  Requires-Dist: respx>=0.22.0; extra == 'dev'
46
+ Requires-Dist: tree-sitter-javascript>=0.23; (sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13') and extra == 'dev'
47
+ Requires-Dist: tree-sitter-python>=0.23; (sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13') and extra == 'dev'
48
+ Requires-Dist: tree-sitter-typescript>=0.23; (sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13') and extra == 'dev'
49
+ Requires-Dist: tree-sitter>=0.23; (sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13') and extra == 'dev'
41
50
  Provides-Extra: fastapi
42
51
  Requires-Dist: fastapi>=0.115.0; extra == 'fastapi'
43
52
  Description-Content-Type: text/markdown
@@ -46,6 +46,10 @@ dev = [
46
46
  "respx>=0.22.0",
47
47
  "openapi-spec-validator>=0.7.1",
48
48
  "jsonschema>=4.21.0",
49
+ 'tree-sitter>=0.23; sys_platform != "darwin" or platform_machine != "x86_64" or python_version < "3.13"',
50
+ 'tree-sitter-python>=0.23; sys_platform != "darwin" or platform_machine != "x86_64" or python_version < "3.13"',
51
+ 'tree-sitter-typescript>=0.23; sys_platform != "darwin" or platform_machine != "x86_64" or python_version < "3.13"',
52
+ 'tree-sitter-javascript>=0.23; sys_platform != "darwin" or platform_machine != "x86_64" or python_version < "3.13"',
49
53
  ]
50
54
  fastapi = [
51
55
  "fastapi>=0.115.0",
@@ -57,6 +61,14 @@ db = [
57
61
  contract = [
58
62
  "schemathesis>=3.30.0",
59
63
  ]
64
+ # imperal_sdk.code_index: tree-sitter parsing of Python / TypeScript / JavaScript
65
+ # (the same packages and markers the Webbee Code client ships).
66
+ code-index = [
67
+ 'tree-sitter>=0.23; sys_platform != "darwin" or platform_machine != "x86_64" or python_version < "3.13"',
68
+ 'tree-sitter-python>=0.23; sys_platform != "darwin" or platform_machine != "x86_64" or python_version < "3.13"',
69
+ 'tree-sitter-typescript>=0.23; sys_platform != "darwin" or platform_machine != "x86_64" or python_version < "3.13"',
70
+ 'tree-sitter-javascript>=0.23; sys_platform != "darwin" or platform_machine != "x86_64" or python_version < "3.13"',
71
+ ]
60
72
 
61
73
  [project.scripts]
62
74
  imperal = "imperal_sdk.cli.main:cli"
@@ -1,5 +1,5 @@
1
1
  {
2
- "sdk_version": "6.0.2",
2
+ "sdk_version": "6.1.0",
3
3
  "symbols": {
4
4
  "ActionResult": {
5
5
  "action_vocab_safe": false,
@@ -1,5 +1,5 @@
1
1
  {
2
- "_sdk_version": "6.0.2",
2
+ "_sdk_version": "6.1.0",
3
3
  "constants": {
4
4
  "max_call_depth": {
5
5
  "counts_root": true,
@@ -1,7 +1,7 @@
1
1
  """Imperal Cloud SDK — build extensions for the Imperal platform."""
2
2
  from typing import TYPE_CHECKING
3
3
 
4
- __version__ = "6.0.2"
4
+ __version__ = "6.1.0"
5
5
 
6
6
  # 5.2.2 (2026-06-11): the package root resolves its public surface lazily
7
7
  # (PEP 562). The eager imports pulled the HTTP transport (Context / client
@@ -0,0 +1,429 @@
1
+ """Code index: one code file -> its symbols, imports, references and contracts.
2
+
3
+ Moved from the Webbee Code client (webbee/intel/models.py, contracts.py, indexer.py,
4
+ 2026-10-20) so the client and the Imperal kernel share ONE extractor
5
+ (spec: docs/superpowers/specs/2026-10-19-code-graph-everywhere-design.md, ipw-repo).
6
+ tree-sitter is imported lazily: install the ``code-index`` extra to parse code.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import ast
11
+ import hashlib
12
+ import os
13
+ import re
14
+ from dataclasses import asdict, dataclass, field
15
+ from typing import Iterable
16
+
17
+
18
+ # ---- models (from webbee/intel/models.py) ----
19
+
20
+ @dataclass(frozen=True)
21
+ class Symbol:
22
+ name: str
23
+ kind: str # "function" | "class" | "method" | "symbol"
24
+ path: str # workspace-relative
25
+ start_line: int
26
+ end_line: int
27
+ signature: str = ""
28
+
29
+
30
+ @dataclass
31
+ class FileIndex:
32
+ path: str
33
+ lang: str # "python" | "typescript" | "javascript" | "other"
34
+ symbols: list[Symbol] = field(default_factory=list)
35
+ imports: list[str] = field(default_factory=list) # imported module/path strings
36
+ refs: list[str] = field(default_factory=list) # referenced identifier names (for the graph)
37
+ content_hash: str = ""
38
+ endpoints: list[dict] = field(default_factory=list)
39
+ schemas: list[dict] = field(default_factory=list)
40
+
41
+
42
+ @dataclass
43
+ class ProjectIndex:
44
+ files: dict[str, FileIndex] = field(default_factory=dict)
45
+ git_ref: str = ""
46
+
47
+
48
+ # ---- contracts (from webbee/intel/contracts.py) ----
49
+
50
+ """Deterministic endpoint/schema evidence extraction.
51
+
52
+ This is deliberately a projection over source snapshots, not a second source
53
+ of truth. Every record carries file+line provenance and is rebuilt from the
54
+ content-addressed repository index. Unsupported syntax is simply absent; no
55
+ LLM inference is stored as fact.
56
+ """
57
+
58
+
59
+ _HTTP_METHODS = frozenset({"get", "post", "put", "patch", "delete", "options", "head"})
60
+
61
+
62
+ @dataclass(frozen=True)
63
+ class EndpointEvidence:
64
+ method: str
65
+ route: str
66
+ handler: str
67
+ path: str
68
+ line: int
69
+ schema_refs: tuple[str, ...] = ()
70
+
71
+ def to_dict(self) -> dict:
72
+ return asdict(self)
73
+
74
+
75
+ @dataclass(frozen=True)
76
+ class SchemaEvidence:
77
+ name: str
78
+ schema_kind: str
79
+ path: str
80
+ line: int
81
+ fields: tuple[str, ...] = ()
82
+ storage_name: str = ""
83
+
84
+ def to_dict(self) -> dict:
85
+ return asdict(self)
86
+
87
+
88
+ def _name(node) -> str:
89
+ if isinstance(node, ast.Name):
90
+ return node.id
91
+ if isinstance(node, ast.Attribute):
92
+ left = _name(node.value)
93
+ return f"{left}.{node.attr}" if left else node.attr
94
+ if isinstance(node, ast.Subscript):
95
+ return _name(node.value)
96
+ return ""
97
+
98
+
99
+ def _literal_string(node) -> str:
100
+ return node.value if isinstance(node, ast.Constant) and isinstance(node.value, str) else ""
101
+
102
+
103
+ def _annotation_names(node) -> set[str]:
104
+ if node is None:
105
+ return set()
106
+ names = set()
107
+ for part in ast.walk(node):
108
+ n = _name(part)
109
+ if n and n.split(".")[-1][:1].isupper():
110
+ names.add(n.split(".")[-1])
111
+ return names
112
+
113
+
114
+ _ROUTER_CTORS = frozenset({"APIRouter", "Blueprint", "FastAPI", "Flask"})
115
+
116
+
117
+ def _router_prefixes(tree) -> dict:
118
+ """``name -> prefix`` of the routers this module builds (``router = APIRouter(prefix="/api")``,
119
+ ``Blueprint("x", __name__, url_prefix="/x")``): a route is the router's prefix + its path."""
120
+ out = {}
121
+ for node in ast.walk(tree):
122
+ if isinstance(node, ast.Assign) and isinstance(node.value, ast.Call) \
123
+ and _name(node.value.func).split(".")[-1] in _ROUTER_CTORS:
124
+ prefix = next((_literal_string(k.value) for k in node.value.keywords
125
+ if k.arg in ("prefix", "url_prefix")), "")
126
+ for t in node.targets:
127
+ if isinstance(t, ast.Name):
128
+ out[t.id] = prefix
129
+ return out
130
+
131
+
132
+ def _route_of(prefixes: dict, owner: str, route: str) -> str:
133
+ """The full route (the router's prefix + the path; a FastAPI router path may be "" under a
134
+ prefix), or "" when it is not a route."""
135
+ full = prefixes.get(owner, "") + route
136
+ return full if full.startswith("/") else ""
137
+
138
+
139
+ def _methods_kw(call) -> list:
140
+ for kw in call.keywords:
141
+ if kw.arg == "methods" and isinstance(kw.value, (ast.List, ast.Tuple, ast.Set)):
142
+ return [m.lower() for m in (_literal_string(e) for e in kw.value.elts) if m]
143
+ return []
144
+
145
+
146
+ def _endpoint_refs(fn, call) -> tuple:
147
+ refs = set()
148
+ if fn is not None:
149
+ for arg in (*fn.args.posonlyargs, *fn.args.args, *fn.args.kwonlyargs):
150
+ refs.update(_annotation_names(arg.annotation))
151
+ refs.update(_annotation_names(fn.returns))
152
+ for kw in call.keywords:
153
+ if kw.arg in {"response_model", "request_model", "model"}:
154
+ refs.update(_annotation_names(kw.value))
155
+ return tuple(sorted(refs))
156
+
157
+
158
+ def _python_contracts(path: str, text: str):
159
+ try:
160
+ tree = ast.parse(text)
161
+ except (SyntaxError, ValueError):
162
+ return [], []
163
+ prefixes = _router_prefixes(tree)
164
+ funcs = {n.name: n for n in ast.walk(tree) if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef))}
165
+ endpoints, schemas = [], []
166
+ for node in ast.walk(tree):
167
+ if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute) \
168
+ and node.func.attr == "add_api_route" and len(node.args) >= 2:
169
+ # router.add_api_route("/x", handler, methods=["GET"])
170
+ owner, route = _name(node.func.value), _literal_string(node.args[0])
171
+ full, handler = _route_of(prefixes, owner, route), _name(node.args[1])
172
+ for method in (_methods_kw(node) or ["get"]):
173
+ if full and method in _HTTP_METHODS:
174
+ endpoints.append(EndpointEvidence(method.upper(), full, handler.split(".")[-1], path,
175
+ node.lineno, _endpoint_refs(funcs.get(handler), node)))
176
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
177
+ for dec in node.decorator_list:
178
+ if not isinstance(dec, ast.Call) or not isinstance(dec.func, ast.Attribute):
179
+ continue
180
+ verb = dec.func.attr.lower()
181
+ route = _literal_string(dec.args[0]) if dec.args else ""
182
+ full = _route_of(prefixes, _name(dec.func.value), route)
183
+ # @router.get(...), and @app.route / @router.api_route(..., methods=[...])
184
+ methods = [verb] if verb in _HTTP_METHODS else (
185
+ _methods_kw(dec) or ["get"] if verb in ("route", "api_route") else [])
186
+ for method in methods:
187
+ if not full or method not in _HTTP_METHODS:
188
+ continue
189
+ endpoints.append(EndpointEvidence(
190
+ method.upper(), full, node.name, path,
191
+ getattr(dec, "lineno", node.lineno), _endpoint_refs(node, dec)))
192
+ elif isinstance(node, ast.ClassDef):
193
+ bases = {_name(b).split(".")[-1] for b in node.bases}
194
+ is_model = bool(bases & {"BaseModel", "TypedDict", "Schema", "Serializer"})
195
+ is_table = bool(bases & {"Base", "DeclarativeBase", "Model"})
196
+ if not (is_model or is_table):
197
+ continue
198
+ fields, storage = set(), ""
199
+ for stmt in node.body:
200
+ if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Name):
201
+ fields.add(stmt.target.id)
202
+ elif isinstance(stmt, ast.Assign):
203
+ for target in stmt.targets:
204
+ if isinstance(target, ast.Name):
205
+ if target.id == "__tablename__":
206
+ storage = _literal_string(stmt.value)
207
+ elif isinstance(stmt.value, ast.Call):
208
+ call = _name(stmt.value.func).split(".")[-1]
209
+ if call in {"Column", "mapped_column", "Field"}:
210
+ fields.add(target.id)
211
+ schemas.append(SchemaEvidence(
212
+ node.name, "table" if is_table else "model", path, node.lineno,
213
+ tuple(sorted(fields)), storage))
214
+ return endpoints, schemas
215
+
216
+
217
+ _TS_ENDPOINT = re.compile(
218
+ r"(?m)\b(?:app|router|server)\s*\.\s*(get|post|put|patch|delete|options|head)"
219
+ r"\s*\(\s*([\"'])(/[^\"']*)\2\s*,\s*([A-Za-z_$][\w$]*)"
220
+ )
221
+ _TS_SCHEMA = re.compile(
222
+ r"(?ms)\b(?:export\s+)?(?:interface|type|class)\s+([A-Za-z_$][\w$]*)"
223
+ r"(?:\s+extends[^\{=]+)?\s*(?:\{|=\s*\{)(.*?)\}"
224
+ )
225
+ _TS_FIELD = re.compile(r"(?m)^\s*([A-Za-z_$][\w$]*)\s*\??\s*:")
226
+
227
+
228
+ def _typescript_contracts(path: str, text: str):
229
+ endpoints = [EndpointEvidence(
230
+ m.group(1).upper(), m.group(3), m.group(4), path,
231
+ text.count("\n", 0, m.start()) + 1)
232
+ for m in _TS_ENDPOINT.finditer(text)]
233
+ schemas = []
234
+ for m in _TS_SCHEMA.finditer(text):
235
+ schemas.append(SchemaEvidence(
236
+ m.group(1), "model", path, text.count("\n", 0, m.start()) + 1,
237
+ tuple(sorted(set(_TS_FIELD.findall(m.group(2)))))))
238
+ return endpoints, schemas
239
+
240
+
241
+ _NEXT_HANDLER = re.compile(
242
+ r"(?m)^\s*export\s+(?:async\s+)?(?:function\s+|const\s+)(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)\b")
243
+ _NEXT_APP_ROUTE = re.compile(r"(?:^|/)app/(.*?)/?route\.(?:ts|tsx|js|jsx|mjs)$")
244
+ _NEXT_PAGES_API = re.compile(r"(?:^|/)pages/(api(?:/.*?)?)(?:/index)?\.(?:ts|tsx|js|jsx)$")
245
+
246
+
247
+ def _next_route(segments: str) -> str:
248
+ """A Next.js file route: route groups ``(x)`` and parallel slots ``@x`` vanish."""
249
+ parts = [p for p in segments.split("/") if p and not (p.startswith("(") and p.endswith(")"))
250
+ and not p.startswith("@")]
251
+ return "/" + "/".join(parts)
252
+
253
+
254
+ def _next_contracts(path: str, text: str):
255
+ """Next.js route handlers: ``app/**/route.ts`` exporting GET/POST/..., and ``pages/api/**``."""
256
+ p = path.replace("\\", "/")
257
+ m = _NEXT_APP_ROUTE.search(p)
258
+ if m:
259
+ route = _next_route(m.group(1))
260
+ return [EndpointEvidence(h.group(1), route, h.group(1), path, text.count("\n", 0, h.start()) + 1)
261
+ for h in _NEXT_HANDLER.finditer(text)]
262
+ m = _NEXT_PAGES_API.search(p)
263
+ if m and re.search(r"(?m)^\s*export\s+default\b", text):
264
+ return [EndpointEvidence("ANY", _next_route(m.group(1)), "default", path, 1)]
265
+ return []
266
+
267
+
268
+ def extract_contracts(path: str, text: str, lang: str):
269
+ if lang == "python":
270
+ return _python_contracts(path, text)
271
+ if lang in {"typescript", "javascript"}:
272
+ endpoints, schemas = _typescript_contracts(path, text)
273
+ return endpoints + _next_contracts(path, text), schemas
274
+ return [], []
275
+
276
+
277
+ def match_contracts(repos: Iterable[dict]) -> list[dict]:
278
+ """Build deterministic cross-repo links from exact contract identities.
279
+
280
+ Endpoint route+method and schema names are intentionally exact. Semantic
281
+ guesses belong in retrieval ranking, never in the evidence graph.
282
+ """
283
+ repos = sorted(repos, key=lambda r: r.get("repo_key", ""))
284
+ out = []
285
+ for i, left in enumerate(repos):
286
+ for right in repos[i + 1:]:
287
+ lk, rk = left.get("repo_key", ""), right.get("repo_key", "")
288
+ le = {(x.method, x.route): x for x in left.get("endpoints", ())}
289
+ re_ = {(x.method, x.route): x for x in right.get("endpoints", ())}
290
+ for key in sorted(le.keys() & re_.keys()):
291
+ out.append({"relation": "endpoint_identity", "source_repo": lk,
292
+ "target_repo": rk, "identity": f"{key[0]} {key[1]}"})
293
+ # A schema contract can be declared as a concrete model/table OR
294
+ # referenced by an endpoint annotation/response_model. Both are
295
+ # deterministic source evidence; including references lets a
296
+ # producer endpoint link to a consumer's shared DTO even when the
297
+ # producer imports that DTO from another package.
298
+ def schema_names(repo):
299
+ names = {x.name for x in repo.get("schemas", ())}
300
+ for endpoint in repo.get("endpoints", ()):
301
+ names.update(endpoint.schema_refs)
302
+ return names
303
+
304
+ for name in sorted(schema_names(left) & schema_names(right)):
305
+ source, target = sorted((lk, rk))
306
+ out.append({"relation": "schema_name_match", "source_repo": source,
307
+ "target_repo": target, "identity": name})
308
+ return out
309
+
310
+
311
+ # ---- indexer (from webbee/intel/indexer.py) ----
312
+
313
+ LANG_BY_EXT = {".py": "python", ".ts": "typescript", ".tsx": "typescript",
314
+ ".js": "javascript", ".jsx": "javascript"}
315
+
316
+ # tree-sitter Language handles are lazy-loaded + cached (import cost is real).
317
+ _LANG_CACHE: dict = {}
318
+
319
+
320
+ def _get_language(lang: str):
321
+ if lang in _LANG_CACHE:
322
+ return _LANG_CACHE[lang]
323
+ try:
324
+ if lang == "python":
325
+ import tree_sitter_python as ts_py
326
+ from tree_sitter import Language
327
+ obj = Language(ts_py.language())
328
+ elif lang == "typescript":
329
+ import tree_sitter_typescript as ts_ts
330
+ from tree_sitter import Language
331
+ obj = Language(ts_ts.language_typescript())
332
+ elif lang == "javascript":
333
+ import tree_sitter_javascript as ts_js
334
+ from tree_sitter import Language
335
+ obj = Language(ts_js.language())
336
+ else:
337
+ obj = None
338
+ except Exception:
339
+ obj = None
340
+ _LANG_CACHE[lang] = obj
341
+ return obj
342
+
343
+
344
+ # Minimal per-language node-type -> symbol-kind maps (clean-room; NOT the AGPL
345
+ # package's queries). We walk the tree once and pick definition nodes; this is
346
+ # syntax-level extraction, exactly what tree-sitter guarantees.
347
+ _DEF_NODES = {
348
+ "python": {"function_definition": "function", "class_definition": "class"},
349
+ "typescript": {"function_declaration": "function", "class_declaration": "class",
350
+ "method_definition": "method", "interface_declaration": "class"},
351
+ "javascript": {"function_declaration": "function", "class_declaration": "class",
352
+ "method_definition": "method"},
353
+ }
354
+
355
+
356
+ def _lang_for(path: str) -> str:
357
+ return LANG_BY_EXT.get(os.path.splitext(path)[1].lower(), "other")
358
+
359
+
360
+ def _name_of(node, src_bytes: bytes) -> str:
361
+ n = node.child_by_field_name("name")
362
+ if n is not None:
363
+ return src_bytes[n.start_byte:n.end_byte].decode("utf-8", "replace")
364
+ return ""
365
+
366
+
367
+ def parse_file(path: str, text: str) -> FileIndex | None:
368
+ lang = _lang_for(path)
369
+ fi = FileIndex(path=path, lang=lang, content_hash=hashlib.sha256(text.encode("utf-8", "replace")).hexdigest())
370
+ endpoints, schemas = extract_contracts(path, text, lang)
371
+ fi.endpoints = [x.to_dict() for x in endpoints]
372
+ fi.schemas = [x.to_dict() for x in schemas]
373
+ if lang == "other":
374
+ return fi # line-only fallback (no symbols) — never crash
375
+ L = _get_language(lang)
376
+ if L is None:
377
+ return fi
378
+ try:
379
+ from tree_sitter import Parser
380
+ parser = Parser(L)
381
+ src = text.encode("utf-8", "replace")
382
+ tree = parser.parse(src)
383
+ defmap = _DEF_NODES.get(lang, {})
384
+ stack = [tree.root_node]
385
+ while stack:
386
+ node = stack.pop()
387
+ kind = defmap.get(node.type)
388
+ if kind:
389
+ # A def/class node's own name-identifier must NOT be walked
390
+ # as a generic child -- otherwise it lands in `refs` too,
391
+ # making the defining file its own "caller"/"dependent".
392
+ # Nested defs (methods, inner functions) are still reached:
393
+ # every other child is still pushed onto the stack.
394
+ # NOTE: tree-sitter Node objects are re-wrapped on each
395
+ # access, so `is`/`is not` identity checks don't hold across
396
+ # two separate child_by_field_name/children calls -- compare
397
+ # by (start_byte, end_byte) span instead.
398
+ name_node = node.child_by_field_name("name")
399
+ name_span = (name_node.start_byte, name_node.end_byte) if name_node is not None else None
400
+ nm = _name_of(node, src)
401
+ if nm:
402
+ sig = src[node.start_byte:min(node.end_byte, node.start_byte + 200)].decode("utf-8", "replace").split("\n", 1)[0]
403
+ fi.symbols.append(Symbol(name=nm, kind=kind, path=path,
404
+ start_line=node.start_point[0] + 1,
405
+ end_line=node.end_point[0] + 1, signature=sig))
406
+ for ch in node.children:
407
+ if name_span is None or (ch.start_byte, ch.end_byte) != name_span:
408
+ stack.append(ch)
409
+ continue
410
+ if node.type in ("identifier", "call", "call_expression"):
411
+ fi.refs.append(src[node.start_byte:node.end_byte].decode("utf-8", "replace").split("(")[0].strip())
412
+ stack.extend(node.children)
413
+ except Exception:
414
+ return fi # parse error -> line-only, fail-soft
415
+ return fi
416
+
417
+
418
+ def build_index(root: str, files: list[str]) -> ProjectIndex:
419
+ idx = ProjectIndex()
420
+ for rel in files:
421
+ try:
422
+ with open(os.path.join(root, rel), "r", encoding="utf-8") as f:
423
+ text = f.read()
424
+ except (OSError, UnicodeDecodeError):
425
+ continue
426
+ fi = parse_file(rel, text)
427
+ if fi is not None:
428
+ idx.files[rel] = fi
429
+ return idx
@@ -0,0 +1,82 @@
1
+ from imperal_sdk.code_index import extract_contracts, match_contracts
2
+
3
+
4
+ def test_extracts_python_http_endpoints_with_provenance():
5
+ text = '''
6
+ @router.post("/v1/orders/{order_id}", response_model=OrderOut)
7
+ async def create_order(order_id: int, body: OrderIn):
8
+ return service.create(body)
9
+
10
+ @app.get('/healthz')
11
+ def health():
12
+ return {"ok": True}
13
+ '''
14
+ endpoints, schemas = extract_contracts("api/orders.py", text, "python")
15
+ assert [(e.method, e.route, e.handler) for e in endpoints] == [
16
+ ("POST", "/v1/orders/{order_id}", "create_order"),
17
+ ("GET", "/healthz", "health"),
18
+ ]
19
+ assert endpoints[0].path == "api/orders.py"
20
+ assert endpoints[0].line == 2
21
+ assert "OrderIn" in endpoints[0].schema_refs
22
+ assert "OrderOut" in endpoints[0].schema_refs
23
+
24
+
25
+ def test_extracts_pydantic_and_sqlalchemy_schemas():
26
+ text = '''
27
+ class OrderIn(BaseModel):
28
+ sku: str
29
+ quantity: int = 1
30
+
31
+ class OrderRow(Base):
32
+ __tablename__ = "orders"
33
+ id = Column(Integer, primary_key=True)
34
+ payload = mapped_column(JSON)
35
+ '''
36
+ endpoints, schemas = extract_contracts("models.py", text, "python")
37
+ assert not endpoints
38
+ by_name = {s.name: s for s in schemas}
39
+ assert by_name["OrderIn"].schema_kind == "model"
40
+ assert by_name["OrderIn"].fields == ("quantity", "sku")
41
+ assert by_name["OrderRow"].schema_kind == "table"
42
+ assert by_name["OrderRow"].storage_name == "orders"
43
+ assert by_name["OrderRow"].fields == ("id", "payload")
44
+
45
+
46
+ def test_extracts_typescript_express_and_interfaces():
47
+ text = '''
48
+ router.put("/v1/users/:id", updateUser)
49
+ export interface UserPatch {
50
+ displayName?: string;
51
+ active: boolean;
52
+ }
53
+ '''
54
+ endpoints, schemas = extract_contracts("routes/users.ts", text, "typescript")
55
+ assert [(e.method, e.route, e.handler) for e in endpoints] == [
56
+ ("PUT", "/v1/users/:id", "updateUser")
57
+ ]
58
+ assert schemas[0].name == "UserPatch"
59
+ assert schemas[0].fields == ("active", "displayName")
60
+
61
+
62
+ def test_cross_repo_matching_is_deterministic_and_typed():
63
+ producer_eps, producer_schemas = extract_contracts(
64
+ "api.py",
65
+ '@app.post("/v1/orders", response_model=OrderOut)\ndef create(body: OrderIn): pass\n',
66
+ "python",
67
+ )
68
+ _, client_schemas = extract_contracts(
69
+ "client.py", "class OrderIn(BaseModel):\n sku: str\n", "python"
70
+ )
71
+ links = match_contracts(
72
+ [
73
+ {"repo_key": "producer", "endpoints": producer_eps, "schemas": producer_schemas},
74
+ {"repo_key": "client", "endpoints": [], "schemas": client_schemas},
75
+ ]
76
+ )
77
+ schema_links = [x for x in links if x["relation"] == "schema_name_match"]
78
+ assert schema_links
79
+ assert schema_links[0]["source_repo"] == "client"
80
+ assert schema_links[0]["target_repo"] == "producer"
81
+
82
+
@@ -0,0 +1,53 @@
1
+ import pytest
2
+ pytest.importorskip("tree_sitter") # skip when the intel extra isn't installed
3
+ from imperal_sdk import code_index as indexer
4
+ from imperal_sdk.code_index import ProjectIndex
5
+
6
+
7
+ def test_parse_python_symbols(tmp_path):
8
+ src = "def alpha(x):\n return beta(x)\n\nclass Gamma:\n def method(self):\n pass\n"
9
+ fi = indexer.parse_file("m.py", src)
10
+ names = {s.name for s in fi.symbols}
11
+ assert {"alpha", "Gamma", "method"} <= names
12
+ a = next(s for s in fi.symbols if s.name == "alpha")
13
+ assert a.kind == "function" and a.start_line == 1
14
+
15
+
16
+ def test_parse_ts_symbols():
17
+ fi = indexer.parse_file("m.ts", "export function widget(a: number){ return a }\nclass Box {}\n")
18
+ names = {s.name for s in fi.symbols}
19
+ assert "widget" in names and "Box" in names
20
+
21
+
22
+ def test_unsupported_ext_is_line_only_not_crash():
23
+ fi = indexer.parse_file("data.bin", "\x00\x01binary")
24
+ assert fi is not None and fi.symbols == [] and fi.lang == "other"
25
+
26
+
27
+ def test_build_index(tmp_path):
28
+ (tmp_path / "a.py").write_text("def a():\n return b()\n")
29
+ (tmp_path / "b.py").write_text("def b():\n return 1\n")
30
+ idx = indexer.build_index(str(tmp_path), ["a.py", "b.py"])
31
+ assert isinstance(idx, ProjectIndex)
32
+ assert set(idx.files) == {"a.py", "b.py"}
33
+ assert any(s.name == "a" for s in idx.files["a.py"].symbols)
34
+
35
+
36
+ def test_def_own_name_is_not_recorded_as_a_ref():
37
+ # A def's own name-identifier must not land in fi.refs -- otherwise the
38
+ # defining file counts itself as a "caller"/"dependent" of its own
39
+ # symbol, inflating callers_of/impact_of_change with a false positive.
40
+ src = "def alpha():\n return 1\n"
41
+ fi = indexer.parse_file("m.py", src)
42
+ assert "alpha" not in fi.refs
43
+
44
+
45
+ def test_nested_def_inside_class_still_discovered_after_name_exclusion():
46
+ # The name-node exclusion must not break traversal into a def's body --
47
+ # nested/inner defs (e.g. methods) still need to be found.
48
+ src = "class Gamma:\n def method(self):\n return other()\n"
49
+ fi = indexer.parse_file("m.py", src)
50
+ names = {s.name for s in fi.symbols}
51
+ assert {"Gamma", "method"} <= names
52
+ assert "other" in fi.refs # the call inside the method body is still a ref
53
+ assert "method" not in fi.refs # but the method's own name is not
File without changes
File without changes