ommlds 0.0.0.dev463__py3-none-any.whl → 0.0.0.dev465__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.

Potentially problematic release.


This version of ommlds might be problematic. Click here for more details.

Files changed (81) hide show
  1. ommlds/.omlish-manifests.json +2 -2
  2. ommlds/cli/inject.py +14 -32
  3. ommlds/cli/main.py +34 -59
  4. ommlds/cli/sessions/{chat2 → chat}/backends/catalog.py +5 -5
  5. ommlds/cli/sessions/chat/backends/inject.py +37 -0
  6. ommlds/cli/sessions/chat/backends/injection.py +16 -0
  7. ommlds/cli/sessions/{chat2 → chat}/backends/types.py +3 -3
  8. ommlds/cli/sessions/chat/chat/ai/inject.py +78 -0
  9. ommlds/cli/sessions/chat/chat/ai/injection.py +14 -0
  10. ommlds/cli/sessions/{chat2 → chat}/chat/ai/rendering.py +13 -10
  11. ommlds/cli/sessions/chat/chat/ai/services.py +81 -0
  12. ommlds/cli/sessions/chat/chat/ai/tools.py +44 -0
  13. ommlds/cli/sessions/{chat2 → chat}/chat/ai/types.py +5 -5
  14. ommlds/cli/sessions/chat/chat/state/inject.py +40 -0
  15. ommlds/cli/sessions/{chat2 → chat}/chat/state/inmemory.py +1 -1
  16. ommlds/cli/sessions/{chat2 → chat}/chat/state/storage.py +2 -2
  17. ommlds/cli/sessions/{chat2 → chat}/chat/state/types.py +1 -1
  18. ommlds/cli/sessions/chat/chat/user/inject.py +61 -0
  19. ommlds/cli/sessions/{chat2 → chat}/chat/user/interactive.py +1 -1
  20. ommlds/cli/sessions/{chat2 → chat}/chat/user/oneshot.py +1 -1
  21. ommlds/cli/sessions/{chat2 → chat}/chat/user/types.py +1 -1
  22. ommlds/cli/sessions/{chat2 → chat}/configs.py +4 -1
  23. ommlds/cli/sessions/{chat2 → chat}/content/messages.py +6 -2
  24. ommlds/cli/sessions/{chat2 → chat}/content/strings.py +2 -2
  25. ommlds/cli/sessions/{chat2 → chat}/driver.py +2 -2
  26. ommlds/cli/sessions/chat/inject.py +47 -63
  27. ommlds/cli/sessions/chat/phases/inject.py +27 -0
  28. ommlds/cli/sessions/chat/phases/injection.py +14 -0
  29. ommlds/cli/sessions/{chat2/phases.py → chat/phases/manager.py} +2 -28
  30. ommlds/cli/sessions/chat/phases/types.py +29 -0
  31. ommlds/cli/sessions/chat/rendering/inject.py +32 -0
  32. ommlds/cli/sessions/{chat2 → chat}/rendering/markdown.py +2 -2
  33. ommlds/cli/sessions/{chat2 → chat}/rendering/raw.py +6 -6
  34. ommlds/cli/sessions/{chat2 → chat}/rendering/types.py +1 -1
  35. ommlds/cli/sessions/{chat2 → chat}/session.py +1 -1
  36. ommlds/cli/sessions/{chat2 → chat}/tools/confirmation.py +4 -4
  37. ommlds/cli/sessions/{chat2 → chat}/tools/execution.py +18 -5
  38. ommlds/cli/sessions/chat/tools/inject.py +145 -0
  39. ommlds/cli/sessions/chat/tools/injection.py +29 -0
  40. ommlds/cli/sessions/chat/tools/rendering.py +58 -0
  41. ommlds/cli/{tools → sessions/chat/tools}/weather.py +1 -1
  42. ommlds/cli/sessions/completion/configs.py +21 -0
  43. ommlds/cli/sessions/completion/inject.py +28 -0
  44. ommlds/cli/sessions/completion/{completion.py → session.py} +4 -9
  45. ommlds/cli/sessions/embedding/configs.py +21 -0
  46. ommlds/cli/sessions/embedding/inject.py +28 -0
  47. ommlds/cli/sessions/embedding/{embedding.py → session.py} +4 -9
  48. ommlds/cli/sessions/inject.py +27 -15
  49. ommlds/cli/state/inject.py +28 -0
  50. ommlds/minichain/backends/impls/anthropic/chat.py +4 -61
  51. ommlds/minichain/backends/impls/anthropic/protocol.py +109 -0
  52. ommlds/minichain/backends/impls/anthropic/stream.py +17 -17
  53. {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev465.dist-info}/METADATA +3 -3
  54. {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev465.dist-info}/RECORD +69 -60
  55. ommlds/cli/sessions/chat/base.py +0 -42
  56. ommlds/cli/sessions/chat/code.py +0 -125
  57. ommlds/cli/sessions/chat/interactive.py +0 -70
  58. ommlds/cli/sessions/chat/printing.py +0 -126
  59. ommlds/cli/sessions/chat/prompt.py +0 -161
  60. ommlds/cli/sessions/chat/state.py +0 -110
  61. ommlds/cli/sessions/chat/tools.py +0 -97
  62. ommlds/cli/sessions/chat2/_inject.py +0 -105
  63. ommlds/cli/sessions/chat2/chat/ai/services.py +0 -70
  64. ommlds/cli/sessions/chat2/inject.py +0 -143
  65. ommlds/cli/tools/config.py +0 -14
  66. ommlds/cli/tools/inject.py +0 -75
  67. /ommlds/cli/sessions/{chat2 → chat/backends}/__init__.py +0 -0
  68. /ommlds/cli/sessions/{chat2/backends → chat/chat}/__init__.py +0 -0
  69. /ommlds/cli/sessions/{chat2/chat → chat/chat/ai}/__init__.py +0 -0
  70. /ommlds/cli/sessions/{chat2/chat/ai → chat/chat/state}/__init__.py +0 -0
  71. /ommlds/cli/sessions/{chat2/chat/state → chat/chat/user}/__init__.py +0 -0
  72. /ommlds/cli/sessions/{chat2/chat/user → chat/content}/__init__.py +0 -0
  73. /ommlds/cli/sessions/{chat2/content → chat/phases}/__init__.py +0 -0
  74. /ommlds/cli/sessions/{chat2 → chat}/rendering/__init__.py +0 -0
  75. /ommlds/cli/sessions/{chat2 → chat}/tools/__init__.py +0 -0
  76. /ommlds/cli/{tools → state}/__init__.py +0 -0
  77. /ommlds/cli/{state.py → state/storage.py} +0 -0
  78. {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev465.dist-info}/WHEEL +0 -0
  79. {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev465.dist-info}/entry_points.txt +0 -0
  80. {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev465.dist-info}/licenses/LICENSE +0 -0
  81. {ommlds-0.0.0.dev463.dist-info → ommlds-0.0.0.dev465.dist-info}/top_level.txt +0 -0
@@ -1,161 +0,0 @@
1
- import dataclasses as dc
2
- import os
3
-
4
- from omlish import check
5
- from omlish import lang
6
-
7
- from .... import minichain as mc
8
- from .base import DEFAULT_CHAT_MODEL_BACKEND
9
- from .base import ChatOptions
10
- from .base import ChatSession
11
- from .printing import ChatSessionPrinter
12
- from .printing import MarkdownStreamPrinter
13
- from .printing import SimpleStreamPrinter
14
- from .printing import StreamPrinter
15
- from .state import ChatStateManager
16
- from .tools import ToolUseExecutor
17
-
18
-
19
- ##
20
-
21
-
22
- class ToolExecutionRequestDeniedError(Exception):
23
- pass
24
-
25
-
26
- class PromptChatSession(ChatSession['PromptChatSession.Config']):
27
- @dc.dataclass(frozen=True)
28
- class Config(ChatSession.Config): # noqa
29
- content: mc.Content
30
-
31
- _: dc.KW_ONLY
32
-
33
- new: bool = False
34
-
35
- backend: str | None = None
36
- model_name: str | None = None
37
-
38
- stream: bool = False
39
-
40
- def __init__(
41
- self,
42
- config: Config,
43
- *,
44
- state_manager: ChatStateManager,
45
- chat_options: ChatOptions | None = None,
46
- printer: ChatSessionPrinter,
47
- backend_catalog: mc.BackendCatalog,
48
- tool_exec_request_executor: ToolUseExecutor,
49
- ) -> None:
50
- super().__init__(config)
51
-
52
- self._state_manager = state_manager
53
- self._chat_options = chat_options
54
- self._printer = printer
55
- self._backend_catalog = backend_catalog
56
- self._tool_exec_request_executor = tool_exec_request_executor
57
-
58
- async def run(self) -> None:
59
- if self._config.stream:
60
- await self._run_stream()
61
- else:
62
- await self._run_immediate()
63
-
64
- async def _run_stream(self) -> None:
65
- prompt = check.isinstance(self._config.content, str)
66
-
67
- if self._config.new:
68
- state = self._state_manager.clear_state()
69
- else:
70
- state = self._state_manager.get_state()
71
-
72
- new_chat: list[mc.Message] = [
73
- mc.UserMessage(prompt),
74
- ]
75
-
76
- mdl: mc.ChatChoicesStreamService
77
- async with lang.async_maybe_managing(self._backend_catalog.get_backend(
78
- mc.ChatChoicesStreamService,
79
- self._config.backend or DEFAULT_CHAT_MODEL_BACKEND,
80
- *([mc.ModelName(mn)] if (mn := self._config.model_name) is not None else []),
81
- )) as mdl:
82
- async with (await mdl.invoke(mc.ChatChoicesStreamRequest(
83
- [*state.chat, *new_chat],
84
- (self._chat_options or []),
85
- ))).v as st_resp:
86
- lst: list[str] = []
87
-
88
- sp_cls: type[StreamPrinter]
89
- if self._config.markdown:
90
- sp_cls = MarkdownStreamPrinter
91
- else:
92
- sp_cls = SimpleStreamPrinter
93
- with sp_cls() as sp:
94
- async for o in st_resp:
95
- if o:
96
- c = check.isinstance(check.single(check.single(o.choices).deltas), mc.ContentAiChoiceDelta).c # noqa
97
- if c is not None:
98
- s = check.isinstance(c, str)
99
- sp.feed(s)
100
- lst.append(s)
101
-
102
- resp_m = mc.AiMessage(''.join(lst))
103
- new_chat.append(resp_m)
104
-
105
- self._state_manager.extend_chat(new_chat)
106
-
107
- async def _run_immediate(self) -> None:
108
- prompt = check.isinstance(self._config.content, str)
109
-
110
- if self._config.new:
111
- state = self._state_manager.clear_state()
112
- else:
113
- state = self._state_manager.get_state()
114
-
115
- new_chat: list[mc.Message] = [
116
- mc.UserMessage(prompt),
117
- ]
118
-
119
- mdl: mc.ChatChoicesService
120
- async with lang.async_maybe_managing(self._backend_catalog.get_backend(
121
- mc.ChatChoicesService,
122
- self._config.backend or DEFAULT_CHAT_MODEL_BACKEND,
123
- *([mc.ModelName(mn)] if (mn := self._config.model_name) is not None else []),
124
- )) as mdl:
125
- response: mc.ChatChoicesResponse = await mdl.invoke(mc.ChatChoicesRequest(
126
- [*state.chat, *new_chat],
127
- (self._chat_options or []),
128
- ))
129
-
130
- for resp_m in response.v[0].ms:
131
- new_chat.append(resp_m)
132
-
133
- if isinstance(resp_m, mc.AiMessage):
134
- self._printer.print(resp_m)
135
-
136
- elif isinstance(resp_m, mc.ToolUseMessage):
137
- tr: mc.ToolUse = resp_m.tu
138
-
139
- # FIXME: lol
140
- from ....minichain.lib.fs.context import FsContext
141
-
142
- trm = await self._tool_exec_request_executor.execute_tool_use(
143
- tr,
144
- FsContext(root_dir=os.getcwd()),
145
- )
146
-
147
- print(trm.tur.c)
148
- new_chat.append(trm)
149
-
150
- response = await mdl.invoke(mc.ChatChoicesRequest(
151
- [*state.chat, *new_chat],
152
- (self._chat_options or []),
153
- ))
154
-
155
- resp_m = check.isinstance(check.single(response.v[0].ms), mc.AiMessage)
156
- new_chat.append(resp_m)
157
-
158
- else:
159
- raise TypeError(resp_m)
160
-
161
- self._state_manager.extend_chat(new_chat)
@@ -1,110 +0,0 @@
1
- import abc
2
- import dataclasses as dc
3
- import datetime
4
-
5
- from omlish import check
6
- from omlish import lang
7
-
8
- from .... import minichain as mc
9
- from ...state import StateStorage
10
-
11
-
12
- ##
13
-
14
-
15
- @dc.dataclass(frozen=True)
16
- class ChatState:
17
- name: str | None = None
18
-
19
- created_at: datetime.datetime = dc.field(default_factory=lang.utcnow)
20
- updated_at: datetime.datetime = dc.field(default_factory=lang.utcnow)
21
-
22
- chat: mc.Chat = ()
23
-
24
-
25
- ##
26
-
27
-
28
- class ChatStateManager(lang.Abstract):
29
- @abc.abstractmethod
30
- def get_state(self) -> ChatState:
31
- raise NotImplementedError
32
-
33
- @abc.abstractmethod
34
- def clear_state(self) -> ChatState:
35
- raise NotImplementedError
36
-
37
- @abc.abstractmethod
38
- def extend_chat(self, chat_additions: mc.Chat) -> ChatState:
39
- raise NotImplementedError
40
-
41
-
42
- ##
43
-
44
-
45
- class InMemoryChatStateManager(ChatStateManager):
46
- def __init__(self, initial_state: ChatState | None = None) -> None:
47
- super().__init__()
48
-
49
- if initial_state is None:
50
- initial_state = ChatState()
51
- self._state = initial_state
52
-
53
- def get_state(self) -> ChatState:
54
- return self._state
55
-
56
- def clear_state(self) -> ChatState:
57
- self._state = ChatState()
58
- return self._state
59
-
60
- def extend_chat(self, chat_additions: mc.Chat) -> ChatState:
61
- self._state = dc.replace(
62
- self._state,
63
- chat=[*self._state.chat, *chat_additions],
64
- updated_at=lang.utcnow(),
65
- )
66
- return self._state
67
-
68
-
69
- ##
70
-
71
-
72
- class StateStorageChatStateManager(ChatStateManager):
73
- def __init__(
74
- self,
75
- *,
76
- storage: StateStorage,
77
- key: str = 'chat',
78
- ) -> None:
79
- super().__init__()
80
-
81
- self._storage = storage
82
- self._key = check.non_empty_str(key)
83
-
84
- self._state: ChatState | None = None
85
-
86
- def get_state(self) -> ChatState:
87
- if self._state is not None:
88
- return self._state
89
- state: ChatState | None = lang.sync_await(self._storage.load_state(self._key, ChatState))
90
- if state is None:
91
- state = ChatState()
92
- self._state = state
93
- return state
94
-
95
- def clear_state(self) -> ChatState:
96
- state = ChatState()
97
- lang.sync_await(self._storage.save_state(self._key, state, ChatState))
98
- self._state = state
99
- return state
100
-
101
- def extend_chat(self, chat_additions: mc.Chat) -> ChatState:
102
- state = self.get_state()
103
- state = dc.replace(
104
- state,
105
- chat=[*state.chat, *chat_additions],
106
- updated_at=lang.utcnow(),
107
- )
108
- lang.sync_await(self._storage.save_state(self._key, state, ChatState))
109
- self._state = state
110
- return state
@@ -1,97 +0,0 @@
1
- import abc
2
- import typing as ta
3
-
4
- from omlish import check
5
- from omlish import lang
6
- from omlish.formats import json
7
- from omlish.term.confirm import confirm_action
8
-
9
- from .... import minichain as mc
10
-
11
-
12
- ##
13
-
14
-
15
- class ToolExecutionRequestDeniedError(Exception):
16
- pass
17
-
18
-
19
- class ToolExecutionConfirmation(lang.Abstract):
20
- @abc.abstractmethod
21
- def confirm_tool_execution_or_raise(
22
- self,
23
- tr: mc.ToolUse,
24
- tce: mc.ToolCatalogEntry,
25
- ) -> ta.Awaitable[None]:
26
- raise NotImplementedError
27
-
28
-
29
- class NopToolExecutionConfirmation(ToolExecutionConfirmation):
30
- async def confirm_tool_execution_or_raise(
31
- self,
32
- tr: mc.ToolUse,
33
- tce: mc.ToolCatalogEntry,
34
- ) -> None:
35
- pass
36
-
37
-
38
- class AskingToolExecutionConfirmation(ToolExecutionConfirmation):
39
- async def confirm_tool_execution_or_raise(
40
- self,
41
- tr: mc.ToolUse,
42
- tce: mc.ToolCatalogEntry,
43
- ) -> None:
44
- tr_dct = dict(
45
- id=tr.id,
46
- name=tce.spec.name,
47
- args=tr.args,
48
- # spec=msh.marshal(tce.spec),
49
- )
50
- cr = confirm_action(f'Execute requested tool?\n\n{json.dumps_pretty(tr_dct)}') # FIXME: async lol
51
-
52
- if not cr:
53
- raise ToolExecutionRequestDeniedError
54
-
55
-
56
- ##
57
-
58
-
59
- class ToolUseExecutor(lang.Abstract):
60
- @abc.abstractmethod
61
- def execute_tool_use(
62
- self,
63
- tr: mc.ToolUse,
64
- *ctx_items: ta.Any,
65
- ) -> ta.Awaitable[mc.ToolUseResultMessage]:
66
- raise NotImplementedError
67
-
68
-
69
- class ToolUseExecutorImpl(ToolUseExecutor):
70
- def __init__(
71
- self,
72
- *,
73
- catalog: mc.ToolCatalog,
74
- confirmation: ToolExecutionConfirmation,
75
- ) -> None:
76
- super().__init__()
77
-
78
- self._catalog = catalog
79
- self._confirmation = confirmation
80
-
81
- async def execute_tool_use(
82
- self,
83
- tr: mc.ToolUse,
84
- *ctx_items: ta.Any,
85
- ) -> mc.ToolUseResultMessage:
86
- tce = self._catalog.by_name[check.non_empty_str(tr.name)]
87
-
88
- await self._confirmation.confirm_tool_execution_or_raise(tr, tce)
89
-
90
- return await mc.execute_tool_use(
91
- mc.ToolContext(
92
- tr,
93
- *ctx_items,
94
- ),
95
- tce.executor(),
96
- tr,
97
- )
@@ -1,105 +0,0 @@
1
- from omlish import lang
2
-
3
-
4
- with lang.auto_proxy_init(globals()):
5
- from .backends.catalog import ( # noqa
6
- CatalogChatChoicesServiceBackendProvider,
7
- CatalogChatChoicesStreamServiceBackendProvider,
8
- )
9
-
10
- from .backends.types import ( # noqa
11
- BackendName,
12
- BackendConfigs,
13
- BackendProvider,
14
- ChatChoicesServiceBackendProvider,
15
- ChatChoicesStreamServiceBackendProvider,
16
- )
17
-
18
- from .chat.ai.rendering import ( # noqa
19
- RenderingAiChatGenerator,
20
- RenderingStreamAiChatGenerator,
21
- )
22
-
23
- from .chat.ai.services import ( # noqa
24
- ChatChoicesServiceOptions,
25
- ChatChoicesServiceAiChatGenerator,
26
- ChatChoicesStreamServiceStreamAiChatGenerator,
27
- )
28
-
29
- from .chat.ai.types import ( # noqa
30
- AiChatGenerator,
31
- StreamAiChatGenerator,
32
- )
33
-
34
- from .chat.state.inmemory import ( # noqa
35
- InMemoryChatStateManager,
36
- )
37
-
38
- from .chat.state.storage import ( # noqa
39
- StateStorageChatStateManager,
40
- )
41
-
42
- from .chat.state.types import ( # noqa
43
- ChatState,
44
- ChatStateManager,
45
- )
46
-
47
- from .chat.user.interactive import ( # noqa
48
- InteractiveUserChatInput,
49
- )
50
-
51
- from .chat.user.oneshot import ( # noqa
52
- OneshotUserChatInputInitialChat,
53
- OneshotUserChatInput,
54
- )
55
-
56
- from .chat.user.types import ( # noqa
57
- UserChatInput,
58
- )
59
-
60
- from .content.messages import ( # noqa
61
- MessageContentExtractor,
62
- MessageContentExtractorImpl,
63
- )
64
-
65
- from .content.strings import ( # noqa
66
- ContentStringifier,
67
- ContentStringifierImpl,
68
- )
69
-
70
- from .rendering.markdown import ( # noqa
71
- MarkdownContentRendering,
72
- MarkdownStreamContentRendering,
73
- )
74
-
75
- from .rendering.raw import ( # noqa
76
- RawContentRendering,
77
- RawContentStreamRendering,
78
- )
79
-
80
- from .rendering.types import ( # noqa
81
- ContentRendering,
82
- StreamContentRendering,
83
- )
84
-
85
- from .tools.confirmation import ( # noqa
86
- ToolExecutionRequestDeniedError,
87
- ToolExecutionConfirmation,
88
- InteractiveToolExecutionConfirmation,
89
- )
90
-
91
- from .tools.execution import ( # noqa
92
- ToolUseExecutor,
93
- ToolUseExecutorImpl,
94
- )
95
-
96
- from .driver import ( # noqa
97
- ChatDriver,
98
- )
99
-
100
- from .phases import ( # noqa
101
- ChatPhase,
102
- ChatPhaseCallback,
103
- ChatPhaseCallbacks,
104
- ChatPhaseManager,
105
- )
@@ -1,70 +0,0 @@
1
- import typing as ta
2
-
3
- from omlish import check
4
-
5
- from ...... import minichain as mc
6
- from ...backends.types import ChatChoicesServiceBackendProvider
7
- from .types import AiChatGenerator
8
- from .types import StreamAiChatGenerator
9
-
10
-
11
- ##
12
-
13
-
14
- ChatChoicesServiceOptions = ta.NewType('ChatChoicesServiceOptions', ta.Sequence[mc.ChatChoicesOptions])
15
-
16
-
17
- ##
18
-
19
-
20
- class ChatChoicesServiceAiChatGenerator(AiChatGenerator):
21
- def __init__(
22
- self,
23
- service_provider: ChatChoicesServiceBackendProvider,
24
- *,
25
- options: ChatChoicesServiceOptions | None = None,
26
- ) -> None:
27
- super().__init__()
28
-
29
- self._service_provider = service_provider
30
- self._options = options
31
-
32
- async def get_next_ai_messages(self, chat: mc.Chat) -> mc.AiChat:
33
- async with self._service_provider.provide_backend() as service:
34
- resp = await service.invoke(mc.ChatChoicesRequest(chat, self._options or []))
35
-
36
- return check.single(resp.v).ms
37
-
38
-
39
- class ChatChoicesStreamServiceStreamAiChatGenerator(StreamAiChatGenerator):
40
- def __init__(
41
- self,
42
- service: mc.ChatChoicesStreamService,
43
- *,
44
- options: ChatChoicesServiceOptions | None = None,
45
- ) -> None:
46
- super().__init__()
47
-
48
- self._service = service
49
- self._options = options
50
-
51
- async def get_next_ai_messages_streamed(
52
- self,
53
- chat: mc.Chat,
54
- delta_callback: ta.Callable[[mc.AiChoiceDelta], ta.Awaitable[None]] | None = None,
55
- ) -> mc.AiChat:
56
- lst: list[str] = []
57
-
58
- async with (await self._service.invoke(mc.ChatChoicesStreamRequest(chat, self._options or []))).v as st_resp:
59
- async for o in st_resp:
60
- choice = check.single(o.choices)
61
-
62
- for delta in choice.deltas:
63
- if delta_callback is not None:
64
- await delta_callback(delta)
65
-
66
- c = check.isinstance(delta, mc.ContentAiChoiceDelta).c # noqa
67
- if c is not None:
68
- lst.append(check.isinstance(c, str))
69
-
70
- return [mc.AiMessage(''.join(lst))]
@@ -1,143 +0,0 @@
1
- import typing as ta
2
-
3
- from omlish import inject as inj
4
- from omlish import lang
5
-
6
- from .... import minichain as mc
7
- from . import _inject as _inj
8
- from .configs import DEFAULT_CHAT_MODEL_BACKEND
9
- from .configs import ChatConfig
10
-
11
-
12
- ItemT = ta.TypeVar('ItemT')
13
-
14
-
15
- ##
16
-
17
-
18
- CHAT_OPTIONS = inj.items_binder_helper[mc.ChatChoicesOption](_inj.ChatChoicesServiceOptions)
19
- BACKEND_CONFIGS = inj.items_binder_helper[mc.Config](_inj.BackendConfigs)
20
- PHASE_CALLBACKS = inj.items_binder_helper[_inj.ChatPhaseCallback](_inj.ChatPhaseCallbacks)
21
-
22
-
23
- ##
24
-
25
-
26
- def bind_chat(cfg: ChatConfig) -> inj.Elements:
27
- els: list[inj.Elemental] = []
28
-
29
- #
30
-
31
- els.extend([
32
- CHAT_OPTIONS.bind_items_provider(singleton=True),
33
- BACKEND_CONFIGS.bind_items_provider(singleton=True),
34
- PHASE_CALLBACKS.bind_items_provider(singleton=True),
35
- ])
36
-
37
- #
38
-
39
- if cfg.state in ('continue', 'new'):
40
- els.extend([
41
- inj.bind(_inj.StateStorageChatStateManager, singleton=True),
42
- inj.bind(_inj.ChatStateManager, to_key=_inj.StateStorageChatStateManager),
43
- ])
44
-
45
- if cfg.state == 'new':
46
- els.append(PHASE_CALLBACKS.bind_item(to_fn=lang.typed_lambda(cm=_inj.ChatStateManager)(
47
- lambda cm: _inj.ChatPhaseCallback(_inj.ChatPhase.STARTING, cm.clear_state),
48
- )))
49
-
50
- elif cfg.state == 'ephemeral':
51
- els.extend([
52
- inj.bind(_inj.InMemoryChatStateManager, singleton=True),
53
- inj.bind(_inj.ChatStateManager, to_key=_inj.InMemoryChatStateManager),
54
- ])
55
-
56
- else:
57
- raise TypeError(cfg.state)
58
-
59
- #
60
-
61
- if cfg.interactive:
62
- if cfg.initial_content is not None:
63
- async def add_initial_content(cm: '_inj.ChatStateManager') -> None:
64
- await cm.extend_chat([mc.UserMessage(cfg.initial_content)])
65
-
66
- els.append(PHASE_CALLBACKS.bind_item(to_fn=lang.typed_lambda(cm=_inj.ChatStateManager)(
67
- lambda cm: _inj.ChatPhaseCallback(_inj.ChatPhase.STARTED, lambda: add_initial_content(cm)),
68
- )))
69
-
70
- raise NotImplementedError
71
-
72
- els.extend([
73
- inj.bind(_inj.InteractiveUserChatInput, singleton=True),
74
- inj.bind(_inj.UserChatInput, to_key=_inj.InteractiveUserChatInput),
75
- ])
76
-
77
- else:
78
- if cfg.initial_content is None:
79
- raise ValueError('Initial content is required for non-interactive chat')
80
-
81
- els.extend([
82
- inj.bind(_inj.OneshotUserChatInputInitialChat, to_const=[mc.UserMessage(cfg.initial_content)]),
83
- inj.bind(_inj.OneshotUserChatInput, singleton=True),
84
- inj.bind(_inj.UserChatInput, to_key=_inj.OneshotUserChatInput),
85
- ])
86
-
87
- #
88
-
89
- if cfg.stream:
90
- raise NotImplementedError
91
-
92
- else:
93
- ai_stack = inj.wrapper_binder_helper(_inj.AiChatGenerator)
94
-
95
- els.append(ai_stack.push_bind(to_ctor=_inj.ChatChoicesServiceAiChatGenerator, singleton=True))
96
-
97
- if not cfg.silent:
98
- if cfg.markdown:
99
- els.extend([
100
- inj.bind(_inj.MarkdownContentRendering, singleton=True),
101
- inj.bind(_inj.ContentRendering, to_key=_inj.MarkdownContentRendering),
102
- ])
103
- else:
104
- els.extend([
105
- inj.bind(_inj.RawContentRendering, singleton=True),
106
- inj.bind(_inj.ContentRendering, to_key=_inj.RawContentRendering),
107
- ])
108
-
109
- els.append(ai_stack.push_bind(to_ctor=_inj.RenderingAiChatGenerator, singleton=True))
110
-
111
- els.append(inj.bind(_inj.AiChatGenerator, to_key=ai_stack.top))
112
-
113
- #
114
-
115
- els.append(inj.bind(_inj.BackendName, to_const=cfg.backend or DEFAULT_CHAT_MODEL_BACKEND))
116
-
117
- els.extend([
118
- inj.bind(_inj.CatalogChatChoicesServiceBackendProvider),
119
- inj.bind(_inj.ChatChoicesServiceBackendProvider, to_key=_inj.CatalogChatChoicesServiceBackendProvider),
120
- ])
121
-
122
- #
123
-
124
- els.extend([
125
- inj.bind(_inj.ToolUseExecutorImpl, singleton=True),
126
- inj.bind(_inj.ToolUseExecutor, to_key=_inj.ToolUseExecutorImpl),
127
- ])
128
-
129
- #
130
-
131
- els.extend([
132
- inj.bind(_inj.ChatPhaseManager, singleton=True),
133
- ])
134
-
135
- #
136
-
137
- els.extend([
138
- inj.bind(_inj.ChatDriver, singleton=True),
139
- ])
140
-
141
- #
142
-
143
- return inj.as_elements(*els)
@@ -1,14 +0,0 @@
1
- from omlish import dataclasses as dc
2
-
3
-
4
- ##
5
-
6
-
7
- @dc.dataclass(frozen=True, kw_only=True)
8
- class ToolsConfig:
9
- enable_fs_tools: bool = False
10
- enable_todo_tools: bool = False
11
-
12
- enable_unsafe_tools_do_not_use_lol: bool = False
13
-
14
- enable_test_weather_tool: bool = False