kiwi-code 0.0.435__tar.gz → 0.0.436__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 (59) hide show
  1. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/PKG-INFO +1 -1
  2. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/pyproject.toml +1 -1
  3. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/client.py +27 -5
  4. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_tui_headless.py +0 -49
  5. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/uv.lock +1 -1
  6. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/.github/workflows/publish.yml +0 -0
  7. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/.github/workflows/test.yml +0 -0
  8. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/.gitignore +0 -0
  9. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/.python-version +0 -0
  10. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/CLAUDE.md +0 -0
  11. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/Makefile +0 -0
  12. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/README.md +0 -0
  13. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/__init__.py +0 -0
  14. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/auth.py +0 -0
  15. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/checkpoints.py +0 -0
  16. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/cli.py +0 -0
  17. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/commands.py +0 -0
  18. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/logger.py +0 -0
  19. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/models.py +0 -0
  20. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/runtime_manager.py +0 -0
  21. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/server.py +0 -0
  22. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_cli/terminal_mode.py +0 -0
  23. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_runtime/__init__.py +0 -0
  24. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_runtime/__main__.py +0 -0
  25. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_runtime/main.py +0 -0
  26. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/__init__.py +0 -0
  27. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/inline_file_picker.py +0 -0
  28. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/main.py +0 -0
  29. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/random_words.py +0 -0
  30. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/runtime_agent.py +0 -0
  31. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/__init__.py +0 -0
  32. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/attach_content.py +0 -0
  33. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/command_result.py +0 -0
  34. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/dashboard.py +0 -0
  35. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/file_browser.py +0 -0
  36. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/help.py +0 -0
  37. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/id_picker.py +0 -0
  38. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/login.py +0 -0
  39. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/runtime_cleanup.py +0 -0
  40. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/runtime_logs.py +0 -0
  41. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/screens/slash_picker.py +0 -0
  42. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/slash_commands.py +0 -0
  43. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/status_words.py +0 -0
  44. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/widgets.py +0 -0
  45. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/src/kiwi_tui/worktrees.py +0 -0
  46. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/test_hello.py +0 -0
  47. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/__init__.py +0 -0
  48. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/conftest.py +0 -0
  49. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_checkpoints.py +0 -0
  50. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_cli_help.py +0 -0
  51. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_imports.py +0 -0
  52. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_reexec_kiwi.py +0 -0
  53. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_runtime_log_trimming.py +0 -0
  54. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_slash_commands.py +0 -0
  55. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_terminal_mode.py +0 -0
  56. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_tokens.py +0 -0
  57. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_tui_interactive_runtime.py +0 -0
  58. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_tui_palette.py +0 -0
  59. {kiwi_code-0.0.435 → kiwi_code-0.0.436}/tests/test_worktrees.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kiwi-code
3
- Version: 0.0.435
3
+ Version: 0.0.436
4
4
  Summary: A textual-based terminal user interface application
5
5
  Project-URL: Homepage, https://meetkiwi.ai
6
6
  Project-URL: Repository, https://github.com/jetoslabs/kiwi-code
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kiwi-code"
3
- version = "0.0.435"
3
+ version = "0.0.436"
4
4
  description = "A textual-based terminal user interface application"
5
5
  readme = {file = "README.md", content-type = "text/markdown"}
6
6
  requires-python = ">=3.11,<4.0"
@@ -598,6 +598,17 @@ class AutobotsClientWrapper:
598
598
  logger.error(f"Error processing SSE data: {e}")
599
599
  return False
600
600
 
601
+ pending_blank = False
602
+
603
+ def _is_field_line(s: str) -> bool:
604
+ return (
605
+ s.startswith("data:")
606
+ or s.startswith(":")
607
+ or s.startswith("event:")
608
+ or s.startswith("id:")
609
+ or s.startswith("retry:")
610
+ )
611
+
601
612
  async for chunk in response.aiter_bytes():
602
613
  text_chunk = decoder.decode(chunk, final=False)
