klaude-code 2.20.0__tar.gz → 2.22.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. {klaude_code-2.20.0 → klaude_code-2.22.0}/PKG-INFO +18 -7
  2. {klaude_code-2.20.0 → klaude_code-2.22.0}/README.md +16 -5
  3. {klaude_code-2.20.0 → klaude_code-2.22.0}/pyproject.toml +7 -3
  4. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/app/auth_flow.py +7 -7
  5. {klaude_code-2.20.0/src/klaude_code/cli → klaude_code-2.22.0/src/klaude_code/app}/log_viewer.html +125 -9
  6. klaude_code-2.20.0/src/klaude_code/cli/log_server.py → klaude_code-2.22.0/src/klaude_code/app/log_viewer.py +71 -8
  7. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/copilot/oauth.py +3 -1
  8. klaude_code-2.22.0/src/klaude_code/auth/copilot/token_manager.py +64 -0
  9. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/cli/auth_cmd.py +2 -2
  10. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/cli/list_model.py +85 -24
  11. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/cli/main.py +3 -25
  12. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/cli/oauth_usage.py +8 -8
  13. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/config/assets/builtin_config.yaml +60 -138
  14. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/config/builtin_config.py +1 -0
  15. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/config/config.py +89 -42
  16. klaude_code-2.22.0/src/klaude_code/config/sub_agent_model_helper.py +110 -0
  17. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/config/thinking.py +5 -9
  18. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/const.py +5 -5
  19. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/agent.py +16 -2
  20. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/agent_profile.py +23 -128
  21. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/bash_mode.py +3 -3
  22. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/executor.py +55 -54
  23. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/loaded_skills.py +14 -0
  24. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/manager/llm_clients.py +0 -5
  25. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/manager/llm_clients_builder.py +6 -3
  26. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/manager/sub_agent_manager.py +1 -2
  27. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/memory.py +40 -1
  28. klaude_code-2.22.0/src/klaude_code/core/prompts/auto-memory-prompt.md +29 -0
  29. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/prompts/base-system-prompt.md +14 -14
  30. klaude_code-2.22.0/src/klaude_code/core/prompts/system_prompt.py +183 -0
  31. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/reminders.py +44 -104
  32. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/task.py +24 -9
  33. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/__init__.py +14 -7
  34. klaude_code-2.20.0/src/klaude_code/core/tool/task_tool.md → klaude_code-2.22.0/src/klaude_code/core/tool/agent_tool.md +4 -3
  35. klaude_code-2.20.0/src/klaude_code/core/tool/task_tool.py → klaude_code-2.22.0/src/klaude_code/core/tool/agent_tool.py +19 -24
  36. klaude_code-2.22.0/src/klaude_code/core/tool/ask_user_question_tool.md +9 -0
  37. klaude_code-2.22.0/src/klaude_code/core/tool/ask_user_question_tool.py +255 -0
  38. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/context.py +15 -1
  39. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/rewind_tool.md +2 -2
  40. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/web/web_fetch_tool.py +24 -13
  41. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/turn.py +23 -31
  42. klaude_code-2.22.0/src/klaude_code/core/user_interaction/__init__.py +3 -0
  43. klaude_code-2.22.0/src/klaude_code/core/user_interaction/manager.py +114 -0
  44. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/anthropic/client.py +3 -1
  45. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/anthropic/input.py +9 -2
  46. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/copilot/client.py +4 -2
  47. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/google/client.py +0 -68
  48. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/google/input.py +14 -11
  49. klaude_code-2.22.0/src/klaude_code/llm/image.py +323 -0
  50. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/input_common.py +22 -36
  51. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openai_compatible/input.py +1 -2
  52. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openai_compatible/stream.py +0 -50
  53. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openai_responses/input.py +5 -2
  54. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openrouter/client.py +0 -9
  55. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openrouter/input.py +19 -10
  56. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openrouter/reasoning.py +4 -1
  57. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/registry.py +1 -1
  58. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/usage.py +0 -7
  59. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/__init__.py +1 -0
  60. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/commands.py +1 -3
  61. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/events.py +10 -17
  62. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/llm_param.py +18 -22
  63. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/message.py +9 -50
  64. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/model.py +9 -17
  65. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/model_id.py +0 -21
  66. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/op.py +15 -13
  67. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/op_handler.py +5 -5
  68. klaude_code-2.22.0/src/klaude_code/protocol/sub_agent/AGENTS.md +18 -0
  69. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/sub_agent/__init__.py +5 -14
  70. klaude_code-2.20.0/src/klaude_code/protocol/sub_agent/task.py → klaude_code-2.22.0/src/klaude_code/protocol/sub_agent/general_purpose.py +2 -2
  71. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/tools.py +2 -3
  72. klaude_code-2.22.0/src/klaude_code/protocol/user_interaction.py +50 -0
  73. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/session/export.py +12 -187
  74. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/session/session.py +17 -21
  75. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/session/store.py +3 -1
  76. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/session/templates/export_session.html +0 -308
  77. klaude_code-2.22.0/src/klaude_code/skill/assets/frontend-design/SKILL.md +42 -0
  78. klaude_code-2.22.0/src/klaude_code/skill/assets/gpt-image-gen/LICENSE.txt +201 -0
  79. klaude_code-2.22.0/src/klaude_code/skill/assets/gpt-image-gen/SKILL.md +175 -0
  80. klaude_code-2.22.0/src/klaude_code/skill/assets/gpt-image-gen/references/cli.md +132 -0
  81. klaude_code-2.22.0/src/klaude_code/skill/assets/gpt-image-gen/references/codex-network.md +28 -0
  82. klaude_code-2.22.0/src/klaude_code/skill/assets/gpt-image-gen/references/image-api.md +36 -0
  83. klaude_code-2.22.0/src/klaude_code/skill/assets/gpt-image-gen/references/prompting.md +81 -0
  84. klaude_code-2.22.0/src/klaude_code/skill/assets/gpt-image-gen/references/sample-prompts.md +384 -0
  85. klaude_code-2.22.0/src/klaude_code/skill/assets/gpt-image-gen/scripts/image_gen.py +851 -0
  86. klaude_code-2.22.0/src/klaude_code/skill/assets/nano-banana-image-gen/SKILL.md +108 -0
  87. klaude_code-2.22.0/src/klaude_code/skill/assets/nano-banana-image-gen/references/cli.md +149 -0
  88. klaude_code-2.22.0/src/klaude_code/skill/assets/nano-banana-image-gen/references/gemini-api.md +101 -0
  89. klaude_code-2.22.0/src/klaude_code/skill/assets/nano-banana-image-gen/references/prompting.md +142 -0
  90. klaude_code-2.22.0/src/klaude_code/skill/assets/nano-banana-image-gen/references/sample-prompts.md +183 -0
  91. klaude_code-2.22.0/src/klaude_code/skill/assets/nano-banana-image-gen/references/vertex-setup.md +108 -0
  92. klaude_code-2.22.0/src/klaude_code/skill/assets/nano-banana-image-gen/scripts/gemini_image_gen.py +640 -0
  93. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/SKILL.md +315 -0
  94. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/forms.md +294 -0
  95. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/reference.md +612 -0
  96. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/scripts/check_bounding_boxes.py +69 -0
  97. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/scripts/check_fillable_fields.py +9 -0
  98. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/scripts/convert_pdf_to_images.py +31 -0
  99. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/scripts/create_validation_image.py +37 -0
  100. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/scripts/extract_form_field_info.py +123 -0
  101. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/scripts/extract_form_structure.py +116 -0
  102. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/scripts/fill_fillable_fields.py +102 -0
  103. klaude_code-2.22.0/src/klaude_code/skill/assets/pdf/scripts/fill_pdf_form_with_annotations.py +99 -0
  104. klaude_code-2.22.0/src/klaude_code/skill/assets/render-mermaid/.gitignore +1 -0
  105. klaude_code-2.22.0/src/klaude_code/skill/assets/render-mermaid/SKILL.md +28 -0
  106. klaude_code-2.22.0/src/klaude_code/skill/assets/render-mermaid/bun.lock +182 -0
  107. klaude_code-2.22.0/src/klaude_code/skill/assets/render-mermaid/package.json +9 -0
  108. klaude_code-2.22.0/src/klaude_code/skill/assets/render-mermaid/scripts/render_mermaid.js +182 -0
  109. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/skill/assets/skill-creator/SKILL.md +75 -17
  110. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/skill/loader.py +54 -6
  111. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/skill/manager.py +16 -1
  112. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/skill/system_skills.py +2 -2
  113. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/__init__.py +9 -15
  114. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/auth_selector.py +16 -10
  115. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/compact_cmd.py +1 -1
  116. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/continue_cmd.py +1 -1
  117. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/copy_cmd.py +4 -39
  118. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/debug_cmd.py +9 -14
  119. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/export_cmd.py +1 -1
  120. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/fork_session_cmd.py +1 -1
  121. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/model_cmd.py +1 -1
  122. klaude_code-2.20.0/src/klaude_code/tui/command/clear_cmd.py → klaude_code-2.22.0/src/klaude_code/tui/command/new_cmd.py +4 -4
  123. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/refresh_cmd.py +5 -1
  124. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/registry.py +1 -1
  125. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/status_cmd.py +61 -55
  126. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/sub_agent_model_cmd.py +2 -2
  127. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/thinking_cmd.py +1 -1
  128. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/commands.py +0 -11
  129. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/command_output.py +56 -15
  130. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/developer.py +1 -1
  131. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/metadata.py +87 -28
  132. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/rich/markdown.py +70 -16
  133. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/rich/status.py +14 -42
  134. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/rich/theme.py +22 -10
  135. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/tools.py +148 -139
  136. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/welcome.py +42 -8
  137. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/display.py +33 -1
  138. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/input/completers.py +138 -24
  139. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/input/images.py +0 -127
  140. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/input/key_bindings.py +1 -1
  141. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/input/paste.py +1 -1
  142. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/input/prompt_toolkit.py +53 -2
  143. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/machine.py +23 -31
  144. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/renderer.py +24 -31
  145. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/runner.py +163 -63
  146. klaude_code-2.22.0/src/klaude_code/tui/terminal/ask_user_question.py +772 -0
  147. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/terminal/control.py +27 -0
  148. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/terminal/image.py +46 -9
  149. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/terminal/notifier.py +1 -0
  150. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/terminal/selector.py +65 -34
  151. klaude_code-2.20.0/src/klaude_code/tui/command/resume_cmd.py → klaude_code-2.22.0/src/klaude_code/tui/terminal/session_selector.py +0 -46
  152. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/ui/__init__.py +0 -2
  153. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/ui/common.py +0 -10
  154. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/ui/core/display.py +1 -1
  155. klaude_code-2.20.0/src/klaude_code/.DS_Store +0 -0
  156. klaude_code-2.20.0/src/klaude_code/auth/copilot/token_manager.py +0 -27
  157. klaude_code-2.20.0/src/klaude_code/config/sub_agent_model_helper.py +0 -213
  158. klaude_code-2.20.0/src/klaude_code/core/prompts/prompt-sub-agent-image-gen.md +0 -6
  159. klaude_code-2.20.0/src/klaude_code/core/prompts/system_prompt.py +0 -89
  160. klaude_code-2.20.0/src/klaude_code/core/tool/image_gen_tool.md +0 -16
  161. klaude_code-2.20.0/src/klaude_code/core/tool/image_gen_tool.py +0 -147
  162. klaude_code-2.20.0/src/klaude_code/core/tool/mermaid_tool.md +0 -64
  163. klaude_code-2.20.0/src/klaude_code/core/tool/mermaid_tool.py +0 -74
  164. klaude_code-2.20.0/src/klaude_code/llm/image.py +0 -130
  165. klaude_code-2.20.0/src/klaude_code/protocol/sub_agent/AGENTS.md +0 -28
  166. klaude_code-2.20.0/src/klaude_code/protocol/sub_agent/image_gen.py +0 -38
  167. klaude_code-2.20.0/src/klaude_code/session/templates/mermaid_viewer.html +0 -1011
  168. klaude_code-2.20.0/src/klaude_code/skill/.DS_Store +0 -0
  169. klaude_code-2.20.0/src/klaude_code/skill/assets/.DS_Store +0 -0
  170. klaude_code-2.20.0/src/klaude_code/tui/command/export_online_cmd.py +0 -150
  171. klaude_code-2.20.0/src/klaude_code/tui/components/mermaid_viewer.py +0 -163
  172. klaude_code-2.20.0/src/klaude_code/ui/debug_mode.py +0 -37
  173. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/__init__.py +0 -0
  174. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/app/__init__.py +0 -0
  175. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/app/runtime.py +0 -0
  176. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/AGENTS.md +0 -0
  177. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/__init__.py +0 -0
  178. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/base.py +0 -0
  179. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/claude/__init__.py +0 -0
  180. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/claude/exceptions.py +0 -0
  181. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/claude/oauth.py +0 -0
  182. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/claude/token_manager.py +0 -0
  183. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/codex/__init__.py +0 -0
  184. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/codex/exceptions.py +0 -0
  185. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
  186. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/codex/oauth.py +0 -0
  187. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/codex/token_manager.py +0 -0
  188. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/copilot/__init__.py +0 -0
  189. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/copilot/exceptions.py +0 -0
  190. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/auth/env.py +0 -0
  191. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/cli/__init__.py +0 -0
  192. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/cli/config_cmd.py +0 -0
  193. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/cli/cost_cmd.py +0 -0
  194. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/cli/debug.py +0 -0
  195. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/cli/self_update.py +0 -0
  196. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/config/__init__.py +0 -0
  197. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/config/assets/__init__.py +0 -0
  198. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/config/model_matcher.py +0 -0
  199. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/__init__.py +0 -0
  200. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/compaction/AGENTS.md +0 -0
  201. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/compaction/__init__.py +0 -0
  202. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/compaction/compaction.py +0 -0
  203. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/compaction/overflow.py +0 -0
  204. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/compaction/prompts.py +0 -0
  205. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/manager/__init__.py +0 -0
  206. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +0 -0
  207. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
  208. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/rewind/__init__.py +0 -0
  209. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/rewind/manager.py +0 -0
  210. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/__init__.py +0 -0
  211. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/_utils.py +0 -0
  212. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
  213. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
  214. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/apply_patch_tool.py +0 -0
  215. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/diff_builder.py +0 -0
  216. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
  217. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/edit_tool.py +0 -0
  218. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/read_tool.md +0 -0
  219. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/read_tool.py +0 -0
  220. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/write_tool.md +0 -0
  221. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/file/write_tool.py +0 -0
  222. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/offload.py +0 -0
  223. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/report_back_tool.py +0 -0
  224. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/rewind_tool.py +0 -0
  225. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/shell/__init__.py +0 -0
  226. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/shell/bash_tool.md +0 -0
  227. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/shell/bash_tool.py +0 -0
  228. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
  229. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/todo/__init__.py +0 -0
  230. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -0
  231. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/todo/todo_write_tool.py +0 -0
  232. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
  233. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
  234. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/todo/update_plan_tool.py +0 -0
  235. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/tool_abc.py +0 -0
  236. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/tool_registry.py +0 -0
  237. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/tool_runner.py +0 -0
  238. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/web/__init__.py +0 -0
  239. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/web/external_content.py +0 -0
  240. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/web/ssrf.py +0 -0
  241. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/web/web_cache.py +0 -0
  242. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/web/web_fetch_tool.md +0 -0
  243. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
  244. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/core/tool/web/web_search_tool.py +0 -0
  245. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/__init__.py +0 -0
  246. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/anthropic/__init__.py +0 -0
  247. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/bedrock_anthropic/__init__.py +0 -0
  248. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/bedrock_anthropic/client.py +0 -0
  249. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/claude/__init__.py +0 -0
  250. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/claude/client.py +0 -0
  251. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/client.py +0 -0
  252. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/copilot/__init__.py +0 -0
  253. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/google/__init__.py +0 -0
  254. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/google_vertex/__init__.py +0 -0
  255. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/google_vertex/client.py +0 -0
  256. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/json_stable.py +0 -0
  257. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openai_codex/__init__.py +0 -0
  258. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openai_codex/client.py +0 -0
  259. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
  260. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openai_compatible/client.py +0 -0
  261. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openai_responses/__init__.py +0 -0
  262. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openai_responses/client.py +0 -0
  263. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/openrouter/__init__.py +0 -0
  264. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/partial_message.py +0 -0
  265. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/llm/stream_parts.py +0 -0
  266. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/log.py +0 -0
  267. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/protocol/sub_agent/explore.py +0 -0
  268. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/session/__init__.py +0 -0
  269. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/session/codec.py +0 -0
  270. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/session/selector.py +0 -0
  271. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/skill/__init__.py +0 -0
  272. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/skill/assets/deslop/SKILL.md +0 -0
  273. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/skill/assets/executing-plans/SKILL.md +0 -0
  274. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/skill/assets/session-logs/SKILL.md +0 -0
  275. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/skill/assets/web-search/SKILL.md +0 -0
  276. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/skill/assets/writing-plans/SKILL.md +0 -0
  277. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/__init__.py +0 -0
  278. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/command_abc.py +0 -0
  279. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/login_cmd.py +0 -0
  280. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/logout_cmd.py +0 -0
  281. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/model_picker.py +0 -0
  282. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/prompt-init.md +0 -0
  283. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/command/prompt_command.py +0 -0
  284. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/__init__.py +0 -0
  285. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/bash_syntax.py +0 -0
  286. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/common.py +0 -0
  287. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/diffs.py +0 -0
  288. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/errors.py +0 -0
  289. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/rich/__init__.py +0 -0
  290. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/rich/cjk_wrap.py +0 -0
  291. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/rich/code_panel.py +0 -0
  292. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/rich/live.py +0 -0
  293. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/rich/quote.py +0 -0
  294. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/sub_agent.py +0 -0
  295. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/thinking.py +0 -0
  296. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/components/user_input.py +0 -0
  297. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/input/AGENTS.md +0 -0
  298. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/input/__init__.py +0 -0
  299. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/input/drag_drop.py +0 -0
  300. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/terminal/__init__.py +0 -0
  301. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/terminal/color.py +0 -0
  302. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/tui/terminal/progress_bar.py +0 -0
  303. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/ui/core/__init__.py +0 -0
  304. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/ui/core/input.py +0 -0
  305. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/ui/terminal/__init__.py +0 -0
  306. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/ui/terminal/title.py +0 -0
  307. {klaude_code-2.20.0 → klaude_code-2.22.0}/src/klaude_code/update.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: klaude-code
