ommlds 0.0.0.dev436__py3-none-any.whl → 0.0.0.dev480__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 (271) hide show
  1. ommlds/.omlish-manifests.json +332 -35
  2. ommlds/__about__.py +15 -9
  3. ommlds/_hacks/__init__.py +4 -0
  4. ommlds/_hacks/funcs.py +110 -0
  5. ommlds/_hacks/names.py +158 -0
  6. ommlds/_hacks/params.py +73 -0
  7. ommlds/_hacks/patches.py +0 -3
  8. ommlds/backends/anthropic/protocol/_marshal.py +2 -2
  9. ommlds/backends/anthropic/protocol/sse/_marshal.py +1 -1
  10. ommlds/backends/anthropic/protocol/sse/assemble.py +23 -7
  11. ommlds/backends/anthropic/protocol/sse/events.py +13 -0
  12. ommlds/backends/anthropic/protocol/types.py +30 -9
  13. ommlds/backends/google/protocol/__init__.py +3 -0
  14. ommlds/backends/google/protocol/_marshal.py +16 -0
  15. ommlds/backends/google/protocol/types.py +626 -0
  16. ommlds/backends/groq/_marshal.py +23 -0
  17. ommlds/backends/groq/protocol.py +249 -0
  18. ommlds/backends/mlx/generation.py +1 -1
  19. ommlds/backends/mlx/loading.py +58 -1
  20. ommlds/backends/ollama/__init__.py +0 -0
  21. ommlds/backends/ollama/protocol.py +170 -0
  22. ommlds/backends/openai/protocol/__init__.py +9 -28
  23. ommlds/backends/openai/protocol/_common.py +18 -0
  24. ommlds/backends/openai/protocol/_marshal.py +27 -0
  25. ommlds/backends/openai/protocol/chatcompletion/chunk.py +58 -31
  26. ommlds/backends/openai/protocol/chatcompletion/contentpart.py +49 -44
  27. ommlds/backends/openai/protocol/chatcompletion/message.py +55 -43
  28. ommlds/backends/openai/protocol/chatcompletion/request.py +114 -66
  29. ommlds/backends/openai/protocol/chatcompletion/response.py +71 -45
  30. ommlds/backends/openai/protocol/chatcompletion/responseformat.py +27 -20
  31. ommlds/backends/openai/protocol/chatcompletion/tokenlogprob.py +16 -7
  32. ommlds/backends/openai/protocol/completionusage.py +24 -15
  33. ommlds/backends/tavily/__init__.py +0 -0
  34. ommlds/backends/tavily/protocol.py +301 -0
  35. ommlds/backends/tinygrad/models/llama3/__init__.py +22 -14
  36. ommlds/backends/transformers/__init__.py +0 -0
  37. ommlds/backends/transformers/filecache.py +109 -0
  38. ommlds/backends/transformers/streamers.py +73 -0
  39. ommlds/cli/asyncs.py +30 -0
  40. ommlds/cli/backends/catalog.py +93 -0
  41. ommlds/cli/backends/configs.py +9 -0
  42. ommlds/cli/backends/inject.py +31 -36
  43. ommlds/cli/backends/injection.py +16 -0
  44. ommlds/cli/backends/types.py +46 -0
  45. ommlds/cli/content/__init__.py +0 -0
  46. ommlds/cli/content/messages.py +34 -0
  47. ommlds/cli/content/strings.py +42 -0
  48. ommlds/cli/inject.py +15 -32
  49. ommlds/cli/inputs/__init__.py +0 -0
  50. ommlds/cli/inputs/asyncs.py +32 -0
  51. ommlds/cli/inputs/sync.py +75 -0
  52. ommlds/cli/main.py +270 -110
  53. ommlds/cli/rendering/__init__.py +0 -0
  54. ommlds/cli/rendering/configs.py +9 -0
  55. ommlds/cli/rendering/inject.py +31 -0
  56. ommlds/cli/rendering/markdown.py +52 -0
  57. ommlds/cli/rendering/raw.py +73 -0
  58. ommlds/cli/rendering/types.py +21 -0
  59. ommlds/cli/secrets.py +21 -0
  60. ommlds/cli/sessions/base.py +1 -1
  61. ommlds/cli/sessions/chat/chat/__init__.py +0 -0
  62. ommlds/cli/sessions/chat/chat/ai/__init__.py +0 -0
  63. ommlds/cli/sessions/chat/chat/ai/configs.py +11 -0
  64. ommlds/cli/sessions/chat/chat/ai/inject.py +74 -0
  65. ommlds/cli/sessions/chat/chat/ai/injection.py +14 -0
  66. ommlds/cli/sessions/chat/chat/ai/rendering.py +70 -0
  67. ommlds/cli/sessions/chat/chat/ai/services.py +79 -0
  68. ommlds/cli/sessions/chat/chat/ai/tools.py +44 -0
  69. ommlds/cli/sessions/chat/chat/ai/types.py +28 -0
  70. ommlds/cli/sessions/chat/chat/state/__init__.py +0 -0
  71. ommlds/cli/sessions/chat/chat/state/configs.py +11 -0
  72. ommlds/cli/sessions/chat/chat/state/inject.py +36 -0
  73. ommlds/cli/sessions/chat/chat/state/inmemory.py +33 -0
  74. ommlds/cli/sessions/chat/chat/state/storage.py +52 -0
  75. ommlds/cli/sessions/chat/chat/state/types.py +38 -0
  76. ommlds/cli/sessions/chat/chat/user/__init__.py +0 -0
  77. ommlds/cli/sessions/chat/chat/user/configs.py +17 -0
  78. ommlds/cli/sessions/chat/chat/user/inject.py +62 -0
  79. ommlds/cli/sessions/chat/chat/user/interactive.py +31 -0
  80. ommlds/cli/sessions/chat/chat/user/oneshot.py +25 -0
  81. ommlds/cli/sessions/chat/chat/user/types.py +15 -0
  82. ommlds/cli/sessions/chat/configs.py +27 -0
  83. ommlds/cli/sessions/chat/driver.py +43 -0
  84. ommlds/cli/sessions/chat/inject.py +33 -65
  85. ommlds/cli/sessions/chat/phases/__init__.py +0 -0
  86. ommlds/cli/sessions/chat/phases/inject.py +27 -0
  87. ommlds/cli/sessions/chat/phases/injection.py +14 -0
  88. ommlds/cli/sessions/chat/phases/manager.py +29 -0
  89. ommlds/cli/sessions/chat/phases/types.py +29 -0
  90. ommlds/cli/sessions/chat/session.py +27 -0
  91. ommlds/cli/sessions/chat/tools/__init__.py +0 -0
  92. ommlds/cli/sessions/chat/tools/configs.py +22 -0
  93. ommlds/cli/sessions/chat/tools/confirmation.py +46 -0
  94. ommlds/cli/sessions/chat/tools/execution.py +66 -0
  95. ommlds/cli/sessions/chat/tools/fs/__init__.py +0 -0
  96. ommlds/cli/sessions/chat/tools/fs/configs.py +12 -0
  97. ommlds/cli/sessions/chat/tools/fs/inject.py +35 -0
  98. ommlds/cli/sessions/chat/tools/inject.py +88 -0
  99. ommlds/cli/sessions/chat/tools/injection.py +44 -0
  100. ommlds/cli/sessions/chat/tools/rendering.py +58 -0
  101. ommlds/cli/sessions/chat/tools/todo/__init__.py +0 -0
  102. ommlds/cli/sessions/chat/tools/todo/configs.py +12 -0
  103. ommlds/cli/sessions/chat/tools/todo/inject.py +31 -0
  104. ommlds/cli/sessions/chat/tools/weather/__init__.py +0 -0
  105. ommlds/cli/sessions/chat/tools/weather/configs.py +12 -0
  106. ommlds/cli/sessions/chat/tools/weather/inject.py +22 -0
  107. ommlds/cli/{tools/weather.py → sessions/chat/tools/weather/tools.py} +1 -1
  108. ommlds/cli/sessions/completion/configs.py +21 -0
  109. ommlds/cli/sessions/completion/inject.py +42 -0
  110. ommlds/cli/sessions/completion/session.py +35 -0
  111. ommlds/cli/sessions/embedding/configs.py +21 -0
  112. ommlds/cli/sessions/embedding/inject.py +42 -0
  113. ommlds/cli/sessions/embedding/session.py +33 -0
  114. ommlds/cli/sessions/inject.py +28 -11
  115. ommlds/cli/state/__init__.py +0 -0
  116. ommlds/cli/state/inject.py +28 -0
  117. ommlds/cli/{state.py → state/storage.py} +41 -24
  118. ommlds/minichain/__init__.py +84 -24
  119. ommlds/minichain/_marshal.py +49 -9
  120. ommlds/minichain/_typedvalues.py +2 -4
  121. ommlds/minichain/backends/catalogs/base.py +20 -1
  122. ommlds/minichain/backends/catalogs/simple.py +2 -2
  123. ommlds/minichain/backends/catalogs/strings.py +10 -8
  124. ommlds/minichain/backends/impls/anthropic/chat.py +65 -27
  125. ommlds/minichain/backends/impls/anthropic/names.py +10 -8
  126. ommlds/minichain/backends/impls/anthropic/protocol.py +109 -0
  127. ommlds/minichain/backends/impls/anthropic/stream.py +111 -43
  128. ommlds/minichain/backends/impls/duckduckgo/search.py +1 -1
  129. ommlds/minichain/backends/impls/dummy/__init__.py +0 -0
  130. ommlds/minichain/backends/impls/dummy/chat.py +69 -0
  131. ommlds/minichain/backends/impls/google/chat.py +114 -22
  132. ommlds/minichain/backends/impls/google/search.py +7 -2
  133. ommlds/minichain/backends/impls/google/stream.py +219 -0
  134. ommlds/minichain/backends/impls/google/tools.py +149 -0
  135. ommlds/minichain/backends/impls/groq/__init__.py +0 -0
  136. ommlds/minichain/backends/impls/groq/chat.py +75 -0
  137. ommlds/minichain/backends/impls/groq/names.py +48 -0
  138. ommlds/minichain/backends/impls/groq/protocol.py +143 -0
  139. ommlds/minichain/backends/impls/groq/stream.py +125 -0
  140. ommlds/minichain/backends/impls/llamacpp/chat.py +33 -18
  141. ommlds/minichain/backends/impls/llamacpp/completion.py +1 -1
  142. ommlds/minichain/backends/impls/llamacpp/format.py +4 -2
  143. ommlds/minichain/backends/impls/llamacpp/stream.py +37 -20
  144. ommlds/minichain/backends/impls/mistral.py +20 -5
  145. ommlds/minichain/backends/impls/mlx/chat.py +96 -22
  146. ommlds/minichain/backends/impls/ollama/__init__.py +0 -0
  147. ommlds/minichain/backends/impls/ollama/chat.py +199 -0
  148. ommlds/minichain/backends/impls/openai/chat.py +18 -8
  149. ommlds/minichain/backends/impls/openai/completion.py +10 -3
  150. ommlds/minichain/backends/impls/openai/embedding.py +10 -3
  151. ommlds/minichain/backends/impls/openai/format.py +131 -106
  152. ommlds/minichain/backends/impls/openai/names.py +31 -5
  153. ommlds/minichain/backends/impls/openai/stream.py +43 -25
  154. ommlds/minichain/backends/impls/tavily.py +66 -0
  155. ommlds/minichain/backends/impls/tinygrad/chat.py +23 -16
  156. ommlds/minichain/backends/impls/transformers/sentence.py +1 -1
  157. ommlds/minichain/backends/impls/transformers/tokens.py +1 -1
  158. ommlds/minichain/backends/impls/transformers/transformers.py +155 -34
  159. ommlds/minichain/backends/strings/parsing.py +1 -1
  160. ommlds/minichain/backends/strings/resolving.py +4 -1
  161. ommlds/minichain/chat/_marshal.py +16 -9
  162. ommlds/minichain/chat/choices/adapters.py +4 -4
  163. ommlds/minichain/chat/choices/services.py +1 -1
  164. ommlds/minichain/chat/choices/stream/__init__.py +0 -0
  165. ommlds/minichain/chat/choices/stream/adapters.py +35 -0
  166. ommlds/minichain/chat/choices/stream/joining.py +31 -0
  167. ommlds/minichain/chat/choices/stream/services.py +45 -0
  168. ommlds/minichain/chat/choices/stream/types.py +43 -0
  169. ommlds/minichain/chat/choices/types.py +2 -2
  170. ommlds/minichain/chat/history.py +3 -3
  171. ommlds/minichain/chat/messages.py +55 -19
  172. ommlds/minichain/chat/services.py +3 -3
  173. ommlds/minichain/chat/stream/_marshal.py +16 -0
  174. ommlds/minichain/chat/stream/joining.py +85 -0
  175. ommlds/minichain/chat/stream/services.py +15 -21
  176. ommlds/minichain/chat/stream/types.py +32 -19
  177. ommlds/minichain/chat/tools/execution.py +8 -7
  178. ommlds/minichain/chat/tools/ids.py +9 -15
  179. ommlds/minichain/chat/tools/parsing.py +17 -26
  180. ommlds/minichain/chat/transforms/base.py +29 -38
  181. ommlds/minichain/chat/transforms/metadata.py +30 -4
  182. ommlds/minichain/chat/transforms/services.py +9 -11
  183. ommlds/minichain/content/_marshal.py +44 -20
  184. ommlds/minichain/content/json.py +13 -0
  185. ommlds/minichain/content/materialize.py +14 -21
  186. ommlds/minichain/content/prepare.py +4 -0
  187. ommlds/minichain/content/transforms/interleave.py +1 -1
  188. ommlds/minichain/content/transforms/squeeze.py +1 -1
  189. ommlds/minichain/content/transforms/stringify.py +1 -1
  190. ommlds/minichain/json.py +20 -0
  191. ommlds/minichain/lib/code/__init__.py +0 -0
  192. ommlds/minichain/lib/code/prompts.py +6 -0
  193. ommlds/minichain/lib/fs/binfiles.py +108 -0
  194. ommlds/minichain/lib/fs/context.py +126 -0
  195. ommlds/minichain/lib/fs/errors.py +101 -0
  196. ommlds/minichain/lib/fs/suggestions.py +36 -0
  197. ommlds/minichain/lib/fs/tools/__init__.py +0 -0
  198. ommlds/minichain/lib/fs/tools/edit.py +104 -0
  199. ommlds/minichain/lib/fs/tools/ls.py +38 -0
  200. ommlds/minichain/lib/fs/tools/read.py +115 -0
  201. ommlds/minichain/lib/fs/tools/recursivels/__init__.py +0 -0
  202. ommlds/minichain/lib/fs/tools/recursivels/execution.py +40 -0
  203. ommlds/minichain/lib/todo/__init__.py +0 -0
  204. ommlds/minichain/lib/todo/context.py +54 -0
  205. ommlds/minichain/lib/todo/tools/__init__.py +0 -0
  206. ommlds/minichain/lib/todo/tools/read.py +44 -0
  207. ommlds/minichain/lib/todo/tools/write.py +335 -0
  208. ommlds/minichain/lib/todo/types.py +60 -0
  209. ommlds/minichain/llms/_marshal.py +25 -17
  210. ommlds/minichain/llms/types.py +4 -0
  211. ommlds/minichain/registries/globals.py +18 -4
  212. ommlds/minichain/resources.py +66 -43
  213. ommlds/minichain/search.py +1 -1
  214. ommlds/minichain/services/_marshal.py +46 -39
  215. ommlds/minichain/services/facades.py +3 -3
  216. ommlds/minichain/services/services.py +1 -1
  217. ommlds/minichain/standard.py +8 -0
  218. ommlds/minichain/stream/services.py +152 -38
  219. ommlds/minichain/stream/wrap.py +22 -24
  220. ommlds/minichain/tools/_marshal.py +1 -1
  221. ommlds/minichain/tools/execution/catalog.py +2 -1
  222. ommlds/minichain/tools/execution/context.py +34 -14
  223. ommlds/minichain/tools/execution/errors.py +15 -0
  224. ommlds/minichain/tools/execution/executors.py +8 -3
  225. ommlds/minichain/tools/execution/reflect.py +40 -5
  226. ommlds/minichain/tools/fns.py +46 -9
  227. ommlds/minichain/tools/jsonschema.py +14 -5
  228. ommlds/minichain/tools/reflect.py +54 -18
  229. ommlds/minichain/tools/types.py +33 -1
  230. ommlds/minichain/utils.py +27 -0
  231. ommlds/minichain/vectors/_marshal.py +11 -10
  232. ommlds/nanochat/LICENSE +21 -0
  233. ommlds/nanochat/__init__.py +0 -0
  234. ommlds/nanochat/rustbpe/LICENSE +21 -0
  235. ommlds/nanochat/tokenizers.py +406 -0
  236. ommlds/server/server.py +3 -3
  237. ommlds/specs/__init__.py +0 -0
  238. ommlds/specs/mcp/__init__.py +0 -0
  239. ommlds/specs/mcp/_marshal.py +23 -0
  240. ommlds/specs/mcp/protocol.py +266 -0
  241. ommlds/tools/git.py +27 -10
  242. ommlds/tools/ocr.py +8 -9
  243. ommlds/wiki/analyze.py +2 -2
  244. ommlds/wiki/text/mfh.py +1 -5
  245. ommlds/wiki/text/wtp.py +1 -3
  246. ommlds/wiki/utils/xml.py +5 -5
  247. {ommlds-0.0.0.dev436.dist-info → ommlds-0.0.0.dev480.dist-info}/METADATA +24 -21
  248. ommlds-0.0.0.dev480.dist-info/RECORD +427 -0
  249. ommlds/cli/backends/standard.py +0 -20
  250. ommlds/cli/sessions/chat/base.py +0 -42
  251. ommlds/cli/sessions/chat/interactive.py +0 -73
  252. ommlds/cli/sessions/chat/printing.py +0 -96
  253. ommlds/cli/sessions/chat/prompt.py +0 -143
  254. ommlds/cli/sessions/chat/state.py +0 -109
  255. ommlds/cli/sessions/chat/tools.py +0 -91
  256. ommlds/cli/sessions/completion/completion.py +0 -44
  257. ommlds/cli/sessions/embedding/embedding.py +0 -42
  258. ommlds/cli/tools/config.py +0 -13
  259. ommlds/cli/tools/inject.py +0 -64
  260. ommlds/minichain/chat/stream/adapters.py +0 -69
  261. ommlds/minichain/lib/fs/ls/execution.py +0 -32
  262. ommlds-0.0.0.dev436.dist-info/RECORD +0 -303
  263. /ommlds/{cli/tools → backends/google}/__init__.py +0 -0
  264. /ommlds/{minichain/lib/fs/ls → backends/groq}/__init__.py +0 -0
  265. /ommlds/{huggingface.py → backends/huggingface.py} +0 -0
  266. /ommlds/minichain/lib/fs/{ls → tools/recursivels}/rendering.py +0 -0
  267. /ommlds/minichain/lib/fs/{ls → tools/recursivels}/running.py +0 -0
  268. {ommlds-0.0.0.dev436.dist-info → ommlds-0.0.0.dev480.dist-info}/WHEEL +0 -0
  269. {ommlds-0.0.0.dev436.dist-info → ommlds-0.0.0.dev480.dist-info}/entry_points.txt +0 -0
  270. {ommlds-0.0.0.dev436.dist-info → ommlds-0.0.0.dev480.dist-info}/licenses/LICENSE +0 -0
  271. {ommlds-0.0.0.dev436.dist-info → ommlds-0.0.0.dev480.dist-info}/top_level.txt +0 -0
