imperal-sdk 6.3.7__tar.gz → 6.3.8__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 (455) hide show
  1. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/CHANGELOG.md +12 -0
  2. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/PKG-INFO +1 -1
  3. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/sdk-reference.json +1 -1
  4. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/sdk_claims.json +1 -1
  5. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/__init__.py +1 -1
  6. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/code_index.py +190 -50
  7. imperal_sdk-6.3.8/tests/test_code_index_configs.py +70 -0
  8. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_code_index_indexer.py +60 -0
  9. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/.cm.txt +0 -0
  10. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/.github/workflows/identity-contract.yml +0 -0
  11. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/.github/workflows/publish.yml +0 -0
  12. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/.github/workflows/test.yml +0 -0
  13. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/.gitignore +0 -0
  14. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/LICENSE +0 -0
  15. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/README.md +0 -0
  16. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/docs/sdl-facets.md +0 -0
  17. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/pyproject.toml +0 -0
  18. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/sdl_roles.json +0 -0
  19. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/.codebase-index-cache.pkl +0 -0
  20. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/_gateway.py +0 -0
  21. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/_http_retry.py +0 -0
  22. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/_shared_http.py +0 -0
  23. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/adversarial_oracle.py +0 -0
  24. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ai/__init__.py +0 -0
  25. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ai/client.py +0 -0
  26. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/app.py +0 -0
  27. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/apps/__init__.py +0 -0
  28. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/apps/client.py +0 -0
  29. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/auth/__init__.py +0 -0
  30. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/auth/client.py +0 -0
  31. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/auth/middleware.py +0 -0
  32. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/auto_ui.py +0 -0
  33. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/billing/__init__.py +0 -0
  34. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/billing/client.py +0 -0
  35. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/bom_extractor.py +0 -0
  36. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/cache/__init__.py +0 -0
  37. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/cache/client.py +0 -0
  38. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/cache/protocol.py +0 -0
  39. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/catalog.py +0 -0
  40. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/__init__.py +0 -0
  41. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/action_result.py +0 -0
  42. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/error_codes.py +0 -0
  43. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/exceptions.py +0 -0
  44. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/extension.py +0 -0
  45. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/filters.py +0 -0
  46. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/guards.py +0 -0
  47. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/kernel_primitives.py +0 -0
  48. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/narration.py +0 -0
  49. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/narration_guard.py +0 -0
  50. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/prompt.py +0 -0
  51. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/chat/refusal.py +0 -0
  52. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/cli/__init__.py +0 -0
  53. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/cli/linter.py +0 -0
  54. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/cli/main.py +0 -0
  55. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/config/__init__.py +0 -0
  56. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/config/client.py +0 -0
  57. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/context.py +0 -0
  58. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/conversations/__init__.py +0 -0
  59. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/conversations/client.py +0 -0
  60. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/core.py +0 -0
  61. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/cross_surface_bus.py +0 -0
  62. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/__init__.py +0 -0
  63. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/contract_checks.py +0 -0
  64. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/generate_api_surface.py +0 -0
  65. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/generate_reference.py +0 -0
  66. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/generate_sdk_claims.py +0 -0
  67. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/reference/__init__.py +0 -0
  68. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/reference/_flags.py +0 -0
  69. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/reference/_introspect.py +0 -0
  70. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/reference/client_methods.py +0 -0
  71. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/reference/dataclasses_kind.py +0 -0
  72. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/reference/decorators.py +0 -0
  73. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/reference/sdl_funcs.py +0 -0
  74. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/reference/sdl_roles.py +0 -0
  75. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/reference/ui_components.py +0 -0
  76. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/devtools/validate_identity_contract.py +0 -0
  77. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/dwell_guard.py +0 -0
  78. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/errors.py +0 -0
  79. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/extension.py +0 -0
  80. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/extensions/__init__.py +0 -0
  81. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/extensions/client.py +0 -0
  82. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/gnc_guard.py +0 -0
  83. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/http/__init__.py +0 -0
  84. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/http/client.py +0 -0
  85. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/__init__.py +0 -0
  86. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/_impl.py +0 -0
  87. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/actions.py +0 -0
  88. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/custom_roles.py +0 -0
  89. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/migrate.py +0 -0
  90. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/produce.py +0 -0
  91. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/schema.py +0 -0
  92. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/skeleton.py +0 -0
  93. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/ui.py +0 -0
  94. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/ui_children.py +0 -0
  95. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/ui_template.py +0 -0
  96. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ir/validator.py +0 -0
  97. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/manifest.py +0 -0
  98. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/manifest_schema.py +0 -0
  99. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/manifest_schema_ui.py +0 -0
  100. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/notify/__init__.py +0 -0
  101. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/notify/client.py +0 -0
  102. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/oauth_state.py +0 -0
  103. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/oauth_tokens.py +0 -0
  104. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/pipes.py +0 -0
  105. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/prompts/__init__.py +0 -0
  106. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/prompts/icnli_integrity_rules.txt +0 -0
  107. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/prompts/kernel_formatting_rule.txt +0 -0
  108. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/prompts/kernel_proactivity_rule.txt +0 -0
  109. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/protocols.py +0 -0
  110. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/rbac/__init__.py +0 -0
  111. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/rbac/client.py +0 -0
  112. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/rpc/__init__.py +0 -0
  113. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/rpc/codec.py +0 -0
  114. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/rpc/contract.py +0 -0
  115. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/__init__.py +0 -0
  116. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/_platform.py +0 -0
  117. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/canon.py +0 -0
  118. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/engine.py +0 -0
  119. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/executor.py +0 -0
  120. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/hosted_client.py +0 -0
  121. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/interpreter.py +0 -0
  122. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/llm_provider.py +0 -0
  123. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/local_engine.py +0 -0
  124. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/message_adapter.py +0 -0
  125. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/template.py +0 -0
  126. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/runtime/verbs.py +0 -0
  127. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schema/marathon_ram.sql +0 -0
  128. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/action_result.schema.json +0 -0
  129. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/__init__.py +0 -0
  130. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/ai_complete.json +0 -0
  131. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/call.json +0 -0
  132. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/conditional.json +0 -0
  133. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/navigate.json +0 -0
  134. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/open.json +0 -0
  135. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/send.json +0 -0
  136. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/store_create.json +0 -0
  137. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/store_delete.json +0 -0
  138. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/store_get.json +0 -0
  139. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/store_list.json +0 -0
  140. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/actions/store_update.json +0 -0
  141. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/balance_info.schema.json +0 -0
  142. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/chat_result.schema.json +0 -0
  143. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/completion_result.schema.json +0 -0
  144. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/document.schema.json +0 -0
  145. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/event.schema.json +0 -0
  146. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/file_info.schema.json +0 -0
  147. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/function_call.schema.json +0 -0
  148. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/http_response.schema.json +0 -0
  149. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/imperal.schema.json +0 -0
  150. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/ir.schema.json +0 -0
  151. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/limits_result.schema.json +0 -0
  152. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/metered_event.schema.json +0 -0
  153. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/subscription_info.schema.json +0 -0
  154. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/ui_children/__init__.py +0 -0
  155. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/ui_children/accordion.json +0 -0
  156. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/ui_children/datatable_columns.json +0 -0
  157. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/ui_children/datatable_rows.json +0 -0
  158. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/ui_children/menu.json +0 -0
  159. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/ui_children/select.json +0 -0
  160. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/ui_children/tabs.json +0 -0
  161. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/ui_children/timeline.json +0 -0
  162. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/schemas/ui_children/tree.json +0 -0
  163. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/__init__.py +0 -0
  164. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/_generate_roles_json.py +0 -0
  165. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/entity.py +0 -0
  166. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facet_resolve.py +0 -0
  167. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/__init__.py +0 -0
  168. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/catalog.py +0 -0
  169. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/comm.py +0 -0
  170. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/content.py +0 -0
  171. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/device.py +0 -0
  172. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/event.py +0 -0
  173. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/geo.py +0 -0
  174. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/identity.py +0 -0
  175. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/media.py +0 -0
  176. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/metric.py +0 -0
  177. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/money.py +0 -0
  178. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/net.py +0 -0
  179. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/people.py +0 -0
  180. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/quantity.py +0 -0
  181. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/rating.py +0 -0
  182. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/security.py +0 -0
  183. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/task.py +0 -0
  184. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/facets/time.py +0 -0
  185. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/field.py +0 -0
  186. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/sdl/roles.py +0 -0
  187. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/search.py +0 -0
  188. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/secrets/__init__.py +0 -0
  189. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/secrets/client.py +0 -0
  190. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/secrets/exceptions.py +0 -0
  191. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/secrets/panel_handler.py +0 -0
  192. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/secrets/spec.py +0 -0
  193. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/security/__init__.py +0 -0
  194. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/security/call_token.py +0 -0
  195. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/security/deactivation_guard.py +0 -0
  196. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/signals/__init__.py +0 -0
  197. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/signals/client.py +0 -0
  198. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/skeleton/__init__.py +0 -0
  199. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/skeleton/client.py +0 -0
  200. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/storage/__init__.py +0 -0
  201. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/storage/client.py +0 -0
  202. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/store/__init__.py +0 -0
  203. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/store/client.py +0 -0
  204. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/store/exceptions.py +0 -0
  205. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/testing/__init__.py +0 -0
  206. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/testing/autonomous_mock.py +0 -0
  207. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/testing/mock_context.py +0 -0
  208. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/testing/mock_secrets.py +0 -0
  209. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/transport.py +0 -0
  210. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/typed_context.py +0 -0
  211. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/__init__.py +0 -0
  212. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/action_result.py +0 -0
  213. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/chat_result.py +0 -0
  214. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/client_contracts.py +0 -0
  215. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/contracts.py +0 -0
  216. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/contributions.py +0 -0
  217. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/events.py +0 -0
  218. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/health.py +0 -0
  219. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/identity.py +0 -0
  220. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/metered_event.py +0 -0
  221. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/models.py +0 -0
  222. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/pagination.py +0 -0
  223. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/types/store_contracts.py +0 -0
  224. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/__init__.py +0 -0
  225. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/actions.py +0 -0
  226. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/base.py +0 -0
  227. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/canvas.py +0 -0
  228. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/data.py +0 -0
  229. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/display.py +0 -0
  230. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/feedback.py +0 -0
  231. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/graph.py +0 -0
  232. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/input_components.py +0 -0
  233. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/interactive.py +0 -0
  234. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/layout.py +0 -0
  235. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/liquid.py +0 -0
  236. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/signals.py +0 -0
  237. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/stage.py +0 -0
  238. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/ui/theme.py +0 -0
  239. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/users/__init__.py +0 -0
  240. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/users/client.py +0 -0
  241. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/validator.py +0 -0
  242. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/validator_v1_6_0.py +0 -0
  243. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/src/imperal_sdk/vault_ram_client.py +0 -0
  244. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/conftest.py +0 -0
  245. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/__init__.py +0 -0
  246. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_action_schemas.py +0 -0
  247. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_artifacts_freshness.py +0 -0
  248. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_contract_checks_selftest.py +0 -0
  249. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_generate_sdk_claims.py +0 -0
  250. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_identity_nonempty.py +0 -0
  251. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_ir_schema_fresh.py +0 -0
  252. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_meter_lua_contract.py +0 -0
  253. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_metered_event_contract.py +0 -0
  254. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_notify_wire_payload.py +0 -0
  255. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_public_docstrings_engine_neutral.py +0 -0
  256. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_reference_completeness.py +0 -0
  257. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_reference_no_leak.py +0 -0
  258. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_sample_contract_shape.py +0 -0
  259. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contract/test_sdk_matches_kernel_contract.py +0 -0
  260. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contracts/__init__.py +0 -0
  261. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/contracts/test_store_contracts.py +0 -0
  262. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/fixtures/contract/kernel-contract.sample.json +0 -0
  263. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/fixtures/ir/README.md +0 -0
  264. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/fixtures/ir/archive_ended.ir.json +0 -0
  265. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/fixtures/ir/link_saver.ir.json +0 -0
  266. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/fixtures/ir/test_fixtures_valid.py +0 -0
  267. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/fixtures/openapi/auth-gateway.json +0 -0
  268. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/fixtures/openapi/registry.json +0 -0
  269. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/fixtures/openapi/sharelock-cases.json +0 -0
  270. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/__init__.py +0 -0
  271. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_custom_roles.py +0 -0
  272. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ir_impl.py +0 -0
  273. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ir_mapping_real_ext.py +0 -0
  274. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ir_migrate.py +0 -0
  275. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ir_produce.py +0 -0
  276. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ir_schema.py +0 -0
  277. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ir_skeleton.py +0 -0
  278. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ir_ui.py +0 -0
  279. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ir_ui_produce.py +0 -0
  280. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ir_validator.py +0 -0
  281. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ir_versions.py +0 -0
  282. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ui_children.py +0 -0
  283. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ir/test_ui_template.py +0 -0
  284. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/rpc/__init__.py +0 -0
  285. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/rpc/test_boundary_seal.py +0 -0
  286. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/rpc/test_codec.py +0 -0
  287. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/rpc/test_contract.py +0 -0
  288. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/__init__.py +0 -0
  289. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_canon.py +0 -0
  290. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_canon_template.py +0 -0
  291. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_engine_abc.py +0 -0
  292. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_engine_parity.py +0 -0
  293. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_executor_neutral.py +0 -0
  294. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_hosted_client.py +0 -0
  295. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_interpreter.py +0 -0
  296. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_llm_provider_config_store.py +0 -0
  297. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_llm_provider_ctx_injection.py +0 -0
  298. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_local_engine.py +0 -0
  299. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_platform_shim.py +0 -0
  300. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_template.py +0 -0
  301. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_verb_ai.py +0 -0
  302. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_verb_call_directives.py +0 -0
  303. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_verb_conditional.py +0 -0
  304. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/runtime/test_verb_store.py +0 -0
  305. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/store/__init__.py +0 -0
  306. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/store/test_list_users_client.py +0 -0
  307. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/store/test_query_all_client.py +0 -0
  308. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_action_result_time_travel.py +0 -0
  309. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_action_result_typed.py +0 -0
  310. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_agent_presence.py +0 -0
  311. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_app_engine.py +0 -0
  312. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_as_user.py +0 -0
  313. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_auth.py +0 -0
  314. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_autonomous_mock.py +0 -0
  315. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_billing.py +0 -0
  316. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_cache_client.py +0 -0
  317. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_cache_model.py +0 -0
  318. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_call_token.py +0 -0
  319. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_callable_surface_single_source.py +0 -0
  320. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_chat_extension_deprecation.py +0 -0
  321. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_chat_extension_no_llm_router.py +0 -0
  322. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_chat_filters.py +0 -0
  323. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_chat_function_background_flag.py +0 -0
  324. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_chat_guards.py +0 -0
  325. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_chat_guards_bleed.py +0 -0
  326. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_chat_prompt.py +0 -0
  327. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_chat_result.py +0 -0
  328. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_cli.py +0 -0
  329. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_cli_sdk_commands.py +0 -0
  330. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_client_contracts.py +0 -0
  331. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_client_emit_neutral.py +0 -0
  332. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_code_index_contracts.py +0 -0
  333. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_config_client.py +0 -0
  334. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_context.py +0 -0
  335. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_context_background_task.py +0 -0
  336. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_context_deliver_chat_message.py +0 -0
  337. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_context_guards.py +0 -0
  338. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_contracts.py +0 -0
  339. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_contracts_live.py +0 -0
  340. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_contributions.py +0 -0
  341. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_core_primitives.py +0 -0
  342. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_data_model_kwarg.py +0 -0
  343. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_document_contract.py +0 -0
  344. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_emits_decorator.py +0 -0
  345. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_error_codes.py +0 -0
  346. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_errors.py +0 -0
  347. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_event_schema_v2.py +0 -0
  348. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_events_health.py +0 -0
  349. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_extension.py +0 -0
  350. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_extension_pipes.py +0 -0
  351. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_extension_v2.py +0 -0
  352. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_extensions_emit.py +0 -0
  353. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_gateway_namespaces.py +0 -0
  354. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_http_json_and_mock.py +0 -0
  355. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_http_retry.py +0 -0
  356. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_http_timeout_override.py +0 -0
  357. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_id_shape_guard.py +0 -0
  358. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_identity_contract.py +0 -0
  359. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_imperal_schema_v2.py +0 -0
  360. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_import_light.py +0 -0
  361. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_init_onboarding.py +0 -0
  362. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_kernel_primitives.py +0 -0
  363. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_liquid_ui.py +0 -0
  364. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest.py +0 -0
  365. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_file_sinks.py +0 -0
  366. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_linter.py +0 -0
  367. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_no_orchestrator_tool.py +0 -0
  368. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_oauth.py +0 -0
  369. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_panels.py +0 -0
  370. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_roundtrip_gate.py +0 -0
  371. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_schema.py +0 -0
  372. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_v2_events.py +0 -0
  373. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_v2_other_sections.py +0 -0
  374. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_v2_webhooks.py +0 -0
  375. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_manifest_validator_v2.py +0 -0
  376. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_mock_context.py +0 -0
  377. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_models.py +0 -0
  378. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_narration_emission.py +0 -0
  379. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_narration_guard.py +0 -0
  380. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_oauth_authorize_url.py +0 -0
  381. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_oauth_tokens_shared.py +0 -0
  382. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_openai_max_completion_tokens.py +0 -0
  383. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_pagination.py +0 -0
  384. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_panel_rendering_contract.py +0 -0
  385. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_panel_swr_caching.py +0 -0
  386. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_panels.py +0 -0
  387. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_phase_a_dead_removal.py +0 -0
  388. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_phase_a_drift.py +0 -0
  389. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_phase_a_text.py +0 -0
  390. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdk_version_stamp.py +0 -0
  391. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_entity.py +0 -0
  392. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_entity_marker.py +0 -0
  393. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_exports.py +0 -0
  394. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_catalog.py +0 -0
  395. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_collisions.py +0 -0
  396. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_comm.py +0 -0
  397. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_content.py +0 -0
  398. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_device.py +0 -0
  399. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_event.py +0 -0
  400. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_exports.py +0 -0
  401. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_field.py +0 -0
  402. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_geo.py +0 -0
  403. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_identity.py +0 -0
  404. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_media.py +0 -0
  405. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_metric.py +0 -0
  406. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_money.py +0 -0
  407. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_net.py +0 -0
  408. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_people.py +0 -0
  409. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_quantity.py +0 -0
  410. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_rating.py +0 -0
  411. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_resolve.py +0 -0
  412. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_security.py +0 -0
  413. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_task.py +0 -0
  414. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facet_time.py +0 -0
  415. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facets_catalog.py +0 -0
  416. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facets_doc.py +0 -0
  417. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_facets_pkg.py +0 -0
  418. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_field.py +0 -0
  419. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_roles.py +0 -0
  420. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_roles_json.py +0 -0
  421. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_roles_of_facets.py +0 -0
  422. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sdl_vocab_version.py +0 -0
  423. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_search_provider.py +0 -0
  424. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_secret_scope_decorator.py +0 -0
  425. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_secret_spec_scope.py +0 -0
  426. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_skeleton_decorator.py +0 -0
  427. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_spec_validation.py +0 -0
  428. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_stage.py +0 -0
  429. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_surface_adaptation.py +0 -0
  430. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_sync_async_parity.py +0 -0
  431. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_transport_isolation.py +0 -0
  432. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_ui.py +0 -0
  433. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_ui_canvas.py +0 -0
  434. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_ui_fileupload_enhanced.py +0 -0
  435. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_ui_html.py +0 -0
  436. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_ui_image_enhanced.py +0 -0
  437. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_ui_modal.py +0 -0
  438. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_ui_open.py +0 -0
  439. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_ui_signals.py +0 -0
  440. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_ui_theme.py +0 -0
  441. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_user.py +0 -0
  442. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_v7_emit_refusal.py +0 -0
  443. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_validator.py +0 -0
  444. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_validator_drift.py +0 -0
  445. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_validator_pep563.py +0 -0
  446. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_validator_v1_6_0_rules.py +0 -0
  447. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_validator_v25.py +0 -0
  448. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/test_write_arg_bleed.py +0 -0
  449. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/tools/__init__.py +0 -0
  450. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/tools/test_generate_api_surface.py +0 -0
  451. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/tools/test_generate_reference.py +0 -0
  452. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/tools/test_reference_description.py +0 -0
  453. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/tools/test_reference_flags.py +0 -0
  454. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/tools/test_reference_typegraph.py +0 -0
  455. {imperal_sdk-6.3.7 → imperal_sdk-6.3.8}/tests/ui/test_input_type_enum.py +0 -0
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to `imperal-sdk` are documented here.
4
4
 
