kon-coding-agent 0.3.7__tar.gz → 0.3.9__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 (182) hide show
  1. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/AGENTS.md +4 -0
  2. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/CHANGELOG.md +66 -0
  3. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/PKG-INFO +17 -7
  4. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/README.md +14 -5
  5. kon_coding_agent-0.3.9/docs/images/kon-screenshot.png +0 -0
  6. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/pyproject.toml +3 -2
  7. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/config.py +27 -0
  8. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/core/types.py +5 -2
  9. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/defaults/config.toml +10 -12
  10. kon_coding_agent-0.3.9/src/kon/git_branch.py +90 -0
  11. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/__init__.py +3 -19
  12. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/base.py +1 -0
  13. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/models.py +19 -1
  14. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/oauth/__init__.py +2 -0
  15. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/oauth/copilot.py +4 -0
  16. kon_coding_agent-0.3.9/src/kon/llm/providers/__init__.py +61 -0
  17. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/providers/copilot.py +0 -4
  18. kon_coding_agent-0.3.9/src/kon/llm/providers/openai_codex_responses.py +509 -0
  19. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/providers/openai_compat.py +1 -1
  20. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/providers/openai_completions.py +20 -2
  21. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/loop.py +11 -4
  22. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/runtime.py +62 -30
  23. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/session.py +88 -16
  24. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/themes.py +44 -13
  25. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/base.py +1 -0
  26. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/bash.py +48 -37
  27. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/edit.py +1 -0
  28. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/find.py +1 -0
  29. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/grep.py +1 -0
  30. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/read.py +1 -0
  31. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/web_fetch.py +113 -19
  32. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/web_search.py +1 -0
  33. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/write.py +3 -0
  34. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/turn.py +28 -27
  35. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/app.py +294 -50
  36. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/app_protocol.py +1 -5
  37. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/autocomplete.py +15 -17
  38. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/blocks.py +136 -24
  39. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/chat.py +104 -33
  40. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/commands.py +143 -20
  41. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/floating_list.py +24 -7
  42. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/input.py +50 -3
  43. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/selection_mode.py +2 -0
  44. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/session_ui.py +19 -20
  45. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/styles.py +18 -2
  46. kon_coding_agent-0.3.9/src/kon/ui/terminal_image.py +34 -0
  47. kon_coding_agent-0.3.9/src/kon/ui/tool_output.py +34 -0
  48. kon_coding_agent-0.3.9/src/kon/ui/tree.py +437 -0
  49. kon_coding_agent-0.3.9/src/kon/ui/welcome.py +51 -0
  50. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/widgets.py +39 -24
  51. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/llm/test_mock_provider.py +1 -1
  52. kon_coding_agent-0.3.9/tests/llm/test_openai_codex_provider_errors.py +371 -0
  53. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_agentic_loop.py +75 -2
  54. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_compaction.py +1 -1
  55. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_config_migration.py +51 -2
  56. kon_coding_agent-0.3.9/tests/test_git_branch.py +84 -0
  57. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_handoff.py +1 -1
  58. kon_coding_agent-0.3.9/tests/test_llm_lazy_imports.py +46 -0
  59. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_model_provider_resolution.py +7 -0
  60. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_openai_compat.py +32 -0
  61. kon_coding_agent-0.3.9/tests/test_runtime_switch_model.py +213 -0
  62. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_session_persistence.py +55 -0
  63. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_session_resume.py +1 -1
  64. kon_coding_agent-0.3.9/tests/test_session_tree.py +43 -0
  65. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_system_prompt.py +7 -1
  66. kon_coding_agent-0.3.9/tests/tools/test_bash_truncation.py +86 -0
  67. kon_coding_agent-0.3.9/tests/tools/test_web_fetch.py +139 -0
  68. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_autocomplete.py +6 -4
  69. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_info_bar_permissions.py +14 -3
  70. kon_coding_agent-0.3.9/tests/ui/test_input_approval_submit.py +47 -0
  71. kon_coding_agent-0.3.9/tests/ui/test_input_cursor_theme.py +19 -0
  72. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_keybindings.py +3 -2
  73. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_permissions_command.py +5 -5
  74. kon_coding_agent-0.3.9/tests/ui/test_queue_editing.py +154 -0
  75. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_shell_command_detection.py +39 -14
  76. kon_coding_agent-0.3.9/tests/ui/test_streaming_blocks.py +69 -0
  77. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_thinking_notifications_commands.py +6 -6
  78. kon_coding_agent-0.3.9/tests/ui/test_tool_output_expansion.py +67 -0
  79. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/uv.lock +277 -260
  80. kon_coding_agent-0.3.7/docs/architecture-review.md +0 -306
  81. kon_coding_agent-0.3.7/docs/code-health-scan.md +0 -144
  82. kon_coding_agent-0.3.7/docs/images/kon-screenshot.png +0 -0
  83. kon_coding_agent-0.3.7/micro +0 -0
  84. kon_coding_agent-0.3.7/src/kon/llm/providers/__init__.py +0 -57
  85. kon_coding_agent-0.3.7/src/kon/llm/providers/openai_codex_responses.py +0 -344
  86. kon_coding_agent-0.3.7/src/kon/ui/welcome.py +0 -85
  87. kon_coding_agent-0.3.7/tests/llm/test_openai_codex_provider_errors.py +0 -13
  88. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/.github/workflows/test.yml +0 -0
  89. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/.gitignore +0 -0
  90. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/.kon/skills/kon-release-publish/SKILL.md +0 -0
  91. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/.kon/skills/kon-tmux-test/SKILL.md +0 -0
  92. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/.kon/skills/kon-tmux-test/run-e2e-tests.sh +0 -0
  93. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/.kon/skills/kon-tmux-test/setup-test-project.sh +0 -0
  94. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/.python-version +0 -0
  95. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/LICENSE +0 -0
  96. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/docs/e2e-test-coverage-review.md +0 -0
  97. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/docs/local-models.md +0 -0
  98. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/scripts/show_themes.py +0 -0
  99. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/__init__.py +0 -0
  100. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/async_utils.py +0 -0
  101. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/builtin_skills/init/SKILL.md +0 -0
  102. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/context/__init__.py +0 -0
  103. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/context/_xml.py +0 -0
  104. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/context/agent_mds.py +0 -0
  105. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/context/git.py +0 -0
  106. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/context/loader.py +0 -0
  107. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/context/skills.py +0 -0
  108. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/core/__init__.py +0 -0
  109. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/core/compaction.py +0 -0
  110. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/core/handoff.py +0 -0
  111. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/defaults/__init__.py +0 -0
  112. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/events.py +0 -0
  113. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/oauth/openai.py +0 -0
  114. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/providers/anthropic.py +0 -0
  115. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/providers/azure_ai_foundry.py +0 -0
  116. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/providers/copilot_anthropic.py +0 -0
  117. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/providers/github_copilot_headers.py +0 -0
  118. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/providers/mock.py +0 -0
  119. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/providers/openai_responses.py +0 -0
  120. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/llm/providers/sanitize.py +0 -0
  121. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/notify.py +0 -0
  122. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/permissions.py +0 -0
  123. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/py.typed +0 -0
  124. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/sounds/completion.wav +0 -0
  125. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/sounds/error.wav +0 -0
  126. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/sounds/permission.wav +0 -0
  127. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/__init__.py +0 -0
  128. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/_read_image.py +0 -0
  129. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools/_tool_utils.py +0 -0
  130. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/tools_manager.py +0 -0
  131. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/__init__.py +0 -0
  132. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/clipboard.py +0 -0
  133. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/export.py +0 -0
  134. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/formatting.py +0 -0
  135. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/latex.py +0 -0
  136. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/path_complete.py +0 -0
  137. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/ui/prompt_history.py +0 -0
  138. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/src/kon/update_check.py +0 -0
  139. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/conftest.py +0 -0
  140. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/context/test_agents.py +0 -0
  141. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/context/test_skills.py +0 -0
  142. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/llm/__init__.py +0 -0
  143. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/llm/test_anthropic_provider.py +0 -0
  144. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/llm/test_azure_ai_foundry_provider.py +0 -0
  145. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/llm/test_openai_oauth.py +0 -0
  146. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_cli_auth_flags.py +0 -0
  147. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_cli_provider_resolution.py +0 -0
  148. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_config_binaries.py +0 -0
  149. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_config_error_fallback.py +0 -0
  150. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_config_injection.py +0 -0
  151. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_handoff_link_interrupt.py +0 -0
  152. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_launch_warnings.py +0 -0
  153. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_local_auth_config.py +0 -0
  154. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_notifications_config.py +0 -0
  155. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_notify.py +0 -0
  156. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_permissions.py +0 -0
  157. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_session_queries.py +0 -0
  158. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_system_prompt_git_context.py +0 -0
  159. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_themes.py +0 -0
  160. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_tools_manager.py +0 -0
  161. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_ui_notifications.py +0 -0
  162. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_update_check.py +0 -0
  163. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/test_update_notice_behavior.py +0 -0
  164. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/tools/test_diff.py +0 -0
  165. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/tools/test_edit.py +0 -0
  166. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/tools/test_edit_display.py +0 -0
  167. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/tools/test_read.py +0 -0
  168. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/tools/test_read_image.py +0 -0
  169. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/tools/test_read_image_integration.py +0 -0
  170. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/tools/test_subprocess_cancellation.py +0 -0
  171. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/tools/test_write.py +0 -0
  172. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_app_approval_keys.py +0 -0
  173. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_floating_list.py +0 -0
  174. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_info_bar_clicks.py +0 -0
  175. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_input_handoff.py +0 -0
  176. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_input_paste.py +0 -0
  177. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_input_shell_style.py +0 -0
  178. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_latex.py +0 -0
  179. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_permission_selection_status.py +0 -0
  180. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_prompt_history.py +0 -0
  181. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_status_line.py +0 -0
  182. {kon_coding_agent-0.3.7 → kon_coding_agent-0.3.9}/tests/ui/test_styles.py +0 -0
@@ -11,6 +11,10 @@
11
11
  - Use `uv run python -m pytest` for testing in general; after edits/writes
12
12
  - If the user asks for e2e tests then run the kon-tmux e2e test if available
13
13
 
14
+ ## Skills
15
+
16
+ - Kon supports registering a skill as a slash command by setting `register_cmd: true` in the SKILL.md frontmatter. If a user asks for a "registered" skill, include this field.
17
+
14
18
  ## Committing code
15
19
 
16
20
  - If the user tells you to commit code, look at all the changes and create multile commits if needed bsaed on logical groupings
@@ -6,6 +6,72 @@ All notable changes to this project will be documented in this file.
6
6
 
7
7
  - No changes yet.
8
8
 
9
+ ## 0.3.9 - 2026-05-20
10
+
11
+ ### Added
12
+
13
+ - Added inline image display from tool results in chat UI.
14
+ - Added tree view for handoff navigation.
15
+ - Added ability to edit queued messages.
16
+ - Added Kanagawa Dragon theme.
17
+ - Added lazy provider loading for faster startup - @Meltedd.
18
+
19
+ ### Changed
20
+
21
+ - Swapped thinking block keybindings.
22
+ - Grouped preferences under settings.
23
+ - Refreshed startup resource display.
24
+ - Smoother streaming experience.
25
+ - Updated permission mode symbols — single tick for auto, stop icon for prompt.
26
+ - Lowercase slash command descriptions, `L` prefix for queue items.
27
+ - Updated README with ASCII art title, new screenshot, and refined styling.
28
+
29
+ ### Fixed
30
+
31
+ - Fixed Codex provider event handling, transport, and tracking - @Meltedd.
32
+ - Fixed tool expansion crash on startup - @0xku.
33
+ - Fixed Enter key not submitting permission prompts.
34
+ - Fixed manual shell output expand behavior.
35
+ - Fixed streaming cursor removal.
36
+ - Fixed tool output top padding missing blank line.
37
+ - Fixed tree selector display and empty tree state alignment.
38
+ - Fixed input cursor visibility in light themes.
39
+ - Fixed floating list popup styling.
40
+ - Fixed selected color alignment across themes and solarized-light dim color.
41
+ - Fixed legacy Shift+Enter mapping.
42
+ - Fixed Windows startup warning by delaying textual image import - @sukhbinder.
43
+
44
+ ## 0.3.8 - 2026-05-08
45
+
46
+ ### Added
47
+
48
+ - Added DeepSeek provider support - @Kreijstal.
49
+ - Added Codex websocket streaming with SSE fallback.
50
+ - Added expandable tool output.
51
+ - Added session handoff tree display in the resume list.
52
+ - Added config migration v5→v6 to replace legacy system prompts with the current default.
53
+ - Added dynamic tool guidelines in the system prompt via `prompt_guidelines` on `BaseTool`.
54
+
55
+ ### Changed
56
+
57
+ - Deduplicated tool prompt guidelines in the system prompt.
58
+ - Simplified prefix formatting in the session tree display.
59
+ - Added skills registration guidance to `AGENTS.md`.
60
+ - Removed old architectural review docs.
61
+ - Adjusted info bar pause icon spacing.
62
+
63
+ ### Fixed
64
+
65
+ - Fixed provider-specific OpenAI-compatible API key selection.
66
+ - Patched vulnerable dependencies - @Meltedd.
67
+ - Restored web fetch extraction compatibility with `html-to-markdown` 3.3.
68
+ - Handled `html-to-markdown` dict return types and raised the minimum supported version.
69
+ - Fixed info bar git branch refreshing.
70
+ - Marked GLM-5.1 as supporting native vision.
71
+ - Hardened `web_fetch` against SSRF - @Meltedd.
72
+ - Enforced output caps on shell-mode bash - @Meltedd.
73
+ - Used themed notice color for launch warning block borders.
74
+
9
75
  ## 0.3.7 - 2026-05-02
10
76
 
11
77
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kon-coding-agent
3
- Version: 0.3.7
3
+ Version: 0.3.9
4
4
  Summary: Minimal coding agent
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -9,17 +9,22 @@ Requires-Dist: aiohttp>=3.13.3
9
9
  Requires-Dist: anthropic>=0.79.0
10
10
  Requires-Dist: curl-cffi>=0.15.0
11
11
  Requires-Dist: ddgs>=9.0.0
12
- Requires-Dist: html-to-markdown<3.3.0,>=3.1.0
12
+ Requires-Dist: html-to-markdown<3.4.0,>=3.3.0
13
13
  Requires-Dist: openai>=2.21.0
14
14
  Requires-Dist: pillow>=12.1.1
15
15
  Requires-Dist: pydantic>=2.12.5
16
16
  Requires-Dist: readability-lxml>=0.8.4
17
17
  Requires-Dist: rich>=14.3.2
18
+ Requires-Dist: textual-image[textual]>=0.12.0
18
19
  Requires-Dist: textual>=8.0.0
19
20
  Description-Content-Type: text/markdown
20
21
 
21
- <h1 align="center">Kon</h1>
22
- <p align="center">A minimal terminal coding agent with a small core, strong defaults, and user-owned context.</p>
22
+ <pre align="center">
23
+ ░█░█░█▀█░█▀█
24
+ ░█▀▄░█░█░█░█
25
+ ░▀░▀░▀▀▀░▀░▀
26
+ </pre>
27
+ <p align="center">Minimal coding agent harness</p>
23
28
  <p align="center">
24
29
  <a href="https://pypi.org/project/kon-coding-agent/"><img alt="PyPI" src="https://img.shields.io/pypi/v/kon-coding-agent?style=flat-square" /></a>
25
30
  <a href="https://www.python.org/downloads/release/python-3120/"><img alt="Python" src="https://img.shields.io/badge/python-3.12%2B-blue?style=flat-square" /></a>
@@ -27,7 +32,7 @@ Description-Content-Type: text/markdown
27
32
  </p>
28
33
 
29
34
  <p align="center">
30
- <img src="docs/images/kon-screenshot.png" alt="Kon terminal UI screenshot" width="490" />
35
+ <img src="docs/images/kon-screenshot.png" alt="Kon terminal UI screenshot" width="700" />
31
36
  </p>
32
37
 
33
38
  Kon is a minimal coding agent focused on a tiny core prompt, a small built-in toolset, and project-specific context layered on top only when you want it. The default system prompt stays **under 270 tokens**, and even including the built-in tool descriptions and parameter schemas, the fixed harness stays at about **~1,000 tokens**. The core experience is built around just **6 default tools** plus **2 optional web tools**.
@@ -84,7 +89,7 @@ kon
84
89
 
85
90
  ```text
86
91
  usage: kon [-h] [--model MODEL]
87
- [--provider {azure-ai-foundry,github-copilot,openai,openai-codex,openai-responses,zhipu}]
92
+ [--provider {azure-ai-foundry,deepseek,github-copilot,openai,openai-codex,openai-responses,zhipu}]
88
93
  [--api-key API_KEY] [--base-url BASE_URL] [--continue]
89
94
  [--resume RESUME_SESSION] [--version]
90
95
  [--extra-tools EXTRA_TOOLS]
@@ -94,7 +99,7 @@ Kon TUI
94
99
  options:
95
100
  -h, --help show this help message and exit
96
101
  --model, -m MODEL Model to use
97
- --provider, -p {azure-ai-foundry,github-copilot,openai,openai-codex,openai-responses,zhipu}
102
+ --provider, -p {azure-ai-foundry,deepseek,github-copilot,openai,openai-codex,openai-responses,zhipu}
98
103
  Provider to use
99
104
  --api-key, -k API_KEY
100
105
  API key
@@ -482,6 +487,7 @@ Built-in provider support includes:
482
487
  - **OpenAI Codex**
483
488
  - **OpenAI Responses / OpenAI-compatible endpoints**
484
489
  - **Azure AI Foundry**
490
+ - **DeepSeek**
485
491
  - **ZhiPu**
486
492
 
487
493
  Use `/model` in the TUI to switch between available configured models.
@@ -493,12 +499,16 @@ Kon supports both OAuth login flows and direct API-key configuration.
493
499
  - **GitHub Copilot OAuth**: run `/login` and choose GitHub Copilot
494
500
  - **OpenAI OAuth**: run `/login` and choose OpenAI
495
501
  - **OpenAI-compatible providers**: use `OPENAI_API_KEY` or provider-specific equivalents
502
+ - OpenAI/default: `OPENAI_API_KEY` only
503
+ - DeepSeek: `DEEPSEEK_API_KEY` first, then `OPENAI_API_KEY`
504
+ - ZhiPu/ZAI: `ZAI_API_KEY` first, then `OPENAI_API_KEY`
496
505
  - **Azure AI Foundry**: set `AZURE_AI_FOUNDRY_API_KEY` and `AZURE_AI_FOUNDRY_BASE_URL`
497
506
 
498
507
  You can also pass credentials directly on launch:
499
508
 
500
509
  ```bash
501
510
  kon --provider openai --model some-model --api-key "$OPENAI_API_KEY"
511
+ kon --provider deepseek --model deepseek-v4-flash
502
512
  ```
503
513
 
504
514
  ### Local models
@@ -1,5 +1,9 @@
1
- <h1 align="center">Kon</h1>
2
- <p align="center">A minimal terminal coding agent with a small core, strong defaults, and user-owned context.</p>
1
+ <pre align="center">
2
+ ░█░█░█▀█░█▀█
3
+ ░█▀▄░█░█░█░█
4
+ ░▀░▀░▀▀▀░▀░▀
5
+ </pre>
6
+ <p align="center">Minimal coding agent harness</p>
3
7
  <p align="center">
4
8
  <a href="https://pypi.org/project/kon-coding-agent/"><img alt="PyPI" src="https://img.shields.io/pypi/v/kon-coding-agent?style=flat-square" /></a>
5
9
  <a href="https://www.python.org/downloads/release/python-3120/"><img alt="Python" src="https://img.shields.io/badge/python-3.12%2B-blue?style=flat-square" /></a>
@@ -7,7 +11,7 @@
7
11
  </p>
8
12
 
9
13
  <p align="center">
10
- <img src="docs/images/kon-screenshot.png" alt="Kon terminal UI screenshot" width="490" />
14
+ <img src="docs/images/kon-screenshot.png" alt="Kon terminal UI screenshot" width="700" />
11
15
  </p>
12
16
 
13
17
  Kon is a minimal coding agent focused on a tiny core prompt, a small built-in toolset, and project-specific context layered on top only when you want it. The default system prompt stays **under 270 tokens**, and even including the built-in tool descriptions and parameter schemas, the fixed harness stays at about **~1,000 tokens**. The core experience is built around just **6 default tools** plus **2 optional web tools**.
@@ -64,7 +68,7 @@ kon
64
68
 
65
69
  ```text
