ommlds 0.0.0.dev466__py3-none-any.whl → 0.0.0.dev512__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 (367) hide show
  1. ommlds/.omlish-manifests.json +404 -31
  2. ommlds/README.md +11 -0
  3. ommlds/__about__.py +21 -12
  4. ommlds/_hacks/__init__.py +4 -0
  5. ommlds/_hacks/funcs.py +110 -0
  6. ommlds/_hacks/names.py +158 -0
  7. ommlds/_hacks/params.py +73 -0
  8. ommlds/_hacks/patches.py +0 -3
  9. ommlds/backends/anthropic/protocol/__init__.py +13 -1
  10. ommlds/backends/anthropic/protocol/_dataclasses.py +1625 -0
  11. ommlds/backends/anthropic/protocol/sse/events.py +2 -0
  12. ommlds/backends/anthropic/protocol/types.py +5 -7
  13. ommlds/backends/cerebras/__init__.py +7 -0
  14. ommlds/backends/cerebras/_dataclasses.py +4254 -0
  15. ommlds/backends/cerebras/_marshal.py +24 -0
  16. ommlds/backends/cerebras/clients.py +9 -0
  17. ommlds/backends/cerebras/protocol.py +310 -0
  18. ommlds/backends/google/protocol/__init__.py +13 -0
  19. ommlds/backends/google/protocol/_dataclasses.py +5997 -0
  20. ommlds/backends/google/protocol/types.py +6 -8
  21. ommlds/backends/groq/__init__.py +7 -0
  22. ommlds/backends/groq/_dataclasses.py +3901 -0
  23. ommlds/backends/groq/_marshal.py +23 -0
  24. ommlds/backends/groq/clients.py +9 -0
  25. ommlds/backends/groq/protocol.py +247 -0
  26. ommlds/{huggingface.py → backends/huggingface/cache.py} +1 -6
  27. ommlds/backends/huggingface/cli.py +208 -0
  28. ommlds/backends/llamacpp/logging.py +4 -1
  29. ommlds/backends/mlx/caching.py +7 -3
  30. ommlds/backends/mlx/cli.py +10 -7
  31. ommlds/backends/mlx/generation.py +18 -16
  32. ommlds/backends/mlx/limits.py +10 -6
  33. ommlds/backends/mlx/loading.py +7 -4
  34. ommlds/backends/ollama/__init__.py +7 -0
  35. ommlds/backends/ollama/_dataclasses.py +3940 -0
  36. ommlds/backends/ollama/cli.py +36 -0
  37. ommlds/backends/ollama/protocol.py +201 -0
  38. ommlds/backends/openai/protocol/__init__.py +15 -1
  39. ommlds/backends/openai/protocol/_common.py +3 -5
  40. ommlds/backends/openai/protocol/_dataclasses.py +7708 -0
  41. ommlds/backends/tavily/__init__.py +7 -0
  42. ommlds/backends/tavily/_dataclasses.py +1734 -0
  43. ommlds/backends/tavily/protocol.py +299 -0
  44. ommlds/backends/tinygrad/models/llama3/__init__.py +22 -14
  45. ommlds/backends/torch/backends.py +1 -1
  46. ommlds/backends/transformers/__init__.py +14 -0
  47. ommlds/backends/transformers/filecache.py +109 -0
  48. ommlds/backends/transformers/streamers.py +73 -0
  49. ommlds/cli/__init__.py +7 -0
  50. ommlds/cli/_dataclasses.py +3835 -0
  51. ommlds/cli/asyncs.py +30 -0
  52. ommlds/cli/backends/catalog.py +88 -0
  53. ommlds/cli/backends/configs.py +9 -0
  54. ommlds/cli/backends/inject.py +100 -42
  55. ommlds/cli/{sessions/chat/backends → backends}/injection.py +1 -1
  56. ommlds/cli/backends/meta.py +82 -0
  57. ommlds/cli/{sessions/chat/backends → backends}/types.py +11 -1
  58. ommlds/cli/{sessions/chat/content → content}/messages.py +2 -2
  59. ommlds/cli/{sessions/chat/content → content}/strings.py +1 -1
  60. ommlds/cli/inject.py +17 -8
  61. ommlds/cli/inputs/asyncs.py +32 -0
  62. ommlds/cli/inputs/sync.py +75 -0
  63. ommlds/cli/main.py +346 -114
  64. ommlds/cli/rendering/configs.py +9 -0
  65. ommlds/cli/{sessions/chat/rendering → rendering}/inject.py +4 -5
  66. ommlds/cli/{sessions/chat/rendering → rendering}/markdown.py +1 -1
  67. ommlds/cli/{sessions/chat/rendering → rendering}/raw.py +1 -1
  68. ommlds/cli/{sessions/chat/rendering → rendering}/types.py +7 -1
  69. ommlds/cli/secrets.py +22 -0
  70. ommlds/cli/sessions/base.py +1 -10
  71. ommlds/cli/sessions/chat/configs.py +13 -30
  72. ommlds/cli/sessions/chat/drivers/ai/configs.py +13 -0
  73. ommlds/cli/sessions/chat/drivers/ai/events.py +57 -0
  74. ommlds/cli/sessions/chat/{chat → drivers}/ai/inject.py +15 -12
  75. ommlds/cli/sessions/chat/{chat → drivers}/ai/rendering.py +8 -8
  76. ommlds/cli/sessions/chat/{chat → drivers}/ai/services.py +5 -5
  77. ommlds/cli/sessions/chat/{chat → drivers}/ai/tools.py +4 -8
  78. ommlds/cli/sessions/chat/{chat → drivers}/ai/types.py +10 -1
  79. ommlds/cli/sessions/chat/drivers/configs.py +25 -0
  80. ommlds/cli/sessions/chat/drivers/events/inject.py +27 -0
  81. ommlds/cli/sessions/chat/drivers/events/injection.py +14 -0
  82. ommlds/cli/sessions/chat/drivers/events/manager.py +16 -0
  83. ommlds/cli/sessions/chat/drivers/events/types.py +44 -0
  84. ommlds/cli/sessions/chat/drivers/impl.py +50 -0
  85. ommlds/cli/sessions/chat/drivers/inject.py +70 -0
  86. ommlds/cli/sessions/chat/drivers/state/configs.py +13 -0
  87. ommlds/cli/sessions/chat/drivers/state/ids.py +25 -0
  88. ommlds/cli/sessions/chat/drivers/state/inject.py +83 -0
  89. ommlds/cli/sessions/chat/{chat → drivers}/state/inmemory.py +1 -6
  90. ommlds/cli/sessions/chat/{chat → drivers}/state/storage.py +18 -12
  91. ommlds/cli/sessions/chat/{chat → drivers}/state/types.py +11 -6
  92. ommlds/cli/sessions/chat/drivers/tools/configs.py +22 -0
  93. ommlds/cli/sessions/chat/drivers/tools/confirmation.py +44 -0
  94. ommlds/cli/sessions/chat/drivers/tools/errorhandling.py +39 -0
  95. ommlds/cli/sessions/chat/{tools → drivers/tools}/execution.py +3 -4
  96. ommlds/cli/sessions/chat/drivers/tools/fs/__init__.py +0 -0
  97. ommlds/cli/sessions/chat/drivers/tools/fs/configs.py +12 -0
  98. ommlds/cli/sessions/chat/drivers/tools/fs/inject.py +35 -0
  99. ommlds/cli/sessions/chat/drivers/tools/inject.py +83 -0
  100. ommlds/cli/sessions/chat/{tools → drivers/tools}/injection.py +20 -5
  101. ommlds/cli/sessions/chat/{tools → drivers/tools}/rendering.py +3 -3
  102. ommlds/cli/sessions/chat/drivers/tools/todo/__init__.py +0 -0
  103. ommlds/cli/sessions/chat/drivers/tools/todo/configs.py +12 -0
  104. ommlds/cli/sessions/chat/drivers/tools/todo/inject.py +31 -0
  105. ommlds/cli/sessions/chat/drivers/tools/weather/__init__.py +0 -0
  106. ommlds/cli/sessions/chat/drivers/tools/weather/configs.py +12 -0
  107. ommlds/cli/sessions/chat/drivers/tools/weather/inject.py +22 -0
  108. ommlds/cli/sessions/chat/{tools/weather.py → drivers/tools/weather/tools.py} +1 -1
  109. ommlds/cli/sessions/chat/drivers/types.py +31 -0
  110. ommlds/cli/sessions/chat/drivers/user/__init__.py +0 -0
  111. ommlds/cli/sessions/chat/drivers/user/configs.py +14 -0
  112. ommlds/cli/sessions/chat/drivers/user/inject.py +41 -0
  113. ommlds/cli/sessions/chat/facades/__init__.py +0 -0
  114. ommlds/cli/sessions/chat/facades/commands/__init__.py +0 -0
  115. ommlds/cli/sessions/chat/facades/commands/base.py +83 -0
  116. ommlds/cli/sessions/chat/facades/commands/configs.py +9 -0
  117. ommlds/cli/sessions/chat/facades/commands/inject.py +41 -0
  118. ommlds/cli/sessions/chat/facades/commands/injection.py +15 -0
  119. ommlds/cli/sessions/chat/facades/commands/manager.py +59 -0
  120. ommlds/cli/sessions/chat/facades/commands/simple.py +34 -0
  121. ommlds/cli/sessions/chat/facades/commands/types.py +13 -0
  122. ommlds/cli/sessions/chat/facades/configs.py +11 -0
  123. ommlds/cli/sessions/chat/facades/facade.py +26 -0
  124. ommlds/cli/sessions/chat/facades/inject.py +35 -0
  125. ommlds/cli/sessions/chat/facades/ui.py +34 -0
  126. ommlds/cli/sessions/chat/inject.py +10 -49
  127. ommlds/cli/sessions/chat/interfaces/__init__.py +0 -0
  128. ommlds/cli/sessions/chat/interfaces/bare/__init__.py +0 -0
  129. ommlds/cli/sessions/chat/interfaces/bare/configs.py +15 -0
  130. ommlds/cli/sessions/chat/interfaces/bare/inject.py +69 -0
  131. ommlds/cli/sessions/chat/interfaces/bare/interactive.py +49 -0
  132. ommlds/cli/sessions/chat/interfaces/bare/oneshot.py +21 -0
  133. ommlds/cli/sessions/chat/{tools/confirmation.py → interfaces/bare/tools.py} +3 -22
  134. ommlds/cli/sessions/chat/interfaces/base.py +13 -0
  135. ommlds/cli/sessions/chat/interfaces/configs.py +11 -0
  136. ommlds/cli/sessions/chat/interfaces/inject.py +29 -0
  137. ommlds/cli/sessions/chat/interfaces/textual/__init__.py +0 -0
  138. ommlds/cli/sessions/chat/interfaces/textual/app.py +429 -0
  139. ommlds/cli/sessions/chat/interfaces/textual/configs.py +11 -0
  140. ommlds/cli/sessions/chat/interfaces/textual/facades.py +19 -0
  141. ommlds/cli/sessions/chat/interfaces/textual/inject.py +111 -0
  142. ommlds/cli/sessions/chat/interfaces/textual/inputhistory.py +174 -0
  143. ommlds/cli/sessions/chat/interfaces/textual/interface.py +24 -0
  144. ommlds/cli/sessions/chat/interfaces/textual/styles/__init__.py +29 -0
  145. ommlds/cli/sessions/chat/interfaces/textual/styles/input.tcss +53 -0
  146. ommlds/cli/sessions/chat/interfaces/textual/styles/markdown.tcss +7 -0
  147. ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss +167 -0
  148. ommlds/cli/sessions/chat/interfaces/textual/tools.py +38 -0
  149. ommlds/cli/sessions/chat/interfaces/textual/widgets/__init__.py +0 -0
  150. ommlds/cli/sessions/chat/interfaces/textual/widgets/input.py +70 -0
  151. ommlds/cli/sessions/chat/interfaces/textual/widgets/messages.py +207 -0
  152. ommlds/cli/sessions/chat/session.py +8 -13
  153. ommlds/cli/sessions/completion/configs.py +5 -6
  154. ommlds/cli/sessions/completion/inject.py +15 -2
  155. ommlds/cli/sessions/completion/session.py +10 -18
  156. ommlds/cli/sessions/configs.py +10 -0
  157. ommlds/cli/sessions/embedding/configs.py +5 -6
  158. ommlds/cli/sessions/embedding/inject.py +15 -2
  159. ommlds/cli/sessions/embedding/session.py +10 -18
  160. ommlds/cli/sessions/inject.py +15 -15
  161. ommlds/cli/state/storage.py +8 -2
  162. ommlds/minichain/__init__.py +217 -60
  163. ommlds/minichain/_dataclasses.py +20640 -0
  164. ommlds/minichain/_typedvalues.py +15 -8
  165. ommlds/minichain/backends/catalogs/base.py +20 -1
  166. ommlds/minichain/backends/catalogs/simple.py +2 -2
  167. ommlds/minichain/backends/catalogs/strings.py +13 -10
  168. ommlds/minichain/backends/impls/anthropic/chat.py +28 -5
  169. ommlds/minichain/backends/impls/anthropic/names.py +3 -3
  170. ommlds/minichain/backends/impls/anthropic/protocol.py +2 -2
  171. ommlds/minichain/backends/impls/anthropic/stream.py +23 -18
  172. ommlds/minichain/backends/impls/cerebras/__init__.py +0 -0
  173. ommlds/minichain/backends/impls/cerebras/chat.py +82 -0
  174. ommlds/minichain/backends/impls/cerebras/names.py +45 -0
  175. ommlds/minichain/backends/impls/cerebras/protocol.py +143 -0
  176. ommlds/minichain/backends/impls/cerebras/stream.py +114 -0
  177. ommlds/minichain/backends/impls/duckduckgo/search.py +5 -1
  178. ommlds/minichain/backends/impls/dummy/__init__.py +0 -0
  179. ommlds/minichain/backends/impls/dummy/chat.py +69 -0
  180. ommlds/minichain/backends/impls/google/chat.py +20 -84
  181. ommlds/minichain/backends/impls/google/names.py +6 -0
  182. ommlds/minichain/backends/impls/google/protocol.py +105 -0
  183. ommlds/minichain/backends/impls/google/search.py +10 -5
  184. ommlds/minichain/backends/impls/google/stream.py +64 -142
  185. ommlds/minichain/backends/impls/google/tools.py +2 -2
  186. ommlds/minichain/backends/impls/groq/__init__.py +0 -0
  187. ommlds/minichain/backends/impls/groq/chat.py +77 -0
  188. ommlds/minichain/backends/impls/groq/names.py +48 -0
  189. ommlds/minichain/backends/impls/groq/protocol.py +143 -0
  190. ommlds/minichain/backends/impls/groq/stream.py +114 -0
  191. ommlds/minichain/backends/impls/huggingface/repos.py +1 -5
  192. ommlds/minichain/backends/impls/llamacpp/chat.py +15 -3
  193. ommlds/minichain/backends/impls/llamacpp/completion.py +7 -3
  194. ommlds/minichain/backends/impls/llamacpp/stream.py +38 -19
  195. ommlds/minichain/backends/impls/mistral.py +9 -2
  196. ommlds/minichain/backends/impls/mlx/chat.py +100 -23
  197. ommlds/minichain/backends/impls/ollama/__init__.py +0 -0
  198. ommlds/minichain/backends/impls/ollama/chat.py +193 -0
  199. ommlds/minichain/backends/impls/ollama/protocol.py +144 -0
  200. ommlds/minichain/backends/impls/openai/chat.py +14 -7
  201. ommlds/minichain/backends/impls/openai/completion.py +9 -2
  202. ommlds/minichain/backends/impls/openai/embedding.py +9 -2
  203. ommlds/minichain/backends/impls/openai/format.py +117 -115
  204. ommlds/minichain/backends/impls/openai/names.py +33 -5
  205. ommlds/minichain/backends/impls/openai/stream.py +61 -70
  206. ommlds/minichain/backends/impls/sentencepiece/tokens.py +9 -6
  207. ommlds/minichain/backends/impls/tavily.py +66 -0
  208. ommlds/minichain/backends/impls/tinygrad/chat.py +17 -14
  209. ommlds/minichain/backends/impls/tokenizers/tokens.py +9 -6
  210. ommlds/minichain/backends/impls/transformers/sentence.py +5 -2
  211. ommlds/minichain/backends/impls/transformers/tokens.py +9 -6
  212. ommlds/minichain/backends/impls/transformers/transformers.py +139 -20
  213. ommlds/minichain/backends/strings/parsing.py +2 -2
  214. ommlds/minichain/backends/strings/resolving.py +7 -2
  215. ommlds/minichain/chat/choices/stream/__init__.py +0 -0
  216. ommlds/minichain/chat/{stream → choices/stream}/adapters.py +7 -7
  217. ommlds/minichain/chat/choices/stream/joining.py +31 -0
  218. ommlds/minichain/chat/choices/stream/services.py +45 -0
  219. ommlds/minichain/chat/choices/stream/types.py +43 -0
  220. ommlds/minichain/chat/content.py +42 -0
  221. ommlds/minichain/chat/messages.py +46 -42
  222. ommlds/minichain/chat/stream/_marshal.py +4 -4
  223. ommlds/minichain/chat/stream/joining.py +56 -43
  224. ommlds/minichain/chat/stream/services.py +15 -15
  225. ommlds/minichain/chat/stream/types.py +17 -24
  226. ommlds/minichain/chat/templating.py +3 -3
  227. ommlds/minichain/content/__init__.py +20 -3
  228. ommlds/minichain/content/_marshal.py +181 -55
  229. ommlds/minichain/content/code.py +26 -0
  230. ommlds/minichain/content/composite.py +28 -0
  231. ommlds/minichain/content/content.py +27 -0
  232. ommlds/minichain/content/dynamic.py +12 -0
  233. ommlds/minichain/content/emphasis.py +27 -0
  234. ommlds/minichain/content/images.py +2 -2
  235. ommlds/minichain/content/json.py +2 -2
  236. ommlds/minichain/content/link.py +13 -0
  237. ommlds/minichain/content/markdown.py +12 -0
  238. ommlds/minichain/content/metadata.py +10 -0
  239. ommlds/minichain/content/namespaces.py +8 -0
  240. ommlds/minichain/content/placeholders.py +10 -9
  241. ommlds/minichain/content/quote.py +26 -0
  242. ommlds/minichain/content/raw.py +49 -0
  243. ommlds/minichain/content/recursive.py +12 -0
  244. ommlds/minichain/content/resources.py +22 -0
  245. ommlds/minichain/content/section.py +26 -0
  246. ommlds/minichain/content/sequence.py +17 -3
  247. ommlds/minichain/content/standard.py +32 -0
  248. ommlds/minichain/content/tag.py +28 -0
  249. ommlds/minichain/content/templates.py +13 -0
  250. ommlds/minichain/content/text.py +2 -2
  251. ommlds/minichain/content/transform/__init__.py +0 -0
  252. ommlds/minichain/content/transform/json.py +55 -0
  253. ommlds/minichain/content/transform/markdown.py +8 -0
  254. ommlds/minichain/content/transform/materialize.py +59 -0
  255. ommlds/minichain/content/transform/metadata.py +16 -0
  256. ommlds/minichain/content/transform/namespaces.py +20 -0
  257. ommlds/minichain/content/transform/placeholders.py +60 -0
  258. ommlds/minichain/content/{prepare.py → transform/prepare.py} +10 -15
  259. ommlds/minichain/content/transform/recursive.py +54 -0
  260. ommlds/minichain/content/transform/resources.py +58 -0
  261. ommlds/minichain/content/transform/standard.py +43 -0
  262. ommlds/minichain/content/{transforms → transform}/stringify.py +1 -7
  263. ommlds/minichain/content/transform/strings.py +33 -0
  264. ommlds/minichain/content/transform/templates.py +25 -0
  265. ommlds/minichain/content/transform/types.py +18 -0
  266. ommlds/minichain/content/transform/visitors.py +38 -0
  267. ommlds/minichain/content/visitors.py +218 -0
  268. ommlds/minichain/http/__init__.py +0 -0
  269. ommlds/minichain/http/stream.py +195 -0
  270. ommlds/minichain/lib/fs/tools/read.py +1 -1
  271. ommlds/minichain/lib/fs/tools/recursivels/rendering.py +1 -1
  272. ommlds/minichain/lib/fs/tools/recursivels/running.py +1 -1
  273. ommlds/minichain/lib/todo/tools/write.py +2 -1
  274. ommlds/minichain/lib/todo/types.py +1 -1
  275. ommlds/minichain/llms/types.py +4 -0
  276. ommlds/minichain/metadata.py +56 -2
  277. ommlds/minichain/models/configs.py +2 -2
  278. ommlds/minichain/models/names.py +2 -0
  279. ommlds/minichain/registries/globals.py +18 -4
  280. ommlds/minichain/resources.py +49 -3
  281. ommlds/minichain/search.py +1 -1
  282. ommlds/minichain/services/README.md +154 -0
  283. ommlds/minichain/services/__init__.py +6 -2
  284. ommlds/minichain/services/_marshal.py +46 -10
  285. ommlds/minichain/services/_origclasses.py +11 -0
  286. ommlds/minichain/services/_typedvalues.py +8 -3
  287. ommlds/minichain/services/requests.py +73 -3
  288. ommlds/minichain/services/responses.py +73 -3
  289. ommlds/minichain/services/services.py +9 -0
  290. ommlds/minichain/standard.py +8 -0
  291. ommlds/minichain/stream/services.py +43 -17
  292. ommlds/minichain/text/applypatch.py +2 -1
  293. ommlds/minichain/text/toolparsing/llamacpp/types.py +1 -1
  294. ommlds/minichain/tokens/specials.py +1 -1
  295. ommlds/minichain/tools/execution/catalog.py +2 -2
  296. ommlds/minichain/tools/execution/errorhandling.py +36 -0
  297. ommlds/minichain/tools/execution/errors.py +2 -2
  298. ommlds/minichain/tools/execution/executors.py +1 -1
  299. ommlds/minichain/tools/fns.py +1 -1
  300. ommlds/minichain/tools/jsonschema.py +2 -2
  301. ommlds/minichain/tools/reflect.py +11 -7
  302. ommlds/minichain/tools/types.py +16 -19
  303. ommlds/minichain/vectors/_marshal.py +1 -1
  304. ommlds/minichain/vectors/embeddings.py +1 -1
  305. ommlds/minichain/wrappers/__init__.py +7 -0
  306. ommlds/minichain/wrappers/firstinwins.py +144 -0
  307. ommlds/minichain/wrappers/instrument.py +146 -0
  308. ommlds/minichain/wrappers/retry.py +168 -0
  309. ommlds/minichain/wrappers/services.py +98 -0
  310. ommlds/minichain/wrappers/stream.py +57 -0
  311. ommlds/nanochat/LICENSE +21 -0
  312. ommlds/nanochat/__init__.py +0 -0
  313. ommlds/nanochat/rustbpe/LICENSE +21 -0
  314. ommlds/nanochat/rustbpe/README.md +10 -0
  315. ommlds/nanochat/tokenizers.py +440 -0
  316. ommlds/specs/__init__.py +0 -0
  317. ommlds/specs/mcp/__init__.py +0 -0
  318. ommlds/specs/mcp/_marshal.py +23 -0
  319. ommlds/specs/mcp/clients.py +146 -0
  320. ommlds/specs/mcp/protocol.py +369 -0
  321. ommlds/tools/git.py +84 -64
  322. ommlds/tools/ocr.py +1 -1
  323. ommlds/wiki/analyze.py +2 -2
  324. ommlds/wiki/models.py +4 -4
  325. ommlds/wiki/text/mfh.py +9 -9
  326. ommlds/wiki/utils/xml.py +5 -5
  327. {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/METADATA +28 -21
  328. ommlds-0.0.0.dev512.dist-info/RECORD +534 -0
  329. {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/WHEEL +1 -1
  330. ommlds/cli/backends/standard.py +0 -20
  331. ommlds/cli/sessions/chat/backends/catalog.py +0 -56
  332. ommlds/cli/sessions/chat/backends/inject.py +0 -37
  333. ommlds/cli/sessions/chat/chat/state/inject.py +0 -40
  334. ommlds/cli/sessions/chat/chat/user/inject.py +0 -61
  335. ommlds/cli/sessions/chat/chat/user/interactive.py +0 -29
  336. ommlds/cli/sessions/chat/chat/user/oneshot.py +0 -25
  337. ommlds/cli/sessions/chat/chat/user/types.py +0 -15
  338. ommlds/cli/sessions/chat/driver.py +0 -43
  339. ommlds/cli/sessions/chat/tools/inject.py +0 -145
  340. ommlds/minichain/backends/impls/openai/format2.py +0 -210
  341. ommlds/minichain/content/materialize.py +0 -196
  342. ommlds/minichain/content/simple.py +0 -47
  343. ommlds/minichain/content/transforms/base.py +0 -46
  344. ommlds/minichain/content/transforms/interleave.py +0 -70
  345. ommlds/minichain/content/transforms/squeeze.py +0 -72
  346. ommlds/minichain/content/transforms/strings.py +0 -24
  347. ommlds/minichain/content/types.py +0 -43
  348. ommlds/minichain/stream/wrap.py +0 -62
  349. ommlds-0.0.0.dev466.dist-info/RECORD +0 -376
  350. /ommlds/{cli/sessions/chat/backends → backends/huggingface}/__init__.py +0 -0
  351. /ommlds/cli/{sessions/chat/chat → content}/__init__.py +0 -0
  352. /ommlds/cli/{sessions/chat/chat/ai → inputs}/__init__.py +0 -0
  353. /ommlds/cli/{sessions/chat/chat/state → rendering}/__init__.py +0 -0
  354. /ommlds/cli/sessions/chat/{chat/user → drivers}/__init__.py +0 -0
  355. /ommlds/cli/sessions/chat/{content → drivers/ai}/__init__.py +0 -0
  356. /ommlds/cli/sessions/chat/{chat → drivers}/ai/injection.py +0 -0
  357. /ommlds/cli/sessions/chat/{phases → drivers/events}/__init__.py +0 -0
  358. /ommlds/cli/sessions/chat/{rendering → drivers/phases}/__init__.py +0 -0
  359. /ommlds/cli/sessions/chat/{phases → drivers/phases}/inject.py +0 -0
  360. /ommlds/cli/sessions/chat/{phases → drivers/phases}/injection.py +0 -0
  361. /ommlds/cli/sessions/chat/{phases → drivers/phases}/manager.py +0 -0
  362. /ommlds/cli/sessions/chat/{phases → drivers/phases}/types.py +0 -0
  363. /ommlds/cli/sessions/chat/{tools → drivers/state}/__init__.py +0 -0
  364. /ommlds/{minichain/content/transforms → cli/sessions/chat/drivers/tools}/__init__.py +0 -0
  365. {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/entry_points.txt +0 -0
  366. {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/licenses/LICENSE +0 -0
  367. {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/top_level.txt +0 -0
@@ -1,36 +1,19 @@
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 ...rendering.configs import RenderingConfig
4
+ from ..configs import SessionConfig
5
+ from .drivers.configs import DriverConfig
6
+ from .facades.configs import FacadeConfig
7
+ from .interfaces.bare.configs import BareInterfaceConfig
8
+ from .interfaces.configs import InterfaceConfig
5
9
 
6
10
 
7
11
  ##
8
12
 
9
13
 
10
- DEFAULT_CHAT_MODEL_BACKEND = 'openai'
11
-
12
-
13
- ##
14
-
15
-
16
- @dc.dataclass(frozen=True)
17
- 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
- interactive: bool = False
28
-
29
- silent: bool = False
30
- markdown: bool = False
31
-
32
- stream: bool = False
33
-
34
- enable_tools: bool = False
35
- enabled_tools: ta.AbstractSet[str] | None = None
36
- dangerous_no_tool_confirmation: bool = False
14
+ @dc.dataclass(frozen=True, kw_only=True)
15
+ class ChatConfig(SessionConfig):
16
+ driver: DriverConfig = DriverConfig()
17
+ facade: FacadeConfig = FacadeConfig()
18
+ interface: InterfaceConfig = BareInterfaceConfig()
19
+ rendering: RenderingConfig = RenderingConfig()
@@ -0,0 +1,13 @@
1
+ from omlish import dataclasses as dc
2
+
3
+
4
+ ##
5
+
6
+
7
+ @dc.dataclass(frozen=True, kw_only=True)
8
+ class AiConfig:
9
+ stream: bool = False
10
+
11
+ verbose: bool = False
12
+
13
+ enable_tools: bool = False
@@ -0,0 +1,57 @@
1
+ import typing as ta
2
+
3
+ from ...... import minichain as mc
4
+ from ..events.manager import ChatEventsManager
5
+ from ..events.types import AiDeltaChatEvent
6
+ from ..events.types import AiMessagesChatEvent
7
+ from .types import AiChatGenerator
8
+ from .types import StreamAiChatGenerator
9
+
10
+
11
+ ##
12
+
13
+
14
+ class EventEmittingAiChatGenerator(AiChatGenerator):
15
+ def __init__(
16
+ self,
17
+ *,
18
+ wrapped: AiChatGenerator,
19
+ events: ChatEventsManager,
20
+ ) -> None:
21
+ super().__init__()
22
+
23
+ self._wrapped = wrapped
24
+ self._events = events
25
+
26
+ async def get_next_ai_messages(self, chat: 'mc.Chat') -> 'mc.Chat':
27
+ out = await self._wrapped.get_next_ai_messages(chat)
28
+
29
+ await self._events.emit_event(AiMessagesChatEvent(out))
30
+
31
+ return out
32
+
33
+
34
+ class EventEmittingStreamAiChatGenerator(StreamAiChatGenerator):
35
+ def __init__(
36
+ self,
37
+ *,
38
+ wrapped: StreamAiChatGenerator,
39
+ events: ChatEventsManager,
40
+ ) -> None:
41
+ super().__init__()
42
+
43
+ self._wrapped = wrapped
44
+ self._events = events
45
+
46
+ async def get_next_ai_messages_streamed(
47
+ self,
48
+ chat: 'mc.Chat',
49
+ delta_callback: ta.Callable[['mc.AiDelta'], ta.Awaitable[None]] | None = None,
50
+ ) -> 'mc.Chat':
51
+ async def inner(delta: mc.AiDelta) -> None:
52
+ await self._events.emit_event(AiDeltaChatEvent(delta))
53
+
54
+ if delta_callback is not None:
55
+ await delta_callback(delta)
56
+
57
+ return await self._wrapped.get_next_ai_messages_streamed(chat, delta_callback=inner)
@@ -2,10 +2,12 @@ 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
 
8
9
  with lang.auto_proxy_import(globals()):
10
+ from . import events as _events
9
11
  from . import rendering as _rendering
10
12
  from . import services as _services
11
13
  from . import tools as _tools
@@ -15,12 +17,7 @@ with lang.auto_proxy_import(globals()):
15
17
  ##
16
18
 
17
19
 
18
- def bind_ai(
19
- *,
20
- stream: bool = False,
21
- silent: bool = False,
22
- enable_tools: bool = False,
23
- ) -> inj.Elements:
20
+ def bind_ai(cfg: AiConfig = AiConfig()) -> inj.Elements:
24
21
  els: list[inj.Elemental] = []
25
22
 
26
23
  #
@@ -38,14 +35,16 @@ def bind_ai(
38
35
 
39
36
  ai_stack = inj.wrapper_binder_helper(_types.AiChatGenerator)
40
37
 
41
- if stream:
38
+ if cfg.stream:
42
39
  stream_ai_stack = inj.wrapper_binder_helper(_types.StreamAiChatGenerator)
43
40
 
44
41
  els.append(stream_ai_stack.push_bind(to_ctor=_services.ChatChoicesStreamServiceStreamAiChatGenerator, singleton=True)) # noqa
45
42
 
46
- if not silent:
43
+ if cfg.verbose:
47
44
  els.append(stream_ai_stack.push_bind(to_ctor=_rendering.RenderingStreamAiChatGenerator, singleton=True))
48
45
 
46
+ els.append(stream_ai_stack.push_bind(to_ctor=_events.EventEmittingStreamAiChatGenerator, singleton=True))
47
+
49
48
  els.extend([
50
49
  inj.bind(_types.StreamAiChatGenerator, to_key=stream_ai_stack.top),
51
50
  ai_stack.push_bind(to_key=_types.StreamAiChatGenerator),
@@ -54,18 +53,22 @@ def bind_ai(
54
53
  else:
55
54
  els.append(ai_stack.push_bind(to_ctor=_services.ChatChoicesServiceAiChatGenerator, singleton=True))
56
55
 
57
- if not silent:
56
+ if cfg.verbose:
58
57
  els.append(ai_stack.push_bind(to_ctor=_rendering.RenderingAiChatGenerator, singleton=True))
59
58
 
60
- if enable_tools:
59
+ els.append(ai_stack.push_bind(to_ctor=_events.EventEmittingAiChatGenerator, singleton=True))
60
+
61
+ if cfg.enable_tools:
61
62
  els.append(ai_stack.push_bind(to_ctor=_tools.ToolExecutingAiChatGenerator, singleton=True))
62
63
 
63
64
  els.append(inj.bind(_types.AiChatGenerator, to_key=ai_stack.top))
64
65
 
65
66
  #
66
67
 
67
- if enable_tools:
68
- def _provide_tools_chat_choices_options_provider(tc: mc.ToolCatalog) -> _services.ChatChoicesServiceOptionsProvider: # noqa
68
+ if cfg.enable_tools:
69
+ def _provide_tools_chat_choices_options_provider(
70
+ tc: mc.ToolCatalog,
71
+ ) -> _services.ChatChoicesServiceOptionsProvider:
69
72
  return _services.ChatChoicesServiceOptionsProvider(lambda: [
70
73
  mc.Tool(tce.spec)
71
74
  for tce in tc.by_name.values()
@@ -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
 
@@ -57,11 +57,11 @@ class RenderingStreamAiChatGenerator(StreamAiChatGenerator):
57
57
  async def get_next_ai_messages_streamed(
58
58
  self,
59
59
  chat: 'mc.Chat',
60
- delta_callback: ta.Callable[['mc.AiChoiceDelta'], ta.Awaitable[None]] | None = None,
61
- ) -> mc.Chat:
60
+ delta_callback: ta.Callable[['mc.AiDelta'], ta.Awaitable[None]] | None = None,
61
+ ) -> 'mc.Chat':
62
62
  async with self._renderer.create_context() as renderer:
63
- async def inner(delta: mc.AiChoiceDelta) -> None:
64
- if isinstance(delta, mc.ContentAiChoiceDelta):
63
+ async def inner(delta: mc.AiDelta) -> None:
64
+ if isinstance(delta, mc.ContentAiDelta):
65
65
  await renderer.render_content(delta.c)
66
66
 
67
67
  if delta_callback is not None:
@@ -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
 
@@ -59,12 +59,12 @@ class ChatChoicesStreamServiceStreamAiChatGenerator(StreamAiChatGenerator):
59
59
  async def get_next_ai_messages_streamed(
60
60
  self,
61
61
  chat: 'mc.Chat',
62
- delta_callback: ta.Callable[['mc.AiChoiceDelta'], ta.Awaitable[None]] | None = None,
63
- ) -> mc.AiChat:
62
+ delta_callback: ta.Callable[['mc.AiDelta'], ta.Awaitable[None]] | None = None,
63
+ ) -> 'mc.AiChat':
64
64
  opts = self._options() if self._options is not None else []
65
65
 
66
66
  async with self._service_provider.provide_backend() as service:
67
- joiner = mc.AiChoiceDeltaJoiner()
67
+ joiner = mc.AiChoicesDeltaJoiner()
68
68
 
69
69
  async with (await service.invoke(mc.ChatChoicesStreamRequest(chat, opts))).v as st_resp:
70
70
  async for o in st_resp:
@@ -1,5 +1,5 @@
1
1
  from ...... import minichain as mc
2
- from ...tools.execution import ToolUseExecutor
2
+ from ..tools.execution import ToolUseExecutor
3
3
  from .types import AiChatGenerator
4
4
 
5
5
 
@@ -24,17 +24,13 @@ class ToolExecutingAiChatGenerator(AiChatGenerator):
24
24
  while True:
25
25
  new = await self._wrapped.get_next_ai_messages([*chat, *out])
26
26
 
27
- out.extend(new)
28
-
29
27
  cont = False
30
28
 
31
29
  for msg in new:
30
+ out.append(msg)
31
+
32
32
  if isinstance(msg, mc.ToolUseMessage):
33
- trm = await self._executor.execute_tool_use(
34
- msg.tu,
35
- # fs_tool_context,
36
- # todo_tool_context, # noqa
37
- )
33
+ trm = await self._executor.execute_tool_use(msg.tu)
38
34
 
39
35
  out.append(trm)
40
36
 
@@ -23,6 +23,15 @@ class StreamAiChatGenerator(AiChatGenerator, lang.Abstract):
23
23
  def get_next_ai_messages_streamed(
24
24
  self,
25
25
  chat: 'mc.Chat',
26
- delta_callback: ta.Callable[['mc.AiChoiceDelta'], ta.Awaitable[None]] | None = None,
26
+ delta_callback: ta.Callable[['mc.AiDelta'], ta.Awaitable[None]] | None = None,
27
27
  ) -> ta.Awaitable['mc.Chat']:
28
28
  raise NotImplementedError
29
+
30
+
31
+ ##
32
+
33
+
34
+ class AiChatOutput(lang.Abstract):
35
+ @abc.abstractmethod
36
+ def output_ai_chat(self, chat: 'mc.Chat') -> ta.Awaitable[None]:
37
+ raise NotImplementedError
@@ -0,0 +1,25 @@
1
+ from omlish import dataclasses as dc
2
+
3
+ from ....backends.configs import BackendConfig
4
+ from .ai.configs import AiConfig
5
+ from .state.configs import StateConfig
6
+ from .tools.configs import ToolsConfig
7
+ from .user.configs import UserConfig
8
+
9
+
10
+ ##
11
+
12
+
13
+ DEFAULT_BACKEND = 'openai'
14
+
15
+
16
+ ##
17
+
18
+
19
+ @dc.dataclass(frozen=True, kw_only=True)
20
+ class DriverConfig:
21
+ ai: AiConfig = AiConfig()
22
+ backend: BackendConfig = BackendConfig()
23
+ state: StateConfig = StateConfig()
24
+ tools: ToolsConfig = ToolsConfig()
25
+ user: UserConfig = UserConfig()
@@ -0,0 +1,27 @@
1
+ from omlish import inject as inj
2
+ from omlish import lang
3
+
4
+ from .injection import event_callbacks
5
+
6
+
7
+ with lang.auto_proxy_import(globals()):
8
+ from . import manager as _manager
9
+
10
+
11
+ ##
12
+
13
+
14
+ def bind_events() -> inj.Elements:
15
+ els: list[inj.Elemental] = []
16
+
17
+ #
18
+
19
+ els.append(event_callbacks().bind_items_provider(singleton=True))
20
+
21
+ #
22
+
23
+ els.append(inj.bind(_manager.ChatEventsManager, 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 event_callbacks() -> 'inj.ItemsBinderHelper[_types.ChatEventCallback]':
14
+ return inj.items_binder_helper[_types.ChatEventCallback](_types.ChatEventCallbacks)
@@ -0,0 +1,16 @@
1
+ from .types import ChatEvent
2
+ from .types import ChatEventCallbacks
3
+
4
+
5
+ ##
6
+
7
+
8
+ class ChatEventsManager:
9
+ def __init__(self, callbacks: ChatEventCallbacks) -> None:
10
+ super().__init__()
11
+
12
+ self._callbacks = callbacks
13
+
14
+ async def emit_event(self, event: ChatEvent) -> None:
15
+ for cb in self._callbacks:
16
+ await cb(event)
@@ -0,0 +1,44 @@
1
+ import typing as ta
2
+
3
+ from omlish import dataclasses as dc
4
+ from omlish import lang
5
+
6
+ from ...... import minichain as mc
7
+
8
+
9
+ ##
10
+
11
+
12
+ class ChatEvent(lang.Abstract, lang.Sealed):
13
+ pass
14
+
15
+
16
+ class ChatEventCallback(lang.Func1[ChatEvent, ta.Awaitable[None]]):
17
+ pass
18
+
19
+
20
+ ChatEventCallbacks = ta.NewType('ChatEventCallbacks', ta.Sequence[ChatEventCallback])
21
+
22
+
23
+ ##
24
+
25
+
26
+ @dc.dataclass(frozen=True)
27
+ class UserMessagesChatEvent(ChatEvent, lang.Final):
28
+ chat: 'mc.UserChat'
29
+
30
+
31
+ @dc.dataclass(frozen=True)
32
+ class AiMessagesChatEvent(ChatEvent, lang.Final):
33
+ chat: 'mc.Chat'
34
+
35
+
36
+ @dc.dataclass(frozen=True)
37
+ class AiDeltaChatEvent(ChatEvent, lang.Final):
38
+ delta: 'mc.AiDelta'
39
+
40
+
41
+ @dc.dataclass(frozen=True)
42
+ class ErrorChatEvent(ChatEvent, lang.Final):
43
+ message: str | None = None
44
+ error: BaseException | None = None
@@ -0,0 +1,50 @@
1
+ """
2
+ TODO:
3
+ - lifecycles
4
+ - StreamService
5
+ """
6
+ from ..... import minichain as mc
7
+ from .ai.types import AiChatGenerator
8
+ from .events.manager import ChatEventsManager
9
+ from .events.types import UserMessagesChatEvent
10
+ from .phases.manager import ChatPhaseManager
11
+ from .phases.types import ChatPhase
12
+ from .state.types import ChatStateManager
13
+ from .types import ChatDriver
14
+
15
+
16
+ ##
17
+
18
+
19
+ class ChatDriverImpl(ChatDriver):
20
+ def __init__(
21
+ self,
22
+ *,
23
+ phases: ChatPhaseManager,
24
+ ai_chat_generator: AiChatGenerator,
25
+ chat_state_manager: ChatStateManager,
26
+ events: ChatEventsManager,
27
+ ) -> None:
28
+ super().__init__()
29
+
30
+ self._phases = phases
31
+ self._ai_chat_generator = ai_chat_generator
32
+ self._chat_state_manager = chat_state_manager
33
+ self._events = events
34
+
35
+ async def start(self) -> None:
36
+ await self._phases.set_phase(ChatPhase.STARTING)
37
+ await self._phases.set_phase(ChatPhase.STARTED)
38
+
39
+ async def stop(self) -> None:
40
+ await self._phases.set_phase(ChatPhase.STOPPING)
41
+ await self._phases.set_phase(ChatPhase.STOPPED)
42
+
43
+ async def send_user_messages(self, next_user_chat: 'mc.UserChat') -> None:
44
+ await self._events.emit_event(UserMessagesChatEvent(next_user_chat))
45
+
46
+ prev_user_chat = (await self._chat_state_manager.get_state()).chat
47
+
48
+ next_ai_chat = await self._ai_chat_generator.get_next_ai_messages([*prev_user_chat, *next_user_chat])
49
+
50
+ await self._chat_state_manager.extend_chat([*next_user_chat, *next_ai_chat])
@@ -0,0 +1,70 @@
1
+ """
2
+ TODO:
3
+ - private + expose(ChatDriver)
4
+ """
5
+ import uuid
6
+
7
+ from omlish import inject as inj
8
+ from omlish import lang
9
+
10
+ from ....backends.types import DefaultBackendName
11
+ from .configs import DEFAULT_BACKEND
12
+ from .configs import DriverConfig
13
+
14
+
15
+ with lang.auto_proxy_import(globals()):
16
+ from ....backends import inject as _backends
17
+ from . import impl as _impl
18
+ from . import types as _types
19
+ from .ai import inject as _ai
20
+ from .events import inject as _events
21
+ from .phases import inject as _phases
22
+ from .state import inject as _state
23
+ from .tools import inject as _tools
24
+ from .user import inject as _user
25
+
26
+
27
+ ##
28
+
29
+
30
+ def bind_driver(cfg: DriverConfig = DriverConfig()) -> inj.Elements:
31
+ els: list[inj.Elemental] = []
32
+
33
+ #
34
+
35
+ els.extend([
36
+ _backends.bind_backends(cfg.backend),
37
+
38
+ _ai.bind_ai(cfg.ai),
39
+
40
+ _events.bind_events(),
41
+
42
+ _phases.bind_phases(),
43
+
44
+ _state.bind_state(cfg.state),
45
+
46
+ _tools.bind_tools(cfg.tools),
47
+
48
+ _user.bind_user(cfg.user),
49
+ ])
50
+
51
+ #
52
+
53
+ els.extend([
54
+ inj.bind(_impl.ChatDriverImpl, singleton=True),
55
+ inj.bind(_types.ChatDriver, to_key=_impl.ChatDriverImpl),
56
+
57
+ inj.bind_async_late(_types.ChatDriver, _types.ChatDriverGetter),
58
+ ])
59
+
60
+ #
61
+
62
+ els.append(inj.bind(DefaultBackendName, to_const=DEFAULT_BACKEND))
63
+
64
+ #
65
+
66
+ els.append(inj.bind(_types.ChatDriverId(uuid.uuid4())))
67
+
68
+ #
69
+
70
+ return inj.as_elements(*els)
@@ -0,0 +1,13 @@
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'
12
+
13
+ chat_id: str | None = None
@@ -0,0 +1,25 @@
1
+ from .storage import StateStorage
2
+ from .types import ChatId
3
+
4
+
5
+ ##
6
+
7
+
8
+ _LAST_CHAT_ID_STATE_KEY: str = 'last_chat_id'
9
+
10
+
11
+ class LastChatIdManager:
12
+ def __init__(
13
+ self,
14
+ *,
15
+ state_storage: StateStorage,
16
+ ) -> None:
17
+ super().__init__()
18
+
19
+ self._state_storage = state_storage
20
+
21
+ async def get_last_chat_id(self) -> ChatId | None:
22
+ return await self._state_storage.load_state(_LAST_CHAT_ID_STATE_KEY, ChatId)
23
+
24
+ async def set_last_chat_id(self, chat_id: ChatId | None) -> None:
25
+ await self._state_storage.save_state(_LAST_CHAT_ID_STATE_KEY, chat_id, ChatId)
@@ -0,0 +1,83 @@
1
+ """
2
+ TODO:
3
+ - given chat-id + ephemeral = continue in mem
4
+ - fork chats
5
+ """
6
+ import uuid
7
+
8
+ from omlish import inject as inj
9
+ from omlish import lang
10
+
11
+ from ..phases.injection import phase_callbacks
12
+ from ..phases.types import ChatPhase
13
+ from ..phases.types import ChatPhaseCallback
14
+ from .configs import StateConfig
15
+
16
+
17
+ with lang.auto_proxy_import(globals()):
18
+ from . import ids as _ids
19
+ from . import inmemory as _inmemory
20
+ from . import storage as _storage
21
+ from . import types as _types
22
+
23
+
24
+ ##
25
+
26
+
27
+ def _new_chat_id() -> '_types.ChatId':
28
+ return _types.ChatId(uuid.uuid4())
29
+
30
+
31
+ async def _get_last_or_new_chat_id(lcim: '_ids.LastChatIdManager') -> '_types.ChatId':
32
+ return lcid if (lcid := await lcim.get_last_chat_id()) is not None else _new_chat_id()
33
+
34
+
35
+ ##
36
+
37
+
38
+ def bind_state(cfg: StateConfig = StateConfig()) -> inj.Elements:
39
+ els: list[inj.Elemental] = []
40
+
41
+ if cfg.state in ('continue', 'new'):
42
+ if cfg.state == 'new':
43
+ els.append(inj.bind(_types.ChatId(uuid.UUID(cfg.chat_id)) if cfg.chat_id is not None else _new_chat_id()))
44
+
45
+ elif cfg.chat_id is not None:
46
+ els.append(inj.bind(_types.ChatId(uuid.UUID(cfg.chat_id))))
47
+
48
+ else:
49
+ els.append(inj.bind(_types.ChatId, to_async_fn=_get_last_or_new_chat_id, singleton=True))
50
+
51
+ els.extend([
52
+ inj.bind(_storage.build_chat_storage_key),
53
+
54
+ inj.bind(_types.ChatStateManager, to_ctor=_storage.StateStorageChatStateManager, singleton=True),
55
+ ])
56
+
57
+ #
58
+
59
+ els.extend([
60
+ inj.bind(_ids.LastChatIdManager, singleton=True),
61
+
62
+ phase_callbacks().bind_item(to_fn=inj.target(
63
+ lcim=_ids.LastChatIdManager,
64
+ cid=_types.ChatId,
65
+ )(lambda lcim, cid: ChatPhaseCallback(ChatPhase.STARTED, lambda: lcim.set_last_chat_id(cid)))),
66
+ ])
67
+
68
+ elif cfg.state == 'ephemeral':
69
+ if cfg.chat_id is not None:
70
+ raise ValueError('chat-id is not allowed for ephemeral state')
71
+
72
+ els.extend([
73
+ inj.bind(_new_chat_id()),
74
+
75
+ inj.bind(_types.ChatStateManager, to_ctor=_inmemory.InMemoryChatStateManager, singleton=True),
76
+ ])
77
+
78
+ else:
79
+ raise TypeError(cfg.state)
80
+
81
+ #
82
+
83
+ return inj.as_elements(*els)