-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: clear separation of public and internal packages #39
Closed
lifeizhou-ap
wants to merge
27
commits into
main
from
lifei/refactor-distinguish-private-public-functions
Closed
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
83ecb6c
initial change
lifeizhou-ap 744c7f9
moved configuration constants to config module
lifeizhou-ap 67935c5
moved session_path from config to session_file util
lifeizhou-ap 9bf35a6
created _internal package to have functions and classes that used int…
lifeizhou-ap f2a9564
moved toolkit to _internal package, and leave the Toolkit class file …
lifeizhou-ap 081cb9b
moved toolkit test
lifeizhou-ap 66d0d5e
removed unused file utils
lifeizhou-ap 7232562
created profile package in internal folder
lifeizhou-ap 76f8d1c
move get_language to public as it is used by plugins
lifeizhou-ap 0b0ebd7
Merge branch 'main' into lifei/refactor-distinguish-private-public-fu…
lifeizhou-ap 252c36a
reorganised files in the toolkit folder
lifeizhou-ap 513249f
created github folder for github toolkit
lifeizhou-ap 0e0fa7f
moved cli prompt into internal folder
lifeizhou-ap 061fc93
move main.py and session.py to internal folder
lifeizhou-ap 448a7e6
removed unused load_provider function
lifeizhou-ap a8d766e
mark private function in session object
lifeizhou-ap 11e6a34
move session and main tests
lifeizhou-ap 2e1d9e5
Merge branch 'main' into lifei/refactor-distinguish-private-public-fu…
lifeizhou-ap 87854db
fixed the format
lifeizhou-ap f7594c9
fixed the test
lifeizhou-ap 48fcd1d
used proper print
lifeizhou-ap 6658937
created pluginbase package. This can be accessed by external plugins…
lifeizhou-ap dbd39f7
reorganised the uitls to exposed minimal utils to be accessed by plu…
lifeizhou-ap ef72ff0
fixed format
lifeizhou-ap cae81be
organise command
lifeizhou-ap d3dbfbc
fixed format issue
lifeizhou-ap 5e943de
refactored utils files
lifeizhou-ap File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from .pluginbase.notifier import Notifier # noqa: F401 | ||
from .pluginbase.toolkit import Toolkit, tool # noqa: F401 | ||
from .pluginbase.profile import Profile, ToolkitSpec # noqa: F401 | ||
from .pluginbase.command import Command # noqa: F401 | ||
from .pluginbase.utils import converter # noqa: F401 |
File renamed without changes.
4 changes: 2 additions & 2 deletions
4
src/goose/command/__init__.py → src/goose/_internal/cli/command/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,70 +5,20 @@ | |
from exchange import Message, ToolResult, ToolUse, Text | ||
from prompt_toolkit.shortcuts import confirm | ||
from rich import print | ||
from rich.console import RenderableType | ||
from rich.live import Live | ||
from rich.markdown import Markdown | ||
from rich.panel import Panel | ||
from rich.status import Status | ||
|
||
from goose.build import build_exchange | ||
from goose.cli.config import ( | ||
default_profiles, | ||
ensure_config, | ||
read_config, | ||
session_path, | ||
) | ||
from goose.cli.prompt.goose_prompt_session import GoosePromptSession | ||
from goose.notifier import Notifier | ||
from goose.profile import Profile | ||
from goose.utils import droid, load_plugins | ||
from goose.utils.session_file import read_from_file, write_to_file | ||
from .session_utils import random_session_name | ||
|
||
RESUME_MESSAGE = "I see we were interrupted. How can I help you?" | ||
|
||
|
||
def load_provider() -> str: | ||
# We try to infer a provider, by going in order of what will auth | ||
providers = load_plugins(group="exchange.provider") | ||
for provider, cls in providers.items(): | ||
try: | ||
cls.from_env() | ||
print(Panel(f"[green]Detected an available provider: [/]{provider}")) | ||
return provider | ||
except Exception: | ||
pass | ||
else: | ||
# TODO link to auth docs | ||
print( | ||
Panel( | ||
"[red]Could not authenticate any providers[/]\n" | ||
+ "Returning a default pointing to openai, but you will need to set an API token env variable." | ||
) | ||
) | ||
return "openai" | ||
|
||
|
||
def load_profile(name: Optional[str]) -> Profile: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moved this function in the _internal.profile package |
||
if name is None: | ||
name = "default" | ||
from .session_notifier import SessionNotifier | ||
|
||
# If the name is one of the default values, we ensure a valid configuration | ||
if name in default_profiles(): | ||
return ensure_config(name) | ||
from ...profile.config import load_profile | ||
from ...exchange.build import build_exchange | ||
from ..prompt.goose_prompt_session import GoosePromptSession | ||
from goose.pluginbase.utils.session_file import read_from_file, write_to_file, session_path | ||
|
||
# Otherwise this is a custom config and we return it from the config file | ||
return read_config()[name] | ||
|
||
|
||
class SessionNotifier(Notifier): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moved this class in a separate file |
||
def __init__(self, status_indicator: Status) -> None: | ||
self.status_indicator = status_indicator | ||
|
||
def log(self, content: RenderableType) -> None: | ||
print(content) | ||
|
||
def status(self, status: str) -> None: | ||
self.status_indicator.update(status) | ||
RESUME_MESSAGE = "I see we were interrupted. How can I help you?" | ||
|
||
|
||
class Session: | ||
|
@@ -92,7 +42,7 @@ def __init__( | |
self.exchange = build_exchange(profile=load_profile(profile), notifier=notifier) | ||
|
||
if name is not None and self.session_file_path.exists(): | ||
messages = self.load_session() | ||
messages = self._load_session() | ||
|
||
if messages and messages[-1].role == "user": | ||
if type(messages[-1].content[-1]) is Text: | ||
|
@@ -112,11 +62,11 @@ def __init__( | |
self.exchange.messages.extend(messages) | ||
|
||
if len(self.exchange.messages) == 0 and plan: | ||
self.setup_plan(plan=plan) | ||
self._setup_plan(plan=plan) | ||
|
||
self.prompt_session = GoosePromptSession.create_prompt_session() | ||
|
||
def setup_plan(self, plan: dict) -> None: | ||
def _setup_plan(self, plan: dict) -> None: | ||
if len(self.exchange.messages): | ||
raise ValueError("The plan can only be set on an empty session.") | ||
self.exchange.messages.append(Message.user(plan["kickoff_message"])) | ||
|
@@ -127,7 +77,7 @@ def setup_plan(self, plan: dict) -> None: | |
plan_tool_use = ToolUse(id="initialplan", name="update_plan", parameters=dict(tasks=tasks)) | ||
self.exchange.add_tool_use(plan_tool_use) | ||
|
||
def process_first_message(self) -> Optional[Message]: | ||
def _process_first_message(self) -> Optional[Message]: | ||
# Get a first input unless it has been specified, such as by a plan | ||
if len(self.exchange.messages) == 0 or self.exchange.messages[-1].role == "assistant": | ||
user_input = self.prompt_session.get_user_input() | ||
|
@@ -141,14 +91,14 @@ def run(self) -> None: | |
Runs the main loop to handle user inputs and responses. | ||
Continues until an empty string is returned from the prompt. | ||
""" | ||
message = self.process_first_message() | ||
message = self._process_first_message() | ||
while message: # Loop until no input (empty string). | ||
with Live(self.status_indicator, refresh_per_second=8, transient=True): | ||
try: | ||
self.exchange.add(message) | ||
self.reply() # Process the user message. | ||
self._reply() # Process the user message. | ||
except KeyboardInterrupt: | ||
self.interrupt_reply() | ||
self._interrupt_reply() | ||
except Exception: | ||
print(traceback.format_exc()) | ||
if self.exchange.messages: | ||
|
@@ -164,9 +114,9 @@ def run(self) -> None: | |
user_input = self.prompt_session.get_user_input() | ||
message = Message.user(text=user_input.text) if user_input.to_continue() else None | ||
|
||
self.save_session() | ||
self._save_session() | ||
|
||
def reply(self) -> None: | ||
def _reply(self) -> None: | ||
"""Reply to the last user message, calling tools as needed | ||
|
||
Args: | ||
|
@@ -190,7 +140,7 @@ def reply(self) -> None: | |
if response.text: | ||
print(Markdown(response.text)) | ||
|
||
def interrupt_reply(self) -> None: | ||
def _interrupt_reply(self) -> None: | ||
"""Recover from an interruption at an arbitrary state""" | ||
# Default recovery message if no user message is pending. | ||
recovery = "We interrupted before the next processing started." | ||
|
@@ -224,28 +174,28 @@ def interrupt_reply(self) -> None: | |
def session_file_path(self) -> Path: | ||
return session_path(self.name) | ||
|
||
def save_session(self) -> None: | ||
def _save_session(self) -> None: | ||
"""Save the current session to a file in JSON format.""" | ||
if self.name is None: | ||
self.generate_session_name() | ||
self._generate_session_name() | ||
|
||
try: | ||
if self.session_file_path.exists(): | ||
if not confirm(f"Session {self.name} exists in {self.session_file_path}, overwrite?"): | ||
self.generate_session_name() | ||
self._generate_session_name() | ||
write_to_file(self.session_file_path, self.exchange.messages) | ||
except PermissionError as e: | ||
raise RuntimeError(f"Failed to save session due to permissions: {e}") | ||
except (IOError, OSError) as e: | ||
raise RuntimeError(f"Failed to save session due to I/O error: {e}") | ||
|
||
def load_session(self) -> List[Message]: | ||
def _load_session(self) -> List[Message]: | ||
"""Load a session from a JSON file.""" | ||
return read_from_file(self.session_file_path) | ||
|
||
def generate_session_name(self) -> None: | ||
def _generate_session_name(self) -> None: | ||
user_entered_session_name = self.prompt_session.get_save_session_name() | ||
self.name = user_entered_session_name if user_entered_session_name else droid() | ||
self.name = user_entered_session_name if user_entered_session_name else random_session_name() | ||
print(f"Saving to [bold cyan]{self.session_file_path}[/bold cyan]") | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from goose.pluginbase.notifier import Notifier | ||
from rich.status import Status | ||
from rich.console import RenderableType | ||
from rich import print | ||
|
||
|
||
class SessionNotifier(Notifier): | ||
def __init__(self, status_indicator: Status) -> None: | ||
self.status_indicator = status_indicator | ||
|
||
def log(self, content: RenderableType) -> None: | ||
print(content) | ||
|
||
def status(self, status: str) -> None: | ||
self.status_indicator.update(status) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import random | ||
import string | ||
|
||
def random_session_name() -> str: | ||
return "".join( | ||
[ | ||
random.choice(string.ascii_lowercase), | ||
random.choice(string.digits), | ||
random.choice(string.ascii_lowercase), | ||
random.choice(string.digits), | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from typing import Any, Dict | ||
from goose.pluginbase.profile import Profile, ToolkitSpec | ||
|
||
|
||
def default_profile(provider: str, processor: str, accelerator: str, **kwargs: Dict[str, Any]) -> Profile: | ||
"""Get the default profile""" | ||
|
||
# TODO consider if the providers should have recommended models | ||
|
||
return Profile( | ||
provider=provider, | ||
processor=processor, | ||
accelerator=accelerator, | ||
moderator="truncate", | ||
toolkits=[ToolkitSpec("developer")], | ||
) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleted this this function as it is not used