klaude-code 2.6.0__py3-none-any.whl → 2.7.0__py3-none-any.whl

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 (34) hide show
  1. klaude_code/app/runtime.py +1 -1
  2. klaude_code/auth/env.py +19 -15
  3. klaude_code/cli/auth_cmd.py +1 -1
  4. klaude_code/cli/main.py +98 -8
  5. klaude_code/const.py +10 -1
  6. klaude_code/core/reminders.py +4 -5
  7. klaude_code/core/turn.py +1 -1
  8. klaude_code/protocol/commands.py +0 -1
  9. klaude_code/skill/loader.py +12 -13
  10. klaude_code/skill/manager.py +3 -3
  11. klaude_code/tui/command/__init__.py +1 -4
  12. klaude_code/tui/command/copy_cmd.py +1 -1
  13. klaude_code/tui/command/fork_session_cmd.py +4 -4
  14. klaude_code/tui/components/command_output.py +1 -1
  15. klaude_code/tui/components/rich/markdown.py +60 -0
  16. klaude_code/tui/components/rich/theme.py +8 -0
  17. klaude_code/tui/components/user_input.py +38 -27
  18. klaude_code/tui/input/AGENTS.md +44 -0
  19. klaude_code/tui/input/completers.py +10 -14
  20. klaude_code/tui/input/drag_drop.py +197 -0
  21. klaude_code/tui/input/images.py +227 -0
  22. klaude_code/tui/input/key_bindings.py +173 -19
  23. klaude_code/tui/input/paste.py +71 -0
  24. klaude_code/tui/input/prompt_toolkit.py +13 -3
  25. klaude_code/tui/machine.py +1 -1
  26. klaude_code/tui/runner.py +1 -1
  27. klaude_code/tui/terminal/image.py +40 -9
  28. klaude_code/tui/terminal/selector.py +52 -2
  29. {klaude_code-2.6.0.dist-info → klaude_code-2.7.0.dist-info}/METADATA +10 -10
  30. {klaude_code-2.6.0.dist-info → klaude_code-2.7.0.dist-info}/RECORD +32 -30
  31. klaude_code/tui/command/terminal_setup_cmd.py +0 -248
  32. klaude_code/tui/input/clipboard.py +0 -152
  33. {klaude_code-2.6.0.dist-info → klaude_code-2.7.0.dist-info}/WHEEL +0 -0
  34. {klaude_code-2.6.0.dist-info → klaude_code-2.7.0.dist-info}/entry_points.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  klaude_code/.DS_Store,sha256=cLWFbSgdN0bXEd3_tz93BJSposEPafUBqSr7t-3lPbA,6148
2
2
  klaude_code/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  klaude_code/app/__init__.py,sha256=7mgWpN9SFDqe8AW44bBn9M19nVsBcZURrsGB_8l2hrU,264
4
- klaude_code/app/runtime.py,sha256=St5ZVo9snvc90R5fG4OojlWwtlRSB66AZAYfZD7AOCE,5982
4
+ klaude_code/app/runtime.py,sha256=xo5_oxc80kjoF1h5IWSEWukRwdA257JzakC_VgcikII,5976
5
5
  klaude_code/auth/__init__.py,sha256=4Rlp-JkYkmYu38oifN79PNHyFU2WzzcDDp7pG0QmlAE,677
6
6
  klaude_code/auth/base.py,sha256=ccH2sC0TWB5lPpGm4FSjCgnehwn9riYiXxHCh2iFJe0,3011
7
7
  klaude_code/auth/claude/__init__.py,sha256=h1oyqEttDM5TAF6w1Stk6YXYMsbATjODCsi6GhU4zAA,218
@@ -13,14 +13,14 @@ klaude_code/auth/codex/exceptions.py,sha256=TcAKPozsY3SCh_krTYFlJ8FU5jepgSTg-5UO
13
13
  klaude_code/auth/codex/jwt_utils.py,sha256=tuaJKT4vAIGeaQjNzgNcHWGrYYSDrDeaQT9h4cw5Us8,1134
14
14
  klaude_code/auth/codex/oauth.py,sha256=4hAGZ2Dv87NC3loEws7U5yNyPyIrryGm5YXY2FkHeyo,7840
15
15
  klaude_code/auth/codex/token_manager.py,sha256=EiEdxEErh_mcnW8USWbvdbN91LK7nyk0PZJZGmdUTG8,1405
16
- klaude_code/auth/env.py,sha256=-d0bJXJE-e2AY5JL82TpR6kkjbJCtyGdBzN-G6P4Be0,2398
16
+ klaude_code/auth/env.py,sha256=QLqV2QjVCAAPSaH2xm2W0KvQ-RSbRxk_Y_FSH_MGDNY,2550
17
17
  klaude_code/cli/__init__.py,sha256=YzlAoWAr5rx5oe6B_4zPxRFS4QaZauuy1AFwampP5fg,45
18
- klaude_code/cli/auth_cmd.py,sha256=DHY6TGCEOkrZJ-rNVTZ2vg0bS5DltUDiVD0BzBreqDs,8680
18
+ klaude_code/cli/auth_cmd.py,sha256=mgnFav918Mx5KyXNX3dAFC3Ps-CW4Ym3LYHK_ro6nBs,8721
19
19
  klaude_code/cli/config_cmd.py,sha256=7BmZpKeiO24mKKLKGO46WvSQzSaNwuZ3KtCV4GH-Yh0,3306
20
20
  klaude_code/cli/cost_cmd.py,sha256=NNykvNxQn3QvFTe5FYM2RIRskZi97rrbKhAxC5o8Fag,17579
21
21
  klaude_code/cli/debug.py,sha256=vEHOjObhrIHDAXk3q6cOgeW2NZxCx5AWM1rJ6FiJnVU,1901
