kiwi-code 0.0.512__tar.gz → 0.0.513__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 (143) hide show
  1. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/PKG-INFO +1 -1
  2. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/pyproject.toml +1 -1
  3. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/autocode.py +33 -0
  4. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/terminal_mode.py +3 -2
  5. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/term_dashboard.py +12 -5
  6. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_autocode_actions.py +49 -0
  7. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_term_dashboard_ui.py +53 -0
  8. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/uv.lock +1 -1
  9. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/.github/workflows/publish.yml +0 -0
  10. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/.github/workflows/test.yml +0 -0
  11. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/.gitignore +0 -0
  12. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/.python-version +0 -0
  13. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/Makefile +0 -0
  14. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/README.md +0 -0
  15. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/docs/runtime_audit.html +0 -0
  16. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/docs/social_login_e2e.md +0 -0
  17. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/scripts/set_edition.py +0 -0
  18. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/scripts/ws_auth_check.py +0 -0
  19. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/common/__init__.py +0 -0
  20. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/common/banner.py +0 -0
  21. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/__init__.py +0 -0
  22. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/_edition.py +0 -0
  23. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/auth.py +0 -0
  24. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/checkpoints.py +0 -0
  25. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/cli.py +0 -0
  26. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/client.py +0 -0
  27. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/commands.py +0 -0
  28. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/edition.py +0 -0
  29. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/human_questions.py +0 -0
  30. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/io_threads.py +0 -0
  31. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/logger.py +0 -0
  32. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/models.py +0 -0
  33. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/oauth.py +0 -0
  34. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/run_activity.py +0 -0
  35. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/runtime_manager.py +0 -0
  36. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/server.py +0 -0
  37. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_cli/subagents.py +0 -0
  38. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/__init__.py +0 -0
  39. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/__main__.py +0 -0
  40. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/auth.py +0 -0
  41. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/checkpoints.py +0 -0
  42. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/cli.py +0 -0
  43. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/commands.py +0 -0
  44. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/constants.py +0 -0
  45. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/__init__.py +0 -0
  46. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/batch.py +0 -0
  47. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/codelens.py +0 -0
  48. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/context.py +0 -0
  49. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/edits.py +0 -0
  50. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/handler.py +0 -0
  51. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/paths.py +0 -0
  52. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/read.py +0 -0
  53. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/search.py +0 -0
  54. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/text.py +0 -0
  55. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/upload.py +0 -0
  56. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/fs/write.py +0 -0
  57. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/handlers.py +0 -0
  58. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/link.py +0 -0
  59. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/main.py +0 -0
  60. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/restricted.py +0 -0
  61. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/sessions.py +0 -0
  62. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/state.py +0 -0
  63. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/tui_bridge.py +0 -0
  64. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/ui.py +0 -0
  65. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_runtime/uploads.py +0 -0
  66. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/__init__.py +0 -0
  67. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/attention.py +0 -0
  68. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/autoupdate.py +0 -0
  69. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/inline_file_picker.py +0 -0
  70. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/latex_unicode.py +0 -0
  71. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/main.py +0 -0
  72. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/random_words.py +0 -0
  73. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/role_mode.py +0 -0
  74. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/runtime_agent.py +0 -0
  75. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/__init__.py +0 -0
  76. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/attach_content.py +0 -0
  77. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/command_result.py +0 -0
  78. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/detach_files.py +0 -0
  79. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/file_browser.py +0 -0
  80. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/help.py +0 -0
  81. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/id_picker.py +0 -0
  82. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/login.py +0 -0
  83. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/runtime_cleanup.py +0 -0
  84. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/runtime_logs.py +0 -0
  85. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/slash_picker.py +0 -0
  86. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/term_activity_view.py +0 -0
  87. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/term_dashboard_css.py +0 -0
  88. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/term_dashboard_helpers.py +0 -0
  89. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/term_dashboard_widgets.py +0 -0
  90. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/term_question_widgets.py +0 -0
  91. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/term_status_line.py +0 -0
  92. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/screens/term_subagent_widgets.py +0 -0
  93. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/slash_commands.py +0 -0
  94. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/status_words.py +0 -0
  95. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/term_app.py +0 -0
  96. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/terminal_theme.py +0 -0
  97. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/ui_settings.py +0 -0
  98. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/widgets.py +0 -0
  99. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/src/kiwi_tui/worktrees.py +0 -0
  100. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/test_hello.py +0 -0
  101. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/__init__.py +0 -0
  102. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/conftest.py +0 -0
  103. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_account_server.py +0 -0
  104. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_attention.py +0 -0
  105. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_autoupdate.py +0 -0
  106. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_batch_fs_tool.py +0 -0
  107. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_checkpoints.py +0 -0
  108. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_cli_help.py +0 -0
  109. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_command_tips.py +0 -0
  110. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_copy_path_fs_tool.py +0 -0
  111. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_fs_edit_fidelity.py +0 -0
  112. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_human_questions.py +0 -0
  113. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_imports.py +0 -0
  114. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_io_threads.py +0 -0
  115. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_login_social.py +0 -0
  116. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_math_and_tables.py +0 -0
  117. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_oauth.py +0 -0
  118. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_read_file_streaming.py +0 -0
  119. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_reexec_kiwi.py +0 -0
  120. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_reply_selection.py +0 -0
  121. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_role_mode_injection.py +0 -0
  122. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_run_activity.py +0 -0
  123. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_run_steering.py +0 -0
  124. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_runtime_cleanup_per_account.py +0 -0
  125. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_runtime_connection.py +0 -0
  126. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_runtime_edit_diffs.py +0 -0
  127. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_runtime_fixes.py +0 -0
  128. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_runtime_imports_on_windows.py +0 -0
  129. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_runtime_log_trimming.py +0 -0
  130. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_runtime_social_login.py +0 -0
  131. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_search_in_files_fs_tool.py +0 -0
  132. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_slash_commands.py +0 -0
  133. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_stats_command.py +0 -0
  134. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_status_line.py +0 -0
  135. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_subagents.py +0 -0
  136. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_terminal_mode.py +0 -0
  137. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_terminal_theme.py +0 -0
  138. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_toasts.py +0 -0
  139. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_tokens.py +0 -0
  140. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_tui_interactive_runtime.py +0 -0
  141. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_tui_palette.py +0 -0
  142. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_unified_diff.py +0 -0
  143. {kiwi_code-0.0.512 → kiwi_code-0.0.513}/tests/test_worktrees.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: kiwi-code