66
70
  usage: kon [-h] [--model MODEL]
67
- [--provider {azure-ai-foundry,github-copilot,openai,openai-codex,openai-responses,zhipu}]
71
+ [--provider {azure-ai-foundry,deepseek,github-copilot,openai,openai-codex,openai-responses,zhipu}]
68
72
  [--api-key API_KEY] [--base-url BASE_URL] [--continue]
69
73
  [--resume RESUME_SESSION] [--version]
70
74
  [--extra-tools EXTRA_TOOLS]
@@ -74,7 +78,7 @@ Kon TUI
74
78
  options:
75
79
  -h, --help show this help message and exit
76
80
  --model, -m MODEL Model to use
77
- --provider, -p {azure-ai-foundry,github-copilot,openai,openai-codex,openai-responses,zhipu}
81
+ --provider, -p {azure-ai-foundry,deepseek,github-copilot,openai,openai-codex,openai-responses,zhipu}
78
82
  Provider to use
79
83
  --api-key, -k API_KEY
80
84
  API key
@@ -462,6 +466,7 @@ Built-in provider support includes:
462
466
  - **OpenAI Codex**
463
467
  - **OpenAI Responses / OpenAI-compatible endpoints**
464
468
  - **Azure AI Foundry**
469
+ - **DeepSeek**
465
470
  - **ZhiPu**
466
471
 
467
472
  Use `/model` in the TUI to switch between available configured models.
@@ -473,12 +478,16 @@ Kon supports both OAuth login flows and direct API-key configuration.
473
478
  - **GitHub Copilot OAuth**: run `/login` and choose GitHub Copilot
474
479
  - **OpenAI OAuth**: run `/login` and choose OpenAI
475
480
  - **OpenAI-compatible providers**: use `OPENAI_API_KEY` or provider-specific equivalents
481
+ - OpenAI/default: `OPENAI_API_KEY` only
482
+ - DeepSeek: `DEEPSEEK_API_KEY` first, then `OPENAI_API_KEY`
483
+ - ZhiPu/ZAI: `ZAI_API_KEY` first, then `OPENAI_API_KEY`
476
484
  - **Azure AI Foundry**: set `AZURE_AI_FOUNDRY_API_KEY` and `AZURE_AI_FOUNDRY_BASE_URL`
477
485
 
478
486
  You can also pass credentials directly on launch:
479
487
 
480
488
  ```bash
481
489
  kon --provider openai --model some-model --api-key "$OPENAI_API_KEY"
490
+ kon --provider deepseek --model deepseek-v4-flash
482
491
  ```
483
492
 
484
493
  ### Local models
@@ -14,7 +14,7 @@ default = true
14
14
 
15
15
  [project]
16
16
  name = "kon-coding-agent"
17
- version = "0.3.7"
17
+ version = "0.3.9"
18
18
  description = "Minimal coding agent"
19
19
  readme = "README.md"
20
20
  requires-python = ">=3.12"
@@ -24,13 +24,14 @@ dependencies = [
24
24
  "anthropic>=0.79.0",
25
25
  "curl-cffi>=0.15.0",
26
26
  "ddgs>=9.0.0",
27
- "html-to-markdown>=3.1.0,<3.3.0",
27
+ "html-to-markdown>=3.3.0,<3.4.0",
28
28
  "openai>=2.21.0",
29
29
  "pillow>=12.1.1",
30
30
  "pydantic>=2.12.5",
31
31
  "readability-lxml>=0.8.4",
32
32
  "rich>=14.3.2",
33
33
  "textual>=8.0.0",
34
+ "textual-image[textual]>=0.12.0",
34
35
  ]
35
36
 
36
37
  [dependency-groups]
@@ -344,6 +344,29 @@ def _migrate_v4_to_v5(data: dict[str, Any]) -> dict[str, Any]:
344
344
  return migrated
345
345
 
346
346
 
347
+ def _migrate_v5_to_v6(data: dict[str, Any]) -> dict[str, Any]:
348
+ migrated = Config._apply_legacy_key_shims(data)
349
+ llm = migrated.get("llm")
350
+ if not isinstance(llm, dict):
351
+ llm = {}
352
+ migrated["llm"] = llm
353
+
354
+ system_prompt = llm.get("system_prompt")
355
+ if not isinstance(system_prompt, dict):
356
+ system_prompt = {}
357
+ llm["system_prompt"] = system_prompt
358
+
359
+ system_prompt["content"] = _DEFAULT_CONFIG_DATA["llm"]["system_prompt"]["content"]
360
+ system_prompt["git_context"] = _DEFAULT_CONFIG_DATA["llm"]["system_prompt"]["git_context"]
361
+
362
+ meta = migrated.get("meta")
363
+ if not isinstance(meta, dict):
364
+ migrated["meta"] = {"config_version": 6}
365
+ else:
366
+ meta["config_version"] = 6
367
+ return migrated
368
+
369
+
347
370
  def _migrate_config_data(data: dict[str, Any]) -> tuple[dict[str, Any], int, int, bool]:
348
371
  original = deepcopy(data)
349
372
  current_version = _get_config_version(original)
@@ -370,6 +393,10 @@ def _migrate_config_data(data: dict[str, Any]) -> tuple[dict[str, Any], int, int
370
393
  migrated = _migrate_v4_to_v5(migrated)
371
394
  current_version = 5
372
395
  continue
396
+ if current_version == 5:
397
+ migrated = _migrate_v5_to_v6(migrated)
398
+ current_version = 6
399
+ continue
373
400
  break
374
401
 
375
402
  migrated_version = _get_config_version(migrated)
@@ -66,6 +66,7 @@ class ToolCallDelta(BaseModel):
66
66
  type: Literal["tool_call_delta"] = "tool_call_delta"
67
67
  index: int # Correlates with ToolCallStart.index
68
68
  arguments_delta: str
69
+ replace: bool = False
69
70
 
70
71
 
71
72
  class StreamDone(BaseModel):
@@ -129,7 +130,8 @@ class ToolResultMessage(BaseModel):
129
130
  tool_name: str
130
131
  content: list[TextContent | ImageContent]
131
132
  ui_summary: str | None = None # One-line UI text rendered on tool header line
132
- ui_details: str | None = None # Multiline UI text rendered below the header
133
+ ui_details: str | None = None # Collapsed multiline UI text rendered below the header
134
+ ui_details_full: str | None = None # Expanded multiline UI text rendered below the header
133
135
  is_error: bool = False
134
136
  file_changes: FileChanges | None = None
135
137
 
@@ -165,7 +167,8 @@ class ToolResult(BaseModel):
165
167
  result: str | None = None # Raw result (sent to LLM)
166
168
  images: list[ImageContent] | None = None # Images to include in result
167
169
  ui_summary: str | None = None # One-line result text appended to the tool header
168
- ui_details: str | None = None # Multiline result body rendered below the header
170
+ ui_details: str | None = None # Collapsed multiline result body rendered below the header
171
+ ui_details_full: str | None = None # Expanded multiline result body rendered below the header
169
172
  file_changes: FileChanges | None = None # Track +/- lines for edit/write tools
170
173
 
171
174
 
@@ -1,5 +1,5 @@
1
1
  [meta]
2
- config_version = 5
2
+ config_version = 6
3
3
 
4
4
  [llm]
5
5
  default_provider = "openai-codex" # "zhipu", "github-copilot", "openai-codex"
@@ -32,17 +32,8 @@ content = """You are an expert coding assistant called Kon. You help users by re
32
32
  - Be concise in your responses
33
33
  - Show file paths clearly when working with files
34
34
  - When summarizing your actions, output plain text directly DO NOT use cat or bash to display
35
- - Kon session logs are JSONL files in ~/.kon/sessions; if the user references recent sessions or a particular session, look there
36
-
37
- # Tool usage
38
-
39
- - Prefer specialized tools over bash for file operations:
40
- - Use read to view files (NOT cat/head/tail)
41
- - Use edit for precise changes (NOT sed/awk)
42
- - Use write only for new files or complete rewrites (NOT echo >/cat <<EOF)
43
- - Use grep to search file contents (NOT grep or rg via bash)
44
- - Use find to search for files by name/glob (NOT find or ls via bash)
45
- - Use bash for terminal operations (git, package managers, builds, tests, running scripts)"""
35
+ - Kon session logs are JSONL files in ~/.kon/sessions; If the user references recent sessions or a particular session, look there
36
+ - If the user mentions adding a new skill then look at https://github.com/0xku/kon/blob/main/README.md#skills"""
46
37
 
47
38
  [compaction]
48
39
  # What kon should do after compacting history on context overflow.
@@ -80,3 +71,10 @@ mode = "prompt" # "prompt" or "auto"
80
71
  enabled = false
81
72
  # Audio playback volume from 0.0 (muted) to 1.0 (full volume).
82
73
  volume = 0.5
74
+
75
+ # Example: DeepSeek provider
76
+ # export DEEPSEEK_API_KEY="sk-your-api-key"
77
+ #
78
+ # Then set in [llm]:
79
+ # default_provider = "deepseek"
80
+ # default_model = "deepseek-v4-flash"
@@ -0,0 +1,90 @@
1
+ import os
2
+ import subprocess
3
+ from dataclasses import dataclass
4
+
5
+
6
+ @dataclass(frozen=True)
7
+ class GitPaths:
8
+ repo_dir: str
9
+ common_git_dir: str
10
+ head_path: str
11
+
12
+
13
+ def find_git_paths(cwd: str) -> GitPaths | None:
14
+ """Find git metadata paths for regular repos and worktrees."""
15
+ directory = os.path.abspath(cwd)
16
+ while True:
17
+ git_path = os.path.join(directory, ".git")
18
+ if os.path.exists(git_path):
19
+ try:
20
+ if os.path.isfile(git_path):
21
+ with open(git_path, encoding="utf-8") as f:
22
+ content = f.read().strip()
23
+ if content.startswith("gitdir: "):
24
+ git_dir = os.path.abspath(
25
+ os.path.join(directory, content.removeprefix("gitdir: ").strip())
26
+ )
27
+ head_path = os.path.join(git_dir, "HEAD")
28
+ if not os.path.exists(head_path):
29
+ return None
30
+ common_dir_path = os.path.join(git_dir, "commondir")
31
+ if os.path.exists(common_dir_path):
32
+ with open(common_dir_path, encoding="utf-8") as f:
33
+ common_dir = f.read().strip()
34
+ common_git_dir = os.path.abspath(os.path.join(git_dir, common_dir))
35
+ else:
36
+ common_git_dir = git_dir
37
+ return GitPaths(directory, common_git_dir, head_path)
38
+ elif os.path.isdir(git_path):
39
+ head_path = os.path.join(git_path, "HEAD")
40
+ if not os.path.exists(head_path):
41
+ return None
42
+ return GitPaths(directory, git_path, head_path)
43
+ except OSError:
44
+ return None
45
+
46
+ parent = os.path.dirname(directory)
47
+ if parent == directory:
48
+ return None
49
+ directory = parent
50
+
51
+
52
+ def _resolve_branch_with_git(repo_dir: str) -> str | None:
53
+ try:
54
+ result = subprocess.run(
55
+ ["git", "--no-optional-locks", "symbolic-ref", "--quiet", "--short", "HEAD"],
56
+ cwd=repo_dir,
57
+ capture_output=True,
58
+ text=True,
59
+ timeout=1,
60
+ check=False,
61
+ )
62
+ except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
63
+ return None
64
+
65
+ if result.returncode != 0:
66
+ return None
67
+ branch = result.stdout.strip()
68
+ return branch or None
69
+
70
+
71
+ def resolve_git_branch(cwd: str) -> str:
72
+ """Resolve current git branch, returning an empty string outside git repos."""
73
+ git_paths = find_git_paths(cwd)
74
+ if git_paths is None:
75
+ return ""
76
+
77
+ try:
78
+ with open(git_paths.head_path, encoding="utf-8") as f:
79
+ content = f.read().strip()
80
+ except OSError:
81
+ return ""
82
+
83
+ prefix = "ref: refs/heads/"
84
+ if content.startswith(prefix):
85
+ branch = content.removeprefix(prefix)
86
+ if branch == ".invalid":
87
+ return _resolve_branch_with_git(git_paths.repo_dir) or "detached"
88
+ return branch
89
+
90
+ return "detached"
@@ -10,6 +10,7 @@ from .models import (
10
10
  from .oauth import clear_credentials as clear_copilot_credentials
11
11
  from .oauth import (
12
12
  clear_openai_credentials,
13
+ is_copilot_logged_in,
13
14
  is_openai_logged_in,
14
15
  load_openai_credentials,
15
16
  openai_login,
@@ -18,33 +19,15 @@ from .oauth import get_valid_openai_token as get_openai_token
18
19
  from .oauth import get_valid_token as get_copilot_token
19
20
  from .oauth import load_credentials as load_copilot_credentials
20
21
  from .oauth import login as copilot_login
21
- from .providers import (
22
- API_TYPE_TO_PROVIDER_CLASS,
23
- PROVIDER_API_BY_NAME,
24
- CopilotAnthropicProvider,
25
- CopilotProvider,
26
- CopilotResponsesProvider,
27
- OpenAICodexResponsesProvider,
28
- OpenAICompletionsProvider,
29
- OpenAIResponsesProvider,
30
- is_copilot_logged_in,
31
- resolve_provider_api_type,
32
- )
22
+ from .providers import PROVIDER_API_BY_NAME, get_provider_class, resolve_provider_api_type
33
23
 
34
24
  __all__ = [
35
- "API_TYPE_TO_PROVIDER_CLASS",
36
25
  "DEFAULT_THINKING_LEVELS",
37
26
  "PROVIDER_API_BY_NAME",
38
27
  "ApiType",
39
28
  "BaseProvider",
40
- "CopilotAnthropicProvider",
41
- "CopilotProvider",
42
- "CopilotResponsesProvider",
43
29
  "LLMStream",
44
30
  "Model",
45
- "OpenAICodexResponsesProvider",
46
- "OpenAICompletionsProvider",
47
- "OpenAIResponsesProvider",
48
31
  "ProviderConfig",
49
32
  "clear_copilot_credentials",
50
33
  "clear_openai_credentials",
@@ -55,6 +38,7 @@ __all__ = [
55
38
  "get_model",
56
39
  "get_models_by_provider",
57
40
  "get_openai_token",
41
+ "get_provider_class",
58
42
  "is_copilot_logged_in",
59
43
  "is_openai_logged_in",
60
44
  "load_copilot_credentials",
@@ -16,6 +16,7 @@ ENV_API_KEY_MAP: dict[str, str] = {
16
16
  "openai": "OPENAI_API_KEY",
17
17
  "google": "GEMINI_API_KEY",
18
18
  "azure-ai-foundry": "AZURE_AI_FOUNDRY_API_KEY",
19
+ "deepseek": "DEEPSEEK_API_KEY",
19
20
  }
20
21
 
21
22
 
@@ -53,9 +53,27 @@ MODELS: dict[str, Model] = {
53
53
  api=ApiType.OPENAI_COMPLETIONS,
54
54
  base_url="https://api.z.ai/api/coding/paas/v4",
55
55
  max_tokens=8192,
56
+ supports_images=True,
57
+ supports_thinking=True,
58
+ ),
59
+ # DeepSeek models (OpenAI-compatible Chat Completions API)
60
+ "deepseek-v4-flash": Model(
61
+ id="deepseek-v4-flash",
62
+ provider="deepseek",
63
+ api=ApiType.OPENAI_COMPLETIONS,
64
+ base_url="https://api.deepseek.com",
65
+ max_tokens=8192,
66
+ supports_images=False,
67
+ supports_thinking=True,
68
+ ),
69
+ "deepseek-v4-pro": Model(
70
+ id="deepseek-v4-pro",
71
+ provider="deepseek",
72
+ api=ApiType.OPENAI_COMPLETIONS,
73
+ base_url="https://api.deepseek.com",
74
+ max_tokens=8192,
56
75
  supports_images=False,
57
76
  supports_thinking=True,
58
- vision_model="glm-4v-flash",
59
77
  ),
60
78
  # GitHub Copilot models - Claude (uses Anthropic Messages API for thinking support)
61
79
  "claude-sonnet-4.6-copilot": Model(
@@ -5,6 +5,7 @@ from .copilot import (
5
5
  get_base_url_from_token,
6
6
  get_copilot_auth_path,
7
7
  get_valid_token,
8
+ is_copilot_logged_in,
8
9
  load_credentials,
9
10
  login,
10
11
  )
@@ -29,6 +30,7 @@ __all__ = [
29
30
  "get_openai_auth_path",
30
31
  "get_valid_openai_token",
31
32
  "get_valid_token",
33
+ "is_copilot_logged_in",
32
34
  "is_openai_logged_in",
33
35
  "load_credentials",
34
36
  "load_openai_credentials",
@@ -86,6 +86,10 @@ def clear_credentials() -> None:
86
86
  path.unlink()
87
87
 
88
88
 
89
+ def is_copilot_logged_in() -> bool:
90
+ return load_credentials() is not None
91
+
92
+
89
93
  def _get_urls(domain: str) -> dict[str, str]:
90
94
  return {
91
95
  "device_code": f"https://{domain}/login/device/code",
@@ -0,0 +1,61 @@
1
+ from ..base import BaseProvider
2
+ from ..models import ApiType
3
+
4
+ PROVIDER_API_BY_NAME: dict[str, ApiType] = {
5
+ "openai": ApiType.OPENAI_COMPLETIONS,
6
+ "zhipu": ApiType.OPENAI_COMPLETIONS,
7
+ "deepseek": ApiType.OPENAI_COMPLETIONS,
8
+ "github-copilot": ApiType.GITHUB_COPILOT,
9
+ "openai-responses": ApiType.OPENAI_RESPONSES,
10
+ "openai-codex": ApiType.OPENAI_CODEX_RESPONSES,
11
+ "azure-ai-foundry": ApiType.AZURE_AI_FOUNDRY,
12
+ }
13
+
14
+
15
+ def resolve_provider_api_type(provider: str | None) -> ApiType:
16
+ if provider is None:
17
+ return ApiType.OPENAI_COMPLETIONS
18
+
19
+ api_type = PROVIDER_API_BY_NAME.get(provider)
20
+ if api_type is None:
21
+ valid = ", ".join(sorted(PROVIDER_API_BY_NAME))
22
+ raise ValueError(f"Unknown provider '{provider}'. Valid providers: {valid}")
23
+
24
+ return api_type
25
+
26
+
27
+ def get_provider_class(api_type: ApiType) -> type[BaseProvider]:
28
+ match api_type:
29
+ case ApiType.GITHUB_COPILOT:
30
+ from .copilot import CopilotProvider
31
+
32
+ return CopilotProvider
33
+ case ApiType.GITHUB_COPILOT_RESPONSES:
34
+ from .copilot import CopilotResponsesProvider
35
+
36
+ return CopilotResponsesProvider
37
+ case ApiType.OPENAI_RESPONSES:
38
+ from .openai_responses import OpenAIResponsesProvider
39
+
40
+ return OpenAIResponsesProvider
41
+ case ApiType.OPENAI_CODEX_RESPONSES:
42
+ from .openai_codex_responses import OpenAICodexResponsesProvider
43
+
44
+ return OpenAICodexResponsesProvider
45
+ case ApiType.ANTHROPIC_COPILOT:
46
+ from .copilot_anthropic import CopilotAnthropicProvider
47
+
48
+ return CopilotAnthropicProvider
49
+ case ApiType.AZURE_AI_FOUNDRY:
50
+ from .azure_ai_foundry import AzureAIFoundryProvider
51
+
52
+ return AzureAIFoundryProvider
53
+ case ApiType.OPENAI_COMPLETIONS:
54
+ from .openai_completions import OpenAICompletionsProvider
55
+
56
+ return OpenAICompletionsProvider
57
+
58
+ raise ValueError(f"Unsupported API type: {api_type.value}")
59
+
60
+
61
+ __all__ = ["PROVIDER_API_BY_NAME", "get_provider_class", "resolve_provider_api_type"]
@@ -142,7 +142,3 @@ class CopilotResponsesProvider(OpenAIResponsesProvider):
142
142
  temperature=temperature,
143
143
  max_tokens=max_tokens,
144
144
  )
145
-
146
-
147
- def is_copilot_logged_in() -> bool:
148
- return load_credentials() is not None