kiwi-code 0.0.442__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.
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/PKG-INFO +1 -1
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/pyproject.toml +1 -1
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/__init__.py +1 -1
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/cli.py +14 -38
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/commands.py +1 -160
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_runtime/__init__.py +1 -1
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_runtime/main.py +287 -33
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/__init__.py +1 -1
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/main.py +5 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/dashboard.py +4 -360
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/term_dashboard.py +166 -14
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/slash_commands.py +1 -5
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_term_dashboard_ui.py +142 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/uv.lock +1 -1
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/.github/workflows/publish.yml +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/.github/workflows/test.yml +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/.gitignore +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/.python-version +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/CLAUDE.md +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/Makefile +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/README.md +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/auth.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/checkpoints.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/client.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/logger.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/models.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/runtime_manager.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/server.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_cli/terminal_mode.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_runtime/__main__.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/inline_file_picker.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/random_words.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/runtime_agent.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/__init__.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/attach_content.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/command_result.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/detach_files.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/file_browser.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/help.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/id_picker.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/login.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/runtime_cleanup.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/runtime_logs.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/screens/slash_picker.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/status_words.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/term_app.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/widgets.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/src/kiwi_tui/worktrees.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/test_hello.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/__init__.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/conftest.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_batch_fs_tool.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_checkpoints.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_cli_help.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_copy_path_fs_tool.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_imports.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_read_file_streaming.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_reexec_kiwi.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_runtime_log_trimming.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_search_in_files_fs_tool.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_slash_commands.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_terminal_mode.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_tokens.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_tui_headless.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_tui_interactive_runtime.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_tui_palette.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_unified_diff.py +0 -0
- {kiwi_code-0.0.442 → kiwi_code-0.0.444}/tests/test_worktrees.py +0 -0
|
@@ -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
|
-
|
|
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]
|