kiwi-code 0.0.443__tar.gz → 0.0.444__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 (68) hide show
  1. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/PKG-INFO +1 -1
  2. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/pyproject.toml +1 -1
  3. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/__init__.py +1 -1
  4. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/cli.py +14 -38
  5. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/commands.py +1 -160
  6. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_runtime/__init__.py +1 -1
  7. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_runtime/main.py +4 -1
  8. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/__init__.py +1 -1
  9. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/main.py +5 -0
  10. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/dashboard.py +4 -360
  11. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/term_dashboard.py +166 -14
  12. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/slash_commands.py +1 -5
  13. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_term_dashboard_ui.py +142 -0
  14. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/uv.lock +1 -1
  15. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/.github/workflows/publish.yml +0 -0
  16. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/.github/workflows/test.yml +0 -0
  17. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/.gitignore +0 -0
  18. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/.python-version +0 -0
  19. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/CLAUDE.md +0 -0
  20. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/Makefile +0 -0
  21. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/README.md +0 -0
  22. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/auth.py +0 -0
  23. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/checkpoints.py +0 -0
  24. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/client.py +0 -0
  25. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/logger.py +0 -0
  26. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/models.py +0 -0
  27. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/runtime_manager.py +0 -0
  28. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/server.py +0 -0
  29. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_cli/terminal_mode.py +0 -0
  30. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_runtime/__main__.py +0 -0
  31. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/inline_file_picker.py +0 -0
  32. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/random_words.py +0 -0
  33. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/runtime_agent.py +0 -0
  34. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/__init__.py +0 -0
  35. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/attach_content.py +0 -0
  36. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/command_result.py +0 -0
  37. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/detach_files.py +0 -0
  38. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/file_browser.py +0 -0
  39. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/help.py +0 -0
  40. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/id_picker.py +0 -0
  41. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/login.py +0 -0
  42. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/runtime_cleanup.py +0 -0
  43. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/runtime_logs.py +0 -0
  44. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/screens/slash_picker.py +0 -0
  45. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/status_words.py +0 -0
  46. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/term_app.py +0 -0
  47. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/widgets.py +0 -0
  48. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/src/kiwi_tui/worktrees.py +0 -0
  49. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/test_hello.py +0 -0
  50. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/__init__.py +0 -0
  51. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/conftest.py +0 -0
  52. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_batch_fs_tool.py +0 -0
  53. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_checkpoints.py +0 -0
  54. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_cli_help.py +0 -0
  55. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_copy_path_fs_tool.py +0 -0
  56. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_imports.py +0 -0
  57. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_read_file_streaming.py +0 -0
  58. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_reexec_kiwi.py +0 -0
  59. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_runtime_log_trimming.py +0 -0
  60. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_search_in_files_fs_tool.py +0 -0
  61. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_slash_commands.py +0 -0
  62. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_terminal_mode.py +0 -0
  63. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_tokens.py +0 -0
  64. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_tui_headless.py +0 -0
  65. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_tui_interactive_runtime.py +0 -0
  66. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_tui_palette.py +0 -0
  67. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/tests/test_unified_diff.py +0 -0
  68. {kiwi_code-0.0.443 → kiwi_code-0.0.444}/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.443
3
+ Version: 0.0.444
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.443"
3
+ version = "0.0.444"
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"
@@ -1,3 +1,3 @@
1
1
  """Kiwi CLI - command-line interface and shared infrastructure modules."""
2
2
 
3
- __version__ = "0.0.443"
3
+ __version__ = "0.0.444"
@@ -8,23 +8,26 @@ from .auth import TokenManager
8
8
  from .models import AppConfig
9
9
  from .server import http_url_from_server
10
10
  from . import commands
11
+ from . import __version__ as KIWI_CLI_VERSION
11
12
 
12
13
  app = typer.Typer(name="kiwi", help="Kiwi — interact with the Kiwi AI platform.")
13
14
 
14
15
  actions_app = typer.Typer(name="actions", help="Manage actions.")
15
16
  action_runs_app = typer.Typer(name="runs", help="Manage action runs (results).")
16
- graphs_app = typer.Typer(name="graphs", help="Manage action graphs.")
17
- graph_runs_app = typer.Typer(name="graph-runs", help="Manage action graph runs (results).")
18
17
 
19
18
  app.add_typer(actions_app)
20
19
  app.add_typer(action_runs_app)
21
- app.add_typer(graphs_app)
22
- app.add_typer(graph_runs_app)
23
20
 
24
21
  # NOTE: kiwi-runtime is a standalone executable; this CLI does not manage it.
25
22
 
26
23
  _SERVER: str | None = None
27
24
 