5
+ ## 6.3.8 — 2026-11-04
6
+
7
+ ### Fixed
8
+ - `code_index`: one string-aware reader of resolution configs (`strip_jsonc`, `parse_jsonc`, `parse_config`).
9
+ Comments and trailing commas are removed outside strings only -- a regex stripper read `"@/*"` in a Next.js
10
+ `tsconfig.json` as a comment opener, lost `paths`, and every `@/` import fell out of the graph. The Tenant Vault
11
+ carries a literal copy (a test compares the source).
12
+ - `sftp_list_tree` / `sftp_read_many` keep up to `SFTP_PARALLEL` (32) requests in flight on one connection: listing
13
+ walks level by level, reads go in slices. Live (Mac -> a US server, 1 572 files): listing 47 s -> 6.7 s, 200
14
+ files read 206 s -> 10.1 s. Results are the same (paths sorted; .gitignore rules still reach a directory's
15
+ children before they are filtered).
16
+
5
17
  ## 6.3.7 — 2026-10-21
6
18
 
7
19
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: imperal-sdk
3
- Version: 6.3.7
3
+ Version: 6.3.8
4
4
  Summary: SDK for building Imperal Cloud extensions
5
5
  Author: Imperal, Inc.
6
6
  Author-email: Valentin Scerbacov <valentin@imperal.io>
