feat: recursively resolve .goosehints files (#358)

This commit is contained in:
Alistair Gray
2024-11-27 21:27:40 -05:00
committed by GitHub
parent 4222477758
commit fcbac4ee24
4 changed files with 41 additions and 21 deletions
+2 -10
View File
@@ -1,6 +1,4 @@
import os import os
from goose.toolkit.utils import render_template
from pathlib import Path
from exchange.content import Text from exchange.content import Text
from exchange.exchange import Exchange from exchange.exchange import Exchange
from exchange.message import Message from exchange.message import Message
@@ -8,6 +6,7 @@ from exchange.moderators import Moderator
from exchange.moderators.passive import PassiveModerator from exchange.moderators.passive import PassiveModerator
from exchange.moderators.truncate import ContextTruncate from exchange.moderators.truncate import ContextTruncate
from goose.synopsis.system import system from goose.synopsis.system import system
from goose.utils.goosehints import fetch_goosehints
class Synopsis(Moderator): class Synopsis(Moderator):
@@ -39,14 +38,7 @@ class Synopsis(Moderator):
self.current_plan = "" self.current_plan = ""
self.originals = [] self.originals = []
hints = [] self.hints = fetch_goosehints()
hints_path = Path(".goosehints")
home_hints_path = Path.home() / ".config/goose/.goosehints"
if hints_path.is_file():
hints.append(render_template(hints_path))
if home_hints_path.is_file():
hints.append(render_template(home_hints_path))
self.hints = "\n".join(hints)
def rewrite(self, exchange: Exchange) -> None: def rewrite(self, exchange: Exchange) -> None:
# Get the last message, which would be either a user text or a user tool use # Get the last message, which would be either a user text or a user tool use
+5 -10
View File
@@ -7,7 +7,8 @@ from pathlib import Path
from exchange import Message from exchange import Message
from goose.toolkit.base import Toolkit, tool from goose.toolkit.base import Toolkit, tool
from goose.toolkit.utils import get_language, render_template, RULEPREFIX, RULESTYLE from goose.toolkit.utils import get_language, RULEPREFIX, RULESTYLE
from goose.utils.goosehints import fetch_goosehints
from goose.utils.shell import shell from goose.utils.shell import shell
from rich.markdown import Markdown from rich.markdown import Markdown
from rich.table import Table from rich.table import Table
@@ -28,17 +29,11 @@ class Developer(Toolkit):
def system(self) -> str: def system(self) -> str:
"""Retrieve system configuration details for developer""" """Retrieve system configuration details for developer"""
hints_path = Path(".goosehints")
system_prompt = Message.load("prompts/developer.jinja").text system_prompt = Message.load("prompts/developer.jinja").text
home_hints_path = Path.home() / ".config/goose/.goosehints" hints = fetch_goosehints()
hints = []
if hints_path.is_file():
hints.append(render_template(hints_path))
if home_hints_path.is_file():
hints.append(render_template(home_hints_path))
if hints: if hints:
hints_text = "\n".join(hints) system_prompt = f"{system_prompt}\n\nHints:\n{hints}"
system_prompt = f"{system_prompt}\n\nHints:\n{hints_text}"
return system_prompt return system_prompt
@tool @tool
+21
View File
@@ -0,0 +1,21 @@
from pathlib import Path
from goose.toolkit.utils import render_template
def fetch_goosehints() -> str:
hints = []
dirs = [Path.cwd()] + list(Path.cwd().parents)
# reverse to go from parent to child
dirs.reverse()
for dir in dirs:
hints_path = dir / ".goosehints"
if hints_path.is_file():
hints.append(render_template(hints_path))
home_hints_path = Path.home() / ".config/goose/.goosehints"
if home_hints_path.is_file():
hints.append(render_template(home_hints_path))
return "\n\n".join(hints)
+13 -1
View File
@@ -75,6 +75,18 @@ def test_system_prompt_with_goosehints(temp_dir, developer_toolkit):
assert system_prompt.endswith(expected_end) assert system_prompt.endswith(expected_end)
def test_system_prompt_with_goosehints_from_parent_dir(temp_dir, developer_toolkit):
hints_file = temp_dir / ".goosehints"
hints_file.write_text("This is from the README.md file in parent.")
inner_temp_dir = temp_dir / "inner"
inner_temp_dir.mkdir(parents=True, exist_ok=True)
with change_dir(inner_temp_dir):
system_prompt = developer_toolkit.system()
expected = "This is from the README.md file in parent."
assert system_prompt.endswith(expected)
def test_system_prompt_with_goosehints_only_from_home_dir(temp_dir, developer_toolkit): def test_system_prompt_with_goosehints_only_from_home_dir(temp_dir, developer_toolkit):
readme_file_home = Path.home() / ".config/goose/README.md" readme_file_home = Path.home() / ".config/goose/README.md"
readme_file_home.parent.mkdir(parents=True, exist_ok=True) readme_file_home.parent.mkdir(parents=True, exist_ok=True)
@@ -113,7 +125,7 @@ def test_system_prompt_with_goosehints_only_from_home_dir(temp_dir, developer_to
system_prompt = developer_toolkit.system() system_prompt = developer_toolkit.system()
expected_content_local = "Hints from local:\n\nThis is from the README.md file.\nEnd." expected_content_local = "Hints from local:\n\nThis is from the README.md file.\nEnd."
expected_content_home = "Hints from home:\n\nThis is from the README.md file in home.\nEnd." expected_content_home = "Hints from home:\n\nThis is from the README.md file in home.\nEnd."
expected_end = f"Hints:\n{expected_content_local}\n{expected_content_home}" expected_end = f"Hints:\n{expected_content_local}\n\n{expected_content_home}"
assert system_prompt.endswith(expected_end) assert system_prompt.endswith(expected_end)
finally: finally:
home_hints_file.unlink() home_hints_file.unlink()