janito 1.6.0__py3-none-any.whl → 1.7.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 (43) hide show
  1. janito/__init__.py +1 -1
  2. janito/agent/config.py +2 -2
  3. janito/agent/config_defaults.py +1 -0
  4. janito/agent/conversation.py +4 -1
  5. janito/agent/openai_client.py +2 -0
  6. janito/agent/platform_discovery.py +90 -0
  7. janito/agent/profile_manager.py +83 -91
  8. janito/agent/rich_message_handler.py +72 -64
  9. janito/agent/templates/profiles/system_prompt_template_base.toml +76 -0
  10. janito/agent/templates/profiles/system_prompt_template_default.toml +3 -0
  11. janito/agent/templates/profiles/system_prompt_template_technical.toml +13 -0
  12. janito/agent/tests/test_prompt_toml.py +61 -0
  13. janito/agent/tools/__init__.py +4 -0
  14. janito/agent/tools/ask_user.py +8 -2
  15. janito/agent/tools/create_directory.py +27 -10
  16. janito/agent/tools/find_files.py +2 -10
  17. janito/agent/tools/get_file_outline.py +29 -0
  18. janito/agent/tools/get_lines.py +9 -10
  19. janito/agent/tools/memory.py +68 -0
  20. janito/agent/tools/run_bash_command.py +79 -60
  21. janito/agent/tools/run_powershell_command.py +153 -0
  22. janito/agent/tools/run_python_command.py +4 -0
  23. janito/agent/tools/search_files.py +0 -6
  24. janito/cli/_print_config.py +1 -1
  25. janito/cli/config_commands.py +1 -1
  26. janito/cli/main.py +1 -1
  27. janito/cli/runner/__init__.py +0 -2
  28. janito/cli/runner/cli_main.py +3 -13
  29. janito/cli/runner/config.py +4 -2
  30. janito/cli/runner/scan.py +22 -9
  31. janito/cli_chat_shell/chat_loop.py +13 -9
  32. janito/cli_chat_shell/chat_ui.py +2 -2
  33. janito/cli_chat_shell/commands/__init__.py +2 -0
  34. janito/cli_chat_shell/commands/sum.py +49 -0
  35. janito/cli_chat_shell/load_prompt.py +47 -8
  36. janito/cli_chat_shell/ui.py +8 -2
  37. janito/web/app.py +6 -9
  38. {janito-1.6.0.dist-info → janito-1.7.0.dist-info}/METADATA +17 -9
  39. {janito-1.6.0.dist-info → janito-1.7.0.dist-info}/RECORD +43 -35
  40. {janito-1.6.0.dist-info → janito-1.7.0.dist-info}/WHEEL +0 -0
  41. {janito-1.6.0.dist-info → janito-1.7.0.dist-info}/entry_points.txt +0 -0
  42. {janito-1.6.0.dist-info → janito-1.7.0.dist-info}/licenses/LICENSE +0 -0
  43. {janito-1.6.0.dist-info → janito-1.7.0.dist-info}/top_level.txt +0 -0
@@ -15,7 +15,6 @@ class SearchFilesTool(ToolBase):
15
15
  directories (list[str]): List of directories to search in.
16
16
  pattern (str): Plain text substring to search for in files. (Not a regular expression or glob pattern.)
17
17
  recursive (bool): Whether to search recursively in subdirectories. Defaults to True.
18
- max_depth (int, optional): Maximum directory depth to search (0 = only top-level). If None, unlimited. Defaults to None.
19
18
  Returns:
20
19
  str: Matching lines from files as a newline-separated string, each formatted as 'filepath:lineno: line'. Example:
21
20
  - "/path/to/file.py:10: def my_function():"
@@ -27,7 +26,6 @@ class SearchFilesTool(ToolBase):
27
26
  directories: list[str],
28
27
  pattern: str,
29
28
  recursive: bool = True,
30
- max_depth: int = None,
31
29
  ) -> str:
32
30
  if not pattern:
33
31
  self.report_warning(
@@ -49,12 +47,8 @@ class SearchFilesTool(ToolBase):
49
47
  )
50
48
  walker = [(directory, dirs, files)]
51
49
  for root, dirs, files in walker:
52
- # Calculate depth
53
50
  rel_path = os.path.relpath(root, directory)
