janito 1.9.0__py3-none-any.whl → 1.10.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.
- janito/__init__.py +1 -1
- janito/agent/api_exceptions.py +4 -0
- janito/agent/config.py +1 -1
- janito/agent/config_defaults.py +2 -26
- janito/agent/conversation.py +163 -122
- janito/agent/conversation_api.py +149 -159
- janito/agent/{conversation_history.py → llm_conversation_history.py} +18 -1
- janito/agent/openai_client.py +38 -23
- janito/agent/openai_schema_generator.py +162 -129
- janito/agent/platform_discovery.py +134 -77
- janito/agent/profile_manager.py +5 -5
- janito/agent/rich_message_handler.py +80 -31
- janito/agent/templates/profiles/system_prompt_template_base.txt.j2 +5 -4
- janito/agent/test_openai_schema_generator.py +93 -0
- janito/agent/tool_base.py +7 -2
- janito/agent/tool_executor.py +54 -49
- janito/agent/tool_registry.py +5 -2
- janito/agent/tool_use_tracker.py +26 -5
- janito/agent/tools/__init__.py +6 -3
- janito/agent/tools/create_directory.py +3 -1
- janito/agent/tools/create_file.py +7 -1
- janito/agent/tools/fetch_url.py +40 -3
- janito/agent/tools/find_files.py +3 -1
- janito/agent/tools/get_file_outline/core.py +6 -7
- janito/agent/tools/get_file_outline/search_outline.py +3 -1
- janito/agent/tools/get_lines.py +7 -2
- janito/agent/tools/move_file.py +3 -1
- janito/agent/tools/present_choices.py +3 -1
- janito/agent/tools/python_command_runner.py +150 -0
- janito/agent/tools/python_file_runner.py +148 -0
- janito/agent/tools/python_stdin_runner.py +154 -0
- janito/agent/tools/remove_directory.py +3 -1
- janito/agent/tools/remove_file.py +5 -1
- janito/agent/tools/replace_file.py +12 -2
- janito/agent/tools/replace_text_in_file.py +4 -2
- janito/agent/tools/run_bash_command.py +30 -69
- janito/agent/tools/run_powershell_command.py +134 -105
- janito/agent/tools/search_text.py +172 -122
- janito/agent/tools/validate_file_syntax/core.py +3 -1
- janito/agent/tools_utils/action_type.py +7 -0
- janito/agent/tools_utils/dir_walk_utils.py +3 -2
- janito/agent/tools_utils/formatting.py +47 -21
- janito/agent/tools_utils/gitignore_utils.py +66 -40
- janito/agent/tools_utils/test_gitignore_utils.py +46 -0
- janito/cli/_print_config.py +63 -61
- janito/cli/arg_parser.py +13 -12
- janito/cli/cli_main.py +137 -147
- janito/cli/main.py +152 -174
- janito/cli/one_shot.py +40 -26
- janito/i18n/__init__.py +1 -1
- janito/rich_utils.py +46 -8
- janito/shell/commands/__init__.py +2 -4
- janito/shell/commands/conversation_restart.py +3 -1
- janito/shell/commands/edit.py +3 -0
- janito/shell/commands/history_view.py +3 -3
- janito/shell/commands/lang.py +3 -0
- janito/shell/commands/livelogs.py +5 -3
- janito/shell/commands/prompt.py +6 -0
- janito/shell/commands/session.py +3 -0
- janito/shell/commands/session_control.py +3 -0
- janito/shell/commands/termweb_log.py +8 -0
- janito/shell/commands/tools.py +3 -0
- janito/shell/commands/track.py +36 -0
- janito/shell/commands/utility.py +13 -18
- janito/shell/commands/verbose.py +3 -4
- janito/shell/input_history.py +62 -0
- janito/shell/main.py +117 -181
- janito/shell/session/manager.py +0 -21
- janito/shell/ui/interactive.py +0 -2
- janito/termweb/static/editor.css +0 -4
- janito/tests/test_rich_utils.py +44 -0
- janito/web/app.py +0 -75
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/METADATA +61 -42
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/RECORD +78 -71
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/WHEEL +1 -1
- janito/agent/providers.py +0 -77
- janito/agent/tools/run_python_command.py +0 -161
- janito/shell/commands/sum.py +0 -49
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/entry_points.txt +0 -0
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/licenses/LICENSE +0 -0
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,9 @@
|
|
1
1
|
"""
|
2
|
-
|
3
|
-
|
4
|
-
-
|
5
|
-
-
|
2
|
+
Generates OpenAI-compatible function schemas from Python callables and class docstrings.
|
3
|
+
|
4
|
+
- Ensures all parameters are documented and type-annotated.
|
5
|
+
- Integrates return documentation into the schema description.
|
6
|
+
- Supports Google, NumPy, and relaxed docstring formats.
|
6
7
|
"""
|
7
8
|
|
8
9
|
import inspect
|
@@ -20,135 +21,167 @@ PYTHON_TYPE_TO_JSON = {
|
|
20
21
|
}
|
21
22
|
|
22
23
|
|
23
|
-
|
24
|
-
if hasattr(annotation, "__origin__"):
|
25
|
-
if annotation.__origin__ is list or annotation.__origin__ is typing.List:
|
26
|
-
return {
|
27
|
-
"type": "array",
|
28
|
-
"items": _type_to_json_schema(annotation.__args__[0]),
|
29
|
-
}
|
30
|
-
if annotation.__origin__ is dict or annotation.__origin__ is typing.Dict:
|
31
|
-
return {"type": "object"}
|
32
|
-
return {"type": PYTHON_TYPE_TO_JSON.get(annotation, "string")}
|
33
|
-
|
34
|
-
|
35
|
-
def _parse_docstring(docstring: str):
|
24
|
+
class OpenAISchemaGenerator:
|
36
25
|
"""
|
37
|
-
|
38
|
-
|
39
|
-
|
26
|
+
Generates OpenAI-compatible function schemas from Python callables and class docstrings.
|
27
|
+
|
28
|
+
- Ensures all parameters are documented and type-annotated.
|
29
|
+
- Integrates return documentation into the schema description.
|
30
|
+
- Supports Google, NumPy, and relaxed docstring formats.
|
40
31
|
"""
|
41
|
-
if not docstring:
|
42
|
-
return "", {}, ""
|
43
|
-
lines = docstring.strip().split("\n")
|
44
|
-
summary = lines[0].strip()
|
45
|
-
param_descs = {}
|
46
|
-
return_desc = ""
|
47
|
-
in_params = False
|
48
|
-
in_returns = False
|
49
|
-
param_section_headers = ("args", "arguments", "params", "parameters")
|
50
|
-
for line in lines[1:]:
|
51
|
-
stripped_line = line.strip()
|
52
|
-
if any(
|
53
|
-
stripped_line.lower().startswith(h + ":") or stripped_line.lower() == h
|
54
|
-
for h in param_section_headers
|
55
|
-
):
|
56
|
-
in_params = True
|
57
|
-
in_returns = False
|
58
|
-
continue
|
59
|
-
if (
|
60
|
-
stripped_line.lower().startswith("returns:")
|
61
|
-
or stripped_line.lower() == "returns"
|
62
|
-
):
|
63
|
-
in_returns = True
|
64
|
-
in_params = False
|
65
|
-
continue
|
66
|
-
if in_params:
|
67
|
-
# Accept: name: desc, name (type): desc, name - desc, name desc
|
68
|
-
m = re.match(
|
69
|
-
r"([a-zA-Z_][a-zA-Z0-9_]*)\s*(?:\(([^)]+)\))?\s*[:\-]?\s*(.+)",
|
70
|
-
stripped_line,
|
71
|
-
)
|
72
|
-
if m:
|
73
|
-
param, _, desc = m.groups()
|
74
|
-
param_descs[param] = desc.strip()
|
75
|
-
elif stripped_line and stripped_line[0] != "-":
|
76
|
-
# Continuation of previous param
|
77
|
-
if param_descs:
|
78
|
-
last = list(param_descs)[-1]
|
79
|
-
param_descs[last] += " " + stripped_line
|
80
|
-
elif in_returns:
|
81
|
-
if stripped_line:
|
82
|
-
return_desc += (" " if return_desc else "") + stripped_line
|
83
|
-
return summary, param_descs, return_desc
|
84
32
|
|
33
|
+
def __init__(self):
|
34
|
+
pass
|
85
35
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
for
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
36
|
+
def type_to_json_schema(self, annotation):
|
37
|
+
if hasattr(annotation, "__origin__"):
|
38
|
+
if annotation.__origin__ is list or annotation.__origin__ is typing.List:
|
39
|
+
return {
|
40
|
+
"type": "array",
|
41
|
+
"items": self.type_to_json_schema(annotation.__args__[0]),
|
42
|
+
}
|
43
|
+
if annotation.__origin__ is dict or annotation.__origin__ is typing.Dict:
|
44
|
+
return {"type": "object"}
|
45
|
+
return {"type": PYTHON_TYPE_TO_JSON.get(annotation, "string")}
|
46
|
+
|
47
|
+
def parse_param_section(self, lines, param_section_headers):
|
48
|
+
param_descs = {}
|
49
|
+
in_params = False
|
50
|
+
for line in lines:
|
51
|
+
stripped_line = line.strip()
|
52
|
+
if any(
|
53
|
+
stripped_line.lower().startswith(h + ":") or stripped_line.lower() == h
|
54
|
+
for h in param_section_headers
|
55
|
+
):
|
56
|
+
in_params = True
|
57
|
+
continue
|
58
|
+
if in_params:
|
59
|
+
m = re.match(
|
60
|
+
r"([a-zA-Z_][a-zA-Z0-9_]*)\s*(?:\(([^)]+)\))?\s*[:\-]?\s*(.+)",
|
61
|
+
stripped_line,
|
62
|
+
)
|
63
|
+
if m:
|
64
|
+
param, _, desc = m.groups()
|
65
|
+
param_descs[param] = desc.strip()
|
66
|
+
elif stripped_line and stripped_line[0] != "-":
|
67
|
+
if param_descs:
|
68
|
+
last = list(param_descs)[-1]
|
69
|
+
param_descs[last] += " " + stripped_line
|
70
|
+
if (
|
71
|
+
stripped_line.lower().startswith("returns:")
|
72
|
+
or stripped_line.lower() == "returns"
|
73
|
+
):
|
74
|
+
break
|
75
|
+
return param_descs
|
76
|
+
|
77
|
+
def parse_return_section(self, lines):
|
78
|
+
in_returns = False
|
79
|
+
return_desc = ""
|
80
|
+
for line in lines:
|
81
|
+
stripped_line = line.strip()
|
82
|
+
if (
|
83
|
+
stripped_line.lower().startswith("returns:")
|
84
|
+
or stripped_line.lower() == "returns"
|
85
|
+
):
|
86
|
+
in_returns = True
|
87
|
+
continue
|
88
|
+
if in_returns:
|
89
|
+
if stripped_line:
|
90
|
+
return_desc += (" " if return_desc else "") + stripped_line
|
91
|
+
return return_desc
|
92
|
+
|
93
|
+
def parse_docstring(self, docstring: str):
|
94
|
+
"""
|
95
|
+
Parses a docstring to extract summary, parameter descriptions, and return description.
|
96
|
+
Accepts Google, NumPy, and relaxed formats.
|
97
|
+
Returns: summary, {param: description}, return_description
|
98
|
+
"""
|
99
|
+
if not docstring:
|
100
|
+
return "", {}, ""
|
101
|
+
lines = docstring.strip().split("\n")
|
102
|
+
summary = lines[0].strip()
|
103
|
+
param_section_headers = ("args", "arguments", "params", "parameters")
|
104
|
+
param_descs = self.parse_param_section(lines[1:], param_section_headers)
|
105
|
+
return_desc = self.parse_return_section(lines[1:])
|
106
|
+
return summary, param_descs, return_desc
|
107
|
+
|
108
|
+
def generate_schema(self, tool_class):
|
109
|
+
"""
|
110
|
+
Generates an OpenAI-compatible function schema for a tool class.
|
111
|
+
The tool class must have _tool_run_method and _tool_name attributes set by the tool registration decorator.
|
112
|
+
Raises ValueError if the return type is not explicitly str or if any parameter is missing a type hint.
|
113
|
+
"""
|
114
|
+
if not hasattr(tool_class, "_tool_run_method") or not hasattr(
|
115
|
+
tool_class, "_tool_name"
|
116
|
+
):
|
117
|
+
raise ValueError(
|
118
|
+
"Tool class must have _tool_run_method and _tool_name attributes (set by @register_tool)."
|
119
|
+
)
|
120
|
+
func = tool_class._tool_run_method
|
121
|
+
tool_name = tool_class._tool_name
|
122
|
+
sig = inspect.signature(func)
|
123
|
+
# Enforce explicit str return type
|
124
|
+
if sig.return_annotation is inspect._empty or sig.return_annotation is not str:
|
125
|
+
raise ValueError(
|
126
|
+
f"Tool '{tool_name}' must have an explicit return type of 'str'. Found: {sig.return_annotation}"
|
127
|
+
)
|
128
|
+
# Enforce type hints for all parameters (except self)
|
129
|
+
missing_type_hints = [
|
130
|
+
name
|
131
|
+
for name, param in sig.parameters.items()
|
132
|
+
if name != "self" and param.annotation is inspect._empty
|
133
|
+
]
|
134
|
+
if missing_type_hints:
|
135
|
+
raise ValueError(
|
136
|
+
f"Tool '{tool_name}' is missing type hints for parameter(s): {', '.join(missing_type_hints)}.\n"
|
137
|
+
f"All parameters must have explicit type hints for schema generation."
|
138
|
+
)
|
139
|
+
# Only use the class docstring for schema generation
|
140
|
+
class_doc = (
|
141
|
+
tool_class.__doc__.strip() if tool_class and tool_class.__doc__ else ""
|
124
142
|
)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
143
|
+
summary, param_descs, return_desc = self.parse_docstring(class_doc)
|
144
|
+
description = summary
|
145
|
+
if return_desc:
|
146
|
+
description += f"\n\nReturns: {return_desc}"
|
147
|
+
# Check that all parameters in the signature have documentation
|
148
|
+
undocumented = [
|
149
|
+
name
|
150
|
+
for name, param in sig.parameters.items()
|
151
|
+
if name != "self" and name not in param_descs
|
152
|
+
]
|
153
|
+
if undocumented:
|
154
|
+
raise ValueError(
|
155
|
+
f"Tool '{tool_name}' is missing docstring documentation for parameter(s): {', '.join(undocumented)}.\n"
|
156
|
+
f"Parameter documentation must be provided in the Tool class docstring, not the method docstring."
|
157
|
+
)
|
158
|
+
properties = OrderedDict()
|
159
|
+
required = []
|
160
|
+
# Inject tool_call_reason as the first required parameter, unless --ntt is set
|
161
|
+
from janito.agent.runtime_config import runtime_config
|
129
162
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
163
|
+
if not runtime_config.get("no_tools_tracking", False):
|
164
|
+
properties["tool_call_reason"] = {
|
165
|
+
"type": "string",
|
166
|
+
"description": "The reason or context for why this tool is being called. This is required for traceability.",
|
167
|
+
}
|
168
|
+
required.append("tool_call_reason")
|
169
|
+
for name, param in sig.parameters.items():
|
170
|
+
if name == "self":
|
171
|
+
continue
|
172
|
+
annotation = param.annotation
|
173
|
+
pdesc = param_descs.get(name, "")
|
174
|
+
schema = self.type_to_json_schema(annotation)
|
175
|
+
schema["description"] = pdesc
|
176
|
+
properties[name] = schema
|
177
|
+
if param.default == inspect._empty:
|
178
|
+
required.append(name)
|
179
|
+
return {
|
180
|
+
"name": tool_name,
|
181
|
+
"description": description,
|
182
|
+
"parameters": {
|
183
|
+
"type": "object",
|
184
|
+
"properties": properties,
|
185
|
+
"required": required,
|
186
|
+
},
|
134
187
|
}
|
135
|
-
required.append("tool_call_reason")
|
136
|
-
for name, param in sig.parameters.items():
|
137
|
-
if name == "self":
|
138
|
-
continue
|
139
|
-
annotation = param.annotation
|
140
|
-
pdesc = param_descs.get(name, "")
|
141
|
-
schema = _type_to_json_schema(annotation)
|
142
|
-
schema["description"] = pdesc
|
143
|
-
properties[name] = schema
|
144
|
-
if param.default == inspect._empty:
|
145
|
-
required.append(name)
|
146
|
-
return {
|
147
|
-
"name": tool_name,
|
148
|
-
"description": description,
|
149
|
-
"parameters": {
|
150
|
-
"type": "object",
|
151
|
-
"properties": properties,
|
152
|
-
"required": required,
|
153
|
-
},
|
154
|
-
}
|
@@ -1,90 +1,147 @@
|
|
1
|
+
import os
|
1
2
|
import platform
|
3
|
+
import subprocess
|
2
4
|
import sys
|
3
5
|
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
7
|
+
class PlatformDiscovery:
|
8
|
+
"""
|
9
|
+
Provides utilities for detecting the current shell, platform, and Python version.
|
10
|
+
Uses the system's environment and subprocess modules internally.
|
11
|
+
"""
|
12
|
+
|
13
|
+
def __init__(self):
|
14
|
+
"""
|
15
|
+
Initialize the PlatformDiscovery instance.
|
16
|
+
Uses os.environ and subprocess by default.
|
17
|
+
"""
|
18
|
+
self.os_environ = os.environ
|
19
|
+
self.subprocess_mod = subprocess
|
20
|
+
|
21
|
+
def _detect_git_bash(self):
|
22
|
+
if self.os_environ.get("MSYSTEM"):
|
23
|
+
return f"Git Bash ({self.os_environ.get('MSYSTEM')})"
|
24
|
+
return None
|
25
|
+
|
26
|
+
def _detect_wsl(self):
|
27
|
+
if self.os_environ.get("WSL_DISTRO_NAME"):
|
28
|
+
shell = self.os_environ.get("SHELL")
|
29
|
+
shell_name = shell.split("/")[-1] if shell else "unknown"
|
30
|
+
distro = self.os_environ.get("WSL_DISTRO_NAME")
|
31
|
+
return f"{shell_name} (WSL: {distro})"
|
32
|
+
return None
|
33
|
+
|
34
|
+
def _detect_powershell(self):
|
22
35
|
try:
|
23
|
-
result =
|
36
|
+
result = self.subprocess_mod.run(
|
24
37
|
["powershell.exe", "-NoProfile", "-Command", "$host.Name"],
|
25
38
|
capture_output=True,
|
26
39
|
text=True,
|
27
40
|
timeout=2,
|
28
41
|
)
|
29
42
|
if result.returncode == 0 and "ConsoleHost" in result.stdout:
|
30
|
-
|
31
|
-
else:
|
32
|
-
shell_info = None
|
43
|
+
return "PowerShell"
|
33
44
|
except Exception:
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
45
|
+
pass
|
46
|
+
return None
|
47
|
+
|
48
|
+
def _detect_shell_env(self):
|
49
|
+
shell = self.os_environ.get("SHELL")
|
50
|
+
if shell:
|
51
|
+
return shell
|
52
|
+
return None
|
53
|
+
|
54
|
+
def _detect_comspec(self):
|
55
|
+
comspec = self.os_environ.get("COMSPEC")
|
56
|
+
if comspec:
|
57
|
+
if "powershell" in comspec.lower():
|
58
|
+
return "PowerShell"
|
59
|
+
elif "cmd" in comspec.lower():
|
60
|
+
return "cmd.exe"
|
41
61
|
else:
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
62
|
+
return "Unknown shell"
|
63
|
+
return "Unknown shell"
|
64
|
+
|
65
|
+
def _append_term_info(self, shell_info):
|
66
|
+
term_env = self.os_environ.get("TERM")
|
67
|
+
if term_env:
|
68
|
+
shell_info += f" [TERM={term_env}]"
|
69
|
+
term_program = self.os_environ.get("TERM_PROGRAM")
|
70
|
+
if term_program:
|
71
|
+
shell_info += f" [TERM_PROGRAM={term_program}]"
|
72
|
+
return shell_info
|
73
|
+
|
74
|
+
def detect_shell(self) -> str:
|
75
|
+
"""
|
76
|
+
Detects the current shell environment and returns a descriptive string,
|
77
|
+
including terminal information if available.
|
78
|
+
|
79
|
+
Note:
|
80
|
+
This method may invoke subprocesses to execute shell commands
|
81
|
+
(e.g., to detect PowerShell), which could have side effects or
|
82
|
+
performance implications.
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
str: Description of the detected shell and terminal info.
|
86
|
+
"""
|
87
|
+
shell_info = (
|
88
|
+
self._detect_git_bash()
|
89
|
+
or self._detect_wsl()
|
90
|
+
or self._detect_powershell()
|
91
|
+
or self._detect_shell_env()
|
92
|
+
or self._detect_comspec()
|
93
|
+
)
|
94
|
+
shell_info = self._append_term_info(shell_info)
|
95
|
+
return shell_info
|
96
|
+
|
97
|
+
def get_platform_name(self) -> str:
|
98
|
+
"""
|
99
|
+
Returns the normalized platform name.
|
100
|
+
|
101
|
+
Returns:
|
102
|
+
str: One of 'windows', 'linux', 'darwin', or the raw platform string.
|
103
|
+
"""
|
104
|
+
sys_platform = platform.system().lower()
|
105
|
+
if sys_platform.startswith("win"):
|
106
|
+
return "windows"
|
107
|
+
elif sys_platform.startswith("linux"):
|
108
|
+
return "linux"
|
109
|
+
elif sys_platform.startswith("darwin"):
|
110
|
+
return "darwin"
|
111
|
+
return sys_platform
|
112
|
+
|
113
|
+
def get_python_version(self) -> str:
|
114
|
+
"""
|
115
|
+
Returns the current Python version as a string.
|
116
|
+
|
117
|
+
Returns:
|
118
|
+
str: Python version (e.g., '3.12.0').
|
119
|
+
"""
|
120
|
+
return platform.python_version()
|
121
|
+
|
122
|
+
def is_windows(self) -> bool:
|
123
|
+
"""
|
124
|
+
Checks if the current platform is Windows.
|
125
|
+
|
126
|
+
Returns:
|
127
|
+
bool: True if running on Windows, False otherwise.
|
128
|
+
"""
|
129
|
+
return sys.platform.startswith("win")
|
130
|
+
|
131
|
+
def is_linux(self) -> bool:
|
132
|
+
"""
|
133
|
+
Checks if the current platform is Linux.
|
134
|
+
|
135
|
+
Returns:
|
136
|
+
bool: True if running on Linux, False otherwise.
|
137
|
+
"""
|
138
|
+
return sys.platform.startswith("linux")
|
139
|
+
|
140
|
+
def is_mac(self) -> bool:
|
141
|
+
"""
|
142
|
+
Checks if the current platform is macOS.
|
143
|
+
|
144
|
+
Returns:
|
145
|
+
bool: True if running on macOS, False otherwise.
|
146
|
+
"""
|
147
|
+
return sys.platform.startswith("darwin")
|
janito/agent/profile_manager.py
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
from openai import OpenAI
|
2
2
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
3
3
|
from pathlib import Path
|
4
|
-
from janito.agent.platform_discovery import
|
5
|
-
from janito.agent.platform_discovery import detect_shell
|
4
|
+
from janito.agent.platform_discovery import PlatformDiscovery
|
6
5
|
|
7
6
|
|
8
7
|
class AgentProfileManager:
|
@@ -21,9 +20,10 @@ class AgentProfileManager:
|
|
21
20
|
main_template_name = "system_prompt_template_base_pt.txt.j2"
|
22
21
|
else:
|
23
22
|
main_template_name = "system_prompt_template_base.txt.j2"
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
pd = PlatformDiscovery()
|
24
|
+
platform_name = pd.get_platform_name()
|
25
|
+
python_version = pd.get_python_version()
|
26
|
+
shell_info = pd.detect_shell()
|
27
27
|
|
28
28
|
context = {
|
29
29
|
"role": self.role,
|