3
- Version: 0.0.512
3
+ Version: 0.0.513
4
4
  Summary: A textual-based terminal user interface application
5
5
  Project-URL: Homepage, https://kiwicode.ai
6
6
  Author-email: Anurag <anurag@meetkiwi.co>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kiwi-code"
3
- version = "0.0.512"
3
+ version = "0.0.513"
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"
@@ -8,6 +8,11 @@ contains "autocode" in any spelling: "Autocode", "AutoCodeClaude",
8
8
  When two of them have the same name ignoring case, spaces and punctuation
9
9
  ("AutocodeClaude" and "AutoCodeClaude", "Autocode OpenAI Flash" and
10
10
  "AutocodeOpenaiFlash"), only the most recently created one is kept.
11
+
12
+ Which one a new session starts with depends on the account (``default_id_for``):
13
+ Work (Enterprise, api.meetkiwi.ai) starts with "Autocode OpenAI Flash", Personal
14
+ (Subscription, api.runkai.ai) and every other server with "Autocode". The VS Code
15
+ extension makes the same choice (src/defaultAgent.ts).
11
16
  """
12
17
 
13
18
  import re
@@ -17,11 +22,17 @@ from datetime import datetime, timezone
17
22
  from pykiwiai import AuthenticatedClient
18
23
  from pykiwiai.api.actions import list_system_actions_v1_actions_system_actions_get
19
24
 
25
+ from kiwi_cli.server import SERVER_PRESETS
26
+
20
27
  # Fetch every system action in one page: paging with offset is not reliable on
21
28
  # the servers (offset > 0 returns an empty page).
22
29
  _SYSTEM_ACTIONS_LIMIT = 500
23
30
 
24
31
 
32
+ #: The default on the Work (Enterprise) server, compared as _normalize compares names.
33
+ _ENTERPRISE_DEFAULT = "autocodeopenaiflash"
34
+
35
+
25
36
  def _normalize(name: object) -> str:
26
37
  return re.sub(r"[^a-z0-9]", "", str(name or "").lower())
27
38
 
@@ -64,6 +75,28 @@ class AutocodeActions:
64
75
  return action.id
65
76
  return self.actions[0].id if self.actions else None
66
77
 
78
+ def name_of(self, action_id: object) -> str | None:
79
+ """The name of the AutoCode action ``action_id``, or None if it is not one."""
80
+ for action in self.actions:
81
+ if action.id == action_id:
82
+ return action.name
83
+ return None
84
+
85
+ def default_id_for(self, backend_url: object) -> str | None:
86
+ """The action a new session starts with on ``backend_url``: "Autocode OpenAI
87
+ Flash" on the Work (Enterprise) server when it has one, else ``default_id``."""
88
+ if is_enterprise_backend(backend_url):
89
+ for action in self.actions:
90
+ if _normalize(action.name) == _ENTERPRISE_DEFAULT:
91
+ return action.id
92
+ return self.default_id
93
+
94
+
95
+ def is_enterprise_backend(backend_url: object) -> bool:
96
+ """True for the Work (Enterprise) server, api.meetkiwi.ai."""
97
+ url = str(backend_url or "").strip().rstrip("/").lower()
98
+ return url == SERVER_PRESETS["work"]["http"]
99
+
67
100
 
68
101
  def _created(action: AutocodeAction) -> datetime:
69
102
  """When the action was created. Falls back to the timestamp in its ObjectId."""
@@ -227,10 +227,11 @@ def _default_action_id(session: _TerminalSession) -> str:
227
227
  found = fetch_autocode_actions(session.client.client)
228
228
  if found.status_code in (401, 403) and _refresh_tokens(session):
229
229
  found = fetch_autocode_actions(session.client.client)
230
- if found.default_id is None:
230
+ default_id = found.default_id_for(session.backend_url)
231
+ if default_id is None:
231
232
  detail = "no AutoCode actions on this server" if found.ok else f"HTTP {found.status_code}"
232
233
  raise TerminalModeError(f"Could not find the AutoCode action ({detail}). Pass --action-id to choose one.")
233
- return found.default_id
234
+ return default_id
234
235
 
235
236
 
236
237
  def _build_authenticated_session(server: str | None) -> _TerminalSession:
@@ -1503,7 +1503,8 @@ class TermDashboardScreen(Screen):
1503
1503
  cwd = str(Path.cwd())
1504
1504
  cwd_short = cwd if len(cwd) <= 44 else f"{cwd[:20]}…{cwd[-20:]}"
1505
1505
 
1506
- action = self.current_action_name or self.current_action_id or ""
1506
+ # While its name loads, an action shows as "…", not as its id.
1507
+ action = self.current_action_name or ("…" if self.current_action_id else "")
1507
1508
  action = str(action)
1508
1509
  action_short = action if len(action) <= 16 else (action[:12] + "…")
1509
1510
 
@@ -1643,7 +1644,7 @@ class TermDashboardScreen(Screen):
1643
1644
  def _refresh_welcome_meta(self) -> None:
1644
1645
  """Update action name + run id displayed in the welcome header."""
1645
1646
  try:
1646
- action = self.current_action_name or self.current_action_id or "—"
1647
+ action = self.current_action_name or ("…" if self.current_action_id else "—")
1647
1648
  run = self.current_run_id or "—"
1648
1649
  self.query_one("#term-welcome-account", Static).update(self._account_text())
1649
1650
  self.query_one("#term-welcome-action", Static).update(f"Action: {action}")
@@ -1764,9 +1765,14 @@ class TermDashboardScreen(Screen):
1764
1765
  except Exception as e:
1765
1766
  logger.debug(f"Loading AutoCode actions failed: {e}")
1766
1767
  if not self.current_action_id and self._autocode is not None:
1767
- self.current_action_id = self._autocode.default_id or ""
1768
+ self.current_action_id = self._autocode.default_id_for(self._autocode_backend) or ""
1768
1769
  requested_id = self.current_action_id
1769
- if not requested_id:
1770
+ # An AutoCode action's name is already in the list just fetched: show it with the
1771
+ # id, rather than the id first and the name a request later.
1772
+ known = self._autocode.name_of(requested_id) if self._autocode is not None and requested_id else None
1773
+ if known and not self.current_action_name:
1774
+ self.current_action_name = known
1775
+ if not requested_id or known:
1770
1776
  self._refresh_top_bar()
1771
1777
  self._refresh_hint_model()
1772
1778
  self._refresh_input_label()
@@ -1779,7 +1785,8 @@ class TermDashboardScreen(Screen):
1779
1785
  if resp.status_code == 200 and resp.parsed:
1780
1786
  self.current_action_name = getattr(resp.parsed, "name", None) or requested_id
1781
1787
  else:
1782
- self.current_action_name = None
1788
+ # The name could not be found: the id is all there is to show.
1789
+ self.current_action_name = requested_id
1783
1790
  self._refresh_top_bar()
1784
1791
  self._refresh_hint_model()
1785
1792
  self._refresh_input_label()
@@ -154,3 +154,52 @@ def test_the_default_autocode_is_also_the_latest_one(monkeypatch):
154
154
  )
155
155
  found = fetch_autocode_actions(client=None)
156
156
  assert [a.id for a in found.actions] == ["new"] and found.default_id == "new"
157
+
158
+
159
+ # The default by account: Work (Enterprise, api.meetkiwi.ai) starts with Autocode OpenAI
160
+ # Flash, Personal (Subscription, api.runkai.ai) and every other server with Autocode. The
161
+ # VS Code extension makes the same choice (src/defaultAgent.ts).
162
+
163
+ WORK = "https://api.meetkiwi.ai"
164
+ PERSONAL = "https://api.runkai.ai"
165
+
166
+
167
+ def _flash_and_autocode(monkeypatch):
168
+ _respond(
169
+ monkeypatch,
170
+ 200,
171
+ [
172
+ _doc("a", "Autocode"),
173
+ _doc("f1", "Autocode OpenAI Flash", created_at=datetime(2026, 5, 1)),
174
+ _doc("f2", "AutocodeOpenaiFlash", created_at=datetime(2026, 10, 24)),
175
+ _doc("c", "AutoCodeClaude", "claude"),
176
+ ],
177
+ )
178
+ return fetch_autocode_actions(client=None)
179
+
180
+
181
+ @pytest.mark.parametrize("url", [WORK, WORK + "/", "https://API.meetkiwi.ai"])
182
+ def test_work_starts_with_the_latest_flash(monkeypatch, url):
183
+ assert _flash_and_autocode(monkeypatch).default_id_for(url) == "f2"
184
+
185
+
186
+ @pytest.mark.parametrize("url", [PERSONAL, "https://dev.api.myautobots.com", "http://localhost:8000", "", None])
187
+ def test_personal_and_other_servers_start_with_autocode(monkeypatch, url):
188
+ assert _flash_and_autocode(monkeypatch).default_id_for(url) == "a"
189
+
190
+
191
+ def test_work_without_flash_starts_with_autocode(monkeypatch):
192
+ _respond(monkeypatch, 200, [_doc("a", "Autocode"), _doc("c", "AutoCodeClaude", "claude")])
193
+ assert fetch_autocode_actions(client=None).default_id_for(WORK) == "a"
194
+
195
+
196
+ def test_no_actions_means_no_default_on_work_either():
197
+ assert AutocodeActions(status_code=200).default_id_for(WORK) is None
198
+
199
+
200
+ def test_name_of_gives_an_autocode_actions_name(monkeypatch):
201
+ found = _flash_and_autocode(monkeypatch)
202
+ assert found.name_of("f2") == "AutocodeOpenaiFlash"
203
+ assert found.name_of("a") == "Autocode"
204
+ assert found.name_of("unknown") is None
205
+ assert found.name_of(None) is None
@@ -979,3 +979,56 @@ async def test_scrolling_up_while_a_reply_streams_stays_up_until_back_at_the_end
979
979
  await pilot.pause(0.3)
