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
@@ -0,0 +1,29 @@
1
+ from omlish import inject as inj
2
+ from omlish import lang
3
+
4
+ from .bare.configs import BareInterfaceConfig
5
+ from .configs import InterfaceConfig
6
+ from .textual.configs import TextualInterfaceConfig
7
+
8
+
9
+ with lang.auto_proxy_import(globals()):
10
+ from .bare import inject as _bare
11
+ from .textual import inject as _textual
12
+
13
+
14
+ ##
15
+
16
+
17
+ def bind_interface(cfg: InterfaceConfig = BareInterfaceConfig()) -> inj.Elements:
18
+ els: list[inj.Elemental] = []
19
+
20
+ if isinstance(cfg, TextualInterfaceConfig):
21
+ els.append(_textual.bind_textual(cfg))
22
+
23
+ elif isinstance(cfg, BareInterfaceConfig):
24
+ els.append(_bare.bind_bare(cfg))
25
+
26
+ else:
27
+ raise TypeError(cfg)
28
+
29
+ return inj.as_elements(*els)
@@ -0,0 +1,429 @@
1
+ """
2
+ TODO:
3
+ - textual.getters.query_one
4
+ - AUTO_FOCUS
5
+ """
6
+ import asyncio
7
+ import os
8
+ import typing as ta
9
+ import weakref
10
+
11
+ from omdev.tui import textual as tx
12
+ from omlish import check
13
+ from omlish import dataclasses as dc
14
+ from omlish import lang
15
+ from omlish.logs import all as logs
16
+
17
+ from ...... import minichain as mc
18
+ from .....backends.types import BackendName
19
+ from ...drivers.events.types import AiDeltaChatEvent
20
+ from ...drivers.events.types import AiMessagesChatEvent
21
+ from ...drivers.types import ChatDriver
22
+ from ...facades.facade import ChatFacade
23
+ from .inputhistory import InputHistoryManager
24
+ from .styles import read_app_css
25
+ from .widgets.input import InputOuter
26
+ from .widgets.input import InputTextArea
27
+ from .widgets.messages import AiMessage
28
+ from .widgets.messages import MessageDivider
29
+ from .widgets.messages import MessagesContainer
30
+ from .widgets.messages import StaticAiMessage
31
+ from .widgets.messages import StreamAiMessage
32
+ from .widgets.messages import ToolConfirmationMessage
33
+ from .widgets.messages import UiMessage
34
+ from .widgets.messages import UserMessage
35
+ from .widgets.messages import WelcomeMessage
36
+
37
+
38
+ log, alog = logs.get_module_loggers(globals())
39
+
40
+
41
+ ##
42
+
43
+
44
+ ChatEventQueue = ta.NewType('ChatEventQueue', asyncio.Queue)
45
+
46
+
47
+ ##
48
+
49
+
50
+ class ChatAppGetter(lang.AsyncCachedFunc0['ChatApp']):
51
+ pass
52
+
53
+
54
+ class ChatAppScreen(tx.Screen):
55
+ BINDINGS: ta.ClassVar[ta.Sequence[tx.BindingType]] = [
56
+ tx.Binding(
57
+ 'alt+c,super+c',
58
+ 'screen.copy_text',
59
+ 'Copy selected text',
60
+ show=False,
61
+ ),
62
+ ]
63
+
64
+ @classmethod
65
+ def _merge_bindings(cls) -> tx.BindingsMap:
66
+ return tx.unbind_map_keys(super()._merge_bindings(), ['ctrl+c'])
67
+
68
+
69
+ class ChatApp(
70
+ tx.ClipboardAppMixin,
71
+ tx.DevtoolsAppMixin,
72
+ tx.App,
73
+ ):
74
+ ENABLE_COMMAND_PALETTE: ta.ClassVar[bool] = False
75
+
76
+ BINDINGS: ta.ClassVar[ta.Sequence[tx.BindingType]] = [
77
+ *tx.App.BINDINGS,
78
+
79
+ tx.Binding(
80
+ 'escape',
81
+ 'cancel',
82
+ 'Cancel current operation',
83
+ show=False,
84
+ priority=True,
85
+ ),
86
+ ]
87
+
88
+ def __init__(
89
+ self,
90
+ *,
91
+ chat_facade: ChatFacade,
92
+ chat_driver: ChatDriver,
93
+ chat_event_queue: ChatEventQueue,
94
+ backend_name: BackendName | None = None,
95
+ devtools_setup: tx.DevtoolsSetup | None = None,
96
+ input_history_manager: InputHistoryManager,
97
+ ) -> None:
98
+ super().__init__()
99
+
100
+ if devtools_setup is not None:
101
+ devtools_setup(self)
102
+
103
+ self._chat_facade = chat_facade
104
+ self._chat_driver = chat_driver
105
+ self._chat_event_queue = chat_event_queue
106
+ self._backend_name = backend_name
107
+ self._input_history_manager = input_history_manager
108
+
109
+ self._chat_action_queue: asyncio.Queue[ta.Any] = asyncio.Queue()
110
+
111
+ self._input_focused_key_events: weakref.WeakSet[tx.Key] = weakref.WeakSet()
112
+
113
+ def get_driver_class(self) -> type[tx.Driver]:
114
+ return tx.get_pending_writes_driver_class(super().get_driver_class())
115
+
116
+ def get_default_screen(self) -> tx.Screen:
117
+ return ChatAppScreen(id='_default')
118
+
119
+ CSS: ta.ClassVar[str] = read_app_css()
120
+
121
+ ##
122
+ # Compose
123
+
124
+ def compose(self) -> tx.ComposeResult:
125
+ yield MessagesContainer(id='messages-container')
126
+
127
+ yield InputOuter(id='input-outer')
128
+
129
+ ##
130
+ # Widget getters
131
+
132
+ def _get_input_text_area(self) -> InputTextArea:
133
+ return self.query_one('#input', InputTextArea)
134
+
135
+ def _get_messages_container(self) -> tx.VerticalScroll:
136
+ return self.query_one('#messages-container', MessagesContainer)
137
+
138
+ ##
139
+ # Messages
140
+
141
+ def _is_messages_at_bottom(self, threshold: int = 3) -> bool:
142
+ return (ms := self._get_messages_container()).scroll_y >= (ms.max_scroll_y - threshold)
143
+
144
+ def _scroll_messages_to_bottom(self) -> None:
145
+ self._get_messages_container().scroll_end(animate=False)
146
+
147
+ def _anchor_messages(self) -> None:
148
+ if (ms := self._get_messages_container()).max_scroll_y:
149
+ ms.anchor()
150
+
151
+ def _scroll_messages_to_bottom_and_anchor(self) -> None:
152
+ self._scroll_messages_to_bottom()
153
+ self._anchor_messages()
154
+
155
+ #
156
+
157
+ _pending_mount_messages: list[tx.Widget] | None = None
158
+
159
+ async def _enqueue_mount_messages(self, *messages: tx.Widget) -> None:
160
+ if (lst := self._pending_mount_messages) is None:
161
+ lst = self._pending_mount_messages = []
162
+
163
+ lst.extend(messages)
164
+
165
+ _stream_ai_message: StreamAiMessage | None = None
166
+
167
+ async def _finalize_stream_ai_message(self) -> None:
168
+ if self._stream_ai_message is None:
169
+ return
170
+
171
+ await self._stream_ai_message.stop_stream()
172
+ self._stream_ai_message = None
173
+
174
+ async def _append_stream_ai_message_content(self, content: str) -> None:
175
+ if (sam := self._stream_ai_message) is not None:
176
+ was_at_bottom = self._is_messages_at_bottom()
177
+
178
+ await sam.append_content(content)
179
+
180
+ if was_at_bottom:
181
+ self.call_after_refresh(self._scroll_messages_to_bottom_and_anchor)
182
+
183
+ else:
184
+ await self._mount_messages(StreamAiMessage(content))
185
+
186
+ _num_mounted_messages = 0
187
+
188
+ async def _mount_messages(self, *messages: tx.Widget) -> None:
189
+ was_at_bottom = self._is_messages_at_bottom()
190
+
191
+ msg_ctr = self._get_messages_container()
192
+
193
+ for msg in [*(self._pending_mount_messages or []), *messages]:
194
+ if isinstance(msg, (AiMessage, ToolConfirmationMessage)):
195
+ await self._finalize_stream_ai_message()
196
+
197
+ if self._num_mounted_messages:
198
+ await msg_ctr.mount(MessageDivider())
199
+
200
+ await msg_ctr.mount(msg)
201
+
202
+ self._num_mounted_messages += 1
203
+
204
+ if isinstance(msg, StreamAiMessage):
205
+ self._stream_ai_message = check.replacing_none(self._stream_ai_message, msg)
206
+ await msg.write_initial_content()
207
+
208
+ self._pending_mount_messages = None
209
+
210
+ self.call_after_refresh(self._scroll_messages_to_bottom)
211
+
212
+ if was_at_bottom:
213
+ self.call_after_refresh(self._anchor_messages)
214
+
215
+ ##
216
+ # Chat events
217
+
218
+ _chat_event_queue_task: asyncio.Task[None] | None = None
219
+
220
+ @logs.async_exception_logging(alog, BaseException)
221
+ async def _chat_event_queue_task_main(self) -> None:
222
+ while True:
223
+ ev = await self._chat_event_queue.get()
224
+ if ev is None:
225
+ break
226
+
227
+ await alog.debug(lambda: f'Got chat event: {ev!r}')
228
+
229
+ if isinstance(ev, AiMessagesChatEvent):
230
+ wx: list[tx.Widget] = []
231
+
232
+ for ai_msg in ev.chat:
233
+ if isinstance(ai_msg, mc.AiMessage):
234
+ wx.append(
235
+ StaticAiMessage(
236
+ check.isinstance(ai_msg.c, str),
237
+ markdown=True,
238
+ ),
239
+ )
240
+
241
+ if wx:
242
+ await self._enqueue_mount_messages(*wx)
243
+ self.call_later(self._mount_messages)
244
+
245
+ elif isinstance(ev, AiDeltaChatEvent):
246
+ if isinstance(ev.delta, mc.ContentAiDelta):
247
+ cc = check.isinstance(ev.delta.c, str)
248
+ self.call_later(self._append_stream_ai_message_content, cc)
249
+
250
+ elif isinstance(ev.delta, mc.ToolUseAiDelta):
251
+ pass
252
+
253
+ ##
254
+ # Chat actions
255
+
256
+ @dc.dataclass(frozen=True)
257
+ class UserInput:
258
+ text: str
259
+
260
+ async def _execute_user_input(self, ac: UserInput) -> None:
261
+ try:
262
+ await self._chat_facade.handle_user_input(ac.text)
263
+ except Exception as e: # noqa
264
+ # raise
265
+ await self.display_ui_message(repr(e))
266
+
267
+ #
268
+
269
+ _cur_chat_action: asyncio.Task[None] | None = None
270
+
271
+ async def _execute_chat_action(self, fn: ta.Callable[[], ta.Any]) -> None:
272
+ check.state(self._cur_chat_action is None)
273
+
274
+ self._cur_chat_action = asyncio.create_task(fn())
275
+
276
+ try:
277
+ await self._cur_chat_action
278
+
279
+ except asyncio.CancelledError:
280
+ pass
281
+
282
+ except BaseException as e: # noqa
283
+ raise
284
+
285
+ finally:
286
+ self._cur_chat_action = None
287
+
288
+ #
289
+
290
+ _chat_action_queue_task: asyncio.Task[None] | None = None
291
+
292
+ @logs.async_exception_logging(alog, BaseException)
293
+ async def _chat_action_queue_task_main(self) -> None:
294
+ while True:
295
+ ac = await self._chat_action_queue.get()
296
+ if ac is None:
297
+ break
298
+
299
+ await alog.debug(lambda: f'Got chat action: {ac!r}')
300
+
301
+ if isinstance(ac, ChatApp.UserInput):
302
+ await self._execute_chat_action(lambda: self._execute_user_input(ac))
303
+
304
+ else:
305
+ raise TypeError(ac) # noqa
306
+
307
+ ##
308
+ # Mounting
309
+
310
+ async def on_mount(self) -> None:
311
+ check.state(self._chat_event_queue_task is None)
312
+ self._chat_event_queue_task = asyncio.create_task(self._chat_event_queue_task_main())
313
+
314
+ await self._chat_driver.start()
315
+
316
+ check.state(self._chat_action_queue_task is None)
317
+ self._chat_action_queue_task = asyncio.create_task(self._chat_action_queue_task_main())
318
+
319
+ self._get_input_text_area().focus()
320
+
321
+ await self._mount_messages(
322
+ WelcomeMessage('\n'.join([
323
+ f'Backend: {self._backend_name or "?"}',
324
+ f'Dir: {os.getcwd()}',
325
+ ])),
326
+ )
327
+
328
+ async def on_unmount(self) -> None:
329
+ if (cat := self._chat_action_queue_task) is not None:
330
+ await self._chat_event_queue.put(None)
331
+ await cat
332
+
333
+ await self._chat_driver.stop()
334
+
335
+ if (cet := self._chat_event_queue_task) is not None:
336
+ await self._chat_event_queue.put(None)
337
+ await cet
338
+
339
+ ##
340
+ # Input
341
+
342
+ @tx.on(InputTextArea.Submitted)
343
+ async def on_input_text_area_submitted(self, event: InputTextArea.Submitted) -> None:
344
+ self._get_input_text_area().clear()
345
+
346
+ await self._finalize_stream_ai_message()
347
+
348
+ await self._mount_messages(
349
+ UserMessage(
350
+ event.text,
351
+ ),
352
+ )
353
+
354
+ self._input_history_manager.add(event.text)
355
+
356
+ await self._chat_action_queue.put(ChatApp.UserInput(event.text))
357
+
358
+ def _move_input_cursor_to_end(self) -> None:
359
+ ita = self._get_input_text_area()
360
+ ln = ita.document.line_count - 1
361
+ lt = ita.document.lines[ln]
362
+ ita.move_cursor((ln, len(lt)))
363
+
364
+ @tx.on(InputTextArea.HistoryPrevious)
365
+ async def on_input_text_area_history_previous(self, event: InputTextArea.HistoryPrevious) -> None:
366
+ if (entry := self._input_history_manager.get_previous(event.text)) is not None:
367
+ self._get_input_text_area().text = entry
368
+ self._move_input_cursor_to_end()
369
+
370
+ @tx.on(InputTextArea.HistoryNext)
371
+ async def on_input_text_area_history_next(self, event: InputTextArea.HistoryNext) -> None:
372
+ if (entry := self._input_history_manager.get_next(event.text)) is not None:
373
+ ita = self._get_input_text_area()
374
+ ita.text = entry
375
+ self._move_input_cursor_to_end()
376
+ else:
377
+ # At the end of history, clear the input
378
+ ita = self._get_input_text_area()
379
+ ita.clear()
380
+ self._input_history_manager.reset_position()
381
+
382
+ @tx.on(tx.Key)
383
+ async def on_key(self, event: tx.Key) -> None:
384
+ if event in self._input_focused_key_events:
385
+ return
386
+
387
+ chat_input = self._get_input_text_area()
388
+
389
+ if not chat_input.has_focus:
390
+ self._input_focused_key_events.add(event)
391
+
392
+ chat_input.focus()
393
+
394
+ self.screen.post_message(tx.Key(event.key, event.character))
395
+
396
+ ##
397
+ # User interaction
398
+
399
+ async def confirm_tool_use(
400
+ self,
401
+ outer_message: str,
402
+ inner_message: str,
403
+ ) -> bool:
404
+ fut: asyncio.Future[bool] = asyncio.get_running_loop().create_future()
405
+
406
+ tcm = ToolConfirmationMessage(
407
+ outer_message,
408
+ inner_message,
409
+ fut,
410
+ )
411
+
412
+ async def inner() -> None:
413
+ await self._mount_messages(tcm)
414
+
415
+ self.call_later(inner)
416
+
417
+ ret = await fut
418
+
419
+ return ret
420
+
421
+ async def display_ui_message(
422
+ self,
423
+ content: str,
424
+ ) -> None:
425
+ await self._mount_messages(UiMessage(content))
426
+
427
+ async def action_cancel(self) -> None:
428
+ if (cat := self._cur_chat_action) is not None:
429
+ cat.cancel()
@@ -0,0 +1,11 @@
1
+ from omlish import dataclasses as dc
2
+
3
+ from ..configs import InterfaceConfig
4
+
5
+
6
+ ##
7
+
8
+
9
+ @dc.dataclass(frozen=True, kw_only=True)
10
+ class TextualInterfaceConfig(InterfaceConfig):
11
+ input_history_file: str | None = None
@@ -0,0 +1,19 @@
1
+ from ...facades.ui import UiMessageDisplayer
2
+ from .app import ChatAppGetter
3
+
4
+
5
+ ##
6
+
7
+
8
+ class ChatAppUiMessageDisplayer(UiMessageDisplayer):
9
+ def __init__(
10
+ self,
11
+ *,
12
+ app: ChatAppGetter,
13
+ ) -> None:
14
+ super().__init__()
15
+
16
+ self._app = app
17
+
18
+ async def display_ui_message(self, content: str) -> None:
19
+ await (await self._app()).display_ui_message(content)
@@ -0,0 +1,111 @@
1
+ """
2
+ FIXME:
3
+ - too lazy to lazy import guts like every other proper inject module lol >_<
4
+ """
5
+ import asyncio
6
+ import contextlib
7
+
8
+ from omlish import inject as inj
9
+ from omlish import lang
10
+
11
+ from ...drivers.events.injection import event_callbacks
12
+ from ..base import ChatInterface
13
+ from .configs import TextualInterfaceConfig
14
+
15
+
16
+ with lang.auto_proxy_import(globals()):
17
+ from omdev.tui import textual as tx
18
+
19
+ from ...drivers.tools import confirmation as _tools_confirmation
20
+ from ...facades import ui as _facades_ui
21
+ from . import app as _app
22
+ from . import facades as _facades
23
+ from . import inputhistory as _inputhistory
24
+ from . import interface as _interface
25
+ from . import tools as _tools
26
+
27
+
28
+ ##
29
+
30
+
31
+ def bind_textual(cfg: TextualInterfaceConfig = TextualInterfaceConfig()) -> inj.Elements:
32
+ els: list[inj.Elemental] = [
33
+ inj.bind(ChatInterface, to_ctor=_interface.TextualChatInterface, singleton=True),
34
+ ]
35
+
36
+ #
37
+
38
+ els.extend([
39
+ inj.bind(_app.ChatApp, singleton=True),
40
+ inj.bind_async_late(_app.ChatApp, _app.ChatAppGetter),
41
+ ])
42
+
43
+ #
44
+
45
+ els.extend([
46
+ inj.bind(_app.ChatEventQueue, to_const=asyncio.Queue()),
47
+
48
+ event_callbacks().bind_item(to_fn=inj.target(eq=_app.ChatEventQueue)(lambda eq: lambda ev: eq.put(ev))),
49
+ ])
50
+
51
+ #
52
+
53
+ if cfg.enable_tools:
54
+ if cfg.dangerous_no_tool_confirmation:
55
+ els.append(inj.bind(
56
+ _tools_confirmation.ToolExecutionConfirmation,
57
+ to_ctor=_tools_confirmation.UnsafeAlwaysAllowToolExecutionConfirmation,
58
+ singleton=True,
59
+ ))
60
+
61
+ else:
62
+ els.append(inj.bind(
63
+ _tools_confirmation.ToolExecutionConfirmation,
64
+ to_ctor=_tools.ChatAppToolExecutionConfirmation,
65
+ singleton=True,
66
+ ))
67
+
68
+ #
69
+
70
+ els.extend([
71
+ inj.bind(tx.DevtoolsConfig(port=41932)), # FIXME: lol
72
+
73
+ inj.bind(
74
+ tx.DevtoolsManager,
75
+ singleton=True,
76
+ to_async_fn=inj.make_async_managed_provider(
77
+ tx.DevtoolsManager,
78
+ contextlib.aclosing,
79
+ ),
80
+ ),
81
+
82
+ inj.bind(
83
+ tx.DevtoolsSetup,
84
+ to_async_fn=inj.target(mgr=tx.DevtoolsManager)(lambda mgr: mgr.get_setup()),
85
+ singleton=True,
86
+ ),
87
+ ])
88
+
89
+ #
90
+
91
+ els.extend([
92
+ inj.bind(_facades.ChatAppUiMessageDisplayer, singleton=True),
93
+ inj.bind(_facades_ui.UiMessageDisplayer, to_key=_facades.ChatAppUiMessageDisplayer),
94
+ ])
95
+
96
+ #
97
+
98
+ def _make_input_history_storage() -> _inputhistory.InputHistoryStorage:
99
+ if cfg.input_history_file is not None:
100
+ return _inputhistory.FileInputHistoryStorage(path=cfg.input_history_file)
101
+ else:
102
+ return _inputhistory.InMemoryInputHistoryStorage()
103
+
104
+ els.extend([
105
+ inj.bind(_inputhistory.InputHistoryStorage, to_fn=_make_input_history_storage, singleton=True),
106
+ inj.bind(_inputhistory.InputHistoryManager, singleton=True),
107
+ ])
108
+
109
+ #
110
+
111
+ return inj.as_elements(*els)