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
@@ -2,13 +2,10 @@ import contextlib
2
2
  import os.path
3
3
  import typing as ta
4
4
 
5
- import llama_cpp as lcc
6
-
7
5
  from omlish import check
8
6
  from omlish import lang
9
7
  from omlish import typedvalues as tv
10
8
 
11
- from .....backends import llamacpp as lcu
12
9
  from ....chat.choices.services import ChatChoicesRequest
13
10
  from ....chat.choices.services import ChatChoicesResponse
14
11
  from ....chat.choices.services import static_check_is_chat_choices_service
@@ -27,6 +24,21 @@ from .format import ROLES_MAP
27
24
  from .format import get_msg_content
28
25
 
29
26
 
27
+ with lang.auto_proxy_import(globals()):
28
+ import llama_cpp as lcc
29
+
30
+ from .....backends import llamacpp as lcu
31
+
32
+
33
+ ##
34
+
35
+
36
+ # @omlish-manifest $.minichain.backends.strings.manifests.BackendStringsManifest(
37
+ # ['ChatChoicesService'],
38
+ # 'llamacpp',
39
+ # )
40
+
41
+
30
42
  ##
31
43
 
32
44
 
@@ -2,11 +2,9 @@ import contextlib
2
2
  import os.path
3
3
  import typing as ta
4
4
 
5
- import llama_cpp as lcc
6
-
5
+ from omlish import lang
7
6
  from omlish import typedvalues as tv
8
7
 
9
- from .....backends import llamacpp as lcu
10
8
  from ....completion import CompletionOption
11
9
  from ....completion import CompletionRequest
12
10
  from ....completion import CompletionResponse
@@ -18,6 +16,12 @@ from ....llms.types import Temperature
18
16
  from ....models.configs import ModelPath
19
17
 
20
18
 
19
+ with lang.auto_proxy_import(globals()):
20
+ import llama_cpp as lcc
21
+
22
+ from .....backends import llamacpp as lcu
23
+
24
+
21
25
  ##
22
26
 
23
27
 
@@ -2,20 +2,17 @@ import contextlib
2
2
  import threading
3
3
  import typing as ta # noqa
4
4
 
5
- import llama_cpp as lcc
6
-
7
5
  from omlish import check
8
6
  from omlish import lang
9
7
  from omlish import typedvalues as tv
10
8
 
11
- from .....backends import llamacpp as lcu
12
9
  from ....chat.choices.services import ChatChoicesOutputs
13
- from ....chat.stream.services import ChatChoicesStreamRequest
14
- from ....chat.stream.services import ChatChoicesStreamResponse
15
- from ....chat.stream.services import static_check_is_chat_choices_stream_service
16
- from ....chat.stream.types import AiChoiceDeltas
17
- from ....chat.stream.types import AiChoicesDeltas
18
- from ....chat.stream.types import ContentAiChoiceDelta
10
+ from ....chat.choices.stream.services import ChatChoicesStreamRequest
11
+ from ....chat.choices.stream.services import ChatChoicesStreamResponse
12
+ from ....chat.choices.stream.services import static_check_is_chat_choices_stream_service
13
+ from ....chat.choices.stream.types import AiChoiceDeltas
14
+ from ....chat.choices.stream.types import AiChoicesDeltas
15
+ from ....chat.stream.types import ContentAiDelta
19
16
  from ....configs import Config
20
17
  from ....models.configs import ModelPath
21
18
  from ....resources import UseResources
@@ -26,6 +23,21 @@ from .format import ROLES_MAP
26
23
  from .format import get_msg_content
27
24
 
28
25
 
26
+ with lang.auto_proxy_import(globals()):
27
+ import llama_cpp as lcc
28
+
29
+ from .....backends import llamacpp as lcu
30
+
31
+
32
+ ##
33
+
34
+
35
+ # @omlish-manifest $.minichain.backends.strings.manifests.BackendStringsManifest(
36
+ # ['ChatChoicesStreamService'],
37
+ # 'llamacpp',
38
+ # )
39
+
40
+
29
41
  ##
30
42
 
31
43
 
@@ -76,18 +88,25 @@ class LlamacppChatChoicesStreamService(lang.ExitStacked):
76
88
  rs.enter_context(lang.defer(close_output))
77
89
 
78
90
  async def inner(sink: StreamResponseSink[AiChoicesDeltas]) -> ta.Sequence[ChatChoicesOutputs] | None:
91
+ last_role: ta.Any = None
92
+
79
93
  for chunk in output:
80
94
  check.state(chunk['object'] == 'chat.completion.chunk')
81
- l: list[AiChoiceDeltas] = []
82
- for choice in chunk['choices']:
83
- # FIXME: check role is assistant
84
- # FIXME: stop reason
85
- if not (delta := choice.get('delta', {})):
86
- continue
87
- if not (content := delta.get('content', '')):
88
- continue
89
- l.append(AiChoiceDeltas([ContentAiChoiceDelta(content)]))
90
- await sink.emit(AiChoicesDeltas(l))
95
+
96
+ choice = check.single(chunk['choices'])
97
+
98
+ if not (delta := choice.get('delta', {})):
99
+ continue
100
+
101
+ # FIXME: check role is assistant
102
+ if (role := delta.get('role')) != last_role:
103
+ last_role = role
104
+
105
+ # FIXME: stop reason
106
+
107
+ if (content := delta.get('content', '')):
108
+ await sink.emit(AiChoicesDeltas([AiChoiceDeltas([ContentAiDelta(content)])]))
109
+
91
110
  return None
92
111
 
93
112
  return await new_stream_response(rs, inner)
@@ -40,10 +40,16 @@ class MistralChatChoicesService:
40
40
  AiMessage: 'assistant',
41
41
  }
42
42
 
43
- def __init__(self, *, api_key: str | None = None) -> None:
43
+ def __init__(
44
+ self,
45
+ *,
46
+ api_key: str | None = None,
47
+ http_client: http.AsyncHttpClient | None = None,
48
+ ) -> None:
44
49
  super().__init__()
45
50
 
46
51
  self._api_key = api_key
52
+ self._http_client = http_client
47
53
 
48
54
  def _get_msg_content(self, m: Message) -> str | None:
49
55
  if isinstance(m, AiMessage):
@@ -73,7 +79,7 @@ class MistralChatChoicesService:
73
79
  ],
74
80
  }
75
81
 
76
- resp = http.request(
82
+ resp = await http.async_request(
77
83
  'https://api.mistral.ai/v1/chat/completions',
78
84
  method='POST',
79
85
  data=json.dumps_compact(req_dct).encode('utf-8'),
@@ -82,6 +88,7 @@ class MistralChatChoicesService:
82
88
  'Accept': 'application/json',
83
89
  'Authorization': f'Bearer {key}',
84
90
  },
91
+ client=self._http_client,
85
92
  )
86
93
 
87
94
  if resp.status == 429:
@@ -1,32 +1,46 @@
1
+ import contextlib
1
2
  import typing as ta
2
3
 
3
4
  from omlish import check
4
5
  from omlish import lang
5
6
  from omlish import typedvalues as tv
6
7
 
7
- from .....backends import mlx as mlxu
8
+ from ....chat.choices.services import ChatChoicesOutputs
8
9
  from ....chat.choices.services import ChatChoicesRequest
9
10
  from ....chat.choices.services import ChatChoicesResponse
10
11
  from ....chat.choices.services import static_check_is_chat_choices_service
12
+ from ....chat.choices.stream.services import ChatChoicesStreamRequest
13
+ from ....chat.choices.stream.services import ChatChoicesStreamResponse
14
+ from ....chat.choices.stream.services import static_check_is_chat_choices_stream_service
15
+ from ....chat.choices.stream.types import AiChoiceDeltas
16
+ from ....chat.choices.stream.types import AiChoicesDeltas
11
17
  from ....chat.choices.types import AiChoice
12
18
  from ....chat.choices.types import ChatChoicesOptions
13
19
  from ....chat.messages import AiMessage
14
20
  from ....chat.messages import Message
15
21
  from ....chat.messages import SystemMessage
16
22
  from ....chat.messages import UserMessage
23
+ from ....chat.stream.types import ContentAiDelta
17
24
  from ....configs import Config
18
25
  from ....llms.types import MaxTokens
19
26
  from ....models.configs import ModelPath
20
27
  from ....models.configs import ModelRepo
21
28
  from ....models.configs import ModelSpecifier
29
+ from ....resources import UseResources
22
30
  from ....standard import DefaultOptions
31
+ from ....stream.services import StreamResponseSink
32
+ from ....stream.services import new_stream_response
33
+
34
+
35
+ with lang.auto_proxy_import(globals()):
36
+ from .....backends import mlx as mlxu
23
37
 
24
38
 
25
39
  ##
26
40
 
27
41
 
28
42
  # @omlish-manifest $.minichain.backends.strings.manifests.BackendStringsManifest(
29
- # ['ChatChoicesService'],
43
+ # ['ChatChoicesService', 'ChatChoicesStreamService'],
30
44
  # 'mlx',
31
45
  # )
32
46
 
@@ -34,12 +48,7 @@ from ....standard import DefaultOptions
34
48
  ##
35
49
 
36
50
 
37
- # @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
38
- # name='mlx',
39
- # type='ChatChoicesService',
40
- # )
41
- @static_check_is_chat_choices_service
42
- class MlxChatChoicesService(lang.ExitStacked):
51
+ class BaseMlxChatChoicesService(lang.ExitStacked):
43
52
  DEFAULT_MODEL: ta.ClassVar[ModelSpecifier] = (
44
53
  # 'mlx-community/DeepSeek-Coder-V2-Lite-Instruct-8bit'
45
54
  # 'mlx-community/Llama-3.3-70B-Instruct-4bit'
@@ -52,8 +61,8 @@ class MlxChatChoicesService(lang.ExitStacked):
52
61
  # 'mlx-community/Qwen2.5-0.5B-4bit'
53
62
  # 'mlx-community/Qwen2.5-32B-Instruct-8bit'
54
63
  # 'mlx-community/Qwen2.5-Coder-32B-Instruct-8bit'
55
- # 'mlx-community/mamba-2.8b-hf-f16'
56
64
  # 'mlx-community/Qwen3-30B-A3B-6bit'
65
+ # 'mlx-community/mamba-2.8b-hf-f16'
57
66
  )
58
67
 
59
68
  def __init__(self, *configs: Config) -> None:
@@ -70,17 +79,14 @@ class MlxChatChoicesService(lang.ExitStacked):
70
79
  }
71
80
 
72
81
  def _get_msg_content(self, m: Message) -> str | None:
73
- if isinstance(m, AiMessage):
74
- return check.isinstance(m.c, str)
75
-
76
- elif isinstance(m, (SystemMessage, UserMessage)):
82
+ if isinstance(m, (AiMessage, SystemMessage, UserMessage)):
77
83
  return check.isinstance(m.c, str)
78
84
 
79
85
  else:
80
86
  raise TypeError(m)
81
87
 
82
88
  @lang.cached_function(transient=True)
83
- def _load_model(self) -> mlxu.LoadedModel:
89
+ def _load_model(self) -> 'mlxu.LoadedModel':
84
90
  # FIXME: walk state, find all mx.arrays, dealloc/set to empty
85
91
  check.not_none(self._exit_stack)
86
92
 
@@ -96,10 +102,9 @@ class MlxChatChoicesService(lang.ExitStacked):
96
102
  max_tokens=MaxTokens,
97
103
  )
98
104
 
99
- async def invoke(self, request: ChatChoicesRequest) -> ChatChoicesResponse:
100
- loaded_model = self._load_model()
101
-
102
- tokenizer = loaded_model.tokenization.tokenizer
105
+ @lang.cached_function(transient=True)
106
+ def _get_tokenizer(self) -> 'mlxu.tokenization.Tokenizer':
107
+ tokenizer = self._load_model().tokenization.tokenizer
103
108
 
104
109
  if not (
105
110
  hasattr(tokenizer, 'apply_chat_template') and
@@ -107,26 +112,44 @@ class MlxChatChoicesService(lang.ExitStacked):
107
112
  ):
108
113
  raise RuntimeError(tokenizer)
109
114
 
110
- prompt = tokenizer.apply_chat_template(
115
+ return tokenizer
116
+
117
+ def _build_prompt(self, messages: ta.Sequence[Message]) -> str:
118
+ return check.isinstance(self._get_tokenizer().apply_chat_template(
111
119
  [ # type: ignore[arg-type]
112
120
  dict(
113
121
  role=self.ROLES_MAP[type(m)],
114
122
  content=self._get_msg_content(m),
115
123
  )
116
- for m in request.v
124
+ for m in messages
117
125
  ],
118
126
  tokenize=False,
119
127
  add_generation_prompt=True,
120
- )
128
+ ), str)
129
+
130
+ def _build_kwargs(self, oc: tv.TypedValuesConsumer) -> dict[str, ta.Any]:
131
+ kwargs: dict[str, ta.Any] = {}
132
+ kwargs.update(oc.pop_scalar_kwargs(**self._OPTION_KWARG_NAMES_MAP))
133
+ return kwargs
121
134
 
122
- kwargs = dict()
135
+
136
+ # @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
137
+ # name='mlx',
138
+ # type='ChatChoicesService',
139
+ # )
140
+ @static_check_is_chat_choices_service
141
+ class MlxChatChoicesService(BaseMlxChatChoicesService):
142
+ async def invoke(self, request: ChatChoicesRequest) -> ChatChoicesResponse:
143
+ loaded_model = self._load_model()
144
+
145
+ prompt = self._build_prompt(request.v)
123
146
 
124
147
  with tv.consume(
125
148
  *self._default_options,
126
149
  *request.options,
127
150
  override=True,
128
151
  ) as oc:
129
- kwargs.update(oc.pop_scalar_kwargs(**self._OPTION_KWARG_NAMES_MAP))
152
+ kwargs = self._build_kwargs(oc)
130
153
 
131
154
  response = mlxu.generate(
132
155
  loaded_model.model,
@@ -139,3 +162,57 @@ class MlxChatChoicesService(lang.ExitStacked):
139
162
  return ChatChoicesResponse([
140
163
  AiChoice([AiMessage(response)]) # noqa
141
164
  ])
165
+
166
+
167
+ # @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
168
+ # name='mlx',
169
+ # type='ChatChoicesStreamService',
170
+ # )
171
+ @static_check_is_chat_choices_stream_service
172
+ class MlxChatChoicesStreamService(BaseMlxChatChoicesService):
173
+ def __init__(self, *configs: Config) -> None:
174
+ super().__init__()
175
+
176
+ with tv.consume(*configs) as cc:
177
+ self._model = cc.pop(MlxChatChoicesService.DEFAULT_MODEL)
178
+ self._default_options: tv.TypedValues = DefaultOptions.pop(cc)
179
+
180
+ READ_CHUNK_SIZE = 64 * 1024
181
+
182
+ async def invoke(
183
+ self,
184
+ request: ChatChoicesStreamRequest,
185
+ *,
186
+ max_tokens: int = 4096, # FIXME: ChatOption
187
+ ) -> ChatChoicesStreamResponse:
188
+ loaded_model = self._load_model()
189
+
190
+ prompt = self._build_prompt(request.v)
191
+
192
+ with tv.consume(
193
+ *self._default_options,
194
+ *request.options,
195
+ override=True,
196
+ ) as oc:
197
+ oc.pop(UseResources, None)
198
+ kwargs = self._build_kwargs(oc)
199
+
200
+ async with UseResources.or_new(request.options) as rs:
201
+ gen: ta.Iterator[mlxu.GenerationOutput] = rs.enter_context(contextlib.closing(mlxu.stream_generate(
202
+ loaded_model.model,
203
+ loaded_model.tokenization,
204
+ check.isinstance(prompt, str),
205
+ mlxu.GenerationParams(**kwargs),
206
+ # verbose=True,
207
+ )))
208
+
209
+ async def inner(sink: StreamResponseSink[AiChoicesDeltas]) -> ta.Sequence[ChatChoicesOutputs]:
210
+ for go in gen:
211
+ if go.text:
212
+ await sink.emit(AiChoicesDeltas([AiChoiceDeltas([
213
+ ContentAiDelta(go.text),
214
+ ])]))
215
+
216
+ return []
217
+
218
+ return await new_stream_response(rs, inner)
File without changes
@@ -0,0 +1,193 @@
1
+ """
2
+ dolphin3:latest d5ab9ae8e1f2 4.9 GB 11 months ago (no tools)
3
+
4
+ functiongemma:270m 7c19b650567a 300 MB 5 minutes ago
5
+ gemma3:27b a418f5838eaf 17 GB 7 weeks ago (no tools)
6
+ gemma3:4b a2af6cc3eb7f 3.3 GB 7 weeks ago (no tools)
7
+
8
+ llama3.2:1b baf6a787fdff 1.3 GB 13 months ago (too stupid for tools)
9
+ llama3.2:latest a80c4f17acd5 2.0 GB 13 months ago
10
+
11
+ devstral-small-2:24b 24277f07f62d 15 GB 15 hours ago
12
+ ministral-3:14b 4760c35aeb9d 9.1 GB 11 hours ago
13
+ mistral:latest 6577803aa9a0 4.4 GB 3 seconds ago
14
+
15
+ nemotron-3-nano:30b b725f1117407 24 GB 15 hours ago
16
+
17
+ olmo-3.1:32b-instruct a16b6a5be6cf 19 GB 11 hours ago (no tools)
18
+ olmo-3.1:32b-think 223d4ec84d91 19 GB 11 hours ago (no tools)
19
+
20
+ phi4-mini:latest 78fad5d182a7 2.5 GB 8 months ago (no tools)
21
+
22
+ qwen3-coder:30b 06c1097efce0 18 GB 11 hours ago
23
+ qwen3-next:80b b2ebb986e4e9 50 GB 11 hours ago
24
+ qwen3:30b ad815644918f 18 GB 11 hours ago
25
+ qwen3:32b 030ee887880f 20 GB 11 hours ago
26
+ """
27
+ import typing as ta
28
+
29
+ from omlish import check
30
+ from omlish import lang
31
+ from omlish import marshal as msh
32
+ from omlish import typedvalues as tv
33
+ from omlish.formats import json
34
+ from omlish.http import all as http
35
+ from omlish.io.buffers import DelimitingBuffer
36
+
37
+ from .....backends.ollama import protocol as pt
38
+ from ....chat.choices.services import ChatChoicesOutputs
39
+ from ....chat.choices.services import ChatChoicesRequest
40
+ from ....chat.choices.services import ChatChoicesResponse
41
+ from ....chat.choices.services import static_check_is_chat_choices_service
42
+ from ....chat.choices.stream.services import ChatChoicesStreamRequest
43
+ from ....chat.choices.stream.services import ChatChoicesStreamResponse
44
+ from ....chat.choices.stream.services import static_check_is_chat_choices_stream_service
45
+ from ....chat.choices.stream.types import AiChoicesDeltas
46
+ from ....chat.tools.types import Tool
47
+ from ....models.configs import ModelName
48
+ from ....resources import UseResources
49
+ from ....standard import ApiUrl
50
+ from ....stream.services import StreamResponseSink
51
+ from ....stream.services import new_stream_response
52
+ from .protocol import build_mc_ai_choice_deltas
53
+ from .protocol import build_mc_choices_response
54
+ from .protocol import build_ol_request_messages
55
+ from .protocol import build_ol_request_tool
56
+
57
+
58
+ ##
59
+
60
+
61
+ # @omlish-manifest $.minichain.backends.strings.manifests.BackendStringsManifest(
62
+ # [
63
+ # 'ChatChoicesService',
64
+ # 'ChatChoicesStreamService',
65
+ # ],
66
+ # 'ollama',
67
+ # )
68
+
69
+
70
+ ##
71
+
72
+
73
+ class BaseOllamaChatChoicesService(lang.Abstract):
74
+ DEFAULT_API_URL: ta.ClassVar[ApiUrl] = ApiUrl('http://localhost:11434/api')
75
+ DEFAULT_MODEL_NAME: ta.ClassVar[ModelName] = ModelName('llama3.2')
76
+
77
+ def __init__(
78
+ self,
79
+ *configs: ApiUrl | ModelName,
80
+ http_client: http.AsyncHttpClient | None = None,
81
+ ) -> None:
82
+ super().__init__()
83
+
84
+ self._http_client = http_client
85
+
86
+ with tv.consume(*configs) as cc:
87
+ self._api_url = cc.pop(self.DEFAULT_API_URL)
88
+ self._model_name = cc.pop(self.DEFAULT_MODEL_NAME)
89
+
90
+
91
+ ##
92
+
93
+
94
+ # @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
95
+ # name='ollama',
96
+ # type='ChatChoicesService',
97
+ # )
98
+ @static_check_is_chat_choices_service
99
+ class OllamaChatChoicesService(BaseOllamaChatChoicesService):
100
+ async def invoke(
101
+ self,
102
+ request: ChatChoicesRequest,
103
+ ) -> ChatChoicesResponse:
104
+ messages = build_ol_request_messages(request.v)
105
+
106
+ tools: list[pt.Tool] = []
107
+ with tv.TypedValues(*request.options).consume() as oc:
108
+ t: Tool
109
+ for t in oc.pop(Tool, []):
110
+ tools.append(build_ol_request_tool(t))
111
+
112
+ a_req = pt.ChatRequest(
113
+ model=self._model_name.v,
114
+ messages=messages,
115
+ tools=tools or None,
116
+ stream=False,
117
+ )
118
+
119
+ raw_request = msh.marshal(a_req)
120
+
121
+ async with http.manage_async_client(self._http_client) as http_client:
122
+ raw_response = await http_client.request(http.HttpRequest(
123
+ self._api_url.v.removesuffix('/') + '/chat',
124
+ data=json.dumps(raw_request).encode('utf-8'),
125
+ ))
126
+
127
+ json_response = json.loads(check.not_none(raw_response.data).decode('utf-8'))
128
+
129
+ resp = msh.unmarshal(json_response, pt.ChatResponse)
130
+
131
+ return build_mc_choices_response(resp)
132
+
133
+
134
+ ##
135
+
136
+
137
+ # @omlish-manifest $.minichain.registries.manifests.RegistryManifest(
138
+ # name='ollama',
139
+ # type='ChatChoicesStreamService',
140
+ # )
141
+ @static_check_is_chat_choices_stream_service
142
+ class OllamaChatChoicesStreamService(BaseOllamaChatChoicesService):
143
+ READ_CHUNK_SIZE: ta.ClassVar[int] = -1
144
+
145
+ async def invoke(
146
+ self,
147
+ request: ChatChoicesStreamRequest,
148
+ ) -> ChatChoicesStreamResponse:
149
+ messages = build_ol_request_messages(request.v)
150
+
151
+ tools: list[pt.Tool] = []
152
+ with tv.TypedValues(*request.options).consume() as oc:
153
+ t: Tool
154
+ for t in oc.pop(Tool, []):
155
+ tools.append(build_ol_request_tool(t))
156
+
157
+ a_req = pt.ChatRequest(
158
+ model=self._model_name.v,
159
+ messages=messages,
160
+ tools=tools or None,
161
+ stream=True,
162
+ )
163
+
164
+ raw_request = msh.marshal(a_req)
165
+
166
+ http_request = http.HttpRequest(
167
+ self._api_url.v.removesuffix('/') + '/chat',
168
+ data=json.dumps(raw_request).encode('utf-8'),
169
+ )
170
+
171
+ async with UseResources.or_new(request.options) as rs:
172
+ http_client = await rs.enter_async_context(http.manage_async_client(self._http_client))
173
+ http_response = await rs.enter_async_context(await http_client.stream_request(http_request))
174
+
175
+ async def inner(sink: StreamResponseSink[AiChoicesDeltas]) -> ta.Sequence[ChatChoicesOutputs] | None:
176
+ db = DelimitingBuffer([b'\r', b'\n', b'\r\n'])
177
+ while True:
178
+ b = await http_response.stream.read1(self.READ_CHUNK_SIZE)
179
+ for l in db.feed(b):
180
+ if isinstance(l, DelimitingBuffer.Incomplete):
181
+ # FIXME: handle
182
+ raise TypeError(l)
183
+
184
+ lj = json.loads(l.decode('utf-8'))
185
+ lp: pt.ChatResponse = msh.unmarshal(lj, pt.ChatResponse)
186
+
187
+ if (ds := build_mc_ai_choice_deltas(lp)).deltas:
188
+ await sink.emit(AiChoicesDeltas([ds]))
189
+
190
+ if not b:
191
+ return []
192
+
193
+ return await new_stream_response(rs, inner)