980
980
  await stream(5)
981
981
  assert gap() <= 1
982
+
983
+
984
+ @pytest.mark.asyncio
985
+ async def test_an_action_shows_by_name_never_by_its_id_while_the_name_loads() -> None:
986
+ app = _TermDashboardTestApp()
987
+ async with app.run_test(size=(120, 60)) as pilot:
988
+ await pilot.pause(0.05)
989
+ screen = app.screen
990
+ screen.current_action_id = "6a0625b8ab5f80ba8ac5d012"
991
+ screen.current_action_name = None
992
+ screen._refresh_welcome_meta()
993
+ screen._refresh_top_bar()
994
+ await pilot.pause(0)
995
+
996
+ assert str(screen.query_one("#term-welcome-action").content) == "Action: …"
997
+ assert "6a0625b8" not in _top_bar_text(screen)
998
+
999
+
1000
+ @pytest.mark.asyncio
1001
+ async def test_the_default_autocode_is_named_from_its_list_without_a_second_request(monkeypatch) -> None:
1002
+ from kiwi_cli.autocode import AutocodeAction, AutocodeActions
1003
+ from pykiwiai.api.actions import get_action_v1_actions_id_get
1004
+
1005
+ app = _TermDashboardTestApp()
1006
+ async with app.run_test(size=(120, 60)) as pilot:
1007
+ await pilot.pause(0.05)
1008
+ screen = app.screen
1009
+ app.autobots_client = SimpleNamespace(client=object(), base_url="https://api.meetkiwi.ai")
1010
+ app._sync_autobots_client_from_disk = lambda: None
1011
+ listed = AutocodeActions(
1012
+ status_code=200,
1013
+ actions=(
1014
+ AutocodeAction(id="a", name="Autocode", type="openai"),
1015
+ AutocodeAction(id="f", name="Autocode OpenAI Flash", type="openai"),
1016
+ ),
1017
+ )
1018
+
1019
+ async def load(refresh: bool = False):
1020
+ screen._autocode, screen._autocode_backend = listed, "https://api.meetkiwi.ai"
1021
+ return listed
1022
+
1023
+ monkeypatch.setattr(screen, "_load_autocode_actions", load)
1024
+
1025
+ def no_request(**_kwargs):
1026
+ raise AssertionError("the name was already known")
1027
+
1028
+ monkeypatch.setattr(get_action_v1_actions_id_get, "sync_detailed", no_request)
1029
+ screen.current_action_id = ""
1030
+ screen.current_action_name = None
1031
+
1032
+ await screen._fetch_action_name_async()
1033
+ assert screen.current_action_id == "f"
1034
+ assert screen.current_action_name == "Autocode OpenAI Flash"
@@ -412,7 +412,7 @@ wheels = [
412
412
 
413
413
  [[package]]
414
414
  name = "kiwi-code"
415
- version = "0.0.512"
415
+ version = "0.0.513"
416
416
  source = { editable = "." }
417
417
  dependencies = [
418
418
  { name = "codeglass" },
File without changes
File without changes
File without changes
File without changes
File without changes