janito 2.1.1__py3-none-any.whl → 2.3.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 (137) hide show
  1. janito/__init__.py +6 -6
  2. janito/agent/setup_agent.py +14 -5
  3. janito/agent/templates/profiles/system_prompt_template_main.txt.j2 +3 -1
  4. janito/cli/chat_mode/bindings.py +6 -0
  5. janito/cli/chat_mode/session.py +16 -0
  6. janito/cli/chat_mode/shell/autocomplete.py +21 -21
  7. janito/cli/chat_mode/shell/commands/__init__.py +3 -2
  8. janito/cli/chat_mode/shell/commands/clear.py +12 -12
  9. janito/cli/chat_mode/shell/commands/exec.py +27 -0
  10. janito/cli/chat_mode/shell/commands/multi.py +51 -51
  11. janito/cli/chat_mode/shell/commands/tools.py +17 -6
  12. janito/cli/chat_mode/shell/input_history.py +62 -62
  13. janito/cli/chat_mode/shell/session/manager.py +1 -0
  14. janito/cli/chat_mode/toolbar.py +3 -1
  15. janito/cli/cli_commands/list_models.py +35 -35
  16. janito/cli/cli_commands/list_providers.py +9 -9
  17. janito/cli/cli_commands/list_tools.py +53 -53
  18. janito/cli/cli_commands/model_selection.py +50 -50
  19. janito/cli/cli_commands/model_utils.py +13 -2
  20. janito/cli/cli_commands/set_api_key.py +19 -19
  21. janito/cli/cli_commands/show_config.py +51 -51
  22. janito/cli/cli_commands/show_system_prompt.py +62 -62
  23. janito/cli/config.py +2 -1
  24. janito/cli/core/__init__.py +4 -4
  25. janito/cli/core/event_logger.py +59 -59
  26. janito/cli/core/getters.py +3 -1
  27. janito/cli/core/runner.py +27 -6
  28. janito/cli/core/setters.py +5 -1
  29. janito/cli/core/unsetters.py +54 -54
  30. janito/cli/main_cli.py +12 -1
  31. janito/cli/prompt_core.py +5 -2
  32. janito/cli/rich_terminal_reporter.py +22 -3
  33. janito/cli/single_shot_mode/__init__.py +6 -6
  34. janito/cli/single_shot_mode/handler.py +11 -1
  35. janito/cli/verbose_output.py +1 -1
  36. janito/config.py +5 -5
  37. janito/config_manager.py +2 -0
  38. janito/driver_events.py +14 -0
  39. janito/drivers/anthropic/driver.py +113 -113
  40. janito/drivers/azure_openai/driver.py +38 -3
  41. janito/drivers/driver_registry.py +0 -2
  42. janito/drivers/openai/driver.py +196 -36
  43. janito/formatting_token.py +54 -54
  44. janito/i18n/__init__.py +35 -35
  45. janito/i18n/messages.py +23 -23
  46. janito/i18n/pt.py +47 -47
  47. janito/llm/__init__.py +5 -5
  48. janito/llm/agent.py +443 -443
  49. janito/llm/auth.py +1 -0
  50. janito/llm/driver.py +7 -1
  51. janito/llm/driver_config.py +1 -0
  52. janito/llm/driver_config_builder.py +34 -34
  53. janito/llm/driver_input.py +12 -12
  54. janito/llm/message_parts.py +60 -60
  55. janito/llm/model.py +38 -38
  56. janito/llm/provider.py +196 -196
  57. janito/provider_config.py +7 -3
  58. janito/provider_registry.py +29 -5
  59. janito/providers/__init__.py +1 -0
  60. janito/providers/anthropic/model_info.py +22 -22
  61. janito/providers/anthropic/provider.py +2 -2
  62. janito/providers/azure_openai/model_info.py +7 -6
  63. janito/providers/azure_openai/provider.py +44 -2
  64. janito/providers/deepseek/__init__.py +1 -1
  65. janito/providers/deepseek/model_info.py +16 -16
  66. janito/providers/deepseek/provider.py +91 -91
  67. janito/providers/google/model_info.py +21 -29
  68. janito/providers/google/provider.py +49 -38
  69. janito/providers/mistralai/provider.py +2 -2
  70. janito/providers/openai/model_info.py +0 -11
  71. janito/providers/openai/provider.py +1 -1
  72. janito/providers/provider_static_info.py +2 -3
  73. janito/providers/registry.py +26 -26
  74. janito/tools/adapters/__init__.py +1 -1
  75. janito/tools/adapters/local/__init__.py +62 -62
  76. janito/tools/adapters/local/adapter.py +33 -11
  77. janito/tools/adapters/local/ask_user.py +102 -102
  78. janito/tools/adapters/local/copy_file.py +84 -84
  79. janito/tools/adapters/local/create_directory.py +69 -69
  80. janito/tools/adapters/local/create_file.py +82 -82
  81. janito/tools/adapters/local/delete_text_in_file.py +4 -7
  82. janito/tools/adapters/local/fetch_url.py +97 -97
  83. janito/tools/adapters/local/find_files.py +138 -140
  84. janito/tools/adapters/local/get_file_outline/__init__.py +1 -1
  85. janito/tools/adapters/local/get_file_outline/core.py +117 -151
  86. janito/tools/adapters/local/get_file_outline/java_outline.py +40 -0
  87. janito/tools/adapters/local/get_file_outline/markdown_outline.py +14 -14
  88. janito/tools/adapters/local/get_file_outline/python_outline.py +303 -303
  89. janito/tools/adapters/local/get_file_outline/python_outline_v2.py +156 -156
  90. janito/tools/adapters/local/get_file_outline/search_outline.py +33 -33
  91. janito/tools/adapters/local/move_file.py +3 -13
  92. janito/tools/adapters/local/open_html_in_browser.py +24 -29
  93. janito/tools/adapters/local/open_url.py +3 -2
  94. janito/tools/adapters/local/python_code_run.py +166 -166
  95. janito/tools/adapters/local/python_command_run.py +164 -164
  96. janito/tools/adapters/local/python_file_run.py +163 -163
  97. janito/tools/adapters/local/remove_directory.py +6 -17
  98. janito/tools/adapters/local/remove_file.py +9 -15
  99. janito/tools/adapters/local/replace_text_in_file.py +6 -9
  100. janito/tools/adapters/local/run_bash_command.py +176 -176
  101. janito/tools/adapters/local/run_powershell_command.py +219 -219
  102. janito/tools/adapters/local/search_text/__init__.py +1 -1
  103. janito/tools/adapters/local/search_text/core.py +201 -201
  104. janito/tools/adapters/local/search_text/match_lines.py +1 -1
  105. janito/tools/adapters/local/search_text/pattern_utils.py +73 -73
  106. janito/tools/adapters/local/search_text/traverse_directory.py +145 -145
  107. janito/tools/adapters/local/validate_file_syntax/__init__.py +1 -1
  108. janito/tools/adapters/local/validate_file_syntax/core.py +106 -106
  109. janito/tools/adapters/local/validate_file_syntax/css_validator.py +35 -35
  110. janito/tools/adapters/local/validate_file_syntax/html_validator.py +93 -93
  111. janito/tools/adapters/local/validate_file_syntax/js_validator.py +27 -27
  112. janito/tools/adapters/local/validate_file_syntax/json_validator.py +6 -6
  113. janito/tools/adapters/local/validate_file_syntax/markdown_validator.py +109 -109
  114. janito/tools/adapters/local/validate_file_syntax/ps1_validator.py +32 -32
  115. janito/tools/adapters/local/validate_file_syntax/python_validator.py +5 -5
  116. janito/tools/adapters/local/validate_file_syntax/xml_validator.py +11 -11
  117. janito/tools/adapters/local/validate_file_syntax/yaml_validator.py +6 -6
  118. janito/tools/adapters/local/view_file.py +167 -167
  119. janito/tools/inspect_registry.py +17 -17
  120. janito/tools/tool_base.py +105 -105
  121. janito/tools/tool_events.py +58 -58
  122. janito/tools/tool_run_exception.py +12 -12
  123. janito/tools/tool_use_tracker.py +81 -81
  124. janito/tools/tool_utils.py +45 -45
  125. janito/tools/tools_adapter.py +78 -6
  126. janito/tools/tools_schema.py +104 -104
  127. janito/version.py +4 -4
  128. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/METADATA +388 -232
  129. janito-2.3.0.dist-info/RECORD +181 -0
  130. janito-2.3.0.dist-info/licenses/LICENSE +21 -0
  131. janito/cli/chat_mode/shell/commands/last.py +0 -137
  132. janito/drivers/google_genai/driver.py +0 -54
  133. janito/drivers/google_genai/schema_generator.py +0 -67
  134. janito-2.1.1.dist-info/RECORD +0 -181
  135. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/WHEEL +0 -0
  136. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/entry_points.txt +0 -0
  137. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/top_level.txt +0 -0
