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
ommlds/cli/asyncs.py ADDED
@@ -0,0 +1,30 @@
1
+ import abc
2
+ import functools
3
+ import typing as ta
4
+
5
+ from omlish import lang
6
+
7
+
8
+ with lang.auto_proxy_import(globals()):
9
+ import anyio
10
+
11
+
12
+ T = ta.TypeVar('T')
13
+ P = ta.ParamSpec('P')
14
+
15
+
16
+ ##
17
+
18
+
19
+ class AsyncThreadRunner(lang.Abstract):
20
+ @abc.abstractmethod
21
+ def run_in_thread(self, fn: ta.Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> ta.Awaitable[T]:
22
+ raise NotImplementedError
23
+
24
+
25
+ ##
26
+
27
+
28
+ class AnyioAsyncThreadRunner(AsyncThreadRunner):
29
+ def run_in_thread(self, fn: ta.Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> ta.Awaitable[T]:
30
+ return anyio.to_thread.run_sync(functools.partial(fn, *args, **kwargs))
@@ -0,0 +1,88 @@
1
+ import contextlib
2
+ import typing as ta
3
+
4
+ from omlish import lang
5
+
6
+ from ... import minichain as mc
7
+ from .types import BackendConfigs
8
+ from .types import BackendName
9
+ from .types import BackendProvider
10
+ from .types import ChatChoicesServiceBackendProvider
11
+ from .types import ChatChoicesStreamServiceBackendProvider
12
+ from .types import CompletionServiceBackendProvider
13
+ from .types import EmbeddingServiceBackendProvider
14
+ from .types import ServiceT
15
+
16
+
17
+ ##
18
+
19
+
20
+ class CatalogBackendProvider(BackendProvider[ServiceT], lang.Abstract):
21
+ class Instantiator(lang.Func2['mc.BackendCatalog.Backend', BackendConfigs | None, ta.Awaitable[ta.Any]]):
22
+ pass
23
+
24
+ def __init__(
25
+ self,
26
+ *,
27
+ name: BackendName | None = None,
28
+ catalog: 'mc.BackendCatalog',
29
+ configs: BackendConfigs | None = None,
30
+ instantiator: Instantiator | None = None,
31
+ ) -> None:
32
+ super().__init__()
33
+
34
+ self._name = name
35
+ self._catalog = catalog
36
+ self._configs = configs
37
+ if instantiator is None:
38
+ instantiator = CatalogBackendProvider.Instantiator(lang.as_async(lambda be, cfgs: be.factory(*cfgs or [])))
39
+ self._instantiator = instantiator
40
+
41
+ @contextlib.asynccontextmanager
42
+ async def _provide_backend(self, cls: type[ServiceT]) -> ta.AsyncIterator[ServiceT]:
43
+ name: str
44
+ if self._name is not None:
45
+ name = self._name
46
+ else:
47
+ raise RuntimeError('No backend name specified')
48
+
49
+ be = self._catalog.get_backend(cls, name)
50
+
51
+ service: ServiceT
52
+ async with lang.async_or_sync_maybe_managing(await self._instantiator(be, self._configs)) as service:
53
+ yield service
54
+
55
+
56
+ ##
57
+
58
+
59
+ class CatalogChatChoicesServiceBackendProvider(
60
+ CatalogBackendProvider['mc.ChatChoicesService'],
61
+ ChatChoicesServiceBackendProvider,
62
+ ):
63
+ def provide_backend(self) -> ta.AsyncContextManager['mc.ChatChoicesService']:
64
+ return self._provide_backend(mc.ChatChoicesService) # type: ignore[type-abstract]
65
+
66
+
67
+ class CatalogChatChoicesStreamServiceBackendProvider(
68
+ CatalogBackendProvider['mc.ChatChoicesStreamService'],
69
+ ChatChoicesStreamServiceBackendProvider,
70
+ ):
71
+ def provide_backend(self) -> ta.AsyncContextManager['mc.ChatChoicesStreamService']:
72
+ return self._provide_backend(mc.ChatChoicesStreamService) # type: ignore[type-abstract]
73
+
74
+
75
+ class CatalogCompletionServiceBackendProvider(
76
+ CatalogBackendProvider['mc.CompletionService'],
77
+ CompletionServiceBackendProvider,
78
+ ):
79
+ def provide_backend(self) -> ta.AsyncContextManager['mc.CompletionService']:
80
+ return self._provide_backend(mc.CompletionService) # type: ignore[type-abstract]
81
+
82
+
83
+ class CatalogEmbeddingServiceBackendProvider(
84
+ CatalogBackendProvider['mc.EmbeddingService'],
85
+ EmbeddingServiceBackendProvider,
86
+ ):
87
+ def provide_backend(self) -> ta.AsyncContextManager['mc.EmbeddingService']:
88
+ return self._provide_backend(mc.EmbeddingService) # type: ignore[type-abstract]
@@ -0,0 +1,9 @@
1
+ from omlish import dataclasses as dc
2
+
3
+
4
+ ##
5
+
6
+
7
+ @dc.dataclass(frozen=True, kw_only=True)
8
+ class BackendConfig:
9
+ backend: str | None = None
@@ -2,69 +2,127 @@ import typing as ta
2
2
 
3
3
  from omlish import inject as inj
4
4
  from omlish import lang
5
+ from omlish import typedvalues as tv
5
6
 
6
7
  from ... import minichain as mc
8
+ from .configs import BackendConfig
9
+ from .injection import backend_configs
10
+
11
+
12
+ with lang.auto_proxy_import(globals()):
13
+ from ...minichain.backends.impls.huggingface import repos as hf_repos
14
+ from . import catalog as _catalog
15
+ from . import meta as _meta
16
+ from . import types as _types
7
17
 
8
18
 
9
19
  ##
10
20
 
11
21
 
12
- def bind_strings_backends() -> inj.Elements:
22
+ def bind_backends(cfg: BackendConfig = BackendConfig()) -> inj.Elements:
13
23
  lst: list[inj.Elemental] = []
14
24
 
25
+ #
26
+
15
27
  lst.extend([
16
28
  inj.bind(mc.BackendStringBackendCatalog, singleton=True),
17
29
  inj.bind(mc.BackendCatalog, to_key=mc.BackendStringBackendCatalog),
18
30
  ])
19
31
 
20
- from ...minichain.backends.impls.huggingface.repos import HuggingfaceModelRepoResolver
21
-
22
32
  lst.extend([
23
- inj.bind(HuggingfaceModelRepoResolver, singleton=True),
24
- inj.bind(mc.ModelRepoResolver, to_key=HuggingfaceModelRepoResolver),
33
+ inj.bind(hf_repos.HuggingfaceModelRepoResolver, singleton=True),
34
+ inj.bind(mc.ModelRepoResolver, to_key=hf_repos.HuggingfaceModelRepoResolver),
25
35
 
26
36
  ])
27
37
 
28
- return inj.as_elements(*lst)
38
+ #
29
39
 
40
+ lst.append(backend_configs().bind_items_provider(singleton=True))
30
41
 
31
- def bind_simple_backends() -> inj.Elements:
32
- lst: list[inj.Elemental] = []
33
-
34
- lst.extend([
35
- inj.set_binder[mc.SimpleBackendCatalogEntry](),
36
- inj.bind(
37
- lang.typed_lambda(mc.SimpleBackendCatalogEntries, s=ta.AbstractSet[mc.SimpleBackendCatalogEntry])(
38
- lambda s: list(s),
39
- ),
40
- singleton=True,
41
- ),
42
- ])
43
-
44
- lst.extend([
45
- inj.bind(mc.SimpleBackendCatalog, singleton=True),
46
- inj.bind(mc.BackendCatalog, to_key=mc.SimpleBackendCatalog),
47
- ])
48
-
49
- from .standard import STANDARD_BACKEND_CATALOG_ENTRIES
50
-
51
- lst.extend([
52
- inj.bind_set_entry_const(ta.AbstractSet[mc.SimpleBackendCatalogEntry], e)
53
- for e in STANDARD_BACKEND_CATALOG_ENTRIES
54
- ])
55
-
56
- return inj.as_elements(*lst)
57
-
58
-
59
- def bind_backends(
60
- *,
61
- enable_backend_strings: bool = False,
62
- ) -> inj.Elements:
63
- lst: list[inj.Elemental] = []
42
+ #
64
43
 
65
- if enable_backend_strings:
66
- lst.append(bind_strings_backends())
44
+ if cfg.backend is not None:
45
+ lst.append(inj.bind(_types.BackendName, to_const=cfg.backend))
67
46
  else:
68
- lst.append(bind_simple_backends())
47
+ lst.append(inj.bind(_types.BackendName, to_fn=inj.target(dbn=_types.DefaultBackendName)(lambda dbn: dbn)))
48
+
49
+ backend_provider_pairs: list = [
50
+ (_types.ChatChoicesServiceBackendProvider, _catalog.CatalogChatChoicesServiceBackendProvider),
51
+ (_types.ChatChoicesStreamServiceBackendProvider, _catalog.CatalogChatChoicesStreamServiceBackendProvider),
52
+ (_types.CompletionServiceBackendProvider, _catalog.CatalogCompletionServiceBackendProvider),
53
+ (_types.EmbeddingServiceBackendProvider, _catalog.CatalogEmbeddingServiceBackendProvider),
54
+ ]
55
+
56
+ for bp_iface, bp_impl in backend_provider_pairs:
57
+ bp_stack = inj.wrapper_binder_helper(bp_iface)
58
+
59
+ if bp_iface is _types.ChatChoicesServiceBackendProvider:
60
+ fiw_ben_lst: list[str] = [
61
+ # 'openai',
62
+ # 'anthropic',
63
+ # 'groq',
64
+ # 'cerebras',
65
+ ]
66
+
67
+ if fiw_ben_lst:
68
+ for ben in fiw_ben_lst:
69
+ ben_bp_key: inj.Key = inj.Key(bp_impl, tag=ben)
70
+ lst.extend([
71
+ inj.private(
72
+ inj.bind(_types.BackendName, to_const=ben),
73
+ inj.bind(ben_bp_key, to_ctor=bp_impl, singleton=True, expose=True),
74
+ inj.bind(bp_iface, to_key=ben_bp_key),
75
+ ),
76
+ bp_stack.push_bind(to_key=ben_bp_key),
77
+ ])
78
+
79
+ fiw_key: inj.Key = inj.Key(_meta.FirstInWinsBackendProvider, tag=bp_iface)
80
+ lst.extend([
81
+ inj.private(
82
+ inj.set_binder[_types.BackendProvider]().bind(bp_stack.top),
83
+ inj.bind(fiw_key, to_ctor=_meta.FirstInWinsBackendProvider, singleton=True, expose=True),
84
+ ),
85
+ bp_stack.push_bind(to_key=fiw_key),
86
+ ])
87
+
88
+ else:
89
+ lst.append(bp_stack.push_bind(to_ctor=bp_impl, singleton=True))
90
+
91
+ else:
92
+ lst.append(bp_stack.push_bind(to_ctor=bp_impl, singleton=True))
93
+
94
+ if bp_iface is _types.ChatChoicesServiceBackendProvider:
95
+ rt_key: inj.Key = inj.Key(_meta.RetryBackendProvider, tag=bp_iface)
96
+ lst.extend([
97
+ inj.private(
98
+ inj.bind(_types.BackendProvider, to_key=bp_stack.top),
99
+ inj.bind(rt_key, to_ctor=_meta.RetryBackendProvider, singleton=True, expose=True),
100
+ ),
101
+ bp_stack.push_bind(to_key=rt_key),
102
+ ])
103
+
104
+ elif bp_iface is _types.ChatChoicesStreamServiceBackendProvider:
105
+ rts_key: inj.Key = inj.Key(_meta.RetryStreamBackendProvider, tag=bp_iface)
106
+ lst.extend([
107
+ inj.private(
108
+ inj.bind(_types.BackendProvider, to_key=bp_stack.top),
109
+ inj.bind(rts_key, to_ctor=_meta.RetryStreamBackendProvider, singleton=True, expose=True),
110
+ ),
111
+ bp_stack.push_bind(to_key=rts_key),
112
+ ])
113
+
114
+ lst.append(inj.bind(bp_iface, to_key=bp_stack.top))
115
+
116
+ #
117
+
118
+ async def catalog_backend_instantiator_provider(injector: inj.AsyncInjector) -> _catalog.CatalogBackendProvider.Instantiator: # noqa
119
+ async def inner(be: 'mc.BackendCatalog.Backend', cfgs: _types.BackendConfigs | None) -> ta.Any:
120
+ kwt = inj.build_kwargs_target(be.factory, non_strict=True)
121
+ kw = await injector.provide_kwargs(kwt)
122
+ return be.factory(*tv.collect(*(be.configs or []), *(cfgs or []), override=True), **kw)
123
+
124
+ return _catalog.CatalogBackendProvider.Instantiator(inner)
125
+
126
+ lst.append(inj.bind(_catalog.CatalogBackendProvider.Instantiator, to_async_fn=catalog_backend_instantiator_provider)) # noqa
69
127
 
70
128
  return inj.as_elements(*lst)
@@ -1,7 +1,7 @@
1
1
  from omlish import inject as inj
2
2
  from omlish import lang
3
3
 
4
- from ..... import minichain as mc
4
+ from ... import minichain as mc
5
5
 
6
6
 
7
7
  with lang.auto_proxy_import(globals()):
@@ -0,0 +1,82 @@
1
+ import contextlib
2
+ import typing as ta
3
+
4
+ from ... import minichain as mc
5
+ from .types import BackendProvider
6
+
7
+
8
+ ServiceT = ta.TypeVar('ServiceT', bound=mc.Service)
9
+ StreamServiceT = ta.TypeVar('StreamServiceT', bound=mc.Service)
10
+
11
+
12
+ ##
13
+
14
+
15
+ class FirstInWinsBackendProvider(BackendProvider[ServiceT]):
16
+ def __init__(
17
+ self,
18
+ backend_providers: ta.AbstractSet[BackendProvider],
19
+ ) -> None:
20
+ super().__init__()
21
+
22
+ self._backend_providers = [ta.cast(BackendProvider[ServiceT], bp) for bp in backend_providers]
23
+
24
+ def provide_backend(self) -> ta.AsyncContextManager[ServiceT]:
25
+ @contextlib.asynccontextmanager
26
+ async def inner():
27
+ from ...minichain.wrappers.firstinwins import AsyncioFirstInWinsService
28
+
29
+ async with contextlib.AsyncExitStack() as aes:
30
+ svcs = [
31
+ await aes.enter_async_context(bp.provide_backend())
32
+ for bp in self._backend_providers
33
+ ]
34
+ yield AsyncioFirstInWinsService(*svcs)
35
+
36
+ return inner()
37
+
38
+
39
+ ##
40
+
41
+
42
+ class RetryBackendProvider(BackendProvider):
43
+ def __init__(
44
+ self,
45
+ backend_provider: BackendProvider,
46
+ ) -> None:
47
+ super().__init__()
48
+
49
+ self._backend_provider = backend_provider
50
+
51
+ def provide_backend(self) -> ta.AsyncContextManager:
52
+ @contextlib.asynccontextmanager
53
+ async def inner():
54
+ async with contextlib.AsyncExitStack() as aes:
55
+ yield mc.RetryService(
56
+ await aes.enter_async_context(self._backend_provider.provide_backend()),
57
+ )
58
+
59
+ return inner()
60
+
61
+
62
+ ##
63
+
64
+
65
+ class RetryStreamBackendProvider(BackendProvider):
66
+ def __init__(
67
+ self,
68
+ backend_provider: BackendProvider,
69
+ ) -> None:
70
+ super().__init__()
71
+
72
+ self._backend_provider = backend_provider
73
+
74
+ def provide_backend(self) -> ta.AsyncContextManager:
75
+ @contextlib.asynccontextmanager
76
+ async def inner():
77
+ async with contextlib.AsyncExitStack() as aes:
78
+ yield mc.RetryStreamService(
79
+ await aes.enter_async_context(self._backend_provider.provide_backend()),
80
+ )
81
+
82
+ return inner()
@@ -3,7 +3,7 @@ import typing as ta
3
3
 
4
4
  from omlish import lang
5
5
 
6
- from ..... import minichain as mc
6
+ from ... import minichain as mc
7
7
 
8
8
 
9
9
  ServiceT = ta.TypeVar('ServiceT', bound=mc.Service)
@@ -13,6 +13,8 @@ ServiceT = ta.TypeVar('ServiceT', bound=mc.Service)
13
13
 
14
14
 
15
15
  BackendName = ta.NewType('BackendName', str)
16
+ DefaultBackendName = ta.NewType('DefaultBackendName', str)
17
+
16
18
  BackendConfigs = ta.NewType('BackendConfigs', ta.Sequence['mc.Config'])
17
19
 
18
20
 
@@ -34,3 +36,11 @@ class ChatChoicesServiceBackendProvider(BackendProvider['mc.ChatChoicesService']
34
36
 
35
37
  class ChatChoicesStreamServiceBackendProvider(BackendProvider['mc.ChatChoicesStreamService'], lang.Abstract):
36
38
  pass
39
+
40
+
41
+ class CompletionServiceBackendProvider(BackendProvider['mc.CompletionService'], lang.Abstract):
42
+ pass
43
+
44
+
45
+ class EmbeddingServiceBackendProvider(BackendProvider['mc.EmbeddingService'], lang.Abstract):
46
+ pass
@@ -4,7 +4,7 @@ import typing as ta
4
4
  from omlish import check
5
5
  from omlish import lang
6
6
 
7
- from ..... import minichain as mc
7
+ from ... import minichain as mc
8
8
 
9
9
 
10
10
  ##
@@ -19,7 +19,7 @@ class MessageContentExtractor(lang.Abstract):
19
19
  class MessageContentExtractorImpl(MessageContentExtractor):
20
20
  def extract_message_content(self, message: 'mc.Message') -> ta.Optional['mc.Content']:
21
21
  if isinstance(message, (mc.SystemMessage, mc.UserMessage, mc.AiMessage)):
22
- if message.c is not None:
22
+ if message.c:
23
23
  return check.isinstance(message.c, str)
24
24
  else:
25
25
  return None
@@ -4,7 +4,7 @@ import typing as ta
4
4
  from omlish import lang
5
5
  from omlish.formats import json
6
6
 
7
- from ..... import minichain as mc
7
+ from ... import minichain as mc
8
8
 
9
9
 
10
10
  ##
ommlds/cli/inject.py CHANGED
@@ -1,11 +1,12 @@
1
- import typing as ta
2
-
3
1
  from omlish import inject as inj
4
2
  from omlish import lang
3
+ from omlish import lifecycles as lc
4
+
5
+ from .sessions.configs import SessionConfig
5
6
 
6
7
 
7
8
  with lang.auto_proxy_import(globals()):
8
- from .backends import inject as _backends
9
+ from . import asyncs
9
10
  from .sessions import inject as _sessions
10
11
  from .state import inject as _state
11
12
 
@@ -15,18 +16,20 @@ with lang.auto_proxy_import(globals()):
15
16
 
16
17
  def bind_main(
17
18
  *,
18
- session_cfg: ta.Any,
19
- enable_backend_strings: bool = False,
19
+ session_cfg: SessionConfig,
20
20
  ) -> inj.Elements:
21
21
  els: list[inj.Elemental] = []
22
22
 
23
23
  #
24
24
 
25
25
  els.extend([
26
- _backends.bind_backends(
27
- enable_backend_strings=enable_backend_strings,
28
- ),
26
+ lc.bind_async_lifecycle_registrar(),
27
+ lc.bind_async_managed_lifecycle_manager(eager=True),
28
+ ])
29
29
 
30
+ #
31
+
32
+ els.extend([
30
33
  _sessions.bind_sessions(session_cfg),
31
34
 
32
35
  _state.bind_state(),
@@ -34,4 +37,10 @@ def bind_main(
34
37
 
35
38
  #
36
39
 
40
+ els.extend([
41
+ inj.bind(asyncs.AsyncThreadRunner, to_ctor=asyncs.AnyioAsyncThreadRunner),
42
+ ])
43
+
44
+ #
45
+
37
46
  return inj.as_elements(*els)
@@ -0,0 +1,32 @@
1
+ import typing as ta
2
+
3
+ from .. import asyncs
4
+ from .sync import SyncStringInput
5
+
6
+
7
+ ##
8
+
9
+
10
+ class AsyncStringInput(ta.Protocol):
11
+ def __call__(self) -> ta.Awaitable[str]: ...
12
+
13
+
14
+ class ThreadAsyncStringInput:
15
+ def __init__(self, child: SyncStringInput, runner: asyncs.AsyncThreadRunner) -> None:
16
+ super().__init__()
17
+
18
+ self._child = child
19
+ self._runner = runner
20
+
21
+ async def __call__(self) -> str:
22
+ return await self._runner.run_in_thread(self._child)
23
+
24
+
25
+ class SyncAsyncStringInput:
26
+ def __init__(self, child: SyncStringInput) -> None:
27
+ super().__init__()
28
+
29
+ self._child = child
30
+
31
+ async def __call__(self) -> str:
32
+ return self._child()
@@ -0,0 +1,75 @@
1
+ import sys
2
+ import typing as ta
3
+
4
+ from omlish import check
5
+ from omlish import lang
6
+
7
+
8
+ with lang.auto_proxy_import(globals()):
9
+ from omlish.subprocesses import editor
10
+ from omlish.subprocesses import sync as sync_subprocesses
11
+
12
+
13
+ ##
14
+
15
+
16
+ class SyncStringInput(ta.Protocol):
17
+ def __call__(self) -> str: ...
18
+
19
+
20
+ class InputSyncStringInput:
21
+ DEFAULT_PROMPT: ta.ClassVar[str] = '> '
22
+
23
+ def __init__(
24
+ self,
25
+ prompt: str | None = None,
26
+ *,
27
+ use_readline: bool | ta.Literal['auto'] = False,
28
+ ) -> None:
29
+ super().__init__()
30
+
31
+ if prompt is None:
32
+ prompt = self.DEFAULT_PROMPT
33
+ self._prompt = prompt
34
+ self._use_readline = use_readline
35
+
36
+ self._handled_readline = False
37
+
38
+ def _handle_readline(self) -> None:
39
+ if self._handled_readline:
40
+ return
41
+ self._handled_readline = True
42
+
43
+ if not self._use_readline:
44
+ return
45
+
46
+ if self._use_readline == 'auto':
47
+ if not sys.stdin.isatty():
48
+ return
49
+
50
+ try:
51
+ import readline # noqa
52
+ except ImportError:
53
+ pass
54
+
55
+ def __call__(self) -> str:
56
+ self._handle_readline()
57
+ return input(self._prompt)
58
+
59
+
60
+ class FileSyncStringInput(InputSyncStringInput):
61
+ def __init__(self, path: str) -> None:
62
+ super().__init__()
63
+
64
+ self._path = check.non_empty_str(path)
65
+
66
+ def __call__(self) -> str:
67
+ with open(self._path) as f:
68
+ return f.read()
69
+
70
+
71
+ class UserEditorSyncStringInput(InputSyncStringInput):
72
+ def __call__(self) -> str:
73
+ if (ec := editor.edit_text_with_user_editor('', sync_subprocesses.subprocesses)) is None:
74
+ raise EOFError
75
+ return ec