alysis-code 0.13.3__tar.gz → 0.13.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (461) hide show
  1. {alysis_code-0.13.3 → alysis_code-0.13.4}/PKG-INFO +1 -1
  2. {alysis_code-0.13.3 → alysis_code-0.13.4}/docs/CHANGELOG.md +29 -0
  3. {alysis_code-0.13.3 → alysis_code-0.13.4}/pyproject.toml +1 -1
  4. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/__init__.py +1 -1
  5. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/config_flow.py +82 -2
  6. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/content.py +21 -5
  7. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/gemini_generate_content.py +234 -2
  8. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/openai_compat.py +19 -1
  9. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/model_registry.py +888 -73
  10. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/profile_presets.py +442 -234
  11. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/reasoning_contracts.py +162 -20
  12. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/web_search.py +3 -2
  13. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/web_search_provider_adapters.py +83 -17
  14. {alysis_code-0.13.3 → alysis_code-0.13.4}/.gitignore +0 -0
  15. {alysis_code-0.13.3 → alysis_code-0.13.4}/LICENSE +0 -0
  16. {alysis_code-0.13.3 → alysis_code-0.13.4}/NOTICE +0 -0
  17. {alysis_code-0.13.3 → alysis_code-0.13.4}/README.md +0 -0
  18. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/__main__.py +0 -0
  19. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/_build_info.py +0 -0
  20. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/account_login.py +0 -0
  21. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/README.md +0 -0
  22. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/__init__.py +0 -0
  23. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/acceptance_contract.py +0 -0
  24. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/blast_radius.py +0 -0
  25. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/cache_keepalive.py +0 -0
  26. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/completion_certificate.py +0 -0
  27. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/completion_gate.py +0 -0
  28. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/empty_response_stall.py +0 -0
  29. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/errors.py +0 -0
  30. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/llm_calls.py +0 -0
  31. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/mutation_classification.py +0 -0
  32. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/prompt_context.py +0 -0
  33. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/read_ledger.py +0 -0
  34. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/regression_baseline.py +0 -0
  35. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/reproduction_first.py +0 -0
  36. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/sensitive_output.py +0 -0
  37. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/session.py +0 -0
  38. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/steering.py +0 -0
  39. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/subagent_execution.py +0 -0
  40. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/subagent_workspace.py +0 -0
  41. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/tools_assembly.py +0 -0
  42. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/turn/__init__.py +0 -0
  43. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/turn/core.py +0 -0
  44. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/turn/events.py +0 -0
  45. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/turn/exploration.py +0 -0
  46. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/turn/interventions.py +0 -0
  47. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/turn/read_cache.py +0 -0
  48. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/turn/snapshot.py +0 -0
  49. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/turn_contract.py +0 -0
  50. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/turn_path.py +0 -0
  51. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/verification.py +0 -0
  52. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/verification_commands.py +0 -0
  53. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent/verification_evidence.py +0 -0
  54. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent_loop.py +0 -0
  55. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent_runtimes/__init__.py +0 -0
  56. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent_runtimes/base.py +0 -0
  57. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent_runtimes/builtins.py +0 -0
  58. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent_runtimes/codex_cli.py +0 -0
  59. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent_runtimes/host.py +0 -0
  60. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent_runtimes/registry.py +0 -0
  61. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agent_runtimes/service.py +0 -0
  62. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agentbox_client.py +0 -0
  63. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/agentbox_integration.py +0 -0
  64. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/alysis_cloud.py +0 -0
  65. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/approval_scope.py +0 -0
  66. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/README.md +0 -0
  67. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/__init__.py +0 -0
  68. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/asset_read_core.py +0 -0
  69. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/budget_allocator.py +0 -0
  70. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/comprehender.py +0 -0
  71. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/index.py +0 -0
  72. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/ingestion.py +0 -0
  73. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/legacy_migration.py +0 -0
  74. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/models.py +0 -0
  75. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/ocr.py +0 -0
  76. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-000.txt +0 -0
  77. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-001.txt +0 -0
  78. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-002.txt +0 -0
  79. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-003.txt +0 -0
  80. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-004.txt +0 -0
  81. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-005.txt +0 -0
  82. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-006.txt +0 -0
  83. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-007.txt +0 -0
  84. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-008.txt +0 -0
  85. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-009.txt +0 -0
  86. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-010.txt +0 -0
  87. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-011.txt +0 -0
  88. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-012.txt +0 -0
  89. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-013.txt +0 -0
  90. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-014.txt +0 -0
  91. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-015.txt +0 -0
  92. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-016.txt +0 -0
  93. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-017.txt +0 -0
  94. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-018.txt +0 -0
  95. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-019.txt +0 -0
  96. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/ascii/f-020.txt +0 -0
  97. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/index.html +0 -0
  98. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/owl/show-owl.sh +0 -0
  99. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/paths.py +0 -0
  100. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/plan_binding.py +0 -0
  101. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/planner_context.py +0 -0
  102. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/planner_tools.py +0 -0
  103. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/prompts.py +0 -0
  104. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/replanner_context.py +0 -0
  105. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/surface.py +0 -0
  106. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/untrusted_content.py +0 -0
  107. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/usage_logger.py +0 -0
  108. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/worker_mirror.py +0 -0
  109. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/worker_section.py +0 -0
  110. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/assets/worker_tools.py +0 -0
  111. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/atomic_io.py +0 -0
  112. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/auth_diagnostics.py +0 -0
  113. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/background_runner.py +0 -0
  114. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/branding.py +0 -0
  115. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/budget_policy.py +0 -0
  116. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/build_identity.py +0 -0
  117. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/builtin_hooks/__init__.py +0 -0
  118. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/builtin_hooks/notify_done_windows.py +0 -0
  119. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/bwrap_etc.py +0 -0
  120. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cancellation.py +0 -0
  121. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/capabilities.py +0 -0
  122. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/chatgpt_codex_static_provider.py +0 -0
  123. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli.py +0 -0
  124. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/__init__.py +0 -0
  125. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/assets_cli.py +0 -0
  126. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/assets_modal.py +0 -0
  127. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/chat/__init__.py +0 -0
  128. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/chat/commands.py +0 -0
  129. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/chat/loop.py +0 -0
  130. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/chat/mid_turn_policy.py +0 -0
  131. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/chat/rendering.py +0 -0
  132. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/chat/state.py +0 -0
  133. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/chat_resume.py +0 -0
  134. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/chat_slash_completer.py +0 -0
  135. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/__init__.py +0 -0
  136. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/_shared.py +0 -0
  137. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/auth.py +0 -0
  138. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/chat_resume_helpers.py +0 -0
  139. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/chat_state.py +0 -0
  140. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/chat_status.py +0 -0
  141. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/chat_terminal.py +0 -0
  142. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/chat_tui_panels.py +0 -0
  143. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/cli_common.py +0 -0
  144. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/cli_surface.py +0 -0
  145. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/config.py +0 -0
  146. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/conventions.py +0 -0
  147. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/execution_helpers.py +0 -0
  148. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/extensions.py +0 -0
  149. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/forge.py +0 -0
  150. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/forge_asset_view.py +0 -0
  151. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/forge_helpers.py +0 -0
  152. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/hooks.py +0 -0
  153. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/ide_bridge.py +0 -0
  154. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/mcp.py +0 -0
  155. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/profile.py +0 -0
  156. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/prompt_helpers.py +0 -0
  157. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/report.py +0 -0
  158. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/root.py +0 -0
  159. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/sandbox.py +0 -0
  160. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/server.py +0 -0
  161. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/sessions.py +0 -0
  162. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/skills.py +0 -0
  163. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/startup.py +0 -0
  164. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/tools.py +0 -0
  165. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/update.py +0 -0
  166. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/commands/welcome.py +0 -0
  167. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/config_menu.py +0 -0
  168. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/forge.py +0 -0
  169. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/forge_recovery.py +0 -0
  170. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/setup_wizard.py +0 -0
  171. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/__init__.py +0 -0
  172. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/app.py +0 -0
  173. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/config.py +0 -0
  174. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/config_overlay.py +0 -0
  175. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/footer.py +0 -0
  176. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/forge_status.py +0 -0
  177. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/markdown.py +0 -0
  178. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/owl.py +0 -0
  179. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/plan_meta.py +0 -0
  180. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/selection_bindings.py +0 -0
  181. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/setup_app.py +0 -0
  182. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/setup_flow.py +0 -0
  183. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/state.py +0 -0
  184. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/subagent_identity.py +0 -0
  185. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/subagent_panel.py +0 -0
  186. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/surface.py +0 -0
  187. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/transcript.py +0 -0
  188. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/update_prompt.py +0 -0
  189. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/cli_impl/tui/workspace_guard.py +0 -0
  190. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/clipboard.py +0 -0
  191. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/code_review.py +0 -0
  192. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/compaction/__init__.py +0 -0
  193. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/compaction/conversation_compactor.py +0 -0
  194. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/compaction/importance.py +0 -0
  195. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/compaction/settings.py +0 -0
  196. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/compaction/tool_output_offload.py +0 -0
  197. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/config.py +0 -0
  198. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/conflict_auto_resolver.py +0 -0
  199. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/context/__init__.py +0 -0
  200. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/context/tool_schema_budgeter.py +0 -0
  201. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/crash_diagnostics.py +0 -0
  202. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/custom_tools/README.md +0 -0
  203. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/custom_tools/__init__.py +0 -0
  204. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/custom_tools/discovery.py +0 -0
  205. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/custom_tools/runtime.py +0 -0
  206. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/custom_tools/session.py +0 -0
  207. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/custom_tools/trust.py +0 -0
  208. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/diff_paths.py +0 -0
  209. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/direction_change.py +0 -0
  210. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/dispatch_timing.py +0 -0
  211. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/durable_service_manager.py +0 -0
  212. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/edit_discipline.py +0 -0
  213. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/error_text.py +0 -0
  214. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/execution_budget.py +0 -0
  215. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/execution_context.py +0 -0
  216. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/execution_deadline.py +0 -0
  217. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/execution_shared.py +0 -0
  218. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/README.md +0 -0
  219. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/__init__.py +0 -0
  220. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/activation.py +0 -0
  221. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/install.py +0 -0
  222. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/manifest.py +0 -0
  223. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/models.py +0 -0
  224. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/paths.py +0 -0
  225. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/registry.json +0 -0
  226. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/registry.py +0 -0
  227. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/state.py +0 -0
  228. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/extensions/workspace_trust.py +0 -0
  229. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/failed_task_evidence.py +0 -0
  230. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/failure_category.py +0 -0
  231. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/feedback_report.py +0 -0
  232. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/file_classification.py +0 -0
  233. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/forge.py +0 -0
  234. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/forge_completion.py +0 -0
  235. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/forge_events.py +0 -0
  236. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/frontmatter_utils.py +0 -0
  237. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/git_evidence.py +0 -0
  238. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/git_ops.py +0 -0
  239. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/git_safe.py +0 -0
  240. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/git_worktrees.py +0 -0
  241. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/hooks/README.md +0 -0
  242. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/hooks/__init__.py +0 -0
  243. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/hooks/audit.py +0 -0
  244. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/hooks/config.py +0 -0
  245. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/hooks/dispatcher.py +0 -0
  246. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/hooks/models.py +0 -0
  247. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/hooks/trust.py +0 -0
  248. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/host_actions.py +0 -0
  249. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/host_browser.py +0 -0
  250. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/__init__.py +0 -0
  251. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/activity_events.py +0 -0
  252. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/approvals.py +0 -0
  253. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/artifacts.py +0 -0
  254. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/browser_egress_proxy.py +0 -0
  255. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/cdp_websocket_transport.py +0 -0
  256. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/change_ledger.py +0 -0
  257. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/context_blocks.py +0 -0
  258. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/event_stream.py +0 -0
  259. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/forge_protocol.py +0 -0
  260. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/forge_request_ledger.py +0 -0
  261. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/health.py +0 -0
  262. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/managed_browser.py +0 -0
  263. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/management_protocol.py +0 -0
  264. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/mcp_oauth_coordinator.py +0 -0
  265. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/mcp_oauth_lifecycle.py +0 -0
  266. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/prompt_queue.py +0 -0
  267. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/protocol.py +0 -0
  268. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/resumable_swarm.py +0 -0
  269. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/session_search.py +0 -0
  270. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/stdio_bridge.py +0 -0
  271. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/structured_state.py +0 -0
  272. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/ide/swarm_protocol.py +0 -0
  273. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/integration_gate.py +0 -0
  274. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/interactive_input_guard.py +0 -0
  275. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/interactive_plan_mode.py +0 -0
  276. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/internal_artifacts.py +0 -0
  277. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/knowledge_base.py +0 -0
  278. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/knowledge_capture.py +0 -0
  279. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/knowledge_librarian.py +0 -0
  280. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/language_policy.py +0 -0
  281. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/litellm_static_provider.py +0 -0
  282. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/__init__.py +0 -0
  283. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/anthropic_messages.py +0 -0
  284. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/base.py +0 -0
  285. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/cache_capabilities.py +0 -0
  286. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/cache_control_blocks.py +0 -0
  287. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/cache_policy.py +0 -0
  288. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/factory.py +0 -0
  289. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/gemini_interactions.py +0 -0
  290. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/metadata.py +0 -0
  291. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/openai_responses.py +0 -0
  292. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/protocols.py +0 -0
  293. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/provider_limits.py +0 -0
  294. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/request_plan.py +0 -0
  295. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/request_shape.py +0 -0
  296. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/streaming.py +0 -0
  297. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/temperature_compat.py +0 -0
  298. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/types.py +0 -0
  299. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm/usage_normalization.py +0 -0
  300. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/llm_error_display.py +0 -0
  301. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/logging_redaction.py +0 -0
  302. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/managed_host_deadline.py +0 -0
  303. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/README.md +0 -0
  304. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/__init__.py +0 -0
  305. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/client.py +0 -0
  306. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/config.py +0 -0
  307. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/errors.py +0 -0
  308. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/forge_scope.py +0 -0
  309. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/jsonrpc.py +0 -0
  310. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/manager.py +0 -0
  311. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/models.py +0 -0
  312. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/oauth.py +0 -0
  313. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/oauth_runtime.py +0 -0
  314. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/oauth_store.py +0 -0
  315. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/prompts.py +0 -0
  316. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/resources.py +0 -0
  317. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/roots.py +0 -0
  318. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/server_requests.py +0 -0
  319. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/token_store.py +0 -0
  320. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/transport_http.py +0 -0
  321. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/transport_stdio.py +0 -0
  322. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/mcp/untrusted_content.py +0 -0
  323. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/merge_conflict_reviewer.py +0 -0
  324. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/model_catalog/__init__.py +0 -0
  325. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/model_catalog/chatgpt_codex_subscription_snapshot.json +0 -0
  326. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/model_catalog/litellm_model_prices_snapshot.json +0 -0
  327. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/model_catalog/litellm_model_prices_snapshot.meta.json +0 -0
  328. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/model_metadata_policy.py +0 -0
  329. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/model_metadata_utils.py +0 -0
  330. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/model_router.py +0 -0
  331. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/permission_policy.py +0 -0
  332. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/personas.py +0 -0
  333. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/pipeline_facts.py +0 -0
  334. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/plan_assistant.py +0 -0
  335. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/plan_mode.py +0 -0
  336. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/plan_reconciliation.py +0 -0
  337. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/plan_repair.py +0 -0
  338. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/plan_validation.py +0 -0
  339. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/planning_constraints.py +0 -0
  340. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/policy.py +0 -0
  341. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/preview_server.py +0 -0
  342. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/process_reaping.py +0 -0
  343. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/profiles.py +0 -0
  344. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/provider_auth/__init__.py +0 -0
  345. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/provider_auth/base.py +0 -0
  346. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/provider_auth/openai_codex.py +0 -0
  347. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/provider_auth/registry.py +0 -0
  348. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/provider_auth/store.py +0 -0
  349. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/provider_diagnostics.py +0 -0
  350. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/provider_model_catalog.py +0 -0
  351. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/provider_telemetry.py +0 -0
  352. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/provider_url.py +0 -0
  353. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/remote_sync.py +0 -0
  354. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/replanning.py +0 -0
  355. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/repo_scan.py +0 -0
  356. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/request_estimation.py +0 -0
  357. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/review_gate.py +0 -0
  358. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/run_lock.py +0 -0
  359. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/run_outcome.py +0 -0
  360. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/run_provenance.py +0 -0
  361. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/run_state.py +0 -0
  362. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/runtime_artifacts.py +0 -0
  363. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/runtime_context_features.py +0 -0
  364. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/runtime_kind.py +0 -0
  365. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/safety/__init__.py +0 -0
  366. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/safety/mcp_sanitize.py +0 -0
  367. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/safety/safe_http.py +0 -0
  368. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/safety/subagent_report.py +0 -0
  369. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/sandbox_doctor.py +0 -0
  370. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/sandbox_runner.py +0 -0
  371. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/sandbox_settings.py +0 -0
  372. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/serialized_paths.py +0 -0
  373. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/server/__init__.py +0 -0
  374. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/server/app.py +0 -0
  375. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/server/auth.py +0 -0
  376. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/server/job_config.py +0 -0
  377. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/server/settings.py +0 -0
  378. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/server/store.py +0 -0
  379. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/server/worker_runner.py +0 -0
  380. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/service_persistence.py +0 -0
  381. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/session_artifacts.py +0 -0
  382. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/session_metrics.py +0 -0
  383. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/session_store.py +0 -0
  384. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/README.md +0 -0
  385. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/__init__.py +0 -0
  386. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/conventions.py +0 -0
  387. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/discovery.py +0 -0
  388. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/eval_models.py +0 -0
  389. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/eval_runner.py +0 -0
  390. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/evals.py +0 -0
  391. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/install.py +0 -0
  392. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/loader.py +0 -0
  393. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/matching.py +0 -0
  394. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/models.py +0 -0
  395. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/paths.py +0 -0
  396. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/prompting.py +0 -0
  397. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/scaffold.py +0 -0
  398. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/state.py +0 -0
  399. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/transactions.py +0 -0
  400. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/skills/validation.py +0 -0
  401. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/step_budget.py +0 -0
  402. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/subagent_labels.py +0 -0
  403. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/subagents.py +0 -0
  404. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/surface/__init__.py +0 -0
  405. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/surface/base.py +0 -0
  406. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/surface/console.py +0 -0
  407. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/surface/events.py +0 -0
  408. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/surface/hidden_surface.py +0 -0
  409. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/surface/noop_surface.py +0 -0
  410. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/surface/rich_surface.py +0 -0
  411. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/surface/styles.py +0 -0
  412. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/surface/theme.py +0 -0
  413. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/surface/types.py +0 -0
  414. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/swarm_backend.py +0 -0
  415. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/swarm_orchestrator.py +0 -0
  416. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/swarm_scheduler.py +0 -0
  417. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/swarm_trace.py +0 -0
  418. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/swarm_worker.py +0 -0
  419. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/swarm_write_guard.py +0 -0
  420. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/task_dependencies.py +0 -0
  421. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/task_readiness.py +0 -0
  422. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/task_scope.py +0 -0
  423. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/terminal_manager.py +0 -0
  424. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/terminal_ownership.py +0 -0
  425. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/text_normalization.py +0 -0
  426. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/token_budget.py +0 -0
  427. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/README.md +0 -0
  428. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/__init__.py +0 -0
  429. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/artifacts.py +0 -0
  430. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/availability.py +0 -0
  431. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/fs.py +0 -0
  432. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/git.py +0 -0
  433. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/history.py +0 -0
  434. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/http_timeout.py +0 -0
  435. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/image_generation.py +0 -0
  436. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/registry.py +0 -0
  437. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/repo_map.py +0 -0
  438. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/search.py +0 -0
  439. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/shell.py +0 -0
  440. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/symbols.py +0 -0
  441. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/test_discovery.py +0 -0
  442. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/web.py +0 -0
  443. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/web_search_dashscope.py +0 -0
  444. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/web_search_ddgs.py +0 -0
  445. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/tools/web_search_tavily.py +0 -0
  446. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/transport_retry.py +0 -0
  447. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/updates.py +0 -0
  448. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/usage_tracker.py +0 -0
  449. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/verification_command_analysis.py +0 -0
  450. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/verification_contract.py +0 -0
  451. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/verification_failure_summary.py +0 -0
  452. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/verification_repair.py +0 -0
  453. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/verify_gate.py +0 -0
  454. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/web_research.py +0 -0
  455. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/web_search_adapters.py +0 -0
  456. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/web_search_policy.py +0 -0
  457. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/workspace_binding.py +0 -0
  458. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/workspace_binding_ui.py +0 -0
  459. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/workspace_context.py +0 -0
  460. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/workspace_isolation.py +0 -0
  461. {alysis_code-0.13.3 → alysis_code-0.13.4}/src/alysis_code/workspace_provisioning.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alysis-code
