ommlds 0.0.0.dev490__py3-none-any.whl → 0.0.0.dev491__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/.omlish-manifests.json +3 -3
- ommlds/README.md +11 -0
- ommlds/__about__.py +1 -1
- ommlds/backends/ollama/_dataclasses.py +53 -23
- ommlds/backends/ollama/protocol.py +3 -0
- ommlds/cli/_dataclasses.py +439 -289
- ommlds/cli/main.py +40 -33
- ommlds/cli/rendering/types.py +6 -0
- ommlds/cli/sessions/chat/configs.py +2 -2
- ommlds/cli/sessions/chat/{agents → drivers}/ai/inject.py +3 -1
- ommlds/cli/sessions/chat/{agents → drivers}/configs.py +1 -1
- ommlds/cli/sessions/chat/{agents/agent.py → drivers/driver.py} +1 -1
- ommlds/cli/sessions/chat/{agents → drivers}/inject.py +13 -6
- ommlds/cli/sessions/chat/{agents → drivers}/tools/configs.py +0 -2
- ommlds/cli/sessions/chat/drivers/tools/confirmation.py +44 -0
- ommlds/cli/sessions/chat/{agents → drivers}/tools/execution.py +2 -3
- ommlds/cli/sessions/chat/{agents → drivers}/tools/inject.py +1 -13
- ommlds/cli/sessions/chat/{agents → drivers}/tools/rendering.py +1 -1
- ommlds/cli/sessions/chat/drivers/types.py +10 -0
- ommlds/cli/sessions/chat/{agents → drivers}/user/inject.py +3 -3
- ommlds/cli/sessions/chat/inject.py +2 -2
- ommlds/cli/sessions/chat/interfaces/bare/inject.py +23 -0
- ommlds/cli/sessions/chat/interfaces/bare/interactive.py +6 -6
- ommlds/cli/sessions/chat/interfaces/bare/oneshot.py +5 -5
- ommlds/cli/sessions/chat/{agents/tools/confirmation.py → interfaces/bare/tools.py} +2 -21
- ommlds/cli/sessions/chat/interfaces/bare/user.py +1 -1
- ommlds/cli/sessions/chat/interfaces/configs.py +8 -0
- ommlds/cli/sessions/chat/interfaces/textual/app.py +100 -94
- ommlds/cli/sessions/chat/interfaces/textual/inject.py +29 -5
- ommlds/cli/sessions/chat/interfaces/textual/styles/__init__.py +29 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/markdown.tcss +7 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss +72 -1
- ommlds/cli/sessions/chat/interfaces/textual/widgets/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/textual/widgets/input.py +36 -0
- ommlds/cli/sessions/chat/interfaces/textual/widgets/messages.py +114 -0
- ommlds/minichain/backends/impls/ollama/chat.py +24 -56
- ommlds/minichain/backends/impls/ollama/protocol.py +144 -0
- ommlds/nanochat/rustbpe/README.md +9 -0
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev491.dist-info}/METADATA +6 -6
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev491.dist-info}/RECORD +83 -74
- /ommlds/cli/sessions/chat/{agents → drivers}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/ai/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/ai/configs.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/ai/events.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/ai/injection.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/ai/rendering.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/ai/services.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/ai/tools.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/ai/types.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/events/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/events/inject.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/events/injection.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/events/manager.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/events/types.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/phases/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/phases/inject.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/phases/injection.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/phases/manager.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/phases/types.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/state/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/state/configs.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/state/inject.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/state/inmemory.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/state/storage.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/state/types.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/fs/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/fs/configs.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/fs/inject.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/injection.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/todo/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/todo/configs.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/todo/inject.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/weather/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/weather/configs.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/weather/inject.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/tools/weather/tools.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/user/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{agents → drivers}/user/configs.py +0 -0
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev491.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev491.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev491.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev491.dist-info}/top_level.txt +0 -0
ommlds/cli/main.py
CHANGED
|
@@ -69,10 +69,10 @@ class ChatProfile(Profile):
|
|
|
69
69
|
def configure_backend(self, cfg: ChatConfig) -> ChatConfig:
|
|
70
70
|
return dc.replace(
|
|
71
71
|
cfg,
|
|
72
|
-
|
|
73
|
-
cfg.
|
|
72
|
+
driver=dc.replace(
|
|
73
|
+
cfg.driver,
|
|
74
74
|
backend=dc.replace(
|
|
75
|
-
cfg.
|
|
75
|
+
cfg.driver.backend,
|
|
76
76
|
backend=self._args.backend,
|
|
77
77
|
),
|
|
78
78
|
),
|
|
@@ -104,10 +104,10 @@ class ChatProfile(Profile):
|
|
|
104
104
|
else:
|
|
105
105
|
cfg = dc.replace(
|
|
106
106
|
cfg,
|
|
107
|
-
|
|
108
|
-
cfg.
|
|
107
|
+
driver=dc.replace(
|
|
108
|
+
cfg.driver,
|
|
109
109
|
ai=dc.replace(
|
|
110
|
-
cfg.
|
|
110
|
+
cfg.driver.ai,
|
|
111
111
|
verbose=True,
|
|
112
112
|
),
|
|
113
113
|
),
|
|
@@ -133,10 +133,10 @@ class ChatProfile(Profile):
|
|
|
133
133
|
# TODO: '-' -> stdin
|
|
134
134
|
cfg = dc.replace(
|
|
135
135
|
cfg,
|
|
136
|
-
|
|
137
|
-
cfg.
|
|
136
|
+
driver=dc.replace(
|
|
137
|
+
cfg.driver,
|
|
138
138
|
user=dc.replace(
|
|
139
|
-
cfg.
|
|
139
|
+
cfg.driver.user,
|
|
140
140
|
initial_user_content=' '.join(self._args.message),
|
|
141
141
|
),
|
|
142
142
|
),
|
|
@@ -157,10 +157,10 @@ class ChatProfile(Profile):
|
|
|
157
157
|
def configure_state(self, cfg: ChatConfig) -> ChatConfig:
|
|
158
158
|
return dc.replace(
|
|
159
159
|
cfg,
|
|
160
|
-
|
|
161
|
-
cfg.
|
|
160
|
+
driver=dc.replace(
|
|
161
|
+
cfg.driver,
|
|
162
162
|
state=dc.replace(
|
|
163
|
-
cfg.
|
|
163
|
+
cfg.driver.state,
|
|
164
164
|
state='ephemeral' if self._args.ephemeral else 'new' if self._args.new else 'continue',
|
|
165
165
|
),
|
|
166
166
|
),
|
|
@@ -176,10 +176,10 @@ class ChatProfile(Profile):
|
|
|
176
176
|
def configure_output(self, cfg: ChatConfig) -> ChatConfig:
|
|
177
177
|
return dc.replace(
|
|
178
178
|
cfg,
|
|
179
|
-
|
|
180
|
-
cfg.
|
|
179
|
+
driver=dc.replace(
|
|
180
|
+
cfg.driver,
|
|
181
181
|
ai=dc.replace(
|
|
182
|
-
cfg.
|
|
182
|
+
cfg.driver.ai,
|
|
183
183
|
stream=bool(self._args.stream),
|
|
184
184
|
),
|
|
185
185
|
),
|
|
@@ -199,30 +199,37 @@ class ChatProfile(Profile):
|
|
|
199
199
|
]
|
|
200
200
|
|
|
201
201
|
def configure_tools(self, cfg: ChatConfig) -> ChatConfig:
|
|
202
|
+
if not (
|
|
203
|
+
self._args.enable_fs_tools or
|
|
204
|
+
self._args.enable_todo_tools or
|
|
205
|
+
# self._args.enable_unsafe_tools_do_not_use_lol or
|
|
206
|
+
self._args.enable_test_weather_tool or
|
|
207
|
+
self._args.code
|
|
208
|
+
):
|
|
209
|
+
return cfg
|
|
210
|
+
|
|
202
211
|
return dc.replace(
|
|
203
212
|
cfg,
|
|
204
|
-
|
|
205
|
-
cfg.
|
|
213
|
+
driver=dc.replace(
|
|
214
|
+
cfg.driver,
|
|
206
215
|
ai=dc.replace(
|
|
207
|
-
cfg.
|
|
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
|
-
),
|
|
216
|
+
cfg.driver.ai,
|
|
217
|
+
enable_tools=True,
|
|
215
218
|
),
|
|
216
219
|
tools=dc.replace(
|
|
217
|
-
cfg.
|
|
220
|
+
cfg.driver.tools,
|
|
218
221
|
enabled_tools={ # noqa
|
|
219
|
-
*(cfg.
|
|
222
|
+
*(cfg.driver.tools.enabled_tools or []),
|
|
220
223
|
*(['fs'] if self._args.enable_fs_tools else []),
|
|
221
224
|
*(['todo'] if self._args.enable_todo_tools else []),
|
|
222
225
|
*(['weather'] if self._args.enable_test_weather_tool else []),
|
|
223
226
|
},
|
|
224
227
|
),
|
|
225
228
|
),
|
|
229
|
+
interface=dc.replace(
|
|
230
|
+
cfg.interface,
|
|
231
|
+
enable_tools=True,
|
|
232
|
+
),
|
|
226
233
|
)
|
|
227
234
|
|
|
228
235
|
#
|
|
@@ -237,10 +244,10 @@ class ChatProfile(Profile):
|
|
|
237
244
|
|
|
238
245
|
cfg = dc.replace(
|
|
239
246
|
cfg,
|
|
240
|
-
|
|
241
|
-
cfg.
|
|
247
|
+
driver=dc.replace(
|
|
248
|
+
cfg.driver,
|
|
242
249
|
ai=dc.replace(
|
|
243
|
-
cfg.
|
|
250
|
+
cfg.driver.ai,
|
|
244
251
|
enable_tools=True,
|
|
245
252
|
),
|
|
246
253
|
),
|
|
@@ -252,10 +259,10 @@ class ChatProfile(Profile):
|
|
|
252
259
|
|
|
253
260
|
cfg = dc.replace(
|
|
254
261
|
cfg,
|
|
255
|
-
|
|
256
|
-
cfg.
|
|
262
|
+
driver=dc.replace(
|
|
263
|
+
cfg.driver,
|
|
257
264
|
user=dc.replace(
|
|
258
|
-
cfg.
|
|
265
|
+
cfg.driver.user,
|
|
259
266
|
initial_system_content=system_content,
|
|
260
267
|
),
|
|
261
268
|
),
|
ommlds/cli/rendering/types.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from omlish import dataclasses as dc
|
|
2
2
|
|
|
3
3
|
from ...rendering.configs import RenderingConfig
|
|
4
|
-
from .
|
|
4
|
+
from .drivers.configs import DriverConfig
|
|
5
5
|
from .interfaces.configs import InterfaceConfig
|
|
6
6
|
|
|
7
7
|
|
|
@@ -16,6 +16,6 @@ DEFAULT_BACKEND = 'openai'
|
|
|
16
16
|
|
|
17
17
|
@dc.dataclass(frozen=True, kw_only=True)
|
|
18
18
|
class ChatConfig:
|
|
19
|
-
|
|
19
|
+
driver: DriverConfig = DriverConfig()
|
|
20
20
|
interface: InterfaceConfig = InterfaceConfig()
|
|
21
21
|
rendering: RenderingConfig = RenderingConfig()
|
|
@@ -66,7 +66,9 @@ def bind_ai(cfg: AiConfig = AiConfig()) -> inj.Elements:
|
|
|
66
66
|
#
|
|
67
67
|
|
|
68
68
|
if cfg.enable_tools:
|
|
69
|
-
def _provide_tools_chat_choices_options_provider(
|
|
69
|
+
def _provide_tools_chat_choices_options_provider(
|
|
70
|
+
tc: mc.ToolCatalog,
|
|
71
|
+
) -> _services.ChatChoicesServiceOptionsProvider:
|
|
70
72
|
return _services.ChatChoicesServiceOptionsProvider(lambda: [
|
|
71
73
|
mc.Tool(tce.spec)
|
|
72
74
|
for tce in tc.by_name.values()
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
"""
|
|
2
2
|
TODO:
|
|
3
|
-
- private + expose(
|
|
3
|
+
- private + expose(ChatDriver)
|
|
4
4
|
"""
|
|
5
|
+
import uuid
|
|
6
|
+
|
|
5
7
|
from omlish import inject as inj
|
|
6
8
|
from omlish import lang
|
|
7
9
|
|
|
8
10
|
from ....backends.types import DefaultBackendName
|
|
9
11
|
from .configs import DEFAULT_BACKEND
|
|
10
|
-
from .configs import
|
|
12
|
+
from .configs import DriverConfig
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
with lang.auto_proxy_import(globals()):
|
|
14
16
|
from ....backends import inject as _backends
|
|
15
|
-
from . import
|
|
17
|
+
from . import driver as _driver
|
|
18
|
+
from . import types as _types
|
|
16
19
|
from .ai import inject as _ai
|
|
17
20
|
from .events import inject as _events
|
|
18
21
|
from .phases import inject as _phases
|
|
@@ -24,7 +27,7 @@ with lang.auto_proxy_import(globals()):
|
|
|
24
27
|
##
|
|
25
28
|
|
|
26
29
|
|
|
27
|
-
def
|
|
30
|
+
def bind_driver(cfg: DriverConfig) -> inj.Elements:
|
|
28
31
|
els: list[inj.Elemental] = []
|
|
29
32
|
|
|
30
33
|
#
|
|
@@ -48,9 +51,9 @@ def bind_agent(cfg: AgentConfig) -> inj.Elements:
|
|
|
48
51
|
#
|
|
49
52
|
|
|
50
53
|
els.extend([
|
|
51
|
-
inj.bind(
|
|
54
|
+
inj.bind(_driver.ChatDriver, singleton=True),
|
|
52
55
|
|
|
53
|
-
inj.bind_late(
|
|
56
|
+
inj.bind_late(_driver.ChatDriver),
|
|
54
57
|
])
|
|
55
58
|
|
|
56
59
|
#
|
|
@@ -59,4 +62,8 @@ def bind_agent(cfg: AgentConfig) -> inj.Elements:
|
|
|
59
62
|
|
|
60
63
|
#
|
|
61
64
|
|
|
65
|
+
els.append(inj.bind(_types.ChatDriverId(uuid.uuid4())))
|
|
66
|
+
|
|
67
|
+
#
|
|
68
|
+
|
|
62
69
|
return inj.as_elements(*els)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
from omlish import lang
|
|
5
|
+
|
|
6
|
+
from ...... import minichain as mc
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ToolExecutionRequestDeniedError(Exception):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ToolExecutionConfirmation(lang.Abstract):
|
|
17
|
+
@abc.abstractmethod
|
|
18
|
+
def confirm_tool_execution_or_raise(
|
|
19
|
+
self,
|
|
20
|
+
use: 'mc.ToolUse',
|
|
21
|
+
entry: 'mc.ToolCatalogEntry',
|
|
22
|
+
) -> ta.Awaitable[None]:
|
|
23
|
+
raise NotImplementedError
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AlwaysDenyToolExecutionConfirmation(ToolExecutionConfirmation):
|
|
30
|
+
async def confirm_tool_execution_or_raise(
|
|
31
|
+
self,
|
|
32
|
+
use: 'mc.ToolUse',
|
|
33
|
+
entry: 'mc.ToolCatalogEntry',
|
|
34
|
+
) -> None:
|
|
35
|
+
raise ToolExecutionRequestDeniedError
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class UnsafeAlwaysAllowToolExecutionConfirmation(ToolExecutionConfirmation):
|
|
39
|
+
async def confirm_tool_execution_or_raise(
|
|
40
|
+
self,
|
|
41
|
+
use: 'mc.ToolUse',
|
|
42
|
+
entry: 'mc.ToolCatalogEntry',
|
|
43
|
+
) -> None:
|
|
44
|
+
pass
|
|
@@ -37,7 +37,7 @@ class ToolUseExecutorImpl(ToolUseExecutor):
|
|
|
37
37
|
*,
|
|
38
38
|
catalog: 'mc.ToolCatalog',
|
|
39
39
|
ctx_provider: ToolContextProvider,
|
|
40
|
-
confirmation: ToolExecutionConfirmation
|
|
40
|
+
confirmation: ToolExecutionConfirmation,
|
|
41
41
|
) -> None:
|
|
42
42
|
super().__init__()
|
|
43
43
|
|
|
@@ -52,8 +52,7 @@ class ToolUseExecutorImpl(ToolUseExecutor):
|
|
|
52
52
|
) -> 'mc.ToolUseResultMessage':
|
|
53
53
|
tce = self._catalog.by_name[check.non_empty_str(use.name)]
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
await self._confirmation.confirm_tool_execution_or_raise(use, tce)
|
|
55
|
+
await self._confirmation.confirm_tool_execution_or_raise(use, tce)
|
|
57
56
|
|
|
58
57
|
return await mc.execute_tool_use(
|
|
59
58
|
mc.ToolContext(
|
|
@@ -10,7 +10,6 @@ from .injection import tool_context_providers
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
with lang.auto_proxy_import(globals()):
|
|
13
|
-
from . import confirmation as _confirmation
|
|
14
13
|
from . import execution as _execution
|
|
15
14
|
from . import rendering as _rendering
|
|
16
15
|
|
|
@@ -59,26 +58,15 @@ def bind_tools(cfg: ToolsConfig = ToolsConfig()) -> inj.Elements:
|
|
|
59
58
|
els.append(exec_stack.push_bind(to_ctor=_execution.ToolUseExecutorImpl, singleton=True))
|
|
60
59
|
|
|
61
60
|
if cfg.verbose:
|
|
61
|
+
els.append(exec_stack.push_bind(to_ctor=_rendering.ArgsRenderingToolUseExecutor, singleton=True))
|
|
62
62
|
els.append(exec_stack.push_bind(to_ctor=_rendering.ResultRenderingToolUseExecutor, singleton=True))
|
|
63
63
|
|
|
64
|
-
if cfg.dangerous_no_confirmation:
|
|
65
|
-
els.append(exec_stack.push_bind(to_ctor=_rendering.ArgsRenderingToolUseExecutor, singleton=True))
|
|
66
|
-
|
|
67
64
|
els.extend([
|
|
68
65
|
inj.bind(_execution.ToolUseExecutor, to_key=exec_stack.top),
|
|
69
66
|
])
|
|
70
67
|
|
|
71
68
|
#
|
|
72
69
|
|
|
73
|
-
if not cfg.dangerous_no_confirmation:
|
|
74
|
-
els.append(inj.bind(
|
|
75
|
-
_confirmation.ToolExecutionConfirmation,
|
|
76
|
-
to_ctor=_confirmation.InteractiveToolExecutionConfirmation,
|
|
77
|
-
singleton=True,
|
|
78
|
-
))
|
|
79
|
-
|
|
80
|
-
#
|
|
81
|
-
|
|
82
70
|
els.extend([
|
|
83
71
|
tool_context_providers().bind_items_provider(singleton=True),
|
|
84
72
|
|
|
@@ -9,7 +9,7 @@ from .configs import UserConfig
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
with lang.auto_proxy_import(globals()):
|
|
12
|
-
from .. import
|
|
12
|
+
from .. import driver as _driver
|
|
13
13
|
from ..state import types as _state
|
|
14
14
|
|
|
15
15
|
|
|
@@ -29,12 +29,12 @@ def bind_user(cfg: UserConfig = UserConfig()) -> inj.Elements:
|
|
|
29
29
|
)))
|
|
30
30
|
|
|
31
31
|
if cfg.initial_user_content is not None:
|
|
32
|
-
async def add_initial_user_content(ca: '
|
|
32
|
+
async def add_initial_user_content(ca: '_driver.ChatDriver') -> None:
|
|
33
33
|
await ca.send_user_messages([mc.UserMessage(cfg.initial_user_content)])
|
|
34
34
|
|
|
35
35
|
els.append(phase_callbacks().bind_item(to_fn=inj.KwargsTarget.of(
|
|
36
36
|
lambda ca: ChatPhaseCallback(ChatPhase.STARTED, lambda: add_initial_user_content(ca())),
|
|
37
|
-
ca=inj.Late[
|
|
37
|
+
ca=inj.Late[_driver.ChatDriver],
|
|
38
38
|
)))
|
|
39
39
|
|
|
40
40
|
return inj.as_elements(*els)
|
|
@@ -9,7 +9,7 @@ from .configs import ChatConfig
|
|
|
9
9
|
with lang.auto_proxy_import(globals()):
|
|
10
10
|
from ...rendering import inject as _rendering
|
|
11
11
|
from . import session as _session
|
|
12
|
-
from .
|
|
12
|
+
from .drivers import inject as _drivers
|
|
13
13
|
from .interfaces import inject as _interfaces
|
|
14
14
|
|
|
15
15
|
|
|
@@ -22,7 +22,7 @@ def bind_chat(cfg: ChatConfig) -> inj.Elements:
|
|
|
22
22
|
#
|
|
23
23
|
|
|
24
24
|
els.extend([
|
|
25
|
-
|
|
25
|
+
_drivers.bind_driver(cfg.driver),
|
|
26
26
|
|
|
27
27
|
_interfaces.bind_interface(cfg.interface),
|
|
28
28
|
|
|
@@ -8,8 +8,10 @@ from ..configs import InterfaceConfig
|
|
|
8
8
|
with lang.auto_proxy_import(globals()):
|
|
9
9
|
from .....inputs import asyncs as _inputs_asyncs
|
|
10
10
|
from .....inputs import sync as _inputs_sync
|
|
11
|
+
from ...drivers.tools import confirmation as _tools_confirmation
|
|
11
12
|
from . import interactive as _interactive
|
|
12
13
|
from . import oneshot as _oneshot
|
|
14
|
+
from . import tools as _tools
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
##
|
|
@@ -18,6 +20,8 @@ with lang.auto_proxy_import(globals()):
|
|
|
18
20
|
def bind_bare(cfg: InterfaceConfig = InterfaceConfig()) -> inj.Elements:
|
|
19
21
|
els: list[inj.Elemental] = []
|
|
20
22
|
|
|
23
|
+
#
|
|
24
|
+
|
|
21
25
|
if cfg.interactive:
|
|
22
26
|
els.extend([
|
|
23
27
|
inj.bind(_interactive.InteractiveBareChatInterface, singleton=True),
|
|
@@ -35,4 +39,23 @@ def bind_bare(cfg: InterfaceConfig = InterfaceConfig()) -> inj.Elements:
|
|
|
35
39
|
inj.bind(ChatInterface, to_key=_oneshot.OneshotBareChatInterface),
|
|
36
40
|
])
|
|
37
41
|
|
|
42
|
+
#
|
|
43
|
+
|
|
44
|
+
if cfg.enable_tools:
|
|
45
|
+
if cfg.dangerous_no_tool_confirmation:
|
|
46
|
+
els.append(inj.bind(
|
|
47
|
+
_tools_confirmation.ToolExecutionConfirmation,
|
|
48
|
+
to_ctor=_tools_confirmation.UnsafeAlwaysAllowToolExecutionConfirmation,
|
|
49
|
+
singleton=True,
|
|
50
|
+
))
|
|
51
|
+
|
|
52
|
+
else:
|
|
53
|
+
els.append(inj.bind(
|
|
54
|
+
_tools_confirmation.ToolExecutionConfirmation,
|
|
55
|
+
to_ctor=_tools.InteractiveToolExecutionConfirmation,
|
|
56
|
+
singleton=True,
|
|
57
|
+
))
|
|
58
|
+
|
|
59
|
+
#
|
|
60
|
+
|
|
38
61
|
return inj.as_elements(*els)
|
|
@@ -4,7 +4,7 @@ from ...... import minichain as mc
|
|
|
4
4
|
from .....inputs.asyncs import AsyncStringInput
|
|
5
5
|
from .....inputs.asyncs import SyncAsyncStringInput
|
|
6
6
|
from .....inputs.sync import InputSyncStringInput
|
|
7
|
-
from ...
|
|
7
|
+
from ...drivers.driver import ChatDriver
|
|
8
8
|
from ..base import ChatInterface
|
|
9
9
|
|
|
10
10
|
|
|
@@ -17,18 +17,18 @@ class InteractiveBareChatInterface(ChatInterface):
|
|
|
17
17
|
def __init__(
|
|
18
18
|
self,
|
|
19
19
|
*,
|
|
20
|
-
|
|
20
|
+
driver: ChatDriver,
|
|
21
21
|
string_input: AsyncStringInput | None = None,
|
|
22
22
|
) -> None:
|
|
23
23
|
super().__init__()
|
|
24
24
|
|
|
25
|
-
self.
|
|
25
|
+
self._driver = driver
|
|
26
26
|
if string_input is None:
|
|
27
27
|
string_input = self.DEFAULT_STRING_INPUT
|
|
28
28
|
self._string_input = string_input
|
|
29
29
|
|
|
30
30
|
async def run(self) -> None:
|
|
31
|
-
await self.
|
|
31
|
+
await self._driver.start()
|
|
32
32
|
|
|
33
33
|
while True:
|
|
34
34
|
try:
|
|
@@ -36,6 +36,6 @@ class InteractiveBareChatInterface(ChatInterface):
|
|
|
36
36
|
except EOFError:
|
|
37
37
|
break
|
|
38
38
|
|
|
39
|
-
await self.
|
|
39
|
+
await self._driver.send_user_messages([mc.UserMessage(s)])
|
|
40
40
|
|
|
41
|
-
await self.
|
|
41
|
+
await self._driver.stop()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from ...
|
|
1
|
+
from ...drivers.driver import ChatDriver
|
|
2
2
|
from ..base import ChatInterface
|
|
3
3
|
|
|
4
4
|
|
|
@@ -9,13 +9,13 @@ class OneshotBareChatInterface(ChatInterface):
|
|
|
9
9
|
def __init__(
|
|
10
10
|
self,
|
|
11
11
|
*,
|
|
12
|
-
|
|
12
|
+
driver: ChatDriver,
|
|
13
13
|
) -> None:
|
|
14
14
|
super().__init__()
|
|
15
15
|
|
|
16
|
-
self.
|
|
16
|
+
self._driver = driver
|
|
17
17
|
|
|
18
18
|
async def run(self) -> None:
|
|
19
|
-
await self.
|
|
19
|
+
await self._driver.start()
|
|
20
20
|
|
|
21
|
-
await self.
|
|
21
|
+
await self._driver.stop()
|
|
@@ -1,28 +1,9 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import typing as ta
|
|
3
|
-
|
|
4
|
-
from omlish import lang
|
|
5
1
|
from omlish.formats import json
|
|
6
2
|
from omlish.term.confirm import confirm_action
|
|
7
3
|
|
|
8
4
|
from ...... import minichain as mc
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class ToolExecutionRequestDeniedError(Exception):
|
|
15
|
-
pass
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class ToolExecutionConfirmation(lang.Abstract):
|
|
19
|
-
@abc.abstractmethod
|
|
20
|
-
def confirm_tool_execution_or_raise(
|
|
21
|
-
self,
|
|
22
|
-
use: 'mc.ToolUse',
|
|
23
|
-
entry: 'mc.ToolCatalogEntry',
|
|
24
|
-
) -> ta.Awaitable[None]:
|
|
25
|
-
raise NotImplementedError
|
|
5
|
+
from ...drivers.tools.confirmation import ToolExecutionConfirmation
|
|
6
|
+
from ...drivers.tools.confirmation import ToolExecutionRequestDeniedError
|
|
26
7
|
|
|
27
8
|
|
|
28
9
|
##
|
|
@@ -4,7 +4,7 @@ from ...... import minichain as mc
|
|
|
4
4
|
from .....inputs.asyncs import AsyncStringInput
|
|
5
5
|
from .....inputs.asyncs import SyncAsyncStringInput
|
|
6
6
|
from .....inputs.sync import InputSyncStringInput
|
|
7
|
-
from ...
|
|
7
|
+
from ...drivers.user.types import UserChatInput
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
##
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- obviously, subclasses of InterfaceConfig
|
|
4
|
+
- this is really just another instance of the whole `argparse -> config -> inject` flow
|
|
5
|
+
"""
|
|
1
6
|
import typing as ta
|
|
2
7
|
|
|
3
8
|
from omlish import dataclasses as dc
|
|
@@ -13,3 +18,6 @@ class InterfaceConfig:
|
|
|
13
18
|
use_textual: bool = False
|
|
14
19
|
|
|
15
20
|
use_readline: bool | ta.Literal['auto'] = 'auto'
|
|
21
|
+
|
|
22
|
+
enable_tools: bool = False
|
|
23
|
+
dangerous_no_tool_confirmation: bool = False
|