janito 1.14.2__py3-none-any.whl → 2.0.0__py3-none-any.whl

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 (282) hide show
  1. janito/__init__.py +6 -1
  2. janito/__main__.py +1 -1
  3. janito/agent/setup_agent.py +139 -0
  4. janito/agent/templates/profiles/{system_prompt_template_base.txt.j2 → system_prompt_template_main.txt.j2} +1 -1
  5. janito/cli/__init__.py +9 -0
  6. janito/cli/chat_mode/bindings.py +37 -0
  7. janito/cli/chat_mode/chat_entry.py +23 -0
  8. janito/cli/chat_mode/prompt_style.py +19 -0
  9. janito/cli/chat_mode/session.py +272 -0
  10. janito/{shell/prompt/completer.py → cli/chat_mode/shell/autocomplete.py} +7 -6
  11. janito/cli/chat_mode/shell/commands/__init__.py +55 -0
  12. janito/cli/chat_mode/shell/commands/base.py +9 -0
  13. janito/cli/chat_mode/shell/commands/clear.py +12 -0
  14. janito/{shell → cli/chat_mode/shell}/commands/conversation_restart.py +34 -30
  15. janito/cli/chat_mode/shell/commands/edit.py +25 -0
  16. janito/cli/chat_mode/shell/commands/help.py +16 -0
  17. janito/cli/chat_mode/shell/commands/history_view.py +93 -0
  18. janito/cli/chat_mode/shell/commands/lang.py +25 -0
  19. janito/cli/chat_mode/shell/commands/last.py +137 -0
  20. janito/cli/chat_mode/shell/commands/livelogs.py +49 -0
  21. janito/cli/chat_mode/shell/commands/multi.py +51 -0
  22. janito/cli/chat_mode/shell/commands/prompt.py +64 -0
  23. janito/cli/chat_mode/shell/commands/role.py +36 -0
  24. janito/cli/chat_mode/shell/commands/session.py +40 -0
  25. janito/{shell → cli/chat_mode/shell}/commands/session_control.py +2 -2
  26. janito/cli/chat_mode/shell/commands/termweb_log.py +92 -0
  27. janito/cli/chat_mode/shell/commands/tools.py +32 -0
  28. janito/{shell → cli/chat_mode/shell}/commands/utility.py +4 -7
  29. janito/{shell → cli/chat_mode/shell}/commands/verbose.py +5 -5
  30. janito/cli/chat_mode/shell/session/__init__.py +1 -0
  31. janito/{shell → cli/chat_mode/shell}/session/manager.py +9 -1
  32. janito/cli/chat_mode/toolbar.py +90 -0
  33. janito/cli/cli_commands/list_models.py +35 -0
  34. janito/cli/cli_commands/list_providers.py +9 -0
  35. janito/cli/cli_commands/list_tools.py +53 -0
  36. janito/cli/cli_commands/model_selection.py +50 -0
  37. janito/cli/cli_commands/model_utils.py +84 -0
  38. janito/cli/cli_commands/set_api_key.py +19 -0
  39. janito/cli/cli_commands/show_config.py +51 -0
  40. janito/cli/cli_commands/show_system_prompt.py +62 -0
  41. janito/cli/config.py +28 -0
  42. janito/cli/console.py +3 -0
  43. janito/cli/core/__init__.py +4 -0
  44. janito/cli/core/event_logger.py +59 -0
  45. janito/cli/core/getters.py +31 -0
  46. janito/cli/core/runner.py +141 -0
  47. janito/cli/core/setters.py +174 -0
  48. janito/cli/core/unsetters.py +54 -0
  49. janito/cli/main.py +8 -196
  50. janito/cli/main_cli.py +312 -0
  51. janito/cli/prompt_core.py +230 -0
  52. janito/cli/prompt_handler.py +6 -0
  53. janito/cli/rich_terminal_reporter.py +101 -0
  54. janito/cli/single_shot_mode/__init__.py +6 -0
  55. janito/cli/single_shot_mode/handler.py +137 -0
  56. janito/cli/termweb_starter.py +73 -24
  57. janito/cli/utils.py +25 -0
  58. janito/cli/verbose_output.py +196 -0
  59. janito/config.py +5 -0
  60. janito/config_manager.py +110 -0
  61. janito/conversation_history.py +30 -0
  62. janito/{agent/tools_utils/dir_walk_utils.py → dir_walk_utils.py} +3 -2
  63. janito/driver_events.py +98 -0
  64. janito/drivers/anthropic/driver.py +113 -0
  65. janito/drivers/azure_openai/driver.py +36 -0
  66. janito/drivers/driver_registry.py +33 -0
  67. janito/drivers/google_genai/driver.py +54 -0
  68. janito/drivers/google_genai/schema_generator.py +67 -0
  69. janito/drivers/mistralai/driver.py +41 -0
  70. janito/drivers/openai/driver.py +334 -0
  71. janito/event_bus/__init__.py +2 -0
  72. janito/event_bus/bus.py +68 -0
  73. janito/event_bus/event.py +15 -0
  74. janito/event_bus/handler.py +31 -0
  75. janito/event_bus/queue_bus.py +57 -0
  76. janito/exceptions.py +23 -0
  77. janito/formatting_token.py +54 -0
  78. janito/i18n/pt.py +1 -0
  79. janito/llm/__init__.py +5 -0
  80. janito/llm/agent.py +443 -0
  81. janito/llm/auth.py +62 -0
  82. janito/llm/driver.py +239 -0
  83. janito/llm/driver_config.py +34 -0
  84. janito/llm/driver_config_builder.py +34 -0
  85. janito/llm/driver_input.py +12 -0
  86. janito/llm/message_parts.py +60 -0
  87. janito/llm/model.py +38 -0
  88. janito/llm/provider.py +187 -0
  89. janito/perf_singleton.py +3 -0
  90. janito/performance_collector.py +167 -0
  91. janito/provider_config.py +98 -0
  92. janito/provider_registry.py +152 -0
  93. janito/providers/__init__.py +7 -0
  94. janito/providers/anthropic/model_info.py +22 -0
  95. janito/providers/anthropic/provider.py +65 -0
  96. janito/providers/azure_openai/model_info.py +15 -0
  97. janito/providers/azure_openai/provider.py +72 -0
  98. janito/providers/deepseek/__init__.py +1 -0
  99. janito/providers/deepseek/model_info.py +16 -0
  100. janito/providers/deepseek/provider.py +91 -0
  101. janito/providers/google/__init__.py +1 -0
  102. janito/providers/google/model_info.py +40 -0
  103. janito/providers/google/provider.py +69 -0
  104. janito/providers/mistralai/model_info.py +37 -0
  105. janito/providers/mistralai/provider.py +69 -0
  106. janito/providers/openai/__init__.py +1 -0
  107. janito/providers/openai/model_info.py +137 -0
  108. janito/providers/openai/provider.py +107 -0
  109. janito/providers/openai/schema_generator.py +63 -0
  110. janito/providers/provider_static_info.py +21 -0
  111. janito/providers/registry.py +26 -0
  112. janito/report_events.py +38 -0
  113. janito/termweb/app.py +1 -1
  114. janito/tools/__init__.py +16 -0
  115. janito/tools/adapters/__init__.py +1 -0
  116. janito/tools/adapters/local/__init__.py +54 -0
  117. janito/tools/adapters/local/adapter.py +92 -0
  118. janito/{agent/tools → tools/adapters/local}/ask_user.py +30 -13
  119. janito/tools/adapters/local/copy_file.py +84 -0
  120. janito/{agent/tools → tools/adapters/local}/create_directory.py +11 -10
  121. janito/tools/adapters/local/create_file.py +82 -0
  122. janito/tools/adapters/local/delete_text_in_file.py +136 -0
  123. janito/{agent/tools → tools/adapters/local}/fetch_url.py +18 -19
  124. janito/tools/adapters/local/find_files.py +140 -0
  125. janito/tools/adapters/local/get_file_outline/core.py +151 -0
  126. janito/{agent/tools → tools/adapters/local}/get_file_outline/python_outline.py +125 -0
  127. janito/tools/adapters/local/get_file_outline/python_outline_v2.py +156 -0
  128. janito/{agent/tools → tools/adapters/local}/get_file_outline/search_outline.py +12 -7
  129. janito/{agent/tools → tools/adapters/local}/move_file.py +13 -9
  130. janito/{agent/tools → tools/adapters/local}/open_url.py +7 -5
  131. janito/tools/adapters/local/python_code_run.py +165 -0
  132. janito/tools/adapters/local/python_command_run.py +163 -0
  133. janito/tools/adapters/local/python_file_run.py +162 -0
  134. janito/{agent/tools → tools/adapters/local}/remove_directory.py +15 -9
  135. janito/{agent/tools → tools/adapters/local}/remove_file.py +17 -14
  136. janito/{agent/tools → tools/adapters/local}/replace_text_in_file.py +27 -22
  137. janito/tools/adapters/local/run_bash_command.py +176 -0
  138. janito/tools/adapters/local/run_powershell_command.py +219 -0
  139. janito/{agent/tools → tools/adapters/local}/search_text/core.py +32 -12
  140. janito/{agent/tools → tools/adapters/local}/search_text/match_lines.py +13 -4
  141. janito/{agent/tools → tools/adapters/local}/search_text/pattern_utils.py +12 -4
  142. janito/{agent/tools → tools/adapters/local}/search_text/traverse_directory.py +15 -2
  143. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/core.py +12 -11
  144. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/css_validator.py +1 -1
  145. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/html_validator.py +1 -1
  146. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/js_validator.py +1 -1
  147. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/json_validator.py +1 -1
  148. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/markdown_validator.py +1 -1
  149. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/ps1_validator.py +1 -1
  150. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/python_validator.py +1 -1
  151. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/xml_validator.py +1 -1
  152. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/yaml_validator.py +1 -1
  153. janito/{agent/tools/get_lines.py → tools/adapters/local/view_file.py} +45 -27
  154. janito/tools/inspect_registry.py +17 -0
  155. janito/tools/tool_base.py +105 -0
  156. janito/tools/tool_events.py +58 -0
  157. janito/tools/tool_run_exception.py +12 -0
  158. janito/{agent → tools}/tool_use_tracker.py +2 -4
  159. janito/{agent/tools_utils/utils.py → tools/tool_utils.py} +18 -9
  160. janito/tools/tools_adapter.py +207 -0
  161. janito/tools/tools_schema.py +104 -0
  162. janito/utils.py +11 -0
  163. janito/version.py +4 -0
  164. janito-2.0.0.dist-info/METADATA +232 -0
  165. janito-2.0.0.dist-info/RECORD +180 -0
  166. janito/agent/__init__.py +0 -0
  167. janito/agent/api_exceptions.py +0 -4
  168. janito/agent/config.py +0 -147
  169. janito/agent/config_defaults.py +0 -12
  170. janito/agent/config_utils.py +0 -0
  171. janito/agent/content_handler.py +0 -0
  172. janito/agent/conversation.py +0 -238
  173. janito/agent/conversation_api.py +0 -306
  174. janito/agent/conversation_exceptions.py +0 -18
  175. janito/agent/conversation_tool_calls.py +0 -39
  176. janito/agent/conversation_ui.py +0 -17
  177. janito/agent/event.py +0 -24
  178. janito/agent/event_dispatcher.py +0 -24
  179. janito/agent/event_handler_protocol.py +0 -5
  180. janito/agent/event_system.py +0 -15
  181. janito/agent/llm_conversation_history.py +0 -82
  182. janito/agent/message_handler.py +0 -20
  183. janito/agent/message_handler_protocol.py +0 -5
  184. janito/agent/openai_client.py +0 -149
  185. janito/agent/openai_schema_generator.py +0 -187
  186. janito/agent/profile_manager.py +0 -96
  187. janito/agent/queued_message_handler.py +0 -50
  188. janito/agent/rich_live.py +0 -32
  189. janito/agent/rich_message_handler.py +0 -115
  190. janito/agent/runtime_config.py +0 -36
  191. janito/agent/test_handler_protocols.py +0 -47
  192. janito/agent/test_openai_schema_generator.py +0 -93
  193. janito/agent/tests/__init__.py +0 -1
  194. janito/agent/tool_base.py +0 -63
  195. janito/agent/tool_executor.py +0 -122
  196. janito/agent/tool_registry.py +0 -49
  197. janito/agent/tools/__init__.py +0 -47
  198. janito/agent/tools/create_file.py +0 -59
  199. janito/agent/tools/delete_text_in_file.py +0 -97
  200. janito/agent/tools/find_files.py +0 -106
  201. janito/agent/tools/get_file_outline/core.py +0 -81
  202. janito/agent/tools/present_choices.py +0 -64
  203. janito/agent/tools/python_command_runner.py +0 -201
  204. janito/agent/tools/python_file_runner.py +0 -199
  205. janito/agent/tools/python_stdin_runner.py +0 -208
  206. janito/agent/tools/replace_file.py +0 -72
  207. janito/agent/tools/run_bash_command.py +0 -218
  208. janito/agent/tools/run_powershell_command.py +0 -251
  209. janito/agent/tools_utils/__init__.py +0 -1
  210. janito/agent/tools_utils/action_type.py +0 -7
  211. janito/agent/tools_utils/test_gitignore_utils.py +0 -46
  212. janito/cli/_livereload_log_utils.py +0 -13
  213. janito/cli/_print_config.py +0 -96
  214. janito/cli/_termweb_log_utils.py +0 -17
  215. janito/cli/_utils.py +0 -9
  216. janito/cli/arg_parser.py +0 -272
  217. janito/cli/cli_main.py +0 -281
  218. janito/cli/config_commands.py +0 -211
  219. janito/cli/config_runner.py +0 -35
  220. janito/cli/formatting_runner.py +0 -12
  221. janito/cli/livereload_starter.py +0 -60
  222. janito/cli/logging_setup.py +0 -38
  223. janito/cli/one_shot.py +0 -80
  224. janito/livereload/app.py +0 -25
  225. janito/rich_utils.py +0 -59
  226. janito/shell/__init__.py +0 -0
  227. janito/shell/commands/__init__.py +0 -61
  228. janito/shell/commands/config.py +0 -22
  229. janito/shell/commands/edit.py +0 -24
  230. janito/shell/commands/history_view.py +0 -18
  231. janito/shell/commands/lang.py +0 -19
  232. janito/shell/commands/livelogs.py +0 -42
  233. janito/shell/commands/prompt.py +0 -62
  234. janito/shell/commands/termweb_log.py +0 -94
  235. janito/shell/commands/tools.py +0 -26
  236. janito/shell/commands/track.py +0 -36
  237. janito/shell/main.py +0 -326
  238. janito/shell/prompt/load_prompt.py +0 -57
  239. janito/shell/prompt/session_setup.py +0 -57
  240. janito/shell/session/config.py +0 -109
  241. janito/shell/session/history.py +0 -0
  242. janito/shell/ui/interactive.py +0 -226
  243. janito/termweb/static/editor.css +0 -158
  244. janito/termweb/static/editor.css.bak +0 -145
  245. janito/termweb/static/editor.html +0 -46
  246. janito/termweb/static/editor.html.bak +0 -46
  247. janito/termweb/static/editor.js +0 -265
  248. janito/termweb/static/editor.js.bak +0 -259
  249. janito/termweb/static/explorer.html.bak +0 -59
  250. janito/termweb/static/favicon.ico +0 -0
  251. janito/termweb/static/favicon.ico.bak +0 -0
  252. janito/termweb/static/index.html +0 -53
  253. janito/termweb/static/index.html.bak +0 -54
  254. janito/termweb/static/index.html.bak.bak +0 -175
  255. janito/termweb/static/landing.html.bak +0 -36
  256. janito/termweb/static/termicon.svg +0 -1
  257. janito/termweb/static/termweb.css +0 -214
  258. janito/termweb/static/termweb.css.bak +0 -237
  259. janito/termweb/static/termweb.js +0 -162
  260. janito/termweb/static/termweb.js.bak +0 -168
  261. janito/termweb/static/termweb.js.bak.bak +0 -157
  262. janito/termweb/static/termweb_quickopen.js +0 -135
  263. janito/termweb/static/termweb_quickopen.js.bak +0 -125
  264. janito/tests/test_rich_utils.py +0 -44
  265. janito/web/__init__.py +0 -0
  266. janito/web/__main__.py +0 -25
  267. janito/web/app.py +0 -145
  268. janito-1.14.2.dist-info/METADATA +0 -306
  269. janito-1.14.2.dist-info/RECORD +0 -162
  270. janito-1.14.2.dist-info/licenses/LICENSE +0 -21
  271. /janito/{shell → cli/chat_mode/shell}/input_history.py +0 -0
  272. /janito/{shell/commands/session.py → cli/chat_mode/shell/session/history.py} +0 -0
  273. /janito/{agent/tools_utils/formatting.py → formatting.py} +0 -0
  274. /janito/{agent/tools_utils/gitignore_utils.py → gitignore_utils.py} +0 -0
  275. /janito/{agent/platform_discovery.py → platform_discovery.py} +0 -0
  276. /janito/{agent/tools → tools/adapters/local}/get_file_outline/__init__.py +0 -0
  277. /janito/{agent/tools → tools/adapters/local}/get_file_outline/markdown_outline.py +0 -0
  278. /janito/{agent/tools → tools/adapters/local}/search_text/__init__.py +0 -0
  279. /janito/{agent/tools → tools/adapters/local}/validate_file_syntax/__init__.py +0 -0
  280. {janito-1.14.2.dist-info → janito-2.0.0.dist-info}/WHEEL +0 -0
  281. {janito-1.14.2.dist-info → janito-2.0.0.dist-info}/entry_points.txt +0 -0
  282. {janito-1.14.2.dist-info → janito-2.0.0.dist-info}/top_level.txt +0 -0