3
- Version: 0.13.3
3
+ Version: 0.13.4
4
4
  Summary: Local CLI coding agent powered by any API.
5
5
  Project-URL: Changelog, https://github.com/AlysisAi/alysis-code/blob/main/docs/CHANGELOG.md
6
6
  Project-URL: Documentation, https://github.com/AlysisAi/alysis-code/tree/main/docs
@@ -408,6 +408,35 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
408
408
  Workspace-target extraction also keeps extensionless dotfiles such as `.npmrc` available to
409
409
  verification selection.
410
410
 
411
+ ## [0.13.4] - 2026-09-05
412
+
413
+ Model-catalog and TUI-access refresh.
414
+
415
+ ### Added
416
+
417
+ - Added GPT-6 Astra as the default OpenAI model, with aliases, pricing, context-window,
418
+ reasoning, OpenRouter, and ChatGPT-subscription metadata.
419
+ - Added newly available first-party and gateway routes for Claude Fable 5.1, Gemini 3.8
420
+ Flash, Qwen 3.8, GLM-5.3, Kimi K3, Doubao Seed 2.1, DeepSeek V4 snapshots, Grok 4.6,
421
+ and related hosted variants.
422
+
423
+ ### Changed
424
+
425
+ - Refreshed every hosted preset's model picker, aliases, validation model, retirement
426
+ mappings, pricing, context limits, and reasoning contracts against provider catalogs.
427
+ - Updated TUI model labels to preserve vendor naming and made profile pickers show each
428
+ profile's model, host, active state, retired-model state, and duplicates.
429
+ - Migrated the Perplexity preset from the retiring Sonar Chat Completions endpoint to the
430
+ Agent API, including hosted web search and saved-profile migration.
431
+ - Replaced the OpenAI economy and validation model with GPT-5.6 Luna and kept
432
+ GPT-5.3 Codex limited to the Responses preset.
433
+
434
+ ### Fixed
435
+
436
+ - OpenAI Chat Completions now uses `max_completion_tokens` for GPT-5 and newer models.
437
+ - Native Gemini tool and response schemas are projected onto Gemini's supported OpenAPI
438
+ subset before requests are sent.
439
+
411
440
  ## [0.13.3] - 2026-08-28