22
22
  klaude_code/cli/list_model.py,sha256=dzXwahAZZv8NHPD4pvOTLaTJTEWnCjS1B-K52n3OHOs,13603
23
- klaude_code/cli/main.py,sha256=maa6vgsAgxYVQGk8unhkqgxMTnmEoOmcA8K7TUPMnPs,9438
23
+ klaude_code/cli/main.py,sha256=IHw0syuJW6cFPurghM9w_X_t-m5PUOvWxlcoefhYvXc,12224
24
24
  klaude_code/cli/self_update.py,sha256=1xdG9ifvRZQDSx6RAtSSgXmw9hZNXMLvqC2zu4bS-GY,2622
25
25
  klaude_code/config/__init__.py,sha256=Qe1BeMekBfO2-Zd30x33lB70hdM1QQZGrp4DbWSQ-II,353
26
26
  klaude_code/config/assets/__init__.py,sha256=uMUfmXT3I-gYiI-HVr1DrE60mx5cY1o8V7SYuGqOmvY,32
@@ -30,7 +30,7 @@ klaude_code/config/config.py,sha256=MinPsZH6h2MdmnJiX9F6VpaZHkKb1iG-zV90i6dJq1s,
30
30
  klaude_code/config/model_matcher.py,sha256=3IlLU5h3NDh_bURbCW-PV027C3irG3hyitwj1cj99Ig,6179
31
31
  klaude_code/config/sub_agent_model_helper.py,sha256=fI-OIZWFI4116qjalsZj2pIi0waPR1cXE-OKrVMFS6g,8064
32
32
  klaude_code/config/thinking.py,sha256=RDWH8UYbeDoIKPXaCIcvVwPAh07Ntaq8w5Zn_fhm-Fk,9329
33
- klaude_code/const.py,sha256=dVWGzsUINndi0skjlkDsfJtI5ocqINpJUVm0wxOaO7w,11246
33
+ klaude_code/const.py,sha256=PxQg86WxcTy58Yq9TtsbU4nVkiWhV7RIcai-ZoP_P6Q,11487
34
34
  klaude_code/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  klaude_code/core/agent.py,sha256=5TNzzzHgKLKpEcFhaM0d136kaGUn_mESC8b1nLoxS2o,3913
36
36
  klaude_code/core/agent_profile.py,sha256=EAsAHj9Jd_JaL_ydr13I3uVoBN4RIm9zmKPn3H7NYu8,12817
@@ -50,7 +50,7 @@ klaude_code/core/prompts/prompt-sub-agent-explore.md,sha256=21kFodjhvN0L-c_ZFo4y
50
50
  klaude_code/core/prompts/prompt-sub-agent-image-gen.md,sha256=tXYKSzFd04OiC0dmVO9suMKeD5f9qo_4NsvqGo7irfI,78
51
51
  klaude_code/core/prompts/prompt-sub-agent-web.md,sha256=UwrO5M_jPUbee_8lL7gB-2VFFLxvzEejluXDkMzmR5A,3625
52
52
  klaude_code/core/prompts/prompt-sub-agent.md,sha256=dmmdsOenbAOfqG6FmdR88spOLZkXmntDBs-cmZ9DN_g,897
53
- klaude_code/core/reminders.py,sha256=SOSB1wZMPdCtCwTpvjUW5et-d0JcnUxF7lMg90CZnA4,24384
53
+ klaude_code/core/reminders.py,sha256=_hD2n_QOuKZvty9o6UtndAOirhntfoO1EmmNCohrSOQ,24350
54
54
  klaude_code/core/task.py,sha256=rAgulw45GT1NMhe2P5aLCdCnAa_hOZxKzEAaPYMc6Jk,13982
55
55
  klaude_code/core/tool/__init__.py,sha256=ABUzLwQbBoZPirCcgYbI88GEtswfy1JBDkFUsGpQ-zc,1415
56
56
  klaude_code/core/tool/context.py,sha256=lHMjbLE--WVek8gAPOvaHz4CdeRGzLXSusMyEdEU5ss,2961
@@ -89,7 +89,7 @@ klaude_code/core/tool/web/web_fetch_tool.md,sha256=i0IwsZ6r9vAQeCpwDBtEGrWmHPzZk
89
89
  klaude_code/core/tool/web/web_fetch_tool.py,sha256=jXbJTgpI_RvyXy5ac8qIrC-AKOUX1fJ3TpqXq_BfkS4,9596
90
90
  klaude_code/core/tool/web/web_search_tool.md,sha256=l5gGPx-fXHFel1zLBljm8isy9pwEYXGrq5cFzzw1VBw,1135
91
91
  klaude_code/core/tool/web/web_search_tool.py,sha256=ljkgXxP6L5nJnbYB_IOUtPUN9zA_h5hBD55lhNAja08,4293
92
- klaude_code/core/turn.py,sha256=z_-0XvJsdN3omiCCQOY4wBlN7hwQ2T0fRJeY_dqLdHc,18509
92
+ klaude_code/core/turn.py,sha256=YW1tpMqCz4jEtLej0cpDy9tbs4vTFV7Cl8-5vTPCrQc,18526
93
93
  klaude_code/llm/__init__.py,sha256=b4AsqnrMIs0a5qR_ti6rZcHwFzAReTwOW96EqozEoSo,287
94
94
  klaude_code/llm/anthropic/__init__.py,sha256=PWETvaeNAAX3ue0ww1uRUIxTJG0RpWiutkn7MlwKxBs,67
95
95
  klaude_code/llm/anthropic/client.py,sha256=RpYw4UQnhLzAsp6i-FU7cDW4deqngdAoQaTPGnCeO5U,17346