@@ -1,42 +0,0 @@
1
- def handle_livelogs(console, args=None, shell_state=None, **kwargs):
2
- lines = 20
3
- if args and len(args) > 0 and str(args[0]).isdigit():
4
- lines = int(args[0])
5
- stdout_path = shell_state.termweb_stdout_path if shell_state else None
6
- stderr_path = shell_state.livereload_stderr_path if shell_state else None
7
- if not stdout_path and not stderr_path:
8
- console.print(
9
- "[yellow][livereload] No livereload log files found for this session.[/yellow]"
10
- )
11
- return
12
- stdout_lines = []
13
- stderr_lines = []
14
- if stdout_path:
15
- try:
16
- with open(stdout_path, encoding="utf-8") as f:
17
- stdout_lines = f.readlines()[-lines:]
18
- if stdout_lines:
19
- console.print(
20
- f"[yellow][livereload][stdout] Tail of {stdout_path}:\n"
21
- + "".join(stdout_lines)
22
- )
23
- except Exception as e:
24
- console.print(f"[red][livereload][stdout] Error: {e}[/red]")
25
- if stderr_path:
26
- try:
27
- with open(stderr_path, encoding="utf-8") as f:
28
- stderr_lines = f.readlines()[-lines:]
29
- if stderr_lines:
30
- console.print(
31
- f"[red][livereload][stderr] Tail of {stderr_path}:\n"
32
- + "".join(stderr_lines)
33
- )
34
- except Exception as e:
35
- console.print(f"[red][livereload][stderr] Error: {e}[/red]")
36
- if (not stdout_path or not stdout_lines) and (not stderr_path or not stderr_lines):
37
- console.print("[livereload] No output or errors captured in logs.")
38
-
39
-
40
- handle_livelogs.help_text = (
41
- "Show live updates from the server log file (default: server.log)"
42
- )
@@ -1,62 +0,0 @@
1
- from janito.agent.runtime_config import runtime_config
2
-
3
-
4
- def handle_prompt(console, shell_state=None, **kwargs):
5
- profile_manager = kwargs.get("profile_manager")
6
- if not profile_manager and shell_state and hasattr(shell_state, "profile_manager"):
7
- profile_manager = shell_state.profile_manager
8
- prompt = None
9
- if profile_manager:
10
- prompt = profile_manager.system_prompt_template
11
- if not prompt:
12
- profile_manager.refresh_prompt()
13
- prompt = profile_manager.system_prompt_template
14
- if not prompt:
15
- console.print(
16
- "[bold red]System prompt is not initialized. Please check your profile configuration.[/bold red]"
17
- )
18
- else:
19
- console.print(f"[bold magenta]System Prompt:[/bold magenta]\n{prompt}")
20
-
21
-
22
- handle_prompt.help_text = "Show the system prompt"
23
-
24
-
25
- def handle_role(console, args=None, shell_state=None, **kwargs):
26
- profile_manager = (
27
- shell_state.profile_manager
28
- if shell_state and hasattr(shell_state, "profile_manager")
29
- else kwargs.get("profile_manager")
30
- )
31
- if not args:
32
- console.print("[bold red]Usage: /role <new role description>[/bold red]")
33
- return
34
- new_role = " ".join(args)
35
- if profile_manager:
36
- profile_manager.set_role(new_role)
37
- # Update system message in conversation
38
- found = False
39
- for msg in shell_state.conversation_history.get_messages():
40
- if msg.get("role") == "system":
41
- msg["content"] = (
42
- profile_manager.system_prompt_template if profile_manager else new_role
43
- )
44
- found = True
45
- break
46
- if not found:
47
- if shell_state and hasattr(shell_state, "conversation_history"):
48
- shell_state.conversation_history.set_system_message(new_role)
49
- # Also store the raw role string
50
- if profile_manager:
51
- setattr(profile_manager, "role_name", new_role)
52
- runtime_config.set("role", new_role)
53
- console.print(f"[bold green]System role updated to:[/bold green] {new_role}")
54
-
55
-
56
- handle_role.help_text = "Change the system role"
57
-
58
-
59
- def handle_profile(console, *args, **kwargs):
60
- """/profile - Show the current and available Agent Profile (only 'base' is supported)"""
61
- console.print("[bold green]Current profile:[/bold green] base")
62
- console.print("[bold yellow]Available profiles:[/bold yellow]\n- base")
@@ -1,94 +0,0 @@
1
- import http.client
2
- from rich.console import Console
3
- from janito.agent.runtime_config import runtime_config
4
-
5
-
6
- def is_termweb_running(port):
7
- """Check if termweb is running by making an HTTP request to the root endpoint."""
8
- try:
9
- conn = http.client.HTTPConnection("localhost", port, timeout=0.5)
10
- conn.request("GET", "/")
11
- resp = conn.getresponse()
12
- return resp.status == 200
13
- except Exception:
14
- return False
15
-
16
-
17
- def handle_termweb_log_tail(console: Console, *args, shell_state=None, **kwargs):
18
- lines = 20
19
- if args and args[0].isdigit():
20
- lines = int(args[0])
21
- stdout_path = shell_state.termweb_stdout_path if shell_state else None
22
- stderr_path = shell_state.termweb_stderr_path if shell_state else None
23
- if not stdout_path and not stderr_path:
24
- console.print(
25
- "[yellow][termweb] No termweb log files found for this session.[/yellow]"
26
- )
27
- return
28
- if stdout_path:
29
- try:
30
- with open(stdout_path, encoding="utf-8") as f:
31
- stdout_lines = f.readlines()[-lines:]
32
- if stdout_lines:
33
- console.print(
34
- f"[yellow][termweb][stdout] Tail of {stdout_path}:\n"
35
- + "".join(stdout_lines)
36
- )
37
- except Exception:
38
- pass
39
- if stderr_path:
40
- try:
41
- with open(stderr_path, encoding="utf-8") as f:
42
- stderr_lines = f.readlines()[-lines:]
43
- if stderr_lines:
44
- console.print(
45
- f"[red][termweb][stderr] Tail of {stderr_path}:\n"
46
- + "".join(stderr_lines)
47
- )
48
- except Exception:
49
- pass
50
- if (not stdout_path or not stdout_lines) and (not stderr_path or not stderr_lines):
51
- console.print("[termweb] No output or errors captured in logs.")
52
-
53
-
54
- handle_termweb_log_tail.help_text = "Show the last lines of the latest termweb logs"
55
-
56
-
57
- def handle_termweb_status(console: Console, *args, shell_state=None, **kwargs):
58
- if shell_state is None:
59
- console.print(
60
- "[red]No shell state available. Cannot determine termweb status.[/red]"
61
- )
62
- return
63
- port = getattr(shell_state, "termweb_port", None)
64
- port_source = "shell_state"
65
- if not port:
66
- port = runtime_config.get("termweb_port")
67
- port_source = "runtime_config"
68
- pid = getattr(shell_state, "termweb_pid", None)
69
- stdout_path = getattr(shell_state, "termweb_stdout_path", None)
70
- stderr_path = getattr(shell_state, "termweb_stderr_path", None)
71
- running = False
72
- if port:
73
- running = is_termweb_running(port)
74
- console.print("[bold cyan]TermWeb Server Status:[/bold cyan]")
75
- console.print(f" Running: {'[green]Yes[/green]' if running else '[red]No[/red]'}")
76
- if pid:
77
- console.print(f" PID: {pid}")
78
- if port:
79
- console.print(f" Port: {port} (from {port_source})")
80
- url = f"http://localhost:{port}/"
81
- console.print(f" URL: [underline blue]{url}[/underline blue]")
82
- else:
83
- console.print(
84
- " [yellow]No port configured in state or runtime_config.[/yellow]"
85
- )
86
- if stdout_path:
87
- console.print(f" Stdout log: {stdout_path}")
88
- if stderr_path:
89
- console.print(f" Stderr log: {stderr_path}")
90
-
91
-
92
- handle_termweb_status.help_text = (
93
- "Show status information about the running termweb server"
94
- )
@@ -1,26 +0,0 @@
1
- from janito.agent.tool_registry import get_tool_schemas
2
- from rich.table import Table
3
-
4
-
5
- def handle_tools(console, args=None, shell_state=None):
6
- table = Table(title="Available Tools", show_lines=True, style="bold magenta")
7
- table.add_column("Name", style="cyan", no_wrap=True)
8
- table.add_column("Description", style="green")
9
- table.add_column("Parameters", style="yellow")
10
- try:
11
- for schema in get_tool_schemas():
12
- fn = schema["function"]
13
- params = "\n".join(
14
- [
15
- f"[bold]{k}[/]: {v['type']}"
16
- for k, v in fn["parameters"].get("properties", {}).items()
17
- ]
18
- )
19
- table.add_row(f"[b]{fn['name']}[/b]", fn["description"], params or "-")
20
- except Exception as e:
21
- console.print(f"[red]Error loading tools: {e}[/red]")
22
- return
23
- console.print(table)
24
-
25
-
26
- handle_tools.help_text = "List available tools"
@@ -1,36 +0,0 @@
1
- from janito.agent.tool_use_tracker import ToolUseTracker
2
- from rich.console import Console
3
- from rich.table import Table
4
-
5
-
6
- def handle_track(console: Console, args=None, shell_state=None):
7
- tracker = ToolUseTracker.instance()
8
- history = tracker.get_history()
9
- if not history:
10
- console.print("[bold yellow]No tool usage history found.[/bold yellow]")
11
- return
12
- table = Table(show_header=True, header_style="bold magenta")
13
- table.add_column("#", style="dim", width=4)
14
- table.add_column("Tool")
15
- table.add_column("Params/Result")
16
- for idx, entry in enumerate(history, 1):
17
- tool = entry["tool"]
18
- params = entry["params"].copy()
19
- result = entry.get("result", "")
20
- # For create/replace file, trim content in params only
21
- if tool in ("create_file", "replace_file") and "content" in params:
22
- content = params["content"]
23
- if isinstance(content, str):
24
- lines = content.splitlines()
25
- if len(lines) > 3:
26
- params["content"] = (
27
- "\n".join(lines[:2])
28
- + f"\n... (trimmed, {len(lines)} lines total)"
29
- )
30
- elif len(content) > 120:
31
- params["content"] = content[:120] + "... (trimmed)"
32
- else:
33
- params["content"] = content
34
- param_result = f"{params}\n--- Result ---\n{result}" if result else str(params)
35
- table.add_row(str(idx), tool, param_result)
36
- console.print(table)
janito/shell/main.py DELETED
@@ -1,326 +0,0 @@
1
- from janito.agent.rich_message_handler import RichMessageHandler
2
- from prompt_toolkit.history import InMemoryHistory
3
- from dataclasses import dataclass, field
4
- from typing import Optional, Any, Dict
5
- from janito.shell.prompt.session_setup import (
6
- setup_prompt_session,
7
- print_welcome_message,
8
- )
9
- from janito.shell.commands import handle_command
10
- from janito.agent.conversation_exceptions import EmptyResponseError, ProviderError
11
- from janito.agent.api_exceptions import ApiError
12
- from janito.agent.llm_conversation_history import LLMConversationHistory
13
- import janito.i18n as i18n
14
- from janito.agent.runtime_config import runtime_config
15
- from rich.console import Console
16
- import os
17
- from janito.shell.session.manager import get_session_id
18
- from prompt_toolkit.formatted_text import HTML
19
- import time
20
- from janito.shell.input_history import UserInputHistory
21
-
22
-
23
- @dataclass
24
- class ShellState:
25
- mem_history: Any = field(default_factory=InMemoryHistory)
26
- conversation_history: Any = field(default_factory=lambda: LLMConversationHistory())
27
- last_usage_info: Dict[str, int] = field(
28
- default_factory=lambda: {
29
- "prompt_tokens": 0,
30
- "completion_tokens": 0,
31
- "total_tokens": 0,
32
- }
33
- )
34
- last_elapsed: Optional[float] = None
35
- termweb_stdout_path: Optional[str] = None
36
- termweb_stderr_path: Optional[str] = None
37
- livereload_stdout_path: Optional[str] = None
38
- livereload_stderr_path: Optional[str] = None
39
- paste_mode: bool = False
40
- profile_manager: Optional[Any] = None
41
- user_input_history: Optional[Any] = None
42
-
43
-
44
- # Track the active prompt session for cleanup
45
- active_prompt_session = None
46
-
47
-
48
- def load_session(shell_state, continue_session, session_id, profile_manager):
49
- from janito.shell.session.manager import load_conversation_by_session_id
50
-
51
- if continue_session and session_id:
52
- try:
53
- messages, prompts, usage = load_conversation_by_session_id(session_id)
54
- except FileNotFoundError as e:
55
- shell_state.profile_manager.agent.message_handler.console.print(
56
- f"[bold red]{str(e)}[/bold red]"
57
- )
58
- return False
59
- shell_state.conversation_history = LLMConversationHistory(messages)
60
- conversation_history = shell_state.conversation_history
61
- found = False
62
- for msg in conversation_history.get_messages():
63
- if msg.get("role") == "system":
64
- msg["content"] = profile_manager.system_prompt_template
65
- found = True
66
- break
67
- if not found:
68
- conversation_history.set_system_message(
69
- profile_manager.system_prompt_template
70
- )
71
- shell_state.last_usage_info = usage or {}
72
- else:
73
- conversation_history = shell_state.conversation_history
74
- if (
75
- profile_manager.system_prompt_template
76
- and (
77
- not runtime_config.get("vanilla_mode", False)
78
- or runtime_config.get("system_prompt_template")
79
- )
80
- and not any(
81
- m.get("role") == "system" for m in conversation_history.get_messages()
82
- )
83
- ):
84
- conversation_history.set_system_message(
85
- profile_manager.system_prompt_template
86
- )
87
- return True
88
-
89
-
90
- def _handle_exit_confirmation(session, message_handler, conversation_history):
91
- try:
92
- confirm = (
93
- session.prompt(
94
- HTML("<inputline>Do you really want to exit? (y/n): </inputline>")
95
- )
96
- .strip()
97
- .lower()
98
- )
99
- except KeyboardInterrupt:
100
- message_handler.handle_message({"type": "error", "message": "Exiting..."})
101
- return True
102
- if confirm == "y":
103
- message_handler.handle_message({"type": "error", "message": "Exiting..."})
104
- conversation_history.add_message(
105
- {"role": "system", "content": "[Session ended by user]"}
106
- )
107
- return True
108
- return False
109
-
110
-
111
- def _handle_shell_command(user_input, console):
112
- command = user_input.strip()[1:].strip()
113
- if command:
114
- console.print(f"[bold cyan]Executing shell command:[/] {command}")
115
- exit_code = os.system(command)
116
- console.print(f"[green]Command exited with code {exit_code}[/green]")
117
- else:
118
- console.print("[red]No command provided after ![/red]")
119
-
120
-
121
- def _handle_prompt_command(user_input, console, shell_state, conversation_history):
122
- result = handle_command(
123
- user_input.strip(),
124
- console,
125
- shell_state=shell_state,
126
- )
127
- if result == "exit":
128
- conversation_history.add_message(
129
- {"role": "system", "content": "[Session ended by user]"}
130
- )
131
- return True
132
- return False
133
-
134
-
135
- def handle_prompt_loop(
136
- shell_state, session, profile_manager, agent, max_rounds, session_id
137
- ):
138
- global active_prompt_session
139
- conversation_history = shell_state.conversation_history
140
- message_handler = RichMessageHandler()
141
- console = message_handler.console
142
- while True:
143
- try:
144
- if shell_state.paste_mode:
145
- user_input = session.prompt("Multiline> ", multiline=True)
146
- was_paste_mode = True
147
- shell_state.paste_mode = False
148
- else:
149
- user_input = session.prompt(
150
- HTML("<inputline>💬 </inputline>"), multiline=False
151
- )
152
- was_paste_mode = False
153
- except EOFError:
154
- console.print("\n[bold red]Exiting...[/bold red]")
155
- break
156
- except KeyboardInterrupt:
157
- console.print()
158
- if _handle_exit_confirmation(
159
- session, message_handler, conversation_history
160
- ):
161
- break
162
- else:
163
- continue
164
- # Handle !cmd command: execute shell command with os.system
165
- if user_input.strip().startswith("!"):
166
- _handle_shell_command(user_input, console)
167
- continue
168
-
169
- cmd_input = user_input.strip().lower()
170
- if not was_paste_mode and (cmd_input.startswith("/") or cmd_input == "exit"):
171
- if _handle_prompt_command(
172
- user_input, console, shell_state, conversation_history
173
- ):
174
- break
175
- continue
176
- if not user_input.strip():
177
- continue
178
- shell_state.mem_history.append_string(user_input)
179
- shell_state.user_input_history.append(user_input)
180
- conversation_history.add_message({"role": "user", "content": user_input})
181
- handle_chat(shell_state, profile_manager, agent, max_rounds, session_id)
182
- # Save conversation history after exiting
183
- save_conversation_history(conversation_history, session_id)
184
-
185
-
186
- def handle_keyboard_interrupt(conversation_history, message_handler):
187
- removed_count = 0
188
- while (
189
- conversation_history.last_message()
190
- and conversation_history.last_message().get("role") != "assistant"
191
- ):
192
- conversation_history.remove_last_message()
193
- removed_count += 1
194
- # Remove the assistant message itself, if present
195
- if (
196
- conversation_history.last_message()
197
- and conversation_history.last_message().get("role") == "assistant"
198
- ):
199
- conversation_history.remove_last_message()
200
- removed_count += 1
201
- message_handler.handle_message(
202
- {
203
- "type": "info",
204
- "message": f"\nLast turn cleared due to interruption. Returning to prompt. (removed {removed_count} last msgs)\n",
205
- }
206
- )
207
-
208
-
209
- def handle_chat_error(message_handler, error_type, error):
210
- if error_type == "ProviderError":
211
- message_handler.handle_message(
212
- {"type": "error", "message": f"Provider error: {error}"}
213
- )
214
- elif error_type == "EmptyResponseError":
215
- message_handler.handle_message({"type": "error", "message": f"Error: {error}"})
216
- elif error_type == "ApiError":
217
- message_handler.handle_message({"type": "error", "message": str(error)})
218
- elif error_type == "Exception":
219
- import traceback
220
-
221
- tb = traceback.format_exc()
222
- message_handler.handle_message(
223
- {
224
- "type": "error",
225
- "message": f"Unexpected error: {error}\n{tb}\nReturning to prompt.",
226
- }
227
- )
228
-
229
-
230
- def handle_chat(shell_state, profile_manager, agent, max_rounds, session_id):
231
- conversation_history = shell_state.conversation_history
232
- message_handler = RichMessageHandler()
233
- console = message_handler.console
234
- start_time = time.time()
235
- try:
236
- response = profile_manager.agent.chat(
237
- conversation_history,
238
- max_rounds=max_rounds,
239
- message_handler=message_handler,
240
- spinner=True,
241
- )
242
- except KeyboardInterrupt:
243
- handle_keyboard_interrupt(conversation_history, message_handler)
244
- return
245
- except ProviderError as e:
246
- handle_chat_error(message_handler, "ProviderError", e)
247
- return
248
- except EmptyResponseError as e:
249
- handle_chat_error(message_handler, "EmptyResponseError", e)
250
- return
251
- except ApiError as e:
252
- handle_chat_error(message_handler, "ApiError", e)
253
- return
254
- except Exception as e:
255
- handle_chat_error(message_handler, "Exception", e)
256
- return
257
- shell_state.last_elapsed = time.time() - start_time
258
- usage = response.get("usage")
259
- if usage:
260
- for k in ("prompt_tokens", "completion_tokens", "total_tokens"):
261
- shell_state.last_usage_info[k] = usage.get(k, 0)
262
- content = response.get("content")
263
- if content and (
264
- len(conversation_history) == 0
265
- or conversation_history.get_messages()[-1].get("role") != "assistant"
266
- ):
267
- conversation_history.add_message({"role": "assistant", "content": content})
268
-
269
-
270
- def save_conversation_history(conversation_history, session_id):
271
- from janito.shell.session.manager import get_session_id
272
-
273
- history_dir = os.path.join(os.path.expanduser("~"), ".janito", "chat_history")
274
- os.makedirs(history_dir, exist_ok=True)
275
- session_id_to_save = session_id if session_id else get_session_id()
276
- history_path = os.path.join(history_dir, f"{session_id_to_save}.json")
277
- conversation_history.to_json_file(history_path)
278
-
279
-
280
- def start_chat_shell(
281
- profile_manager,
282
- continue_session=False,
283
- session_id=None,
284
- max_rounds=100,
285
- termweb_stdout_path=None,
286
- termweb_stderr_path=None,
287
- livereload_stdout_path=None,
288
- livereload_stderr_path=None,
289
- ):
290
- i18n.set_locale(runtime_config.get("lang", "en"))
291
- global active_prompt_session
292
- agent = profile_manager.agent
293
- message_handler = RichMessageHandler()
294
- console = message_handler.console
295
- console.clear()
296
- shell_state = ShellState()
297
- shell_state.profile_manager = profile_manager
298
- profile_manager.refresh_prompt()
299
- user_input_history = UserInputHistory()
300
- user_input_dicts = user_input_history.load()
301
- mem_history = shell_state.mem_history
302
- for item in user_input_dicts:
303
- if isinstance(item, dict) and "input" in item:
304
- mem_history.append_string(item["input"])
305
- shell_state.user_input_history = user_input_history
306
- if not load_session(shell_state, continue_session, session_id, profile_manager):
307
- return
308
-
309
- def last_usage_info_ref():
310
- return shell_state.last_usage_info
311
-
312
- last_elapsed = shell_state.last_elapsed
313
- print_welcome_message(console, continue_id=session_id if continue_session else None)
314
- session = setup_prompt_session(
315
- lambda: shell_state.conversation_history.get_messages(),
316
- last_usage_info_ref,
317
- last_elapsed,
318
- mem_history,
319
- profile_manager,
320
- agent,
321
- lambda: shell_state.conversation_history,
322
- )
323
- active_prompt_session = session
324
- handle_prompt_loop(
325
- shell_state, session, profile_manager, agent, max_rounds, session_id
326
- )
@@ -1,57 +0,0 @@
1
- import os
2
- import importlib.resources
3
-
4
-
5
- def load_prompt(filename=None):
6
- """
7
- Load the system prompt from a file. If filename is None, use the default prompt file.
8
- Returns the prompt string.
9
- Tries source path first, then falls back to importlib.resources for installed packages.
10
- """
11
- default_rel_path = os.path.normpath(
12
- os.path.join(
13
- os.path.dirname(__file__),
14
- "../agent/templates/profiles/system_prompt_template_default.j2",
15
- )
16
- )
17
- if filename is None:
18
- filename = default_rel_path
19
-
20
- # Try loading from source path first
21
- abs_path = os.path.abspath(filename)
22
- if os.path.exists(abs_path):
23
- with open(abs_path, "r", encoding="utf-8") as f:
24
- return f.read()
25
-
26
- # If not found, try importlib.resources (for installed package)
27
- try:
28
- # Remove leading directories up to 'janito/agent/templates'
29
- # and get the relative path inside the package
30
- resource_path = filename
31
- for marker in ["janito/agent/templates/", "agent/templates/"]:
32
- idx = filename.replace("\\", "/").find(marker)
33
- if idx != -1:
34
- resource_path = filename[idx + len("janito/agent/templates/") :]
35
- break
36
-
37
- # Try loading from janito.agent.templates.profiles
38
- if resource_path.startswith("profiles/"):
39
- package = "janito.agent.templates.profiles"
40
- resource = resource_path[len("profiles/") :]
41
- elif resource_path.startswith("features/"):
42
- package = "janito.agent.templates.features"
43
- resource = resource_path[len("features/") :]
44
- else:
45
- package = "janito.agent.templates"
46
- resource = resource_path
47
-
48
- with (
49
- importlib.resources.files(package)
50
- .joinpath(resource)
51
- .open("r", encoding="utf-8") as f
52
- ):
53
- return f.read()
54
- except Exception as e:
55
- raise FileNotFoundError(
56
- f"Prompt file not found at '{abs_path}' or in package resources: {e}"
57
- )