412
441
 
413
442
  ### Fixed
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "alysis-code"
7
- version = "0.13.3"
7
+ version = "0.13.4"
8
8
  description = "Local CLI coding agent powered by any API."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,3 +1,3 @@
1
1
  __all__ = ["__version__"]
2
2
 
3
- __version__ = "0.13.3"
3
+ __version__ = "0.13.4"
@@ -37,6 +37,8 @@ from ...config import (
37
37
  from ...llm.protocols import validate_reasoning_trace_adapter_for_protocol
38
38
  from ...profile_presets import (
39
39
  PROFILE_PRESETS,
40
+ canonical_model_alias_for_preset,
41
+ find_preset_for_profile,
40
42
  make_profile_from_preset,
41
43
  preset_selection_label,
42
44
  )
@@ -184,6 +186,75 @@ def _short_preset_description(preset: Any) -> str:
184
186
  return host or "any OpenAI-compatible base URL"
185
187
 
186
188
 
189
+ def _profile_identity(raw: Any) -> tuple[str, str, str]:
190
+ """(protocol, normalized base URL, casefolded model) for duplicate detection."""
191
+ profile = raw if isinstance(raw, dict) else {}
192
+ protocol = str(profile.get("protocol") or "openai_compat").strip()
193
+ base_url = str(profile.get("base_url") or "").strip().rstrip("/")
194
+ model = str(profile.get("default_model") or "").strip().casefold()
195
+ return protocol, base_url, model
196
+
197
+
198
+ def _profile_retired_model_replacement(name: str, raw: Any) -> str:
199
+ """The catalog's replacement id when a saved profile pins a retired model id.
200
+
201
+ Empty when the model is current, unknown, or the profile matches no
202
+ preset (custom endpoints cannot be judged offline).
203
+ """
204
+ profile = raw if isinstance(raw, dict) else {}
205
+ model = str(profile.get("default_model") or "").strip()
206
+ if not model:
207
+ return ""
208
+ try:
209
+ spec = ProfileSpec(
210
+ name=name,
211
+ protocol=str(profile.get("protocol") or "openai_compat").strip(),
212
+ base_url=str(profile.get("base_url") or "").strip(),
213
+ default_model=model,
214
+ )
215
+ preset = find_preset_for_profile(spec)
216
+ except Exception: # noqa: BLE001 - a malformed saved profile must not break the picker
217
+ return ""
218
+ if preset is None:
219
+ return ""
220
+ canonical = canonical_model_alias_for_preset(preset, model)
221
+ return canonical if canonical != model else ""
222
+
223
+
224
+ def _profile_row_descriptions(profiles: dict[str, Any], *, active: str | None) -> dict[str, str]:
225
+ """One summary line per saved profile: ``model · host`` plus what needs attention.
226
+
227
+ The bare name list hid everything that matters when choosing or pruning a
228
+ profile — which model it pins, which endpoint it hits, whether that model
229
+ id has been retired (the catalog will remap it, but the profile should be
230
+ updated), and whether it duplicates another profile.
231
+ """
232
+ identities: dict[tuple[str, str, str], list[str]] = {}
233
+ for name in sorted(profiles):
234
+ identities.setdefault(_profile_identity(profiles[name]), []).append(name)
235
+
236
+ descriptions: dict[str, str] = {}
237
+ for name in sorted(profiles):
238
+ raw = profiles[name]
239
+ profile = raw if isinstance(raw, dict) else {}
240
+ model = str(profile.get("default_model") or "").strip()
241
+ host = urlparse(str(profile.get("base_url") or "").strip()).netloc
242
+ parts: list[str] = []
243
+ if name == active:
244
+ parts.append("active")
245
+ parts.append(model or "no model")
246
+ if host:
247
+ parts.append(host)
248
+ replacement = _profile_retired_model_replacement(name, raw)
249
+ if replacement:
250
+ parts.append(f"retired → {replacement}")
251
+ twins = [other for other in identities.get(_profile_identity(raw), []) if other != name]
252
+ if twins and model:
253
+ parts.append(f"same as {twins[0]}")
254
+ descriptions[name] = " · ".join(parts)
255
+ return descriptions
256
+
257
+
187
258
  # stage → interaction mode, so the overlay's key-binding filters don't have to
188
259
  # build a full :class:`Screen` on every repaint.
189
260
  _STAGE_MODE: dict[str, Mode] = {
@@ -1479,10 +1550,13 @@ class ConfigFlow:
1479
1550
  )
1480
1551
 
1481
1552
  def _screen_provider_switch(self) -> Screen:
1553
+ descriptions = _profile_row_descriptions(
1554
+ self.state.profiles, active=self.state.active_profile
1555
+ )
1482
1556
  rows = [
1483
1557
  Row(
1484
1558
  label=name,
1485
- description="active" if name == self.state.active_profile else "",
1559
+ description=descriptions.get(name, ""),
1486
1560
  value=name,
1487
1561
  current=name == self.state.active_profile,
1488
1562
  )
@@ -1609,7 +1683,13 @@ class ConfigFlow:
1609
1683
  )
1610
1684
 
1611
1685
  def _screen_provider_remove(self) -> Screen:
1612
- rows = [Row(label=name, value=name) for name in sorted(self.state.profiles)]
1686
+ descriptions = _profile_row_descriptions(
1687
+ self.state.profiles, active=self.state.active_profile
1688
+ )
1689
+ rows = [
1690
+ Row(label=name, description=descriptions.get(name, ""), value=name)
1691
+ for name in sorted(self.state.profiles)
1692
+ ]
1613
1693
  return Screen(
1614
1694
  stage="provider_remove",
1615
1695
  mode="list",
@@ -35,11 +35,18 @@ _ACRONYMS = {
35
35
  }
36
36
 
37
37
 
38
+ # Families whose vendors hyphenate the version onto the name ("GPT-6 Astra",
39
+ # "GPT-5.6 Terra", "GLM-5.3"). Everything else keeps a space ("Gemini 3.8
40
+ # Flash", "Claude Opus 5", "Kimi K3"), which matches those vendors' naming.
41
+ _HYPHENATED_VERSION_FAMILIES = frozenset({"GPT", "GLM"})
42
+
43
+
38
44
  def pretty_model_label(model: str | None) -> str:
39
45
  """Turn a raw model id into a friendly footer label.
40
46
 
41
- ``deepseek-chat`` -> ``DeepSeek Chat``; ``gpt-4o`` -> ``GPT 4o``. Falls back
42
- to the raw id when there is nothing sensible to do.
47
+ ``deepseek-chat`` -> ``DeepSeek Chat``; ``gpt-6-astra`` -> ``GPT-6 Astra``;
48
+ ``gpt-4o`` -> ``GPT-4o``. Falls back to the raw id when there is nothing
49
+ sensible to do.
43
50
  """
44
51
  raw = (model or "").strip()
45
52
  if not raw:
@@ -50,11 +57,20 @@ def pretty_model_label(model: str | None) -> str:
50
57
  for token in tokens:
51
58
  low = token.lower()
52
59
  if low in _ACRONYMS:
53
- out.append(_ACRONYMS[low])
60
+ word = _ACRONYMS[low]
54
61
  elif token.isupper():
55
- out.append(token)
62
+ word = token
56
63
  else:
57
- out.append(token[:1].upper() + token[1:])
64
+ word = token[:1].upper() + token[1:]
65
+ if out and out[-1] in _HYPHENATED_VERSION_FAMILIES and word[:1].isdigit():
66
+ out[-1] = f"{out[-1]}-{word}"
67
+ continue
68
+ # Ids that cannot carry a dot spell "5.1" as "5-1" (claude-fable-5-1,
69
+ # doubao-seed-2-1-pro): two adjacent bare numbers are one version.
70
+ if out and out[-1].isdigit() and word.isdigit():
71
+ out[-1] = f"{out[-1]}.{word}"
72
+ continue
73
+ out.append(word)
58
74
  return " ".join(out) or raw
59
75
 
60
76
 
@@ -447,6 +447,232 @@ class _GeminiToolMapping:
447
447
  include_server_side_tool_invocations: bool
448
448
 
449
449
 
450
+ # Gemini's ``Schema`` message is an OpenAPI 3.0 subset, not JSON Schema. Any
451
+ # other keyword is a hard 400 ("Unknown name ... Cannot find field"), and the
452
+ # tool registry, MCP servers and custom tools all emit plain JSON Schema
453
+ # (``additionalProperties``, ``uniqueItems``, ``$ref`` ...). Everything not in
454
+ # this set is dropped or rewritten before the declaration leaves the client.
455
+ _GEMINI_SCHEMA_FIELDS: frozenset[str] = frozenset(
456
+ {
457
+ "type",
458
+ "format",
459
+ "title",
460
+ "description",
461
+ "nullable",
462
+ "enum",
463
+ "maxItems",
464
+ "minItems",
465
+ "properties",
466
+ "required",
467
+ "minProperties",
468
+ "maxProperties",
469
+ "minLength",
470
+ "maxLength",
471
+ "pattern",
472
+ "example",
473
+ "anyOf",
474
+ "propertyOrdering",
475
+ "default",
476
+ "items",
477
+ "minimum",
478
+ "maximum",
479
+ }
480
+ )
481
+ # ``format`` is validated per type; unknown values are rejected outright.
482
+ _GEMINI_SCHEMA_FORMATS: dict[str, frozenset[str]] = {
483
+ "string": frozenset({"date-time", "enum"}),
484
+ "number": frozenset({"float", "double"}),
485
+ "integer": frozenset({"int32", "int64"}),
486
+ }
487
+ _GEMINI_SCHEMA_TYPES: frozenset[str] = frozenset(
488
+ {"string", "number", "integer", "boolean", "array", "object", "null"}
489
+ )
490
+ _GEMINI_SCHEMA_MAX_DEPTH = 32
491
+
492
+
493
+ def _resolve_local_schema_ref(ref: str, root: dict[str, Any]) -> dict[str, Any] | None:
494
+ """Resolve ``#/$defs/x`` / ``#/definitions/x`` style pointers inside ``root``."""
495
+ if not ref.startswith("#/"):
496
+ return None
497
+ node: Any = root
498
+ for raw_part in ref[2:].split("/"):
499
+ part = raw_part.replace("~1", "/").replace("~0", "~")
500
+ if not isinstance(node, dict) or part not in node:
501
+ return None
502
+ node = node[part]
503
+ return node if isinstance(node, dict) else None
504
+
505
+
506
+ def _gemini_schema(
507
+ schema: Any,
508
+ *,
509
+ root: dict[str, Any] | None = None,
510
+ depth: int = 0,
511
+ ) -> dict[str, Any]:
512
+ """Project an arbitrary JSON Schema onto Gemini's ``Schema`` subset.
513
+
514
+ Unknown keywords are dropped; ``const`` becomes a one-value ``enum``;
515
+ ``oneOf`` becomes ``anyOf``; a single-branch ``allOf`` is merged; union
516
+ ``type`` lists become ``nullable`` + ``anyOf``; local ``$ref`` pointers are
517
+ inlined; ``required`` is trimmed to declared properties; ``format`` values
518
+ Gemini does not validate are removed.
519
+ """
520
+ if not isinstance(schema, dict):
521
+ return {}
522
+ if depth > _GEMINI_SCHEMA_MAX_DEPTH:
523
+ return {}
524
+ root_schema = root if root is not None else schema
525
+
526
+ ref = schema.get("$ref")
527
+ if isinstance(ref, str):
528
+ target = _resolve_local_schema_ref(ref, root_schema)
529
+ merged: dict[str, Any] = dict(target or {})
530
+ merged.update({key: value for key, value in schema.items() if key != "$ref"})
531
+ if target is None and len(merged) == 0:
532
+ return {}
533
+ return _gemini_schema(merged, root=root_schema, depth=depth + 1)
534
+
535
+ working: dict[str, Any] = dict(schema)
536
+ all_of = working.pop("allOf", None)
537
+ if isinstance(all_of, list):
538
+ branches = [branch for branch in all_of if isinstance(branch, dict)]
539
+ if len(branches) == 1:
540
+ merged_all = dict(branches[0])
541
+ merged_all.update(working)
542
+ working = merged_all
543
+ one_of = working.pop("oneOf", None)
544
+ if isinstance(one_of, list) and "anyOf" not in working:
545
+ working["anyOf"] = one_of
546
+ if "const" in working and "enum" not in working:
547
+ working["enum"] = [working["const"]]
548
+ working.pop("const", None)
549
+
550
+ out: dict[str, Any] = {}
551
+ raw_type = working.get("type")
552
+ nullable = bool(working.get("nullable"))
553
+ resolved_type: str | None = None
554
+ if isinstance(raw_type, list):
555
+ candidates = [str(item).strip().lower() for item in raw_type if isinstance(item, str)]
556
+ if "null" in candidates:
557
+ nullable = True
558
+ non_null = [item for item in candidates if item != "null" and item in _GEMINI_SCHEMA_TYPES]
559
+ if len(non_null) == 1:
560
+ resolved_type = non_null[0]
561
+ elif len(non_null) > 1 and "anyOf" not in working:
562
+ working["anyOf"] = [{"type": item} for item in non_null]
563
+ elif isinstance(raw_type, str):
564
+ candidate = raw_type.strip().lower()
565
+ if candidate == "null":
566
+ nullable = True
567
+ elif candidate in _GEMINI_SCHEMA_TYPES:
568
+ resolved_type = candidate
569
+ if resolved_type is not None:
570
+ out["type"] = resolved_type
571
+ if nullable:
572
+ out["nullable"] = True
573
+
574
+ for key in ("title", "description", "pattern"):
575
+ value = working.get(key)
576
+ if isinstance(value, str) and value:
577
+ out[key] = value
578
+ for key in (
579
+ "minItems",
580
+ "maxItems",
581
+ "minProperties",
582
+ "maxProperties",
583
+ "minLength",
584
+ "maxLength",
585
+ ):
586
+ value = working.get(key)
587
+ if isinstance(value, int) and not isinstance(value, bool) and value >= 0:
588
+ out[key] = value
589
+ for key in ("minimum", "maximum"):
590
+ value = working.get(key)
591
+ if isinstance(value, (int, float)) and not isinstance(value, bool):
592
+ out[key] = value
593
+ if "default" in working and working["default"] is not None:
594
+ out["default"] = copy.deepcopy(working["default"])
595
+ if "example" in working and working["example"] is not None:
596
+ out["example"] = copy.deepcopy(working["example"])
597
+
598
+ fmt = working.get("format")
599
+ if isinstance(fmt, str) and resolved_type in _GEMINI_SCHEMA_FORMATS:
600
+ if fmt in _GEMINI_SCHEMA_FORMATS[resolved_type]:
601
+ out["format"] = fmt
602
+
603
+ enum_values = working.get("enum")
604
+ if isinstance(enum_values, list) and enum_values:
605
+ if resolved_type in {None, "string"}:
606
+ out["enum"] = [str(value) for value in enum_values]
607
+ out["type"] = "string"
608
+ else:
609
+ # Gemini only validates enums on strings; keep the value list
610
+ # visible to the model through the description instead.
611
+ rendered = ", ".join(str(value) for value in enum_values)
612
+ hint = f"Allowed values: {rendered}"
613
+ out["description"] = (
614
+ f"{out['description']} ({hint})" if out.get("description") else hint
615
+ )
616
+
617
+ properties = working.get("properties")
618
+ if isinstance(properties, dict):
619
+ clean_properties: dict[str, Any] = {}
620
+ for prop_name, prop_schema in properties.items():
621
+ if not isinstance(prop_name, str) or not prop_name:
622
+ continue
623
+ clean_properties[prop_name] = _gemini_schema(
624
+ prop_schema if isinstance(prop_schema, dict) else {},
625
+ root=root_schema,
626
+ depth=depth + 1,
627
+ )
628
+ if clean_properties:
629
+ out["properties"] = clean_properties
630
+ required = working.get("required")
631
+ if isinstance(required, list):
632
+ kept = [
633
+ name for name in required if isinstance(name, str) and name in clean_properties
634
+ ]
635
+ if kept:
636
+ out["required"] = kept
637
+ ordering = working.get("propertyOrdering")
638
+ if isinstance(ordering, list):
639
+ kept_order = [
640
+ name for name in ordering if isinstance(name, str) and name in clean_properties
641
+ ]
642
+ if kept_order:
643
+ out["propertyOrdering"] = kept_order
644
+
645
+ items = working.get("items")
646
+ if isinstance(items, list):
647
+ items = items[0] if items and isinstance(items[0], dict) else None
648
+ if isinstance(items, dict):
649
+ out["items"] = _gemini_schema(items, root=root_schema, depth=depth + 1)
650
+ elif out.get("type") == "array":
651
+ # Gemini requires ``items`` on arrays; an untyped item schema is the
652
+ # closest expression of JSON Schema's "anything".
653
+ out["items"] = {}
654
+
655
+ any_of = working.get("anyOf")
656
+ if isinstance(any_of, list):
657
+ branches = [
658
+ _gemini_schema(branch, root=root_schema, depth=depth + 1)
659
+ for branch in any_of
660
+ if isinstance(branch, dict)
661
+ ]
662
+ # A ``{"type": "null"}`` branch is Gemini's ``nullable`` flag.
663
+ if any(branch == {"nullable": True} for branch in branches):
664
+ out["nullable"] = True
665
+ branches = [branch for branch in branches if branch != {"nullable": True}]
666
+ if len(branches) == 1:
667
+ single = branches[0]
668
+ for key, value in single.items():
669
+ out.setdefault(key, value)
670
+ elif branches:
671
+ out["anyOf"] = branches
672
+
673
+ return {key: value for key, value in out.items() if key in _GEMINI_SCHEMA_FIELDS}
674
+
675
+
450
676
  def _gemini_function_declaration_from_chat_tool(tool: dict[str, Any]) -> dict[str, Any] | None:
451
677
  if not isinstance(tool, dict):
452
678
  return None
@@ -460,9 +686,13 @@ def _gemini_function_declaration_from_chat_tool(tool: dict[str, Any]) -> dict[st
460
686
  name = str(source.get("name") or "").strip()
461
687
  if not name:
462
688
  return None
689
+ raw_parameters = source.get("parameters")
690
+ parameters = _gemini_schema(raw_parameters) if isinstance(raw_parameters, dict) else {}
691
+ if not parameters.get("type"):
692
+ parameters["type"] = "object"
463
693
  declaration: dict[str, Any] = {
464
694
  "name": name,
465
- "parameters": copy.deepcopy(source.get("parameters") or {"type": "object"}),
695
+ "parameters": parameters,
466
696
  }
467
697
  description = str(source.get("description") or "").strip()
468
698
  if description:
@@ -2574,7 +2804,9 @@ def _gemini_response_format(response_format: dict[str, Any] | None) -> dict[str,
2574
2804
  )
2575
2805
  return {
2576
2806
  "responseMimeType": "application/json",
2577
- "responseSchema": copy.deepcopy(schema),
2807
+ # responseSchema is the same OpenAPI-subset ``Schema`` message as
2808
+ # function parameters, so it needs the same projection.
2809
+ "responseSchema": _gemini_schema(schema),
2578
2810
  }
2579
2811
  if response_type == "text":
2580
2812
  return {}
@@ -421,6 +421,24 @@ def _is_moonshot_provider(provider_key: str | None) -> bool:
421
421
  return _normalize_provider_key(provider_key) in {_MOONSHOT_PROVIDER_KEY, "kimi_code"}
422
422
 
423
423
 
424
+ # Routes whose Chat Completions surface wants ``max_completion_tokens``.
425
+ # OpenAI's gpt-5 / o-series reject the legacy ``max_tokens`` outright
426
+ # ("Unsupported parameter: 'max_tokens' is not supported with this model"),
427
+ # and OpenAI accepts ``max_completion_tokens`` on every chat model, so the
428
+ # first-party host (and Azure, which mirrors it) always uses the new field.
429
+ # The decision is keyed on the endpoint host, not on a provider inferred from
430
+ # a ``gpt-*`` model name: an unknown OpenAI-compatible gateway serving such a
431
+ # model may only implement ``max_tokens``.
432
+ _MAX_COMPLETION_TOKENS_HOST_PROVIDERS = frozenset({"openai", "azure"})
433
+
434
+
435
+ def _uses_max_completion_tokens(provider_key: str | None, *, base_url: str | None) -> bool:
436
+ if _is_moonshot_provider(provider_key):
437
+ return True
438
+ host_provider = _normalize_provider_key(_provider_key_from_base_url(base_url))
439
+ return host_provider in _MAX_COMPLETION_TOKENS_HOST_PROVIDERS
440
+
441
+
424
442
  def _is_nvidia_provider(provider_key: str | None) -> bool:
425
443
  return _normalize_provider_key(provider_key) == _NVIDIA_PROVIDER_KEY
426
444
 
@@ -2130,7 +2148,7 @@ class OpenAICompatClient:
2130
2148
  if max_tokens is not None:
2131
2149
  output_limit_field = (
2132
2150
  "max_completion_tokens"
2133
- if _is_moonshot_provider(transport_provider_key)
2151
+ if _uses_max_completion_tokens(transport_provider_key, base_url=self.base_url)
2134
2152
  else "max_tokens"
2135
2153
  )
2136
2154
  payload[output_limit_field] = int(max_tokens)