kiwi-code 0.0.23__tar.gz → 0.0.24__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 (47) hide show
  1. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/PKG-INFO +1 -1
  2. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/pyproject.toml +1 -1
  3. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/screens/dashboard.py +72 -19
  4. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/uv.lock +1 -1
  5. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/.github/workflows/publish.yml +0 -0
  6. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/.github/workflows/test.yml +0 -0
  7. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/.gitignore +0 -0
  8. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/.python-version +0 -0
  9. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/CLAUDE.md +0 -0
  10. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/Makefile +0 -0
  11. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/README.md +0 -0
  12. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_cli/__init__.py +0 -0
  13. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_cli/auth.py +0 -0
  14. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_cli/cli.py +0 -0
  15. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_cli/client.py +0 -0
  16. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_cli/commands.py +0 -0
  17. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_cli/logger.py +0 -0
  18. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_cli/models.py +0 -0
  19. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_cli/runtime_manager.py +0 -0
  20. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_cli/server.py +0 -0
  21. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_runtime/__init__.py +0 -0
  22. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_runtime/__main__.py +0 -0
  23. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_runtime/main.py +0 -0
  24. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_runtime/snake_game/.gitignore +0 -0
  25. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_runtime/snake_game/requirements.txt +0 -0
  26. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/__init__.py +0 -0
  27. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/inline_file_picker.py +0 -0
  28. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/main.py +0 -0
  29. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/runtime_agent.py +0 -0
  30. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/screens/__init__.py +0 -0
  31. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/screens/attach_content.py +0 -0
  32. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/screens/command_result.py +0 -0
  33. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/screens/file_browser.py +0 -0
  34. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/screens/id_picker.py +0 -0
  35. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/screens/login.py +0 -0
  36. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/screens/runtime_cleanup.py +0 -0
  37. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/screens/runtime_logs.py +0 -0
  38. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/screens/slash_picker.py +0 -0
  39. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/src/kiwi_tui/widgets.py +0 -0
  40. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/test_hello.py +0 -0
  41. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/tests/__init__.py +0 -0
  42. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/tests/conftest.py +0 -0
  43. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/tests/test_cli_help.py +0 -0
  44. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/tests/test_imports.py +0 -0
  45. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/tests/test_reexec_kiwi.py +0 -0
  46. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/tests/test_tokens.py +0 -0
  47. {kiwi_code-0.0.23 → kiwi_code-0.0.24}/tests/test_tui_headless.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kiwi-code
3
- Version: 0.0.23
3
+ Version: 0.0.24
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.23"
3
+ version = "0.0.24"
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"
@@ -6,7 +6,7 @@ from textual.app import ComposeResult
6
6
  from textual.binding import Binding
7
7
  from textual.screen import Screen
8
8
  from textual.widgets import Header, Footer, Input, Static, Button, Markdown, LoadingIndicator
9
- from textual.containers import Vertical, VerticalScroll, Horizontal
9
+ from textual.containers import Vertical, VerticalScroll, Horizontal, Center
10
10
  from kiwi_tui.screens.file_browser import FileBrowserScreen
11
11
  from kiwi_tui.screens.attach_content import AttachContentScreen
12
12
  from kiwi_tui.screens.slash_picker import SlashPickerScreen
@@ -38,6 +38,28 @@ class UserMessageRow(Horizontal):
38
38
  yield Static(self._text, classes="user-body", markup=False)
39
39
 
40
40
 
41
+
42
+ class AssistantMessageRow(Horizontal):
43
+ """A single assistant message rendered with a left dot + markdown body."""
44
+
45
+ def __init__(self, markdown_text: str, *, classes: str = "") -> None:
46
+ super().__init__(classes=classes)
47
+ self._markdown_text = markdown_text
48
+
49
+ def compose(self) -> ComposeResult:
50
+ # Solid dot marker on the left side of the model response.
51
+ yield Static("●", classes="assistant-dot", markup=False)
52
+ yield Markdown(self._markdown_text, classes="assistant-body")
53
+
54
+ def update_markdown(self, markdown_text: str) -> None:
55
+ """Update the markdown content in-place."""
56
+ self._markdown_text = markdown_text
57
+ try:
58
+ self.query_one(".assistant-body", Markdown).update(markdown_text)
59
+ except Exception:
60
+ # Defensive: if the widget tree isn't ready or the child was removed.
61
+ pass
62
+
41
63
  # Footer hint for inserting a newline differs by OS:
42
64
  # - macOS terminals often don't forward modified Enter combos to terminal apps reliably, so we advertise Ctrl+N.
43
65
  # - Windows terminals tend to support Shift+Enter for multi-line input.
@@ -95,7 +117,7 @@ class DashboardScreen(Screen):
95
117
 
96
118
  #run-status-bar {
97
119
  width: 100%;
98
- height: 4;
120
+ height: 5;
99
121
  background: $background;
100
122
  }
101
123
 
@@ -129,12 +151,14 @@ class DashboardScreen(Screen):
129
151
  }
130
152
  #copy-run-id {
131
153
  width: auto;
132
- height: auto;
154
+ /* Explicit height so the full border (top+bottom) is visible. */
155
+ height: 3;
133
156
  padding: 0 1;
134
- margin: 0 1;
157
+ margin: 0;
135
158
  }
136
159
 
137
160
 
161
+
138
162
  #activity-bar {
139
163
  width: 100%;
140
164
  height: 1;
@@ -168,7 +192,8 @@ class DashboardScreen(Screen):
168
192
  width: 100%;
169
193
  height: auto;
170
194
  padding: 0 1;