603
614
  buffer += text_chunk
@@ -606,14 +617,26 @@ class AutobotsClientWrapper:
606
617
  line, buffer = buffer.split("\n", 1)
607
618
  line = line.rstrip("\r")
608
619
 
609
- # SSE event boundary (blank line)
620
+ if pending_blank:
621
+ if line == "":
622
+ pending_blank = False
623
+ if _flush_event():
624
+ return
625
+ continue
626
+ if _is_field_line(line):
627
+ pending_blank = False
628
+ if _flush_event():
629
+ return
630
+ else:
631
+ event_data_lines.append("")
632
+ pending_blank = False
633
+
610
634
  if line == "":
611
- if _flush_event():
612
- return
635
+ if event_data_lines:
636
+ pending_blank = True
613
637
  continue
614
638
 
615
639
  if line.startswith(":"):
616
- # keep-alive comments
617
640
  continue
618
641
 
619
642
  if line.startswith("data:"):
@@ -626,7 +649,6 @@ class AutobotsClientWrapper:
626
649
  if event_data_lines:
627
650
  event_data_lines.append(line)
628
651
 
629
- # Flush any remaining bytes in decoder + any pending event data.
630
652
  decoder.decode(b"", final=True)
631
653
  _flush_event()
632
654
  except Exception as e:
@@ -852,55 +852,6 @@ async def test_tui_streaming_requests_autofollow_when_viewport_is_near_bottom(
852
852
  )
853
853
  await pilot.pause()
854
854
  assert calls == [{"after_refresh": True}]
855
- @pytest.mark.asyncio
856
- async def test_tui_streaming_does_not_force_scroll_when_user_reads_older_messages(
857
- isolated_home: Path,
858
- ) -> None:
859
- """Streaming updates should not yank the viewport back to the bottom."""
860
- tokens_path = isolated_home / ".kiwi" / "tokens.json"
861
- tokens_path.parent.mkdir(parents=True, exist_ok=True)
862
- tokens_path.write_text(
863
- json.dumps(
864
- {
865
- "access_token": "test-access-token",
866
- "refresh_token": "test-refresh-token",
867
- "token_type": "Bearer",
868
- "expires_at": None,
869
- }
870
- ),
871
- encoding="utf-8",
872
- )
873
-
874
- from kiwi_tui.main import AutobotsTUI
875
-
876
- app = AutobotsTUI()
877
- async with app.run_test(size=(80, 24)) as pilot:
878
- await pilot.pause()
879
- assert type(app.screen).__name__ == "DashboardScreen"
880
- screen = app.screen
881
-
882
- calls: list[dict] = []
883
- monkeypatch = pytest.MonkeyPatch()
884
- monkeypatch.setattr(screen, "_messages_is_near_bottom", lambda *args, **kwargs: False)
885
- monkeypatch.setattr(
886
- screen,
887
- "_scroll_messages_to_end",
888
- lambda *args, **kwargs: calls.append(dict(kwargs)),
889
- )
890
- try:
891
- widget = screen.update_streaming_message({"blocks": [{"text": "stream start"}]})
892
- await pilot.pause()
893
- assert widget is not None
894
- assert calls == []
895
-
896
- screen.update_streaming_message(
897
- {"blocks": [{"text": "\n".join(f"stream line {i}" for i in range(60))}]},
898
- widget,
899
- )
900
- await pilot.pause()
901
- assert calls == []
902
- finally:
903
- monkeypatch.undo()
904
855
 
905
856
  @pytest.mark.asyncio
906
857
  async def test_tui_quits_cleanly(isolated_home: Path) -> None:
@@ -397,7 +397,7 @@ wheels = [
397
397
 
398
398
  [[package]]
399
399
  name = "kiwi-code"
400
- version = "0.0.435"
400
+ version = "0.0.436"
401
401
  source = { editable = "." }
402
402
  dependencies = [
403
403
  { name = "autobots-client" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes