Skip to content

Commit 4c2c4f5

Browse files
authored
feat: add completions-based OpenAI bot (#39)
1 parent 3f83752 commit 4c2c4f5

File tree

7 files changed

+306
-139
lines changed

7 files changed

+306
-139
lines changed

README.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@
55
66
## Highlights
77

8-
* Concurrent editing. Continue editing while the assistant runs, without any
8+
* Concurrent edits. Continue editing while the assistant runs, without any
99
risks of interference.
10-
11-
12-
## Ideas
13-
14-
* Add a compatibility OpenAI bot version which does not use threads, so that it
15-
can be used with tools only. Gemini only supports the latter.
10+
* Customizable prompt templates
11+
* Extensible bot API

src/git_draft/__main__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,13 @@ def main() -> None:
111111
)
112112
command = getattr(opts, "command", "generate")
113113
if command == "generate":
114-
if not config.bots:
115-
raise ValueError("No bots configured")
116-
114+
bot_config = None
117115
if opts.bot:
118116
bot_configs = [c for c in config.bots if c.name == opts.bot]
119117
if len(bot_configs) != 1:
120118
raise ValueError(f"Found {len(bot_configs)} matching bots")
121119
bot_config = bot_configs[0]
122-
else:
120+
elif config.bots:
123121
bot_config = config.bots[0]
124122
bot = load_bot(bot_config)
125123

src/git_draft/bots/__init__.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
"""
55

66
import importlib
7+
import os
78
import sys
89

9-
from ..common import BotConfig
10+
from ..common import BotConfig, reindent
1011
from .common import Action, Bot, Goal, Operation, OperationHook, Toolbox
1112

1213
__all__ = [
@@ -19,20 +20,11 @@
1920
]
2021

2122

22-
def load_bot(config: BotConfig) -> Bot:
23-
"""Load and return a Bot instance using the provided configuration.
23+
def load_bot(config: BotConfig | None) -> Bot:
24+
"""Load and return a Bot instance using the provided configuration"""
25+
if not config:
26+
return _default_bot()
2427

25-
If a pythonpath is specified in the config and not already present in
26-
sys.path, it is added. The function expects the config.factory in the
27-
format 'module:symbol' or 'symbol'. If only 'symbol' is provided, the
28-
current module is used.
29-
30-
Args:
31-
config: BotConfig object containing bot configuration details.
32-
33-
Raises:
34-
NotImplementedError: If the specified factory cannot be found.
35-
"""
3628
if config.pythonpath and config.pythonpath not in sys.path:
3729
sys.path.insert(0, config.pythonpath)
3830

@@ -44,7 +36,36 @@ def load_bot(config: BotConfig) -> Bot:
4436

4537
factory = getattr(module, symbol, None)
4638
if not factory:
47-
raise NotImplementedError(f"Unknown bot factory: {factory}")
39+
raise NotImplementedError(f"Unknown bot factory: {config.factory}")
4840

4941
kwargs = config.config or {}
5042
return factory(**kwargs)
43+
44+
45+
def _default_bot() -> Bot:
46+
if not os.environ.get("OPENAI_API_KEY"):
47+
raise RuntimeError(
48+
reindent(
49+
"""
50+
The default bot implementation requires an OpenAI API key.
51+
Please specify one via the `$OPENAI_API_KEY` environment
52+
variable or enable a different bot in your configuration.
53+
"""
54+
)
55+
)
56+
57+
try:
58+
from .openai import threads_bot
59+
60+
except ImportError:
61+
raise RuntimeError(
62+
reindent(
63+
"""
64+
The default bot implementation requires the `openai` Python
65+
package. Please install it or specify a different bot in
66+
your configuration.
67+
"""
68+
)
69+
)
70+
else:
71+
return threads_bot()

0 commit comments

Comments
 (0)