janito/llm/auth.py CHANGED
@@ -35,6 +35,7 @@ class LLMAuthManager:
35
35
  os.makedirs(os.path.dirname(self._auth_file), exist_ok=True)
36
36
  with open(self._auth_file, "w") as f:
37
37
  json.dump(self._credentials, f, indent=2)
38
+ f.write("\n")
38
39
 
39
40
  def set_credentials(self, provider_name: str, credentials: str) -> None:
40
41
  """
janito/llm/driver.py CHANGED
@@ -122,11 +122,17 @@ class LLMDriver(ABC):
122
122
  if not self.available:
123
123
  self.handle_driver_unavailable(request_id)
124
124
  return
125
+ # Prepare payload for RequestStarted event
126
+ payload = {"provider_name": self.provider_name}
127
+ if hasattr(config, "model") and getattr(config, "model", None):
128
+ payload["model"] = getattr(config, "model")
129
+ elif hasattr(config, "model_name") and getattr(config, "model_name", None):
130
+ payload["model"] = getattr(config, "model_name")
125
131
  self.output_queue.put(
126
132
  RequestStarted(
127
133
  driver_name=self.__class__.__name__,
128
134
  request_id=request_id,
129
- payload={"provider_name": self.provider_name},
135
+ payload=payload,
130
136
  )
131
137
  )
132
138
  # Check for cancel_event before starting
@@ -23,6 +23,7 @@ class LLMDriverConfig:
23
23
  presence_penalty: Optional[float] = None
24
24
  frequency_penalty: Optional[float] = None
25
25
  stop: Optional[Any] = None # list or string, depending on backend
26
+ reasoning_effort: Optional[str] = None
26
27
  extra: dict = field(
27
28
  default_factory=dict
28
29
  ) # for provider-specific miscellaneous config fields
@@ -1,34 +1,34 @@
1
- from typing import Type, Dict, Any
2
- from janito.llm.driver_config import LLMDriverConfig
3
-
4
-
5
- def build_llm_driver_config(
6
- config: Dict[str, Any], driver_class: Type
7
- ) -> LLMDriverConfig:
8
- """
9
- Build an LLMDriverConfig instance for the given driver class based on its declared driver_fields.
10
- Only fills fields missing from given config; does not overwrite fields already provided.
11
- Any config fields not in driver_fields or LLMDriverConfig fields go into .extra.
12
- """
13
- driver_fields = getattr(driver_class, "driver_fields", None)
14
- if driver_fields is None:
15
- driver_fields = set(LLMDriverConfig.__dataclass_fields__.keys()) - {
16
- "model",
17
- "extra",
18
- }
19
- base_info = {}
20
- extra = {}
21
- for k, v in (config or {}).items():
22
- if k in driver_fields and k in LLMDriverConfig.__dataclass_fields__:
23
- base_info[k] = v
24
- else:
25
- extra[k] = v
26
- # Only set missing fields, do NOT overwrite those from CLI/user
27
- for field in driver_fields:
28
- if field not in base_info and field in LLMDriverConfig.__dataclass_fields__:
29
- base_info[field] = (
30
- None # Optional: replace None with provider/driver default if wanted
31
- )
32
- return LLMDriverConfig(
33
- model=config.get("model") or config.get("model_name"), extra=extra, **base_info
34
- )
1
+ from typing import Type, Dict, Any
2
+ from janito.llm.driver_config import LLMDriverConfig
3
+
4
+
5
+ def build_llm_driver_config(
6
+ config: Dict[str, Any], driver_class: Type
7
+ ) -> LLMDriverConfig:
8
+ """
9
+ Build an LLMDriverConfig instance for the given driver class based on its declared driver_fields.
10
+ Only fills fields missing from given config; does not overwrite fields already provided.
11
+ Any config fields not in driver_fields or LLMDriverConfig fields go into .extra.
12
+ """
13
+ driver_fields = getattr(driver_class, "driver_fields", None)
14
+ if driver_fields is None:
15
+ driver_fields = set(LLMDriverConfig.__dataclass_fields__.keys()) - {
16
+ "model",
17
+ "extra",
18
+ }
19
+ base_info = {}
20
+ extra = {}
21
+ for k, v in (config or {}).items():
22
+ if k in driver_fields and k in LLMDriverConfig.__dataclass_fields__:
23
+ base_info[k] = v
24
+ else:
25
+ extra[k] = v
26
+ # Only set missing fields, do NOT overwrite those from CLI/user
27
+ for field in driver_fields:
28
+ if field not in base_info and field in LLMDriverConfig.__dataclass_fields__:
29
+ base_info[field] = (
30
+ None # Optional: replace None with provider/driver default if wanted
31
+ )
32
+ return LLMDriverConfig(
33
+ model=config.get("model") or config.get("model_name"), extra=extra, **base_info
34
+ )
@@ -1,12 +1,12 @@
1
- from dataclasses import dataclass, field
2
- from typing import Optional
3
- import threading
4
- from janito.llm.driver_config import LLMDriverConfig
5
- from janito.conversation_history import LLMConversationHistory
6
-
7
-
8
- @dataclass
9
- class DriverInput:
10
- config: LLMDriverConfig
11
- conversation_history: LLMConversationHistory
12
- cancel_event: Optional[threading.Event] = field(default=None)
1
+ from dataclasses import dataclass, field
2
+ from typing import Optional
3
+ import threading
4
+ from janito.llm.driver_config import LLMDriverConfig
5
+ from janito.conversation_history import LLMConversationHistory
6
+
7
+
8
+ @dataclass
9
+ class DriverInput:
10
+ config: LLMDriverConfig
11
+ conversation_history: LLMConversationHistory
12
+ cancel_event: Optional[threading.Event] = field(default=None)
@@ -1,60 +1,60 @@
1
- import attr
2
-
3
-
4
- class MessagePart:
5
- """
6
- Base class for all driver message parts.
7
- """
8
-
9
- type: str
10
-
11
-
12
- @attr.s(auto_attribs=True, kw_only=True)
13
- class TextMessagePart(MessagePart):
14
- content: str = ""
15
-
16
-
17
- @attr.s(auto_attribs=True, kw_only=True)
18
- class InlineDataMessagePart(MessagePart):
19
- content: bytes = b""
20
-
21
-
22
- @attr.s(auto_attribs=True, kw_only=True)
23
- class FileDataMessagePart(MessagePart):
24
- content: str = ""
25
-
26
-
27
- @attr.s(auto_attribs=True, kw_only=True)
28
- class VideoMetadataMessagePart(MessagePart):
29
- content: dict = attr.Factory(dict)
30
-
31
-
32
- @attr.s(auto_attribs=True, kw_only=True)
33
- class CodeExecutionResultMessagePart(MessagePart):
34
- content: str = ""
35
- stdout: str = ""
36
- stderr: str = ""
37
-
38
-
39
- @attr.s(auto_attribs=True, kw_only=True)
40
- class ExecutableCodeMessagePart(MessagePart):
41
- content: str = ""
42
-
43
-
44
- @attr.s(auto_attribs=True, kw_only=True)
45
- class FunctionCallMessagePart(MessagePart):
46
- tool_call_id: str = ""
47
- function: object = (
48
- None # Should match OpenAI SDK structure (with arguments as JSON string)
49
- )
50
-
51
-
52
- @attr.s(auto_attribs=True, kw_only=True)
53
- class FunctionResponseMessagePart(MessagePart):
54
- name: str = ""
55
- content: dict = attr.Factory(dict)
56
-
57
-
58
- @attr.s(auto_attribs=True, kw_only=True)
59
- class ThoughtMessagePart(MessagePart):
60
- content: bool = False
1
+ import attr
2
+
3
+
4
+ class MessagePart:
5
+ """
6
+ Base class for all driver message parts.
7
+ """
8
+
9
+ type: str
10
+
11
+
12
+ @attr.s(auto_attribs=True, kw_only=True)
13
+ class TextMessagePart(MessagePart):
14
+ content: str = ""
15
+
16
+
17
+ @attr.s(auto_attribs=True, kw_only=True)
18
+ class InlineDataMessagePart(MessagePart):
19
+ content: bytes = b""
20
+
21
+
22
+ @attr.s(auto_attribs=True, kw_only=True)
23
+ class FileDataMessagePart(MessagePart):
24
+ content: str = ""
25
+
26
+
27
+ @attr.s(auto_attribs=True, kw_only=True)
28
+ class VideoMetadataMessagePart(MessagePart):
29
+ content: dict = attr.Factory(dict)
30
+
31
+
32
+ @attr.s(auto_attribs=True, kw_only=True)
33
+ class CodeExecutionResultMessagePart(MessagePart):
34
+ content: str = ""
35
+ stdout: str = ""
36
+ stderr: str = ""
37
+
38
+
39
+ @attr.s(auto_attribs=True, kw_only=True)
40
+ class ExecutableCodeMessagePart(MessagePart):
41
+ content: str = ""
42
+
43
+
44
+ @attr.s(auto_attribs=True, kw_only=True)
45
+ class FunctionCallMessagePart(MessagePart):
46
+ tool_call_id: str = ""
47
+ function: object = (
48
+ None # Should match OpenAI SDK structure (with arguments as JSON string)
49
+ )
50
+
51
+
52
+ @attr.s(auto_attribs=True, kw_only=True)
53
+ class FunctionResponseMessagePart(MessagePart):
54
+ name: str = ""
55
+ content: dict = attr.Factory(dict)
56
+
57
+
58
+ @attr.s(auto_attribs=True, kw_only=True)
59
+ class ThoughtMessagePart(MessagePart):
60
+ content: bool = False
janito/llm/model.py CHANGED
@@ -1,38 +1,38 @@
1
- from dataclasses import dataclass, field
2
- from typing import Any, Optional
3
-
4
-
5
- @dataclass
6
- class LLMModelInfo:
7
- name: str
8
- context: Any = "N/A"
9
- max_input: Any = "N/A"
10
- max_cot: Any = "N/A"
11
- max_response: Any = "N/A"
12
- thinking_supported: Any = "N/A"
13
- default_temp: float = 0.2
14
- open: Optional[Any] = None
15
- category: Optional[str] = None
16
- driver: Optional[str] = None
17
- # This enables arbitrary provider-specific metadata
18
- other: dict = field(default_factory=dict)
19
-
20
- def to_dict(self) -> dict:
21
- d = self.__dict__.copy()
22
- if not self.open:
23
- d.pop("open")
24
- if not self.category:
25
- d.pop("category")
26
- if not self.driver:
27
- d.pop("driver")
28
- if not self.other:
29
- d.pop("other")
30
- return d
31
-
32
- @staticmethod
33
- def get_model_info(model_specs):
34
- """
35
- Standard get_model_info implementation for all providers:
36
- returns a list of model info dicts, one per model in the given MODEL_SPECS dict.
37
- """
38
- return [m.to_dict() for m in model_specs.values()]
1
+ from dataclasses import dataclass, field
2
+ from typing import Any, Optional
3
+
4
+
5
+ @dataclass
6
+ class LLMModelInfo:
7
+ name: str
8
+ context: Any = "N/A"
9
+ max_input: Any = "N/A"
10
+ max_cot: Any = "N/A"
11
+ max_response: Any = "N/A"
12
+ thinking_supported: Any = "N/A"
13
+ default_temp: float = 0.2
14
+ open: Optional[Any] = None
15
+ category: Optional[str] = None
16
+ driver: Optional[str] = None
17
+ # This enables arbitrary provider-specific metadata
18
+ other: dict = field(default_factory=dict)
19
+
20
+ def to_dict(self) -> dict:
21
+ d = self.__dict__.copy()
22
+ if not self.open:
23
+ d.pop("open")
24
+ if not self.category:
25
+ d.pop("category")
26
+ if not self.driver:
27
+ d.pop("driver")
28
+ if not self.other:
29
+ d.pop("other")
30
+ return d
31
+
32
+ @staticmethod
33
+ def get_model_info(model_specs):
34
+ """
35
+ Standard get_model_info implementation for all providers:
36
+ returns a list of model info dicts, one per model in the given MODEL_SPECS dict.
37
+ """
38
+ return [m.to_dict() for m in model_specs.values()]