@@ -124,7 +124,7 @@ klaude_code/llm/stream_parts.py,sha256=kU40BaWyiKOqzrIwF0_IwogWgKRRqVEt-6MvwMi5J
124
124
  klaude_code/llm/usage.py,sha256=L6w-DlZ3oF8lOR_SEudPBM9idzIy7__f5FZ4ZJ2smi8,5957
125
125
  klaude_code/log.py,sha256=i9iVCmp4dxqxqH_7XPMVjZt8umiH1KPhRbX4Ao93mSM,11382
126
126
  klaude_code/protocol/__init__.py,sha256=TTPnuyQ22RypoTGKdoiS7ZEgHzinuaRHUrauzHDh7Xo,246
127
- klaude_code/protocol/commands.py,sha256=MfiUgN7r7VFGh0pel4nCRnk44F2Yzdcd7xqM-M369vY,771
127
+ klaude_code/protocol/commands.py,sha256=ZgD0GoAT6j5yfF29FIupiKCcP9bq5wxUeDaqFoReOHc,733
128
128
  klaude_code/protocol/events.py,sha256=hn0mM0AOu8nF5lOPoTMQNMsVXOGbBVLh4M5Y9lTE3a0,4284
129
129
  klaude_code/protocol/llm_param.py,sha256=mFdAcbzJrIFB4T2QCbLyeZxZQ_38lUNCclEZIH3eWtQ,5191
130
130
  klaude_code/protocol/message.py,sha256=pu-wvInS781y-qSKbl9MqO7k3CtAN7Yu4hUHJCXKjZQ,6210
@@ -153,18 +153,18 @@ klaude_code/skill/assets/create-plan/SKILL.md,sha256=g_SLyBid2dwj56FBzh87lZGu1t0
153
153
  klaude_code/skill/assets/deslop/SKILL.md,sha256=XMBER6gOyYnZof_u7l30CZSzmDcINe8XP-n_loah0EQ,873
154
154
  klaude_code/skill/assets/handoff/SKILL.md,sha256=GDHrEqWUeAQy7gGhha_y5jzjpv8C-xhk0hqMH5h59v8,1712
155
155
  klaude_code/skill/assets/skill-creator/SKILL.md,sha256=0ByoWb9ao0UKSoM5Tmz-Qe5CAPliTrVpUK0gPd9TFqo,5520
156
- klaude_code/skill/loader.py,sha256=Lcj3j5H9-5wERkvOz77J9Z0uWJ3skrpVQvnzYqrpRJU,8644
157
- klaude_code/skill/manager.py,sha256=GcE6IGooYmWn75wWa2TfJj8VRaBgAlABeK3sD_bIgBY,3448
156
+ klaude_code/skill/loader.py,sha256=g3MNDBq4B4_hf_d1NXf0Zhw3Xu9M2GIiaUZIN6S1ikM,8706
157
+ klaude_code/skill/manager.py,sha256=6N1sfa0a5a7NgQgj3M_rRO2aj0vecyeBp_kWOZg211c,3452
158
158
  klaude_code/skill/system_skills.py,sha256=ryGN07t0Xv2Yn_Prfq072tdIN0Dp4ZpdXLTl7O7rCkg,6122
159
159
  klaude_code/tui/__init__.py,sha256=Q8-0D-uesw3oFwHcFLD5UaWlTFbrj8qV7dSn6C6_g_o,274
160
- klaude_code/tui/command/__init__.py,sha256=qeQYDQ93mCOgP4SdHTXcMvrqQ8xdmMiNH-nBzmMUqIw,3477
160
+ klaude_code/tui/command/__init__.py,sha256=SyEvpvytaRTv-6sJpJzlv142GUfLRYc2k5z2ZqWKxD8,3305
161
161
  klaude_code/tui/command/clear_cmd.py,sha256=9stN0blD24sME_xvTae0gN1r9caZA7QmLWnxzhTB4iA,744
162
162
  klaude_code/tui/command/command_abc.py,sha256=sTzn0LAJguDKPrXK-0wkiadf0jQuAtuXbDMfDZJ4pqk,2438
163
- klaude_code/tui/command/copy_cmd.py,sha256=T-r1tWpNCNeixHeTnaR5RWd7bNkjw10CsPERTNRBy3U,1789
163
+ klaude_code/tui/command/copy_cmd.py,sha256=2gjKYTbOspmVotD8FrU7oQgwyNxdcjYP0iLKs6AXcL4,1792
164
164
  klaude_code/tui/command/debug_cmd.py,sha256=cXi2ymcsbcJVCKfVKPvtUFPOmgNFEpwG-IcLlnkiyZY,2698
165
165
  klaude_code/tui/command/export_cmd.py,sha256=KdFlOMJ6gruKYnd_24eWJJb21t9gLVwI1FnN1s08m5U,1609
166
166
  klaude_code/tui/command/export_online_cmd.py,sha256=34De0K486wNOC5yjjPemcGTILrKQhWld2qfV3c0PUQ8,5664
167
- klaude_code/tui/command/fork_session_cmd.py,sha256=1ilbZ0FG8uuio4y-5R3toCTI6N5ZzJwNG3ZzahWnork,9235
167
+ klaude_code/tui/command/fork_session_cmd.py,sha256=mBLrRCbBYW5en73gmNBDu0AuN_AvUs_mOEpJL7Sr37k,9220
168
168
  klaude_code/tui/command/model_cmd.py,sha256=EnUcr_nnUm433G2HwEKKNssVE767IgQFNoc9etxPpmY,1734
169
169
  klaude_code/tui/command/model_picker.py,sha256=CQ5tb9sThFRon6cbibtLAtK1VR6fxmecdLUX1_h4Cng,5127
170
170
  klaude_code/tui/command/prompt-init.md,sha256=a4_FQ3gKizqs2vl9oEY5jtG6HNhv3f-1b5RSCFq0A18,1873
@@ -174,13 +174,12 @@ klaude_code/tui/command/registry.py,sha256=2HDrC6ZqGKSdzQAYra2TSFt1kc3tDliobjrWf
174
174
  klaude_code/tui/command/resume_cmd.py,sha256=XaQyoB00_TiimUNl__z5ZvRg5EdG16LXvkGAZ3H6YxU,3359
175
175
  klaude_code/tui/command/status_cmd.py,sha256=yALYGxyUX7iVdSRAKdG526YkqOvGV9F0CJNwk8nmzu4,5164
176
176
  klaude_code/tui/command/sub_agent_model_cmd.py,sha256=iz9_bdxHBSOQjjMWPP4RBW58V_HhWREweG-4cXuotk0,5610
177
- klaude_code/tui/command/terminal_setup_cmd.py,sha256=DfusD9c8eVkWPKGtQI0JvTgJnU_686huyzXsYE9TSEM,10639
178
177
  klaude_code/tui/command/thinking_cmd.py,sha256=QV3YjcyNRTrmYrujvxfR6Dt05gTK7_uompT9BNWUfgg,2684
179
178
  klaude_code/tui/commands.py,sha256=EvUzo0b8zL1NerR7gzqU-w7ehJHWY_yXMxsty9JGKKo,3261
180
179
  klaude_code/tui/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
181
180
  klaude_code/tui/components/assistant.py,sha256=3VUIGf_BJhmoWZ5bHw-QUTMElUxp-MZQKUMWNimHKLE,904
182
181
  klaude_code/tui/components/bash_syntax.py,sha256=0Pceo8w7jbK56smaVSBzkZYgCXzqqy7Qnx6kDZOh1yA,7450
183
- klaude_code/tui/components/command_output.py,sha256=n1bxmPTXysJrm2UERNeOxC9fyW57qm-DIjQ5DU10wxE,3737
182
+ klaude_code/tui/components/command_output.py,sha256=IC8smn6k6C6DGgDdlhG2prvsw2V2ZW092jifKqVMc5c,3731
184
183
  klaude_code/tui/components/common.py,sha256=dhUYLVVOSKxg5GCoS4eyUeKZ3E8Kpt4nqft4njuvPaI,4698
185
184
  klaude_code/tui/components/developer.py,sha256=1hDr7boJN1z_JyvvFNn8m7MAf4lPDN3eoqmofE0lv4Y,5414
186
185
  klaude_code/tui/components/diffs.py,sha256=JUokkkJeTIoKD0b-c-chMzIDmMjivBQqH8DYXIA3hHs,10411
@@ -191,32 +190,35 @@ klaude_code/tui/components/rich/__init__.py,sha256=zEZjnHR3Fnv_sFMxwIMjoJfwDoC4G
191
190
  klaude_code/tui/components/rich/cjk_wrap.py,sha256=eMqBxftUtll7zrytUb9WtJ6naYLyax0W4KJRpGwWulM,7602
192
191
  klaude_code/tui/components/rich/code_panel.py,sha256=ZKuJHh-kh-hIkBXSGLERLaDbJ7I9hvtvmYKocJn39_w,4744
193
192
  klaude_code/tui/components/rich/live.py,sha256=xiMT6dPsxM_jaazddKrV9CMJQWwpe2t9OdjffHvo1JU,2821
194
- klaude_code/tui/components/rich/markdown.py,sha256=dkSzovKFY8zMQqRhad9k-fpV3Iot1CxKvxe202aaP4w,19512
193
+ klaude_code/tui/components/rich/markdown.py,sha256=RqNfrbQ8sXbuLh9Zay1MLdl6SzLoLbfglTCyXi54wR8,21682
195
194
  klaude_code/tui/components/rich/quote.py,sha256=u6sBmGdp0ckaZLw_XgJk7iHW4zxnWikUaB3GX2tkhlM,5375
196
195
  klaude_code/tui/components/rich/searchable_text.py,sha256=PUe6MotKxSBY4FlPeojVjVQgxCsx_jiQ41bCzLp8WvE,2271
197
196
  klaude_code/tui/components/rich/status.py,sha256=kNt08FQGvMZJB-zUhT5UyVFA7jvuRBNqf6yDXLEhb9c,14756
198
- klaude_code/tui/components/rich/theme.py,sha256=UE70dpIOM8yXoDJk1i3qR3wwOYYEf4VuZ5khHCA8jxw,15260
197
+ klaude_code/tui/components/rich/theme.py,sha256=aAXJhRlo0sESy59-bKbdwTPpbqD4kaZWdyb84D6mM9A,15830
199
198
  klaude_code/tui/components/sub_agent.py,sha256=byCyRPq0xfit55cLwmp7SfRbCmyiXL77JklvFcbKW4M,6598
200
199
  klaude_code/tui/components/thinking.py,sha256=AXC7Xpyiu7ST-eWGLRGY7N8Dak2ny3lV3mvznmfqKmM,2890
201
200
  klaude_code/tui/components/tools.py,sha256=Up8DQbXuiPfcbiFVZD6gmZO0YBz2SExWS-tE_xeriX4,25060
202
- klaude_code/tui/components/user_input.py,sha256=6VHH77xwUUW0rW7yv8hOwGXsmK52HEsBg9-QZVbOm1A,3427
201
+ klaude_code/tui/components/user_input.py,sha256=2H-H99NtvAa3cMKl9wgxZKdWPRDg50GjDJ47OWXE08s,3693
203
202
  klaude_code/tui/components/welcome.py,sha256=ZSCcT-wFdSp3L1Fq7shWWz4Rk-BAXvsKisfvIUnP8a4,3665