3
- Version: 2.20.0
3
+ Version: 2.22.0
4
4
  Summary: Minimal code agent CLI
5
5
  Requires-Dist: anthropic>=0.66.0
6
6
  Requires-Dist: chardet>=5.2.0,<6
@@ -9,7 +9,7 @@ Requires-Dist: diff-match-patch>=20241021
9
9
  Requires-Dist: filelock>=3.20.3
10
10
  Requires-Dist: google-genai>=1.56.0
11
11
  Requires-Dist: markdown-it-py>=4.0.0
12
- Requires-Dist: openai>=1.102.0
12
+ Requires-Dist: openai>=2.24.0
13
13
  Requires-Dist: prompt-toolkit>=3.0.52
14
14
  Requires-Dist: pydantic>=2.11.7
15
15
  Requires-Dist: python-socks>=2.8.1
@@ -29,7 +29,7 @@ Minimal code agent CLI.
29
29
  - **Keep reasoning item in context**: Interleaved thinking support
30
30
  - **Model-aware tools**: Claude Code tool set for Opus, `apply_patch` for GPT-5/Codex
31
31
  - **Reminders**: Cooldown-based todo tracking, instruction reinforcement and external file change reminder
32
- - **Sub-agents**: Task, Explore, Web, ImageGen
32
+ - **Sub-agents**: Task, Explore
33
33
  - **Structured sub-agent output**: Main agent defines JSON schema and get schema-compliant responses via constrained decoding