@@ -65,6 +65,33 @@ with _lang.auto_proxy_init(
65
65
 
66
66
  ##
67
67
 
68
+ from .chat.choices.stream.adapters import ( # noqa
69
+ ChatChoicesStreamServiceChatChoicesService,
70
+ )
71
+
72
+ from .chat.choices.stream.joining import ( # noqa
73
+ AiChoicesDeltaJoiner,
74
+ )
75
+
76
+ from .chat.choices.stream.services import ( # noqa
77
+ ChatChoicesStreamRequest,
78
+ ChatChoicesStreamResponse,
79
+ ChatChoicesStreamService,
80
+ AbstractChatChoicesStreamService,
81
+ static_check_is_chat_choices_stream_service,
82
+ )
83
+
84
+ from .chat.choices.stream.types import ( # noqa
85
+ ChatChoicesStreamOption,
86
+ ChatChoicesStreamOptions,
87
+
88
+ ChatChoicesStreamOutput,
89
+ ChatChoicesStreamOutputs,
90
+
91
+ AiChoiceDeltas,
92
+ AiChoicesDeltas,
93
+ )
94
+
68
95
  from .chat.choices.adapters import ( # noqa
69
96
  ChatChoicesServiceChatService,
70
97
  )
@@ -88,35 +115,31 @@ with _lang.auto_proxy_init(
88
115
  AiChoices,
89
116
  )
90
117
 
91
- from .chat.stream.adapters import ( # noqa
92
- ChatChoicesStreamServiceChatChoicesService,
118
+ from .chat.stream.joining import ( # noqa
119
+ AiDeltaJoiner,
93
120
  )
94
121
 
95
122
  from .chat.stream.services import ( # noqa
96
- ChatChoicesStreamRequest,
97
- ChatChoicesStreamResponse,
98
- ChatChoicesStreamService,
99
- AbstractChatChoicesStreamService,
100
- static_check_is_chat_choices_stream_service,
101
-
102
- ChatChoicesStreamGenerator,
123
+ ChatStreamRequest,
124
+ ChatStreamResponse,
125
+ ChatStreamService,
126
+ AbstractChatStreamService,
127
+ static_check_is_chat_stream_service,
103
128
  )
104
129
 
105
130
  from .chat.stream.types import ( # noqa
106
- ChatChoicesStreamOption,
107
- ChatChoicesStreamOptions,
131
+ AiDelta,
132
+ AiDeltas,
108
133
 
109
- ChatChoicesStreamOutput,
110
- ChatChoicesStreamOutputs,
134
+ ContentAiDelta,
111
135
 
112
- ToolExecRequestDelta,
113
- AiMessageDelta,
114
- AiChoiceDelta,
115
- AiChoiceDeltas,
136
+ AnyToolUseAiDelta,
137
+ ToolUseAiDelta,
138
+ PartialToolUseAiDelta,
116
139
  )
117
140
 
118
141
  from .chat.tools.execution import ( # noqa
119
- execute_tool_request,
142
+ execute_tool_use,
120
143
  )
121
144
 
122
145
  from .chat.transforms.base import ( # noqa
@@ -124,7 +147,6 @@ with _lang.auto_proxy_init(
124
147
  CompositeMessageTransform,
125
148
  FnMessageTransform,
126
149
  TypeFilteredMessageTransform,
127
- fn_message_transform,
128
150
 
129
151
  ChatTransform,
130
152
  CompositeChatTransform,
@@ -155,12 +177,22 @@ with _lang.auto_proxy_init(
155
177
  )
156
178
 
157
179
  from .chat.messages import ( # noqa
158
- AiMessage,
159
- Chat,
160
180
  Message,
181
+ Chat,
182
+
183
+ AnyUserMessage,
184
+ UserChat,
185
+ check_user_chat,
186
+
187
+ AnyAiMessage,
188
+ AiChat,
189
+ check_ai_chat,
190
+
161
191
  SystemMessage,
162
- ToolExecResultMessage,
163
192
  UserMessage,
193
+ AiMessage,
194
+ ToolUseMessage,
195
+ ToolUseResultMessage,
164
196
  )
165
197
 
166
198
  from .chat.services import ( # noqa
@@ -199,8 +231,14 @@ with _lang.auto_proxy_init(
199
231
  ImageContent,
200
232
  )
201
233
 
234
+ from .content.json import ( # noqa
235
+ JsonContent,
236
+ )
237
+
202
238
  from .content.materialize import ( # noqa
203
239
  CanContent,
240
+
241
+ materialize_content,
204
242
  )
205
243
 
206
244
  from .content.metadata import ( # noqa
@@ -270,6 +308,7 @@ with _lang.auto_proxy_init(
270
308
  TopK,
271
309
  Temperature,
272
310
  MaxTokens,
311
+ MaxCompletionTokens,
273
312
 
274
313
  LlmOutput,
275
314
 
@@ -301,6 +340,7 @@ with _lang.auto_proxy_init(
301
340
  ##
302
341
 
303
342
  from .registries.globals import ( # noqa
343
+ get_registry_cls,
304
344
  register_type,
305
345
  registry_new,
306
346
  registry_of,
@@ -322,7 +362,12 @@ with _lang.auto_proxy_init(
322
362
  StreamOption,
323
363
  StreamOptions,
324
364
 
325
- ResponseGenerator,
365
+ StreamResponseSink,
366
+ StreamResponseIterator,
367
+
368
+ StreamServiceCancelledError,
369
+ StreamServiceNotAwaitedError,
370
+
326
371
  StreamResponse,
327
372
  new_stream_response,
328
373
  )
@@ -358,6 +403,10 @@ with _lang.auto_proxy_init(
358
403
  reflect_tool_catalog_entry,
359
404
  )
360
405
 
406
+ from .tools.execution.errors import ( # noqa
407
+ ToolExecutionError,
408
+ )
409
+
361
410
  from .tools.fns import ( # noqa
362
411
  ToolFn,
363
412
 
@@ -394,7 +443,8 @@ with _lang.auto_proxy_init(
394
443
 
395
444
  ToolSpec,
396
445
 
397
- ToolExecRequest,
446
+ ToolUse,
447
+ ToolUseResult,
398
448
  )
399
449
 
400
450
  ##
@@ -486,6 +536,12 @@ with _lang.auto_proxy_init(
486
536
  EnvKey,
487
537
  )
488
538
 
539
+ from .json import ( # noqa
540
+ JsonSchema,
541
+
542
+ JsonValue,
543
+ )
544
+
489
545
  from .metadata import ( # noqa
490
546
  Metadata,
491
547
 
@@ -521,6 +577,10 @@ with _lang.auto_proxy_init(
521
577
  )
522
578
 
523
579
  from .standard import ( # noqa
580
+ Device,
581
+
582
+ ApiUrl,
583
+
524
584
  ApiKey,
525
585
 
526
586
  DefaultOptions,
@@ -1,27 +1,67 @@
1
+ import typing as ta
2
+
1
3
  from omlish import dataclasses as dc
4
+ from omlish import lang
2
5
  from omlish import marshal as msh
3
6
  from omlish import reflect as rfl
4
- from omlish.funcs import match as mfs
5
7
  from omlish.typedvalues.marshal import build_typed_values_marshaler
6
8
  from omlish.typedvalues.marshal import build_typed_values_unmarshaler
7
9
 
10
+ from .json import JsonValue
11
+
8
12
 
9
13
  ##
10
14
 
11
15
 
12
16
  @dc.dataclass()
13
- class _TypedValuesFieldMarshalerFactory(msh.MarshalerFactoryMatchClass):
17
+ class _TypedValuesFieldMarshalerFactory(msh.MarshalerFactory):
14
18
  tvs_rty: rfl.Type
15
19
 
16
- @mfs.simple(lambda _, ctx, rty: True)
17
- def _build(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
18
- return build_typed_values_marshaler(ctx, self.tvs_rty)
20
+ def make_marshaler(self, ctx: msh.MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Marshaler] | None:
21
+ return lambda: build_typed_values_marshaler(ctx, self.tvs_rty)
19
22
 
20
23
 
21
24
  @dc.dataclass()
22
- class _TypedValuesFieldUnmarshalerFactory(msh.UnmarshalerFactoryMatchClass):
25
+ class _TypedValuesFieldUnmarshalerFactory(msh.UnmarshalerFactory):
23
26
  tvs_rty: rfl.Type
24
27
 
25
- @mfs.simple(lambda _, ctx, rty: True)
26
- def _build(self, ctx: msh.UnmarshalContext, rty: rfl.Type) -> msh.Unmarshaler:
27
- return build_typed_values_unmarshaler(ctx, self.tvs_rty)
28
+ def make_unmarshaler(self, ctx: msh.UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Unmarshaler] | None: # noqa
29
+ return lambda: build_typed_values_unmarshaler(ctx, self.tvs_rty)
30
+
31
+
32
+ ##
33
+
34
+
35
+ class MarshalJsonValue(lang.NotInstantiable, lang.Final):
36
+ pass
37
+
38
+
39
+ class _JsonValueMarshalerFactory(msh.MarshalerFactory):
40
+ def make_marshaler(self, ctx: msh.MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Marshaler] | None:
41
+ if rty is not MarshalJsonValue:
42
+ return None
43
+ return lambda: msh.NopMarshalerUnmarshaler()
44
+
45
+
46
+ class _JsonValueUnmarshalerFactory(msh.UnmarshalerFactory):
47
+ def make_unmarshaler(self, ctx: msh.UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Unmarshaler] | None: # noqa
48
+ if rty is not MarshalJsonValue:
49
+ return None
50
+ return lambda: msh.NopMarshalerUnmarshaler()
51
+
52
+
53
+ ##
54
+
55
+
56
+ @lang.static_init
57
+ def _install_standard_marshaling() -> None:
58
+ msh.register_global_config(
59
+ JsonValue,
60
+ msh.ReflectOverride(MarshalJsonValue),
61
+ identity=True,
62
+ )
63
+
64
+ msh.install_standard_factories(
65
+ _JsonValueMarshalerFactory(),
66
+ _JsonValueUnmarshalerFactory(),
67
+ )
@@ -74,12 +74,10 @@ def _tv_field_metadata(
74
74
  omit_if=operator.not_,
75
75
  ),
76
76
  marshaler_factory=msh.FuncMarshalerFactory(
77
- lambda ctx, rty: True,
78
- lambda ctx, rty: _marshal._TypedValuesFieldMarshalerFactory(tvs_rty)(ctx, rty), # noqa
77
+ lambda ctx, rty: _marshal._TypedValuesFieldMarshalerFactory(tvs_rty).make_marshaler(ctx, rty), # noqa
79
78
  ),
80
79
  unmarshaler_factory=msh.FuncUnmarshalerFactory(
81
- lambda ctx, rty: True,
82
- lambda ctx, rty: _marshal._TypedValuesFieldUnmarshalerFactory(tvs_rty)(ctx, rty), # noqa
80
+ lambda ctx, rty: _marshal._TypedValuesFieldUnmarshalerFactory(tvs_rty).make_unmarshaler(ctx, rty), # noqa
83
81
  ),
84
82
  ),
85
83
  }
@@ -3,15 +3,34 @@ import typing as ta
3
3
 
4
4
  from omlish import lang
5
5
 
6
+ from ...configs import Config
7
+
8
+
9
+ T = ta.TypeVar('T')
10
+
6
11
 
7
12
  ##
8
13
 
9
14
 
10
15
  class BackendCatalog(lang.Abstract):
16
+ class Backend(ta.NamedTuple):
17
+ factory: ta.Callable[..., ta.Any]
18
+ configs: ta.Sequence[Config] | None
19
+
11
20
  @abc.abstractmethod
12
- def get_backend(self, service_cls: ta.Any, name: str, *args: ta.Any, **kwargs: ta.Any) -> ta.Any:
21
+ def get_backend(self, service_cls: type[T], name: str) -> Backend:
13
22
  raise NotImplementedError
14
23
 
24
+ def new_backend(
25
+ self,
26
+ service_cls: ta.Any,
27
+ name: str,
28
+ *args: ta.Any,
29
+ **kwargs: ta.Any,
30
+ ) -> ta.Any:
31
+ be = self.get_backend(service_cls, name)
32
+ return be.factory(*be.configs or [], *args, **kwargs)
33
+
15
34
  # #
16
35
  #
17
36
  # class Bound(lang.Final, ta.Generic[T]):
@@ -40,9 +40,9 @@ class SimpleBackendCatalog(BackendCatalog):
40
40
  sc_dct[e.name] = e
41
41
  self._dct = dct
42
42
 
43
- def get_backend(self, service_cls: ta.Any, name: str, *args: ta.Any, **kwargs: ta.Any) -> ta.Any:
43
+ def get_backend(self, service_cls: ta.Any, name: str, *args: ta.Any, **kwargs: ta.Any) -> BackendCatalog.Backend:
44
44
  e = self._dct[service_cls][name]
45
- return e.factory_fn(*args, **kwargs)
45
+ return BackendCatalog.Backend(e.factory_fn, None)
46
46
 
47
47
 
48
48
  ##
@@ -5,7 +5,7 @@ from omlish import check
5
5
  from ...models.configs import ModelPath
6
6
  from ...models.configs import ModelRepo
7
7
  from ...models.repos.resolving import ModelRepoResolver
8
- from ...registries.globals import registry_new
8
+ from ...registries.globals import get_registry_cls
9
9
  from ..strings.parsing import parse_backend_string
10
10
  from ..strings.resolving import BackendStringResolver
11
11
  from ..strings.resolving import ResolveBackendStringArgs
@@ -30,26 +30,28 @@ class BackendStringBackendCatalog(BackendCatalog):
30
30
  self._string_resolver = string_resolver
31
31
  self._model_repo_resolver = model_repo_resolver
32
32
 
33
- def get_backend(self, service_cls: ta.Any, name: str, *args: ta.Any, **kwargs: ta.Any) -> ta.Any:
33
+ def get_backend(self, service_cls: ta.Any, name: str, *args: ta.Any, **kwargs: ta.Any) -> BackendCatalog.Backend:
34
34
  ps = parse_backend_string(name)
35
35
  rs = check.not_none(self._string_resolver.resolve_backend_string(ResolveBackendStringArgs(
36
36
  service_cls,
37
37
  ps,
38
38
  )))
39
39
 
40
- al = list(rs.args or [])
40
+ al: list = list(rs.args or [])
41
41
 
42
- # FIXME: lol
42
+ # FIXME: lol - move *into* local model classes as an injected dep?
43
43
  if al and isinstance(al[0], ModelRepo):
44
44
  [mr] = al
45
45
  mrr = check.not_none(self._model_repo_resolver)
46
46
  mrp = check.not_none(mrr.resolve(mr))
47
47
  al = [ModelPath(mrp.path), *al[1:]]
48
48
 
49
- return registry_new(
49
+ cls = get_registry_cls(
50
50
  service_cls,
51
51
  rs.name,
52
- *al,
53
- *args,
54
- **kwargs,
52
+ )
53
+
54
+ return BackendCatalog.Backend(
55
+ cls,
56
+ al,
55
57
  )
@@ -1,4 +1,5 @@
1
1
  """
2
+ https://docs.claude.com/en/api/messages
2
3
  https://github.com/anthropics/anthropic-sdk-python/tree/cd80d46f7a223a5493565d155da31b898a4c6ee5/src/anthropic/types
3
4
  https://github.com/anthropics/anthropic-sdk-python/blob/cd80d46f7a223a5493565d155da31b898a4c6ee5/src/anthropic/resources/completions.py#L53
4
5
  https://github.com/anthropics/anthropic-sdk-python/blob/cd80d46f7a223a5493565d155da31b898a4c6ee5/src/anthropic/resources/messages.py#L70
@@ -6,22 +7,33 @@ https://github.com/anthropics/anthropic-sdk-python/blob/cd80d46f7a223a5493565d15
6
7
  import typing as ta
7
8
 
8
9
  from omlish import check
9
- from omlish import lang
10
+ from omlish import marshal as msh
10
11
  from omlish import typedvalues as tv
11
12
  from omlish.formats import json
12
13
  from omlish.http import all as http
13
14
 
15
+ from .....backends.anthropic.protocol import types as pt
14
16
  from ....chat.choices.services import ChatChoicesRequest
15
17
  from ....chat.choices.services import ChatChoicesResponse
16
18
  from ....chat.choices.services import static_check_is_chat_choices_service
17
19
  from ....chat.choices.types import AiChoice
20
+ from ....chat.choices.types import ChatChoicesOptions
18
21
  from ....chat.messages import AiMessage
22
+ from ....chat.messages import AnyAiMessage
19
23
  from ....chat.messages import Message
20
24
  from ....chat.messages import SystemMessage
25
+ from ....chat.messages import ToolUseMessage
21
26
  from ....chat.messages import UserMessage
27
+ from ....chat.tools.types import Tool
28
+ from ....llms.types import MaxTokens
29
+ from ....llms.types import Temperature
22
30
  from ....models.configs import ModelName
23
31
  from ....standard import ApiKey
32
+ from ....tools.types import ToolUse
33
+ from ....types import Option
24
34
  from .names import MODEL_NAMES
35
+ from .protocol import build_protocol_chat_messages
36
+ from .protocol import build_protocol_tool
25
37
 
26
38
 
27
39
  ##
@@ -35,18 +47,15 @@ from .names import MODEL_NAMES
35
47
  class AnthropicChatChoicesService:
36
48
  DEFAULT_MODEL_NAME: ta.ClassVar[ModelName] = ModelName(check.not_none(MODEL_NAMES.default))
37
49
 
38
- ROLES_MAP: ta.ClassVar[ta.Mapping[type[Message], str]] = {
39
- SystemMessage: 'system',
40
- UserMessage: 'user',
41
- AiMessage: 'assistant',
42
- }
43
-
44
50
  def __init__(
45
51
  self,
46
52
  *configs: ApiKey | ModelName,
53
+ http_client: http.AsyncHttpClient | None = None,
47
54
  ) -> None:
48
55
  super().__init__()
49
56
 
57
+ self._http_client = http_client
58
+
50
59
  with tv.consume(*configs) as cc:
51
60
  self._api_key = check.not_none(ApiKey.pop_secret(cc, env='ANTHROPIC_API_KEY'))
52
61
  self._model_name = cc.pop(self.DEFAULT_MODEL_NAME)
@@ -62,33 +71,46 @@ class AnthropicChatChoicesService:
62
71
  else:
63
72
  raise TypeError(m)
64
73
 
65
- def invoke(
74
+ DEFAULT_OPTIONS: ta.ClassVar[tv.TypedValues[Option]] = tv.TypedValues[Option](
75
+ MaxTokens(4096),
76
+ )
77
+
78
+ _OPTION_KWARG_NAMES_MAP: ta.ClassVar[ta.Mapping[str, type[ChatChoicesOptions]]] = dict(
79
+ temperature=Temperature,
80
+ max_tokens=MaxTokens,
81
+ )
82
+
83
+ async def invoke(
66
84
  self,
67
85
  request: ChatChoicesRequest,
68
- *,
69
- max_tokens: int = 4096, # FIXME: ChatOption
70
86
  ) -> ChatChoicesResponse:
71
- messages = []
72
- system: str | None = None
73
- for i, m in enumerate(request.v):
74
- if isinstance(m, SystemMessage):
75
- if i != 0 or system is not None:
76
- raise Exception('Only supports one system message and must be first')
77
- system = self._get_msg_content(m)
78
- else:
79
- messages.append(dict(
80
- role=self.ROLES_MAP[type(m)], # noqa
81
- content=check.isinstance(self._get_msg_content(m), str),
82
- ))
87
+ messages, system = build_protocol_chat_messages(request.v)
88
+
89
+ kwargs: dict = dict()
83
90
 
84
- raw_request = dict(
91
+ tools: list[pt.ToolSpec] = []
92
+ with tv.TypedValues(
93
+ *self.DEFAULT_OPTIONS,
94
+ *request.options,
95
+ override=True,
96
+ ).consume() as oc:
97
+ kwargs.update(oc.pop_scalar_kwargs(**self._OPTION_KWARG_NAMES_MAP))
98
+
99
+ t: Tool
100
+ for t in oc.pop(Tool, []):
101
+ tools.append(build_protocol_tool(t))
102
+
103
+ a_req = pt.MessagesRequest(
85
104
  model=MODEL_NAMES.resolve(self._model_name.v),
86
- **lang.opt_kw(system=system),
105
+ system=system,
87
106
  messages=messages,
88
- max_tokens=max_tokens,
107
+ tools=tools or None,
108
+ **kwargs,
89
109
  )
90
110
 
91
- raw_response = http.request(
111
+ raw_request = msh.marshal(a_req)
112
+
113
+ raw_response = await http.async_request(
92
114
  'https://api.anthropic.com/v1/messages',
93
115
  headers={
94
116
  http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
@@ -96,10 +118,26 @@ class AnthropicChatChoicesService:
96
118
  b'anthropic-version': b'2023-06-01',
97
119
  },
98
120
  data=json.dumps(raw_request).encode('utf-8'),
121
+ client=self._http_client,
99
122
  )
100
123
 
101
124
  response = json.loads(check.not_none(raw_response.data).decode('utf-8'))
102
125
 
126
+ out: list[AnyAiMessage] = []
127
+ for c in response['content']:
128
+ if c['type'] == 'text':
129
+ out.append(AiMessage(
130
+ check.not_none(c['text']),
131
+ ))
132
+ elif c['type'] == 'tool_use':
133
+ out.append(ToolUseMessage(ToolUse(
134
+ id=c['id'],
135
+ name=c['name'],
136
+ args=c['input'],
137
+ )))
138
+ else:
139
+ raise TypeError(c['type'])
140
+
103
141
  return ChatChoicesResponse([
104
- AiChoice(AiMessage(response['content'][0]['text'])), # noqa
142
+ AiChoice(out),
105
143
  ])
@@ -18,14 +18,13 @@ MODEL_NAMES = ModelNameCollection(
18
18
  'claude-opus-4-1': 'claude-opus-4-1-20250805',
19
19
  'claude-opus': 'claude-opus-4-1',
20
20
 
21
- 'claude-sonnet-4-20250514': None,
22
- 'claude-sonnet-4': 'claude-sonnet-4-20250514',
23
- 'claude-sonnet': 'claude-sonnet-4',
21
+ 'claude-sonnet-4-5-20250929': None,
22
+ 'claude-sonnet-4-5': 'claude-sonnet-4-5-20250929',
23
+ 'claude-sonnet': 'claude-sonnet-4-5',
24
24
 
25
- 'claude-3-5-haiku-latest': None,
26
- 'claude-haiku-3-5-latest': 'claude-3-5-haiku-latest',
27
- 'claude-haiku-3-5': 'claude-haiku-3-5-latest',
28
- 'claude-haiku': 'claude-haiku-3-5',
25
+ 'claude-haiku-4-5-20251001': None,
26
+ 'claude-haiku-4-5': 'claude-haiku-4-5-20251001',
27
+ 'claude-haiku': 'claude-haiku-4-5',
29
28
 
30
29
  'claude': 'claude-haiku',
31
30
  },
@@ -34,7 +33,10 @@ MODEL_NAMES = ModelNameCollection(
34
33
 
35
34
  # @omlish-manifest
36
35
  _BACKEND_STRINGS_MANIFEST = BackendStringsManifest(
37
- ['ChatChoicesService'],
36
+ [
37
+ 'ChatChoicesService',
38
+ 'ChatChoicesStreamService',
39
+ ],
38
40
  'anthropic',
39
41
  model_names=MODEL_NAMES,
40
42
  )
@@ -0,0 +1,109 @@
1
+ import typing as ta
2
+
3
+ from omlish import check
4
+ from omlish import marshal as msh
5
+ from omlish.formats import json
6
+
7
+ from .....backends.anthropic.protocol import types as pt
8
+ from ....chat.messages import AiMessage
9
+ from ....chat.messages import Message
10
+ from ....chat.messages import SystemMessage
11
+ from ....chat.messages import ToolUseMessage
12
+ from ....chat.messages import ToolUseResultMessage
13
+ from ....chat.messages import UserMessage
14
+ from ....chat.tools.types import Tool
15
+ from ....content.prepare import prepare_content_str
16
+ from ....tools.jsonschema import build_tool_spec_params_json_schema
17
+
18
+
19
+ ##
20
+
21
+
22
+ def get_message_content(m: Message) -> str | None:
23
+ if isinstance(m, AiMessage):
24
+ return check.isinstance(m.c, str)
25
+
26
+ elif isinstance(m, (UserMessage, SystemMessage)):
27
+ return check.isinstance(m.c, str)
28
+
29
+ else:
30
+ raise TypeError(m)
31
+
32
+
33
+ #
34
+
35
+
36
+ class BuiltChatMessages(ta.NamedTuple):
37
+ messages: list[pt.Message]
38
+ system: list[pt.Content] | None
39
+
40
+
41
+ ROLES_MAP: ta.Mapping[type[Message], str] = {
42
+ SystemMessage: 'system',
43
+ UserMessage: 'user',
44
+ AiMessage: 'assistant',
45
+ ToolUseMessage: 'assistant',
46
+ }
47
+
48
+
49
+ def build_protocol_chat_messages(msgs: ta.Iterable[Message]) -> BuiltChatMessages:
50
+ messages: list[pt.Message] = []
51
+ system: list[pt.Content] | None = None
52
+
53
+ for i, m in enumerate(msgs):
54
+ if isinstance(m, SystemMessage):
55
+ if i or system is not None:
56
+ raise Exception('Only supports one system message and must be first')
57
+ system = [pt.Text(check.not_none(get_message_content(m)))]
58
+
59
+ elif isinstance(m, ToolUseResultMessage):
60
+ messages.append(pt.Message(
61
+ role='user',
62
+ content=[pt.ToolResult(
63
+ tool_use_id=check.not_none(m.tur.id),
64
+ content=json.dumps_compact(msh.marshal(m.tur.c)) if not isinstance(m.tur.c, str) else m.tur.c,
65
+ )],
66
+ ))
67
+
68
+ elif isinstance(m, AiMessage):
69
+ # messages.append(pt.Message(
70
+ # role=ROLES_MAP[type(m)], # noqa
71
+ # content=[pt.Text(check.isinstance(get_message_content(m), str))],
72
+ # ))
73
+ messages.append(pt.Message(
74
+ role='assistant',
75
+ content=[
76
+ *([pt.Text(check.isinstance(m.c, str))] if m.c is not None else []),
77
+ ],
78
+ ))
79
+
80
+ elif isinstance(m, ToolUseMessage):
81
+ messages.append(pt.Message(
82
+ role='assistant',
83
+ content=[
84
+ pt.ToolUse(
85
+ id=check.not_none(m.tu.id),
86
+ name=check.not_none(m.tu.name),
87
+ input=m.tu.args,
88
+ ),
89
+ ],
90
+ ))
91
+
92
+ else:
93
+ messages.append(pt.Message(
94
+ role=ROLES_MAP[type(m)], # type: ignore[arg-type]
95
+ content=[pt.Text(check.isinstance(get_message_content(m), str))],
96
+ ))
97
+
98
+ return BuiltChatMessages(messages, system)
99
+
100
+
101
+ ##
102
+
103
+
104
+ def build_protocol_tool(t: Tool) -> pt.ToolSpec:
105
+ return pt.ToolSpec(
106
+ name=check.not_none(t.spec.name),
107
+ description=prepare_content_str(t.spec.desc),
108
+ input_schema=build_tool_spec_params_json_schema(t.spec),
109
+ )