@@ -1,5 +1,5 @@
1
1
  {
2
- "sdk_version": "6.3.7",
2
+ "sdk_version": "6.3.8",
3
3
  "symbols": {
4
4
  "ActionResult": {
5
5
  "action_vocab_safe": false,
@@ -1,5 +1,5 @@
1
1
  {
2
- "_sdk_version": "6.3.7",
2
+ "_sdk_version": "6.3.8",
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.3.7"
4
+ __version__ = "6.3.8"
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
@@ -746,6 +746,100 @@ def indexable(rel_path: str) -> str | None:
746
746
  return "code" if os.path.splitext(low)[1] in INDEXABLE_EXT else None
747
747
 
748
748
 
749
+ # ---- resolution configs: the ONE reader (the vault's stores/repos.py carries a literal copy) ----
750
+
751
+ def strip_jsonc(text: str) -> str:
752
+ """JSON with comments (tsconfig, jsconfig) as plain JSON: ``//`` and ``/* */`` comments and trailing
753
+ commas removed OUTSIDE strings only. ``"@/*"`` or ``"**/*.ts"`` is text, never a comment (live 2026-11-03:
754
+ a regex stripper read imperal.io's tsconfig from ``"@/*"`` to ``"**/*.ts"`` as one comment, the JSON
755
+ broke, ``paths`` was lost and every ``@/`` import fell out of the vault graph)."""
756
+ n = len(text)
757
+
758
+ def skip(i: int) -> int:
759
+ """The index past whitespace and comments from ``i`` (outside strings)."""
760
+ while i < n:
761
+ if text[i] in " \t\r\n":
762
+ i += 1
763
+ elif text.startswith("//", i):
764
+ j = text.find("\n", i)
765
+ i = n if j < 0 else j
766
+ elif text.startswith("/*", i):
767
+ j = text.find("*/", i + 2)
768
+ i = n if j < 0 else j + 2
769
+ else:
770
+ break
771
+ return i
772
+
773
+ out: list = []
774
+ i = 0
775
+ while i < n:
776
+ c = text[i]
777
+ if c == '"':
778
+ j = i + 1
779
+ while j < n and text[j] != '"':
780
+ j += 2 if text[j] == "\\" else 1
781
+ out.append(text[i:j + 1])
782
+ i = j + 1
783
+ elif text.startswith("//", i) or text.startswith("/*", i):
784
+ i = skip(i)
785
+ out.append(" ")
786
+ elif c == "," and skip(i + 1) < n and text[skip(i + 1)] in "}]":
787
+ i += 1
788
+ else:
789
+ out.append(c)
790
+ i += 1
791
+ return "".join(out)
792
+
793
+
794
+ def parse_jsonc(text: str) -> dict:
795
+ """A JSON-with-comments object, or ``{}`` when it is not one."""
796
+ import json
797
+ try:
798
+ data = json.loads(strip_jsonc(text))
799
+ except ValueError:
800
+ return {}
801
+ return data if isinstance(data, dict) else {}
802
+
803
+
804
+ def parse_config(path: str, text: str) -> tuple:
805
+ """``(kind, data)`` of a resolution config: tsconfig / jsconfig (JSON with comments), pyproject.toml,
806
+ setup.cfg, package.json. What the linker needs, nothing else."""
807
+ import posixpath
808
+ name = posixpath.basename(_slashes(path)).lower()
809
+ if name == "pyproject.toml":
810
+ try:
811
+ import tomllib
812
+ data = tomllib.loads(text)
813
+ except Exception:
814
+ data = {}
815
+ st = (data.get("tool") or {}).get("setuptools") or {}
816
+ find = (st.get("packages") or {}).get("find") if isinstance(st.get("packages"), dict) else None
817
+ return "pyproject", {"where": list((find or {}).get("where") or []),
818
+ "package_dir": dict(st.get("package-dir") or {}),
819
+ "name": str((data.get("project") or {}).get("name") or "")}
820
+ if name == "setup.cfg":
821
+ import configparser
822
+ cp = configparser.ConfigParser()
823
+ try:
824
+ cp.read_string(text)
825
+ raw = cp.get("options", "package_dir", fallback="")
826
+ except Exception:
827
+ raw = ""
828
+ pdir = {}
829
+ for line in raw.replace(";", "\n").splitlines():
830
+ k, sep, v = line.partition("=")
831
+ if sep:
832
+ pdir[k.strip()] = v.strip()
833
+ return "setup_cfg", {"package_dir": pdir}
834
+ data = parse_jsonc(text)
835
+ if name == "package.json":
836
+ return "package_json", {"name": str(data.get("name") or ""), "main": str(data.get("main") or "")}
837
+ co = data.get("compilerOptions") or {}
838
+ return ("jsconfig" if name == "jsconfig.json" else "tsconfig"), {
839
+ "baseUrl": str(co.get("baseUrl") or ""),
840
+ "paths": {str(k): [str(x) for x in v or []] for k, v in (co.get("paths") or {}).items() if isinstance(v, list)}}
841
+
842
+
749
843
  # ---- the scope graph of one file (spec 4.6.1): defs, bindings with aliases, reference chains ----
750
844
 
751
845
  _CHAIN_PARTS = 6
@@ -1872,55 +1966,94 @@ async def sftp_repo_root(sftp, path: str) -> str:
1872
1966
  return manifest or start
1873
1967
 
1874
1968
 
1969
+ # SFTP requests in flight on one connection. Live 2026-11-03 (Mac -> whm-jump, /home/ipw-repo): one request at a
1970
+ # time listed 1 572 files in 47 s and read 200 files in 206 s (~4 round trips a file) -- a first sync of the kernel
1971
+ # repo would have taken half an hour. asyncssh pipelines requests on one channel; 32 keeps a slow link full without
1972
+ # flooding a small server's sftp-server.
1973
+ SFTP_PARALLEL = 32
1974
+
1975
+
1976
+ async def _gather_bounded(coros, limit: int = SFTP_PARALLEL) -> list:
1977
+ import asyncio
1978
+ gate = asyncio.Semaphore(limit)
1979
+
1980
+ async def one(c):
1981
+ async with gate:
1982
+ return await c
1983
+ return await asyncio.gather(*(one(c) for c in coros))
1984
+
1985
+
1875
1986
  async def sftp_list_tree(sftp, root: str, max_files: int = MAX_REPO_FILES) -> dict:
1876
1987
  """Every indexable file under ``root`` with its size and mtime: .gitignore files honoured, dotted /
1877
1988
  dependency / build trees and virtualenvs skipped, symlinks never followed (no loop, nothing outside
1878
- the root). ``{"items": [{path, size, mtime, kind}], "partial": str, "os"}``."""
1989
+ the root). ``{"items": [{path, size, mtime, kind}], "partial": str, "os"}``. Walked level by level:
1990
+ every directory of a level (and its .gitignore) is read at once; a directory's rules are known
1991
+ before its children are filtered, as in a one-by-one walk."""
1879
1992
  import posixpath
1880
1993
  items: list = []
1881
1994
  partial = ""
1882
1995
  rules: list = []
1883
- stack = [""]
1884
- while stack:
1885
- rel_dir = stack.pop()
1996
+ level = [""]
1997
+
1998
+ async def listed(rel_dir: str):
1886
1999
  here = posixpath.join(root, rel_dir) if rel_dir else root
1887
2000
  try:
1888
- entries = await sftp.readdir(here)
2001
+ return rel_dir, here, await sftp.readdir(here)
1889
2002
  except Exception:
1890
- partial = partial or f"unreadable directory: {rel_dir or '.'}"
1891
- continue
1892
- names = {e.filename for e in entries}
1893
- if rel_dir and "pyvenv.cfg" in names:
1894
- continue # a virtualenv, whatever it is named
1895
- if ".gitignore" in names:
1896
- try:
1897
- data = await _sftp_bytes(sftp, posixpath.join(here, ".gitignore"), 262144)
1898
- rules += gitignore_rules((data or b"").decode("utf-8", "replace"), rel_dir)
1899
- except Exception:
1900
- pass
1901
- for e in sorted(entries, key=lambda x: x.filename):
1902
- name = e.filename
1903
- if name in (".", ".."):
1904
- continue
1905
- rel = f"{rel_dir}/{name}" if rel_dir else name
1906
- kind = getattr(e.attrs, "type", None)
1907
- if kind == _SFTP_LINK:
2003
+ return rel_dir, here, None
2004
+
2005
+ async def ignore_file(here: str):
2006
+ try:
2007
+ return await _sftp_bytes(sftp, posixpath.join(here, ".gitignore"), 262144)
2008
+ except Exception:
2009
+ return None
2010
+
2011
+ while level and not (partial and partial.startswith("over ")):
2012
+ dirs = sorted(await _gather_bounded([listed(d) for d in level]), key=lambda x: x[0])
2013
+ readable = []
2014
+ for rel_dir, here, entries in dirs:
2015
+ if entries is None:
2016
+ partial = partial or f"unreadable directory: {rel_dir or '.'}"
1908
2017
  continue
1909
- if kind == _SFTP_DIR:
1910
- if name.startswith(".") or name in SKIP_DIRS or name.startswith("Program Files") \
1911
- or gitignored(rules, rel, True):
2018
+ names = {e.filename for e in entries}
2019
+ if rel_dir and "pyvenv.cfg" in names:
2020
+ continue # a virtualenv, whatever it is named
2021
+ readable.append((rel_dir, here, entries, ".gitignore" in names))
2022
+ ignores = await _gather_bounded([ignore_file(here) for _r, here, _e, has in readable if has])
2023
+ it = iter(ignores)
2024
+ for rel_dir, _here, _entries, has in readable:
2025
+ if has:
2026
+ data = next(it)
2027
+ if data is not None:
2028
+ rules += gitignore_rules(data.decode("utf-8", "replace"), rel_dir)
2029
+ level = []
2030
+ for rel_dir, _here, entries, _has in readable:
2031
+ for e in sorted(entries, key=lambda x: x.filename):
2032
+ name = e.filename
2033
+ if name in (".", ".."):
1912
2034
  continue
1913
- stack.append(rel)
1914
- continue
1915
- what = indexable(rel)
1916
- if not what or gitignored(rules, rel, False):
1917
- continue
1918
- if len(items) >= max_files:
1919
- partial = f"over {max_files} files"
1920
- stack = []
2035
+ rel = f"{rel_dir}/{name}" if rel_dir else name
2036
+ kind = getattr(e.attrs, "type", None)
2037
+ if kind == _SFTP_LINK:
2038
+ continue
2039
+ if kind == _SFTP_DIR:
2040
+ if name.startswith(".") or name in SKIP_DIRS or name.startswith("Program Files") \
2041
+ or gitignored(rules, rel, True):
2042
+ continue
2043
+ level.append(rel)
2044
+ continue
2045
+ what = indexable(rel)
2046
+ if not what or gitignored(rules, rel, False):
2047
+ continue
2048
+ if len(items) >= max_files:
2049
+ partial = f"over {max_files} files"
2050
+ level = []
2051
+ break
2052
+ items.append({"path": rel, "size": int(getattr(e.attrs, "size", 0) or 0),
2053
+ "mtime": float(getattr(e.attrs, "mtime", 0) or 0), "kind": what})
2054
+ if partial.startswith("over "):
1921
2055
  break
1922
- items.append({"path": rel, "size": int(getattr(e.attrs, "size", 0) or 0),
1923
- "mtime": float(getattr(e.attrs, "mtime", 0) or 0), "kind": what})
2056
+ items.sort(key=lambda i: i["path"])
1924
2057
  return {"items": items, "partial": partial, "os": sftp_os(root)}
1925
2058
 
1926
2059
 
@@ -1933,27 +2066,34 @@ async def sftp_read_many(sftp, root: str, paths: list, max_bytes: int = MAX_FILE
1933
2066
  skipped: list = []
1934
2067
  rest: list = []
1935
2068
  used = 0
2069
+ todo: list = []
1936
2070
  for rel in paths or []:
1937
2071
  full = _inside(root, str(rel))
1938
2072
  if full is None or not indexable(str(rel)):
1939
2073
  skipped.append(rel)
1940
- continue
1941
- if used >= batch_bytes:
1942
- rest.append(rel)
1943
- continue
2074
+ else:
2075
+ todo.append((rel, full))
2076
+
2077
+ async def one(rel, full):
1944
2078
  if not await _sftp_contained(sftp, root, full):
1945
- skipped.append(rel)
1946
- continue
2079
+ return rel, None
1947
2080
  try:
1948
- data = await _sftp_bytes(sftp, full, max_bytes)
2081
+ return rel, await _sftp_bytes(sftp, full, max_bytes)
1949
2082
  except Exception:
1950
- skipped.append(rel)
1951
- continue
1952
- if data is None:
1953
- skipped.append(rel)
1954
- continue
1955
- files[rel] = data
1956
- used += len(data)
2083
+ return rel, None
2084
+
2085
+ # read SFTP_PARALLEL files at once, a slice at a time: the batch cap is checked between slices (a batch may
2086
+ # end one slice over it, as a one-by-one read could end one file over it)
2087
+ for i in range(0, len(todo), SFTP_PARALLEL):
2088
+ if used >= batch_bytes:
2089
+ rest += [rel for rel, _full in todo[i:]]
2090
+ break
2091
+ for rel, data in await _gather_bounded([one(rel, full) for rel, full in todo[i:i + SFTP_PARALLEL]]):
2092
+ if data is None:
2093
+ skipped.append(rel)
2094
+ else:
2095
+ files[rel] = data
2096
+ used += len(data)
1957
2097
  return {"files": files, "skipped": skipped, "rest": rest, "os": sftp_os(root)}
1958
2098
 
1959
2099
 
@@ -0,0 +1,70 @@
1
+ """The one reader of resolution configs (tsconfig/jsconfig are JSON with comments): comments and trailing
2
+ commas go, strings stay whole -- live 2026-11-03, imperal.io's ``"@/*"`` was read as a comment opener."""
3
+ from imperal_sdk.code_index import parse_config, parse_jsonc, strip_jsonc
4
+
5
+ # imperal.io's own tsconfig.json (Next.js 16), verbatim in shape: "@/*" and "**/*.ts" in strings
6
+ NEXT_TSCONFIG = """{
7
+ "compilerOptions": {
8
+ "target": "ES2017",
9
+ "lib": ["dom", "dom.iterable", "esnext"],
10
+ "strict": true,
11
+ "plugins": [
12
+ {
13
+ "name": "next"
14
+ }
15
+ ],
16
+ "paths": {
17
+ "@/*": ["./src/*"]
18
+ }
19
+ },
20
+ "include": [
21
+ "next-env.d.ts",
22
+ "**/*.ts",
23
+ "**/*.tsx",
24
+ ".next/types/**/*.ts"
25
+ ],
26
+ "exclude": ["node_modules"]
27
+ }
28
+ """
29
+
30
+
31
+ def test_next_tsconfig_keeps_its_paths():
32
+ kind, data = parse_config("tsconfig.json", NEXT_TSCONFIG)
33
+ assert kind == "tsconfig"
34
+ assert data == {"baseUrl": "", "paths": {"@/*": ["./src/*"]}}
35
+
36
+
37
+ def test_comments_and_trailing_commas_go_outside_strings_only():
38
+ text = """{
39
+ // a line comment with "quotes" and /* inside
40
+ "compilerOptions": {
41
+ /* a block comment
42
+ over lines, with "@/*" text */
43
+ "baseUrl": ".", // after a value
44
+ "paths": {"~/*": ["src/*",], "url": ["https://example.com/a//b"],},
45
+ },
46
+ }"""
47
+ data = parse_jsonc(text)
48
+ assert data["compilerOptions"]["baseUrl"] == "."
49
+ assert data["compilerOptions"]["paths"] == {"~/*": ["src/*"], "url": ["https://example.com/a//b"]}
50
+
51
+
52
+ def test_escaped_quotes_and_backslashes_stay_inside_the_string():
53
+ text = '{"a": "say \\"/*\\" not a comment", "b": "c:\\\\dir\\\\", "c": 1,}'
54
+ assert parse_jsonc(text) == {"a": 'say "/*" not a comment', "b": "c:\\dir\\", "c": 1}
55
+
56
+
57
+ def test_a_comma_before_a_comment_then_a_brace_is_trailing():
58
+ assert parse_jsonc('{"a": [1, 2, /* end */ ], "b": 3, // last\n}') == {"a": [1, 2], "b": 3}
59
+
60
+
61
+ def test_not_an_object_is_empty():
62
+ assert parse_jsonc("[1, 2]") == {}
63
+ assert parse_jsonc("{ broken") == {}
64
+ assert strip_jsonc("") == ""
65
+
66
+
67
+ def test_package_json_and_jsconfig():
68
+ assert parse_config("web/package.json", '{"name": "web", "main": "index.js", // c\n}') == (
69
+ "package_json", {"name": "web", "main": "index.js"})
70
+ assert parse_config("jsconfig.json", '{"compilerOptions": {"baseUrl": "src"}}')[0] == "jsconfig"
@@ -468,3 +468,63 @@ def test_a_source_with_an_embedder_says_so_to_the_vault_and_one_without_never_do
468
468
  monkeypatch.setattr(ci, "_backend", lambda: None)
469
469
  asyncio.run(ci.sync_source(plan, apply, {"source": "t"}, listing, read))
470
470
  assert [m.get("embeds") for m in seen] == [True, None, None]
471
+
472
+
473
+ def test_sftp_listing_and_reads_run_in_parallel_with_the_same_result():
474
+ """live 2026-11-03 (Mac -> whm-jump): one SFTP request at a time listed 1 572 files in 47 s and read 200 in 206 s;
475
+ in flight together the same listing took 6.7 s and the reads 10.1 s. The result is the walk's, rules included."""
476
+ import asyncio
477
+ import time
478
+ from types import SimpleNamespace as NS
479
+
480
+ from imperal_sdk import code_index as ci
481
+
482
+ def ent(name, kind, size=10):
483
+ return NS(filename=name, attrs=NS(type=kind, size=size, mtime=1.0))
484
+ tree = {"/r": [ent(".gitignore", 1), ent("pkg", ci._SFTP_DIR), ent("gen", ci._SFTP_DIR), ent("top.py", 1)],
485
+ "/r/pkg": [ent(f"m{i}.py", 1) for i in range(60)] + [ent("sub", ci._SFTP_DIR), ent(".gitignore", 1)],
486
+ "/r/pkg/sub": [ent("keep.py", 1), ent("skip_me.py", 1)],
487
+ "/r/gen": [ent("out.py", 1)]}
488
+ files = {"/r/.gitignore": b"gen/\n", "/r/pkg/.gitignore": b"sub/skip_me.py\n",
489
+ **{f"/r/pkg/m{i}.py": b"x = 1\n" for i in range(60)}, "/r/top.py": b"y = 2\n"}
490
+ live = {"now": 0, "peak": 0}
491
+
492
+ class F:
493
+ def __init__(self, data):
494
+ self.data = data
495
+
496
+ async def __aenter__(self):
497
+ return self
498
+
499
+ async def __aexit__(self, *a):
500
+ return False
501
+
502
+ async def read(self, n=-1):
503
+ live["now"] += 1
504
+ live["peak"] = max(live["peak"], live["now"])
505
+ await asyncio.sleep(0.02)
506
+ live["now"] -= 1
507
+ return self.data
508
+
509
+ class S:
510
+ async def readdir(self, p):
511
+ await asyncio.sleep(0.02)
512
+ return tree[p]
513
+
514
+ async def realpath(self, p):
515
+ return p
516
+
517
+ def open(self, p, mode="rb"):
518
+ if p not in files:
519
+ raise OSError(p)
520
+ return F(files[p])
521
+ got = asyncio.run(ci.sftp_list_tree(S(), "/r"))
522
+ paths = [i["path"] for i in got["items"]]
523
+ assert paths == sorted(paths) and "top.py" in paths and "pkg/sub/keep.py" in paths and len(paths) == 62
524
+ assert "gen/out.py" not in paths and "pkg/sub/skip_me.py" not in paths # parent rules reach the children
525
+ t0 = time.monotonic()
526
+ many = asyncio.run(ci.sftp_read_many(S(), "/r", [p for p in paths if p.startswith("pkg/m")]))
527
+ assert len(many["files"]) == 60 and not many["skipped"] and not many["rest"]
528
+ assert live["peak"] > 1 and time.monotonic() - t0 < 60 * 0.02 # overlapped, not one by one
529
+ capped = asyncio.run(ci.sftp_read_many(S(), "/r", [p for p in paths if p.startswith("pkg/m")], batch_bytes=10))
530
+ assert capped["files"] and capped["rest"] and len(capped["files"]) + len(capped["rest"]) == 60
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes