ommlds 0.0.0.dev490__py3-none-any.whl → 0.0.0.dev492__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 +9 -7
- 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 +42 -34
- 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} +7 -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 +5 -5
- 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 +12 -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/inject.py +1 -1
- ommlds/cli/sessions/chat/interfaces/textual/app.py +154 -103
- ommlds/cli/sessions/chat/interfaces/textual/inject.py +34 -9
- ommlds/cli/sessions/chat/interfaces/textual/interface.py +85 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/__init__.py +29 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/input.tcss +3 -1
- ommlds/cli/sessions/chat/interfaces/textual/styles/markdown.tcss +7 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss +131 -9
- ommlds/cli/sessions/chat/interfaces/textual/tools.py +37 -0
- 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 +164 -0
- ommlds/minichain/backends/impls/ollama/chat.py +50 -56
- ommlds/minichain/backends/impls/ollama/protocol.py +144 -0
- ommlds/minichain/backends/impls/openai/names.py +3 -1
- ommlds/nanochat/rustbpe/README.md +9 -0
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev492.dist-info}/METADATA +6 -6
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev492.dist-info}/RECORD +88 -78
- /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.dev492.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev492.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev492.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev490.dist-info → ommlds-0.0.0.dev492.dist-info}/top_level.txt +0 -0
ommlds/cli/main.py
CHANGED
|
@@ -36,7 +36,8 @@ def _process_main_extra_args(args: ap.Namespace) -> None:
|
|
|
36
36
|
logs.configure_standard_logging('DEBUG')
|
|
37
37
|
else:
|
|
38
38
|
logs.configure_standard_logging('INFO')
|
|
39
|
-
|
|
39
|
+
|
|
40
|
+
logs.silence_noisy_loggers()
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
##
|
|
@@ -69,10 +70,10 @@ class ChatProfile(Profile):
|
|
|
69
70
|
def configure_backend(self, cfg: ChatConfig) -> ChatConfig:
|
|
70
71
|
return dc.replace(
|
|
71
72
|
cfg,
|
|
72
|
-
|
|
73
|
-
cfg.
|
|
73
|
+
driver=dc.replace(
|
|
74
|
+
cfg.driver,
|
|
74
75
|
backend=dc.replace(
|
|
75
|
-
cfg.
|
|
76
|
+
cfg.driver.backend,
|
|
76
77
|
backend=self._args.backend,
|
|
77
78
|
),
|
|
78
79
|
),
|
|
@@ -104,10 +105,10 @@ class ChatProfile(Profile):
|
|
|
104
105
|
else:
|
|
105
106
|
cfg = dc.replace(
|
|
106
107
|
cfg,
|
|
107
|
-
|
|
108
|
-
cfg.
|
|
108
|
+
driver=dc.replace(
|
|
109
|
+
cfg.driver,
|
|
109
110
|
ai=dc.replace(
|
|
110
|
-
cfg.
|
|
111
|
+
cfg.driver.ai,
|
|
111
112
|
verbose=True,
|
|
112
113
|
),
|
|
113
114
|
),
|
|
@@ -133,10 +134,10 @@ class ChatProfile(Profile):
|
|
|
133
134
|
# TODO: '-' -> stdin
|
|
134
135
|
cfg = dc.replace(
|
|
135
136
|
cfg,
|
|
136
|
-
|
|
137
|
-
cfg.
|
|
137
|
+
driver=dc.replace(
|
|
138
|
+
cfg.driver,
|
|
138
139
|
user=dc.replace(
|
|
139
|
-
cfg.
|
|
140
|
+
cfg.driver.user,
|
|
140
141
|
initial_user_content=' '.join(self._args.message),
|
|
141
142
|
),
|
|
142
143
|
),
|
|
@@ -157,10 +158,10 @@ class ChatProfile(Profile):
|
|
|
157
158
|
def configure_state(self, cfg: ChatConfig) -> ChatConfig:
|
|
158
159
|
return dc.replace(
|
|
159
160
|
cfg,
|
|
160
|
-
|
|
161
|
-
cfg.
|
|
161
|
+
driver=dc.replace(
|
|
162
|
+
cfg.driver,
|
|
162
163
|
state=dc.replace(
|
|
163
|
-
cfg.
|
|
164
|
+
cfg.driver.state,
|
|
164
165
|
state='ephemeral' if self._args.ephemeral else 'new' if self._args.new else 'continue',
|
|
165
166
|
),
|
|
166
167
|
),
|
|
@@ -176,10 +177,10 @@ class ChatProfile(Profile):
|
|
|
176
177
|
def configure_output(self, cfg: ChatConfig) -> ChatConfig:
|
|
177
178
|
return dc.replace(
|
|
178
179
|
cfg,
|
|
179
|
-
|
|
180
|
-
cfg.
|
|
180
|
+
driver=dc.replace(
|
|
181
|
+
cfg.driver,
|
|
181
182
|
ai=dc.replace(
|
|
182
|
-
cfg.
|
|
183
|
+
cfg.driver.ai,
|
|
183
184
|
stream=bool(self._args.stream),
|
|
184
185
|
),
|
|
185
186
|
),
|
|
@@ -199,30 +200,37 @@ class ChatProfile(Profile):
|
|
|
199
200
|
]
|
|
200
201
|
|
|
201
202
|
def configure_tools(self, cfg: ChatConfig) -> ChatConfig:
|
|
203
|
+
if not (
|
|
204
|
+
self._args.enable_fs_tools or
|
|
205
|
+
self._args.enable_todo_tools or
|
|
206
|
+
# self._args.enable_unsafe_tools_do_not_use_lol or
|
|
207
|
+
self._args.enable_test_weather_tool or
|
|
208
|
+
self._args.code
|
|
209
|
+
):
|
|
210
|
+
return cfg
|
|
211
|
+
|
|
202
212
|
return dc.replace(
|
|
203
213
|
cfg,
|
|
204
|
-
|
|
205
|
-
cfg.
|
|
214
|
+
driver=dc.replace(
|
|
215
|
+
cfg.driver,
|
|
206
216
|
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
|
-
),
|
|
217
|
+
cfg.driver.ai,
|
|
218
|
+
enable_tools=True,
|
|
215
219
|
),
|
|
216
220
|
tools=dc.replace(
|
|
217
|
-
cfg.
|
|
221
|
+
cfg.driver.tools,
|
|
218
222
|
enabled_tools={ # noqa
|
|
219
|
-
*(cfg.
|
|
223
|
+
*(cfg.driver.tools.enabled_tools or []),
|
|
220
224
|
*(['fs'] if self._args.enable_fs_tools else []),
|
|
221
225
|
*(['todo'] if self._args.enable_todo_tools else []),
|
|
222
226
|
*(['weather'] if self._args.enable_test_weather_tool else []),
|
|
223
227
|
},
|
|
224
228
|
),
|
|
225
229
|
),
|
|
230
|
+
interface=dc.replace(
|
|
231
|
+
cfg.interface,
|
|
232
|
+
enable_tools=True,
|
|
233
|
+
),
|
|
226
234
|
)
|
|
227
235
|
|
|
228
236
|
#
|
|
@@ -237,10 +245,10 @@ class ChatProfile(Profile):
|
|
|
237
245
|
|
|
238
246
|
cfg = dc.replace(
|
|
239
247
|
cfg,
|
|
240
|
-
|
|
241
|
-
cfg.
|
|
248
|
+
driver=dc.replace(
|
|
249
|
+
cfg.driver,
|
|
242
250
|
ai=dc.replace(
|
|
243
|
-
cfg.
|
|
251
|
+
cfg.driver.ai,
|
|
244
252
|
enable_tools=True,
|
|
245
253
|
),
|
|
246
254
|
),
|
|
@@ -252,10 +260,10 @@ class ChatProfile(Profile):
|
|
|
252
260
|
|
|
253
261
|
cfg = dc.replace(
|
|
254
262
|
cfg,
|
|
255
|
-
|
|
256
|
-
cfg.
|
|
263
|
+
driver=dc.replace(
|
|
264
|
+
cfg.driver,
|
|
257
265
|
user=dc.replace(
|
|
258
|
-
cfg.
|
|
266
|
+
cfg.driver.user,
|
|
259
267
|
initial_system_content=system_content,
|
|
260
268
|
),
|
|
261
269
|
),
|
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()
|
|
@@ -3,6 +3,8 @@ TODO:
|
|
|
3
3
|
- lifecycles
|
|
4
4
|
- StreamService
|
|
5
5
|
"""
|
|
6
|
+
from omlish import lang
|
|
7
|
+
|
|
6
8
|
from ..... import minichain as mc
|
|
7
9
|
from .ai.types import AiChatGenerator
|
|
8
10
|
from .events.manager import ChatEventsManager
|
|
@@ -15,7 +17,11 @@ from .state.types import ChatStateManager
|
|
|
15
17
|
##
|
|
16
18
|
|
|
17
19
|
|
|
18
|
-
class
|
|
20
|
+
class ChatDriverGetter(lang.Func0['ChatDriver']):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ChatDriver:
|
|
19
25
|
def __init__(
|
|
20
26
|
self,
|
|
21
27
|
*,
|
|
@@ -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, _driver.ChatDriverGetter),
|
|
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(
|
|
33
|
-
await
|
|
32
|
+
async def add_initial_user_content(cd: '_driver.ChatDriver') -> None:
|
|
33
|
+
await cd.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
|
-
lambda
|
|
37
|
-
|
|
36
|
+
lambda cdg: ChatPhaseCallback(ChatPhase.STARTED, lambda: add_initial_user_content(cdg())),
|
|
37
|
+
cdg=_driver.ChatDriverGetter,
|
|
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,12 @@ class InteractiveBareChatInterface(ChatInterface):
|
|
|
36
36
|
except EOFError:
|
|
37
37
|
break
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
print()
|
|
40
|
+
print('<')
|
|
41
|
+
print()
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
await self._driver.send_user_messages([mc.UserMessage(s)])
|
|
44
|
+
|
|
45
|
+
print()
|
|
46
|
+
|
|
47
|
+
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
|
|
@@ -16,7 +16,7 @@ def bind_interface(cfg: InterfaceConfig = InterfaceConfig()) -> inj.Elements:
|
|
|
16
16
|
els: list[inj.Elemental] = []
|
|
17
17
|
|
|
18
18
|
if cfg.use_textual:
|
|
19
|
-
els.append(_textual.bind_textual())
|
|
19
|
+
els.append(_textual.bind_textual(cfg))
|
|
20
20
|
|
|
21
21
|
else:
|
|
22
22
|
els.append(_bare.bind_bare(cfg))
|