kiwi-code 0.0.445__tar.gz → 0.0.446__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.445 → kiwi_code-0.0.446}/PKG-INFO +3 -4
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/pyproject.toml +5 -5
- kiwi_code-0.0.446/scripts/ws_auth_check.py +76 -0
- kiwi_code-0.0.446/src/common/banner.py +61 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/__init__.py +1 -1
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/cli.py +1 -1
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/client.py +13 -12
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/commands.py +25 -13
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/models.py +1 -1
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/server.py +1 -1
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/terminal_mode.py +169 -164
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_runtime/__init__.py +1 -1
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_runtime/main.py +392 -87
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/__init__.py +1 -1
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/main.py +28 -2
- kiwi_code-0.0.446/src/kiwi_tui/role_mode.py +269 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/dashboard.py +275 -50
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/login.py +11 -46
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/runtime_cleanup.py +2 -2
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/term_dashboard.py +780 -108
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/slash_commands.py +13 -26
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/widgets.py +26 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/test_hello.py +1 -1
- kiwi_code-0.0.446/tests/__init__.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/conftest.py +9 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_cli_help.py +10 -7
- kiwi_code-0.0.446/tests/test_role_mode_injection.py +131 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_slash_commands.py +8 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_term_dashboard_ui.py +84 -13
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_terminal_mode.py +5 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_tui_headless.py +35 -34
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_tui_interactive_runtime.py +25 -9
- kiwi_code-0.0.446/uv.lock +1511 -0
- kiwi_code-0.0.445/CLAUDE.md +0 -79
- kiwi_code-0.0.445/uv.lock +0 -1451
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/.github/workflows/publish.yml +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/.github/workflows/test.yml +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/.gitignore +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/.python-version +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/Makefile +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/README.md +0 -0
- {kiwi_code-0.0.445/tests → kiwi_code-0.0.446/src/common}/__init__.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/auth.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/checkpoints.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/logger.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_cli/runtime_manager.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_runtime/__main__.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/inline_file_picker.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/random_words.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/runtime_agent.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/__init__.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/attach_content.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/command_result.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/detach_files.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/file_browser.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/help.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/id_picker.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/runtime_logs.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/screens/slash_picker.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/status_words.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/term_app.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/ui_settings.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/src/kiwi_tui/worktrees.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_batch_fs_tool.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_checkpoints.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_copy_path_fs_tool.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_imports.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_read_file_streaming.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_reexec_kiwi.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_runtime_log_trimming.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_search_in_files_fs_tool.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_tokens.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_tui_palette.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_unified_diff.py +0 -0
- {kiwi_code-0.0.445 → kiwi_code-0.0.446}/tests/test_worktrees.py +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kiwi-code
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.446
|
|
4
4
|
Summary: A textual-based terminal user interface application
|
|
5
5
|
Project-URL: Homepage, https://meetkiwi.ai
|
|
6
|
-
|
|
7
|
-
Author-email: Anurag Jha <anurag@meetkiwi.co>
|
|
6
|
+
Author-email: Anurag <anurag@meetkiwi.co>
|
|
8
7
|
License: Proprietary
|
|
9
8
|
Keywords: cli,terminal,textual,tui
|
|
10
9
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -15,11 +14,11 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
16
|
Requires-Python: <4.0,>=3.11
|
|
18
|
-
Requires-Dist: autobots-client==0.1.1
|
|
19
17
|
Requires-Dist: httpx>=0.25.0
|
|
20
18
|
Requires-Dist: loguru>=0.7.3
|
|
21
19
|
Requires-Dist: psutil>=5.9.0
|
|
22
20
|
Requires-Dist: pydantic>=2.12.5
|
|
21
|
+
Requires-Dist: pykiwiai==0.0.11
|
|
23
22
|
Requires-Dist: setproctitle>=1.3.0
|
|
24
23
|
Requires-Dist: textual-dev>=1.8.0
|
|
25
24
|
Requires-Dist: textual>=8.1.1
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "kiwi-code"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.446"
|
|
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"
|
|
7
7
|
dependencies = [
|
|
8
|
-
"
|
|
8
|
+
"pykiwiai==0.0.11",
|
|
9
9
|
"loguru>=0.7.3",
|
|
10
10
|
"pydantic>=2.12.5",
|
|
11
11
|
"textual>=8.1.1",
|
|
@@ -19,7 +19,7 @@ dependencies = [
|
|
|
19
19
|
]
|
|
20
20
|
|
|
21
21
|
authors = [
|
|
22
|
-
{ name = "Anurag
|
|
22
|
+
{ name = "Anurag", email = "anurag@meetkiwi.co" }
|
|
23
23
|
]
|
|
24
24
|
license = { text = "Proprietary" }
|
|
25
25
|
keywords = ["tui", "textual", "terminal", "cli"]
|
|
@@ -35,7 +35,6 @@ classifiers = [
|
|
|
35
35
|
|
|
36
36
|
[project.urls]
|
|
37
37
|
Homepage = "https://meetkiwi.ai"
|
|
38
|
-
Repository = "https://github.com/jetoslabs/kiwi-code"
|
|
39
38
|
|
|
40
39
|
[project.scripts]
|
|
41
40
|
kiwi = "kiwi_tui.main:main"
|
|
@@ -55,8 +54,9 @@ filterwarnings = [
|
|
|
55
54
|
"ignore::DeprecationWarning",
|
|
56
55
|
]
|
|
57
56
|
|
|
57
|
+
|
|
58
58
|
[tool.hatch.build.targets.wheel]
|
|
59
|
-
packages = ["src/kiwi_cli", "src/kiwi_tui", "src/kiwi_runtime"]
|
|
59
|
+
packages = ["src/common", "src/kiwi_cli", "src/kiwi_tui", "src/kiwi_runtime"]
|
|
60
60
|
|
|
61
61
|
[build-system]
|
|
62
62
|
requires = ["hatchling"]
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Quick WS handshake + auth check.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
uv run python scripts/ws_auth_check.py --token "$ACCESS_TOKEN"
|
|
5
|
+
|
|
6
|
+
Notes:
|
|
7
|
+
- Pass the *raw* access token. If you paste "Bearer <token>", we will strip the prefix.
|
|
8
|
+
- This script does NOT print the token.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import asyncio
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
import uuid
|
|
17
|
+
|
|
18
|
+
import websockets
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _normalize_token(token: str) -> str:
|
|
22
|
+
t = token.strip()
|
|
23
|
+
if t.lower().startswith("bearer "):
|
|
24
|
+
t = t.split(" ", 1)[1].strip()
|
|
25
|
+
return t
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async def main() -> None:
|
|
29
|
+
ap = argparse.ArgumentParser()
|
|
30
|
+
ap.add_argument("--token", required=True, help="Access token (raw JWT; 'Bearer ' prefix is ok)")
|
|
31
|
+
ap.add_argument(
|
|
32
|
+
"--ws-uri",
|
|
33
|
+
default="wss://api.runkai.ai/v1/terminal/ws/connect",
|
|
34
|
+
help="Full ws connect URI (default: wss://api.runkai.ai/v1/terminal/ws/connect)",
|
|
35
|
+
)
|
|
36
|
+
ap.add_argument(
|
|
37
|
+
"--mode",
|
|
38
|
+
default="restricted",
|
|
39
|
+
choices=["restricted", "full"],
|
|
40
|
+
help="Mode to send in auth payload (matches kiwi-runtime)",
|
|
41
|
+
)
|
|
42
|
+
args = ap.parse_args()
|
|
43
|
+
|
|
44
|
+
token = _normalize_token(args.token)
|
|
45
|
+
|
|
46
|
+
async with websockets.connect(
|
|
47
|
+
args.ws_uri,
|
|
48
|
+
ping_interval=None,
|
|
49
|
+
open_timeout=8,
|
|
50
|
+
close_timeout=3,
|
|
51
|
+
max_queue=8,
|
|
52
|
+
) as ws:
|
|
53
|
+
msg = {
|
|
54
|
+
"type": "auth",
|
|
55
|
+
"token": token,
|
|
56
|
+
"agent_id": str(uuid.uuid4()),
|
|
57
|
+
"platform": sys.platform,
|
|
58
|
+
"mode": args.mode,
|
|
59
|
+
"allowed_dirs": [os.getcwd()],
|
|
60
|
+
}
|
|
61
|
+
await ws.send(json.dumps(msg))
|
|
62
|
+
|
|
63
|
+
resp_raw = await asyncio.wait_for(ws.recv(), timeout=10)
|
|
64
|
+
resp = json.loads(resp_raw)
|
|
65
|
+
|
|
66
|
+
print("AUTH_RESP_TYPE", resp.get("type"))
|
|
67
|
+
print("AUTH_RESP_KEYS", sorted(resp.keys()))
|
|
68
|
+
if resp.get("type") == "error":
|
|
69
|
+
print("AUTH_ERROR_MESSAGE", (resp.get("message") or "").strip()[:300])
|
|
70
|
+
else:
|
|
71
|
+
safe = {k: resp.get(k) for k in ("type", "agent_id", "mode", "consumer_id", "message") if k in resp}
|
|
72
|
+
print("AUTH_RESP_SAFE", safe)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Shared Kiwi AI banner assets used by kiwi-runtime and kiwi-tui."""
|
|
2
|
+
|
|
3
|
+
# Block-character kiwi bird logo (16 lines, 33 chars wide).
|
|
4
|
+
LOGO = [
|
|
5
|
+
" ▄██▄ ",
|
|
6
|
+
" ▄██▄▄ ████ ▄▄██▄ ",
|
|
7
|
+
" ▀█████▄ █▀▀█ ▄█████▀ ",
|
|
8
|
+
" ▀███▀▀█ ████ █▀▀███▀ ",
|
|
9
|
+
" ▀█▄ █ ████ █ ▄█▀ ",
|
|
10
|
+
" ▀▀▄██████▄▀▀ ",
|
|
11
|
+
"▄██████▀▀█▄██████████▄█▀▀██████▄",
|
|
12
|
+
"▀██████▄▄█▀██████████▀█▄▄██████▀",
|
|
13
|
+
" ▄▄▀██████▀▄▄ ",
|
|
14
|
+
" ▄█▀ █ ████ █ ▀█▄ ",
|
|
15
|
+
" ▄███▄▄█ ████ █▄▄███▄ ",
|
|
16
|
+
" ▄█████▀ █▄▄█ ▀█████▄ ",
|
|
17
|
+
" ▀██▀▀ ████ ▀▀██▀ ",
|
|
18
|
+
" ▀██▀ ",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
# "KIWI AI" block text (6 lines tall).
|
|
22
|
+
TEXT = [
|
|
23
|
+
"██╗ ██╗██╗██╗ ██╗██╗ █████╗ ██╗",
|
|
24
|
+
"██║ ██╔╝██║██║ ██║██║ ██╔══██╗██║",
|
|
25
|
+
"█████╔╝ ██║██║ █╗ ██║██║ ███████║██║",
|
|
26
|
+
"██╔═██╗ ██║██║███╗██║██║ ██╔══██║██║",
|
|
27
|
+
"██║ ██╗██║╚███╔███╔╝██║ ██║ ██║██║",
|
|
28
|
+
"╚═╝ ╚═╝╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝╚═╝",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
TAGLINE = "Think fast. Code smarter. Automate everything."
|
|
32
|
+
|
|
33
|
+
# Brand color — darker cyan
|
|
34
|
+
CYAN = "rgb(0,168,184)"
|
|
35
|
+
CYAN_HEX = "#00a8b8"
|
|
36
|
+
|
|
37
|
+
# Layout constants (matching kiwi-runtime banner).
|
|
38
|
+
LOGO_W = 33
|
|
39
|
+
GAP = " "
|
|
40
|
+
TEXT_START = 5
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def compose_banner_lines(tagline: str | None = None) -> list[str]:
|
|
44
|
+
"""Compose logo + KIWI AI text side by side, returning a list of lines."""
|
|
45
|
+
effective_tagline = tagline if tagline is not None else TAGLINE
|
|
46
|
+
lines = []
|
|
47
|
+
for i, logo_line in enumerate(LOGO):
|
|
48
|
+
padded = logo_line.ljust(LOGO_W)
|
|
49
|
+
text_idx = i - TEXT_START
|
|
50
|
+
if 0 <= text_idx < len(TEXT):
|
|
51
|
+
lines.append(f"{padded}{GAP}{TEXT[text_idx]}")
|
|
52
|
+
elif text_idx == len(TEXT) + 1:
|
|
53
|
+
lines.append(f"{padded}{GAP}{effective_tagline}")
|
|
54
|
+
else:
|
|
55
|
+
lines.append(padded)
|
|
56
|
+
return lines
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def compose_banner_text(tagline: str | None = None) -> str:
|
|
60
|
+
"""Return the full banner as a single multi-line string."""
|
|
61
|
+
return "\n".join(compose_banner_lines(tagline=tagline))
|
|
@@ -3,7 +3,7 @@ from typing import Optional, Callable
|
|
|
3
3
|
from loguru import logger
|
|
4
4
|
logger.remove() # Suppress loguru console output in CLI mode
|
|
5
5
|
import typer
|
|
6
|
-
from
|
|
6
|
+
from pykiwiai import AuthenticatedClient
|
|
7
7
|
from .auth import TokenManager
|
|
8
8
|
from .models import AppConfig
|
|
9
9
|
from .server import http_url_from_server
|
|
@@ -6,20 +6,20 @@ import json
|
|
|
6
6
|
import codecs
|
|
7
7
|
import httpx
|
|
8
8
|
from loguru import logger
|
|
9
|
-
from
|
|
10
|
-
from
|
|
11
|
-
from
|
|
9
|
+
from pykiwiai import Client, AuthenticatedClient
|
|
10
|
+
from pykiwiai.api.hello import hello_v1_hello_get
|
|
11
|
+
from pykiwiai.api.auth import (
|
|
12
12
|
return_user_and_session_v1_auth_post,
|
|
13
13
|
)
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
14
|
+
from pykiwiai.api.actions import async_run_action_v1_actions_id_async_run_post
|
|
15
|
+
from pykiwiai.api.action_results import get_action_result_v1_action_results_id_get
|
|
16
|
+
from pykiwiai.models.body_return_user_and_session_v1_auth_post import (
|
|
17
17
|
BodyReturnUserAndSessionV1AuthPost,
|
|
18
18
|
)
|
|
19
|
-
from
|
|
19
|
+
from pykiwiai.models.body_async_run_action_v1_actions_id_async_run_post import (
|
|
20
20
|
BodyAsyncRunActionV1ActionsIdAsyncRunPost,
|
|
21
21
|
)
|
|
22
|
-
from
|
|
22
|
+
from pykiwiai.models.body_async_run_action_v1_actions_id_async_run_post_input import (
|
|
23
23
|
BodyAsyncRunActionV1ActionsIdAsyncRunPostInput,
|
|
24
24
|
)
|
|
25
25
|
from .models import AuthTokens, LoginCredentials
|
|
@@ -253,8 +253,8 @@ class AutobotsClientWrapper:
|
|
|
253
253
|
|
|
254
254
|
import mimetypes
|
|
255
255
|
from pathlib import Path
|
|
256
|
-
from
|
|
257
|
-
from
|
|
256
|
+
from pykiwiai.api.files import upload_files_v1_files_post
|
|
257
|
+
from pykiwiai.models.body_upload_files_v1_files_post import BodyUploadFilesV1FilesPost
|
|
258
258
|
|
|
259
259
|
# Validate all files exist first
|
|
260
260
|
paths = []
|
|
@@ -344,7 +344,7 @@ class AutobotsClientWrapper:
|
|
|
344
344
|
logger.info(f"Request body: {body.to_dict()}")
|
|
345
345
|
|
|
346
346
|
# Import UNSET for optional parameter
|
|
347
|
-
from
|
|
347
|
+
from pykiwiai.types import UNSET
|
|
348
348
|
|
|
349
349
|
response = async_run_action_v1_actions_id_async_run_post.sync_detailed(
|
|
350
350
|
id=action_id,
|
|
@@ -464,7 +464,8 @@ class AutobotsClientWrapper:
|
|
|
464
464
|
logger.info(f"Result structure keys: {result_dict.keys()}")
|
|
465
465
|
if "result" in result_dict and isinstance(result_dict["result"], dict):
|
|
466
466
|
logger.info(f"Result.result keys: {result_dict['result'].keys()}")
|
|
467
|
-
|
|
467
|
+
result = result_dict['result']
|
|
468
|
+
logger.info(f"Result's results : {result['results']}")
|
|
468
469
|
return True, result_dict, "Result retrieved"
|
|
469
470
|
else:
|
|
470
471
|
error_msg = f"Failed to get result: status {response.status_code}"
|
|
@@ -5,17 +5,17 @@ and returns a list of strings (output lines).
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from typing import Optional
|
|
8
|
-
from
|
|
9
|
-
from
|
|
8
|
+
from pykiwiai import AuthenticatedClient
|
|
9
|
+
from pykiwiai.api.actions import (
|
|
10
10
|
list_actions_v1_actions_get,
|
|
11
11
|
get_action_v1_actions_id_get,
|
|
12
12
|
)
|
|
13
|
-
from
|
|
13
|
+
from pykiwiai.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
17
|
|
|
18
|
-
from
|
|
18
|
+
from pykiwiai.types import UNSET
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
# Helpers
|
|
@@ -35,6 +35,18 @@ def _val(v) -> str:
|
|
|
35
35
|
return str(v)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
def _enum(v) -> str:
|
|
39
|
+
"""Return a stable string for either Enum-like objects or plain strings.
|
|
40
|
+
|
|
41
|
+
pykiwiai <=0.0.1 used Enum types (value attribute).
|
|
42
|
+
pykiwiai >=0.0.11 uses Literal[str] so fields are plain strings.
|
|
43
|
+
"""
|
|
44
|
+
if v is None or isinstance(v, type(UNSET)):
|
|
45
|
+
return ""
|
|
46
|
+
return str(getattr(v, "value", v))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
38
50
|
# actions
|
|
39
51
|
|
|
40
52
|
def actions_list(client: AuthenticatedClient, *, name: Optional[str] = None, limit: int = 20, offset: int = 0) -> list[str]:
|
|
@@ -57,7 +69,7 @@ def actions_list(client: AuthenticatedClient, *, name: Optional[str] = None, lim
|
|
|
57
69
|
]
|
|
58
70
|
for doc in result.docs:
|
|
59
71
|
lines.append(
|
|
60
|
-
f"{doc.field_id:<28} {_val(doc.name):<30} {_val(doc.type_
|
|
72
|
+
f"{doc.field_id:<28} {_val(doc.name):<30} {_val(_enum(doc.type_)):<25} "
|
|
61
73
|
f"{_val(doc.version):<6} {_fmt_date(doc.created_at)}"
|
|
62
74
|
)
|
|
63
75
|
return lines
|
|
@@ -73,7 +85,7 @@ def actions_get(client: AuthenticatedClient, *, id: str) -> list[str]:
|
|
|
73
85
|
return [
|
|
74
86
|
f"ID: {doc.field_id}",
|
|
75
87
|
f"Name: {doc.name}",
|
|
76
|
-
f"Type: {doc.type_
|
|
88
|
+
f"Type: {_enum(doc.type_)}",
|
|
77
89
|
f"Version: {_val(doc.version)}",
|
|
78
90
|
f"Description: {_val(doc.description)}",
|
|
79
91
|
f"Published: {_val(doc.is_published)}",
|
|
@@ -88,13 +100,13 @@ def actions_get(client: AuthenticatedClient, *, id: str) -> list[str]:
|
|
|
88
100
|
def runs_list(client: AuthenticatedClient, *, action_id: Optional[str] = None, action_name: Optional[str] = None,
|
|
89
101
|
status: Optional[str] = None, limit: int = 20, offset: int = 0) -> list[str]:
|
|
90
102
|
"""List action runs. Returns output lines."""
|
|
91
|
-
from
|
|
103
|
+
from pykiwiai.models.event_result_status import check_event_result_status
|
|
92
104
|
|
|
93
105
|
status_enum = UNSET
|
|
94
106
|
if status:
|
|
95
107
|
try:
|
|
96
|
-
status_enum =
|
|
97
|
-
except
|
|
108
|
+
status_enum = check_event_result_status(status.lower())
|
|
109
|
+
except TypeError:
|
|
98
110
|
return [f"Invalid status: {status}. Valid: processing, success, error, stuck, waiting"]
|
|
99
111
|
|
|
100
112
|
resp = list_action_result_v1_action_results_get.sync_detailed(
|
|
@@ -117,7 +129,7 @@ def runs_list(client: AuthenticatedClient, *, action_id: Optional[str] = None, a
|
|
|
117
129
|
]
|
|
118
130
|
for doc in result.docs:
|
|
119
131
|
lines.append(
|
|
120
|
-
f"{doc.field_id:<28} {doc.status
|
|
132
|
+
f"{doc.field_id:<28} {_enum(doc.status):<12} {_val(doc.name):<30} "
|
|
121
133
|
f"{_fmt_date(doc.created_at):<18} {_fmt_date(doc.updated_at)}"
|
|
122
134
|
)
|
|
123
135
|
return lines
|
|
@@ -132,9 +144,9 @@ def runs_get(client: AuthenticatedClient, *, id: str) -> list[str]:
|
|
|
132
144
|
doc = resp.parsed
|
|
133
145
|
lines = [
|
|
134
146
|
f"ID: {doc.field_id}",
|
|
135
|
-
f"Status: {doc.status
|
|
147
|
+
f"Status: {_enum(doc.status)}",
|
|
136
148
|
f"Name: {_val(doc.name)}",
|
|
137
|
-
f"Type: {doc.type_
|
|
149
|
+
f"Type: {_enum(doc.type_)}",
|
|
138
150
|
f"Saved: {_val(doc.is_saved)}",
|
|
139
151
|
f"Created: {_fmt_date(doc.created_at)}",
|
|
140
152
|
f"Updated: {_fmt_date(doc.updated_at)}",
|
|
@@ -144,7 +156,7 @@ def runs_get(client: AuthenticatedClient, *, id: str) -> list[str]:
|
|
|
144
156
|
"",
|
|
145
157
|
"Action:",
|
|
146
158
|
f" Name: {doc.result.name}",
|
|
147
|
-
f" Type: {doc.result.type_
|
|
159
|
+
f" Type: {_enum(doc.result.type_)}",
|
|
148
160
|
f" ID: {doc.result.field_id}",
|
|
149
161
|
]
|
|
150
162
|
return lines
|
|
@@ -115,7 +115,7 @@ class LoginCredentials(BaseModel):
|
|
|
115
115
|
|
|
116
116
|
class AppConfig(BaseModel):
|
|
117
117
|
"""Application configuration."""
|
|
118
|
-
backend_url: str = "https://api.
|
|
118
|
+
backend_url: str = "https://api.runkai.ai"
|
|
119
119
|
api_key: Optional[str] = None
|
|
120
120
|
log_level: str = "INFO"
|
|
121
121
|
theme: str = "dark"
|
|
@@ -11,7 +11,7 @@ The value can be:
|
|
|
11
11
|
This module intentionally contains *no persistence*. It is runtime-only.
|
|
12
12
|
"""
|
|
13
13
|
SERVER_PRESETS: dict[str, dict[str, str]] = {
|
|
14
|
-
"app": {"ws": "wss://api.
|
|
14
|
+
"app": {"ws": "wss://api.runkai.ai", "http": "https://api.runkai.ai"},
|
|
15
15
|
"dev": {"ws": "wss://dev.api.myautobots.com", "http": "https://dev.api.myautobots.com"},
|
|
16
16
|
"local": {"ws": "ws://localhost:8000", "http": "http://localhost:8000"},
|
|
17
17
|
}
|