171
- margin: 0;
195
+ /* Add breathing room between all messages (user/assistant/info/error/etc.). */
196
+ margin: 1 0 0 0;
172
197
  }
173
198
 
174
199
  .user-message {
@@ -190,13 +215,25 @@ class DashboardScreen(Screen):
190
215
 
191
216
  .assistant-message {
192
217
  color: $text;
193
- margin: 0;
194
218
  padding: 0 1;
195
219
  }
196
220
 
221
+ .assistant-dot {
222
+ width: 2;
223
+ padding: 0 1 0 0;
224
+ color: $brand-cyan;
225
+ text-style: bold;
226
+ content-align: center top;
227
+ }
228
+
229
+ .assistant-body {
230
+ width: 1fr;
231
+ }
232
+
197
233
  .assistant-message Markdown {
198
234
  margin: 0;
199
235
  padding: 0;
236
+ width: 1fr;
200
237
  }
201
238
 
202
239
  .error-message {
@@ -372,8 +409,10 @@ class DashboardScreen(Screen):
372
409
  with Vertical(id="status-action-col"):
373
410
  yield Static("", id="status-action", markup=False)
374
411
  with Vertical(id="status-run-col"):
375
- yield Static("", id="status-run", markup=False)
376
- yield Button("Copy", id="copy-run-id", variant="default")
412
+ with Center():
413
+ yield Static("", id="status-run", markup=False)
414
+ with Center():
415
+ yield Button("Copy", id="copy-run-id", variant="default")
377
416
 
378
417
  with Vertical(id="input-bar"):
379
418
  with Horizontal(id="activity-bar"):
@@ -1520,8 +1559,8 @@ class DashboardScreen(Screen):
1520
1559
  messages = self.query_one("#messages", VerticalScroll)
1521
1560
  css_class = f"message {msg_type}-message"
1522
1561
  if msg_type == "assistant":
1523
- widget = Markdown(self._prepare_markdown(text), classes=css_class)
1524
- messages.mount(widget)
1562
+ prepared = self._prepare_markdown(text)
1563
+ messages.mount(AssistantMessageRow(prepared, classes=css_class))
1525
1564
  elif msg_type == "user":
1526
1565
  # Render a styled "YOU" label without enabling markup (keeps input safe).
1527
1566
  messages.mount(UserMessageRow(str(text), classes=css_class))
@@ -1942,7 +1981,11 @@ class DashboardScreen(Screen):
1942
1981
 
1943
1982
  self._set_streaming(False)
1944
1983
 
1945
- def update_streaming_message(self, output: any, widget_ref: any = None) -> Static:
1984
+ def update_streaming_message(
1985
+ self,
1986
+ output: any,
1987
+ widget_ref: Markdown | AssistantMessageRow | None = None,
1988
+ ) -> Markdown | AssistantMessageRow | None:
1946
1989
  """Update or create a streaming message widget with new output.
1947
1990
 
1948
1991
  Returns the widget being updated/created for future updates.
@@ -1953,21 +1996,24 @@ class DashboardScreen(Screen):
1953
1996
 
1954
1997
  messages = self.query_one("#messages", VerticalScroll)
1955
1998
 
1956
- text_content = self._prepare_markdown(text_content)
1999
+ markdown_text = self._prepare_markdown(text_content)
1957
2000
  if widget_ref is None:
1958
- widget_ref = Markdown(text_content, classes="message assistant-message")
2001
+ widget_ref = AssistantMessageRow(markdown_text, classes="message assistant-message")
1959
2002
  messages.mount(widget_ref)
1960
2003
  else:
1961
2004
  try:
1962
- widget_ref.update(text_content)
2005
+ if isinstance(widget_ref, AssistantMessageRow):
2006
+ widget_ref.update_markdown(markdown_text)
2007
+ else:
2008
+ # Backward-compat: if an older ref is a Markdown widget.
2009
+ widget_ref.update(markdown_text)
1963
2010
  except Exception as e:
1964
2011
  logger.warning(f"Failed to update widget: {e}")
1965
- widget_ref = Markdown(text_content, classes="message assistant-message")
2012
+ widget_ref = AssistantMessageRow(markdown_text, classes="message assistant-message")
1966
2013
  messages.mount(widget_ref)
1967
2014
 
1968
2015
  messages.scroll_end(animate=False)
1969
2016
  return widget_ref
1970
-
1971
2017
  def extract_text_from_output(self, output: any) -> str:
1972
2018
  """Extract text content from output blocks structure and clean it for display."""
1973
2019
  if not isinstance(output, dict):
@@ -2157,10 +2203,17 @@ class DashboardScreen(Screen):
2157
2203
  messages = self.query_one("#messages", VerticalScroll)
2158
2204
  assistant_messages = messages.query(".assistant-message")
2159
2205
 
2206
+ prepared = self._prepare_markdown(text)
2207
+
2160
2208
  if assistant_messages:
2161
- # Update the last assistant message
2162
2209
  last_msg = assistant_messages[-1]
2163
- last_msg.update(text)
2210
+ if isinstance(last_msg, AssistantMessageRow):
2211
+ last_msg.update_markdown(prepared)
2212
+ else:
2213
+ # Backward-compat if we have an older Markdown widget in the tree.
2214
+ try:
2215
+ last_msg.update(prepared)
2216
+ except Exception:
2217
+ self.add_message(text, "assistant")
2164
2218
  else:
2165
- # No existing message, create new one
2166
2219
  self.add_message(text, "assistant")
@@ -397,7 +397,7 @@ wheels = [
397
397
 
398
398
  [[package]]
399
399
  name = "kiwi-code"
400
- version = "0.0.23"
400
+ version = "0.0.24"
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
File without changes
File without changes