ommlds 0.0.0.dev488__py3-none-any.whl → 0.0.0.dev490__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.
- ommlds/cli/_dataclasses.py +657 -328
- ommlds/cli/main.py +74 -42
- ommlds/cli/sessions/chat/agents/agent.py +49 -0
- ommlds/cli/sessions/chat/{chat → agents}/ai/configs.py +3 -1
- ommlds/cli/sessions/chat/agents/ai/events.py +57 -0
- ommlds/cli/sessions/chat/{chat → agents}/ai/inject.py +7 -2
- ommlds/cli/sessions/chat/{chat → agents}/ai/rendering.py +1 -1
- ommlds/cli/sessions/chat/{chat → agents}/ai/services.py +1 -1
- ommlds/cli/sessions/chat/{chat → agents}/ai/tools.py +1 -1
- ommlds/cli/sessions/chat/{chat → agents}/ai/types.py +9 -0
- ommlds/cli/sessions/chat/agents/configs.py +25 -0
- ommlds/cli/sessions/chat/agents/events/inject.py +27 -0
- ommlds/cli/sessions/chat/agents/events/injection.py +14 -0
- ommlds/cli/sessions/chat/agents/events/manager.py +16 -0
- ommlds/cli/sessions/chat/agents/events/types.py +38 -0
- ommlds/cli/sessions/chat/agents/inject.py +62 -0
- ommlds/cli/sessions/chat/{chat → agents}/state/inject.py +3 -3
- ommlds/cli/sessions/chat/{chat → agents}/state/types.py +1 -1
- ommlds/cli/sessions/chat/{tools → agents/tools}/configs.py +3 -1
- ommlds/cli/sessions/chat/{tools → agents/tools}/confirmation.py +1 -1
- ommlds/cli/sessions/chat/{tools → agents/tools}/execution.py +1 -1
- ommlds/cli/sessions/chat/{tools → agents/tools}/fs/inject.py +3 -3
- ommlds/cli/sessions/chat/{tools → agents/tools}/inject.py +8 -4
- ommlds/cli/sessions/chat/{tools → agents/tools}/injection.py +1 -1
- ommlds/cli/sessions/chat/{tools → agents/tools}/rendering.py +3 -3
- ommlds/cli/sessions/chat/{tools → agents/tools}/todo/inject.py +3 -3
- ommlds/cli/sessions/chat/{tools → agents/tools}/weather/tools.py +1 -1
- ommlds/cli/sessions/chat/{chat → agents}/user/configs.py +0 -2
- ommlds/cli/sessions/chat/agents/user/inject.py +40 -0
- ommlds/cli/sessions/chat/configs.py +4 -12
- ommlds/cli/sessions/chat/inject.py +4 -32
- ommlds/cli/sessions/chat/{interface → interfaces}/bare/inject.py +14 -4
- ommlds/cli/sessions/chat/interfaces/bare/interactive.py +41 -0
- ommlds/cli/sessions/chat/interfaces/bare/oneshot.py +21 -0
- ommlds/cli/sessions/chat/{chat/user/interactive.py → interfaces/bare/user.py} +1 -1
- ommlds/cli/sessions/chat/interfaces/textual/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/textual/app.py +211 -0
- ommlds/cli/sessions/chat/interfaces/textual/inject.py +43 -0
- ommlds/cli/sessions/chat/{interface → interfaces}/textual/interface.py +0 -3
- ommlds/cli/sessions/chat/interfaces/textual/styles/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/input.tcss +51 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss +33 -0
- ommlds/cli/sessions/chat/session.py +1 -1
- {ommlds-0.0.0.dev488.dist-info → ommlds-0.0.0.dev490.dist-info}/METADATA +4 -4
- {ommlds-0.0.0.dev488.dist-info → ommlds-0.0.0.dev490.dist-info}/RECORD +76 -66
- ommlds/cli/sessions/chat/chat/user/inject.py +0 -55
- ommlds/cli/sessions/chat/chat/user/oneshot.py +0 -25
- ommlds/cli/sessions/chat/chat/user/types.py +0 -15
- ommlds/cli/sessions/chat/driver.py +0 -43
- ommlds/cli/sessions/chat/interface/bare/interface.py +0 -19
- ommlds/cli/sessions/chat/interface/textual/app.py +0 -14
- ommlds/cli/sessions/chat/interface/textual/inject.py +0 -20
- /ommlds/cli/sessions/chat/{chat → agents}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{chat → agents}/ai/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{chat → agents}/ai/injection.py +0 -0
- /ommlds/cli/sessions/chat/{chat/state → agents/events}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{chat/user → agents/phases}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{phases → agents/phases}/inject.py +0 -0
- /ommlds/cli/sessions/chat/{phases → agents/phases}/injection.py +0 -0
- /ommlds/cli/sessions/chat/{phases → agents/phases}/manager.py +0 -0
- /ommlds/cli/sessions/chat/{phases → agents/phases}/types.py +0 -0
- /ommlds/cli/sessions/chat/{interface → agents/state}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{chat → agents}/state/configs.py +0 -0
- /ommlds/cli/sessions/chat/{chat → agents}/state/inmemory.py +0 -0
- /ommlds/cli/sessions/chat/{chat → agents}/state/storage.py +0 -0
- /ommlds/cli/sessions/chat/{interface/bare → agents/tools}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{interface/textual → agents/tools/fs}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{tools → agents/tools}/fs/configs.py +0 -0
- /ommlds/cli/sessions/chat/{phases → agents/tools/todo}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{tools → agents/tools}/todo/configs.py +0 -0
- /ommlds/cli/sessions/chat/{tools → agents/tools/weather}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{tools → agents/tools}/weather/configs.py +0 -0
- /ommlds/cli/sessions/chat/{tools → agents/tools}/weather/inject.py +0 -0
- /ommlds/cli/sessions/chat/{tools/fs → agents/user}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{tools/todo → interfaces}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{tools/weather → interfaces/bare}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{interface → interfaces}/base.py +0 -0
- /ommlds/cli/sessions/chat/{interface → interfaces}/configs.py +0 -0
- /ommlds/cli/sessions/chat/{interface → interfaces}/inject.py +0 -0
- {ommlds-0.0.0.dev488.dist-info → ommlds-0.0.0.dev490.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev488.dist-info → ommlds-0.0.0.dev490.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev488.dist-info → ommlds-0.0.0.dev490.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev488.dist-info → ommlds-0.0.0.dev490.dist-info}/top_level.txt +0 -0
ommlds/cli/main.py
CHANGED
|
@@ -69,9 +69,12 @@ class ChatProfile(Profile):
|
|
|
69
69
|
def configure_backend(self, cfg: ChatConfig) -> ChatConfig:
|
|
70
70
|
return dc.replace(
|
|
71
71
|
cfg,
|
|
72
|
-
|
|
73
|
-
cfg.
|
|
74
|
-
backend=
|
|
72
|
+
agent=dc.replace(
|
|
73
|
+
cfg.agent,
|
|
74
|
+
backend=dc.replace(
|
|
75
|
+
cfg.agent.backend,
|
|
76
|
+
backend=self._args.backend,
|
|
77
|
+
),
|
|
75
78
|
),
|
|
76
79
|
)
|
|
77
80
|
|
|
@@ -89,17 +92,28 @@ class ChatProfile(Profile):
|
|
|
89
92
|
check.arg(not self._args.message)
|
|
90
93
|
raise NotImplementedError
|
|
91
94
|
|
|
92
|
-
if self._args.
|
|
95
|
+
if self._args.textual:
|
|
93
96
|
cfg = dc.replace(
|
|
94
97
|
cfg,
|
|
95
98
|
interface=dc.replace(
|
|
96
99
|
cfg.interface,
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
use_textual=True,
|
|
101
|
+
),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
else:
|
|
105
|
+
cfg = dc.replace(
|
|
106
|
+
cfg,
|
|
107
|
+
agent=dc.replace(
|
|
108
|
+
cfg.agent,
|
|
109
|
+
ai=dc.replace(
|
|
110
|
+
cfg.agent.ai,
|
|
111
|
+
verbose=True,
|
|
112
|
+
),
|
|
99
113
|
),
|
|
100
|
-
|
|
101
|
-
cfg.
|
|
102
|
-
interactive=
|
|
114
|
+
interface=dc.replace(
|
|
115
|
+
cfg.interface,
|
|
116
|
+
interactive=self._args.interactive,
|
|
103
117
|
),
|
|
104
118
|
)
|
|
105
119
|
|
|
@@ -112,16 +126,19 @@ class ChatProfile(Profile):
|
|
|
112
126
|
]
|
|
113
127
|
|
|
114
128
|
def configure_input(self, cfg: ChatConfig) -> ChatConfig:
|
|
115
|
-
if self._args.interactive:
|
|
129
|
+
if self._args.interactive or self._args.textual:
|
|
116
130
|
check.arg(not self._args.message)
|
|
117
131
|
|
|
118
132
|
elif self._args.message:
|
|
119
133
|
# TODO: '-' -> stdin
|
|
120
134
|
cfg = dc.replace(
|
|
121
135
|
cfg,
|
|
122
|
-
|
|
123
|
-
cfg.
|
|
124
|
-
|
|
136
|
+
agent=dc.replace(
|
|
137
|
+
cfg.agent,
|
|
138
|
+
user=dc.replace(
|
|
139
|
+
cfg.agent.user,
|
|
140
|
+
initial_user_content=' '.join(self._args.message),
|
|
141
|
+
),
|
|
125
142
|
),
|
|
126
143
|
)
|
|
127
144
|
|
|
@@ -140,9 +157,12 @@ class ChatProfile(Profile):
|
|
|
140
157
|
def configure_state(self, cfg: ChatConfig) -> ChatConfig:
|
|
141
158
|
return dc.replace(
|
|
142
159
|
cfg,
|
|
143
|
-
|
|
144
|
-
cfg.
|
|
145
|
-
state=
|
|
160
|
+
agent=dc.replace(
|
|
161
|
+
cfg.agent,
|
|
162
|
+
state=dc.replace(
|
|
163
|
+
cfg.agent.state,
|
|
164
|
+
state='ephemeral' if self._args.ephemeral else 'new' if self._args.new else 'continue',
|
|
165
|
+
),
|
|
146
166
|
),
|
|
147
167
|
)
|
|
148
168
|
|
|
@@ -156,9 +176,12 @@ class ChatProfile(Profile):
|
|
|
156
176
|
def configure_output(self, cfg: ChatConfig) -> ChatConfig:
|
|
157
177
|
return dc.replace(
|
|
158
178
|
cfg,
|
|
159
|
-
|
|
160
|
-
cfg.
|
|
161
|
-
|
|
179
|
+
agent=dc.replace(
|
|
180
|
+
cfg.agent,
|
|
181
|
+
ai=dc.replace(
|
|
182
|
+
cfg.agent.ai,
|
|
183
|
+
stream=bool(self._args.stream),
|
|
184
|
+
),
|
|
162
185
|
),
|
|
163
186
|
rendering=dc.replace(
|
|
164
187
|
cfg.rendering,
|
|
@@ -178,24 +201,27 @@ class ChatProfile(Profile):
|
|
|
178
201
|
def configure_tools(self, cfg: ChatConfig) -> ChatConfig:
|
|
179
202
|
return dc.replace(
|
|
180
203
|
cfg,
|
|
181
|
-
|
|
182
|
-
cfg.
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
204
|
+
agent=dc.replace(
|
|
205
|
+
cfg.agent,
|
|
206
|
+
ai=dc.replace(
|
|
207
|
+
cfg.agent.ai,
|
|
208
|
+
enable_tools=(
|
|
209
|
+
self._args.enable_fs_tools or
|
|
210
|
+
self._args.enable_todo_tools or
|
|
211
|
+
# self._args.enable_unsafe_tools_do_not_use_lol or
|
|
212
|
+
self._args.enable_test_weather_tool or
|
|
213
|
+
self._args.code
|
|
214
|
+
),
|
|
215
|
+
),
|
|
216
|
+
tools=dc.replace(
|
|
217
|
+
cfg.agent.tools,
|
|
218
|
+
enabled_tools={ # noqa
|
|
219
|
+
*(cfg.agent.tools.enabled_tools or []),
|
|
220
|
+
*(['fs'] if self._args.enable_fs_tools else []),
|
|
221
|
+
*(['todo'] if self._args.enable_todo_tools else []),
|
|
222
|
+
*(['weather'] if self._args.enable_test_weather_tool else []),
|
|
223
|
+
},
|
|
189
224
|
),
|
|
190
|
-
),
|
|
191
|
-
tools=dc.replace(
|
|
192
|
-
cfg.tools,
|
|
193
|
-
enabled_tools={ # noqa
|
|
194
|
-
*(cfg.tools.enabled_tools or []),
|
|
195
|
-
*(['fs'] if self._args.enable_fs_tools else []),
|
|
196
|
-
*(['todo'] if self._args.enable_todo_tools else []),
|
|
197
|
-
*(['weather'] if self._args.enable_test_weather_tool else []),
|
|
198
|
-
},
|
|
199
225
|
),
|
|
200
226
|
)
|
|
201
227
|
|
|
@@ -211,9 +237,12 @@ class ChatProfile(Profile):
|
|
|
211
237
|
|
|
212
238
|
cfg = dc.replace(
|
|
213
239
|
cfg,
|
|
214
|
-
|
|
215
|
-
cfg.
|
|
216
|
-
|
|
240
|
+
agent=dc.replace(
|
|
241
|
+
cfg.agent,
|
|
242
|
+
ai=dc.replace(
|
|
243
|
+
cfg.agent.ai,
|
|
244
|
+
enable_tools=True,
|
|
245
|
+
),
|
|
217
246
|
),
|
|
218
247
|
)
|
|
219
248
|
|
|
@@ -223,9 +252,12 @@ class ChatProfile(Profile):
|
|
|
223
252
|
|
|
224
253
|
cfg = dc.replace(
|
|
225
254
|
cfg,
|
|
226
|
-
|
|
227
|
-
cfg.
|
|
228
|
-
|
|
255
|
+
agent=dc.replace(
|
|
256
|
+
cfg.agent,
|
|
257
|
+
user=dc.replace(
|
|
258
|
+
cfg.agent.user,
|
|
259
|
+
initial_system_content=system_content,
|
|
260
|
+
),
|
|
229
261
|
),
|
|
230
262
|
)
|
|
231
263
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- lifecycles
|
|
4
|
+
- StreamService
|
|
5
|
+
"""
|
|
6
|
+
from ..... import minichain as mc
|
|
7
|
+
from .ai.types import AiChatGenerator
|
|
8
|
+
from .events.manager import ChatEventsManager
|
|
9
|
+
from .events.types import UserMessagesChatEvent
|
|
10
|
+
from .phases.manager import ChatPhaseManager
|
|
11
|
+
from .phases.types import ChatPhase
|
|
12
|
+
from .state.types import ChatStateManager
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ChatAgent:
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
*,
|
|
22
|
+
phases: ChatPhaseManager,
|
|
23
|
+
ai_chat_generator: AiChatGenerator,
|
|
24
|
+
chat_state_manager: ChatStateManager,
|
|
25
|
+
events: ChatEventsManager,
|
|
26
|
+
) -> None:
|
|
27
|
+
super().__init__()
|
|
28
|
+
|
|
29
|
+
self._phases = phases
|
|
30
|
+
self._ai_chat_generator = ai_chat_generator
|
|
31
|
+
self._chat_state_manager = chat_state_manager
|
|
32
|
+
self._events = events
|
|
33
|
+
|
|
34
|
+
async def start(self) -> None:
|
|
35
|
+
await self._phases.set_phase(ChatPhase.STARTING)
|
|
36
|
+
await self._phases.set_phase(ChatPhase.STARTED)
|
|
37
|
+
|
|
38
|
+
async def stop(self) -> None:
|
|
39
|
+
await self._phases.set_phase(ChatPhase.STOPPING)
|
|
40
|
+
await self._phases.set_phase(ChatPhase.STOPPED)
|
|
41
|
+
|
|
42
|
+
async def send_user_messages(self, next_user_chat: 'mc.UserChat') -> None:
|
|
43
|
+
await self._events.emit_event(UserMessagesChatEvent(next_user_chat))
|
|
44
|
+
|
|
45
|
+
prev_user_chat = (await self._chat_state_manager.get_state()).chat
|
|
46
|
+
|
|
47
|
+
next_ai_chat = await self._ai_chat_generator.get_next_ai_messages([*prev_user_chat, *next_user_chat])
|
|
48
|
+
|
|
49
|
+
await self._chat_state_manager.extend_chat([*next_user_chat, *next_ai_chat])
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from ...... import minichain as mc
|
|
4
|
+
from ..events.manager import ChatEventsManager
|
|
5
|
+
from ..events.types import AiDeltaChatEvent
|
|
6
|
+
from ..events.types import AiMessagesChatEvent
|
|
7
|
+
from .types import AiChatGenerator
|
|
8
|
+
from .types import StreamAiChatGenerator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class EventEmittingAiChatGenerator(AiChatGenerator):
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
*,
|
|
18
|
+
wrapped: AiChatGenerator,
|
|
19
|
+
events: ChatEventsManager,
|
|
20
|
+
) -> None:
|
|
21
|
+
super().__init__()
|
|
22
|
+
|
|
23
|
+
self._wrapped = wrapped
|
|
24
|
+
self._events = events
|
|
25
|
+
|
|
26
|
+
async def get_next_ai_messages(self, chat: 'mc.Chat') -> 'mc.Chat':
|
|
27
|
+
out = await self._wrapped.get_next_ai_messages(chat)
|
|
28
|
+
|
|
29
|
+
await self._events.emit_event(AiMessagesChatEvent(out))
|
|
30
|
+
|
|
31
|
+
return out
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class EventEmittingStreamAiChatGenerator(StreamAiChatGenerator):
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
*,
|
|
38
|
+
wrapped: StreamAiChatGenerator,
|
|
39
|
+
events: ChatEventsManager,
|
|
40
|
+
) -> None:
|
|
41
|
+
super().__init__()
|
|
42
|
+
|
|
43
|
+
self._wrapped = wrapped
|
|
44
|
+
self._events = events
|
|
45
|
+
|
|
46
|
+
async def get_next_ai_messages_streamed(
|
|
47
|
+
self,
|
|
48
|
+
chat: 'mc.Chat',
|
|
49
|
+
delta_callback: ta.Callable[['mc.AiDelta'], ta.Awaitable[None]] | None = None,
|
|
50
|
+
) -> 'mc.Chat':
|
|
51
|
+
async def inner(delta: mc.AiDelta) -> None:
|
|
52
|
+
await self._events.emit_event(AiDeltaChatEvent(delta))
|
|
53
|
+
|
|
54
|
+
if delta_callback is not None:
|
|
55
|
+
await delta_callback(delta)
|
|
56
|
+
|
|
57
|
+
return await self._wrapped.get_next_ai_messages_streamed(chat, delta_callback=inner)
|
|
@@ -7,6 +7,7 @@ from .injection import chat_options_providers
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
with lang.auto_proxy_import(globals()):
|
|
10
|
+
from . import events as _events
|
|
10
11
|
from . import rendering as _rendering
|
|
11
12
|
from . import services as _services
|
|
12
13
|
from . import tools as _tools
|
|
@@ -39,9 +40,11 @@ def bind_ai(cfg: AiConfig = AiConfig()) -> inj.Elements:
|
|
|
39
40
|
|
|
40
41
|
els.append(stream_ai_stack.push_bind(to_ctor=_services.ChatChoicesStreamServiceStreamAiChatGenerator, singleton=True)) # noqa
|
|
41
42
|
|
|
42
|
-
if
|
|
43
|
+
if cfg.verbose:
|
|
43
44
|
els.append(stream_ai_stack.push_bind(to_ctor=_rendering.RenderingStreamAiChatGenerator, singleton=True))
|
|
44
45
|
|
|
46
|
+
els.append(stream_ai_stack.push_bind(to_ctor=_events.EventEmittingStreamAiChatGenerator, singleton=True))
|
|
47
|
+
|
|
45
48
|
els.extend([
|
|
46
49
|
inj.bind(_types.StreamAiChatGenerator, to_key=stream_ai_stack.top),
|
|
47
50
|
ai_stack.push_bind(to_key=_types.StreamAiChatGenerator),
|
|
@@ -50,9 +53,11 @@ def bind_ai(cfg: AiConfig = AiConfig()) -> inj.Elements:
|
|
|
50
53
|
else:
|
|
51
54
|
els.append(ai_stack.push_bind(to_ctor=_services.ChatChoicesServiceAiChatGenerator, singleton=True))
|
|
52
55
|
|
|
53
|
-
if
|
|
56
|
+
if cfg.verbose:
|
|
54
57
|
els.append(ai_stack.push_bind(to_ctor=_rendering.RenderingAiChatGenerator, singleton=True))
|
|
55
58
|
|
|
59
|
+
els.append(ai_stack.push_bind(to_ctor=_events.EventEmittingAiChatGenerator, singleton=True))
|
|
60
|
+
|
|
56
61
|
if cfg.enable_tools:
|
|
57
62
|
els.append(ai_stack.push_bind(to_ctor=_tools.ToolExecutingAiChatGenerator, singleton=True))
|
|
58
63
|
|
|
@@ -58,7 +58,7 @@ class RenderingStreamAiChatGenerator(StreamAiChatGenerator):
|
|
|
58
58
|
self,
|
|
59
59
|
chat: 'mc.Chat',
|
|
60
60
|
delta_callback: ta.Callable[['mc.AiDelta'], ta.Awaitable[None]] | None = None,
|
|
61
|
-
) -> mc.Chat:
|
|
61
|
+
) -> 'mc.Chat':
|
|
62
62
|
async with self._renderer.create_context() as renderer:
|
|
63
63
|
async def inner(delta: mc.AiDelta) -> None:
|
|
64
64
|
if isinstance(delta, mc.ContentAiDelta):
|
|
@@ -60,7 +60,7 @@ class ChatChoicesStreamServiceStreamAiChatGenerator(StreamAiChatGenerator):
|
|
|
60
60
|
self,
|
|
61
61
|
chat: 'mc.Chat',
|
|
62
62
|
delta_callback: ta.Callable[['mc.AiDelta'], ta.Awaitable[None]] | None = None,
|
|
63
|
-
) -> mc.AiChat:
|
|
63
|
+
) -> 'mc.AiChat':
|
|
64
64
|
opts = self._options() if self._options is not None else []
|
|
65
65
|
|
|
66
66
|
async with self._service_provider.provide_backend() as service:
|
|
@@ -26,3 +26,12 @@ class StreamAiChatGenerator(AiChatGenerator, lang.Abstract):
|
|
|
26
26
|
delta_callback: ta.Callable[['mc.AiDelta'], ta.Awaitable[None]] | None = None,
|
|
27
27
|
) -> ta.Awaitable['mc.Chat']:
|
|
28
28
|
raise NotImplementedError
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AiChatOutput(lang.Abstract):
|
|
35
|
+
@abc.abstractmethod
|
|
36
|
+
def output_ai_chat(self, chat: 'mc.Chat') -> ta.Awaitable[None]:
|
|
37
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from omlish import dataclasses as dc
|
|
2
|
+
|
|
3
|
+
from ....backends.configs import BackendConfig
|
|
4
|
+
from .ai.configs import AiConfig
|
|
5
|
+
from .state.configs import StateConfig
|
|
6
|
+
from .tools.configs import ToolsConfig
|
|
7
|
+
from .user.configs import UserConfig
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
DEFAULT_BACKEND = 'openai'
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
|
20
|
+
class AgentConfig:
|
|
21
|
+
ai: AiConfig = AiConfig()
|
|
22
|
+
backend: BackendConfig = BackendConfig()
|
|
23
|
+
state: StateConfig = StateConfig()
|
|
24
|
+
tools: ToolsConfig = ToolsConfig()
|
|
25
|
+
user: UserConfig = UserConfig()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from omlish import inject as inj
|
|
2
|
+
from omlish import lang
|
|
3
|
+
|
|
4
|
+
from .injection import event_callbacks
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
with lang.auto_proxy_import(globals()):
|
|
8
|
+
from . import manager as _manager
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def bind_events() -> inj.Elements:
|
|
15
|
+
els: list[inj.Elemental] = []
|
|
16
|
+
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
els.append(event_callbacks().bind_items_provider(singleton=True))
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
|
|
23
|
+
els.append(inj.bind(_manager.ChatEventsManager, singleton=True))
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
|
|
27
|
+
return inj.as_elements(*els)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from omlish import inject as inj
|
|
2
|
+
from omlish import lang
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
with lang.auto_proxy_import(globals()):
|
|
6
|
+
from . import types as _types
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@lang.cached_function
|
|
13
|
+
def event_callbacks() -> 'inj.ItemsBinderHelper[_types.ChatEventCallback]':
|
|
14
|
+
return inj.items_binder_helper[_types.ChatEventCallback](_types.ChatEventCallbacks)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .types import ChatEvent
|
|
2
|
+
from .types import ChatEventCallbacks
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ChatEventsManager:
|
|
9
|
+
def __init__(self, callbacks: ChatEventCallbacks) -> None:
|
|
10
|
+
super().__init__()
|
|
11
|
+
|
|
12
|
+
self._callbacks = callbacks
|
|
13
|
+
|
|
14
|
+
async def emit_event(self, event: ChatEvent) -> None:
|
|
15
|
+
for cb in self._callbacks:
|
|
16
|
+
await cb(event)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import dataclasses as dc
|
|
4
|
+
from omlish import lang
|
|
5
|
+
|
|
6
|
+
from ...... import minichain as mc
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ChatEvent(lang.Abstract, lang.Sealed):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ChatEventCallback(lang.Func1[ChatEvent, ta.Awaitable[None]]):
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
ChatEventCallbacks = ta.NewType('ChatEventCallbacks', ta.Sequence[ChatEventCallback])
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dc.dataclass(frozen=True)
|
|
27
|
+
class UserMessagesChatEvent(ChatEvent, lang.Final):
|
|
28
|
+
chat: 'mc.UserChat'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dc.dataclass(frozen=True)
|
|
32
|
+
class AiMessagesChatEvent(ChatEvent, lang.Final):
|
|
33
|
+
chat: 'mc.Chat'
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dc.dataclass(frozen=True)
|
|
37
|
+
class AiDeltaChatEvent(ChatEvent, lang.Final):
|
|
38
|
+
delta: 'mc.AiDelta'
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- private + expose(ChatAgent)
|
|
4
|
+
"""
|
|
5
|
+
from omlish import inject as inj
|
|
6
|
+
from omlish import lang
|
|
7
|
+
|
|
8
|
+
from ....backends.types import DefaultBackendName
|
|
9
|
+
from .configs import DEFAULT_BACKEND
|
|
10
|
+
from .configs import AgentConfig
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
with lang.auto_proxy_import(globals()):
|
|
14
|
+
from ....backends import inject as _backends
|
|
15
|
+
from . import agent as _agent
|
|
16
|
+
from .ai import inject as _ai
|
|
17
|
+
from .events import inject as _events
|
|
18
|
+
from .phases import inject as _phases
|
|
19
|
+
from .state import inject as _state
|
|
20
|
+
from .tools import inject as _tools
|
|
21
|
+
from .user import inject as _user
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def bind_agent(cfg: AgentConfig) -> inj.Elements:
|
|
28
|
+
els: list[inj.Elemental] = []
|
|
29
|
+
|
|
30
|
+
#
|
|
31
|
+
|
|
32
|
+
els.extend([
|
|
33
|
+
_backends.bind_backends(cfg.backend),
|
|
34
|
+
|
|
35
|
+
_ai.bind_ai(cfg.ai),
|
|
36
|
+
|
|
37
|
+
_events.bind_events(),
|
|
38
|
+
|
|
39
|
+
_phases.bind_phases(),
|
|
40
|
+
|
|
41
|
+
_state.bind_state(cfg.state),
|
|
42
|
+
|
|
43
|
+
_tools.bind_tools(cfg.tools),
|
|
44
|
+
|
|
45
|
+
_user.bind_user(cfg.user),
|
|
46
|
+
])
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
|
|
50
|
+
els.extend([
|
|
51
|
+
inj.bind(_agent.ChatAgent, singleton=True),
|
|
52
|
+
|
|
53
|
+
inj.bind_late(_agent.ChatAgent),
|
|
54
|
+
])
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
|
|
58
|
+
els.append(inj.bind(DefaultBackendName, to_const=DEFAULT_BACKEND))
|
|
59
|
+
|
|
60
|
+
#
|
|
61
|
+
|
|
62
|
+
return inj.as_elements(*els)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from omlish import inject as inj
|
|
2
2
|
from omlish import lang
|
|
3
3
|
|
|
4
|
-
from
|
|
5
|
-
from
|
|
6
|
-
from
|
|
4
|
+
from ..phases.injection import phase_callbacks
|
|
5
|
+
from ..phases.types import ChatPhase
|
|
6
|
+
from ..phases.types import ChatPhaseCallback
|
|
7
7
|
from .configs import StateConfig
|
|
8
8
|
|
|
9
9
|
|
|
@@ -9,10 +9,12 @@ from omlish import lang
|
|
|
9
9
|
|
|
10
10
|
@dc.dataclass(frozen=True, kw_only=True)
|
|
11
11
|
class ToolsConfig:
|
|
12
|
-
silent: bool = False
|
|
13
12
|
dangerous_no_confirmation: bool = False
|
|
13
|
+
|
|
14
14
|
enabled_tools: ta.Iterable[str] | None = None
|
|
15
15
|
|
|
16
|
+
verbose: bool = False
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
##
|
|
18
20
|
|
|
@@ -12,9 +12,9 @@ from .configs import FsToolSetConfig
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def bind_fs_tools(cfg: FsToolSetConfig) -> inj.Elements:
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
15
|
+
from .......minichain.lib.fs.context import FsContext
|
|
16
|
+
from .......minichain.lib.fs.tools.ls import ls_tool
|
|
17
|
+
from .......minichain.lib.fs.tools.read import read_tool
|
|
18
18
|
|
|
19
19
|
return inj.as_elements(
|
|
20
20
|
tool_catalog_entries().bind_item_consts(
|
|
@@ -2,8 +2,8 @@ from omlish import check
|
|
|
2
2
|
from omlish import inject as inj
|
|
3
3
|
from omlish import lang
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
from
|
|
5
|
+
from ...... import minichain as mc
|
|
6
|
+
from ..configs import ToolsConfig
|
|
7
7
|
from .injection import ToolSetBinder
|
|
8
8
|
from .injection import tool_catalog_entries
|
|
9
9
|
from .injection import tool_context_providers
|
|
@@ -58,7 +58,7 @@ def bind_tools(cfg: ToolsConfig = ToolsConfig()) -> inj.Elements:
|
|
|
58
58
|
|
|
59
59
|
els.append(exec_stack.push_bind(to_ctor=_execution.ToolUseExecutorImpl, singleton=True))
|
|
60
60
|
|
|
61
|
-
if
|
|
61
|
+
if cfg.verbose:
|
|
62
62
|
els.append(exec_stack.push_bind(to_ctor=_rendering.ResultRenderingToolUseExecutor, singleton=True))
|
|
63
63
|
|
|
64
64
|
if cfg.dangerous_no_confirmation:
|
|
@@ -71,7 +71,11 @@ def bind_tools(cfg: ToolsConfig = ToolsConfig()) -> inj.Elements:
|
|
|
71
71
|
#
|
|
72
72
|
|
|
73
73
|
if not cfg.dangerous_no_confirmation:
|
|
74
|
-
els.append(inj.bind(
|
|
74
|
+
els.append(inj.bind(
|
|
75
|
+
_confirmation.ToolExecutionConfirmation,
|
|
76
|
+
to_ctor=_confirmation.InteractiveToolExecutionConfirmation,
|
|
77
|
+
singleton=True,
|
|
78
|
+
))
|
|
75
79
|
|
|
76
80
|
#
|
|
77
81
|
|