204
203
  klaude_code/tui/display.py,sha256=JfMETvb1gcgymQVXPy5tH2c-B0cHjXn9PtwSiYlP-1Q,3506
204
+ klaude_code/tui/input/AGENTS.md,sha256=2RBLz7H0JbUJv6OBzeadLOlGUF5EBqvtwTGBf6nZuN0,1633
205
205
  klaude_code/tui/input/__init__.py,sha256=cAB38ypo7dHo_jgXUCnoBTUKHtiriVaKCv4YepSU9SU,276
206
- klaude_code/tui/input/clipboard.py,sha256=HjThFB9MG_YdJ76CQv7B-IUoz5JarbWUZDbUVkH1LpY,5106
207
- klaude_code/tui/input/completers.py,sha256=t9uhP2z3MJJNy1rlPk0vs-76YJUcpCdO3KFrM5w3E5Y,32932
208
- klaude_code/tui/input/key_bindings.py,sha256=2uN48J1HRHeCBqq7WrH5J82NIU59oQscce0HquAiYCI,18876
209
- klaude_code/tui/input/prompt_toolkit.py,sha256=qIb-kDJBBzFhSX3BjwxW2EKAGRQmMYvEI6TzR6hJTP8,28671
210
- klaude_code/tui/machine.py,sha256=bpqIb2DZJHPFquDClsblo2kf0KW1tIyIWJs8SKJrEWM,27542
206
+ klaude_code/tui/input/completers.py,sha256=RHf8dFDRxLlCG7Pw5feNjtKvH3yCYET1fKB7p44yICY,32869
207
+ klaude_code/tui/input/drag_drop.py,sha256=7O4CfIGnduNbDikwpr6I4ZFRPnUBg_far6_S2dZ-cvw,5265
208
+ klaude_code/tui/input/images.py,sha256=DqDKl2yt-pNzkfhKKo_ApTjJTccBCvuYDufpMeGM0d4,7090
209
+ klaude_code/tui/input/key_bindings.py,sha256=pM-sFonUzRE56H4XGVrEOuSXqGzLuvckBHnAD0fRAz4,24676
210
+ klaude_code/tui/input/paste.py,sha256=kELg5jC0WdBXWHJUsEjIhZ67KCvHMbN1XzyGmevVSNM,1888
211
+ klaude_code/tui/input/prompt_toolkit.py,sha256=dEAYw1ACvb1RjUIW8MZVlzz0dBvQGazmBoCMCVqkYkA,29012
212
+ klaude_code/tui/machine.py,sha256=xvKlbwiWRi5-RXOiPeCeed-cj5a2BYCXpNMCO0g5hcU,27541
211
213
  klaude_code/tui/renderer.py,sha256=LRF1VtUA5qLweUSlzWFEkyMcSCUwBxqExoWwY5xNE_M,26110
212
- klaude_code/tui/runner.py,sha256=nOq8wC78HzgqHLRgHC8OgYubH--2gPcDqA6GoV913Yc,11270
214
+ klaude_code/tui/runner.py,sha256=Wc0agoPSoRKbdpR-1oTnFa3tYbmF9Nkr0mkK9qltjqQ,11264
213
215
  klaude_code/tui/terminal/__init__.py,sha256=GIMnsEcIAGT_vBHvTlWEdyNmAEpruyscUA6M_j3GQZU,1412
214
216
  klaude_code/tui/terminal/color.py,sha256=6SJR2RA8cqJINNoRz65w0HL3x9g46ydIvDOGWMeNnQU,7195
215
217
  klaude_code/tui/terminal/control.py,sha256=m2fL6uHum5Li25X2IPnI4z_oVzMpVYcSldB-r0NLLzk,4920
216
- klaude_code/tui/terminal/image.py,sha256=ytzmw1J3fmaq49nWTDRmK_7aMIGbdUPCtVccSpVRHxY,1195
218
+ klaude_code/tui/terminal/image.py,sha256=hhBKJLbgeN-BFOsMdIJXKch-hdYusCzrKV2CTAIje2s,2275
217
219
  klaude_code/tui/terminal/notifier.py,sha256=-aTtgRvpzQcfbkOfbeDOfUs3l9smNBZX-60G9f0326Y,4643
218
220
  klaude_code/tui/terminal/progress_bar.py,sha256=Go-0_ZodrmJVaQodaPnyxVU2nkpkBaYLnZBqwAUQukE,2133
219
- klaude_code/tui/terminal/selector.py,sha256=QOuC0Ug251r4ii87kCXV8r2RtJ4llZh1I28edADQY8o,29338
221
+ klaude_code/tui/terminal/selector.py,sha256=7zVlZ6HIiN-Hhx79jnpeOIw5nf12NuTOaRos57m-UII,31259
220
222
  klaude_code/ui/__init__.py,sha256=3k9Sbesq0nNN3jcSMDqJ4zUcys4PKzGg4Xsum-6dZis,451
221
223
  klaude_code/ui/common.py,sha256=_KmCNM-U8VowObYkfq8e9cyuvN1dF85P56hG8tGYlts,4309
222
224
  klaude_code/ui/core/__init__.py,sha256=2NakrTDcxem5D0atyEY_Rxv1BbKCeZweF63L6AAq6r8,23
@@ -226,7 +228,7 @@ klaude_code/ui/debug_mode.py,sha256=ZvqbOx4c_rUerMbEZzOfcbNf9leqEDFjqJUlALtzF9Y,
226
228
  klaude_code/ui/terminal/__init__.py,sha256=5OeAzr994r8-peWsLON0iXsAvJ2pexwMp36JY7FKGDc,179
227
229
  klaude_code/ui/terminal/title.py,sha256=EZpLXTMhunsZPVGaxP317lH0Ad2oOh7OsjbV3yRD5is,1115
228
230
  klaude_code/update.py,sha256=QER816AZe9u3RhRvP0Z37Jh2Ch5RLy9PREyDsI0e1dA,4480
229
- klaude_code-2.6.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
230
- klaude_code-2.6.0.dist-info/entry_points.txt,sha256=kkXIXedaTOtjXPr2rVjRVVXZYlFUcBHELaqmyVlWUFA,92
231
- klaude_code-2.6.0.dist-info/METADATA,sha256=MQ4fWB0k6diVfwvnEISBPHaOxWCsKEOh4JaowkMA3VE,10431
232
- klaude_code-2.6.0.dist-info/RECORD,,
231
+ klaude_code-2.7.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
232
+ klaude_code-2.7.0.dist-info/entry_points.txt,sha256=kkXIXedaTOtjXPr2rVjRVVXZYlFUcBHELaqmyVlWUFA,92
233
+ klaude_code-2.7.0.dist-info/METADATA,sha256=9t7misNdZMZ4SItRwvxxMWn9UBVSRplqmG_0VjiPyw0,10379
234
+ klaude_code-2.7.0.dist-info/RECORD,,
@@ -1,248 +0,0 @@
1
- import os
2
- import subprocess
3
- from pathlib import Path
4
-
5
- from klaude_code.protocol import commands, events, message
6
-
7
- from .command_abc import Agent, CommandABC, CommandResult
8
-
9
-
10
- class TerminalSetupCommand(CommandABC):
11
- """Setup shift+enter newline functionality in terminal"""
12
-
13
- @property
14
- def name(self) -> commands.CommandName:
15
- return commands.CommandName.TERMINAL_SETUP
16
-
17
- @property
18
- def summary(self) -> str:
19
- return "Install shift+enter key binding for newlines"
20
-
21
- @property
22
- def is_interactive(self) -> bool:
23
- return False
24
-
25
- async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
26
- del user_input # unused
27
- term_program = os.environ.get("TERM_PROGRAM", "").lower()
28
-
29
- try:
30
- if term_program == "ghostty":
31
- message = self._setup_ghostty()
32
- elif term_program == "iterm.app":
33
- message = self._setup_iterm()
34
- elif term_program == "vscode":
35
- # VS Code family terminals (VS Code, Windsurf, Cursor) all report TERM_PROGRAM=vscode
36
- message = self._setup_vscode_family()
37
- else:
38
- # Provide generic manual configuration guide for unknown or unsupported terminals
39
- message = self._setup_generic(term_program)
40
-
41
- return self._create_success_result(agent, message)
42
-
43
- except Exception as e:
44
- return self._create_error_result(agent, f"Error configuring terminal: {e!s}")
45
-
46
- def _setup_ghostty(self) -> str:
47
- """Configure shift+enter newline for Ghostty terminal"""
48
- config_dir = Path.home() / ".config" / "ghostty"
49
- config_file = config_dir / "config"
50
-
51
- keybind_line = 'keybind="shift+enter=text:\\n"'
52
-
53
- # Ensure config directory exists
54
- config_dir.mkdir(parents=True, exist_ok=True)
55
-
56
- # Check if configuration already exists in config file
57
- if config_file.exists():
58
- content = config_file.read_text()
59
- if keybind_line in content or 'keybind="shift+enter=' in content:
60
- return "Ghostty terminal shift+enter newline configuration already exists"
61
-
62
- # Add configuration
63
- with config_file.open("a", encoding="utf-8") as f:
64
- if config_file.exists() and not config_file.read_text().endswith("\n"):
65
- f.write("\n")
66
- f.write(f"{keybind_line}\n")
67
-
68
- return f"Added shift+enter newline configuration for Ghostty terminal to {config_file}"
69
-
70
- def _setup_iterm(self) -> str:
71
- """Configure shift+enter newline for iTerm terminal using defaults command"""
72
- try:
73
- # First check if iTerm preferences exist
74
- prefs_path = Path.home() / "Library" / "Preferences" / "com.googlecode.iterm2.plist"
75
- if not prefs_path.exists():
76
- return "iTerm preferences file not found. Please open iTerm first to create initial preferences."
77
-
78
- # Check if the key binding already exists
79
- check_cmd = ["defaults", "read", "com.googlecode.iterm2", "New Bookmarks"]
80
-
81
- try:
82
- result = subprocess.run(check_cmd, capture_output=True, text=True, check=True)
83
- # If we can read bookmarks, iTerm is properly configured
84
- except subprocess.CalledProcessError:
85
- return "Unable to read iTerm configuration. Please ensure iTerm is properly installed and has been opened at least once."
86
-
87
- # Add to the default profile's keyboard map
88
- add_keymap_cmd = [
89
- "defaults",
90
- "write",
91
- "com.googlecode.iterm2",
92
- "GlobalKeyMap",
93
- "-dict-add",
94
- # Do not include quotes when passing args as a list (no shell)
95
- "0x0d-0x20000",
96
- # Pass Property List dict directly; \n should be literal backslash-n so iTerm parses newline
97
- '{Action=12;Text="\\\\n";}',
98
- ]
99
- # Execute without shell so arguments are passed correctly
100
- result = subprocess.run(add_keymap_cmd, capture_output=True, text=True)
101
- print(result.stdout, result.stderr)
102
- if result.returncode == 0:
103
- return "Successfully configured Shift+Enter for newline in iTerm. Please restart iTerm for changes to take effect."
104
- else:
105
- # Fallback to manual instructions if defaults command fails
106
- return (
107
- "Automatic configuration failed. Please manually configure:\n"
108
- "1. Open iTerm -> Preferences (⌘,)\n"
109
- "2. Go to Profiles -> Keys -> Key Mappings\n"
110
- "3. Click '+' to add: Shift+Enter -> Send Text -> \\n"
111
- )
112
-
113
- except Exception as e:
114
- raise Exception(f"Error configuring iTerm: {e!s}") from e
115
-
116
- def _setup_vscode_family(self) -> str:
117
- """Configure shift+enter newline for VS Code family terminals (VS Code, Windsurf, Cursor).
118
-
119
- These editors share TERM_PROGRAM=vscode and use keybindings.json under their respective
120
- Application Support folders. We ensure the required keybinding exists; if not, we append it.
121
- """
122
- base_dir = Path.home() / "Library" / "Application Support"
123
- targets = [
124
- ("VS Code", base_dir / "Code" / "User" / "keybindings.json"),
125
- ("Windsurf", base_dir / "Windsurf" / "User" / "keybindings.json"),
126
- ("Cursor", base_dir / "Cursor" / "User" / "keybindings.json"),
127
- ]
128
-
129
- mapping_block = r""" {
130
- "key": "shift+enter",
131
- "command": "workbench.action.terminal.sendSequence",
132
- "args": {
133
- "text": "\\\r\n"
134
- },
135
- "when": "terminalFocus"
136
- }"""
137
-
138
- results: list[str] = []
139
-
140
- for name, file_path in targets:
141
- try:
142
- _, msg = self._ensure_vscode_keybinding(file_path, mapping_block)
143
- results.append(f"{name}: {msg}")
144
- except Exception as e: # pragma: no cover - protect against any unexpected FS issue
145
- results.append(f"{name}: failed to update keybindings ({e})")
146
-
147
- return "\n".join(results)
148
-
149
- def _ensure_vscode_keybinding(self, path: Path, mapping_block: str) -> tuple[bool, str]:
150
- """Ensure the VS Code-style keybinding exists in the given keybindings.json file.
151
-
152
- Returns (added, message).
153
- - added=True if we created or modified the file to include the mapping
154
- - added=False if mapping already present or file couldn't be safely modified
155
- """
156
- path.parent.mkdir(parents=True, exist_ok=True)
157
-
158
- # If file does not exist, create with the mapping in an array
159
- if not path.exists():
160
- content = "[\n " + mapping_block + "\n]\n"
161
- path.write_text(content, encoding="utf-8")
162
- return True, f"created {path} with Shift+Enter mapping"
163
-
164
- # Read existing content
165
- raw = path.read_text(encoding="utf-8")
166
- text = raw
167
-
168
- # Quick detection: if both key and command exist together anywhere, assume configured
169
- if '"key": "shift+enter"' in text and "workbench.action.terminal.sendSequence" in text:
170
- return False, "already configured"
171
-
172
- stripped = text.strip()
173
- # If file is empty, write a fresh array
174
- if stripped == "":
175
- content = "[\n " + mapping_block + "\n]\n"
176
- path.write_text(content, encoding="utf-8")
177
- return True, "initialized empty keybindings.json with mapping"
178
-
179
- # If the content contains a top-level array (allowing header comments), append before the final ]
180
- open_idx = text.find("[")
181
- close_idx = text.rfind("]")
182
- if open_idx != -1 and close_idx != -1 and open_idx < close_idx:
183
- before = text[:close_idx].rstrip()
184
- after = text[close_idx:]
185
-
186
- # Heuristic: treat as non-empty if there's an object marker between [ and ]
187
- inner = text[open_idx + 1 : close_idx]
188
- has_item = "{" in inner
189
-
190
- # Construct new content by adding optional comma, newline, then our block
191
- new_content = before + ("," if has_item else "") + "\n" + mapping_block + "\n" + after
192
-
193
- path.write_text(new_content, encoding="utf-8")
194
- return True, "appended mapping"
195
-
196
- # Not an array – avoid modifying to prevent corrupting user config
197
- return (
198
- False,
199
- "unsupported keybindings.json format (not an array); please add mapping manually",
200
- )
201
-
202
- def _setup_generic(self, term_program: str) -> str:
203
- """Provide generic manual configuration guide for unknown or unsupported terminals"""
204
- if term_program:
205
- intro = f"Terminal type '{term_program}' is not specifically supported, but you can manually configure shift+enter newline functionality."
206
- else:
207
- intro = "Unable to detect terminal type, but you can manually configure shift+enter newline functionality."
208
-
209
- message = (
210
- f"{intro}\n\n"
211
- "General steps to configure shift+enter for newline:\n"
212
- "1. Open your terminal's preferences/settings\n"
213
- "2. Look for 'Key Bindings', 'Key Mappings', or 'Keyboard' section\n"
214
- "3. Add a new key binding:\n"
215
- " - Key combination: Shift+Enter\n"
216
- " - Action: Send text or Insert text\n"
217
- " - Text to send: \\n (literal newline character)\n"
218
- "4. Save the configuration\n\n"
219
- "Note: The exact steps may vary depending on your terminal application. "
220
- "Currently supported terminals with automatic configuration: Ghostty, iTerm.app, VS Code family (VS Code, Windsurf, Cursor)"
221
- )
222
-
223
- return message
224
-
225
- def _create_success_result(self, agent: "Agent", msg: str) -> CommandResult:
226
- """Create success result"""
227
- return CommandResult(
228
- events=[
229
- events.CommandOutputEvent(
230
- session_id=agent.session.id,
231
- command_name=self.name,
232
- content=msg,
233
- )
234
- ]
235
- )
236
-
237
- def _create_error_result(self, agent: "Agent", msg: str) -> CommandResult:
238
- """Create error result"""
239
- return CommandResult(
240
- events=[
241
- events.CommandOutputEvent(
242
- session_id=agent.session.id,
243
- command_name=self.name,
244
- content=msg,
245
- is_error=True,
246
- )
247
- ]
248
- )
@@ -1,152 +0,0 @@
1
- """Clipboard and image handling for REPL input.
2
-
3
- This module provides:
4
- - ClipboardCaptureState: Captures clipboard images and maps tags to file paths
5
- - capture_clipboard_tag(): Capture clipboard image and return tag
6
- - extract_images_from_text(): Parse tags and return ImageURLPart list
7
- - copy_to_clipboard(): Copy text to system clipboard
8
- """
9
-
10
- from __future__ import annotations
11
-
12
- import re
13
- import shutil
14
- import subprocess
15
- import sys
16
- import uuid
17
- from base64 import b64encode
18
- from pathlib import Path
19
-
20
- from PIL import Image, ImageGrab
21
-
22
- from klaude_code.protocol.message import ImageURLPart
23
-
24
- # Directory for storing clipboard images
25
- CLIPBOARD_IMAGES_DIR = Path.home() / ".klaude" / "clipboard" / "images"
26
-
27
- # Pattern to match [Image #N] tags in user input
28
- _IMAGE_TAG_RE = re.compile(r"\[Image #(\d+)\]")
29
-
30
-
31
- class ClipboardCaptureState:
32
- """Captures clipboard images and maps tags to file paths in memory."""
33
-
34
- def __init__(self, images_dir: Path | None = None):
35
- self._images_dir = images_dir or CLIPBOARD_IMAGES_DIR
36
- self._pending: dict[str, str] = {} # tag -> path mapping
37
- self._counter = 1
38
-
39
- def capture_from_clipboard(self) -> str | None:
40
- """Capture image from clipboard, save to disk, and return a tag like [Image #N]."""
41
- try:
42
- clipboard_data = ImageGrab.grabclipboard()
43
- except OSError:
44
- return None
45
- if not isinstance(clipboard_data, Image.Image):
46
- return None
47
- try:
48
- self._images_dir.mkdir(parents=True, exist_ok=True)
49
- except OSError:
50
- return None
51
- filename = f"clipboard_{uuid.uuid4().hex[:8]}.png"
52
- path = self._images_dir / filename
53
- try:
54
- clipboard_data.save(path, "PNG")
55
- except OSError:
56
- return None
57
- tag = f"[Image #{self._counter}]"
58
- self._counter += 1
59
- self._pending[tag] = str(path)
60
- return tag
61
-
62
- def get_pending_images(self) -> dict[str, str]:
63
- """Return the current tag-to-path mapping for pending images."""
64
- return dict(self._pending)
65
-
66
- def flush(self) -> dict[str, str]:
67
- """Flush pending images and return tag-to-path mapping, then reset state."""
68
- result = dict(self._pending)
69
- self._pending = {}
70
- self._counter = 1
71
- return result
72
-
73
-
74
- # Module-level singleton instance
75
- clipboard_state = ClipboardCaptureState()
76
-
77
-
78
- def capture_clipboard_tag() -> str | None:
79
- """Capture image from clipboard and return tag like [Image #N].
80
-
81
- Uses the module-level clipboard_state singleton. Returns None if no image
82
- is available in the clipboard or capture fails.
83
- """
84
- return clipboard_state.capture_from_clipboard()
85
-
86
-
87
- def extract_images_from_text(text: str) -> list[ImageURLPart]:
88
- """Extract images from pending clipboard state based on tags in text.
89
-
90
- Parses [Image #N] tags in the text, looks up corresponding image paths
91
- in the clipboard state, and creates ImageURLPart objects from them.
92
- Flushes the clipboard state after extraction.
93
- """
94
- pending_images = clipboard_state.flush()
95
- if not pending_images:
96
- return []
97
-
98
- # Find all [Image #N] tags in text
99
- found_tags = set(_IMAGE_TAG_RE.findall(text))
100
- if not found_tags:
101
- return []
102
-
103
- images: list[ImageURLPart] = []
104
- for tag, path in pending_images.items():
105
- # Extract the number from the tag and check if it's referenced
106
- match = _IMAGE_TAG_RE.match(tag)
107
- if match and match.group(1) in found_tags:
108
- image_part = _encode_image_file(path)
109
- if image_part:
110
- images.append(image_part)
111
-
112
- return images
113
-
114
-
115
- def _encode_image_file(file_path: str) -> ImageURLPart | None:
116
- """Encode an image file as base64 data URL and create ImageURLPart."""
117
- try:
118
- path = Path(file_path)
119
- if not path.exists():
120
- return None
121
- with open(path, "rb") as f:
122
- encoded = b64encode(f.read()).decode("ascii")
123
- # Clipboard images are always saved as PNG
124
- data_url = f"data:image/png;base64,{encoded}"
125
- return ImageURLPart(url=data_url, id=None)
126
- except OSError:
127
- return None
128
-
129
-
130
- def copy_to_clipboard(text: str) -> None:
131
- """Copy text to system clipboard using platform-specific commands."""
132
- try:
133
- if sys.platform == "darwin":
134
- subprocess.run(["pbcopy"], input=text.encode("utf-8"), check=True)
135
- elif sys.platform == "win32":
136
- subprocess.run(["clip"], input=text.encode("utf-16"), check=True)
137
- else:
138
- # Linux: try xclip first, then xsel
139
- if shutil.which("xclip"):
140
- subprocess.run(
141
- ["xclip", "-selection", "clipboard"],
142
- input=text.encode("utf-8"),
143
- check=True,
144
- )
145
- elif shutil.which("xsel"):
146
- subprocess.run(
147
- ["xsel", "--clipboard", "--input"],
148
- input=text.encode("utf-8"),
149
- check=True,
150
- )
151
- except (OSError, subprocess.SubprocessError):
152
- pass