lithe-cli 0.2.2__tar.gz → 0.2.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lithe-cli
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Command-line interface for the lithe agent kernel: chat, one-shot runs, undo, and run inspection.
5
5
  License: MIT License
6
6
 
@@ -1,3 +1,3 @@
1
1
  """lithe-cli: the command-line interface for the lithe agent kernel."""
2
2
 
3
- __version__ = "0.2.2"
3
+ __version__ = "0.2.3"
@@ -336,6 +336,15 @@ def _chat_loop(cfg: Any) -> int:
336
336
  except (EOFError, KeyboardInterrupt):
337
337
  print()
338
338
  break
339
+ except UnicodeDecodeError:
340
+ print(
341
+ ui.s(
342
+ "\n(这行输入无法按 UTF-8 解码,已丢弃;"
343
+ "请把终端与 locale 设为 UTF-8(如 export LANG=C.UTF-8)后重试。)",
344
+ RED,
345
+ )
346
+ )
347
+ continue
339
348
  if not line:
340
349
  continue
341
350
  if line in ("/exit", "/quit", "exit", "quit"):
@@ -156,6 +156,15 @@ def _prompt(
156
156
  except (EOFError, KeyboardInterrupt):
157
157
  print()
158
158
  return None
159
+ except UnicodeDecodeError:
160
+ print(
161
+ ui.s(
162
+ "\n 这行输入无法按 UTF-8 解码,已丢弃;"
163
+ "请把终端与 locale 设为 UTF-8(如 export LANG=C.UTF-8)后重试。",
164
+ RED,
165
+ )
166
+ )
167
+ continue
159
168
  if not answer and default:
160
169
  answer = default
161
170
  if not answer:
@@ -177,6 +186,9 @@ def _yes_no(label: str, default: bool, input_fn=input) -> bool:
177
186
  except (EOFError, KeyboardInterrupt):
178
187
  print()
179
188
  return default
189
+ except UnicodeDecodeError:
190
+ print(ui.s("\n 这行输入无法按 UTF-8 解码,按默认值处理。", RED))
191
+ return default
180
192
  return default if not answer else answer in ("y", "yes", "是")
181
193
 
182
194
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lithe-cli
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Command-line interface for the lithe agent kernel: chat, one-shot runs, undo, and run inspection.
5
5
  License: MIT License
6
6
 
@@ -444,6 +444,46 @@ def test_read_masked_echoes_stars_and_swallows_paste_markers():
444
444
  assert "\x1b[200~" not in text and "\x1b[201~" not in text
445
445
 
446
446
 
447
+ def test_undecodable_input_line_never_crashes(tmp_path, monkeypatch, capsys):
448
+ # a mangled (non-UTF-8) input line — e.g. readline/locale mismatch —
449
+ # must be dropped with a hint, not kill the whole process
450
+ def bad_decode(prompt=""):
451
+ raise UnicodeDecodeError("utf-8", b"\xe5", 52, 53, "invalid continuation byte")
452
+
453
+ from lithe_cli import setup
454
+ from lithe_cli.main import _chat_loop
455
+ from conftest import make_config
456
+
457
+ calls = iter([bad_decode, EOFError])
458
+
459
+ def fake_input(prompt=""):
460
+ f = next(calls)
461
+ if isinstance(f, type(EOFError)):
462
+ raise f
463
+ f(prompt)
464
+
465
+ monkeypatch.setattr("builtins.input", fake_input)
466
+ assert _chat_loop(make_config(tmp_path, [])) == 0
467
+ out = capsys.readouterr().out
468
+ assert "UTF-8" in out
469
+
470
+ # the wizard prompts take the same beating and re-ask instead of dying
471
+ answers = iter([bad_decode, "https://ok.example/api"])
472
+
473
+ def wizard_input(prompt=""):
474
+ f = next(answers)
475
+ if callable(f):
476
+ f(prompt)
477
+ return ""
478
+ return f
479
+
480
+ assert (
481
+ setup._prompt("Base URL", validate=setup._http_like, input_fn=wizard_input)
482
+ == "https://ok.example/api"
483
+ )
484
+ assert "UTF-8" in capsys.readouterr().out
485
+
486
+
447
487
  def test_wizard_rejects_bad_url_then_accepts(tmp_path, monkeypatch, capsys):
448
488
  from lithe_cli import setup
449
489
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes