ommlds 0.0.0.dev426__py3-none-any.whl → 0.0.0.dev485__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 (295) hide show
  1. ommlds/.omlish-manifests.json +336 -39
  2. ommlds/__about__.py +16 -10
  3. ommlds/_hacks/__init__.py +4 -0
  4. ommlds/_hacks/funcs.py +110 -0
  5. ommlds/_hacks/names.py +158 -0
  6. ommlds/_hacks/params.py +73 -0
  7. ommlds/_hacks/patches.py +0 -3
  8. ommlds/backends/anthropic/protocol/__init__.py +13 -1
  9. ommlds/backends/anthropic/protocol/_dataclasses.py +1625 -0
  10. ommlds/backends/anthropic/protocol/_marshal.py +2 -2
  11. ommlds/backends/anthropic/protocol/sse/_marshal.py +1 -1
  12. ommlds/backends/anthropic/protocol/sse/assemble.py +23 -7
  13. ommlds/backends/anthropic/protocol/sse/events.py +13 -0
  14. ommlds/backends/anthropic/protocol/types.py +40 -8
  15. ommlds/backends/google/protocol/__init__.py +16 -0
  16. ommlds/backends/google/protocol/_dataclasses.py +5997 -0
  17. ommlds/backends/google/protocol/_marshal.py +16 -0
  18. ommlds/backends/google/protocol/types.py +626 -0
  19. ommlds/backends/groq/__init__.py +7 -0
  20. ommlds/backends/groq/_dataclasses.py +3901 -0
  21. ommlds/backends/groq/_marshal.py +23 -0
  22. ommlds/backends/groq/protocol.py +249 -0
  23. ommlds/backends/llamacpp/logging.py +4 -1
  24. ommlds/backends/mlx/caching.py +7 -3
  25. ommlds/backends/mlx/cli.py +10 -7
  26. ommlds/backends/mlx/generation.py +19 -17
  27. ommlds/backends/mlx/limits.py +10 -6
  28. ommlds/backends/mlx/loading.py +65 -5
  29. ommlds/backends/ollama/__init__.py +7 -0
  30. ommlds/backends/ollama/_dataclasses.py +3458 -0
  31. ommlds/backends/ollama/protocol.py +170 -0
  32. ommlds/backends/openai/protocol/__init__.py +24 -29
  33. ommlds/backends/openai/protocol/_common.py +18 -0
  34. ommlds/backends/openai/protocol/_dataclasses.py +7708 -0
  35. ommlds/backends/openai/protocol/_marshal.py +27 -0
  36. ommlds/backends/openai/protocol/chatcompletion/chunk.py +58 -31
  37. ommlds/backends/openai/protocol/chatcompletion/contentpart.py +49 -44
  38. ommlds/backends/openai/protocol/chatcompletion/message.py +55 -43
  39. ommlds/backends/openai/protocol/chatcompletion/request.py +114 -66
  40. ommlds/backends/openai/protocol/chatcompletion/response.py +71 -45
  41. ommlds/backends/openai/protocol/chatcompletion/responseformat.py +27 -20
  42. ommlds/backends/openai/protocol/chatcompletion/tokenlogprob.py +16 -7
  43. ommlds/backends/openai/protocol/completionusage.py +24 -15
  44. ommlds/backends/tavily/__init__.py +7 -0
  45. ommlds/backends/tavily/_dataclasses.py +1734 -0
  46. ommlds/backends/tavily/protocol.py +301 -0
  47. ommlds/backends/tinygrad/models/llama3/__init__.py +22 -14
  48. ommlds/backends/transformers/__init__.py +14 -0
  49. ommlds/backends/transformers/filecache.py +109 -0
  50. ommlds/backends/transformers/streamers.py +73 -0
  51. ommlds/cli/__init__.py +7 -0
  52. ommlds/cli/_dataclasses.py +2562 -0
  53. ommlds/cli/asyncs.py +30 -0
  54. ommlds/cli/backends/catalog.py +93 -0
  55. ommlds/cli/backends/configs.py +9 -0
  56. ommlds/cli/backends/inject.py +31 -36
  57. ommlds/cli/backends/injection.py +16 -0
  58. ommlds/cli/backends/types.py +46 -0
  59. ommlds/cli/content/messages.py +34 -0
  60. ommlds/cli/content/strings.py +42 -0
  61. ommlds/cli/inject.py +17 -32
  62. ommlds/cli/inputs/__init__.py +0 -0
  63. ommlds/cli/inputs/asyncs.py +32 -0
  64. ommlds/cli/inputs/sync.py +75 -0
  65. ommlds/cli/main.py +270 -110
  66. ommlds/cli/rendering/__init__.py +0 -0
  67. ommlds/cli/rendering/configs.py +9 -0
  68. ommlds/cli/rendering/inject.py +31 -0
  69. ommlds/cli/rendering/markdown.py +52 -0
  70. ommlds/cli/rendering/raw.py +73 -0
  71. ommlds/cli/rendering/types.py +21 -0
  72. ommlds/cli/secrets.py +21 -0
  73. ommlds/cli/sessions/base.py +1 -1
  74. ommlds/cli/sessions/chat/chat/__init__.py +0 -0
  75. ommlds/cli/sessions/chat/chat/ai/__init__.py +0 -0
  76. ommlds/cli/sessions/chat/chat/ai/configs.py +11 -0
  77. ommlds/cli/sessions/chat/chat/ai/inject.py +74 -0
  78. ommlds/cli/sessions/chat/chat/ai/injection.py +14 -0
  79. ommlds/cli/sessions/chat/chat/ai/rendering.py +70 -0
  80. ommlds/cli/sessions/chat/chat/ai/services.py +79 -0
  81. ommlds/cli/sessions/chat/chat/ai/tools.py +44 -0
  82. ommlds/cli/sessions/chat/chat/ai/types.py +28 -0
  83. ommlds/cli/sessions/chat/chat/state/__init__.py +0 -0
  84. ommlds/cli/sessions/chat/chat/state/configs.py +11 -0
  85. ommlds/cli/sessions/chat/chat/state/inject.py +36 -0
  86. ommlds/cli/sessions/chat/chat/state/inmemory.py +33 -0
  87. ommlds/cli/sessions/chat/chat/state/storage.py +52 -0
  88. ommlds/cli/sessions/chat/chat/state/types.py +38 -0
  89. ommlds/cli/sessions/chat/chat/user/__init__.py +0 -0
  90. ommlds/cli/sessions/chat/chat/user/configs.py +17 -0
  91. ommlds/cli/sessions/chat/chat/user/inject.py +62 -0
  92. ommlds/cli/sessions/chat/chat/user/interactive.py +31 -0
  93. ommlds/cli/sessions/chat/chat/user/oneshot.py +25 -0
  94. ommlds/cli/sessions/chat/chat/user/types.py +15 -0
  95. ommlds/cli/sessions/chat/configs.py +27 -0
  96. ommlds/cli/sessions/chat/driver.py +43 -0
  97. ommlds/cli/sessions/chat/inject.py +33 -65
  98. ommlds/cli/sessions/chat/phases/__init__.py +0 -0
  99. ommlds/cli/sessions/chat/phases/inject.py +27 -0
  100. ommlds/cli/sessions/chat/phases/injection.py +14 -0
  101. ommlds/cli/sessions/chat/phases/manager.py +29 -0
  102. ommlds/cli/sessions/chat/phases/types.py +29 -0
  103. ommlds/cli/sessions/chat/session.py +27 -0
  104. ommlds/cli/sessions/chat/tools/__init__.py +0 -0
  105. ommlds/cli/sessions/chat/tools/configs.py +22 -0
  106. ommlds/cli/sessions/chat/tools/confirmation.py +46 -0
  107. ommlds/cli/sessions/chat/tools/execution.py +66 -0
  108. ommlds/cli/sessions/chat/tools/fs/__init__.py +0 -0
  109. ommlds/cli/sessions/chat/tools/fs/configs.py +12 -0
  110. ommlds/cli/sessions/chat/tools/fs/inject.py +35 -0
  111. ommlds/cli/sessions/chat/tools/inject.py +88 -0
  112. ommlds/cli/sessions/chat/tools/injection.py +44 -0
  113. ommlds/cli/sessions/chat/tools/rendering.py +58 -0
  114. ommlds/cli/sessions/chat/tools/todo/__init__.py +0 -0
  115. ommlds/cli/sessions/chat/tools/todo/configs.py +12 -0
  116. ommlds/cli/sessions/chat/tools/todo/inject.py +31 -0
  117. ommlds/cli/sessions/chat/tools/weather/__init__.py +0 -0
  118. ommlds/cli/sessions/chat/tools/weather/configs.py +12 -0
  119. ommlds/cli/sessions/chat/tools/weather/inject.py +22 -0
  120. ommlds/cli/{tools/weather.py → sessions/chat/tools/weather/tools.py} +1 -1
  121. ommlds/cli/sessions/completion/configs.py +21 -0
  122. ommlds/cli/sessions/completion/inject.py +42 -0
  123. ommlds/cli/sessions/completion/session.py +35 -0
  124. ommlds/cli/sessions/embedding/configs.py +21 -0
  125. ommlds/cli/sessions/embedding/inject.py +42 -0
  126. ommlds/cli/sessions/embedding/session.py +33 -0
  127. ommlds/cli/sessions/inject.py +28 -11
  128. ommlds/cli/state/__init__.py +0 -0
  129. ommlds/cli/state/inject.py +28 -0
  130. ommlds/cli/{state.py → state/storage.py} +41 -24
  131. ommlds/minichain/__init__.py +84 -24
  132. ommlds/minichain/_dataclasses.py +15401 -0
  133. ommlds/minichain/_marshal.py +49 -9
  134. ommlds/minichain/_typedvalues.py +2 -4
  135. ommlds/minichain/backends/catalogs/base.py +20 -1
  136. ommlds/minichain/backends/catalogs/simple.py +2 -2
  137. ommlds/minichain/backends/catalogs/strings.py +10 -8
  138. ommlds/minichain/backends/impls/anthropic/chat.py +65 -27
  139. ommlds/minichain/backends/impls/anthropic/names.py +10 -8
  140. ommlds/minichain/backends/impls/anthropic/protocol.py +109 -0
  141. ommlds/minichain/backends/impls/anthropic/stream.py +111 -43
  142. ommlds/minichain/backends/impls/duckduckgo/search.py +6 -2
  143. ommlds/minichain/backends/impls/dummy/__init__.py +0 -0
  144. ommlds/minichain/backends/impls/dummy/chat.py +69 -0
  145. ommlds/minichain/backends/impls/google/chat.py +114 -22
  146. ommlds/minichain/backends/impls/google/search.py +7 -2
  147. ommlds/minichain/backends/impls/google/stream.py +219 -0
  148. ommlds/minichain/backends/impls/google/tools.py +149 -0
  149. ommlds/minichain/backends/impls/groq/__init__.py +0 -0
  150. ommlds/minichain/backends/impls/groq/chat.py +75 -0
  151. ommlds/minichain/backends/impls/groq/names.py +48 -0
  152. ommlds/minichain/backends/impls/groq/protocol.py +143 -0
  153. ommlds/minichain/backends/impls/groq/stream.py +125 -0
  154. ommlds/minichain/backends/impls/huggingface/repos.py +1 -5
  155. ommlds/minichain/backends/impls/llamacpp/chat.py +40 -22
  156. ommlds/minichain/backends/impls/llamacpp/completion.py +9 -5
  157. ommlds/minichain/backends/impls/llamacpp/format.py +4 -2
  158. ommlds/minichain/backends/impls/llamacpp/stream.py +43 -23
  159. ommlds/minichain/backends/impls/mistral.py +20 -5
  160. ommlds/minichain/backends/impls/mlx/chat.py +101 -24
  161. ommlds/minichain/backends/impls/ollama/__init__.py +0 -0
  162. ommlds/minichain/backends/impls/ollama/chat.py +199 -0
  163. ommlds/minichain/backends/impls/openai/chat.py +18 -8
  164. ommlds/minichain/backends/impls/openai/completion.py +10 -3
  165. ommlds/minichain/backends/impls/openai/embedding.py +10 -3
  166. ommlds/minichain/backends/impls/openai/format.py +131 -106
  167. ommlds/minichain/backends/impls/openai/names.py +31 -5
  168. ommlds/minichain/backends/impls/openai/stream.py +43 -25
  169. ommlds/minichain/backends/impls/sentencepiece/tokens.py +9 -6
  170. ommlds/minichain/backends/impls/tavily.py +66 -0
  171. ommlds/minichain/backends/impls/tinygrad/chat.py +30 -20
  172. ommlds/minichain/backends/impls/tokenizers/tokens.py +9 -6
  173. ommlds/minichain/backends/impls/transformers/sentence.py +6 -3
  174. ommlds/minichain/backends/impls/transformers/tokens.py +10 -7
  175. ommlds/minichain/backends/impls/transformers/transformers.py +160 -37
  176. ommlds/minichain/backends/strings/parsing.py +1 -1
  177. ommlds/minichain/backends/strings/resolving.py +4 -1
  178. ommlds/minichain/chat/_marshal.py +16 -9
  179. ommlds/minichain/chat/choices/adapters.py +4 -4
  180. ommlds/minichain/chat/choices/services.py +1 -1
  181. ommlds/minichain/chat/choices/stream/__init__.py +0 -0
  182. ommlds/minichain/chat/choices/stream/adapters.py +35 -0
  183. ommlds/minichain/chat/choices/stream/joining.py +31 -0
  184. ommlds/minichain/chat/choices/stream/services.py +45 -0
  185. ommlds/minichain/chat/choices/stream/types.py +43 -0
  186. ommlds/minichain/chat/choices/types.py +2 -2
  187. ommlds/minichain/chat/history.py +3 -3
  188. ommlds/minichain/chat/messages.py +55 -19
  189. ommlds/minichain/chat/services.py +3 -3
  190. ommlds/minichain/chat/stream/_marshal.py +16 -0
  191. ommlds/minichain/chat/stream/joining.py +85 -0
  192. ommlds/minichain/chat/stream/services.py +15 -21
  193. ommlds/minichain/chat/stream/types.py +32 -19
  194. ommlds/minichain/chat/tools/execution.py +8 -7
  195. ommlds/minichain/chat/tools/ids.py +9 -15
  196. ommlds/minichain/chat/tools/parsing.py +17 -26
  197. ommlds/minichain/chat/transforms/base.py +29 -38
  198. ommlds/minichain/chat/transforms/metadata.py +30 -4
  199. ommlds/minichain/chat/transforms/services.py +9 -11
  200. ommlds/minichain/content/_marshal.py +44 -20
  201. ommlds/minichain/content/json.py +13 -0
  202. ommlds/minichain/content/materialize.py +14 -21
  203. ommlds/minichain/content/prepare.py +4 -0
  204. ommlds/minichain/content/transforms/interleave.py +1 -1
  205. ommlds/minichain/content/transforms/squeeze.py +1 -1
  206. ommlds/minichain/content/transforms/stringify.py +1 -1
  207. ommlds/minichain/json.py +20 -0
  208. ommlds/minichain/lib/code/__init__.py +0 -0
  209. ommlds/minichain/lib/code/prompts.py +6 -0
  210. ommlds/minichain/lib/fs/binfiles.py +108 -0
  211. ommlds/minichain/lib/fs/context.py +126 -0
  212. ommlds/minichain/lib/fs/errors.py +101 -0
  213. ommlds/minichain/lib/fs/suggestions.py +36 -0
  214. ommlds/minichain/lib/fs/tools/__init__.py +0 -0
  215. ommlds/minichain/lib/fs/tools/edit.py +104 -0
  216. ommlds/minichain/lib/fs/tools/ls.py +38 -0
  217. ommlds/minichain/lib/fs/tools/read.py +115 -0
  218. ommlds/minichain/lib/fs/tools/recursivels/__init__.py +0 -0
  219. ommlds/minichain/lib/fs/tools/recursivels/execution.py +40 -0
  220. ommlds/minichain/lib/todo/__init__.py +0 -0
  221. ommlds/minichain/lib/todo/context.py +54 -0
  222. ommlds/minichain/lib/todo/tools/__init__.py +0 -0
  223. ommlds/minichain/lib/todo/tools/read.py +44 -0
  224. ommlds/minichain/lib/todo/tools/write.py +335 -0
  225. ommlds/minichain/lib/todo/types.py +60 -0
  226. ommlds/minichain/llms/_marshal.py +25 -17
  227. ommlds/minichain/llms/types.py +4 -0
  228. ommlds/minichain/registries/globals.py +18 -4
  229. ommlds/minichain/resources.py +68 -45
  230. ommlds/minichain/search.py +1 -1
  231. ommlds/minichain/services/_marshal.py +46 -39
  232. ommlds/minichain/services/facades.py +3 -3
  233. ommlds/minichain/services/services.py +1 -1
  234. ommlds/minichain/standard.py +8 -0
  235. ommlds/minichain/stream/services.py +152 -38
  236. ommlds/minichain/stream/wrap.py +22 -24
  237. ommlds/minichain/text/toolparsing/llamacpp/hermes2.py +3 -2
  238. ommlds/minichain/text/toolparsing/llamacpp/llama31.py +3 -2
  239. ommlds/minichain/text/toolparsing/llamacpp/utils.py +3 -2
  240. ommlds/minichain/tools/_marshal.py +1 -1
  241. ommlds/minichain/tools/execution/catalog.py +2 -1
  242. ommlds/minichain/tools/execution/context.py +34 -14
  243. ommlds/minichain/tools/execution/errors.py +15 -0
  244. ommlds/minichain/tools/execution/executors.py +8 -3
  245. ommlds/minichain/tools/execution/reflect.py +40 -5
  246. ommlds/minichain/tools/fns.py +46 -9
  247. ommlds/minichain/tools/jsonschema.py +14 -5
  248. ommlds/minichain/tools/reflect.py +54 -18
  249. ommlds/minichain/tools/types.py +33 -1
  250. ommlds/minichain/utils.py +27 -0
  251. ommlds/minichain/vectors/_marshal.py +11 -10
  252. ommlds/minichain/vectors/types.py +1 -1
  253. ommlds/nanochat/LICENSE +21 -0
  254. ommlds/nanochat/__init__.py +0 -0
  255. ommlds/nanochat/rustbpe/LICENSE +21 -0
  256. ommlds/nanochat/tokenizers.py +406 -0
  257. ommlds/server/cli.py +1 -2
  258. ommlds/server/server.py +5 -5
  259. ommlds/server/service.py +1 -1
  260. ommlds/specs/__init__.py +0 -0
  261. ommlds/specs/mcp/__init__.py +0 -0
  262. ommlds/specs/mcp/_marshal.py +23 -0
  263. ommlds/specs/mcp/clients.py +146 -0
  264. ommlds/specs/mcp/protocol.py +371 -0
  265. ommlds/tools/git.py +35 -12
  266. ommlds/tools/ocr.py +8 -9
  267. ommlds/wiki/analyze.py +6 -7
  268. ommlds/wiki/text/mfh.py +1 -5
  269. ommlds/wiki/text/wtp.py +1 -3
  270. ommlds/wiki/utils/xml.py +5 -5
  271. {ommlds-0.0.0.dev426.dist-info → ommlds-0.0.0.dev485.dist-info}/METADATA +24 -21
  272. ommlds-0.0.0.dev485.dist-info/RECORD +436 -0
  273. ommlds/cli/backends/standard.py +0 -20
  274. ommlds/cli/sessions/chat/base.py +0 -42
  275. ommlds/cli/sessions/chat/interactive.py +0 -73
  276. ommlds/cli/sessions/chat/printing.py +0 -96
  277. ommlds/cli/sessions/chat/prompt.py +0 -143
  278. ommlds/cli/sessions/chat/state.py +0 -109
  279. ommlds/cli/sessions/chat/tools.py +0 -91
  280. ommlds/cli/sessions/completion/completion.py +0 -44
  281. ommlds/cli/sessions/embedding/embedding.py +0 -42
  282. ommlds/cli/tools/config.py +0 -13
  283. ommlds/cli/tools/inject.py +0 -64
  284. ommlds/minichain/chat/stream/adapters.py +0 -69
  285. ommlds/minichain/lib/fs/ls/execution.py +0 -32
  286. ommlds-0.0.0.dev426.dist-info/RECORD +0 -303
  287. /ommlds/{cli/tools → backends/google}/__init__.py +0 -0
  288. /ommlds/{huggingface.py → backends/huggingface.py} +0 -0
  289. /ommlds/{minichain/lib/fs/ls → cli/content}/__init__.py +0 -0
  290. /ommlds/minichain/lib/fs/{ls → tools/recursivels}/rendering.py +0 -0
  291. /ommlds/minichain/lib/fs/{ls → tools/recursivels}/running.py +0 -0
  292. {ommlds-0.0.0.dev426.dist-info → ommlds-0.0.0.dev485.dist-info}/WHEEL +0 -0
  293. {ommlds-0.0.0.dev426.dist-info → ommlds-0.0.0.dev485.dist-info}/entry_points.txt +0 -0
  294. {ommlds-0.0.0.dev426.dist-info → ommlds-0.0.0.dev485.dist-info}/licenses/LICENSE +0 -0
  295. {ommlds-0.0.0.dev426.dist-info → ommlds-0.0.0.dev485.dist-info}/top_level.txt +0 -0
ommlds/cli/asyncs.py ADDED
@@ -0,0 +1,30 @@
1
+ import abc
2
+ import functools
3
+ import typing as ta
4
+
5
+ from omlish import lang
6
+
7
+
8
+ with lang.auto_proxy_import(globals()):
9
+ import anyio
10
+
11
+
12
+ T = ta.TypeVar('T')
13
+ P = ta.ParamSpec('P')
14
+
15
+
16
+ ##
17
+
18
+
19
+ class AsyncThreadRunner(lang.Abstract):
20
+ @abc.abstractmethod
21
+ def run_in_thread(self, fn: ta.Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> ta.Awaitable[T]:
22
+ raise NotImplementedError
23
+
24
+
25
+ ##
26
+
27
+
28
+ class AnyioAsyncThreadRunner(AsyncThreadRunner):
29
+ def run_in_thread(self, fn: ta.Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> ta.Awaitable[T]:
30
+ return anyio.to_thread.run_sync(functools.partial(fn, *args, **kwargs))
@@ -0,0 +1,93 @@
1
+ import contextlib
2
+ import typing as ta
3
+
4
+ from omlish import lang
5
+
6
+ from ... import minichain as mc
7
+ from .types import BackendConfigs
8
+ from .types import BackendName
9
+ from .types import BackendProvider
10
+ from .types import ChatChoicesServiceBackendProvider
11
+ from .types import ChatChoicesStreamServiceBackendProvider
12
+ from .types import CompletionServiceBackendProvider
13
+ from .types import DefaultBackendName
14
+ from .types import EmbeddingServiceBackendProvider
15
+ from .types import ServiceT
16
+
17
+
18
+ ##
19
+
20
+
21
+ class CatalogBackendProvider(BackendProvider[ServiceT], lang.Abstract):
22
+ class Instantiator(lang.Func2['mc.BackendCatalog.Backend', BackendConfigs | None, ta.Awaitable[ta.Any]]):
23
+ pass
24
+
25
+ def __init__(
26
+ self,
27
+ *,
28
+ name: BackendName | None = None,
29
+ default_name: DefaultBackendName | None = None,
30
+ catalog: 'mc.BackendCatalog',
31
+ configs: BackendConfigs | None = None,
32
+ instantiator: Instantiator | None = None,
33
+ ) -> None:
34
+ super().__init__()
35
+
36
+ self._name = name
37
+ self._default_name = default_name
38
+ self._catalog = catalog
39
+ self._configs = configs
40
+ if instantiator is None:
41
+ instantiator = CatalogBackendProvider.Instantiator(lang.as_async(lambda be, cfgs: be.factory(*cfgs or [])))
42
+ self._instantiator = instantiator
43
+
44
+ @contextlib.asynccontextmanager
45
+ async def _provide_backend(self, cls: type[ServiceT]) -> ta.AsyncIterator[ServiceT]:
46
+ name: str
47
+ if self._name is not None:
48
+ name = self._name
49
+ elif self._default_name is not None:
50
+ name = self._default_name
51
+ else:
52
+ raise RuntimeError('No backend name specified')
53
+
54
+ be = self._catalog.get_backend(cls, name)
55
+
56
+ service: ServiceT
57
+ async with lang.async_or_sync_maybe_managing(await self._instantiator(be, self._configs)) as service:
58
+ yield service
59
+
60
+
61
+ ##
62
+
63
+
64
+ class CatalogChatChoicesServiceBackendProvider(
65
+ CatalogBackendProvider['mc.ChatChoicesService'],
66
+ ChatChoicesServiceBackendProvider,
67
+ ):
68
+ def provide_backend(self) -> ta.AsyncContextManager['mc.ChatChoicesService']:
69
+ return self._provide_backend(mc.ChatChoicesService) # type: ignore[type-abstract]
70
+
71
+
72
+ class CatalogChatChoicesStreamServiceBackendProvider(
73
+ CatalogBackendProvider['mc.ChatChoicesStreamService'],
74
+ ChatChoicesStreamServiceBackendProvider,
75
+ ):
76
+ def provide_backend(self) -> ta.AsyncContextManager['mc.ChatChoicesStreamService']:
77
+ return self._provide_backend(mc.ChatChoicesStreamService) # type: ignore[type-abstract]
78
+
79
+
80
+ class CatalogCompletionServiceBackendProvider(
81
+ CatalogBackendProvider['mc.CompletionService'],
82
+ CompletionServiceBackendProvider,
83
+ ):
84
+ def provide_backend(self) -> ta.AsyncContextManager['mc.CompletionService']:
85
+ return self._provide_backend(mc.CompletionService) # type: ignore[type-abstract]
86
+
87
+
88
+ class CatalogEmbeddingServiceBackendProvider(
89
+ CatalogBackendProvider['mc.EmbeddingService'],
90
+ EmbeddingServiceBackendProvider,
91
+ ):
92
+ def provide_backend(self) -> ta.AsyncContextManager['mc.EmbeddingService']:
93
+ return self._provide_backend(mc.EmbeddingService) # type: ignore[type-abstract]
@@ -0,0 +1,9 @@
1
+ from omlish import dataclasses as dc
2
+
3
+
4
+ ##
5
+
6
+
7
+ @dc.dataclass(frozen=True, kw_only=True)
8
+ class BackendConfig:
9
+ backend: str | None = None
@@ -2,69 +2,64 @@ import typing as ta
2
2
 
3
3
  from omlish import inject as inj
4
4
  from omlish import lang
5
+ from omlish import typedvalues as tv
5
6
 
6
7
  from ... import minichain as mc
8
+ from .configs import BackendConfig
9
+ from .injection import backend_configs
10
+
11
+
12
+ with lang.auto_proxy_import(globals()):
13
+ from ...minichain.backends.impls.huggingface import repos as hf_repos
14
+ from . import catalog as _catalog
15
+ from . import types as _types
7
16
 
8
17
 
9
18
  ##
10
19
 
11
20
 
12
- def bind_strings_backends() -> inj.Elements:
21
+ def bind_backends(cfg: BackendConfig = BackendConfig()) -> inj.Elements:
13
22
  lst: list[inj.Elemental] = []
14
23
 
24
+ #
25
+
15
26
  lst.extend([
16
27
  inj.bind(mc.BackendStringBackendCatalog, singleton=True),
17
28
  inj.bind(mc.BackendCatalog, to_key=mc.BackendStringBackendCatalog),
18
29
  ])
19
30
 
20
- from ...minichain.backends.impls.huggingface.repos import HuggingfaceModelRepoResolver
21
-
22
31
  lst.extend([
23
- inj.bind(HuggingfaceModelRepoResolver, singleton=True),
24
- inj.bind(mc.ModelRepoResolver, to_key=HuggingfaceModelRepoResolver),
32
+ inj.bind(hf_repos.HuggingfaceModelRepoResolver, singleton=True),
33
+ inj.bind(mc.ModelRepoResolver, to_key=hf_repos.HuggingfaceModelRepoResolver),
25
34
 
26
35
  ])
27
36
 
28
- return inj.as_elements(*lst)
29
-
30
-
31
- def bind_simple_backends() -> inj.Elements:
32
- lst: list[inj.Elemental] = []
37
+ #
33
38
 
34
- lst.extend([
35
- inj.set_binder[mc.SimpleBackendCatalogEntry](),
36
- inj.bind(
37
- lang.typed_lambda(mc.SimpleBackendCatalogEntries, s=ta.AbstractSet[mc.SimpleBackendCatalogEntry])(
38
- lambda s: list(s),
39
- ),
40
- singleton=True,
41
- ),
42
- ])
39
+ lst.append(backend_configs().bind_items_provider(singleton=True))
43
40
 
44
- lst.extend([
45
- inj.bind(mc.SimpleBackendCatalog, singleton=True),
46
- inj.bind(mc.BackendCatalog, to_key=mc.SimpleBackendCatalog),
47
- ])
41
+ #
48
42
 
49
- from .standard import STANDARD_BACKEND_CATALOG_ENTRIES
43
+ if cfg.backend is not None:
44
+ lst.append(inj.bind(_types.BackendName, to_const=cfg.backend))
50
45
 
51
46
  lst.extend([
52
- inj.bind_set_entry_const(ta.AbstractSet[mc.SimpleBackendCatalogEntry], e)
53
- for e in STANDARD_BACKEND_CATALOG_ENTRIES
47
+ inj.bind(_types.ChatChoicesServiceBackendProvider, to_ctor=_catalog.CatalogChatChoicesServiceBackendProvider, singleton=True), # noqa
48
+ inj.bind(_types.ChatChoicesStreamServiceBackendProvider, to_ctor=_catalog.CatalogChatChoicesStreamServiceBackendProvider, singleton=True), # noqa
49
+ inj.bind(_types.CompletionServiceBackendProvider, to_ctor=_catalog.CatalogCompletionServiceBackendProvider, singleton=True), # noqa
50
+ inj.bind(_types.EmbeddingServiceBackendProvider, to_ctor=_catalog.CatalogEmbeddingServiceBackendProvider, singleton=True), # noqa
54
51
  ])
55
52
 
56
- return inj.as_elements(*lst)
53
+ #
57
54
 
55
+ async def catalog_backend_instantiator_provider(injector: inj.AsyncInjector) -> _catalog.CatalogBackendProvider.Instantiator: # noqa
56
+ async def inner(be: 'mc.BackendCatalog.Backend', cfgs: _types.BackendConfigs | None) -> ta.Any:
57
+ kwt = inj.build_kwargs_target(be.factory, non_strict=True)
58
+ kw = await injector.provide_kwargs(kwt)
59
+ return be.factory(*tv.collect(*(be.configs or []), *(cfgs or []), override=True), **kw)
58
60
 
59
- def bind_backends(
60
- *,
61
- enable_backend_strings: bool = False,
62
- ) -> inj.Elements:
63
- lst: list[inj.Elemental] = []
61
+ return _catalog.CatalogBackendProvider.Instantiator(inner)
64
62
 
65
- if enable_backend_strings:
66
- lst.append(bind_strings_backends())
67
- else:
68
- lst.append(bind_simple_backends())
63
+ lst.append(inj.bind(_catalog.CatalogBackendProvider.Instantiator, to_async_fn=catalog_backend_instantiator_provider)) # noqa
69
64
 
70
65
  return inj.as_elements(*lst)
@@ -0,0 +1,16 @@
1
+ from omlish import inject as inj
2
+ from omlish import lang
3
+
4
+ from ... import minichain as mc
5
+
6
+
7
+ with lang.auto_proxy_import(globals()):
8
+ from . import types as _types
9
+
10
+
11
+ ##
12
+
13
+
14
+ @lang.cached_function
15
+ def backend_configs() -> 'inj.ItemsBinderHelper[mc.Config]':
16
+ return inj.items_binder_helper[mc.Config](_types.BackendConfigs)
@@ -0,0 +1,46 @@
1
+ import abc
2
+ import typing as ta
3
+
4
+ from omlish import lang
5
+
6
+ from ... import minichain as mc
7
+
8
+
9
+ ServiceT = ta.TypeVar('ServiceT', bound=mc.Service)
10
+
11
+
12
+ ##
13
+
14
+
15
+ BackendName = ta.NewType('BackendName', str)
16
+ DefaultBackendName = ta.NewType('DefaultBackendName', str)
17
+
18
+ BackendConfigs = ta.NewType('BackendConfigs', ta.Sequence['mc.Config'])
19
+
20
+
21
+ ##
22
+
23
+
24
+ class BackendProvider(lang.Abstract, ta.Generic[ServiceT]):
25
+ @abc.abstractmethod
26
+ def provide_backend(self) -> ta.AsyncContextManager[ServiceT]:
27
+ raise NotImplementedError
28
+
29
+
30
+ ##
31
+
32
+
33
+ class ChatChoicesServiceBackendProvider(BackendProvider['mc.ChatChoicesService'], lang.Abstract):
34
+ pass
35
+
36
+
37
+ class ChatChoicesStreamServiceBackendProvider(BackendProvider['mc.ChatChoicesStreamService'], lang.Abstract):
38
+ pass
39
+
40
+
41
+ class CompletionServiceBackendProvider(BackendProvider['mc.CompletionService'], lang.Abstract):
42
+ pass
43
+
44
+
45
+ class EmbeddingServiceBackendProvider(BackendProvider['mc.EmbeddingService'], lang.Abstract):
46
+ pass
@@ -0,0 +1,34 @@
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
+
9
+
10
+ ##
11
+
12
+
13
+ class MessageContentExtractor(lang.Abstract):
14
+ @abc.abstractmethod
15
+ def extract_message_content(self, message: 'mc.Message') -> ta.Optional['mc.Content']:
16
+ raise NotImplementedError
17
+
18
+
19
+ class MessageContentExtractorImpl(MessageContentExtractor):
20
+ def extract_message_content(self, message: 'mc.Message') -> ta.Optional['mc.Content']:
21
+ if isinstance(message, (mc.SystemMessage, mc.UserMessage, mc.AiMessage)):
22
+ if message.c is not None:
23
+ return check.isinstance(message.c, str)
24
+ else:
25
+ return None
26
+
27
+ elif isinstance(message, mc.ToolUseMessage):
28
+ return None
29
+
30
+ elif isinstance(message, mc.ToolUseResultMessage):
31
+ return check.isinstance(message.tur.c, str)
32
+
33
+ else:
34
+ raise TypeError(message)
@@ -0,0 +1,42 @@
1
+ import abc
2
+ import typing as ta
3
+
4
+ from omlish import lang
5
+ from omlish.formats import json
6
+
7
+ from ... import minichain as mc
8
+
9
+
10
+ ##
11
+
12
+
13
+ class ContentStringifier(lang.Abstract):
14
+ @abc.abstractmethod
15
+ def stringify_content(self, content: 'mc.Content') -> str | None:
16
+ raise NotImplementedError
17
+
18
+
19
+ class ContentStringifierImpl(ContentStringifier):
20
+ def stringify_content(self, content: 'mc.Content') -> str | None:
21
+ if isinstance(content, str):
22
+ return content
23
+
24
+ elif isinstance(content, mc.JsonContent):
25
+ return json.dumps_pretty(content.v)
26
+
27
+ else:
28
+ raise TypeError(content)
29
+
30
+
31
+ class HasContentStringifier(lang.Abstract):
32
+ def __init__(
33
+ self,
34
+ *args: ta.Any,
35
+ content_stringifier: ContentStringifier | None = None,
36
+ **kwargs: ta.Any,
37
+ ) -> None:
38
+ super().__init__(*args, **kwargs)
39
+
40
+ if content_stringifier is None:
41
+ content_stringifier = ContentStringifierImpl()
42
+ self._content_stringifier = content_stringifier
ommlds/cli/inject.py CHANGED
@@ -1,28 +1,13 @@
1
- import os.path
1
+ import typing as ta
2
2
 
3
- from omdev.home.paths import get_home_paths
4
3
  from omlish import inject as inj
4
+ from omlish import lang
5
5
 
6
- from .backends.inject import bind_backends
7
- from .sessions.base import Session
8
- from .sessions.inject import bind_sessions
9
- from .state import JsonFileStateStorage
10
- from .state import StateStorage
11
- from .tools.config import ToolsConfig
12
- from .tools.inject import bind_tools
13
6
 
14
-
15
- ##
16
-
17
-
18
- def _provide_state_storage() -> StateStorage:
19
- state_dir = os.path.join(get_home_paths().state_dir, 'minichain', 'cli')
20
- if not os.path.exists(state_dir):
21
- os.makedirs(state_dir, exist_ok=True)
22
- os.chmod(state_dir, 0o770) # noqa
23
-
24
- state_file = os.path.join(state_dir, 'state.json')
25
- return JsonFileStateStorage(state_file)
7
+ with lang.auto_proxy_import(globals()):
8
+ from . import asyncs
9
+ from .sessions import inject as _sessions
10
+ from .state import inject as _state
26
11
 
27
12
 
28
13
  ##
@@ -30,23 +15,23 @@ def _provide_state_storage() -> StateStorage:
30
15
 
31
16
  def bind_main(
32
17
  *,
33
- session_cfg: Session.Config,
34
- tools_config: ToolsConfig,
35
- enable_backend_strings: bool = False,
18
+ session_cfg: ta.Any,
36
19
  ) -> inj.Elements:
37
- els: list[inj.Elemental] = [
38
- bind_backends(
39
- enable_backend_strings=enable_backend_strings,
40
- ),
20
+ els: list[inj.Elemental] = []
21
+
22
+ #
41
23
 
42
- bind_sessions(session_cfg),
24
+ els.extend([
25
+ _sessions.bind_sessions(session_cfg),
43
26
 
44
- bind_tools(tools_config),
45
- ]
27
+ _state.bind_state(),
28
+ ])
46
29
 
47
30
  #
48
31
 
49
- els.append(inj.bind(_provide_state_storage, singleton=True))
32
+ els.extend([
33
+ inj.bind(asyncs.AsyncThreadRunner, to_ctor=asyncs.AnyioAsyncThreadRunner),
34
+ ])
50
35
 
51
36
  #
52
37
 
File without changes
@@ -0,0 +1,32 @@
1
+ import typing as ta
2
+
3
+ from .. import asyncs
4
+ from .sync import SyncStringInput
5
+
6
+
7
+ ##
8
+
9
+
10
+ class AsyncStringInput(ta.Protocol):
11
+ def __call__(self) -> ta.Awaitable[str]: ...
12
+
13
+
14
+ class ThreadAsyncStringInput:
15
+ def __init__(self, child: SyncStringInput, runner: asyncs.AsyncThreadRunner) -> None:
16
+ super().__init__()
17
+
18
+ self._child = child
19
+ self._runner = runner
20
+
21
+ async def __call__(self) -> str:
22
+ return await self._runner.run_in_thread(self._child)
23
+
24
+
25
+ class SyncAsyncStringInput:
26
+ def __init__(self, child: SyncStringInput) -> None:
27
+ super().__init__()
28
+
29
+ self._child = child
30
+
31
+ async def __call__(self) -> str:
32
+ return self._child()
@@ -0,0 +1,75 @@
1
+ import sys
2
+ import typing as ta
3
+
4
+ from omlish import check
5
+ from omlish import lang
6
+
7
+
8
+ with lang.auto_proxy_import(globals()):
9
+ from omlish.subprocesses import editor
10
+ from omlish.subprocesses import sync as sync_subprocesses
11
+
12
+
13
+ ##
14
+
15
+
16
+ class SyncStringInput(ta.Protocol):
17
+ def __call__(self) -> str: ...
18
+
19
+
20
+ class InputSyncStringInput:
21
+ DEFAULT_PROMPT: ta.ClassVar[str] = '> '
22
+
23
+ def __init__(
24
+ self,
25
+ prompt: str | None = None,
26
+ *,
27
+ use_readline: bool | ta.Literal['auto'] = False,
28
+ ) -> None:
29
+ super().__init__()
30
+
31
+ if prompt is None:
32
+ prompt = self.DEFAULT_PROMPT
33
+ self._prompt = prompt
34
+ self._use_readline = use_readline
35
+
36
+ self._handled_readline = False
37
+
38
+ def _handle_readline(self) -> None:
39
+ if self._handled_readline:
40
+ return
41
+ self._handled_readline = True
42
+
43
+ if not self._use_readline:
44
+ return
45
+
46
+ if self._use_readline == 'auto':
47
+ if not sys.stdin.isatty():
48
+ return
49
+
50
+ try:
51
+ import readline # noqa
52
+ except ImportError:
53
+ pass
54
+
55
+ def __call__(self) -> str:
56
+ self._handle_readline()
57
+ return input(self._prompt)
58
+
59
+
60
+ class FileSyncStringInput(InputSyncStringInput):
61
+ def __init__(self, path: str) -> None:
62
+ super().__init__()
63
+
64
+ self._path = check.non_empty_str(path)
65
+
66
+ def __call__(self) -> str:
67
+ with open(self._path) as f:
68
+ return f.read()
69
+
70
+
71
+ class UserEditorSyncStringInput(InputSyncStringInput):
72
+ def __call__(self) -> str:
73
+ if (ec := editor.edit_text_with_user_editor('', sync_subprocesses.subprocesses)) is None:
74
+ raise EOFError
75
+ return ec