25
+ def _version_callback(value: bool) -> None:
26
+ if value:
27
+ typer.echo(f"kiwicli {KIWI_CLI_VERSION}")
28
+ raise typer.Exit()
29
+
30
+
28
31
  @app.callback()
29
32
  def _main(
30
33
  server: Optional[str] = typer.Option(
@@ -35,6 +38,13 @@ def _main(
35
38
  "or a full URL (e.g. https://custom.server.com)."
36
39
  ),
37
40
  ),
41
+ version: Optional[bool] = typer.Option(
42
+ None,
43
+ "--version",
44
+ callback=_version_callback,
45
+ is_eager=True,
46
+ help="Show version and exit.",
47
+ ),
38
48
  ):
39
49
  """Global options for `kiwicli`."""
40
50
  global _SERVER
@@ -181,40 +191,6 @@ def runs_get_cmd(id: str = typer.Argument(help="Action run ID")):
181
191
  _print(_run_with_refresh_retry(lambda c: commands.runs_get(c, id=id)))
182
192
 
183
193
 
184
- # -- graphs -----------------------------------------------------------------
185
-
186
- @graphs_app.command("list")
187
- def graphs_list_cmd(
188
- name: Optional[str] = typer.Option(None, help="Filter by name"),
189
- limit: int = typer.Option(20, help="Max results"),
190
- offset: int = typer.Option(0, help="Offset"),
191
- ):
192
- """List action graphs."""
193
- _print(_run_with_refresh_retry(lambda c: commands.graphs_list(c, name=name, limit=limit, offset=offset)))
194
-
195
- @graphs_app.command("get")
196
- def graphs_get_cmd(id: str = typer.Argument(help="Action graph ID")):
197
- """Get action graph details."""
198
- _print(_run_with_refresh_retry(lambda c: commands.graphs_get(c, id=id)))
199
-
200
-
201
- # -- graph-runs -------------------------------------------------------------
202
-
203
- @graph_runs_app.command("list")
204
- def graph_runs_list_cmd(
205
- graph_id: Optional[str] = typer.Option(None, "--graph-id", help="Filter by graph ID"),
206
- graph_name: Optional[str] = typer.Option(None, "--graph-name", help="Filter by graph name"),
207
- status: Optional[str] = typer.Option(None, help="Filter by status"),
208
- limit: int = typer.Option(20, help="Max results"),
209
- offset: int = typer.Option(0, help="Offset"),
210
- ):
211
- """List action graph runs (results)."""
212
- _print(_run_with_refresh_retry(lambda c: commands.graph_runs_list(c, action_graph_id=graph_id, action_graph_name=graph_name, status=status, limit=limit, offset=offset)))
213
-
214
- @graph_runs_app.command("get")
215
- def graph_runs_get_cmd(id: str = typer.Argument(help="Graph run ID")):
216
- """Get action graph run details."""
217
- _print(_run_with_refresh_retry(lambda c: commands.graph_runs_get(c, id=id)))
218
194
 
219
195
 
220
196
  # -- runtime ----------------------------------------------------------------
@@ -14,14 +14,7 @@ from autobots_client.api.action_results import (
14
14
  list_action_result_v1_action_results_get,
15
15
  get_action_result_v1_action_results_id_get,
16
16
  )
17
- from autobots_client.api.action_graphs import (
18
- list_action_graphs_v1_action_graphs_get,
19
- get_action_graph_v1_action_graphs_id_get,
20
- )
21
- from autobots_client.api.action_graphs_results import (
22
- list_action_graph_result_v1_action_graphs_results_get,
23
- get_action_graph_result_v1_action_graphs_results_id_get,
24
- )
17
+
25
18
  from autobots_client.types import UNSET
26
19
 
27
20
 
@@ -157,122 +150,7 @@ def runs_get(client: AuthenticatedClient, *, id: str) -> list[str]:
157
150
  return lines
158
151
 
159
152
 