34
34
  - **Recursive `@file` mentions**: Circular dependency protection, relative path resolution
35
35
  - **External file sync**: Monitoring for external edits (linter, manual)
@@ -37,7 +37,6 @@ Minimal code agent CLI.
37
37
  - **Output truncation**: Large outputs saved to file system with snapshot links
38
38
  - **Agent Skills**: Built-in + user + project Agent Skills (with implicit invocation by Skill tool or explicit invocation by typing `//skill` or `/skill`)
39
39
  - **Sessions**: Resumable with `--continue`
40
- - **Mermaid diagrams**: Terminal image preview and Interactive local HTML viewer with zoom, pan, and SVG export
41
40
  - **Extras**: Slash commands, sub-agents, image paste, terminal notifications, auto-theming
42
41
 
43
42
  ## Installation
@@ -198,6 +197,21 @@ provider_list:
198
197
  - **Overriding**: Use the same `model_name` as a built-in model to override its parameters.
199
198
  - **Environment Variables**: Use `${VAR_NAME}` syntax for secrets.
200
199
 
200
+ ##### Sub-agent Model Configuration
201
+
202
+ `sub_agent_models` only accepts sub-agent types. Current supported keys are:
203
+
204
+ - `general-purpose` (Task sub-agent)
205
+ - `explore` (Explore sub-agent)
206
+
207
+ If a sub-agent type is not configured, it falls back to the main agent model.
208
+
209
+ ```yaml
210
+ sub_agent_models:
211
+ general-purpose: sonnet
212
+ explore: haiku
213
+ ```
214
+
201
215
  ##### Supported Protocols
