kiwi-code 0.0.447__tar.gz → 0.0.448__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 (76) hide show
  1. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/PKG-INFO +5 -4
  2. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/pyproject.toml +7 -4
  3. kiwi_code-0.0.448/scripts/ws_auth_check.py +76 -0
  4. kiwi_code-0.0.448/src/common/banner.py +57 -0
  5. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/__init__.py +1 -2
  6. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/checkpoints.py +0 -2
  7. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/cli.py +2 -2
  8. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/client.py +18 -20
  9. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/commands.py +25 -19
  10. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/terminal_mode.py +170 -165
  11. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_runtime/__init__.py +1 -2
  12. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_runtime/main.py +310 -107
  13. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/__init__.py +1 -1
  14. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/main.py +58 -214
  15. kiwi_code-0.0.448/src/kiwi_tui/role_mode.py +256 -0
  16. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/runtime_agent.py +0 -3
  17. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/__init__.py +1 -2
  18. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/command_result.py +0 -10
  19. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/detach_files.py +1 -1
  20. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/id_picker.py +0 -19
  21. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/login.py +33 -62
  22. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/runtime_cleanup.py +2 -18
  23. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/runtime_logs.py +0 -9
  24. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/term_dashboard.py +856 -183
  25. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/slash_commands.py +14 -33
  26. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/widgets.py +26 -0
  27. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/worktrees.py +0 -2
  28. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/test_hello.py +2 -2
  29. kiwi_code-0.0.448/tests/__init__.py +0 -0
  30. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/conftest.py +9 -0
  31. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_cli_help.py +9 -13
  32. kiwi_code-0.0.448/tests/test_role_mode_injection.py +131 -0
  33. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_slash_commands.py +8 -0
  34. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_term_dashboard_ui.py +84 -13
  35. kiwi_code-0.0.448/tests/test_terminal_mode.py +47 -0
  36. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_tui_interactive_runtime.py +2 -90
  37. kiwi_code-0.0.448/uv.lock +1583 -0
  38. kiwi_code-0.0.447/CLAUDE.md +0 -79
  39. kiwi_code-0.0.447/src/kiwi_tui/screens/dashboard.py +0 -3870
  40. kiwi_code-0.0.447/tests/test_terminal_mode.py +0 -107
  41. kiwi_code-0.0.447/tests/test_tui_headless.py +0 -1099
  42. kiwi_code-0.0.447/uv.lock +0 -1460
  43. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/.github/workflows/publish.yml +0 -0
  44. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/.github/workflows/test.yml +0 -0
  45. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/.gitignore +0 -0
  46. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/.python-version +0 -0
  47. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/Makefile +0 -0
  48. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/README.md +0 -0
  49. {kiwi_code-0.0.447/tests → kiwi_code-0.0.448/src/common}/__init__.py +0 -0
  50. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/auth.py +0 -0
  51. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/logger.py +0 -0
  52. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/models.py +0 -0
  53. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/runtime_manager.py +0 -0
  54. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_cli/server.py +0 -0
  55. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_runtime/__main__.py +0 -0
  56. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/inline_file_picker.py +0 -0
  57. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/random_words.py +0 -0
  58. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/attach_content.py +0 -0
  59. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/file_browser.py +0 -0
  60. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/help.py +0 -0
  61. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/screens/slash_picker.py +0 -0
  62. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/status_words.py +0 -0
  63. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/term_app.py +0 -0
  64. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/src/kiwi_tui/ui_settings.py +0 -0
  65. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_batch_fs_tool.py +0 -0
  66. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_checkpoints.py +0 -0
  67. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_copy_path_fs_tool.py +0 -0
  68. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_imports.py +0 -0
  69. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_read_file_streaming.py +0 -0
  70. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_reexec_kiwi.py +0 -0
  71. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_runtime_log_trimming.py +0 -0
  72. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_search_in_files_fs_tool.py +0 -0
  73. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_tokens.py +0 -0
  74. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_tui_palette.py +0 -0
  75. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_unified_diff.py +0 -0
  76. {kiwi_code-0.0.447 → kiwi_code-0.0.448}/tests/test_worktrees.py +0 -0
@@ -1,8 +1,8 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: kiwi-code
3
- Version: 0.0.447
3
+ Version: 0.0.448
4
4
  Summary: A textual-based terminal user interface application
5
- Project-URL: Homepage, https://meetkiwi.ai
5
+ Project-URL: Homepage, https://kiwicode.ai
6
6
  Author-email: Anurag <anurag@meetkiwi.co>
7
7
  License: Proprietary
8
8
  Keywords: cli,terminal,textual,tui
@@ -14,11 +14,12 @@ Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Classifier: Programming Language :: Python :: 3.13
16
16
  Requires-Python: <4.0,>=3.11
17
- Requires-Dist: autobots-client==0.1.1
17
+ Requires-Dist: codeglass>=0.1.2
18
18
  Requires-Dist: httpx>=0.25.0
19
19
  Requires-Dist: loguru>=0.7.3
20
20
  Requires-Dist: psutil>=5.9.0
21
21
  Requires-Dist: pydantic>=2.12.5
22
+ Requires-Dist: pykiwiai==0.0.12
22
23
  Requires-Dist: setproctitle>=1.3.0
23
24
  Requires-Dist: textual-dev>=1.8.0
24
25
  Requires-Dist: textual>=8.1.1
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "kiwi-code"
3
- version = "0.0.447"
3
+ version = "0.0.448"
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
- "autobots-client==0.1.1",
8
+ "pykiwiai==0.0.12",
9
9
  "loguru>=0.7.3",
10
10
  "pydantic>=2.12.5",
11
11
  "textual>=8.1.1",
@@ -16,6 +16,7 @@ dependencies = [
16
16
  "psutil>=5.9.0",
17
17
  "setproctitle>=1.3.0",
18
18
  "wonderwords>=2.2.0",
19
+ "codeglass>=0.1.2",
19
20
  ]
20
21
 
21
22
  authors = [
@@ -34,7 +35,8 @@ classifiers = [
34
35
  ]
35
36
 
36
37
  [project.urls]
37
- Homepage = "https://meetkiwi.ai"
38
+ Homepage = "https://kiwicode.ai"
39
+ # Repository = "https://github.com/runkailabs/kiwi-code"
38
40
 
39
41
  [project.scripts]
40
42
  kiwi = "kiwi_tui.main:main"
@@ -54,8 +56,9 @@ filterwarnings = [
54
56
  "ignore::DeprecationWarning",
55
57
  ]
56
58
 
59
+
57
60
  [tool.hatch.build.targets.wheel]
58
- packages = ["src/kiwi_cli", "src/kiwi_tui", "src/kiwi_runtime"]
61
+ packages = ["src/common", "src/kiwi_cli", "src/kiwi_tui", "src/kiwi_runtime"]
59
62
 
60
63
  [build-system]
61
64
  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.meetkiwi.ai/v1/terminal/ws/connect",
34
+ help="Full ws connect URI (default: wss://api.meetkiwi.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,57 @@
1
+ """Shared Kiwi Code banner assets used by kiwi-runtime and kiwi-tui."""
2
+
3
+ # Block-character chevron-and-dot logo (6 lines, 11 chars wide — same height as
4
+ # the KIWI CODE wordmark). Reads as ">." — half-blocks give the diagonal a
5
+ # half-row step so the stroke stays continuous instead of reading as a staircase.
6
+ LOGO = [
7
+ "▀██▄ ",
8
+ " ▀██▄ ",
9
+ " ▀██▄ ",
10
+ " ▄██▀ ",
11
+ " ▄██▀ ",
12
+ "▄██▀ █▌ ",
13
+ ]
14
+
15
+ # "KIWI CODE" block text (6 lines tall).
16
+ TEXT = [
17
+ "██╗ ██╗██╗██╗ ██╗██╗ ██████╗ ██████╗ ██████╗ ███████╗",
18
+ "██║ ██╔╝██║██║ ██║██║ ██╔════╝██╔═══██╗██╔══██╗██╔════╝",
19
+ "█████╔╝ ██║██║ █╗ ██║██║ ██║ ██║ ██║██║ ██║█████╗ ",
20
+ "██╔═██╗ ██║██║███╗██║██║ ██║ ██║ ██║██║ ██║██╔══╝ ",
21
+ "██║ ██╗██║╚███╔███╔╝██║ ╚██████╗╚██████╔╝██████╔╝███████╗",
22
+ "╚═╝ ╚═╝╚═╝ ╚══╝╚══╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝",
23
+ ]
24
+
25
+ TAGLINE = "Think fast. Code smarter. Automate everything."
26
+
27
+ # Brand color — darker cyan
28
+ CYAN = "rgb(0,168,184)"
29
+ CYAN_HEX = "#00a8b8"
30
+
31
+ # Layout constants (matching kiwi-runtime banner).
32
+ LOGO_W = 11
33
+ GAP = " "
34
+ TEXT_START = 0
35
+ TAGLINE_ROW = TEXT_START + len(TEXT) + 1
36
+
37
+
38
+ def compose_banner_lines(tagline: str | None = None) -> list[str]:
39
+ """Compose logo + KIWI CODE text side by side, returning a list of lines."""
40
+ effective_tagline = tagline if tagline is not None else TAGLINE
41
+ lines = []
42
+ # The logo is shorter than logo+tagline, so keep going past it with blanks.
43
+ for i in range(max(len(LOGO), TAGLINE_ROW + 1)):
44
+ padded = (LOGO[i] if i < len(LOGO) else "").ljust(LOGO_W)
45
+ text_idx = i - TEXT_START
46
+ if 0 <= text_idx < len(TEXT):
47
+ lines.append(f"{padded}{GAP}{TEXT[text_idx]}")
48
+ elif i == TAGLINE_ROW:
49
+ lines.append(f"{padded}{GAP}{effective_tagline}")
50
+ else:
51
+ lines.append(padded)
52
+ return lines
53
+
54
+
55
+ def compose_banner_text(tagline: str | None = None) -> str:
56
+ """Return the full banner as a single multi-line string."""
57
+ return "\n".join(compose_banner_lines(tagline=tagline))
@@ -1,4 +1,3 @@
1
1
  """Kiwi CLI - command-line interface and shared infrastructure modules."""
2
2
 
3
-
4
- __version__ = "0.0.447"
3
+ __version__ = "0.0.448"
@@ -1,5 +1,3 @@
1
- from __future__ import annotations
2
-
3
1
  import json
4
2
  import os
5
3
  from dataclasses import dataclass
@@ -3,14 +3,14 @@ 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 autobots_client import AuthenticatedClient
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
10
10
  from . import commands
11
11
  from . import __version__ as KIWI_CLI_VERSION
12
12
 
13
- app = typer.Typer(name="kiwi", help="Kiwi — interact with the Kiwi AI platform.")
13
+ app = typer.Typer(name="kiwi", help="Kiwi — interact with the Kiwi Code platform.")
14
14
 
15
15
  actions_app = typer.Typer(name="actions", help="Manage actions.")
16
16
  action_runs_app = typer.Typer(name="runs", help="Manage action runs (results).")
@@ -6,22 +6,20 @@ import json
6
6
  import codecs
7
7
  import httpx
8
8
  from loguru import logger
9
- from autobots_client import Client, AuthenticatedClient
10
- from autobots_client.api.hello import hello_v1_hello_get
11
- from autobots_client.api.auth import (
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 autobots_client.api.actions import async_run_action_v1_actions_id_async_run_post
15
- from autobots_client.api.action_results import get_action_result_v1_action_results_id_get
16
- from autobots_client.models.body_return_user_and_session_v1_auth_post import (
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 autobots_client.models.body_async_run_action_v1_actions_id_async_run_post import (
19
+ from pykiwiai.models.body_async_run_action_v1_actions_id_async_run_post import (
20
20
  BodyAsyncRunActionV1ActionsIdAsyncRunPost,
21
21
  )
22
- from autobots_client.models.body_async_run_action_v1_actions_id_async_run_post_input import (
23
- BodyAsyncRunActionV1ActionsIdAsyncRunPostInput,
24
- )
22
+ from pykiwiai.models import DataBlock, Metadata
25
23
  from .models import AuthTokens, LoginCredentials
26
24
 
27
25
 
@@ -253,8 +251,8 @@ class AutobotsClientWrapper:
253
251
 
254
252
  import mimetypes
255
253
  from pathlib import Path
256
- from autobots_client.api.files import upload_files_v1_files_post
257
- from autobots_client.models.body_upload_files_v1_files_post import BodyUploadFilesV1FilesPost
254
+ from pykiwiai.api.files import upload_files_v1_files_post
255
+ from pykiwiai.models.body_upload_files_v1_files_post import BodyUploadFilesV1FilesPost
258
256
 
259
257
  # Validate all files exist first
260
258
  paths = []
@@ -333,18 +331,17 @@ class AutobotsClientWrapper:
333
331
  if metadata:
334
332
  default_metadata.update(metadata)
335
333
 
336
- input_data = BodyAsyncRunActionV1ActionsIdAsyncRunPostInput()
337
- input_data.additional_properties = {
338
- "text": user_input,
339
- "urls": urls or [],
340
- "metadata": default_metadata
341
- }
334
+ input_data = DataBlock(
335
+ text=user_input,
336
+ urls=urls or [],
337
+ metadata=Metadata.from_dict(default_metadata),
338
+ )
342
339
 
343
340
  body = BodyAsyncRunActionV1ActionsIdAsyncRunPost(input_=input_data)
344
341
  logger.info(f"Request body: {body.to_dict()}")
345
342
 
346
343
  # Import UNSET for optional parameter
347
- from autobots_client.types import UNSET
344
+ from pykiwiai.types import UNSET
348
345
 
349
346
  response = async_run_action_v1_actions_id_async_run_post.sync_detailed(
350
347
  id=action_id,
@@ -464,7 +461,8 @@ class AutobotsClientWrapper:
464
461
  logger.info(f"Result structure keys: {result_dict.keys()}")
465
462
  if "result" in result_dict and isinstance(result_dict["result"], dict):
466
463
  logger.info(f"Result.result keys: {result_dict['result'].keys()}")
467
-
464
+ result = result_dict['result']
465
+ logger.info(f"Result's results : {result['results']}")
468
466
  return True, result_dict, "Result retrieved"
469
467
  else:
470
468
  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 autobots_client import AuthenticatedClient
9
- from autobots_client.api.actions import (
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 autobots_client.api.action_results import (
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 autobots_client.types import UNSET
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_.value):<25} "
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_.value}",
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 autobots_client.models.event_result_status import EventResultStatus
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 = EventResultStatus(status.lower())
97
- except ValueError:
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.value:<12} {_val(doc.name):<30} "
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.value}",
147
+ f"Status: {_enum(doc.status)}",
136
148
  f"Name: {_val(doc.name)}",
137
- f"Type: {doc.type_.value}",
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_.value}",
159
+ f" Type: {_enum(doc.result.type_)}",
148
160
  f" ID: {doc.result.field_id}",
149
161
  ]
150
162
  return lines
@@ -167,12 +179,6 @@ Files:
167
179
  /files Show pending file uploads
168
180
  /clear-files Clear pending file uploads
169
181
 
170
- Metadata (persistent across runs):
171
- /metadata Show current metadata
172
- /metadata set <k> <v> Set a metadata field
173
- /metadata remove <k> Remove a metadata field
174
- /metadata clear Clear all metadata
175
-
176
182
  Runtime:
177
183
  /runtime status Show runtime status
178
184
  /runtime start Start runtime