160
- # graphs (action graphs)
161
-
162
- def graphs_list(client: AuthenticatedClient, *, name: Optional[str] = None, limit: int = 20, offset: int = 0) -> list[str]:
163
- """List action graphs. Returns output lines."""
164
- resp = list_action_graphs_v1_action_graphs_get.sync_detailed(
165
- client=client,
166
- name=name if name else UNSET,
167
- limit=limit,
168
- offset=offset,
169
- )
170
- if resp.status_code != 200:
171
- return [f"Error: HTTP {resp.status_code}"]
172
-
173
- result = resp.parsed
174
- lines = [
175
- f"Action Graphs ({result.total_count} total, showing {result.offset}-{result.offset + len(result.docs)}):",
176
- "",
177
- f"{'ID':<28} {'Name':<30} {'Ver':<6} {'Published':<10} {'Created'}",
178
- "-" * 105,
179
- ]
180
- for doc in result.docs:
181
- lines.append(
182
- f"{doc.field_id:<28} {_val(doc.name):<30} {_val(doc.version):<6} "
183
- f"{_val(doc.is_published):<10} {_fmt_date(doc.created_at)}"
184
- )
185
- return lines
186
-
187
-
188
- def graphs_get(client: AuthenticatedClient, *, id: str) -> list[str]:
189
- """Get action graph details. Returns output lines."""
190
- resp = get_action_graph_v1_action_graphs_id_get.sync_detailed(id=id, client=client)
191
- if resp.status_code != 200:
192
- return [f"Error: HTTP {resp.status_code}"]
193
-
194
- doc = resp.parsed
195
- if hasattr(doc, 'field_id'):
196
- return [
197
- f"ID: {doc.field_id}",
198
- f"Name: {_val(getattr(doc, 'name', ''))}",
199
- f"Version: {_val(getattr(doc, 'version', ''))}",
200
- f"Description: {_val(getattr(doc, 'description', ''))}",
201
- f"Published: {_val(getattr(doc, 'is_published', ''))}",
202
- f"Created: {_fmt_date(getattr(doc, 'created_at', None))}",
203
- f"Updated: {_fmt_date(getattr(doc, 'updated_at', None))}",
204
- ]
205
- import json
206
- if hasattr(doc, 'to_dict'):
207
- return [json.dumps(doc.to_dict(), indent=2, default=str)]
208
- return [str(doc)]
209
-
210
-
211
- # graph-runs (action graph results)
212
-
213
- def graph_runs_list(client: AuthenticatedClient, *, action_graph_id: Optional[str] = None,
214
- action_graph_name: Optional[str] = None, status: Optional[str] = None,
215
- limit: int = 20, offset: int = 0) -> list[str]:
216
- """List action graph runs. Returns output lines."""
217
- from autobots_client.models.event_result_status import EventResultStatus
218
-
219
- status_enum = UNSET
220
- if status:
221
- try:
222
- status_enum = EventResultStatus(status.lower())
223
- except ValueError:
224
- return [f"Invalid status: {status}. Valid: processing, success, error, stuck, waiting"]
225
-
226
- resp = list_action_graph_result_v1_action_graphs_results_get.sync_detailed(
227
- client=client,
228
- action_graph_id=action_graph_id if action_graph_id else UNSET,
229
- action_graph_name=action_graph_name if action_graph_name else UNSET,
230
- status=status_enum,
231
- limit=limit,
232
- offset=offset,
233
- )
234
- if resp.status_code != 200:
235
- return [f"Error: HTTP {resp.status_code}"]
236
-
237
- result = resp.parsed
238
- lines = [
239
- f"Action Graph Runs ({result.total_count} total, showing {result.offset}-{result.offset + len(result.docs)}):",
240
- "",
241
- f"{'ID':<28} {'Status':<12} {'Name':<30} {'Created':<18} {'Updated'}",
242
- "-" * 105,
243
- ]
244
- for doc in result.docs:
245
- lines.append(
246
- f"{doc.field_id:<28} {doc.status.value:<12} {_val(doc.name):<30} "
247
- f"{_fmt_date(doc.created_at):<18} {_fmt_date(doc.updated_at)}"
248
- )
249
- return lines
250
-
251
-
252
- def graph_runs_get(client: AuthenticatedClient, *, id: str) -> list[str]:
253
- """Get action graph run details. Returns output lines."""
254
- resp = get_action_graph_result_v1_action_graphs_results_id_get.sync_detailed(id=id, client=client)
255
- if resp.status_code != 200:
256
- return [f"Error: HTTP {resp.status_code}"]
257
153
 
258
- doc = resp.parsed
259
- lines = [
260
- f"ID: {doc.field_id}",
261
- f"Status: {doc.status.value}",
262
- f"Name: {_val(doc.name)}",
263
- f"Type: {doc.type_.value}",
264
- f"Saved: {_val(doc.is_saved)}",
265
- f"Created: {_fmt_date(doc.created_at)}",
266
- f"Updated: {_fmt_date(doc.updated_at)}",
267
- ]
268
- if doc.result and not isinstance(doc.result, type(UNSET)):
269
- lines += [
270
- "",
271
- "Action Graph:",
272
- f" Name: {doc.result.name}",
273
- f" ID: {doc.result.field_id}",
274
- ]
275
- return lines
276
154
 
277
155
 
278
156
  # Command dispatcher — parses "/command args" from TUI input
@@ -309,10 +187,6 @@ Query:
309
187
  /autocode-select Choose the version of AutoCode you wish to use