202
216
 
203
217
  - `anthropic` - Anthropic Messages API
@@ -244,7 +258,6 @@ Inside the interactive session (`klaude`), use these commands to streamline your
244
258
  - `/resume` - Select and resume a previous session.
245
259
  - `/fork-session` - Fork current session to a new session ID (supports interactive fork point selection).
246
260
  - `/export` - Export last assistant message to a temp Markdown file.
247
- - `/export-online` - Export and deploy session to surge.sh as a static webpage.
248
261
  - `/debug [filters]` - Toggle debug mode and configure debug filters.
249
262
  - `/init` - Bootstrap a new project structure or module.
250
263
  - `/dev-doc [feature]` - Generate a comprehensive execution plan for a feature.
@@ -274,5 +287,3 @@ The main agent can spawn specialized sub-agents for specific tasks:
274
287
  |-----------|---------|
275
288
  | **Explore** | Fast codebase exploration - find files, search code, answer questions about the codebase |
276
289
  | **Task** | Handle complex multi-step tasks autonomously |
277
- | **WebAgent** | Search the web, fetch pages, and analyze content. Uses Brave LLM Context API when `BRAVE_API_KEY` is set, otherwise falls back to DuckDuckGo |
278
- | **ImageGen** | Generate images from text prompts via OpenRouter Nano Banana Pro |
@@ -7,7 +7,7 @@ Minimal code agent CLI.
7
7
  - **Keep reasoning item in context**: Interleaved thinking support
8
8
  - **Model-aware tools**: Claude Code tool set for Opus, `apply_patch` for GPT-5/Codex
9
9
  - **Reminders**: Cooldown-based todo tracking, instruction reinforcement and external file change reminder
10
- - **Sub-agents**: Task, Explore, Web, ImageGen
10
+ - **Sub-agents**: Task, Explore
11
11
  - **Structured sub-agent output**: Main agent defines JSON schema and get schema-compliant responses via constrained decoding
12
12
  - **Recursive `@file` mentions**: Circular dependency protection, relative path resolution
13
13
  - **External file sync**: Monitoring for external edits (linter, manual)
@@ -15,7 +15,6 @@ Minimal code agent CLI.
15
15
  - **Output truncation**: Large outputs saved to file system with snapshot links
16
16
  - **Agent Skills**: Built-in + user + project Agent Skills (with implicit invocation by Skill tool or explicit invocation by typing `//skill` or `/skill`)
17
17
  - **Sessions**: Resumable with `--continue`
18
- - **Mermaid diagrams**: Terminal image preview and Interactive local HTML viewer with zoom, pan, and SVG export
19
18
  - **Extras**: Slash commands, sub-agents, image paste, terminal notifications, auto-theming
20
19
 
21
20
  ## Installation
