ommlds 0.0.0.dev440__py3-none-any.whl → 0.0.0.dev480__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 +332 -35
- ommlds/__about__.py +15 -9
- ommlds/_hacks/__init__.py +4 -0
- ommlds/_hacks/funcs.py +110 -0
- ommlds/_hacks/names.py +158 -0
- ommlds/_hacks/params.py +73 -0
- ommlds/_hacks/patches.py +0 -3
- ommlds/backends/anthropic/protocol/_marshal.py +2 -2
- ommlds/backends/anthropic/protocol/sse/_marshal.py +1 -1
- ommlds/backends/anthropic/protocol/sse/assemble.py +23 -7
- ommlds/backends/anthropic/protocol/sse/events.py +13 -0
- ommlds/backends/anthropic/protocol/types.py +30 -9
- ommlds/backends/google/protocol/__init__.py +3 -0
- ommlds/backends/google/protocol/_marshal.py +16 -0
- ommlds/backends/google/protocol/types.py +626 -0
- ommlds/backends/groq/_marshal.py +23 -0
- ommlds/backends/groq/protocol.py +249 -0
- ommlds/backends/mlx/generation.py +1 -1
- ommlds/backends/mlx/loading.py +58 -1
- ommlds/backends/ollama/__init__.py +0 -0
- ommlds/backends/ollama/protocol.py +170 -0
- ommlds/backends/openai/protocol/__init__.py +9 -28
- ommlds/backends/openai/protocol/_common.py +18 -0
- ommlds/backends/openai/protocol/_marshal.py +27 -0
- ommlds/backends/openai/protocol/chatcompletion/chunk.py +58 -31
- ommlds/backends/openai/protocol/chatcompletion/contentpart.py +49 -44
- ommlds/backends/openai/protocol/chatcompletion/message.py +55 -43
- ommlds/backends/openai/protocol/chatcompletion/request.py +114 -66
- ommlds/backends/openai/protocol/chatcompletion/response.py +71 -45
- ommlds/backends/openai/protocol/chatcompletion/responseformat.py +27 -20
- ommlds/backends/openai/protocol/chatcompletion/tokenlogprob.py +16 -7
- ommlds/backends/openai/protocol/completionusage.py +24 -15
- ommlds/backends/tavily/__init__.py +0 -0
- ommlds/backends/tavily/protocol.py +301 -0
- ommlds/backends/tinygrad/models/llama3/__init__.py +22 -14
- ommlds/backends/transformers/__init__.py +0 -0
- ommlds/backends/transformers/filecache.py +109 -0
- ommlds/backends/transformers/streamers.py +73 -0
- ommlds/cli/asyncs.py +30 -0
- ommlds/cli/backends/catalog.py +93 -0
- ommlds/cli/backends/configs.py +9 -0
- ommlds/cli/backends/inject.py +31 -36
- ommlds/cli/backends/injection.py +16 -0
- ommlds/cli/backends/types.py +46 -0
- ommlds/cli/content/__init__.py +0 -0
- ommlds/cli/content/messages.py +34 -0
- ommlds/cli/content/strings.py +42 -0
- ommlds/cli/inject.py +15 -32
- ommlds/cli/inputs/__init__.py +0 -0
- ommlds/cli/inputs/asyncs.py +32 -0
- ommlds/cli/inputs/sync.py +75 -0
- ommlds/cli/main.py +270 -110
- ommlds/cli/rendering/__init__.py +0 -0
- ommlds/cli/rendering/configs.py +9 -0
- ommlds/cli/rendering/inject.py +31 -0
- ommlds/cli/rendering/markdown.py +52 -0
- ommlds/cli/rendering/raw.py +73 -0
- ommlds/cli/rendering/types.py +21 -0
- ommlds/cli/secrets.py +21 -0
- ommlds/cli/sessions/base.py +1 -1
- ommlds/cli/sessions/chat/chat/__init__.py +0 -0
- ommlds/cli/sessions/chat/chat/ai/__init__.py +0 -0
- ommlds/cli/sessions/chat/chat/ai/configs.py +11 -0
- ommlds/cli/sessions/chat/chat/ai/inject.py +74 -0
- ommlds/cli/sessions/chat/chat/ai/injection.py +14 -0
- ommlds/cli/sessions/chat/chat/ai/rendering.py +70 -0
- ommlds/cli/sessions/chat/chat/ai/services.py +79 -0
- ommlds/cli/sessions/chat/chat/ai/tools.py +44 -0
- ommlds/cli/sessions/chat/chat/ai/types.py +28 -0
- ommlds/cli/sessions/chat/chat/state/__init__.py +0 -0
- ommlds/cli/sessions/chat/chat/state/configs.py +11 -0
- ommlds/cli/sessions/chat/chat/state/inject.py +36 -0
- ommlds/cli/sessions/chat/chat/state/inmemory.py +33 -0
- ommlds/cli/sessions/chat/chat/state/storage.py +52 -0
- ommlds/cli/sessions/chat/chat/state/types.py +38 -0
- ommlds/cli/sessions/chat/chat/user/__init__.py +0 -0
- ommlds/cli/sessions/chat/chat/user/configs.py +17 -0
- ommlds/cli/sessions/chat/chat/user/inject.py +62 -0
- ommlds/cli/sessions/chat/chat/user/interactive.py +31 -0
- ommlds/cli/sessions/chat/chat/user/oneshot.py +25 -0
- ommlds/cli/sessions/chat/chat/user/types.py +15 -0
- ommlds/cli/sessions/chat/configs.py +27 -0
- ommlds/cli/sessions/chat/driver.py +43 -0
- ommlds/cli/sessions/chat/inject.py +33 -65
- ommlds/cli/sessions/chat/phases/__init__.py +0 -0
- ommlds/cli/sessions/chat/phases/inject.py +27 -0
- ommlds/cli/sessions/chat/phases/injection.py +14 -0
- ommlds/cli/sessions/chat/phases/manager.py +29 -0
- ommlds/cli/sessions/chat/phases/types.py +29 -0
- ommlds/cli/sessions/chat/session.py +27 -0
- ommlds/cli/sessions/chat/tools/__init__.py +0 -0
- ommlds/cli/sessions/chat/tools/configs.py +22 -0
- ommlds/cli/sessions/chat/tools/confirmation.py +46 -0
- ommlds/cli/sessions/chat/tools/execution.py +66 -0
- ommlds/cli/sessions/chat/tools/fs/__init__.py +0 -0
- ommlds/cli/sessions/chat/tools/fs/configs.py +12 -0
- ommlds/cli/sessions/chat/tools/fs/inject.py +35 -0
- ommlds/cli/sessions/chat/tools/inject.py +88 -0
- ommlds/cli/sessions/chat/tools/injection.py +44 -0
- ommlds/cli/sessions/chat/tools/rendering.py +58 -0
- ommlds/cli/sessions/chat/tools/todo/__init__.py +0 -0
- ommlds/cli/sessions/chat/tools/todo/configs.py +12 -0
- ommlds/cli/sessions/chat/tools/todo/inject.py +31 -0
- ommlds/cli/sessions/chat/tools/weather/__init__.py +0 -0
- ommlds/cli/sessions/chat/tools/weather/configs.py +12 -0
- ommlds/cli/sessions/chat/tools/weather/inject.py +22 -0
- ommlds/cli/{tools/weather.py → sessions/chat/tools/weather/tools.py} +1 -1
- ommlds/cli/sessions/completion/configs.py +21 -0
- ommlds/cli/sessions/completion/inject.py +42 -0
- ommlds/cli/sessions/completion/session.py +35 -0
- ommlds/cli/sessions/embedding/configs.py +21 -0
- ommlds/cli/sessions/embedding/inject.py +42 -0
- ommlds/cli/sessions/embedding/session.py +33 -0
- ommlds/cli/sessions/inject.py +28 -11
- ommlds/cli/state/__init__.py +0 -0
- ommlds/cli/state/inject.py +28 -0
- ommlds/cli/{state.py → state/storage.py} +41 -24
- ommlds/minichain/__init__.py +84 -24
- ommlds/minichain/_marshal.py +49 -9
- ommlds/minichain/_typedvalues.py +2 -4
- ommlds/minichain/backends/catalogs/base.py +20 -1
- ommlds/minichain/backends/catalogs/simple.py +2 -2
- ommlds/minichain/backends/catalogs/strings.py +10 -8
- ommlds/minichain/backends/impls/anthropic/chat.py +65 -27
- ommlds/minichain/backends/impls/anthropic/names.py +10 -8
- ommlds/minichain/backends/impls/anthropic/protocol.py +109 -0
- ommlds/minichain/backends/impls/anthropic/stream.py +111 -43
- ommlds/minichain/backends/impls/duckduckgo/search.py +1 -1
- ommlds/minichain/backends/impls/dummy/__init__.py +0 -0
- ommlds/minichain/backends/impls/dummy/chat.py +69 -0
- ommlds/minichain/backends/impls/google/chat.py +114 -22
- ommlds/minichain/backends/impls/google/search.py +7 -2
- ommlds/minichain/backends/impls/google/stream.py +219 -0
- ommlds/minichain/backends/impls/google/tools.py +149 -0
- ommlds/minichain/backends/impls/groq/__init__.py +0 -0
- ommlds/minichain/backends/impls/groq/chat.py +75 -0
- ommlds/minichain/backends/impls/groq/names.py +48 -0
- ommlds/minichain/backends/impls/groq/protocol.py +143 -0
- ommlds/minichain/backends/impls/groq/stream.py +125 -0
- ommlds/minichain/backends/impls/llamacpp/chat.py +33 -18
- ommlds/minichain/backends/impls/llamacpp/completion.py +1 -1
- ommlds/minichain/backends/impls/llamacpp/format.py +4 -2
- ommlds/minichain/backends/impls/llamacpp/stream.py +37 -20
- ommlds/minichain/backends/impls/mistral.py +20 -5
- ommlds/minichain/backends/impls/mlx/chat.py +96 -22
- ommlds/minichain/backends/impls/ollama/__init__.py +0 -0
- ommlds/minichain/backends/impls/ollama/chat.py +199 -0
- ommlds/minichain/backends/impls/openai/chat.py +18 -8
- ommlds/minichain/backends/impls/openai/completion.py +10 -3
- ommlds/minichain/backends/impls/openai/embedding.py +10 -3
- ommlds/minichain/backends/impls/openai/format.py +131 -106
- ommlds/minichain/backends/impls/openai/names.py +31 -5
- ommlds/minichain/backends/impls/openai/stream.py +43 -25
- ommlds/minichain/backends/impls/tavily.py +66 -0
- ommlds/minichain/backends/impls/tinygrad/chat.py +23 -16
- ommlds/minichain/backends/impls/transformers/sentence.py +1 -1
- ommlds/minichain/backends/impls/transformers/tokens.py +1 -1
- ommlds/minichain/backends/impls/transformers/transformers.py +155 -34
- ommlds/minichain/backends/strings/parsing.py +1 -1
- ommlds/minichain/backends/strings/resolving.py +4 -1
- ommlds/minichain/chat/_marshal.py +16 -9
- ommlds/minichain/chat/choices/adapters.py +4 -4
- ommlds/minichain/chat/choices/services.py +1 -1
- ommlds/minichain/chat/choices/stream/__init__.py +0 -0
- ommlds/minichain/chat/choices/stream/adapters.py +35 -0
- ommlds/minichain/chat/choices/stream/joining.py +31 -0
- ommlds/minichain/chat/choices/stream/services.py +45 -0
- ommlds/minichain/chat/choices/stream/types.py +43 -0
- ommlds/minichain/chat/choices/types.py +2 -2
- ommlds/minichain/chat/history.py +3 -3
- ommlds/minichain/chat/messages.py +55 -19
- ommlds/minichain/chat/services.py +3 -3
- ommlds/minichain/chat/stream/_marshal.py +16 -0
- ommlds/minichain/chat/stream/joining.py +85 -0
- ommlds/minichain/chat/stream/services.py +15 -21
- ommlds/minichain/chat/stream/types.py +32 -19
- ommlds/minichain/chat/tools/execution.py +8 -7
- ommlds/minichain/chat/tools/ids.py +9 -15
- ommlds/minichain/chat/tools/parsing.py +17 -26
- ommlds/minichain/chat/transforms/base.py +29 -38
- ommlds/minichain/chat/transforms/metadata.py +30 -4
- ommlds/minichain/chat/transforms/services.py +9 -11
- ommlds/minichain/content/_marshal.py +44 -20
- ommlds/minichain/content/json.py +13 -0
- ommlds/minichain/content/materialize.py +14 -21
- ommlds/minichain/content/prepare.py +4 -0
- ommlds/minichain/content/transforms/interleave.py +1 -1
- ommlds/minichain/content/transforms/squeeze.py +1 -1
- ommlds/minichain/content/transforms/stringify.py +1 -1
- ommlds/minichain/json.py +20 -0
- ommlds/minichain/lib/code/__init__.py +0 -0
- ommlds/minichain/lib/code/prompts.py +6 -0
- ommlds/minichain/lib/fs/binfiles.py +108 -0
- ommlds/minichain/lib/fs/context.py +126 -0
- ommlds/minichain/lib/fs/errors.py +101 -0
- ommlds/minichain/lib/fs/suggestions.py +36 -0
- ommlds/minichain/lib/fs/tools/__init__.py +0 -0
- ommlds/minichain/lib/fs/tools/edit.py +104 -0
- ommlds/minichain/lib/fs/tools/ls.py +38 -0
- ommlds/minichain/lib/fs/tools/read.py +115 -0
- ommlds/minichain/lib/fs/tools/recursivels/__init__.py +0 -0
- ommlds/minichain/lib/fs/tools/recursivels/execution.py +40 -0
- ommlds/minichain/lib/todo/__init__.py +0 -0
- ommlds/minichain/lib/todo/context.py +54 -0
- ommlds/minichain/lib/todo/tools/__init__.py +0 -0
- ommlds/minichain/lib/todo/tools/read.py +44 -0
- ommlds/minichain/lib/todo/tools/write.py +335 -0
- ommlds/minichain/lib/todo/types.py +60 -0
- ommlds/minichain/llms/_marshal.py +25 -17
- ommlds/minichain/llms/types.py +4 -0
- ommlds/minichain/registries/globals.py +18 -4
- ommlds/minichain/resources.py +66 -43
- ommlds/minichain/search.py +1 -1
- ommlds/minichain/services/_marshal.py +46 -39
- ommlds/minichain/services/facades.py +3 -3
- ommlds/minichain/services/services.py +1 -1
- ommlds/minichain/standard.py +8 -0
- ommlds/minichain/stream/services.py +152 -38
- ommlds/minichain/stream/wrap.py +22 -24
- ommlds/minichain/tools/_marshal.py +1 -1
- ommlds/minichain/tools/execution/catalog.py +2 -1
- ommlds/minichain/tools/execution/context.py +34 -14
- ommlds/minichain/tools/execution/errors.py +15 -0
- ommlds/minichain/tools/execution/executors.py +8 -3
- ommlds/minichain/tools/execution/reflect.py +40 -5
- ommlds/minichain/tools/fns.py +46 -9
- ommlds/minichain/tools/jsonschema.py +14 -5
- ommlds/minichain/tools/reflect.py +54 -18
- ommlds/minichain/tools/types.py +33 -1
- ommlds/minichain/utils.py +27 -0
- ommlds/minichain/vectors/_marshal.py +11 -10
- ommlds/nanochat/LICENSE +21 -0
- ommlds/nanochat/__init__.py +0 -0
- ommlds/nanochat/rustbpe/LICENSE +21 -0
- ommlds/nanochat/tokenizers.py +406 -0
- ommlds/server/server.py +3 -3
- ommlds/specs/__init__.py +0 -0
- ommlds/specs/mcp/__init__.py +0 -0
- ommlds/specs/mcp/_marshal.py +23 -0
- ommlds/specs/mcp/protocol.py +266 -0
- ommlds/tools/git.py +27 -10
- ommlds/tools/ocr.py +8 -9
- ommlds/wiki/analyze.py +2 -2
- ommlds/wiki/text/mfh.py +1 -5
- ommlds/wiki/text/wtp.py +1 -3
- ommlds/wiki/utils/xml.py +5 -5
- {ommlds-0.0.0.dev440.dist-info → ommlds-0.0.0.dev480.dist-info}/METADATA +24 -21
- ommlds-0.0.0.dev480.dist-info/RECORD +427 -0
- ommlds/cli/backends/standard.py +0 -20
- ommlds/cli/sessions/chat/base.py +0 -42
- ommlds/cli/sessions/chat/interactive.py +0 -73
- ommlds/cli/sessions/chat/printing.py +0 -96
- ommlds/cli/sessions/chat/prompt.py +0 -143
- ommlds/cli/sessions/chat/state.py +0 -109
- ommlds/cli/sessions/chat/tools.py +0 -91
- ommlds/cli/sessions/completion/completion.py +0 -44
- ommlds/cli/sessions/embedding/embedding.py +0 -42
- ommlds/cli/tools/config.py +0 -13
- ommlds/cli/tools/inject.py +0 -64
- ommlds/minichain/chat/stream/adapters.py +0 -69
- ommlds/minichain/lib/fs/ls/execution.py +0 -32
- ommlds-0.0.0.dev440.dist-info/RECORD +0 -303
- /ommlds/{cli/tools → backends/google}/__init__.py +0 -0
- /ommlds/{minichain/lib/fs/ls → backends/groq}/__init__.py +0 -0
- /ommlds/{huggingface.py → backends/huggingface.py} +0 -0
- /ommlds/minichain/lib/fs/{ls → tools/recursivels}/rendering.py +0 -0
- /ommlds/minichain/lib/fs/{ls → tools/recursivels}/running.py +0 -0
- {ommlds-0.0.0.dev440.dist-info → ommlds-0.0.0.dev480.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev440.dist-info → ommlds-0.0.0.dev480.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev440.dist-info → ommlds-0.0.0.dev480.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev440.dist-info → ommlds-0.0.0.dev480.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from ...... import minichain as mc
|
|
4
|
+
from .types import UserChatInput
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
OneshotUserChatInputInitialChat = ta.NewType('OneshotUserChatInputInitialChat', mc.UserChat)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class OneshotUserChatInput(UserChatInput):
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
initial_chat: OneshotUserChatInputInitialChat,
|
|
17
|
+
) -> None:
|
|
18
|
+
super().__init__()
|
|
19
|
+
|
|
20
|
+
self._pending_chat: mc.UserChat | None = initial_chat
|
|
21
|
+
|
|
22
|
+
async def get_next_user_messages(self) -> 'mc.UserChat':
|
|
23
|
+
ret = self._pending_chat
|
|
24
|
+
self._pending_chat = None
|
|
25
|
+
return ret or []
|
|
@@ -0,0 +1,15 @@
|
|
|
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 UserChatInput(lang.Abstract):
|
|
13
|
+
@abc.abstractmethod
|
|
14
|
+
def get_next_user_messages(self) -> ta.Awaitable['mc.UserChat']:
|
|
15
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from omlish import dataclasses as dc
|
|
2
|
+
|
|
3
|
+
from ...backends.configs import BackendConfig
|
|
4
|
+
from ...rendering.configs import RenderingConfig
|
|
5
|
+
from .chat.ai.configs import AiConfig
|
|
6
|
+
from .chat.state.configs import StateConfig
|
|
7
|
+
from .chat.user.configs import UserConfig
|
|
8
|
+
from .tools.configs import ToolsConfig
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
DEFAULT_BACKEND = 'openai'
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
|
21
|
+
class ChatConfig:
|
|
22
|
+
backend: BackendConfig = BackendConfig()
|
|
23
|
+
ai: AiConfig = AiConfig()
|
|
24
|
+
state: StateConfig = StateConfig()
|
|
25
|
+
user: UserConfig = UserConfig()
|
|
26
|
+
rendering: RenderingConfig = RenderingConfig()
|
|
27
|
+
tools: ToolsConfig = ToolsConfig()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from .chat.ai.types import AiChatGenerator
|
|
2
|
+
from .chat.state.types import ChatStateManager
|
|
3
|
+
from .chat.user.types import UserChatInput
|
|
4
|
+
from .phases.manager import ChatPhaseManager
|
|
5
|
+
from .phases.types import ChatPhase
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ChatDriver:
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
*,
|
|
15
|
+
phases: ChatPhaseManager,
|
|
16
|
+
ai_chat_generator: AiChatGenerator,
|
|
17
|
+
user_chat_input: UserChatInput,
|
|
18
|
+
chat_state_manager: ChatStateManager,
|
|
19
|
+
):
|
|
20
|
+
super().__init__()
|
|
21
|
+
|
|
22
|
+
self._phases = phases
|
|
23
|
+
self._ai_chat_generator = ai_chat_generator
|
|
24
|
+
self._user_chat_input = user_chat_input
|
|
25
|
+
self._chat_state_manager = chat_state_manager
|
|
26
|
+
|
|
27
|
+
async def run(self) -> None:
|
|
28
|
+
await self._phases.set_phase(ChatPhase.STARTING)
|
|
29
|
+
await self._phases.set_phase(ChatPhase.STARTED)
|
|
30
|
+
|
|
31
|
+
while True:
|
|
32
|
+
next_user_chat = await self._user_chat_input.get_next_user_messages()
|
|
33
|
+
if not next_user_chat:
|
|
34
|
+
break
|
|
35
|
+
|
|
36
|
+
prev_user_chat = (await self._chat_state_manager.get_state()).chat
|
|
37
|
+
|
|
38
|
+
next_ai_chat = await self._ai_chat_generator.get_next_ai_messages([*prev_user_chat, *next_user_chat])
|
|
39
|
+
|
|
40
|
+
await self._chat_state_manager.extend_chat([*next_user_chat, *next_ai_chat])
|
|
41
|
+
|
|
42
|
+
await self._phases.set_phase(ChatPhase.STOPPING)
|
|
43
|
+
await self._phases.set_phase(ChatPhase.STOPPED)
|
|
@@ -1,97 +1,65 @@
|
|
|
1
|
-
import typing as ta
|
|
2
|
-
|
|
3
1
|
from omlish import dataclasses as dc
|
|
4
2
|
from omlish import inject as inj
|
|
5
3
|
from omlish import lang
|
|
6
4
|
|
|
7
|
-
from .
|
|
8
|
-
from
|
|
9
|
-
from .
|
|
10
|
-
from .
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from .
|
|
17
|
-
from .
|
|
18
|
-
from .
|
|
19
|
-
from .
|
|
5
|
+
from ...backends.types import DefaultBackendName
|
|
6
|
+
from ..base import Session
|
|
7
|
+
from .configs import DEFAULT_BACKEND
|
|
8
|
+
from .configs import ChatConfig
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
with lang.auto_proxy_import(globals()):
|
|
12
|
+
from ...backends import inject as _backends
|
|
13
|
+
from ...rendering import inject as _rendering
|
|
14
|
+
from . import driver as _driver
|
|
15
|
+
from . import session as _session
|
|
16
|
+
from .chat.ai import inject as _chat_ai
|
|
17
|
+
from .chat.state import inject as _chat_state
|
|
18
|
+
from .chat.user import inject as _chat_user
|
|
19
|
+
from .phases import inject as _phases
|
|
20
|
+
from .tools import inject as _tools
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
##
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
v: ChatOptions
|
|
26
|
+
def bind_chat(cfg: ChatConfig) -> inj.Elements:
|
|
27
|
+
els: list[inj.Elemental] = []
|
|
28
28
|
|
|
29
|
+
#
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
els.extend([
|
|
32
|
+
_backends.bind_backends(cfg.backend),
|
|
32
33
|
|
|
34
|
+
_chat_ai.bind_ai(cfg.ai),
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
_chat_user.bind_user(cfg.user),
|
|
35
37
|
|
|
38
|
+
_chat_state.bind_state(cfg.state),
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
els: list[inj.Elemental] = []
|
|
40
|
+
_phases.bind_phases(),
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
_rendering.bind_rendering(cfg.rendering),
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
inj.set_binder[_InjectedChatOptions](),
|
|
44
|
-
inj.bind(
|
|
45
|
-
lang.typed_lambda(ChatOptions, s=ta.AbstractSet[_InjectedChatOptions])(
|
|
46
|
-
lambda s: ChatOptions([
|
|
47
|
-
co
|
|
48
|
-
for ico in s
|
|
49
|
-
for co in ico.v
|
|
50
|
-
]),
|
|
51
|
-
),
|
|
52
|
-
singleton=True,
|
|
53
|
-
),
|
|
44
|
+
_tools.bind_tools(cfg.tools),
|
|
54
45
|
])
|
|
55
46
|
|
|
56
47
|
#
|
|
57
48
|
|
|
58
49
|
els.extend([
|
|
59
|
-
inj.bind(
|
|
60
|
-
inj.bind(ChatStateManager, to_key=StateStorageChatStateManager),
|
|
50
|
+
inj.bind(_driver.ChatDriver, singleton=True),
|
|
61
51
|
])
|
|
62
52
|
|
|
63
53
|
#
|
|
64
54
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
])
|
|
70
|
-
else:
|
|
71
|
-
els.extend([
|
|
72
|
-
inj.bind(SimpleStringChatSessionPrinter, singleton=True),
|
|
73
|
-
inj.bind(ChatSessionPrinter, to_key=SimpleStringChatSessionPrinter),
|
|
74
|
-
])
|
|
75
|
-
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
-
if cfg.dangerous_no_tool_confirmation:
|
|
79
|
-
els.extend([
|
|
80
|
-
inj.bind(NopToolExecutionConfirmation, singleton=True),
|
|
81
|
-
inj.bind(ToolExecutionConfirmation, to_key=NopToolExecutionConfirmation),
|
|
82
|
-
])
|
|
83
|
-
else:
|
|
84
|
-
els.extend([
|
|
85
|
-
inj.bind(AskingToolExecutionConfirmation, singleton=True),
|
|
86
|
-
inj.bind(ToolExecutionConfirmation, to_key=AskingToolExecutionConfirmation),
|
|
87
|
-
])
|
|
55
|
+
els.extend([
|
|
56
|
+
inj.bind(_session.ChatSession.Config(**dc.asdict(cfg))),
|
|
57
|
+
inj.bind(Session, to_ctor=_session.ChatSession, singleton=True),
|
|
58
|
+
])
|
|
88
59
|
|
|
89
60
|
#
|
|
90
61
|
|
|
91
|
-
els.
|
|
92
|
-
inj.bind(ToolExecRequestExecutorImpl, singleton=True),
|
|
93
|
-
inj.bind(ToolExecRequestExecutor, to_key=ToolExecRequestExecutorImpl),
|
|
94
|
-
])
|
|
62
|
+
els.append(inj.bind(DefaultBackendName, to_const=DEFAULT_BACKEND))
|
|
95
63
|
|
|
96
64
|
#
|
|
97
65
|
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from omlish import inject as inj
|
|
2
|
+
from omlish import lang
|
|
3
|
+
|
|
4
|
+
from .injection import phase_callbacks
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
with lang.auto_proxy_import(globals()):
|
|
8
|
+
from . import manager as _manager
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def bind_phases() -> inj.Elements:
|
|
15
|
+
els: list[inj.Elemental] = []
|
|
16
|
+
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
els.append(phase_callbacks().bind_items_provider(singleton=True))
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
|
|
23
|
+
els.append(inj.bind(_manager.ChatPhaseManager, 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 phase_callbacks() -> 'inj.ItemsBinderHelper[_types.ChatPhaseCallback]':
|
|
14
|
+
return inj.items_binder_helper[_types.ChatPhaseCallback](_types.ChatPhaseCallbacks)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from omlish import check
|
|
2
|
+
from omlish import collections as col
|
|
3
|
+
|
|
4
|
+
from .types import ChatPhase
|
|
5
|
+
from .types import ChatPhaseCallbacks
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ChatPhaseManager:
|
|
12
|
+
def __init__(self, callbacks: ChatPhaseCallbacks) -> None:
|
|
13
|
+
super().__init__()
|
|
14
|
+
|
|
15
|
+
self._callbacks = callbacks
|
|
16
|
+
self._callbacks_by_phase = col.multi_map_by(lambda cb: cb.phase, callbacks)
|
|
17
|
+
|
|
18
|
+
check.state(not self._callbacks_by_phase.get(ChatPhase.NEW))
|
|
19
|
+
|
|
20
|
+
self._phase = ChatPhase.NEW
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def phase(self) -> ChatPhase:
|
|
24
|
+
return self._phase
|
|
25
|
+
|
|
26
|
+
async def set_phase(self, phase: ChatPhase) -> None:
|
|
27
|
+
self._phase = phase
|
|
28
|
+
for cb in self._callbacks_by_phase.get(phase, ()):
|
|
29
|
+
await cb.fn()
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
from omlish import dataclasses as dc
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ChatPhase(enum.Enum):
|
|
11
|
+
NEW = enum.auto()
|
|
12
|
+
|
|
13
|
+
STARTING = enum.auto()
|
|
14
|
+
STARTED = enum.auto()
|
|
15
|
+
|
|
16
|
+
STOPPING = enum.auto()
|
|
17
|
+
STOPPED = enum.auto()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dc.dataclass(frozen=True)
|
|
24
|
+
class ChatPhaseCallback:
|
|
25
|
+
phase: ChatPhase = dc.xfield(validate=lambda v: v != ChatPhase.NEW)
|
|
26
|
+
fn: ta.Callable[[], ta.Awaitable[None]] = dc.xfield()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
ChatPhaseCallbacks = ta.NewType('ChatPhaseCallbacks', ta.Sequence[ChatPhaseCallback])
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from omlish import dataclasses as dc
|
|
2
|
+
|
|
3
|
+
from ..base import Session
|
|
4
|
+
from .configs import ChatConfig
|
|
5
|
+
from .driver import ChatDriver
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ChatSession(Session['ChatSession.Config']):
|
|
12
|
+
@dc.dataclass(frozen=True)
|
|
13
|
+
class Config(Session.Config, ChatConfig):
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
config: Config,
|
|
19
|
+
*,
|
|
20
|
+
driver: ChatDriver,
|
|
21
|
+
) -> None:
|
|
22
|
+
super().__init__(config)
|
|
23
|
+
|
|
24
|
+
self._driver = driver
|
|
25
|
+
|
|
26
|
+
async def run(self) -> None:
|
|
27
|
+
await self._driver.run()
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import dataclasses as dc
|
|
4
|
+
from omlish import lang
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
|
11
|
+
class ToolsConfig:
|
|
12
|
+
silent: bool = False
|
|
13
|
+
dangerous_no_confirmation: bool = False
|
|
14
|
+
enabled_tools: ta.Iterable[str] | None = None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
|
21
|
+
class ToolSetConfig(lang.Abstract):
|
|
22
|
+
pass
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
from omlish import lang
|
|
5
|
+
from omlish.formats import json
|
|
6
|
+
from omlish.term.confirm import confirm_action
|
|
7
|
+
|
|
8
|
+
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
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class InteractiveToolExecutionConfirmation(ToolExecutionConfirmation):
|
|
32
|
+
async def confirm_tool_execution_or_raise(
|
|
33
|
+
self,
|
|
34
|
+
use: 'mc.ToolUse',
|
|
35
|
+
entry: 'mc.ToolCatalogEntry',
|
|
36
|
+
) -> None:
|
|
37
|
+
tr_dct = dict(
|
|
38
|
+
id=use.id,
|
|
39
|
+
name=entry.spec.name,
|
|
40
|
+
args=use.args,
|
|
41
|
+
# spec=msh.marshal(tce.spec),
|
|
42
|
+
)
|
|
43
|
+
cr = confirm_action(f'Execute requested tool?\n\n{json.dumps_pretty(tr_dct)}') # FIXME: async lol
|
|
44
|
+
|
|
45
|
+
if not cr:
|
|
46
|
+
raise ToolExecutionRequestDeniedError
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
from omlish import check
|
|
5
|
+
from omlish import lang
|
|
6
|
+
|
|
7
|
+
from ..... import minichain as mc
|
|
8
|
+
from .confirmation import ToolExecutionConfirmation
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ToolContextProvider(lang.Func0[ta.Sequence[ta.Any]]):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
ToolContextProviders = ta.NewType('ToolContextProviders', ta.Sequence[ToolContextProvider])
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ToolUseExecutor(lang.Abstract):
|
|
25
|
+
@abc.abstractmethod
|
|
26
|
+
def execute_tool_use(
|
|
27
|
+
self,
|
|
28
|
+
use: 'mc.ToolUse',
|
|
29
|
+
*ctx_items: ta.Any,
|
|
30
|
+
) -> ta.Awaitable['mc.ToolUseResultMessage']:
|
|
31
|
+
raise NotImplementedError
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ToolUseExecutorImpl(ToolUseExecutor):
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
*,
|
|
38
|
+
catalog: 'mc.ToolCatalog',
|
|
39
|
+
ctx_provider: ToolContextProvider,
|
|
40
|
+
confirmation: ToolExecutionConfirmation | None = None,
|
|
41
|
+
) -> None:
|
|
42
|
+
super().__init__()
|
|
43
|
+
|
|
44
|
+
self._catalog = catalog
|
|
45
|
+
self._ctx_provider = ctx_provider
|
|
46
|
+
self._confirmation = confirmation
|
|
47
|
+
|
|
48
|
+
async def execute_tool_use(
|
|
49
|
+
self,
|
|
50
|
+
use: 'mc.ToolUse',
|
|
51
|
+
*ctx_items: ta.Any,
|
|
52
|
+
) -> 'mc.ToolUseResultMessage':
|
|
53
|
+
tce = self._catalog.by_name[check.non_empty_str(use.name)]
|
|
54
|
+
|
|
55
|
+
if self._confirmation is not None:
|
|
56
|
+
await self._confirmation.confirm_tool_execution_or_raise(use, tce)
|
|
57
|
+
|
|
58
|
+
return await mc.execute_tool_use(
|
|
59
|
+
mc.ToolContext(
|
|
60
|
+
use,
|
|
61
|
+
*self._ctx_provider(),
|
|
62
|
+
*ctx_items,
|
|
63
|
+
),
|
|
64
|
+
tce.executor(),
|
|
65
|
+
use,
|
|
66
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from omlish import inject as inj
|
|
4
|
+
|
|
5
|
+
from ..injection import ToolSetBinder
|
|
6
|
+
from ..injection import bind_tool_context_provider_to_key
|
|
7
|
+
from ..injection import tool_catalog_entries
|
|
8
|
+
from .configs import FsToolSetConfig
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def bind_fs_tools(cfg: FsToolSetConfig) -> inj.Elements:
|
|
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
|
+
|
|
19
|
+
return inj.as_elements(
|
|
20
|
+
tool_catalog_entries().bind_item_consts(
|
|
21
|
+
ls_tool(),
|
|
22
|
+
read_tool(),
|
|
23
|
+
),
|
|
24
|
+
|
|
25
|
+
inj.bind(FsContext(
|
|
26
|
+
root_dir=os.getcwd(),
|
|
27
|
+
)),
|
|
28
|
+
bind_tool_context_provider_to_key(FsContext),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
FS_TOOL_SET_BINDER = ToolSetBinder(FsToolSetConfig, bind_fs_tools)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from omlish import check
|
|
2
|
+
from omlish import inject as inj
|
|
3
|
+
from omlish import lang
|
|
4
|
+
|
|
5
|
+
from ..... import minichain as mc
|
|
6
|
+
from .configs import ToolsConfig
|
|
7
|
+
from .injection import ToolSetBinder
|
|
8
|
+
from .injection import tool_catalog_entries
|
|
9
|
+
from .injection import tool_context_providers
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
with lang.auto_proxy_import(globals()):
|
|
13
|
+
from . import confirmation as _confirmation
|
|
14
|
+
from . import execution as _execution
|
|
15
|
+
from . import rendering as _rendering
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# if tools_config.enable_unsafe_tools_do_not_use_lol:
|
|
22
|
+
# from ...minichain.lib.bash import bash_tool
|
|
23
|
+
# els.append(bind_tool(bash_tool()))
|
|
24
|
+
#
|
|
25
|
+
# from ...minichain.lib.fs.tools.edit import edit_tool
|
|
26
|
+
# els.append(bind_tool(edit_tool()))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def bind_tools(cfg: ToolsConfig = ToolsConfig()) -> inj.Elements:
|
|
33
|
+
els: list[inj.Elemental] = []
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
|
|
37
|
+
els.append(inj.bind(mc.ToolCatalog, singleton=True))
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
|
|
41
|
+
els.append(tool_catalog_entries().bind_items_provider(singleton=True))
|
|
42
|
+
|
|
43
|
+
for etn in check.not_isinstance(cfg.enabled_tools or [], str):
|
|
44
|
+
from .fs.inject import FS_TOOL_SET_BINDER
|
|
45
|
+
from .todo.inject import TODO_TOOL_SET_BINDER
|
|
46
|
+
from .weather.inject import WEATHER_TOOL_SET_BINDER
|
|
47
|
+
ts_binder: ToolSetBinder = { # type: ignore[assignment] # FIXME: placeholder obviously lol
|
|
48
|
+
'fs': FS_TOOL_SET_BINDER,
|
|
49
|
+
'todo': TODO_TOOL_SET_BINDER,
|
|
50
|
+
'weather': WEATHER_TOOL_SET_BINDER,
|
|
51
|
+
}[etn]
|
|
52
|
+
|
|
53
|
+
els.append(ts_binder.fn(ts_binder.cfg_cls()))
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
|
|
57
|
+
exec_stack = inj.wrapper_binder_helper(_execution.ToolUseExecutor)
|
|
58
|
+
|
|
59
|
+
els.append(exec_stack.push_bind(to_ctor=_execution.ToolUseExecutorImpl, singleton=True))
|
|
60
|
+
|
|
61
|
+
if not cfg.silent:
|
|
62
|
+
els.append(exec_stack.push_bind(to_ctor=_rendering.ResultRenderingToolUseExecutor, singleton=True))
|
|
63
|
+
|
|
64
|
+
if cfg.dangerous_no_confirmation:
|
|
65
|
+
els.append(exec_stack.push_bind(to_ctor=_rendering.ArgsRenderingToolUseExecutor, singleton=True))
|
|
66
|
+
|
|
67
|
+
els.extend([
|
|
68
|
+
inj.bind(_execution.ToolUseExecutor, to_key=exec_stack.top),
|
|
69
|
+
])
|
|
70
|
+
|
|
71
|
+
#
|
|
72
|
+
|
|
73
|
+
if not cfg.dangerous_no_confirmation:
|
|
74
|
+
els.append(inj.bind(_confirmation.ToolExecutionConfirmation, to_ctor=_confirmation.InteractiveToolExecutionConfirmation, singleton=True)) # noqa
|
|
75
|
+
|
|
76
|
+
#
|
|
77
|
+
|
|
78
|
+
els.extend([
|
|
79
|
+
tool_context_providers().bind_items_provider(singleton=True),
|
|
80
|
+
|
|
81
|
+
inj.bind(_execution.ToolContextProvider, to_fn=lang.typed_lambda(tcps=_execution.ToolContextProviders)(
|
|
82
|
+
lambda tcps: _execution.ToolContextProvider(lambda: [tc for tcp in tcps for tc in tcp()]),
|
|
83
|
+
), singleton=True),
|
|
84
|
+
])
|
|
85
|
+
|
|
86
|
+
#
|
|
87
|
+
|
|
88
|
+
return inj.as_elements(*els)
|