ommlds 0.0.0.dev475__py3-none-any.whl → 0.0.0.dev477__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.
Files changed (83) hide show
  1. ommlds/.omlish-manifests.json +85 -1
  2. ommlds/__about__.py +1 -1
  3. ommlds/backends/groq/_marshal.py +23 -0
  4. ommlds/backends/groq/protocol.py +249 -0
  5. ommlds/cli/{sessions/chat/backends → backends}/catalog.py +35 -3
  6. ommlds/cli/backends/configs.py +9 -0
  7. ommlds/cli/backends/inject.py +31 -36
  8. ommlds/cli/{sessions/chat/backends → backends}/injection.py +1 -1
  9. ommlds/cli/{sessions/chat/backends → backends}/types.py +11 -1
  10. ommlds/cli/{sessions/chat/content → content}/messages.py +1 -1
  11. ommlds/cli/{sessions/chat/content → content}/strings.py +1 -1
  12. ommlds/cli/inject.py +0 -6
  13. ommlds/cli/inputs/asyncs.py +32 -0
  14. ommlds/cli/{sessions/chat/chat/user/inputs.py → inputs/sync.py} +0 -30
  15. ommlds/cli/main.py +267 -113
  16. ommlds/cli/rendering/__init__.py +0 -0
  17. ommlds/cli/rendering/configs.py +9 -0
  18. ommlds/cli/{sessions/chat/rendering → rendering}/inject.py +4 -5
  19. ommlds/cli/{sessions/chat/rendering → rendering}/markdown.py +1 -1
  20. ommlds/cli/{sessions/chat/rendering → rendering}/raw.py +1 -1
  21. ommlds/cli/{sessions/chat/rendering → rendering}/types.py +1 -1
  22. ommlds/cli/secrets.py +21 -0
  23. ommlds/cli/sessions/base.py +1 -1
  24. ommlds/cli/sessions/chat/chat/ai/configs.py +11 -0
  25. ommlds/cli/sessions/chat/chat/ai/inject.py +7 -11
  26. ommlds/cli/sessions/chat/chat/ai/rendering.py +4 -4
  27. ommlds/cli/sessions/chat/chat/ai/services.py +2 -2
  28. ommlds/cli/sessions/chat/chat/state/configs.py +11 -0
  29. ommlds/cli/sessions/chat/chat/state/inject.py +6 -10
  30. ommlds/cli/sessions/chat/chat/state/inmemory.py +1 -2
  31. ommlds/cli/sessions/chat/chat/state/storage.py +1 -2
  32. ommlds/cli/sessions/chat/chat/state/types.py +1 -1
  33. ommlds/cli/sessions/chat/chat/user/configs.py +17 -0
  34. ommlds/cli/sessions/chat/chat/user/inject.py +13 -19
  35. ommlds/cli/sessions/chat/chat/user/interactive.py +3 -3
  36. ommlds/cli/sessions/chat/configs.py +15 -26
  37. ommlds/cli/sessions/chat/inject.py +18 -35
  38. ommlds/cli/sessions/chat/session.py +1 -1
  39. ommlds/cli/sessions/chat/tools/configs.py +22 -0
  40. ommlds/cli/sessions/chat/tools/fs/__init__.py +0 -0
  41. ommlds/cli/sessions/chat/tools/fs/configs.py +12 -0
  42. ommlds/cli/sessions/chat/tools/fs/inject.py +35 -0
  43. ommlds/cli/sessions/chat/tools/inject.py +17 -74
  44. ommlds/cli/sessions/chat/tools/injection.py +15 -0
  45. ommlds/cli/sessions/chat/tools/rendering.py +1 -1
  46. ommlds/cli/sessions/chat/tools/todo/__init__.py +0 -0
  47. ommlds/cli/sessions/chat/tools/todo/configs.py +12 -0
  48. ommlds/cli/sessions/chat/tools/todo/inject.py +31 -0
  49. ommlds/cli/sessions/chat/tools/weather/__init__.py +0 -0
  50. ommlds/cli/sessions/chat/tools/weather/configs.py +12 -0
  51. ommlds/cli/sessions/chat/tools/weather/inject.py +22 -0
  52. ommlds/cli/sessions/chat/tools/{weather.py → weather/tools.py} +1 -1
  53. ommlds/cli/sessions/completion/configs.py +2 -2
  54. ommlds/cli/sessions/completion/inject.py +14 -0
  55. ommlds/cli/sessions/completion/session.py +7 -11
  56. ommlds/cli/sessions/embedding/configs.py +2 -2
  57. ommlds/cli/sessions/embedding/inject.py +14 -0
  58. ommlds/cli/sessions/embedding/session.py +7 -11
  59. ommlds/cli/state/storage.py +1 -1
  60. ommlds/minichain/backends/catalogs/strings.py +1 -1
  61. ommlds/minichain/backends/impls/groq/__init__.py +0 -0
  62. ommlds/minichain/backends/impls/groq/chat.py +75 -0
  63. ommlds/minichain/backends/impls/groq/names.py +48 -0
  64. ommlds/minichain/backends/impls/groq/protocol.py +143 -0
  65. ommlds/minichain/backends/impls/groq/stream.py +125 -0
  66. ommlds/minichain/backends/impls/openai/chat.py +3 -3
  67. ommlds/minichain/backends/impls/openai/names.py +27 -3
  68. ommlds/minichain/backends/impls/openai/stream.py +2 -2
  69. ommlds/minichain/chat/stream/joining.py +1 -0
  70. ommlds/minichain/tools/reflect.py +5 -1
  71. ommlds/wiki/utils/xml.py +5 -5
  72. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/METADATA +5 -5
  73. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/RECORD +80 -58
  74. ommlds/cli/backends/standard.py +0 -20
  75. ommlds/cli/main2.py +0 -220
  76. ommlds/cli/sessions/chat/backends/inject.py +0 -53
  77. /ommlds/{cli/sessions/chat/backends → backends/groq}/__init__.py +0 -0
  78. /ommlds/cli/{sessions/chat/content → content}/__init__.py +0 -0
  79. /ommlds/cli/{sessions/chat/rendering → inputs}/__init__.py +0 -0
  80. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/WHEEL +0 -0
  81. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/entry_points.txt +0 -0
  82. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/licenses/LICENSE +0 -0
  83. {ommlds-0.0.0.dev475.dist-info → ommlds-0.0.0.dev477.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@ from omlish import inject as inj
2
2
  from omlish import lang
3
3
 
4
4
  from ...... import minichain as mc
5
+ from .configs import AiConfig
5
6
  from .injection import chat_options_providers
6
7
 
7
8
 
@@ -15,12 +16,7 @@ with lang.auto_proxy_import(globals()):
15
16
  ##
16
17
 
17
18
 
18
- def bind_ai(
19
- *,
20
- stream: bool = False,
21
- silent: bool = False,
22
- enable_tools: bool = False,
23
- ) -> inj.Elements:
19
+ def bind_ai(cfg: AiConfig = AiConfig()) -> inj.Elements:
24
20
  els: list[inj.Elemental] = []
25
21
 
26
22
  #
@@ -38,12 +34,12 @@ def bind_ai(
38
34
 
39
35
  ai_stack = inj.wrapper_binder_helper(_types.AiChatGenerator)
40
36
 
41
- if stream:
37
+ if cfg.stream:
42
38
  stream_ai_stack = inj.wrapper_binder_helper(_types.StreamAiChatGenerator)
43
39
 
44
40
  els.append(stream_ai_stack.push_bind(to_ctor=_services.ChatChoicesStreamServiceStreamAiChatGenerator, singleton=True)) # noqa
45
41
 
46
- if not silent:
42
+ if not cfg.silent:
47
43
  els.append(stream_ai_stack.push_bind(to_ctor=_rendering.RenderingStreamAiChatGenerator, singleton=True))
48
44
 
49
45
  els.extend([
@@ -54,17 +50,17 @@ def bind_ai(
54
50
  else:
55
51
  els.append(ai_stack.push_bind(to_ctor=_services.ChatChoicesServiceAiChatGenerator, singleton=True))
56
52
 
57
- if not silent:
53
+ if not cfg.silent:
58
54
  els.append(ai_stack.push_bind(to_ctor=_rendering.RenderingAiChatGenerator, singleton=True))
59
55
 
60
- if enable_tools:
56
+ if cfg.enable_tools:
61
57
  els.append(ai_stack.push_bind(to_ctor=_tools.ToolExecutingAiChatGenerator, singleton=True))
62
58
 
63
59
  els.append(inj.bind(_types.AiChatGenerator, to_key=ai_stack.top))
64
60
 
65
61
  #
66
62
 
67
- if enable_tools:
63
+ if cfg.enable_tools:
68
64
  def _provide_tools_chat_choices_options_provider(tc: mc.ToolCatalog) -> _services.ChatChoicesServiceOptionsProvider: # noqa
69
65
  return _services.ChatChoicesServiceOptionsProvider(lambda: [
70
66
  mc.Tool(tce.spec)
@@ -1,10 +1,10 @@
1
1
  import typing as ta
2
2
 
3
3
  from ...... import minichain as mc
4
- from ...content.messages import MessageContentExtractor
5
- from ...content.messages import MessageContentExtractorImpl
6
- from ...rendering.types import ContentRendering
7
- from ...rendering.types import StreamContentRendering
4
+ from .....content.messages import MessageContentExtractor
5
+ from .....content.messages import MessageContentExtractorImpl
6
+ from .....rendering.types import ContentRendering
7
+ from .....rendering.types import StreamContentRendering
8
8
  from .types import AiChatGenerator
9
9
  from .types import StreamAiChatGenerator
10
10
 
@@ -4,8 +4,8 @@ from omlish import check
4
4
  from omlish import lang
5
5
 
6
6
  from ...... import minichain as mc
7
- from ...backends.types import ChatChoicesServiceBackendProvider
8
- from ...backends.types import ChatChoicesStreamServiceBackendProvider
7
+ from .....backends.types import ChatChoicesServiceBackendProvider
8
+ from .....backends.types import ChatChoicesStreamServiceBackendProvider
9
9
  from .types import AiChatGenerator
10
10
  from .types import StreamAiChatGenerator
11
11
 
@@ -0,0 +1,11 @@
1
+ import typing as ta
2
+
3
+ from omlish import dataclasses as dc
4
+
5
+
6
+ ##
7
+
8
+
9
+ @dc.dataclass(frozen=True, kw_only=True)
10
+ class StateConfig:
11
+ state: ta.Literal['new', 'continue', 'ephemeral'] = 'continue'
@@ -1,11 +1,10 @@
1
- import typing as ta
2
-
3
1
  from omlish import inject as inj
4
2
  from omlish import lang
5
3
 
6
4
  from ...phases.injection import phase_callbacks
7
5
  from ...phases.types import ChatPhase
8
6
  from ...phases.types import ChatPhaseCallback
7
+ from .configs import StateConfig
9
8
 
10
9
 
11
10
  with lang.auto_proxy_import(globals()):
@@ -17,24 +16,21 @@ with lang.auto_proxy_import(globals()):
17
16
  ##
18
17
 
19
18
 
20
- def bind_state(
21
- *,
22
- state: ta.Literal['new', 'continue', 'ephemeral'] = 'continue',
23
- ) -> inj.Elements:
19
+ def bind_state(cfg: StateConfig = StateConfig()) -> inj.Elements:
24
20
  els: list[inj.Elemental] = []
25
21
 
26
- if state in ('continue', 'new'):
22
+ if cfg.state in ('continue', 'new'):
27
23
  els.append(inj.bind(_types.ChatStateManager, to_ctor=_storage.StateStorageChatStateManager, singleton=True))
28
24
 
29
- if state == 'new':
25
+ if cfg.state == 'new':
30
26
  els.append(phase_callbacks().bind_item(to_fn=lang.typed_lambda(cm=_types.ChatStateManager)(
31
27
  lambda cm: ChatPhaseCallback(ChatPhase.STARTING, cm.clear_state),
32
28
  )))
33
29
 
34
- elif state == 'ephemeral':
30
+ elif cfg.state == 'ephemeral':
35
31
  els.append(inj.bind(_types.ChatStateManager, to_ctor=_inmemory.InMemoryChatStateManager, singleton=True))
36
32
 
37
33
  else:
38
- raise TypeError(state)
34
+ raise TypeError(cfg.state)
39
35
 
40
36
  return inj.as_elements(*els)
@@ -1,5 +1,4 @@
1
- import dataclasses as dc
2
-
1
+ from omlish import dataclasses as dc
3
2
  from omlish import lang
4
3
 
5
4
  from ...... import minichain as mc
@@ -1,6 +1,5 @@
1
- import dataclasses as dc
2
-
3
1
  from omlish import check
2
+ from omlish import dataclasses as dc
4
3
  from omlish import lang
5
4
 
6
5
  from ...... import minichain as mc
@@ -1,8 +1,8 @@
1
1
  import abc
2
- import dataclasses as dc
3
2
  import datetime
4
3
  import typing as ta
5
4
 
5
+ from omlish import dataclasses as dc
6
6
  from omlish import lang
7
7
 
8
8
  from ...... import minichain as mc
@@ -0,0 +1,17 @@
1
+ import typing as ta
2
+
3
+ from omlish import dataclasses as dc
4
+
5
+ from ...... import minichain as mc
6
+
7
+
8
+ ##
9
+
10
+
11
+ @dc.dataclass(frozen=True, kw_only=True)
12
+ class UserConfig:
13
+ initial_system_content: ta.Optional['mc.Content'] = None
14
+ initial_user_content: ta.Optional['mc.Content'] = None
15
+
16
+ interactive: bool = False
17
+ use_readline: bool | ta.Literal['auto'] = 'auto'
@@ -1,5 +1,3 @@
1
- import typing as ta
2
-
3
1
  from omlish import inject as inj
4
2
  from omlish import lang
5
3
 
@@ -7,11 +5,13 @@ from ...... import minichain as mc
7
5
  from ...phases.injection import phase_callbacks
8
6
  from ...phases.types import ChatPhase
9
7
  from ...phases.types import ChatPhaseCallback
8
+ from .configs import UserConfig
10
9
 
11
10
 
12
11
  with lang.auto_proxy_import(globals()):
12
+ from .....inputs import asyncs as _inputs_asyncs
13
+ from .....inputs import sync as _inputs_sync
13
14
  from ..state import types as _state
14
- from . import inputs as _inputs
15
15
  from . import interactive as _interactive
16
16
  from . import oneshot as _oneshot
17
17
  from . import types as _types
@@ -20,28 +20,22 @@ with lang.auto_proxy_import(globals()):
20
20
  ##
21
21
 
22
22
 
23
- def bind_user(
24
- *,
25
- initial_system_content: ta.Optional['mc.Content'] = None,
26
- initial_user_content: ta.Optional['mc.Content'] = None,
27
- interactive: bool = False,
28
- use_readline: bool | ta.Literal['auto'] = False,
29
- ) -> inj.Elements:
23
+ def bind_user(cfg: UserConfig = UserConfig()) -> inj.Elements:
30
24
  els: list[inj.Elemental] = []
31
25
 
32
26
  # FIXME: barf
33
- if initial_system_content is not None:
27
+ if cfg.initial_system_content is not None:
34
28
  async def add_initial_system_content(cm: '_state.ChatStateManager') -> None:
35
- await cm.extend_chat([mc.SystemMessage(initial_system_content)])
29
+ await cm.extend_chat([mc.SystemMessage(cfg.initial_system_content)])
36
30
 
37
31
  els.append(phase_callbacks().bind_item(to_fn=lang.typed_lambda(cm=_state.ChatStateManager)(
38
32
  lambda cm: ChatPhaseCallback(ChatPhase.STARTED, lambda: add_initial_system_content(cm)),
39
33
  )))
40
34
 
41
- if interactive:
42
- if initial_user_content is not None:
35
+ if cfg.interactive:
36
+ if cfg.initial_user_content is not None:
43
37
  async def add_initial_user_content(cm: '_state.ChatStateManager') -> None:
44
- await cm.extend_chat([mc.UserMessage(initial_user_content)])
38
+ await cm.extend_chat([mc.UserMessage(cfg.initial_user_content)])
45
39
 
46
40
  els.append(phase_callbacks().bind_item(to_fn=lang.typed_lambda(cm=_state.ChatStateManager)(
47
41
  lambda cm: ChatPhaseCallback(ChatPhase.STARTED, lambda: add_initial_user_content(cm)),
@@ -52,16 +46,16 @@ def bind_user(
52
46
  els.append(inj.bind(_types.UserChatInput, to_ctor=_interactive.InteractiveUserChatInput, singleton=True))
53
47
 
54
48
  els.extend([
55
- inj.bind(_inputs.SyncStringInput, to_const=_inputs.InputSyncStringInput(use_readline=use_readline)), # noqa
56
- inj.bind(_inputs.AsyncStringInput, to_ctor=_inputs.ThreadAsyncStringInput, singleton=True),
49
+ inj.bind(_inputs_sync.SyncStringInput, to_const=_inputs_sync.InputSyncStringInput(use_readline=cfg.use_readline)), # noqa
50
+ inj.bind(_inputs_asyncs.AsyncStringInput, to_ctor=_inputs_asyncs.ThreadAsyncStringInput, singleton=True),
57
51
  ])
58
52
 
59
53
  else:
60
- if initial_user_content is None:
54
+ if cfg.initial_user_content is None:
61
55
  raise ValueError('Initial user content is required for non-interactive chat')
62
56
 
63
57
  els.extend([
64
- inj.bind(_oneshot.OneshotUserChatInputInitialChat, to_const=[mc.UserMessage(initial_user_content)]),
58
+ inj.bind(_oneshot.OneshotUserChatInputInitialChat, to_const=[mc.UserMessage(cfg.initial_user_content)]),
65
59
  inj.bind(_types.UserChatInput, to_ctor=_oneshot.OneshotUserChatInput, singleton=True),
66
60
  ])
67
61
 
@@ -1,9 +1,9 @@
1
1
  import typing as ta
2
2
 
3
3
  from ...... import minichain as mc
4
- from .inputs import AsyncStringInput
5
- from .inputs import InputSyncStringInput
6
- from .inputs import SyncAsyncStringInput
4
+ from .....inputs.asyncs import AsyncStringInput
5
+ from .....inputs.asyncs import SyncAsyncStringInput
6
+ from .....inputs.sync import InputSyncStringInput
7
7
  from .types import UserChatInput
8
8
 
9
9
 
@@ -1,38 +1,27 @@
1
- import dataclasses as dc
2
- import typing as ta
1
+ from omlish import dataclasses as dc
3
2
 
4
- from .... import minichain as mc
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
5
9
 
6
10
 
7
11
  ##
8
12
 
9
13
 
10
- DEFAULT_CHAT_MODEL_BACKEND = 'openai'
14
+ DEFAULT_BACKEND = 'openai'
11
15
 
12
16
 
13
17
  ##
14
18
 
15
19
 
16
- @dc.dataclass(frozen=True)
20
+ @dc.dataclass(frozen=True, kw_only=True)
17
21
  class ChatConfig:
18
- _: dc.KW_ONLY
19
-
20
- backend: str | None = None
21
- model_name: str | None = None
22
-
23
- state: ta.Literal['new', 'continue', 'ephemeral'] = 'continue'
24
-
25
- initial_system_content: ta.Optional['mc.Content'] = None
26
- initial_user_content: ta.Optional['mc.Content'] = None
27
-
28
- interactive: bool = False
29
- use_readline: bool | ta.Literal['auto'] = 'auto'
30
-
31
- silent: bool = False
32
- markdown: bool = False
33
-
34
- stream: bool = False
35
-
36
- enable_tools: bool = False
37
- enabled_tools: ta.AbstractSet[str] | None = None
38
- dangerous_no_tool_confirmation: bool = False
22
+ backend: BackendConfig = BackendConfig()
23
+ ai: AiConfig = AiConfig()
24
+ state: StateConfig = StateConfig()
25
+ user: UserConfig = UserConfig()
26
+ rendering: RenderingConfig = RenderingConfig()
27
+ tools: ToolsConfig = ToolsConfig()
@@ -2,20 +2,21 @@ from omlish import dataclasses as dc
2
2
  from omlish import inject as inj
3
3
  from omlish import lang
4
4
 
5
+ from ...backends.types import DefaultBackendName
5
6
  from ..base import Session
6
- from .configs import DEFAULT_CHAT_MODEL_BACKEND
7
+ from .configs import DEFAULT_BACKEND
7
8
  from .configs import ChatConfig
8
9
 
9
10
 
10
11
  with lang.auto_proxy_import(globals()):
12
+ from ...backends import inject as _backends
13
+ from ...rendering import inject as _rendering
11
14
  from . import driver as _driver
12
15
  from . import session as _session
13
- from .backends import inject as _backends
14
16
  from .chat.ai import inject as _chat_ai
15
17
  from .chat.state import inject as _chat_state
16
18
  from .chat.user import inject as _chat_user
17
19
  from .phases import inject as _phases
18
- from .rendering import inject as _rendering
19
20
  from .tools import inject as _tools
20
21
 
21
22
 
@@ -28,42 +29,20 @@ def bind_chat(cfg: ChatConfig) -> inj.Elements:
28
29
  #
29
30
 
30
31
  els.extend([
31
- _backends.bind_backends(
32
- backend=cfg.backend or DEFAULT_CHAT_MODEL_BACKEND,
33
- ),
34
-
35
- _chat_ai.bind_ai(
36
- stream=cfg.stream,
37
- silent=cfg.silent,
38
- enable_tools=cfg.enable_tools,
39
- ),
40
-
41
- _chat_user.bind_user(
42
- initial_system_content=cfg.initial_system_content,
43
- initial_user_content=cfg.initial_user_content,
44
- interactive=cfg.interactive,
45
- use_readline=cfg.use_readline,
46
- ),
47
-
48
- _chat_state.bind_state(
49
- state=cfg.state,
50
- ),
32
+ _backends.bind_backends(cfg.backend),
51
33
 
52
- _phases.bind_phases(),
34
+ _chat_ai.bind_ai(cfg.ai),
53
35
 
54
- _rendering.bind_rendering(
55
- markdown=cfg.markdown,
56
- ),
57
- ])
36
+ _chat_user.bind_user(cfg.user),
58
37
 
59
- #
38
+ _chat_state.bind_state(cfg.state),
39
+
40
+ _phases.bind_phases(),
60
41
 
61
- if cfg.enable_tools:
62
- els.append(_tools.bind_tools(
63
- silent=cfg.silent,
64
- dangerous_no_confirmation=cfg.dangerous_no_tool_confirmation,
65
- enabled_tools=cfg.enabled_tools,
66
- ))
42
+ _rendering.bind_rendering(cfg.rendering),
43
+
44
+ _tools.bind_tools(cfg.tools),
45
+ ])
67
46
 
68
47
  #
69
48
 
@@ -80,4 +59,8 @@ def bind_chat(cfg: ChatConfig) -> inj.Elements:
80
59
 
81
60
  #
82
61
 
62
+ els.append(inj.bind(DefaultBackendName, to_const=DEFAULT_BACKEND))
63
+
64
+ #
65
+
83
66
  return inj.as_elements(*els)
@@ -1,4 +1,4 @@
1
- import dataclasses as dc
1
+ from omlish import dataclasses as dc
2
2
 
3
3
  from ..base import Session
4
4
  from .configs import ChatConfig
@@ -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
File without changes
@@ -0,0 +1,12 @@
1
+ from omlish import dataclasses as dc
2
+ from omlish import lang
3
+
4
+ from ..configs import ToolSetConfig
5
+
6
+
7
+ ##
8
+
9
+
10
+ @dc.dataclass(frozen=True, kw_only=True)
11
+ class FsToolSetConfig(ToolSetConfig, lang.Final):
12
+ pass
@@ -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)
@@ -1,12 +1,10 @@
1
- import os
2
- import typing as ta
3
-
4
1
  from omlish import check
5
2
  from omlish import inject as inj
6
3
  from omlish import lang
7
4
 
8
5
  from ..... import minichain as mc
9
- from .injection import bind_tool_context_provider_to_key
6
+ from .configs import ToolsConfig
7
+ from .injection import ToolSetBinder
10
8
  from .injection import tool_catalog_entries
11
9
  from .injection import tool_context_providers
12
10
 
@@ -20,65 +18,6 @@ with lang.auto_proxy_import(globals()):
20
18
  ##
21
19
 
22
20
 
23
- _TOOL_BINDERS: dict[str, ta.Callable[[], inj.Elements]] = {}
24
-
25
-
26
- def _tool_binder(name: str) -> ta.Callable[[ta.Callable[[], inj.Elements]], ta.Callable[[], inj.Elements]]:
27
- def inner(fn):
28
- check.not_in(name, _TOOL_BINDERS)
29
- _TOOL_BINDERS[name] = fn
30
- return fn
31
- return inner
32
-
33
-
34
- #
35
-
36
-
37
- @_tool_binder('weather')
38
- def _bind_weather_tool() -> inj.Elements:
39
- from .weather import WEATHER_TOOL
40
-
41
- return inj.as_elements(
42
- tool_catalog_entries().bind_item_consts(WEATHER_TOOL),
43
- )
44
-
45
-
46
- @_tool_binder('todo')
47
- def _bind_todo_tools() -> inj.Elements:
48
- from .....minichain.lib.todo.context import TodoContext
49
- from .....minichain.lib.todo.tools.read import todo_read_tool
50
- from .....minichain.lib.todo.tools.write import todo_write_tool
51
-
52
- return inj.as_elements(
53
- tool_catalog_entries().bind_item_consts(
54
- todo_read_tool(),
55
- todo_write_tool(),
56
- ),
57
-
58
- inj.bind(TodoContext()),
59
- bind_tool_context_provider_to_key(TodoContext),
60
- )
61
-
62
-
63
- @_tool_binder('fs')
64
- def _bind_fs_tools() -> inj.Elements:
65
- from .....minichain.lib.fs.context import FsContext
66
- from .....minichain.lib.fs.tools.ls import ls_tool
67
- from .....minichain.lib.fs.tools.read import read_tool
68
-
69
- return inj.as_elements(
70
- tool_catalog_entries().bind_item_consts(
71
- ls_tool(),
72
- read_tool(),
73
- ),
74
-
75
- inj.bind(FsContext(
76
- root_dir=os.getcwd(),
77
- )),
78
- bind_tool_context_provider_to_key(FsContext),
79
- )
80
-
81
-
82
21
  # if tools_config.enable_unsafe_tools_do_not_use_lol:
83
22
  # from ...minichain.lib.bash import bash_tool
84
23
  # els.append(bind_tool(bash_tool()))
@@ -90,12 +29,7 @@ def _bind_fs_tools() -> inj.Elements:
90
29
  ##
91
30
 
92
31
 
93
- def bind_tools(
94
- *,
95
- silent: bool = False,
96
- dangerous_no_confirmation: bool = False,
97
- enabled_tools: ta.Iterable[str] | None = None,
98
- ) -> inj.Elements:
32
+ def bind_tools(cfg: ToolsConfig = ToolsConfig()) -> inj.Elements:
99
33
  els: list[inj.Elemental] = []
100
34
 
101
35
  #
@@ -106,8 +40,17 @@ def bind_tools(
106
40
 
107
41
  els.append(tool_catalog_entries().bind_items_provider(singleton=True))
108
42
 
109
- for etn in check.not_isinstance(enabled_tools or [], str):
110
- els.append(_TOOL_BINDERS[etn]())
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()))
111
54
 
112
55
  #
113
56
 
@@ -115,10 +58,10 @@ def bind_tools(
115
58
 
116
59
  els.append(exec_stack.push_bind(to_ctor=_execution.ToolUseExecutorImpl, singleton=True))
117
60
 
118
- if not silent:
61
+ if not cfg.silent:
119
62
  els.append(exec_stack.push_bind(to_ctor=_rendering.ResultRenderingToolUseExecutor, singleton=True))
120
63
 
121
- if dangerous_no_confirmation:
64
+ if cfg.dangerous_no_confirmation:
122
65
  els.append(exec_stack.push_bind(to_ctor=_rendering.ArgsRenderingToolUseExecutor, singleton=True))
123
66
 
124
67
  els.extend([
@@ -127,7 +70,7 @@ def bind_tools(
127
70
 
128
71
  #
129
72
 
130
- if not dangerous_no_confirmation:
73
+ if not cfg.dangerous_no_confirmation:
131
74
  els.append(inj.bind(_confirmation.ToolExecutionConfirmation, to_ctor=_confirmation.InteractiveToolExecutionConfirmation, singleton=True)) # noqa
132
75
 
133
76
  #
@@ -1,14 +1,20 @@
1
1
  import typing as ta
2
2
 
3
+ from omlish import dataclasses as dc
3
4
  from omlish import inject as inj
4
5
  from omlish import lang
5
6
 
6
7
  from ..... import minichain as mc
8
+ from .configs import ToolSetConfig
7
9
 
8
10
 
9
11
  with lang.auto_proxy_import(globals()):
10
12
  from . import execution as _execution
11
13
 
14
+
15
+ ToolSetConfigT = ta.TypeVar('ToolSetConfigT', bound='ToolSetConfig')
16
+
17
+
12
18
  ##
13
19
 
14
20
 
@@ -27,3 +33,12 @@ def bind_tool_context_provider_to_key(key: ta.Any) -> inj.Elements:
27
33
  lambda v: _execution.ToolContextProvider(lambda: [v]),
28
34
  v=key,
29
35
  ), singleton=True)
36
+
37
+
38
+ ##
39
+
40
+
41
+ @dc.dataclass(frozen=True)
42
+ class ToolSetBinder(lang.Final, ta.Generic[ToolSetConfigT]):
43
+ cfg_cls: type[ToolSetConfig]
44
+ fn: ta.Callable[[ToolSetConfigT], inj.Elements]
@@ -1,7 +1,7 @@
1
1
  import typing as ta
2
2
 
3
3
  from ..... import minichain as mc
4
- from ..rendering.types import ContentRendering
4
+ from ....rendering.types import ContentRendering
5
5
  from .execution import ToolUseExecutor
6
6
 
7
7
 
File without changes