310
188
  /runs list [--action-id ID] [--status STATUS] [--limit N]
311
189
  /runs get <id>
312
- /graphs list [--name NAME] [--limit N]
313
- /graphs get <id>
314
- /graph-runs list [--graph-id ID] [--status STATUS] [--limit N]
315
- /graph-runs get <id>
316
190
 
317
191
  /help Show this help"""
318
192
 
@@ -400,39 +274,6 @@ def dispatch(command_str: str, client: AuthenticatedClient) -> list[str]:
400
274
  else:
401
275
  return ["Usage: /runs list | /runs get <id>"]
402
276
 
403
- elif group == "graphs":
404
- if sub == "list":
405
- return graphs_list(
406
- client,
407
- name=opts.get("name"),
408
- limit=_int(opts.get("limit", "20"), 20),
409
- offset=_int(opts.get("offset", "0"), 0),
410
- )
411
- elif sub == "get":
412
- pos = opts.get("_positional", [])
413
- if not pos:
414
- return ["Usage: /graphs get <id>"]
415
- return graphs_get(client, id=pos[0])
416
- else:
417
- return ["Usage: /graphs list | /graphs get <id>"]
418
-
419
- elif group in ("graph-runs", "graph_runs"):
420
- if sub == "list":
421
- return graph_runs_list(
422
- client,
423
- action_graph_id=opts.get("graph_id"),
424
- action_graph_name=opts.get("graph_name"),
425
- status=opts.get("status"),
426
- limit=_int(opts.get("limit", "20"), 20),
427
- offset=_int(opts.get("offset", "0"), 0),
428
- )
429
- elif sub == "get":
430
- pos = opts.get("_positional", [])
431
- if not pos:
432
- return ["Usage: /graph-runs get <id>"]
433
- return graph_runs_get(client, id=pos[0])
434
- else:
435
- return ["Usage: /graph-runs list | /graph-runs get <id>"]
436
277
 
437
278
  else:
438
279
  return [f"Unknown command: /{group}", "", HELP_TEXT]
@@ -1,3 +1,3 @@
1
1
  """Kiwi Runtime — terminal agent that connects to the server via WebSocket."""
2
2
 
3
- __version__ = "0.0.443"
3
+ __version__ = "0.0.444"
@@ -46,6 +46,7 @@ if not IS_WINDOWS:
46
46
  import httpx
47
47
  import websockets
48
48
  import threading
49
+ from kiwi_runtime import __version__ as KIWI_RUNTIME_VERSION
49
50
  FS_MAX_CONCURRENCY = 8
50
51
 
51
52
  # Shared token storage (used by both kiwi-code and standalone kiwi-runtime)
@@ -4372,7 +4373,7 @@ async def _connect_once(
4372
4373
  ws_endpoint,
4373
4374
  ping_interval=20,
4374
4375
  ping_timeout=90,
4375
- close_timeout=10,
4376
+ close_timeout=60,
4376
4377
  max_queue=64,
4377
4378
  ) as ws:
4378
4379
 
@@ -4856,6 +4857,8 @@ def main():
4856
4857
  subparsers = parser.add_subparsers(dest="command")
4857
4858
 
4858
4859
  connect_parser = subparsers.add_parser("connect", help="Connect to the server")
4860
+
4861
+ parser.add_argument("--version", action="version", version=f"kiwi-runtime {KIWI_RUNTIME_VERSION}")
4859
4862
  connect_parser.add_argument(
4860
4863
  "--server",
4861
4864
  default="app",
@@ -1,3 +1,3 @@
1
1
  """Autobots TUI - A textual-based terminal user interface."""
2
2
 
3
- __version__ = "0.0.443"
3
+ __version__ = "0.0.444"
@@ -25,6 +25,7 @@ from kiwi_cli.terminal_mode import (
25
25
  # from kiwi_cli import runtime_manager
26
26
  from .screens import LoginScreen, DashboardScreen, RuntimeCleanupScreen # , RuntimeLogsScreen
27
27
  from kiwi_tui.screens.runtime_cleanup import RuntimeRow
28
+ from . import __version__ as KIWI_CODE_VERSION
28
29
  from kiwi_tui.runtime_agent import (
29
30
  RuntimeConnectArgs,
30
31
  bind_pending_to_run,
@@ -1155,6 +1156,10 @@ def main() -> int:
1155
1156
 
1156
1157
  argv = sys.argv[1:]
1157
1158
 
1159
+ if "--version" in argv:
1160
+ print(f"kiwi {KIWI_CODE_VERSION}")
1161
+ return 0
1162
+
1158
1163
  # UI selector (defaults to term UI).
1159
1164
  # - `kiwi` => term UI
1160
1165
  # - `kiwi alt` => legacy UI