@@ -176,6 +175,21 @@ provider_list:
176
175
  - **Overriding**: Use the same `model_name` as a built-in model to override its parameters.
177
176
  - **Environment Variables**: Use `${VAR_NAME}` syntax for secrets.
178
177
 
178
+ ##### Sub-agent Model Configuration
179
+
180
+ `sub_agent_models` only accepts sub-agent types. Current supported keys are:
181
+
182
+ - `general-purpose` (Task sub-agent)
183
+ - `explore` (Explore sub-agent)
184
+
185
+ If a sub-agent type is not configured, it falls back to the main agent model.
186
+
187
+ ```yaml
188
+ sub_agent_models:
189
+ general-purpose: sonnet
190
+ explore: haiku
191
+ ```
192
+
179
193
  ##### Supported Protocols
180
194
 
181
195
  - `anthropic` - Anthropic Messages API
@@ -222,7 +236,6 @@ Inside the interactive session (`klaude`), use these commands to streamline your
222
236
  - `/resume` - Select and resume a previous session.
223
237
  - `/fork-session` - Fork current session to a new session ID (supports interactive fork point selection).
224
238
  - `/export` - Export last assistant message to a temp Markdown file.
225
- - `/export-online` - Export and deploy session to surge.sh as a static webpage.
226
239
  - `/debug [filters]` - Toggle debug mode and configure debug filters.
227
240
  - `/init` - Bootstrap a new project structure or module.
228
241
  - `/dev-doc [feature]` - Generate a comprehensive execution plan for a feature.
@@ -252,5 +265,3 @@ The main agent can spawn specialized sub-agents for specific tasks:
252
265
  |-----------|---------|
253
266
  | **Explore** | Fast codebase exploration - find files, search code, answer questions about the codebase |
254
267
  | **Task** | Handle complex multi-step tasks autonomously |
255
- | **WebAgent** | Search the web, fetch pages, and analyze content. Uses Brave LLM Context API when `BRAVE_API_KEY` is set, otherwise falls back to DuckDuckGo |
256
- | **ImageGen** | Generate images from text prompts via OpenRouter Nano Banana Pro |
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "klaude-code"
7
- version = "2.20.0"
7
+ version = "2.22.0"
8
8
  description = "Minimal code agent CLI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -16,7 +16,7 @@ dependencies = [
16
16
  "filelock>=3.20.3",
17
17
  "google-genai>=1.56.0",
18
18
  "markdown-it-py>=4.0.0",
19
- "openai>=1.102.0",
19
+ "openai>=2.24.0",
20
20
  "prompt-toolkit>=3.0.52",
21
21
  "pydantic>=2.11.7",
22
22
  "python-socks>=2.8.1",
@@ -40,6 +40,7 @@ dev = [
40
40
  "pyright>=1.1.407",
41
41
  "pytest>=8.4.1",
42
42
  "pytest-cov>=7.0.0",
43
+ "ruff==0.14.3",
43
44
  "ty>=0.0.8",
44
45
  ]
45
46
 
@@ -69,7 +70,10 @@ venv = ".venv"
69
70
  extraPaths = ["src"]
70
71
  reportMissingImports = "warning"
71
72
  reportMissingModuleSource = "warning"
72
- exclude = [".venv/"]
73
+ exclude = [
74
+ ".venv/",
75
+ "src/klaude_code/skill/assets/**/scripts/",
76
+ ]
73
77
 
74
78
  [[tool.pyright.executionEnvironments]]
75
79
  root = "."
@@ -136,7 +136,7 @@ def execute_login(provider: str) -> None:
136
136
  except Exception as e:
137
137
  log((f"Login failed: {e}", "red"))
138
138
  raise typer.Exit(1) from None
139
- case "copilot":
139
+ case "github-copilot" | "copilot":
140
140
  from klaude_code.auth.copilot.oauth import CopilotOAuth
141
141
  from klaude_code.auth.copilot.token_manager import CopilotTokenManager
142
142
 
@@ -145,7 +145,7 @@ def execute_login(provider: str) -> None:
145
145
  if token_manager.is_logged_in():
146
146
  state = token_manager.get_state()
147
147
  if state and not state.is_expired():
148
- log(("You are already logged in to Copilot.", "green"))
148
+ log(("You are already logged in to GitHub Copilot.", "green"))
149
149
  domain = state.enterprise_domain or "github.com"
150
150
  expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.UTC)
151
151
  log(f" Domain: {domain}")
@@ -232,18 +232,18 @@ def execute_logout(provider: str) -> None:
232
232
  if typer.confirm("Are you sure you want to logout from Claude?"):
233
233
  token_manager.delete()
234
234
  log(("Logged out from Claude.", "green"))
235
- case "copilot":
235
+ case "github-copilot" | "copilot":
236
236
  from klaude_code.auth.copilot.token_manager import CopilotTokenManager
237
237
 
238
238
  token_manager = CopilotTokenManager()
239
239
 
240
240
  if not token_manager.is_logged_in():
241
- log("You are not logged in to Copilot.")
241
+ log("You are not logged in to GitHub Copilot.")
242
242
  return
243
243
 
244
- if typer.confirm("Are you sure you want to logout from Copilot?"):
244
+ if typer.confirm("Are you sure you want to logout from GitHub Copilot?"):
245
245
  token_manager.delete()
246
- log(("Logged out from Copilot.", "green"))
246
+ log(("Logged out from GitHub Copilot.", "green"))
247
247
  case _:
248
- log((f"Error: Unknown provider '{provider}'. Supported: codex, claude, copilot", "red"))
248
+ log((f"Error: Unknown provider '{provider}'. Supported: codex, claude, github-copilot", "red"))
249
249
  raise typer.Exit(1)
@@ -86,6 +86,25 @@ body {
86
86
  flex: 1;
87
87
  letter-spacing: -0.01em;
88
88
  }
89
+ .nav-btn {
90
+ background: var(--bg-surface);
91
+ border: 1px solid var(--border);
92
+ color: var(--fg-secondary);
93
+ padding: 4px 10px;
94
+ border-radius: 6px;
95
+ font-size: 16px;
96
+ font-weight: 700;
97
+ font-family: var(--font-sans);
98
+ cursor: pointer;
99
+ transition: all 0.2s ease;
100
+ white-space: nowrap;
101
+ box-shadow: 0 1px 2px rgba(0,0,0,0.02);
102
+ }
103
+ .nav-btn:hover {
104
+ background: var(--bg-hover);
105
+ color: var(--fg);
106
+ border-color: var(--border-strong);
107
+ }
89
108
  #toolbar .filter-group {
90
109
  display: flex;
91
110
  gap: 6px;
@@ -93,10 +112,13 @@ body {
93
112
  flex-wrap: wrap;
94
113
  }
95
114
  .filter-btn {
96
- background: transparent;
97
- border: 1px solid transparent;
115
+ display: inline-flex;
116
+ align-items: center;
117
+ gap: 6px;
118
+ background: var(--bg-surface);
119
+ border: 1px solid var(--border-strong);
98
120
  color: var(--fg-secondary);
99
- padding: 4px 8px;
121
+ padding: 4px 10px;
100
122
  border-radius: 6px;
101
123
  font-size: 16px;
102
124
  font-weight: 700;
@@ -105,13 +127,23 @@ body {
105
127
  transition: all 0.2s ease;
106
128
  line-height: 1.2;
107
129
  }
108
- .filter-btn:hover { background: #e6f0fa; color: #005fcc; }
130
+ .filter-btn:hover {
131
+ background: var(--bg-hover);
132
+ color: var(--fg);
133
+ border-color: var(--fg-tertiary);
134
+ }
109
135
  .filter-btn.active {
110
136
  background: #dbeafe;
111
137
  color: #1e3a8a;
112
- border-color: transparent;
138
+ border-color: #bfdbfe;
113
139
  box-shadow: none;
114
140
  }
141
+ .filter-btn.active::after {
142
+ content: '\00d7';
143
+ font-size: 14px;
144
+ line-height: 1;
145
+ opacity: 0.85;
146
+ }
115
147
 
116
148
  #search-box {
117
149
  background: var(--bg-surface);
@@ -366,6 +398,7 @@ body {
366
398
  <div id="container">
367
399
  <div id="left">
368
400
  <div id="toolbar">
401
+ <button class="nav-btn" id="btn-back-list" title="Back to log files">Logs</button>
369
402
  <span class="title" id="log-title">No log loaded</span>
370
403
  <input type="text" id="search-box" placeholder="Search... (/)">
371
404
  <div class="filter-group" id="filter-group"></div>
@@ -395,15 +428,76 @@ let selectedIdx = -1;
395
428
  let activeFilters = new Set();
396
429
  let searchQuery = '';
397
430
  let showRaw = false;
431
+ let viewerMode = 'files';
432
+
433
+ function setViewerMode(mode) {
434
+ viewerMode = mode;
435
+ const isLogMode = mode === 'log';
436
+ document.getElementById('btn-back-list').style.display = isLogMode ? '' : 'none';
437
+ document.getElementById('search-box').style.display = isLogMode ? '' : 'none';
438
+ document.getElementById('filter-group').style.display = isLogMode ? '' : 'none';
439
+ for (const id of ['btn-copy', 'btn-expand-all', 'btn-collapse-all', 'btn-raw']) {
440
+ document.getElementById(id).disabled = !isLogMode;
441
+ }
442
+ }
443
+
444
+ document.getElementById('btn-back-list').addEventListener('click', () => {
445
+ location.search = '';
446
+ });
447
+
448
+ async function loadLogList() {
449
+ setViewerMode('files');
450
+ const title = document.getElementById('log-title');
451
+ const list = document.getElementById('log-list');
452
+ const label = document.getElementById('right-label');
453
+ const view = document.getElementById('json-view');
454
+ title.textContent = 'Log files';
455
+ label.textContent = 'Select a log file';
456
+ view.innerHTML = '<span class="empty-hint">Choose a log file from the left list</span>';
457
+ list.innerHTML = '<div class="log-line"><span class="msg">Loading...</span></div>';
458
+
459
+ try {
460
+ const resp = await fetch('/api/logs');
461
+ if (!resp.ok) throw new Error(resp.statusText);
462
+ const files = await resp.json();
463
+ list.innerHTML = '';
464
+
465
+ if (files.length === 0) {
466
+ list.innerHTML = '<div class="log-line"><span class="msg">No log files found</span></div>';
467
+ return;
468
+ }
469
+
470
+ const frag = document.createDocumentFragment();
471
+ files.forEach((file, idx) => {
472
+ const div = document.createElement('div');
473
+ div.className = 'log-line';
474
+ const mtime = new Date(file.mtime * 1000).toLocaleString();
475
+ div.innerHTML =
476
+ '<span class="lineno">' + (idx + 1) + '</span>' +
477
+ '<span class="ts">' + esc(mtime) + '</span> ' +
478
+ '<span class="msg">' + esc(file.relative_path) + '</span> ' +
479
+ '<span class="json-inline">' + esc(formatBytes(file.size_bytes)) + '</span>';
480
+ div.addEventListener('click', () => {
481
+ location.search = '?log=' + encodeURIComponent(file.path);
482
+ });
483
+ frag.appendChild(div);
484
+ });
485
+ list.appendChild(frag);
486
+ } catch (e) {
487
+ title.textContent = 'Error: ' + e.message;
488
+ list.innerHTML = '<div class="log-line"><span class="msg">Failed to load log files</span></div>';
489
+ }
490
+ }
398
491
 
399
492
  // --- Data loading ---
400
493
  async function loadLog() {
401
494
  const params = new URLSearchParams(location.search);
402
495
  const logPath = params.get('log');
403
496
  if (!logPath) {
404
- document.getElementById('log-title').textContent = 'No log path specified';
497
+ await loadLogList();
405
498
  return;
406
499
  }
500
+ setViewerMode('log');
407
501
  document.getElementById('log-title').textContent = logPath.split('/').slice(-2).join('/');
408
502
  try {
409
503
  const resp = await fetch('/api/log?path=' + encodeURIComponent(logPath));
@@ -482,13 +576,28 @@ function toggleFilter(type, btn) {
482
576
  btn.classList.add('active');
483
577
  }
484
578
  applyFilters();
579
+
580
+ if (selectedIdx >= 0) {
581
+ const list = document.getElementById('log-list');
582
+ const selected = list.children[selectedIdx];
583
+ if (selected && !selected.classList.contains('hidden')) {
584
+ const listRect = list.getBoundingClientRect();
585
+ const rowRect = selected.getBoundingClientRect();
586
+ const fullyVisible = rowRect.top >= listRect.top && rowRect.bottom <= listRect.bottom;
587
+ if (!fullyVisible) {
588
+ selected.scrollIntoView({ block: 'center' });
589
+ }
590
+ }
591
+ }
485
592
  }
486
593
 
487
594
  function applyFilters() {
595
+ if (viewerMode !== 'log') return;
488
596
  const list = document.getElementById('log-list');
489
597
  const items = list.children;
490
598
  for (let i = 0; i < items.length; i++) {
491
599
  const entry = logLines[i];
600
+ if (!entry) continue;
492
601
  let visible = true;
493
602
  if (activeFilters.size > 0 && entry.type && !activeFilters.has(entry.type)) {
494
603
  visible = false;
@@ -763,11 +872,12 @@ document.getElementById('btn-raw').addEventListener('click', () => {
763
872
  // --- Search ---
764
873
  const searchBox = document.getElementById('search-box');
765
874
  searchBox.addEventListener('input', () => {
875
+ if (viewerMode !== 'log') return;
766
876
  searchQuery = searchBox.value.toLowerCase();
767
877
  applyFilters();
768
878
  });
769
879
  document.addEventListener('keydown', (e) => {
770
- if (e.key === '/' && document.activeElement !== searchBox) {
880
+ if (viewerMode === 'log' && e.key === '/' && document.activeElement !== searchBox) {
771
881
  e.preventDefault();
772
882
  searchBox.focus();
773
883
  }
@@ -775,16 +885,17 @@ document.addEventListener('keydown', (e) => {
775
885
  searchBox.value = '';
776
886
  searchQuery = '';
777
887
  searchBox.blur();
778
- applyFilters();
888
+ if (viewerMode === 'log') applyFilters();
779
889
  }
780
890
  // Arrow keys for navigation
781
- if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
891
+ if (viewerMode === 'log' && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
782
892
  e.preventDefault();
783
893
  navigateLine(e.key === 'ArrowDown' ? 1 : -1);
784
894
  }
785
895
  });
786
896
 
787
897
  function navigateLine(direction) {
898
+ if (viewerMode !== 'log') return;
788
899
  const list = document.getElementById('log-list');
789
900
  let next = selectedIdx + direction;
790
901
  // Skip hidden lines
@@ -939,6 +1050,11 @@ function badgeify(s) {
939
1050
  return esc(s).replace(/\[([\w.]+)\]/g, '<span class="badge">$1</span>');
940
1051
  }
941
1052
  function truncate(s, n) { return s.length <= n ? s : s.slice(0, n) + '...'; }
1053
+ function formatBytes(bytes) {
1054
+ if (bytes < 1024) return bytes + ' B';
1055
+ if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
1056
+ return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
1057
+ }
942
1058
 
943
1059
  // --- Init ---
944
1060
  buildFilters();
@@ -1,6 +1,7 @@
1
1
  """Minimal HTTP server for the debug log viewer."""
2
2
 
3
- import socket
3
+ import errno
4
+ import json
4
5
  import threading
5
6
  import webbrowser
6
7
  from http.server import BaseHTTPRequestHandler, HTTPServer
@@ -10,6 +11,7 @@ from urllib.parse import parse_qs, urlparse
10
11
  from klaude_code.const import DEFAULT_DEBUG_LOG_DIR
11
12
 
12
13
  _VIEWER_HTML = Path(__file__).parent / "log_viewer.html"
14
+ _DEFAULT_LOG_VIEWER_PORT = 8765
13
15
 
14
16
 
15
17
  class _LogViewerHandler(BaseHTTPRequestHandler):
@@ -27,6 +29,8 @@ class _LogViewerHandler(BaseHTTPRequestHandler):
27
29
  self._serve_log(paths[0])
28
30
  else:
29
31
  self._error(400, "missing path parameter")
32
+ elif parsed.path == "/api/logs":
33
+ self._serve_logs()
30
34
  else:
31
35
  self._error(404, "not found")
32
36
 
@@ -41,7 +45,7 @@ class _LogViewerHandler(BaseHTTPRequestHandler):
41
45
  def _serve_log(self, raw_path: str) -> None:
42
46
  log_path = Path(raw_path).resolve()
43
47
  log_dir = DEFAULT_DEBUG_LOG_DIR.resolve()
44
- if not str(log_path).startswith(str(log_dir)):
48
+ if not _is_path_within(log_path, log_dir):
45
49
  self._error(403, "access denied: path outside log directory")
46
50
  return
47
51
  if not log_path.is_file():
@@ -54,6 +58,15 @@ class _LogViewerHandler(BaseHTTPRequestHandler):
54
58
  self.end_headers()
55
59
  self.wfile.write(content)
56
60
 
61
+ def _serve_logs(self) -> None:
62
+ logs = _list_log_files(DEFAULT_DEBUG_LOG_DIR.resolve())
63
+ body = json.dumps(logs).encode()
64
+ self.send_response(200)
65
+ self.send_header("Content-Type", "application/json; charset=utf-8")
66
+ self.send_header("Content-Length", str(len(body)))
67
+ self.end_headers()
68
+ self.wfile.write(body)
69
+
57
70
  def _error(self, code: int, msg: str) -> None:
58
71
  body = msg.encode()
59
72
  self.send_response(code)
@@ -66,10 +79,61 @@ class _LogViewerHandler(BaseHTTPRequestHandler):
66
79
  pass
67
80
 
68
81
 
69
- def _find_free_port() -> int:
70
- with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
71
- s.bind(("127.0.0.1", 0))
72
- return s.getsockname()[1]
82
+ def _create_server_with_fallback(start_port: int) -> tuple[HTTPServer, int]:
83
+ for port in range(start_port, 65536):
84
+ try:
85
+ server = HTTPServer(("127.0.0.1", port), _LogViewerHandler)
86
+ except OSError as exc:
87
+ if exc.errno == errno.EADDRINUSE:
88
+ continue
89
+ raise
90
+ return server, port
91
+ raise RuntimeError(f"no available port from {start_port} to 65535")
92
+
93
+
94
+ def _is_path_within(path: Path, root: Path) -> bool:
95
+ try:
96
+ path.relative_to(root)
97
+ return True
98
+ except ValueError:
99
+ return False
100
+
101
+
102
+ def _list_log_files(log_dir: Path) -> list[dict[str, object]]:
103
+ if not log_dir.exists():
104
+ return []
105
+
106
+ files: list[tuple[float, dict[str, object]]] = []
107
+ seen_paths: set[Path] = set()
108
+ for path in log_dir.rglob("*.log"):
109
+ if not path.is_file():
110
+ continue
111
+
112
+ try:
113
+ stat = path.stat()
114
+ resolved = path.resolve()
115
+ relative_path = str(resolved.relative_to(log_dir))
116
+ except (OSError, ValueError):
117
+ continue
118
+
119
+ if resolved in seen_paths:
120
+ continue
121
+ seen_paths.add(resolved)
122
+
123
+ files.append(
124
+ (
125
+ stat.st_mtime,
126
+ {
127
+ "path": str(resolved),
128
+ "relative_path": relative_path,
129
+ "size_bytes": stat.st_size,
130
+ "mtime": stat.st_mtime,
131
+ },
132
+ )
133
+ )
134
+
135
+ files.sort(key=lambda item: item[0], reverse=True)
136
+ return [item[1] for item in files]
73
137
 
74
138
 
75
139
  def start_log_viewer(log_path: Path) -> str:
@@ -77,8 +141,7 @@ def start_log_viewer(log_path: Path) -> str:
77
141
 
78
142
  Returns the URL of the viewer.
79
143
  """
80
- port = _find_free_port()
81
- server = HTTPServer(("127.0.0.1", port), _LogViewerHandler)
144
+ server, port = _create_server_with_fallback(_DEFAULT_LOG_VIEWER_PORT)
82
145
  thread = threading.Thread(target=server.serve_forever, daemon=True)
83
146
  thread.start()
84
147
 
@@ -224,7 +224,9 @@ class CopilotOAuth:
224
224
  """Ensure we have a valid Copilot token and return (token, base_url)."""
225
225
  state = self.token_manager.get_state()
226
226
  if state is None:
227
- raise CopilotNotLoggedInError("Not logged in to Copilot. Run 'klaude auth login copilot' first.")
227
+ raise CopilotNotLoggedInError(
228
+ "Not logged in to GitHub Copilot. Run 'klaude auth login github-copilot' first."
229
+ )
228
230
 
229
231
  if state.is_expired():
230
232
  state = self.refresh()
@@ -0,0 +1,64 @@
1
+ """Token storage and management for GitHub Copilot authentication."""
2
+
3
+ from pathlib import Path
4
+ from typing import Any, cast
5
+
6
+ from klaude_code.auth.base import BaseAuthState, BaseTokenManager
7
+
8
+
9
+ class CopilotAuthState(BaseAuthState):
10
+ """Stored authentication state for GitHub Copilot."""
11
+
12
+ enterprise_domain: str | None = None
13
+ copilot_base_url: str = "https://api.individual.githubcopilot.com"
14
+
15
+
16
+ class CopilotTokenManager(BaseTokenManager[CopilotAuthState]):
17
+ """Manage GitHub Copilot OAuth tokens."""
18
+
19
+ _LEGACY_STORAGE_KEY = "copilot"
20
+
21
+ def __init__(self, auth_file: Path | None = None):
22
+ super().__init__(auth_file)
23
+
24
+ @property
25
+ def storage_key(self) -> str:
26
+ return "github-copilot"
27
+
28
+ def load(self) -> CopilotAuthState | None:
29
+ state = super().load()
30
+ if state is not None:
31
+ return state
32
+
33
+ store = self._load_store()
34
+ legacy_data = store.get(self._LEGACY_STORAGE_KEY)
35
+ if not isinstance(legacy_data, dict):
36
+ return None
37
+ legacy_payload = cast(dict[str, Any], legacy_data)
38
+
39
+ try:
40
+ migrated = self._create_state(legacy_payload)
41
+ except ValueError:
42
+ return None
43
+
44
+ store[self.storage_key] = migrated.model_dump(mode="json")
45
+ store.pop(self._LEGACY_STORAGE_KEY, None)
46
+ self._save_store(store)
47
+ self._state = migrated
48
+ return migrated
49
+
50
+ def delete(self) -> None:
51
+ store = self._load_store()
52
+ store.pop(self.storage_key, None)
53
+ store.pop(self._LEGACY_STORAGE_KEY, None)
54
+
55
+ if len(store) == 0:
56
+ if self.auth_file.exists():
57
+ self.auth_file.unlink()
58
+ else:
59
+ self._save_store(store)
60
+
61
+ self._state = None
62
+
63
+ def _create_state(self, data: dict[str, Any]) -> CopilotAuthState:
64
+ return CopilotAuthState.model_validate(data)
@@ -9,7 +9,7 @@ from klaude_code.tui.command.auth_selector import select_provider
9
9
  def _build_provider_help() -> str:
10
10
  from klaude_code.config.builtin_config import SUPPORTED_API_KEYS
11
11
 
12
- names = ["codex", "claude", "copilot"] + [k.name.split()[0].lower() for k in SUPPORTED_API_KEYS]
12
+ names = ["codex", "claude", "github-copilot", "copilot"] + [k.name.split()[0].lower() for k in SUPPORTED_API_KEYS]
13
13
  return f"Provider name ({', '.join(names)})"
14
14
 
15
15
 
@@ -26,7 +26,7 @@ def login_command(
26
26
 
27
27
 
28
28
  def logout_command(
29
- provider: str | None = typer.Argument(None, help="Provider to logout (codex|claude|copilot)"),
29
+ provider: str | None = typer.Argument(None, help="Provider to logout (codex|claude|github-copilot|copilot)"),
30
30
  ) -> None:
31
31
  """Logout from a provider."""
32
32
  if provider is None: