klaude-code 1.2.23__py3-none-any.whl → 1.2.25__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/cli/runtime.py +17 -1
  2. klaude_code/command/prompt-jj-describe.md +32 -0
  3. klaude_code/command/thinking_cmd.py +37 -28
  4. klaude_code/{const/__init__.py → const.py} +7 -6
  5. klaude_code/core/executor.py +46 -3
  6. klaude_code/core/tool/file/read_tool.py +23 -1
  7. klaude_code/core/tool/file/write_tool.py +7 -3
  8. klaude_code/llm/openai_compatible/client.py +29 -102
  9. klaude_code/llm/openai_compatible/stream.py +272 -0
  10. klaude_code/llm/openrouter/client.py +29 -109
  11. klaude_code/llm/openrouter/{reasoning_handler.py → reasoning.py} +24 -2
  12. klaude_code/protocol/model.py +13 -1
  13. klaude_code/protocol/op.py +11 -0
  14. klaude_code/protocol/op_handler.py +5 -0
  15. klaude_code/ui/core/stage_manager.py +0 -3
  16. klaude_code/ui/modes/repl/display.py +2 -0
  17. klaude_code/ui/modes/repl/event_handler.py +97 -57
  18. klaude_code/ui/modes/repl/input_prompt_toolkit.py +25 -4
  19. klaude_code/ui/modes/repl/renderer.py +119 -25
  20. klaude_code/ui/renderers/assistant.py +1 -1
  21. klaude_code/ui/renderers/metadata.py +2 -6
  22. klaude_code/ui/renderers/sub_agent.py +28 -5
  23. klaude_code/ui/renderers/thinking.py +16 -10
  24. klaude_code/ui/renderers/tools.py +26 -2
  25. klaude_code/ui/rich/code_panel.py +24 -5
  26. klaude_code/ui/rich/live.py +17 -0
  27. klaude_code/ui/rich/markdown.py +185 -107
  28. klaude_code/ui/rich/status.py +19 -17
  29. klaude_code/ui/rich/theme.py +63 -12
  30. {klaude_code-1.2.23.dist-info → klaude_code-1.2.25.dist-info}/METADATA +2 -1
  31. {klaude_code-1.2.23.dist-info → klaude_code-1.2.25.dist-info}/RECORD +33 -32
  32. klaude_code/llm/openai_compatible/stream_processor.py +0 -83
  33. {klaude_code-1.2.23.dist-info → klaude_code-1.2.25.dist-info}/WHEEL +0 -0
  34. {klaude_code-1.2.23.dist-info → klaude_code-1.2.25.dist-info}/entry_points.txt +0 -0
@@ -22,7 +22,7 @@ BREATHING_SPINNER_NAME = "dots"
22
22
 
23
23
  # Alternating glyphs for the breathing spinner - switches at each "transparent" point
24
24
  _BREATHING_SPINNER_GLYPHS_BASE = [
25
- "",
25
+ "",
26
26
  ]
27
27
 
28
28
  # Shuffle glyphs on module load for variety across sessions
@@ -56,18 +56,12 @@ def _shimmer_profile(main_text: str) -> list[tuple[str, float]]:
56
56
  char_count = len(chars)
57
57
  period = char_count + padding * 2
58
58
 
59
- # Keep a roughly constant shimmer speed (characters per second)
60
- # regardless of text length by deriving a character velocity from a
61
- # baseline text length and the configured sweep duration.
62
- # The baseline is chosen to be close to the default
63
- # "Thinking … (esc to interrupt)" status line.
64
- baseline_chars = 30
65
- base_period = baseline_chars + padding * 2
66
- sweep_seconds = const.STATUS_SHIMMER_SWEEP_SECONDS
67
- char_speed = base_period / sweep_seconds if sweep_seconds > 0 else base_period
59
+ # Use same period as breathing spinner for visual consistency
60
+ sweep_seconds = max(const.SPINNER_BREATH_PERIOD_SECONDS, 0.1)
68
61
 
69
62
  elapsed = _elapsed_since_start()
70
- pos_f = (elapsed * char_speed) % float(period)
63
+ # Complete one full sweep in sweep_seconds, regardless of text length
64
+ pos_f = (elapsed / sweep_seconds % 1.0) * period
71
65
  pos = int(pos_f)
72
66
  band_half_width = const.STATUS_SHIMMER_BAND_HALF_WIDTH
73
67
 
@@ -169,9 +163,19 @@ class ShimmerStatusText:
169
163
  Supports optional right-aligned text that stays fixed at the right edge.