54
51
  depth = 0 if rel_path == "." else rel_path.count(os.sep) + 1
55
- if max_depth is not None and depth > max_depth:
56
- dirs[:] = []
57
- continue
58
52
  if not recursive and depth > 0:
59
53
  break
60
54
  dirs, files = filter_ignored(root, dirs, files)
@@ -82,7 +82,7 @@ def print_full_config(
82
82
  Path(__file__).parent
83
83
  / "agent"
84
84
  / "templates"
85
- / "system_prompt_template.j2"
85
+ / "system_prompt_template_default.j2"
86
86
  )
87
87
  for key, value in default_items.items():
88
88
  if key == "system_prompt_template" and value is None:
@@ -175,7 +175,7 @@ def handle_config_commands(args):
175
175
  Path(__file__).parent
176
176
  / "agent"
177
177
  / "templates"
178
- / "system_prompt_template.j2"
178
+ / "system_prompt_template_default.j2"
179
179
  )
180
180
  print(
181
181
  f"{key} = (default template path: {home_shorten(str(template_path))})"
janito/cli/main.py CHANGED
@@ -3,7 +3,7 @@
3
3
  from janito.cli.arg_parser import create_parser
4
4
  from janito.cli.config_commands import handle_config_commands
5
5
  from janito.cli.logging_setup import setup_verbose_logging
6
- from janito.cli.runner import run_cli
6
+ from janito.cli.runner.cli_main import run_cli
7
7
 
8
8
  # Ensure all tools are registered at startup
9
9
  import janito.agent.tools # noqa: F401
@@ -1,2 +0,0 @@
1
- from .cli_main import run_cli
2
- from .formatting import format_tokens
@@ -1,11 +1,9 @@
1
1
  import sys
2
- import os
3
2
  from rich.console import Console
4
3
  from janito.agent.profile_manager import AgentProfileManager
5
4
  from janito.agent.runtime_config import unified_config, runtime_config
6
5
  from janito.agent.config import get_api_key
7
6
  from janito import __version__
8
- from .formatting import format_tokens
9
7
  from .scan import scan_project
10
8
  from .config import get_system_prompt_template
11
9
  from janito.agent.conversation_exceptions import (
@@ -14,6 +12,7 @@ from janito.agent.conversation_exceptions import (
14
12
  ProviderError,
15
13
  )
16
14
 
15
+
17
16
  def run_cli(args):
18
17
  if args.version:
19
18
  print(f"janito version {__version__}")
@@ -24,14 +23,6 @@ def run_cli(args):
24
23
  scan_project()
25
24
  sys.exit(0)
26
25
 
27
- # Check for .janito/tech.txt and print a tip if missing
28
- tech_txt_path = os.path.join(".janito", "tech.txt")
29
- if not os.path.exists(tech_txt_path):
30
- print("⚠️ No tech.txt found in .janito.")
31
- print(
32
- "💡 Tip: Run with --scan first to auto-detect project tech/skills and improve results."
33
- )
34
-
35
26
  role = args.role or unified_config.get("role", "software engineer")
36
27
 
37
28
  # Ensure runtime_config is updated so chat shell sees the role
@@ -127,8 +118,8 @@ def run_cli(args):
127
118
  messages.append({"role": "user", "content": prompt})
128
119
  try:
129
120
  try:
130
- max_rounds = runtime_config.get("max_rounds", 50)
131
- profile_manager.agent.handle_conversation(
121
+ max_rounds = 50
122
+ profile_manager.agent.chat(
132
123
  messages,
133
124
  message_handler=message_handler,
134
125
  spinner=True,
@@ -136,7 +127,6 @@ def run_cli(args):
136
127
  verbose_response=getattr(args, "verbose_response", False),
137
128
  verbose_events=getattr(args, "verbose_events", False),
138
129
  stream=getattr(args, "stream", False),
139
- verbose_stream=getattr(args, "verbose_stream", False),
140
130
  )
141
131
  except MaxRoundsExceededError:
142
132
  console.print("[red]Max conversation rounds exceeded.[/red]")
@@ -1,8 +1,8 @@
1
- import os
2
1
  from janito.agent.profile_manager import AgentProfileManager
3
2
  from janito.agent.runtime_config import unified_config, runtime_config
4
3
  from janito.agent.config import get_api_key
5
4
 
5
+
6
6
  def get_system_prompt_template(args, role):
7
7
  system_prompt_template = None
8
8
  if getattr(args, "system_prompt_template_file", None):
@@ -26,7 +26,9 @@ def get_system_prompt_template(args, role):
26
26
  interaction_mode=unified_config.get("interaction_mode", "prompt"),
27
27
  verbose_tools=unified_config.get("verbose_tools", False),
28
28
  base_url=unified_config.get("base_url", None),
29
- azure_openai_api_version=unified_config.get("azure_openai_api_version", None),
29
+ azure_openai_api_version=unified_config.get(
30
+ "azure_openai_api_version", "2023-05-15"
31
+ ),
30
32
  use_azure_openai=unified_config.get("use_azure_openai", False),
31
33
  )
32
34
  system_prompt_template = profile_manager.render_prompt()
janito/cli/runner/scan.py CHANGED
@@ -1,30 +1,43 @@
1
1
  import os
2
- from janito.agent.openai_client import Agent
2
+ from janito.agent.profile_manager import AgentProfileManager
3
3
  from janito.agent.runtime_config import unified_config
4
4
  from janito.agent.config import get_api_key
5
5
 
6
+
6
7
  def scan_project():
7
- prompt_path = os.path.abspath(os.path.join(
8
- os.path.dirname(__file__),
9
- "..", "..", "agent", "templates", "detect_tech_prompt.j2"
10
- ))
8
+ prompt_path = os.path.abspath(
9
+ os.path.join(
10
+ os.path.dirname(__file__),
11
+ "..",
12
+ "..",
13
+ "agent",
14
+ "templates",
15
+ "detect_tech_prompt.j2",
16
+ )
17
+ )
11
18
  with open(prompt_path, "r", encoding="utf-8") as f:
12
19
  detect_prompt = f.read()
13
20
  api_key = get_api_key()
14
21
  model = unified_config.get("model")
15
22
  base_url = unified_config.get("base_url", "https://openrouter.ai/api/v1")
16
- azure_openai_api_version = unified_config.get("azure_openai_api_version", "2023-05-15")
23
+ azure_openai_api_version = unified_config.get(
24
+ "azure_openai_api_version", "2023-05-15"
25
+ )
17
26
  use_azure_openai = unified_config.get("use_azure_openai", False)
18
- agent = Agent(
27
+ profile_manager = AgentProfileManager(
19
28
  api_key=api_key,
20
29
  model=model,
21
- system_prompt_template=detect_prompt,
30
+ role=unified_config.get("role", "software engineer"),
31
+ interaction_style=unified_config.get("interaction_style", "default"),
32
+ interaction_mode=unified_config.get("interaction_mode", "prompt"),
22
33
  verbose_tools=True,
23
34
  base_url=base_url,
24
35
  azure_openai_api_version=azure_openai_api_version,
25
36
  use_azure_openai=use_azure_openai,
26
37
  )
38
+ agent = profile_manager.agent
27
39
  from janito.agent.rich_message_handler import RichMessageHandler
40
+
28
41
  message_handler = RichMessageHandler()
29
42
  messages = [{"role": "system", "content": detect_prompt}]
30
43
  print("🔍 Scanning project for relevant tech/skills...")
@@ -32,7 +45,7 @@ def scan_project():
32
45
  messages,
33
46
  message_handler=message_handler,
34
47
  spinner=True,
35
- max_rounds=10,
48
+ max_rounds=50,
36
49
  verbose_response=False,
37
50
  verbose_events=False,
38
51
  stream=False,
@@ -1,5 +1,5 @@
1
1
  from janito.agent.rich_message_handler import RichMessageHandler
2
- from .chat_state import load_chat_state, save_chat_state
2
+ from .chat_state import load_chat_state
3
3
  from .chat_ui import setup_prompt_session, print_welcome_message
4
4
  from .commands import handle_command
5
5
  from janito.agent.conversation_exceptions import EmptyResponseError, ProviderError
@@ -14,19 +14,23 @@ def start_chat_shell(profile_manager, continue_session=False, max_rounds=50):
14
14
  state = load_chat_state(continue_session)
15
15
  messages = state["messages"]
16
16
  mem_history = state["mem_history"]
17
- last_usage_info = state["last_usage_info"]
17
+ last_usage_info_ref = {"value": state["last_usage_info"]}
18
18
  last_elapsed = state["last_elapsed"]
19
19
 
20
- # Add system prompt if needed
21
- if profile_manager.system_prompt_template and not any(
22
- m.get("role") == "system" for m in messages
20
+ # Add system prompt if needed (skip in vanilla mode)
21
+ from janito.agent.runtime_config import runtime_config
22
+
23
+ if (
24
+ profile_manager.system_prompt_template
25
+ and not runtime_config.get("vanilla_mode", False)
26
+ and not any(m.get("role") == "system" for m in messages)
23
27
  ):
24
28
  messages.insert(0, {"role": "system", "content": agent.system_prompt_template})
25
29
 
26
30
  print_welcome_message(console, continued=continue_session)
27
31
 
28
32
  session = setup_prompt_session(
29
- messages, last_usage_info, last_elapsed, mem_history, profile_manager, agent
33
+ messages, last_usage_info_ref, last_elapsed, mem_history, profile_manager, agent
30
34
  )
31
35
 
32
36
  while True:
@@ -96,7 +100,7 @@ def start_chat_shell(profile_manager, continue_session=False, max_rounds=50):
96
100
  start_time = time.time()
97
101
 
98
102
  try:
99
- response = profile_manager.agent.handle_conversation(
103
+ response = profile_manager.agent.chat(
100
104
  messages,
101
105
  max_rounds=max_rounds,
102
106
  message_handler=message_handler,
@@ -118,7 +122,7 @@ def start_chat_shell(profile_manager, continue_session=False, max_rounds=50):
118
122
  last_elapsed = time.time() - start_time
119
123
 
120
124
  usage = response.get("usage")
121
- last_usage_info = usage
125
+ last_usage_info_ref["value"] = usage
122
126
 
123
127
  # Save conversation and input history
124
- save_chat_state(messages, mem_history, last_usage_info)
128
+ # save_chat_state(messages, mem_history, last_usage_info)
@@ -5,7 +5,7 @@ from janito.agent.runtime_config import runtime_config
5
5
 
6
6
 
7
7
  def setup_prompt_session(
8
- messages, last_usage_info, last_elapsed, mem_history, profile_manager, agent
8
+ messages, last_usage_info_ref, last_elapsed, mem_history, profile_manager, agent
9
9
  ):
10
10
  model_name = getattr(agent, "model", None)
11
11
 
@@ -13,7 +13,7 @@ def setup_prompt_session(
13
13
  return messages
14
14
 
15
15
  def get_usage():
16
- return last_usage_info
16
+ return last_usage_info_ref["value"]
17
17
 
18
18
  def get_elapsed():
19
19
  return last_elapsed
@@ -2,6 +2,7 @@ from .session import handle_continue, handle_history
2
2
  from .system import handle_system, handle_role, handle_style
3
3
  from .session_control import handle_exit, handle_restart
4
4
  from .utility import handle_help, handle_clear, handle_multi
5
+ from .sum import handle_sum
5
6
  from .config import handle_reload
6
7
  from .history_reset import handle_reset
7
8
  from ..config_shell import handle_config_shell
@@ -23,6 +24,7 @@ if not runtime_config.get("vanilla_mode", False):
23
24
 
24
25
  COMMAND_HANDLERS.update(
25
26
  {
27
+ "/sum": handle_sum,
26
28
  "/clear": handle_clear,
27
29
  "/reset": handle_reset,
28
30
  "/config": handle_config_shell,
@@ -0,0 +1,49 @@
1
+ def handle_sum(console, state, **kwargs):
2
+ """
3
+ Summarize the current chat history and replace it with a summary message.
4
+ """
5
+ agent = kwargs.get("agent")
6
+ if agent is None:
7
+ console.print("[bold red]Agent not provided to /sum command.[/bold red]")
8
+ return
9
+
10
+ messages = state.get("messages", [])
11
+ if not messages or len(messages) < 2:
12
+ console.print(
13
+ "[bold yellow]Not enough conversation to summarize.[/bold yellow]"
14
+ )
15
+ return
16
+
17
+ # Find the system message if present
18
+ system_msg = next((m for m in messages if m.get("role") == "system"), None)
19
+
20
+ # Prepare summary prompt
21
+ summary_prompt = {
22
+ "role": "user",
23
+ "content": "Summarize the following conversation in a concise paragraph for context. Only output the summary, do not include any tool calls or formatting.",
24
+ }
25
+ # Exclude system messages for the summary context
26
+ convo_for_summary = [m for m in messages if m.get("role") != "system"]
27
+ summary_messages = [summary_prompt] + convo_for_summary
28
+
29
+ try:
30
+ summary_response = agent.chat(summary_messages, spinner=True, max_tokens=256)
31
+ summary_text = (
32
+ summary_response["content"]
33
+ if isinstance(summary_response, dict)
34
+ else str(summary_response)
35
+ )
36
+ except Exception as e:
37
+ console.print(f"[bold red]Error during summarization: {e}[/bold red]")
38
+ return
39
+
40
+ # Rebuild conversation history
41
+ new_history = []
42
+ if system_msg:
43
+ new_history.append(system_msg)
44
+ new_history.append({"role": "assistant", "content": summary_text})
45
+ state["messages"] = new_history
46
+
47
+ console.print(
48
+ "[bold green]Conversation summarized and history replaced with summary.[/bold green]"
49
+ )
@@ -1,18 +1,57 @@
1
1
  import os
2
+ import importlib.resources
2
3
 
3
4
 
4
5
  def load_prompt(filename=None):
5
6
  """
6
7
  Load the system prompt from a file. If filename is None, use the default prompt file.
7
8
  Returns the prompt string.
9
+ Tries source path first, then falls back to importlib.resources for installed packages.
8
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
+ )
9
17
  if filename is None:
10
- # Default prompt file path (can be customized)
11
- filename = os.path.join(
12
- os.path.dirname(__file__), "../agent/templates/system_prompt_template.j2"
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}"
13
57
  )
14
- filename = os.path.abspath(filename)
15
- if not os.path.exists(filename):
16
- raise FileNotFoundError(f"Prompt file not found: {filename}")
17
- with open(filename, "r", encoding="utf-8") as f:
18
- return f.read()
@@ -151,12 +151,18 @@ def get_prompt_session(get_toolbar_func, mem_history):
151
151
  )
152
152
  kb = KeyBindings()
153
153
 
154
+ # F12 instruction rotation
155
+ _f12_instructions = ["proceed", "go ahead", "continue", "next", "okay"]
156
+ _f12_index = {"value": 0}
157
+
154
158
  @kb.add("f12")
155
159
  def _(event):
156
- """When F12 is pressed, send 'proceed' as input immediately."""
160
+ """When F12 is pressed, rotate through a set of short instructions."""
157
161
  buf = event.app.current_buffer
158
- buf.text = "proceed"
162
+ idx = _f12_index["value"]
163
+ buf.text = _f12_instructions[idx]
159
164
  buf.validate_and_handle()
165
+ _f12_index["value"] = (idx + 1) % len(_f12_instructions)
160
166
 
161
167
  session = PromptSession(
162
168
  multiline=False,
janito/web/app.py CHANGED
@@ -9,7 +9,6 @@ from flask import (
9
9
  from queue import Queue
10
10
  import json
11
11
  from janito.agent.queued_message_handler import QueuedMessageHandler
12
- from janito.agent.openai_client import Agent
13
12
  from janito.agent.profile_manager import AgentProfileManager
14
13
  import os
15
14
  import threading
@@ -32,7 +31,9 @@ else:
32
31
  interaction_mode=unified_config.get("interaction_mode", "prompt"),
33
32
  verbose_tools=unified_config.get("verbose_tools", False),
34
33
  base_url=unified_config.get("base_url", None),
35
- azure_openai_api_version=unified_config.get("azure_openai_api_version", None),
34
+ azure_openai_api_version=unified_config.get(
35
+ "azure_openai_api_version", "2023-05-15"
36
+ ),
36
37
  use_azure_openai=unified_config.get("use_azure_openai", False),
37
38
  )
38
39
  system_prompt_template = profile_manager.render_prompt()
@@ -60,11 +61,7 @@ stream_queue = Queue()
60
61
  message_handler = QueuedMessageHandler(stream_queue)
61
62
 
62
63
  # Instantiate the Agent with config-driven parameters (no tool_handler)
63
- agent = Agent(
64
- api_key=unified_config.get("api_key"),
65
- model=unified_config.get("model"),
66
- base_url=unified_config.get("base_url"),
67
- )
64
+ agent = profile_manager.agent
68
65
 
69
66
 
70
67
  @app.route("/get_config")
@@ -147,7 +144,7 @@ def index():
147
144
  def load_conversation():
148
145
  global conversation
149
146
  try:
150
- with open(conversation_file, "r") as f:
147
+ with open(conversation_file, "r", encoding="utf-8") as f:
151
148
  conversation = json.load(f)
152
149
  except (FileNotFoundError, json.JSONDecodeError):
153
150
  conversation = []
@@ -187,7 +184,7 @@ def execute_stream():
187
184
  )
188
185
  try:
189
186
  os.makedirs(os.path.dirname(conversation_file), exist_ok=True)
190
- with open(conversation_file, "w") as f:
187
+ with open(conversation_file, "w", encoding="utf-8") as f:
191
188
  json.dump(conversation, f, indent=2)
192
189
  except Exception as e:
193
190
  print(f"Error saving conversation: {e}")
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: janito
3
- Version: 1.6.0
4
- Summary: A Natural Language Programming Agent,
3
+ Version: 1.7.0
4
+ Summary: Natural Language Coding Agent,
5
5
  Author-email: João Pinto <joao.pinto@gmail.com>
6
- License: MIT
7
- Project-URL: homepage, https://github.com/joaompinto/janito
6
+ License-Expression: MIT
7
+ Project-URL: homepage, https://janito.dev
8
8
  Project-URL: repository, https://github.com/joaompinto/janito
9
9
  Keywords: agent,framework,tools,automation
10
10
  Classifier: Programming Language :: Python :: 3.10
@@ -21,16 +21,24 @@ Requires-Dist: pathspec
21
21
  Requires-Dist: prompt_toolkit
22
22
  Requires-Dist: requests
23
23
  Requires-Dist: rich
24
+ Requires-Dist: toml
25
+ Provides-Extra: docs
26
+ Requires-Dist: mkdocs>=1.5.3; extra == "docs"
27
+ Requires-Dist: mkdocs-material>=9.4.8; extra == "docs"
24
28
  Dynamic: license-file
25
29
 
26
- # 🚀 Janito: Natural Language Programming Agent
30
+ # 🚀 Janito: Natural Language Coding Agent
27
31
 
28
- **Current Version: 1.6.0**
29
- See [CHANGELOG.md](./CHANGELOG.md) and [RELEASE_NOTES_1.6.md](./RELEASE_NOTES_1.6.md) for details on the latest release.
32
+ **Current Version: 1.7.0**
33
+ See [CHANGELOG.md](./CHANGELOG.md) for details on the latest release.
30
34
 
31
35
  Janito is an AI-powered assistant for the command line and web that interprets natural language system_prompt_template to edit code, manage files, and analyze projects using patterns and tools designed by experienced software engineers. It prioritizes transparency, interactive clarification, and precise, reviewable changes.
32
36
 
33
- For a technical overview, see the [Architecture Guide](docs/ARCHITECTURE.md).
37
+ For a technical overview, see the [Architecture Guide](docs/reference/architecture.md).
38
+
39
+ ## 📖 Full Documentation & Overview
40
+ - For structured and in-depth guides, visit the [Janito Documentation Site](https://docs.janito.dev).
41
+ - For a high-level, user-friendly overview, see [janito.dev](https://janito.dev).
34
42
 
35
43
  ---
36
44
 
@@ -144,7 +152,7 @@ The default template ensures the agent:
144
152
  - Provides concise plans before taking action
145
153
  - Documents any changes made
146
154
 
147
- For more details or to customize the prompt, see the template file at `janito/agent/templates/system_prompt_template.j2` and the architecture overview in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).
155
+ For more details or to customize the prompt, see the template file at `janito/agent/templates/system_prompt_template.j2` and the architecture overview in [docs/reference/architecture.md](docs/reference/architecture.md).
148
156
 
149
157
  ---
150
158