170
164
  """
171
165
 
172
- def __init__(self, main_text: str | Text, main_style: ThemeKey, right_text: Text | None = None) -> None:
173
- self._main_text = main_text if isinstance(main_text, Text) else Text(main_text)
174
- self._main_style = main_style
166
+ def __init__(
167
+ self,
168
+ main_text: str | Text,
169
+ right_text: Text | None = None,
170
+ main_style: ThemeKey = ThemeKey.STATUS_TEXT,
171
+ ) -> None:
172
+ if isinstance(main_text, Text):
173
+ text = main_text.copy()
174
+ if not text.style:
175
+ text.style = str(main_style)
176
+ self._main_text = text
177
+ else:
178
+ self._main_text = Text(main_text, style=main_style)
175
179
  self._hint_text = Text(const.STATUS_HINT_TEXT)
176
180
  self._hint_style = ThemeKey.STATUS_HINT
177
181
  self._right_text = right_text
@@ -193,13 +197,11 @@ class ShimmerStatusText:
193
197
  def _render_left_text(self, console: Console) -> Text:
194
198
  """Render the left part with shimmer effect on main text only."""
195
199
  result = Text()
196
- main_style = console.get_style(str(self._main_style))
197
200
  hint_style = console.get_style(str(self._hint_style))
198
201
 
199
202
  # Apply shimmer only to main text
200
203
  for index, (ch, intensity) in enumerate(_shimmer_profile(self._main_text.plain)):
201
- char_style = self._main_text.get_style_at_offset(console, index)
202
- base_style = main_style + char_style
204
+ base_style = self._main_text.get_style_at_offset(console, index)
203
205
  style = _shimmer_style(console, base_style, intensity)
204
206
  result.append(ch, style=style)
205
207
 
@@ -25,7 +25,18 @@ class Palette:
25
25
  diff_remove: str
26
26
  diff_remove_char: str
27
27
  code_theme: str
28
- text_background: str
28
+ code_background: str
29
+ green_background: str
30
+ blue_grey_background: str
31
+ # Sub-agent backgrounds (corresponding to sub_agent_colors order)
32
+ cyan_background: str
33
+ green_sub_background: str
34
+ blue_sub_background: str
35
+ purple_background: str
36
+ orange_background: str
37
+ red_background: str
38
+ grey_background: str
39
+ yellow_background: str
29
40
 
30
41
 
31
42
  LIGHT_PALETTE = Palette(
@@ -47,7 +58,17 @@ LIGHT_PALETTE = Palette(
47
58
  diff_remove="#82071e on #ffecec",
48
59
  diff_remove_char="#82071e on #ffcfcf",
49
60
  code_theme="ansi_light",
50
- text_background="#e0e0e0",
61
+ code_background="#e0e0e0",
62
+ green_background="#e8f1e9",
63
+ blue_grey_background="#e8e9f1",
64
+ cyan_background="#e0f0f0",
65
+ green_sub_background="#e0f0e0",
66
+ blue_sub_background="#e0e8f5",
67
+ purple_background="#ede0f5",
68
+ orange_background="#f5ebe0",
69
+ red_background="#f5e0e0",
70
+ grey_background="#e8e8e8",
71
+ yellow_background="#f5f5e0",
51
72
  )
52
73
 
53
74
  DARK_PALETTE = Palette(
@@ -69,12 +90,26 @@ DARK_PALETTE = Palette(
69
90
  diff_remove="#ffcdd2 on #3d1f23",
70
91
  diff_remove_char="#ffcdd2 on #7a3a42",
71
92
  code_theme="ansi_dark",
72
- text_background="#2f3440",
93
+ code_background="#2f3440",
94
+ green_background="#23342c",
95
+ blue_grey_background="#313848",
96
+ cyan_background="#1a3333",
97
+ green_sub_background="#1b3928",
98
+ blue_sub_background="#1a2a3d",
99
+ purple_background="#2a2640",
100
+ orange_background="#3d2a1a",
101
+ red_background="#3d1f23",
102
+ grey_background="#2a2d30",
103
+ yellow_background="#3d3a1a",
73
104
  )
74
105
 
75
106
 
76
107
  class ThemeKey(str, Enum):
77
108
  LINES = "lines"
109
+
110
+ # PANEL
111
+ SUB_AGENT_RESULT_PANEL = "panel.sub_agent_result"
112
+ WRITE_MARKDOWN_PANEL = "panel.write_markdown"
78
113
  # DIFF
79
114
  DIFF_FILE_NAME = "diff.file_name"
80
115
  DIFF_REMOVE = "diff.remove"
@@ -92,9 +127,9 @@ class ThemeKey(str, Enum):
92
127
  METADATA_DIM = "metadata.dim"
93
128
  METADATA_BOLD = "metadata.bold"
94
129
  # SPINNER_STATUS
95
- SPINNER_STATUS = "spinner.status"
96
- SPINNER_STATUS_TEXT = "spinner.status.text"
97
- SPINNER_STATUS_TEXT_BOLD = "spinner.status.text.bold"
130
+ STATUS_SPINNER = "spinner.status"
131
+ STATUS_TEXT = "spinner.status.text"
132
+ STATUS_TEXT_BOLD = "spinner.status.text.bold"
98
133
  # STATUS
99
134
  STATUS_HINT = "status.hint"
100
135
  # USER_INPUT
@@ -162,6 +197,7 @@ class Themes:
162
197
  thinking_markdown_theme: Theme
163
198
  code_theme: str
164
199
  sub_agent_colors: list[Style]
200
+ sub_agent_backgrounds: list[Style]
165
201
 
166
202
 
167
203
  def get_theme(theme: str | None = None) -> Themes:
@@ -170,6 +206,9 @@ def get_theme(theme: str | None = None) -> Themes:
170
206
  app_theme=Theme(
171
207
  styles={
172
208
  ThemeKey.LINES.value: palette.grey3,
209
+ # PANEL
210
+ ThemeKey.SUB_AGENT_RESULT_PANEL.value: f"on {palette.blue_grey_background}",
211
+ ThemeKey.WRITE_MARKDOWN_PANEL.value: f"on {palette.green_background}",
173
212
  # DIFF
174
213
  ThemeKey.DIFF_FILE_NAME.value: palette.blue,
175
214
  ThemeKey.DIFF_REMOVE.value: palette.diff_remove,
@@ -183,7 +222,7 @@ def get_theme(theme: str | None = None) -> Themes:
183
222
  ThemeKey.ERROR_BOLD.value: "bold " + palette.red,
184
223
  ThemeKey.INTERRUPT.value: "reverse bold " + palette.red,
185
224
  # USER_INPUT
186
- ThemeKey.USER_INPUT.value: palette.magenta,
225
+ ThemeKey.USER_INPUT.value: "bold " + palette.magenta,
187
226
  ThemeKey.USER_INPUT_PROMPT.value: "bold " + palette.magenta,
188
227
  ThemeKey.USER_INPUT_AT_PATTERN.value: palette.purple,
189
228
  ThemeKey.USER_INPUT_SLASH_COMMAND.value: "bold reverse " + palette.blue,
@@ -192,11 +231,10 @@ def get_theme(theme: str | None = None) -> Themes:
192
231
  ThemeKey.METADATA.value: palette.lavender,
193
232
  ThemeKey.METADATA_DIM.value: "dim " + palette.lavender,
194
233
  ThemeKey.METADATA_BOLD.value: "bold " + palette.lavender,
195
- # SPINNER_STATUS
196
- ThemeKey.SPINNER_STATUS.value: palette.blue,
197
- ThemeKey.SPINNER_STATUS_TEXT.value: palette.blue,
198
- ThemeKey.SPINNER_STATUS_TEXT_BOLD.value: "bold " + palette.blue,
199
234
  # STATUS
235
+ ThemeKey.STATUS_SPINNER.value: palette.blue,
236
+ ThemeKey.STATUS_TEXT.value: palette.blue,
237
+ ThemeKey.STATUS_TEXT_BOLD.value: "bold italic " + palette.blue,
200
238
  ThemeKey.STATUS_HINT.value: palette.grey2,
201
239
  # REMINDER
202
240
  ThemeKey.REMINDER.value: palette.grey1,
@@ -265,7 +303,10 @@ def get_theme(theme: str | None = None) -> Themes:
265
303
  ),
266
304
  thinking_markdown_theme=Theme(
267
305
  styles={
268
- "markdown.code": palette.grey1 + " italic on " + palette.text_background,
306
+ # THINKING (used for left-side mark in thinking output)
307
+ ThemeKey.THINKING.value: "italic " + palette.grey2,
308
+ ThemeKey.THINKING_BOLD.value: "bold italic " + palette.grey1,
309
+ "markdown.code": palette.grey1 + " italic on " + palette.code_background,
269
310
  "markdown.code.block": palette.grey1,
270
311
  "markdown.code.border": palette.grey3,
271
312
  "markdown.h1": "bold reverse",
@@ -292,4 +333,14 @@ def get_theme(theme: str | None = None) -> Themes:
292
333
  Style(color=palette.grey1),
293
334
  Style(color=palette.yellow),
294
335
  ],
336
+ sub_agent_backgrounds=[
337
+ Style(bgcolor=palette.cyan_background),
338
+ Style(bgcolor=palette.green_sub_background),
339
+ Style(bgcolor=palette.blue_sub_background),
340
+ Style(bgcolor=palette.purple_background),
341
+ Style(bgcolor=palette.orange_background),
342
+ Style(bgcolor=palette.red_background),
343
+ Style(bgcolor=palette.grey_background),
344
+ Style(bgcolor=palette.yellow_background),
345
+ ],
295
346
  )
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: klaude-code
3
- Version: 1.2.23
3
+ Version: 1.2.25
4
4
  Summary: Add your description here
5
5
  Requires-Dist: anthropic>=0.66.0
6
6
  Requires-Dist: chardet>=5.2.0
7
7
  Requires-Dist: ddgs>=9.9.3
8
8
  Requires-Dist: diff-match-patch>=20241021
9
+ Requires-Dist: markdown-it-py>=4.0.0
9
10
  Requires-Dist: openai>=1.102.0
10
11
  Requires-Dist: pillow>=12.0.0
11
12
  Requires-Dist: prompt-toolkit>=3.0.52
@@ -11,7 +11,7 @@ klaude_code/cli/config_cmd.py,sha256=SBFmBnHvkf5IJtpsDDuHsHWQCmYd2i4PtIMBOKpxmOM
11
11
  klaude_code/cli/debug.py,sha256=vizBXc3648vBZQonreMqvv_b5UdRgcQoOIT-iEIx1G4,2318
12
12
  klaude_code/cli/list_model.py,sha256=9YOxhWE0J59NaY-SrgPA9_jA1A8rlOGwWmzK0TRuos4,8011
13
13
  klaude_code/cli/main.py,sha256=pyU2W2X3lg7Z-4adiOzA9_2l-5QSejYm68HrhAiu470,10469
14
- klaude_code/cli/runtime.py,sha256=0qYbtTP41m0K8eA2de_VFuERTV1NHn265O1-BMcdrw0,14238
14
+ klaude_code/cli/runtime.py,sha256=XqF1d53UnIgnmnlqKGR3YBdBNlBFuoyc7BvUfr22CGw,14824
15
15
  klaude_code/cli/self_update.py,sha256=fekLNRm3ivZ-Xbc-79rcgDBXbq-Zb-BkSQOGMRLeTAs,7986
16
16
  klaude_code/cli/session_cmd.py,sha256=jAopkqq_DGgoDIcGxT-RSzn9R4yqBC8NCaNgK1GLqnQ,2634
17
17
  klaude_code/command/__init__.py,sha256=B39fxrrvxb51B6qeQJoh3lXWCsPoI81BJvdSLb-8CYg,3117
@@ -23,20 +23,21 @@ klaude_code/command/export_online_cmd.py,sha256=kOVmFEW7gEEFvaKnXL8suNenktLyTW-1
23
23
  klaude_code/command/help_cmd.py,sha256=yQJnVtj6sgXQdGsi4u9aS7EcjJLSrXccUA-v_bqmsRw,1633
24
24
  klaude_code/command/model_cmd.py,sha256=GmDln1N6u7eWLK15tm_lcdDJBY8qI0ih48h6AhijafI,1665
25
25
  klaude_code/command/prompt-init.md,sha256=a4_FQ3gKizqs2vl9oEY5jtG6HNhv3f-1b5RSCFq0A18,1873
26
+ klaude_code/command/prompt-jj-describe.md,sha256=n-7hiXU8oodCMR3ipNyRR86pAUzXMz6seloU9a6QQnY,974
26
27
  klaude_code/command/prompt_command.py,sha256=rMi-ZRLpUSt1t0IQVtwnzIYqcrXK-MwZrabbZ8dc8U4,2774
27
28
  klaude_code/command/refresh_cmd.py,sha256=575eJ5IsOc1e_7CulMxvTu5GQ6BaXTG1k8IsAqzrwdQ,1244
28
29
  klaude_code/command/registry.py,sha256=avTjsoyLv11SsLsY_qb3OpsRjsSyxIlu7uwJI0Nq6HE,6176
29
30
  klaude_code/command/release_notes_cmd.py,sha256=FIrBRfKTlXEp8mBh15buNjgOrl_GMX7FeeMWxYYBn1o,2674
30
31
  klaude_code/command/status_cmd.py,sha256=sYmzfex7RVhgrBCjRyD8fsZ6ioZvjVzQ_-FvmcsA7fo,5365
31
32
  klaude_code/command/terminal_setup_cmd.py,sha256=SivM1gX_anGY_8DCQNFZ5VblFqt4sVgCMEWPRlo6K5w,10911
32
- klaude_code/command/thinking_cmd.py,sha256=XDyq0q8eb3Os4FyWjr-moiKjmzGIaNhOC9h89y1AZ84,8854
33
+ klaude_code/command/thinking_cmd.py,sha256=8EdSN6huXihM5NHJEryZLA7CkgRT7mZgMVTJsT1-x8U,9108
33
34
  klaude_code/config/__init__.py,sha256=Qrqvi8nizkj6N77h2vDj0r4rbgCiqxvz2HLBPFuWulA,120
34
35
  klaude_code/config/config.py,sha256=2jvM6a8zoC-TdRFaLIw3OW5paxxeXC6l-o05ds4RysA,7263
35
36
  klaude_code/config/select_model.py,sha256=KCdFjaoHXyO9QidNna_OGdDrvlEXtRUXKfG-F8kdNLk,5188
36
- klaude_code/const/__init__.py,sha256=yZCljtZYt0FPIczkU8i9v26Nvipn5x6OPeBE8L8A8wI,4396
37
+ klaude_code/const.py,sha256=Hj7tBQLk51eELV-_nnE8nFoAvB_UKTeTkcr929f4hEI,4399
37
38
  klaude_code/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
39
  klaude_code/core/agent.py,sha256=bWm-UFX_0-KAy5j_YHH8X8o3MJT4-40Ni2EaDP2SL5k,5819
39
- klaude_code/core/executor.py,sha256=HmKtj0ZremRcLCGHkPckR_k0FSZh6FZ52-LMRSMZK9c,24882
40
+ klaude_code/core/executor.py,sha256=MkfKPOZWknjyQzSUl_qCGRxsyYY9zetQVnerO_dWqx4,26827
40
41
  klaude_code/core/manager/__init__.py,sha256=hdIbpnYj6i18byiWjtJIm5l7NYYDQMvafw8fePVPydc,562
41
42
  klaude_code/core/manager/llm_clients.py,sha256=X2oMFWgJcP0tK8GEtMMDYR3HyR6_H8FuyCqpzWF5x2k,871
42
43
  klaude_code/core/manager/llm_clients_builder.py,sha256=pPZ_xBh-_ipV66L-9a1fnwNos4iik82Zkq0E0y3WrfI,1521
@@ -64,9 +65,9 @@ klaude_code/core/tool/file/diff_builder.py,sha256=b53S4Ebw7aPmd9AZ97Pxu6MRcnUIdV
64
65
  klaude_code/core/tool/file/edit_tool.md,sha256=rEcUjJuPC46t1nXWjTDxplDcxWDbzTWsr6_bYt5_aRI,1110
65
66
  klaude_code/core/tool/file/edit_tool.py,sha256=wuXISJRTWobNCKjkQ01UpoA13I0Zxcg1r7hXErAQxnQ,10897
66
67
  klaude_code/core/tool/file/read_tool.md,sha256=74SLSl1tq3L0por73M0QV_ws41MRIvGXQpfLb8dmtp0,1351
67
- klaude_code/core/tool/file/read_tool.py,sha256=d51eVmDWNVnrhoHyL5_crB8cvCpBNH6S00VAzJfyLgg,12076
68
+ klaude_code/core/tool/file/read_tool.py,sha256=HFA4lYaS_eV9C0UjXCuIVXhbD6OKrpkq4WN33z0EgP0,12877
68
69
  klaude_code/core/tool/file/write_tool.md,sha256=CNnYgtieUasuHdpXLDpTEsqe492Pf7v75M4RQ3oIer8,613
69
- klaude_code/core/tool/file/write_tool.py,sha256=YLQca640fUNA1P95qX52A7I-PaJuReEOLlxRnDcSe44,5414
70
+ klaude_code/core/tool/file/write_tool.py,sha256=j9OCPnCXIg4RC-DF5yw7U5_X1KMNBnqxn1exF-XqFeo,5682
70
71
  klaude_code/core/tool/report_back_tool.py,sha256=KRZzQAIxniwXe58SDJcfK_DCf9TFFAx8XC75wPEjmpY,3246
71
72
  klaude_code/core/tool/shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
73
  klaude_code/core/tool/shell/bash_tool.md,sha256=ILKpnRCBTkU2uSDEdZQjNYo1l6hsM4TO-3RD5zWC61c,3935
@@ -104,14 +105,14 @@ klaude_code/llm/codex/__init__.py,sha256=8vN2j2ezWB_UVpfqQ8ooStsBeLL5SY4SUMXOXdW
104
105
  klaude_code/llm/codex/client.py,sha256=0BAOiLAdk2PxBEYuC_TGOs4_h6yfNZr1YWuf1lzkBxM,5329
105
106
  klaude_code/llm/input_common.py,sha256=NxiYlhGRFntiLiKm5sKLCF0xGYW6DwcyvIhj6KAZoeU,8533
106
107
  klaude_code/llm/openai_compatible/__init__.py,sha256=ACGpnki7k53mMcCl591aw99pm9jZOZk0ghr7atOfNps,81
107
- klaude_code/llm/openai_compatible/client.py,sha256=ctGJAZkg3vUNN34RoTTZsakC22u4kVNmtOmun1GszvU,7991
108
+ klaude_code/llm/openai_compatible/client.py,sha256=sMzHxaDZ4CRDgwSr1pZPqpG6YbHJA-Zk0cFyC_r-ihA,4396
108
109
  klaude_code/llm/openai_compatible/input.py,sha256=rtWVjpwb9tLrinucezmncQXet8MerUxE5Gxc32sfDr4,3750
109
- klaude_code/llm/openai_compatible/stream_processor.py,sha256=EOJeoWlQGHrDj6chMclflj9RMqFgE1X7cdieQ5U5rZI,3415
110
+ klaude_code/llm/openai_compatible/stream.py,sha256=_OlnD5IBAq4xS5tb3mZUObZFGjXP-66lY4g8cxErRoo,10808
110
111
  klaude_code/llm/openai_compatible/tool_call_accumulator.py,sha256=kuw3ceDgenQz2Ccc9KYqBkDo6F1sDb5Aga6m41AIECA,4071
111
112
  klaude_code/llm/openrouter/__init__.py,sha256=_As8lHjwj6vapQhLorZttTpukk5ZiCdhFdGT38_ASPo,69
112
- klaude_code/llm/openrouter/client.py,sha256=9QeqXCwDjtqQWkW3h8qwJ6B3qAv1RmssQNJcCVS3wzc,9087
113
+ klaude_code/llm/openrouter/client.py,sha256=zUkH7wkiYUJMGS_8iaVwdhzUnry7WLw4Q1IDQtncmK0,4864
113
114
  klaude_code/llm/openrouter/input.py,sha256=aHVJCejkwzWaTM_EBbgmzKWyZfttAws2Y7QDW_NCnZk,5671
114
- klaude_code/llm/openrouter/reasoning_handler.py,sha256=r8I2F-oFTCkqJpINv74SCQZXwAuQZym7wJi5ScSe6hs,3378
115
+ klaude_code/llm/openrouter/reasoning.py,sha256=d6RU6twuGfdf0mXGQoxSNRzFaSa3GJFV8Eve5GzDXfU,4472
115
116
  klaude_code/llm/registry.py,sha256=grgHetTd-lSxTXiY689QW_Zd6voaid7qBqSnulpg_fE,1734
116
117
  klaude_code/llm/responses/__init__.py,sha256=WsiyvnNiIytaYcaAqNiB8GI-5zcpjjeODPbMlteeFjA,67
117
118
  klaude_code/llm/responses/client.py,sha256=XEsVehevQJ0WFbEVxIkI-su7VwIcaeq0P9eSrIRcGug,10184
@@ -121,9 +122,9 @@ klaude_code/protocol/__init__.py,sha256=aGUgzhYqvhuT3Mk2vj7lrHGriH4h9TSbqV1RsRFA
121
122
  klaude_code/protocol/commands.py,sha256=GN6GX9fo7YYtfumrBTpOmOvZofsnzZN2SAxP2X0BjTk,644
122
123
  klaude_code/protocol/events.py,sha256=KUMf1rLNdHQO9cZiQ9Pa1VsKkP1PTMbUkp18bu_jGy8,3935
123
124
  klaude_code/protocol/llm_param.py,sha256=cb4ubLq21PIsMOC8WJb0aid12z_sT1b7FsbNJMr-jLg,4255
124
- klaude_code/protocol/model.py,sha256=4ZJhB5PRXSZiMv6tFt8YoB4bBMNDQ0s9BcT3WqDu980,13435
125
- klaude_code/protocol/op.py,sha256=X3UeXxBOLf_jkEaYXhQSTpjtUV2u1Ot5f4bbPWNdQp4,4241
126
- klaude_code/protocol/op_handler.py,sha256=qaWrm2rlskSyF7ukPtxFAKf8brgLsUaVzg6035N-7w0,1565
125
+ klaude_code/protocol/model.py,sha256=aJUavwtGWY-XiDF6qk2ZV6FwEfjTqOnXZeznB7_zc_4,13606
126
+ klaude_code/protocol/op.py,sha256=zG8AGFcTx1vIZFN0lNZjIjucjmDYM4eVOR7tRiLofF4,4589
127
+ klaude_code/protocol/op_handler.py,sha256=feTMdrz2QBwnjdv6ndizTinbBA9HFeH4oiBDeQBRKoY,1749
127
128
  klaude_code/protocol/sub_agent/__init__.py,sha256=Abap5lPLgnSCQsVD3axfeqnj2UtxOcDLGX8e9HugfSU,3964
128
129
  klaude_code/protocol/sub_agent/explore.py,sha256=Z4M7i98XBLew38ClXiW-hJteSYjMUu2b548rkR7JW3A,2579
129
130
  klaude_code/protocol/sub_agent/oracle.py,sha256=0cbuutKQcvwaM--Q15mbkCdbpZMF4YjxDN1jkuGVKp4,3344
@@ -152,7 +153,7 @@ klaude_code/ui/__init__.py,sha256=XuEQsFUkJet8HI04cRmNLwnHOUqaPCRy4hF7PJnIfCY,27
152
153
  klaude_code/ui/core/__init__.py,sha256=2NakrTDcxem5D0atyEY_Rxv1BbKCeZweF63L6AAq6r8,23
153
154
  klaude_code/ui/core/display.py,sha256=NwFQ9oKi8i3T5EsYDRrTpGBr3BZI0Ggns37JuQEOH54,3540
154
155
  klaude_code/ui/core/input.py,sha256=GqEos_VKRpfzQg0LQvr3210gzu2mw0_7OpPyNXmF3LI,2533
155
- klaude_code/ui/core/stage_manager.py,sha256=QeKIbeqlQk4TwwjCirXdv6Yp__-kxL58ytgYVUTYdkY,1711
156
+ klaude_code/ui/core/stage_manager.py,sha256=5rJ7Fg3vf_4x9PTt6VOZ-SVRpg9jAZhZkCh_tQslLNg,1578
156
157
  klaude_code/ui/modes/__init__.py,sha256=ByDPbyYYU4o5kdnEes3b1VEV173RI9XAXyzkFbrApEY,26
157
158
  klaude_code/ui/modes/debug/__init__.py,sha256=1-1tAk7FtENdYzExSttYdHiJ-qH3DIQ5yYJ51ms2uSg,13
158
159
  klaude_code/ui/modes/debug/display.py,sha256=7_j9NGZqL4wE2LWhF1TjDHac4MfaWlYN2RHZCTfQad8,1096
@@ -161,31 +162,31 @@ klaude_code/ui/modes/exec/display.py,sha256=m2kkgaUoGD9rEVUmcm7Vs_PyAI2iruKCJYRh
161
162
  klaude_code/ui/modes/repl/__init__.py,sha256=35a6SUiL1SDi2i43X2VjHQw97rR7yhbLBzkGI5aC6Bc,1526
162
163
  klaude_code/ui/modes/repl/clipboard.py,sha256=ZCpk7kRSXGhh0Q_BWtUUuSYT7ZOqRjAoRcg9T9n48Wo,5137
163
164
  klaude_code/ui/modes/repl/completers.py,sha256=GIvUS9TAFMMPDpoXLuIupEccoqIMEpSEw4IZmKjVo4c,28560
164
- klaude_code/ui/modes/repl/display.py,sha256=0u4ISeOoYjynF7InYyV-PMOZqP44QBbjYOLOL18V0c0,2245
165
- klaude_code/ui/modes/repl/event_handler.py,sha256=RRcufuJU8zD7hJes0HDq85lpLn1Q85XetN6x3iLO8fM,23357
166
- klaude_code/ui/modes/repl/input_prompt_toolkit.py,sha256=pSephISw0nT4cMcGrVMIks0NJevORxPrHOikbdhmgMY,8082
165
+ klaude_code/ui/modes/repl/display.py,sha256=06wawOHWO2ItEA9EIEh97p3GDID7TJhAtpaA03nPQXs,2335
166
+ klaude_code/ui/modes/repl/event_handler.py,sha256=r-e12QmWz2_lGg0PilqFG0WB-BmsB0ygqZClkRA63CA,24672
167
+ klaude_code/ui/modes/repl/input_prompt_toolkit.py,sha256=F1p4JZp-KjDvTEZVR6bC0nb4ayd2VaEYsLmEA0KJOUM,9054
167
168
  klaude_code/ui/modes/repl/key_bindings.py,sha256=Fxz9Ey2SnOHvfleMeSYVduxuofY0Yo-97hMRs-OMe-o,7800
168
- klaude_code/ui/modes/repl/renderer.py,sha256=YJAF3Cx2fmyrmGOHLVRvUlXvlRR8ptYZtngR50Vg7uY,11639
169
+ klaude_code/ui/modes/repl/renderer.py,sha256=CsNMAf1GzGMyEfNsA0I68PQBfnI1KWpYewoVxEegv7w,15838
169
170
  klaude_code/ui/renderers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
170
- klaude_code/ui/renderers/assistant.py,sha256=aYBE0l07G28ij0Nq6Ey8q2d4cvubcdIDKORaPbOa9fI,743
171
+ klaude_code/ui/renderers/assistant.py,sha256=nO_QNJ2e9TwtU2IlojO9lCMWNFUNmcE9Ezz-WW748_w,743
171
172
  klaude_code/ui/renderers/common.py,sha256=5RdXC3ngtlhfmxRlbwOPtHtbXhAoWwbHoGX78tZcaTc,2284
172
173
  klaude_code/ui/renderers/developer.py,sha256=CawltuPSt_8s5lLoYKWYD9htwORbjgHeb4Ap0L2q7R4,6881
173
174
  klaude_code/ui/renderers/diffs.py,sha256=A37Wuz1_UIg0-st5le68-DRGz4-kot6N-wy9xEMKdz0,10403
174
175
  klaude_code/ui/renderers/errors.py,sha256=o9pOHRqZ0nxMPwkmV4CG81X7taW1-izvga6RY3fFRMI,516
175
- klaude_code/ui/renderers/metadata.py,sha256=pIMdc1BItuGnORlMMmpjAYZy3g_vTKKjQAckHx53lr8,8305
176
- klaude_code/ui/renderers/sub_agent.py,sha256=grQ_9G_7iYHdCpxrM0qDAKEMQfXcxBv0bI0GPe3s0lE,4961
177
- klaude_code/ui/renderers/thinking.py,sha256=XFq-J4cXlZQFqJFUohM8Xv0fOauJqQgiQ3KDiwSIUiw,1769
178
- klaude_code/ui/renderers/tools.py,sha256=ZNopwuvF_4DNCuqFegtHqv0K7RzAoh6LhtK3Sg1LXkI,21291
176
+ klaude_code/ui/renderers/metadata.py,sha256=b1aNqLjyaqErP4O5YSEXg7ychJcNTKpZ6hTmdcNJX84,8190
177
+ klaude_code/ui/renderers/sub_agent.py,sha256=-8aDIIG4vmqwSSJepYy_tn2vmChAHOLjwmPWN2o_B_Y,5728
178
+ klaude_code/ui/renderers/thinking.py,sha256=y5ICt0eJvpn2rtv5-_x6FDWyOYAnJHkfTdBWCr4Y6Yk,1946
179
+ klaude_code/ui/renderers/tools.py,sha256=W24deCM4GhZT69gzo3FwZ0QVYbQ-x5Bo2-y5nFkOsdE,22268
179
180
  klaude_code/ui/renderers/user_input.py,sha256=e2hZS7UUnzQuQ6UqzSKRDkFJMkKTLUoub1JclHMX40g,3941
180
181
  klaude_code/ui/rich/__init__.py,sha256=zEZjnHR3Fnv_sFMxwIMjoJfwDoC4GRGv3lHJzAGRq_o,236
181
182
  klaude_code/ui/rich/cjk_wrap.py,sha256=ncmifgTwF6q95iayHQyazGbntt7BRQb_Ed7aXc8JU6Y,7551
182
- klaude_code/ui/rich/code_panel.py,sha256=MdUP4QSaQJQxX0MQJT0pvrkhpGYZx3gWdIRbZT_Uj_I,3938
183
- klaude_code/ui/rich/live.py,sha256=Uid0QAZG7mHb4KrCF8p9c9n1nHLHzW75xSqcLZ4bLWY,2098
184
- klaude_code/ui/rich/markdown.py,sha256=fdfJcXPa0tc0Cafo4xqt6rGo8SKCL2CyPA5--AcsntU,11410
183
+ klaude_code/ui/rich/code_panel.py,sha256=ZKuJHh-kh-hIkBXSGLERLaDbJ7I9hvtvmYKocJn39_w,4744
184
+ klaude_code/ui/rich/live.py,sha256=qiBLPSE4KW_Dpemy5MZ5BKhkFWEN2fjXBiQHmhJrPSM,2722
185
+ klaude_code/ui/rich/markdown.py,sha256=LoI47hzyXi3vsLJ69Kfj2qlZhWah7bscQ7O-CjYV9rs,14564
185
186
  klaude_code/ui/rich/quote.py,sha256=tZcxN73SfDBHF_qk0Jkh9gWBqPBn8VLp9RF36YRdKEM,1123
186
187
  klaude_code/ui/rich/searchable_text.py,sha256=DCVZgEFv7_ergAvT2v7XrfQAUXUzhmAwuVAchlIx8RY,2448
187
- klaude_code/ui/rich/status.py,sha256=SNJVLHTYn3IScm5jkQc6LW3fO-HxXaj_FmGYUvkem9Q,9500
188
- klaude_code/ui/rich/theme.py,sha256=ru40YDV79RxeskZzIpgHPf3J4Ol70HMqbLPHU-s7iG8,11288
188
+ klaude_code/ui/rich/status.py,sha256=QHg4oWmPSQH19H81vOFpImEqWyDtAbIXjuCGsuDjBPA,9278
189
+ klaude_code/ui/rich/theme.py,sha256=GpPd_BD7rkCpmWDjdOYoW65UgJSMxAjA28Sgv5GbUNg,13291
189
190
  klaude_code/ui/terminal/__init__.py,sha256=GIMnsEcIAGT_vBHvTlWEdyNmAEpruyscUA6M_j3GQZU,1412
190
191
  klaude_code/ui/terminal/color.py,sha256=M-i09DVlLAhAyhQjfeAi7OipoGi1p_OVkaZxeRfykY0,7135
191
192
  klaude_code/ui/terminal/control.py,sha256=6SGNwxorP3jMW9xqnZy2BC0OsJd4DSrS13O3t6YlZzs,4916
@@ -193,7 +194,7 @@ klaude_code/ui/terminal/notifier.py,sha256=wkRM66d98Oh6PujnN4bB7NiQxIYEHqQXverMK
193
194
  klaude_code/ui/terminal/progress_bar.py,sha256=MDnhPbqCnN4GDgLOlxxOEVZPDwVC_XL2NM5sl1MFNcQ,2133
194
195
  klaude_code/ui/utils/__init__.py,sha256=YEsCLjbCPaPza-UXTPUMTJTrc9BmNBUP5CbFWlshyOQ,15
195
196
  klaude_code/ui/utils/common.py,sha256=tqHqwgLtAyP805kwRFyoAL4EgMutcNb3Y-GAXJ4IeuM,2263
196
- klaude_code-1.2.23.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
197
- klaude_code-1.2.23.dist-info/entry_points.txt,sha256=7CWKjolvs6dZiYHpelhA_FRJ-sVDh43eu3iWuOhKc_w,53
198
- klaude_code-1.2.23.dist-info/METADATA,sha256=3CSrp2lOoq2vot5oktv0RZZnlGPoSSX5qaahIdDyY8M,7725
199
- klaude_code-1.2.23.dist-info/RECORD,,
197
+ klaude_code-1.2.25.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
198
+ klaude_code-1.2.25.dist-info/entry_points.txt,sha256=7CWKjolvs6dZiYHpelhA_FRJ-sVDh43eu3iWuOhKc_w,53
199
+ klaude_code-1.2.25.dist-info/METADATA,sha256=kgFYc3ithDjpNaEC_p6PQNa6E1eaYQZ2bi13r7PQQMs,7762
200
+ klaude_code-1.2.25.dist-info/RECORD,,
@@ -1,83 +0,0 @@
1
- """Shared stream processing utilities for OpenAI-compatible clients.
2
-
3
- This module provides a reusable stream state manager that handles the common
4
- logic for accumulating and flushing reasoning, assistant content, and tool calls
5
- across different LLM providers (OpenAI-compatible, OpenRouter).
6
- """
7
-
8
- from collections.abc import Callable
9
- from typing import Literal
10
-
11
- from klaude_code.llm.openai_compatible.tool_call_accumulator import BasicToolCallAccumulator, ToolCallAccumulatorABC
12
- from klaude_code.protocol import model
13
-
14
- StreamStage = Literal["waiting", "reasoning", "assistant", "tool"]
15
-
16
-
17
- class StreamStateManager:
18
- """Manages streaming state and provides flush operations for accumulated content.
19
-
20
- This class encapsulates the common state management logic used by both
21
- OpenAI-compatible and OpenRouter clients, reducing code duplication.
22
- """
23
-
24
- def __init__(
25
- self,
26
- param_model: str,
27
- response_id: str | None = None,
28
- reasoning_flusher: Callable[[], list[model.ConversationItem]] | None = None,
29
- ):
30
- self.param_model = param_model
31
- self.response_id = response_id
32
- self.stage: StreamStage = "waiting"
33
- self.accumulated_reasoning: list[str] = []
34
- self.accumulated_content: list[str] = []
35
- self.accumulated_tool_calls: ToolCallAccumulatorABC = BasicToolCallAccumulator()
36
- self.emitted_tool_start_indices: set[int] = set()
37
- self._reasoning_flusher = reasoning_flusher
38
-
39
- def set_response_id(self, response_id: str) -> None:
40
- """Set the response ID once received from the stream."""
41
- self.response_id = response_id
42
- self.accumulated_tool_calls.response_id = response_id # pyright: ignore[reportAttributeAccessIssue]
43
-
44
- def flush_reasoning(self) -> list[model.ConversationItem]:
45
- """Flush accumulated reasoning content and return items."""
46
- if self._reasoning_flusher is not None:
47
- return self._reasoning_flusher()
48
- if not self.accumulated_reasoning:
49
- return []
50
- item = model.ReasoningTextItem(
51
- content="".join(self.accumulated_reasoning),
52
- response_id=self.response_id,
53
- model=self.param_model,
54
- )
55
- self.accumulated_reasoning = []
56
- return [item]
57
-
58
- def flush_assistant(self) -> list[model.ConversationItem]:
59
- """Flush accumulated assistant content and return items."""
60
- if not self.accumulated_content:
61
- return []
62
- item = model.AssistantMessageItem(
63
- content="".join(self.accumulated_content),
64
- response_id=self.response_id,
65
- )
66
- self.accumulated_content = []
67
- return [item]
68
-
69
- def flush_tool_calls(self) -> list[model.ToolCallItem]:
70
- """Flush accumulated tool calls and return items."""
71
- items: list[model.ToolCallItem] = self.accumulated_tool_calls.get()
72
- if items:
73
- self.accumulated_tool_calls.chunks_by_step = [] # pyright: ignore[reportAttributeAccessIssue]
74
- return items
75
-
76
- def flush_all(self) -> list[model.ConversationItem]:
77
- """Flush all accumulated content in order: reasoning, assistant, tool calls."""
78
- items: list[model.ConversationItem] = []
79
- items.extend(self.flush_reasoning())
80
- items.extend(self.flush_assistant())
81
- if self.stage == "tool":
82
- items.extend(self.flush_tool_calls())
83
- return items