ommlds 0.0.0.dev480__py3-none-any.whl → 0.0.0.dev503__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 (277) hide show
  1. ommlds/.omlish-manifests.json +100 -33
  2. ommlds/README.md +11 -0
  3. ommlds/__about__.py +9 -6
  4. ommlds/backends/anthropic/protocol/__init__.py +13 -1
  5. ommlds/backends/anthropic/protocol/_dataclasses.py +1625 -0
  6. ommlds/backends/anthropic/protocol/sse/events.py +2 -0
  7. ommlds/backends/cerebras/__init__.py +7 -0
  8. ommlds/backends/cerebras/_dataclasses.py +4254 -0
  9. ommlds/backends/cerebras/_marshal.py +24 -0
  10. ommlds/backends/cerebras/protocol.py +312 -0
  11. ommlds/backends/google/protocol/__init__.py +13 -0
  12. ommlds/backends/google/protocol/_dataclasses.py +5997 -0
  13. ommlds/backends/groq/__init__.py +7 -0
  14. ommlds/backends/groq/_dataclasses.py +3901 -0
  15. ommlds/backends/groq/clients.py +9 -0
  16. ommlds/backends/llamacpp/logging.py +4 -1
  17. ommlds/backends/mlx/caching.py +7 -3
  18. ommlds/backends/mlx/cli.py +10 -7
  19. ommlds/backends/mlx/generation.py +18 -16
  20. ommlds/backends/mlx/limits.py +10 -6
  21. ommlds/backends/mlx/loading.py +7 -4
  22. ommlds/backends/ollama/__init__.py +7 -0
  23. ommlds/backends/ollama/_dataclasses.py +3488 -0
  24. ommlds/backends/ollama/protocol.py +3 -0
  25. ommlds/backends/openai/protocol/__init__.py +15 -1
  26. ommlds/backends/openai/protocol/_dataclasses.py +7708 -0
  27. ommlds/backends/tavily/__init__.py +7 -0
  28. ommlds/backends/tavily/_dataclasses.py +1734 -0
  29. ommlds/backends/transformers/__init__.py +14 -0
  30. ommlds/cli/__init__.py +7 -0
  31. ommlds/cli/_dataclasses.py +3515 -0
  32. ommlds/cli/backends/catalog.py +0 -5
  33. ommlds/cli/backends/inject.py +70 -7
  34. ommlds/cli/backends/meta.py +82 -0
  35. ommlds/cli/content/messages.py +1 -1
  36. ommlds/cli/inject.py +11 -3
  37. ommlds/cli/main.py +137 -68
  38. ommlds/cli/rendering/types.py +6 -0
  39. ommlds/cli/secrets.py +2 -1
  40. ommlds/cli/sessions/base.py +1 -10
  41. ommlds/cli/sessions/chat/configs.py +9 -17
  42. ommlds/cli/sessions/chat/{chat → drivers}/ai/configs.py +3 -1
  43. ommlds/cli/sessions/chat/drivers/ai/events.py +57 -0
  44. ommlds/cli/sessions/chat/{chat → drivers}/ai/inject.py +10 -3
  45. ommlds/cli/sessions/chat/{chat → drivers}/ai/rendering.py +1 -1
  46. ommlds/cli/sessions/chat/{chat → drivers}/ai/services.py +1 -1
  47. ommlds/cli/sessions/chat/{chat → drivers}/ai/tools.py +4 -8
  48. ommlds/cli/sessions/chat/{chat → drivers}/ai/types.py +9 -0
  49. ommlds/cli/sessions/chat/drivers/configs.py +25 -0
  50. ommlds/cli/sessions/chat/drivers/events/inject.py +27 -0
  51. ommlds/cli/sessions/chat/drivers/events/injection.py +14 -0
  52. ommlds/cli/sessions/chat/drivers/events/manager.py +16 -0
  53. ommlds/cli/sessions/chat/drivers/events/types.py +38 -0
  54. ommlds/cli/sessions/chat/drivers/impl.py +50 -0
  55. ommlds/cli/sessions/chat/drivers/inject.py +70 -0
  56. ommlds/cli/sessions/chat/{chat → drivers}/state/configs.py +2 -0
  57. ommlds/cli/sessions/chat/drivers/state/ids.py +25 -0
  58. ommlds/cli/sessions/chat/drivers/state/inject.py +83 -0
  59. ommlds/cli/sessions/chat/{chat → drivers}/state/inmemory.py +0 -4
  60. ommlds/cli/sessions/chat/{chat → drivers}/state/storage.py +17 -10
  61. ommlds/cli/sessions/chat/{chat → drivers}/state/types.py +10 -5
  62. ommlds/cli/sessions/chat/{tools → drivers/tools}/configs.py +2 -2
  63. ommlds/cli/sessions/chat/drivers/tools/confirmation.py +44 -0
  64. ommlds/cli/sessions/chat/drivers/tools/errorhandling.py +39 -0
  65. ommlds/cli/sessions/chat/{tools → drivers/tools}/execution.py +3 -4
  66. ommlds/cli/sessions/chat/{tools → drivers/tools}/fs/inject.py +3 -3
  67. ommlds/cli/sessions/chat/{tools → drivers/tools}/inject.py +7 -12
  68. ommlds/cli/sessions/chat/{tools → drivers/tools}/injection.py +5 -5
  69. ommlds/cli/sessions/chat/{tools → drivers/tools}/rendering.py +3 -3
  70. ommlds/cli/sessions/chat/{tools → drivers/tools}/todo/inject.py +3 -3
  71. ommlds/cli/sessions/chat/{tools → drivers/tools}/weather/tools.py +1 -1
  72. ommlds/cli/sessions/chat/drivers/types.py +31 -0
  73. ommlds/cli/sessions/chat/{chat → drivers}/user/configs.py +0 -3
  74. ommlds/cli/sessions/chat/drivers/user/inject.py +41 -0
  75. ommlds/cli/sessions/chat/facades/__init__.py +0 -0
  76. ommlds/cli/sessions/chat/facades/commands/__init__.py +0 -0
  77. ommlds/cli/sessions/chat/facades/commands/base.py +83 -0
  78. ommlds/cli/sessions/chat/facades/commands/configs.py +9 -0
  79. ommlds/cli/sessions/chat/facades/commands/inject.py +41 -0
  80. ommlds/cli/sessions/chat/facades/commands/injection.py +15 -0
  81. ommlds/cli/sessions/chat/facades/commands/manager.py +59 -0
  82. ommlds/cli/sessions/chat/facades/commands/simple.py +34 -0
  83. ommlds/cli/sessions/chat/facades/commands/types.py +13 -0
  84. ommlds/cli/sessions/chat/facades/configs.py +11 -0
  85. ommlds/cli/sessions/chat/facades/facade.py +26 -0
  86. ommlds/cli/sessions/chat/facades/inject.py +35 -0
  87. ommlds/cli/sessions/chat/facades/ui.py +34 -0
  88. ommlds/cli/sessions/chat/inject.py +8 -31
  89. ommlds/cli/sessions/chat/interfaces/__init__.py +0 -0
  90. ommlds/cli/sessions/chat/interfaces/bare/__init__.py +0 -0
  91. ommlds/cli/sessions/chat/interfaces/bare/configs.py +15 -0
  92. ommlds/cli/sessions/chat/interfaces/bare/inject.py +69 -0
  93. ommlds/cli/sessions/chat/interfaces/bare/interactive.py +49 -0
  94. ommlds/cli/sessions/chat/interfaces/bare/oneshot.py +21 -0
  95. ommlds/cli/sessions/chat/{tools/confirmation.py → interfaces/bare/tools.py} +3 -22
  96. ommlds/cli/sessions/chat/interfaces/base.py +13 -0
  97. ommlds/cli/sessions/chat/interfaces/configs.py +11 -0
  98. ommlds/cli/sessions/chat/interfaces/inject.py +29 -0
  99. ommlds/cli/sessions/chat/interfaces/textual/__init__.py +0 -0
  100. ommlds/cli/sessions/chat/interfaces/textual/app.py +310 -0
  101. ommlds/cli/sessions/chat/interfaces/textual/configs.py +11 -0
  102. ommlds/cli/sessions/chat/interfaces/textual/facades.py +19 -0
  103. ommlds/cli/sessions/chat/interfaces/textual/inject.py +97 -0
  104. ommlds/cli/sessions/chat/interfaces/textual/interface.py +24 -0
  105. ommlds/cli/sessions/chat/interfaces/textual/styles/__init__.py +29 -0
  106. ommlds/cli/sessions/chat/interfaces/textual/styles/input.tcss +53 -0
  107. ommlds/cli/sessions/chat/interfaces/textual/styles/markdown.tcss +7 -0
  108. ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss +157 -0
  109. ommlds/cli/sessions/chat/interfaces/textual/tools.py +38 -0
  110. ommlds/cli/sessions/chat/interfaces/textual/widgets/__init__.py +0 -0
  111. ommlds/cli/sessions/chat/interfaces/textual/widgets/input.py +36 -0
  112. ommlds/cli/sessions/chat/interfaces/textual/widgets/messages.py +197 -0
  113. ommlds/cli/sessions/chat/session.py +8 -13
  114. ommlds/cli/sessions/completion/configs.py +3 -4
  115. ommlds/cli/sessions/completion/inject.py +1 -2
  116. ommlds/cli/sessions/completion/session.py +4 -8
  117. ommlds/cli/sessions/configs.py +10 -0
  118. ommlds/cli/sessions/embedding/configs.py +3 -4
  119. ommlds/cli/sessions/embedding/inject.py +1 -2
  120. ommlds/cli/sessions/embedding/session.py +4 -8
  121. ommlds/cli/sessions/inject.py +15 -15
  122. ommlds/cli/state/storage.py +7 -1
  123. ommlds/minichain/__init__.py +161 -38
  124. ommlds/minichain/_dataclasses.py +20452 -0
  125. ommlds/minichain/_typedvalues.py +11 -4
  126. ommlds/minichain/backends/impls/anthropic/names.py +3 -3
  127. ommlds/minichain/backends/impls/anthropic/protocol.py +2 -2
  128. ommlds/minichain/backends/impls/anthropic/stream.py +1 -1
  129. ommlds/minichain/backends/impls/cerebras/__init__.py +0 -0
  130. ommlds/minichain/backends/impls/cerebras/chat.py +80 -0
  131. ommlds/minichain/backends/impls/cerebras/names.py +45 -0
  132. ommlds/minichain/backends/impls/cerebras/protocol.py +143 -0
  133. ommlds/minichain/backends/impls/cerebras/stream.py +125 -0
  134. ommlds/minichain/backends/impls/duckduckgo/search.py +5 -1
  135. ommlds/minichain/backends/impls/google/names.py +6 -0
  136. ommlds/minichain/backends/impls/google/stream.py +1 -1
  137. ommlds/minichain/backends/impls/google/tools.py +2 -2
  138. ommlds/minichain/backends/impls/groq/chat.py +2 -0
  139. ommlds/minichain/backends/impls/groq/protocol.py +2 -2
  140. ommlds/minichain/backends/impls/groq/stream.py +3 -1
  141. ommlds/minichain/backends/impls/huggingface/repos.py +1 -5
  142. ommlds/minichain/backends/impls/llamacpp/chat.py +6 -3
  143. ommlds/minichain/backends/impls/llamacpp/completion.py +7 -3
  144. ommlds/minichain/backends/impls/llamacpp/stream.py +6 -3
  145. ommlds/minichain/backends/impls/mlx/chat.py +6 -3
  146. ommlds/minichain/backends/impls/ollama/chat.py +51 -57
  147. ommlds/minichain/backends/impls/ollama/protocol.py +144 -0
  148. ommlds/minichain/backends/impls/openai/format.py +4 -3
  149. ommlds/minichain/backends/impls/openai/names.py +3 -1
  150. ommlds/minichain/backends/impls/openai/stream.py +33 -1
  151. ommlds/minichain/backends/impls/sentencepiece/tokens.py +9 -6
  152. ommlds/minichain/backends/impls/tinygrad/chat.py +7 -4
  153. ommlds/minichain/backends/impls/tokenizers/tokens.py +9 -6
  154. ommlds/minichain/backends/impls/transformers/sentence.py +5 -2
  155. ommlds/minichain/backends/impls/transformers/tokens.py +9 -6
  156. ommlds/minichain/backends/impls/transformers/transformers.py +10 -8
  157. ommlds/minichain/backends/strings/resolving.py +1 -1
  158. ommlds/minichain/chat/content.py +42 -0
  159. ommlds/minichain/chat/messages.py +43 -39
  160. ommlds/minichain/chat/stream/joining.py +36 -12
  161. ommlds/minichain/chat/stream/types.py +1 -1
  162. ommlds/minichain/chat/templating.py +3 -3
  163. ommlds/minichain/content/__init__.py +19 -3
  164. ommlds/minichain/content/_marshal.py +181 -55
  165. ommlds/minichain/content/code.py +26 -0
  166. ommlds/minichain/content/composite.py +28 -0
  167. ommlds/minichain/content/content.py +27 -0
  168. ommlds/minichain/content/dynamic.py +12 -0
  169. ommlds/minichain/content/emphasis.py +27 -0
  170. ommlds/minichain/content/images.py +2 -2
  171. ommlds/minichain/content/json.py +2 -2
  172. ommlds/minichain/content/link.py +13 -0
  173. ommlds/minichain/content/markdown.py +12 -0
  174. ommlds/minichain/content/metadata.py +10 -0
  175. ommlds/minichain/content/namespaces.py +8 -0
  176. ommlds/minichain/content/placeholders.py +10 -9
  177. ommlds/minichain/content/quote.py +26 -0
  178. ommlds/minichain/content/raw.py +49 -0
  179. ommlds/minichain/content/recursive.py +12 -0
  180. ommlds/minichain/content/section.py +26 -0
  181. ommlds/minichain/content/sequence.py +17 -3
  182. ommlds/minichain/content/standard.py +32 -0
  183. ommlds/minichain/content/tag.py +28 -0
  184. ommlds/minichain/content/templates.py +13 -0
  185. ommlds/minichain/content/text.py +2 -2
  186. ommlds/minichain/content/transform/__init__.py +0 -0
  187. ommlds/minichain/content/transform/json.py +55 -0
  188. ommlds/minichain/content/transform/markdown.py +8 -0
  189. ommlds/minichain/content/transform/materialize.py +51 -0
  190. ommlds/minichain/content/transform/metadata.py +16 -0
  191. ommlds/minichain/content/{prepare.py → transform/prepare.py} +10 -15
  192. ommlds/minichain/content/transform/recursive.py +97 -0
  193. ommlds/minichain/content/transform/standard.py +43 -0
  194. ommlds/minichain/content/{transforms → transform}/stringify.py +1 -7
  195. ommlds/minichain/content/transform/strings.py +33 -0
  196. ommlds/minichain/content/transform/templates.py +25 -0
  197. ommlds/minichain/content/visitors.py +231 -0
  198. ommlds/minichain/lib/fs/tools/read.py +1 -1
  199. ommlds/minichain/lib/fs/tools/recursivels/rendering.py +1 -1
  200. ommlds/minichain/lib/fs/tools/recursivels/running.py +1 -1
  201. ommlds/minichain/lib/todo/tools/write.py +2 -1
  202. ommlds/minichain/lib/todo/types.py +1 -1
  203. ommlds/minichain/metadata.py +56 -2
  204. ommlds/minichain/resources.py +22 -1
  205. ommlds/minichain/services/README.md +154 -0
  206. ommlds/minichain/services/__init__.py +6 -2
  207. ommlds/minichain/services/_marshal.py +46 -10
  208. ommlds/minichain/services/_origclasses.py +11 -0
  209. ommlds/minichain/services/_typedvalues.py +8 -3
  210. ommlds/minichain/services/requests.py +73 -3
  211. ommlds/minichain/services/responses.py +73 -3
  212. ommlds/minichain/services/services.py +9 -0
  213. ommlds/minichain/stream/services.py +24 -1
  214. ommlds/minichain/text/applypatch.py +2 -1
  215. ommlds/minichain/text/toolparsing/llamacpp/types.py +1 -1
  216. ommlds/minichain/tokens/specials.py +1 -1
  217. ommlds/minichain/tools/execution/catalog.py +1 -1
  218. ommlds/minichain/tools/execution/errorhandling.py +36 -0
  219. ommlds/minichain/tools/execution/errors.py +2 -2
  220. ommlds/minichain/tools/execution/executors.py +1 -1
  221. ommlds/minichain/tools/fns.py +1 -1
  222. ommlds/minichain/tools/jsonschema.py +2 -2
  223. ommlds/minichain/tools/reflect.py +6 -6
  224. ommlds/minichain/tools/types.py +12 -15
  225. ommlds/minichain/vectors/_marshal.py +1 -1
  226. ommlds/minichain/vectors/embeddings.py +1 -1
  227. ommlds/minichain/wrappers/__init__.py +7 -0
  228. ommlds/minichain/wrappers/firstinwins.py +144 -0
  229. ommlds/minichain/wrappers/instrument.py +146 -0
  230. ommlds/minichain/wrappers/retry.py +168 -0
  231. ommlds/minichain/wrappers/services.py +98 -0
  232. ommlds/minichain/wrappers/stream.py +57 -0
  233. ommlds/nanochat/rustbpe/README.md +9 -0
  234. ommlds/nanochat/tokenizers.py +40 -6
  235. ommlds/specs/mcp/clients.py +146 -0
  236. ommlds/specs/mcp/protocol.py +123 -18
  237. ommlds/tools/git.py +82 -65
  238. {ommlds-0.0.0.dev480.dist-info → ommlds-0.0.0.dev503.dist-info}/METADATA +13 -11
  239. ommlds-0.0.0.dev503.dist-info/RECORD +520 -0
  240. ommlds/cli/sessions/chat/chat/state/inject.py +0 -36
  241. ommlds/cli/sessions/chat/chat/user/inject.py +0 -62
  242. ommlds/cli/sessions/chat/chat/user/interactive.py +0 -31
  243. ommlds/cli/sessions/chat/chat/user/oneshot.py +0 -25
  244. ommlds/cli/sessions/chat/chat/user/types.py +0 -15
  245. ommlds/cli/sessions/chat/driver.py +0 -43
  246. ommlds/minichain/content/materialize.py +0 -196
  247. ommlds/minichain/content/simple.py +0 -47
  248. ommlds/minichain/content/transforms/base.py +0 -46
  249. ommlds/minichain/content/transforms/interleave.py +0 -70
  250. ommlds/minichain/content/transforms/squeeze.py +0 -72
  251. ommlds/minichain/content/transforms/strings.py +0 -24
  252. ommlds/minichain/content/types.py +0 -43
  253. ommlds/minichain/stream/wrap.py +0 -62
  254. ommlds-0.0.0.dev480.dist-info/RECORD +0 -427
  255. /ommlds/cli/sessions/chat/{chat → drivers}/__init__.py +0 -0
  256. /ommlds/cli/sessions/chat/{chat → drivers}/ai/__init__.py +0 -0
  257. /ommlds/cli/sessions/chat/{chat → drivers}/ai/injection.py +0 -0
  258. /ommlds/cli/sessions/chat/{chat/state → drivers/events}/__init__.py +0 -0
  259. /ommlds/cli/sessions/chat/{chat/user → drivers/phases}/__init__.py +0 -0
  260. /ommlds/cli/sessions/chat/{phases → drivers/phases}/inject.py +0 -0
  261. /ommlds/cli/sessions/chat/{phases → drivers/phases}/injection.py +0 -0
  262. /ommlds/cli/sessions/chat/{phases → drivers/phases}/manager.py +0 -0
  263. /ommlds/cli/sessions/chat/{phases → drivers/phases}/types.py +0 -0
  264. /ommlds/cli/sessions/chat/{phases → drivers/state}/__init__.py +0 -0
  265. /ommlds/cli/sessions/chat/{tools → drivers/tools}/__init__.py +0 -0
  266. /ommlds/cli/sessions/chat/{tools → drivers/tools}/fs/__init__.py +0 -0
  267. /ommlds/cli/sessions/chat/{tools → drivers/tools}/fs/configs.py +0 -0
  268. /ommlds/cli/sessions/chat/{tools → drivers/tools}/todo/__init__.py +0 -0
  269. /ommlds/cli/sessions/chat/{tools → drivers/tools}/todo/configs.py +0 -0
  270. /ommlds/cli/sessions/chat/{tools → drivers/tools}/weather/__init__.py +0 -0
  271. /ommlds/cli/sessions/chat/{tools → drivers/tools}/weather/configs.py +0 -0
  272. /ommlds/cli/sessions/chat/{tools → drivers/tools}/weather/inject.py +0 -0
  273. /ommlds/{minichain/content/transforms → cli/sessions/chat/drivers/user}/__init__.py +0 -0
  274. {ommlds-0.0.0.dev480.dist-info → ommlds-0.0.0.dev503.dist-info}/WHEEL +0 -0
  275. {ommlds-0.0.0.dev480.dist-info → ommlds-0.0.0.dev503.dist-info}/entry_points.txt +0 -0
  276. {ommlds-0.0.0.dev480.dist-info → ommlds-0.0.0.dev503.dist-info}/licenses/LICENSE +0 -0
  277. {ommlds-0.0.0.dev480.dist-info → ommlds-0.0.0.dev503.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,231 @@
1
+ import collections.abc
2
+ import inspect
3
+ import typing as ta
4
+
5
+ from omlish import check
6
+ from omlish import lang
7
+
8
+ from .code import BlockCodeContent
9
+ from .code import CodeContent
10
+ from .code import InlineCodeContent
11
+ from .composite import CompositeContent
12
+ from .content import BaseContent
13
+ from .content import Content
14
+ from .dynamic import DynamicContent
15
+ from .emphasis import BoldContent
16
+ from .emphasis import BoldItalicContent
17
+ from .emphasis import EmphasisContent
18
+ from .emphasis import ItalicContent
19
+ from .images import ImageContent
20
+ from .json import JsonContent
21
+ from .link import LinkContent
22
+ from .markdown import MarkdownContent
23
+ from .namespaces import NamespaceContent
24
+ from .placeholders import PlaceholderContent
25
+ from .quote import QuoteContent
26
+ from .recursive import RecursiveContent
27
+ from .section import SectionContent
28
+ from .sequence import BlockContent
29
+ from .sequence import InlineContent
30
+ from .sequence import ItemListContent
31
+ from .sequence import SequenceContent
32
+ from .standard import StandardContent
33
+ from .tag import TagContent
34
+ from .templates import TemplateContent
35
+ from .text import TextContent
36
+
37
+
38
+ C = ta.TypeVar('C')
39
+ R = ta.TypeVar('R')
40
+
41
+
42
+ ##
43
+
44
+
45
+ class ContentVisitor(lang.Abstract, ta.Generic[C, R]):
46
+ _visit_method_map: ta.ClassVar[ta.Mapping[ta.Any, str]]
47
+
48
+ def visit(self, c: Content, ctx: C) -> R:
49
+ if isinstance(c, str):
50
+ return self.visit_str(c, ctx)
51
+
52
+ if isinstance(c, collections.abc.Sequence):
53
+ return self.visit_sequence(c, ctx)
54
+
55
+ try:
56
+ a = self._visit_method_map[type(c)]
57
+ except KeyError:
58
+ raise TypeError(c) from None
59
+
60
+ return getattr(self, a)(c, ctx)
61
+
62
+ ##
63
+ # per-type visit methods
64
+
65
+ def visit_content(self, c: Content, ctx: C) -> R:
66
+ raise TypeError(c)
67
+
68
+ ##
69
+ # non-BaseContent
70
+
71
+ def visit_str(self, c: str, ctx: C) -> R:
72
+ return self.visit_content(c, ctx)
73
+
74
+ def visit_sequence(self, c: ta.Sequence[Content], ctx: C) -> R:
75
+ return self.visit_content(c, ctx)
76
+
77
+ ##
78
+ # BaseContent
79
+
80
+ def visit_base_content(self, c: BaseContent, ctx: C) -> R:
81
+ return self.visit_content(c, ctx)
82
+
83
+ ##
84
+ # StandardContent
85
+
86
+ def visit_standard_content(self, c: StandardContent, ctx: C) -> R:
87
+ return self.visit_base_content(c, ctx)
88
+
89
+ ##
90
+ # leaf StandardContent
91
+
92
+ def visit_image_content(self, c: ImageContent, ctx: C) -> R:
93
+ return self.visit_standard_content(c, ctx)
94
+
95
+ def visit_json_content(self, c: JsonContent, ctx: C) -> R:
96
+ return self.visit_standard_content(c, ctx)
97
+
98
+ def visit_link_content(self, c: LinkContent, ctx: C) -> R:
99
+ return self.visit_standard_content(c, ctx)
100
+
101
+ def visit_markdown_content(self, c: MarkdownContent, ctx: C) -> R:
102
+ return self.visit_standard_content(c, ctx)
103
+
104
+ def visit_quote_content(self, c: QuoteContent, ctx: C) -> R:
105
+ return self.visit_standard_content(c, ctx)
106
+
107
+ def visit_text_content(self, c: TextContent, ctx: C) -> R:
108
+ return self.visit_standard_content(c, ctx)
109
+
110
+ ##
111
+ # CompositeContent
112
+
113
+ def visit_composite_content(self, c: CompositeContent, ctx: C) -> R:
114
+ return self.visit_standard_content(c, ctx)
115
+
116
+ def visit_section_content(self, c: SectionContent, ctx: C) -> R:
117
+ return self.visit_composite_content(c, ctx)
118
+
119
+ def visit_tag_content(self, c: TagContent, ctx: C) -> R:
120
+ return self.visit_composite_content(c, ctx)
121
+
122
+ ##
123
+ # CodeContent
124
+
125
+ def visit_code_content(self, c: CodeContent, ctx: C) -> R:
126
+ return self.visit_standard_content(c, ctx)
127
+
128
+ def visit_inline_code_content(self, c: InlineCodeContent, ctx: C) -> R:
129
+ return self.visit_code_content(c, ctx)
130
+
131
+ def visit_block_code_content(self, c: BlockCodeContent, ctx: C) -> R:
132
+ return self.visit_code_content(c, ctx)
133
+
134
+ ##
135
+ # DynamicContent
136
+
137
+ def visit_dynamic_content(self, c: DynamicContent, ctx: C) -> R:
138
+ return self.visit_standard_content(c, ctx)
139
+
140
+ def visit_recursive_content(self, c: RecursiveContent, ctx: C) -> R:
141
+ return self.visit_dynamic_content(c, ctx)
142
+
143
+ def visit_namespace_content(self, c: NamespaceContent, ctx: C) -> R:
144
+ return self.visit_recursive_content(c, ctx)
145
+
146
+ def visit_placeholder_content(self, c: PlaceholderContent, ctx: C) -> R:
147
+ return self.visit_recursive_content(c, ctx)
148
+
149
+ def visit_template_content(self, c: TemplateContent, ctx: C) -> R:
150
+ return self.visit_dynamic_content(c, ctx)
151
+
152
+ ##
153
+ # EmphasisContent
154
+
155
+ def visit_emphasis_content(self, c: EmphasisContent, ctx: C) -> R:
156
+ return self.visit_standard_content(c, ctx)
157
+
158
+ def visit_bold_content(self, c: BoldContent, ctx: C) -> R:
159
+ return self.visit_emphasis_content(c, ctx)
160
+
161
+ def visit_italic_content(self, c: ItalicContent, ctx: C) -> R:
162
+ return self.visit_emphasis_content(c, ctx)
163
+
164
+ def visit_bold_italic_content(self, c: BoldItalicContent, ctx: C) -> R:
165
+ return self.visit_emphasis_content(c, ctx)
166
+
167
+ ##
168
+ # SequenceContent
169
+
170
+ def visit_sequence_content(self, c: SequenceContent, ctx: C) -> R:
171
+ return self.visit_composite_content(c, ctx)
172
+
173
+ def visit_inline_content(self, c: InlineContent, ctx: C) -> R:
174
+ return self.visit_sequence_content(c, ctx)
175
+
176
+ def visit_block_content(self, c: BlockContent, ctx: C) -> R:
177
+ return self.visit_sequence_content(c, ctx)
178
+
179
+ def visit_item_list_content(self, c: ItemListContent, ctx: C) -> R:
180
+ return self.visit_sequence_content(c, ctx)
181
+
182
+
183
+ ContentVisitor._visit_method_map = { # noqa
184
+ list(inspect.signature(o).parameters.values())[1].annotation: a
185
+ for a, o in ContentVisitor.__dict__.items()
186
+ if a.startswith('visit_')
187
+ }
188
+
189
+
190
+ ##
191
+
192
+
193
+ class StandardContentVisitorTypeError(TypeError):
194
+ pass
195
+
196
+
197
+ class StandardContentVisitor(ContentVisitor[C, R], lang.Abstract):
198
+ def visit_str(self, c: str, ctx: C) -> R:
199
+ raise StandardContentVisitorTypeError(c)
200
+
201
+ def visit_sequence(self, c: ta.Sequence[Content], ctx: C) -> R:
202
+ raise StandardContentVisitorTypeError(c)
203
+
204
+
205
+ ##
206
+
207
+
208
+ class StaticContentVisitorTypeError(TypeError):
209
+ pass
210
+
211
+
212
+ class StaticContentVisitor(ContentVisitor[C, R], lang.Abstract):
213
+ def visit_dynamic_content(self, c: DynamicContent, ctx: C) -> R:
214
+ raise StaticContentVisitorTypeError(c)
215
+
216
+
217
+ ##
218
+
219
+
220
+ class ContentTransform(ContentVisitor[C, Content], lang.Abstract):
221
+ def visit_content(self, c: Content, ctx: C) -> Content:
222
+ return c
223
+
224
+ def visit_sequence(self, c: ta.Sequence[Content], ctx: C) -> Content:
225
+ return [self.visit(cc, ctx) for cc in c]
226
+
227
+ def visit_composite_content(self, c: CompositeContent, ctx: C) -> Content:
228
+ cc = c.child_content()
229
+ ncc = self.visit_sequence(cc, ctx)
230
+ nc = c.replace_child_content(check.isinstance(ncc, collections.abc.Sequence))
231
+ return super().visit_composite_content(nc, ctx)
@@ -27,7 +27,7 @@ MAX_LINE_LENGTH = 2_000
27
27
 
28
28
  @tool_spec_override(
29
29
  desc=f"""
30
- Reads a file from the local filesystem. You can access any file directly by using this tool.
30
+ Reads a file from the local filesystem. You can access any file directly by using this tool.
31
31
 
32
32
  Assume this tool is able to read all files on the machine. If the User provides a path to a file assume that
33
33
  path is valid. It is okay to read a file that does not exist; an error will be returned.
@@ -5,10 +5,10 @@ TODO:
5
5
  - any directory with unlisted children will be suffixed inline with '...'
6
6
  - absence of '...' indicates an empty directory
7
7
  """
8
- import dataclasses as dc
9
8
  import typing as ta
10
9
 
11
10
  from omlish import check
11
+ from omlish import dataclasses as dc
12
12
  from omlish import lang
13
13
 
14
14
  from .running import DirLsItem
@@ -1,8 +1,8 @@
1
- import dataclasses as dc
2
1
  import os.path
3
2
  import typing as ta
4
3
 
5
4
  from omlish import check
5
+ from omlish import dataclasses as dc
6
6
  from omlish import lang
7
7
 
8
8
 
@@ -8,6 +8,7 @@ from omlish import lang
8
8
  from omlish import marshal as msh
9
9
 
10
10
  from ....content.namespaces import ContentNamespace
11
+ from ....content.namespaces import NamespaceContent
11
12
  from ....tools.execution.catalog import ToolCatalogEntry
12
13
  from ....tools.execution.reflect import reflect_tool_catalog_entry
13
14
  from ....tools.reflect import tool_spec_override
@@ -311,7 +312,7 @@ class TodoWriteDescriptionChunks(ContentNamespace):
311
312
 
312
313
 
313
314
  @tool_spec_override(
314
- desc=TodoWriteDescriptionChunks,
315
+ desc=NamespaceContent(TodoWriteDescriptionChunks),
315
316
  )
316
317
  def execute_todo_write_tool(todo_items: ta.Sequence[TodoItem]) -> ta.Sequence[TodoItem]:
317
318
  if todo_items:
@@ -3,9 +3,9 @@ TODO:
3
3
  - enums lol
4
4
  - * with ToolParam-like desc metadata somehow *
5
5
  """
6
- import dataclasses as dc
7
6
  import typing as ta
8
7
 
8
+ from omlish import dataclasses as dc
9
9
  from omlish import lang
10
10
 
11
11
  from ...tools.reflect import tool_param_metadata
@@ -3,9 +3,13 @@ import datetime
3
3
  import typing as ta
4
4
  import uuid
5
5
 
6
+ from omlish import check
7
+ from omlish import dataclasses as dc
6
8
  from omlish import lang
7
9
  from omlish import typedvalues as tv
8
10
 
11
+ from ._typedvalues import _tv_field_metadata
12
+
9
13
 
10
14
  ##
11
15
 
@@ -21,9 +25,9 @@ MetadataT = ta.TypeVar('MetadataT', bound=Metadata)
21
25
 
22
26
 
23
27
  class MetadataContainer(
24
- tv.TypedValueGeneric[MetadataT],
25
28
  lang.Abstract,
26
29
  lang.PackageSealed,
30
+ ta.Generic[MetadataT],
27
31
  ):
28
32
  @property
29
33
  @abc.abstractmethod
@@ -31,13 +35,63 @@ class MetadataContainer(
31
35
  raise NotImplementedError
32
36
 
33
37
  @abc.abstractmethod
34
- def with_metadata(self, *mds: MetadataT, override: bool = False) -> ta.Self:
38
+ def with_metadata(
39
+ self,
40
+ *add: MetadataT,
41
+ discard: ta.Iterable[type] | None = None,
42
+ override: bool = False,
43
+ ) -> ta.Self:
35
44
  raise NotImplementedError
36
45
 
37
46
 
38
47
  ##
39
48
 
40
49
 
50
+ @dc.dataclass(frozen=True)
51
+ class MetadataContainerDataclass( # noqa
52
+ MetadataContainer[MetadataT],
53
+ lang.Abstract,
54
+ ):
55
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
56
+ super().__init_subclass__(**kwargs)
57
+
58
+ check.state(hasattr(cls, '_metadata'))
59
+
60
+ @staticmethod
61
+ def _configure_metadata_field(md_fld, md_cls):
62
+ dc.set_field_metadata(
63
+ check.isinstance(md_fld, dc.Field),
64
+ _tv_field_metadata(
65
+ check.not_none(md_cls),
66
+ marshal_name='metadata',
67
+ ),
68
+ )
69
+
70
+ @property
71
+ def metadata(self) -> tv.TypedValues[MetadataT]:
72
+ return check.isinstance(getattr(self, '_metadata'), tv.TypedValues)
73
+
74
+ def with_metadata(
75
+ self,
76
+ *add: MetadataT,
77
+ discard: ta.Iterable[type] | None = None,
78
+ override: bool = False,
79
+ ) -> ta.Self:
80
+ new = (old := self.metadata).update(
81
+ *add,
82
+ discard=discard,
83
+ override=override,
84
+ )
85
+
86
+ if new is old:
87
+ return self
88
+
89
+ return dc.replace(self, _metadata=new) # type: ignore[call-arg] # noqa
90
+
91
+
92
+ ##
93
+
94
+
41
95
  class CommonMetadata(Metadata, lang.Abstract):
42
96
  pass
43
97
 
@@ -33,6 +33,10 @@ class ResourcesRefNotRegisteredError(Exception):
33
33
 
34
34
  @ta.final
35
35
  class Resources(lang.Final, lang.NotPicklable):
36
+ """
37
+ Essentially a reference-tracked AsyncContextManager.
38
+ """
39
+
36
40
  def __init__(
37
41
  self,
38
42
  *,
@@ -80,10 +84,14 @@ class Resources(lang.Final, lang.NotPicklable):
80
84
  @contextlib.asynccontextmanager
81
85
  async def inner():
82
86
  init_ref = Resources._InitRef()
87
+
83
88
  res = Resources(init_ref=init_ref, **kwargs)
89
+
84
90
  await res.init()
91
+
85
92
  try:
86
93
  yield res
94
+
87
95
  finally:
88
96
  await res.remove_ref(init_ref)
89
97
 
@@ -94,6 +102,7 @@ class Resources(lang.Final, lang.NotPicklable):
94
102
  def add_ref(self, ref: ResourcesRef) -> None:
95
103
  check.isinstance(ref, ResourcesRef)
96
104
  check.state(not self._closed)
105
+
97
106
  self._refs.add(ref)
98
107
 
99
108
  def has_ref(self, ref: ResourcesRef) -> bool:
@@ -101,10 +110,13 @@ class Resources(lang.Final, lang.NotPicklable):
101
110
 
102
111
  async def remove_ref(self, ref: ResourcesRef) -> None:
103
112
  check.isinstance(ref, ResourcesRef)
113
+
104
114
  try:
105
115
  self._refs.remove(ref)
116
+
106
117
  except KeyError:
107
118
  raise ResourcesRefNotRegisteredError(ref) from None
119
+
108
120
  if not self._no_autoclose and not self._refs:
109
121
  await self.aclose()
110
122
 
@@ -112,10 +124,12 @@ class Resources(lang.Final, lang.NotPicklable):
112
124
 
113
125
  def enter_context(self, cm: ta.ContextManager[T]) -> T:
114
126
  check.state(not self._closed)
127
+
115
128
  return self._aes.enter_context(cm)
116
129
 
117
130
  async def enter_async_context(self, cm: ta.AsyncContextManager[T]) -> T:
118
131
  check.state(not self._closed)
132
+
119
133
  return await self._aes.enter_async_context(cm)
120
134
 
121
135
  #
@@ -150,7 +164,11 @@ class Resources(lang.Final, lang.NotPicklable):
150
164
  class ResourceManaged(ResourcesRef, lang.Final, lang.NotPicklable, ta.Generic[T]):
151
165
  """
152
166
  A class to 'handoff' a ref to a `Resources`, allowing the `Resources` to temporarily survive being passed from
153
- instantiation within a callee to being `__aenter__`'d in the caller.
167
+ instantiation within a callee.
168
+
169
+ This class wraps an arbitrary value, likely an object referencing resources managed by the `Resources`, which is
170
+ accessed by `__aenter__`'ing. However, as the point of this class is handoff of a `Resources`, not necessarily some
171
+ arbitrary value, the value needn't necessarily be related to the `Resources`, or may even be `None`.
154
172
 
155
173
  The ref to the `Resources` is allocated in the ctor, so the contract is that an instance of this must be immediately
156
174
  `__aenter__`'d before doing anything else with the return value of the call. Failure to do so leaks the `Resources`.
@@ -172,11 +190,13 @@ class ResourceManaged(ResourcesRef, lang.Final, lang.NotPicklable, ta.Generic[T]
172
190
  async def __aenter__(self) -> T:
173
191
  check.state(self.__state == 'new')
174
192
  self.__state = 'entered'
193
+
175
194
  return self.__v
176
195
 
177
196
  async def __aexit__(self, exc_type, exc_val, exc_tb):
178
197
  check.state(self.__state == 'entered')
179
198
  self.__state = 'exited'
199
+
180
200
  await self.__resources.remove_ref(self)
181
201
 
182
202
  def __del__(self) -> None:
@@ -203,6 +223,7 @@ class UseResources(tv.UniqueScalarTypedValue[Resources], ResourcesOption, lang.F
203
223
  if (ur := tv.as_collection(options).get(UseResources)) is not None:
204
224
  async with ResourceManaged(ur.v, ur.v) as rs:
205
225
  yield rs
226
+
206
227
  else:
207
228
  async with Resources.new() as rs:
208
229
  yield rs
@@ -0,0 +1,154 @@
1
+ The core service abstraction. In general, Services are intended to encapsulate non-trivial, resourceful, effectful
2
+ operations, which are likely to have various implementations, each having their own specific capabilities in addition
3
+ to their common interface, and where wrapping, adapting, and transforming them in a uniform manner is desirable.
4
+
5
+ For example:
6
+ - A ChatService is passed a Request with a Chat value and returns a Response with an AiChat value.
7
+ - A ChatChoicesService is passed a Request with a Chat and returns a Response with a list of AiChoices.
8
+ - A ChatChoicesServiceChatService is a simple adapter taking a ChatChoicesService which it will invoke with its given
9
+ Request, expect a single AiChoice value in that Response, and return that single AiChat as its Response - thus acting
10
+ as a ChatService.
11
+ - Thus, all chat backends that return choices can be adapted to code expecting a single chat as output.
12
+ - A ChatStreamService is passed a Request with a Chat value and returns a Response with a value from which AiDeltas
13
+ may be streamed.
14
+ - A ChatChoicesStreamService is passed a Request with a Chat value and returns a Response with a value from which
15
+ AiChoicesDeltas may be streamed.
16
+ - A ChatChoicesStreamServiceChatChoicesService is an adapter taking a ChatChoicesStreamService and aggregating the
17
+ AiChoicesDeltas into joined, non-delta AiChoices.
18
+ - This may then be wrapped in a ChatChoicesServiceChatService to act as a ChatService.
19
+ - In practice however there are usually dedicated streaming and non-streaming implementations if possible as
20
+ non-streaming will usually have less overhead.
21
+ - An OpenaiChatChoicesService can act as a ChatChoicesService, and will accept all generic ChatOptions, in addition to
22
+ any OpenaiChatOptions inapplicable to any other backend. It may also produce all generic ChatOutputs, in addition to
23
+ OpenaiChatOutputs that will not be produced by other backends.
24
+ - Beyond chat, a VectorSearchService is passed a Request with a VectorSearch value and returns a Response with a
25
+ VectorHits value.
26
+ - A RetryService wraps any other Service and will attempt to re-invoke it on failure.
27
+ - A FirstInWinsService wraps any number of other Services and will return the first non-error Response it receives.
28
+
29
+ The service abstraction consists of 3 interrelated generic types:
30
+ - Request, an immutable final generic class containing a single value and any number of options.
31
+ - Response, an immutable final generic class containing a single value and any number of outputs.
32
+ - Service, a generic protocol consisting of a single async method `invoke`, taking a request and returning a response.
33
+
34
+ There are 2 related abstract base classes in the parent package:
35
+ - Option, a non-generic abstract class representing a service option.
36
+ - Output, a non-generic abstract class representing a service output.
37
+
38
+ The purpose of this arrangement is to provide the following:
39
+ - There is only one method - `Service.invoke` - to deal with.
40
+ - There is no base `Service` class - service types are distinguished only by the requests they accept and responses
41
+ they return.
42
+ - It facilitates a clear, introspectable, generally type-safe means for handling 'less-specific' and 'more-specific'
43
+ service types.
44
+ - It facilitates generic wrapper and transformation machinery.
45
+
46
+ The variance of the type parameters of the 3 classes is central:
47
+ - `Request[V_co, OptionT_co]`
48
+ - `Response[V_co, OutputT_contra]`
49
+ - `Service[RequestT_contra, ResponseT_co]`
50
+
51
+ And to understand this, it's important to understand how Option and Output subtypes are intended to be arranged:
52
+ - These types are *not* intended to form a deep type hierarchy:
53
+ - A RemoteChatOption is *not* intended to inherit from a ChatOption: a ChatOption (be it a base class or union alias)
54
+ represents an option that *any* ChatService can accept, whereas a RemoteChatOption represents an option that *only*
55
+ applies to a RemoteChatService.
56
+ - If RemoteChatOption inherited from a base ChatOption, then it would have to apply to *all* ChatService
57
+ implementations.
58
+ - For example: were ApiKey to inherit from ChatOption, then it would have to apply to all ChatServices, including
59
+ LocalChatService, which has no concept of an api key.
60
+ - Similarly, a RemoteChatOutput is *not* intended to inherit from a ChatOutput: a ChatOutput represents an output that
61
+ *any* ChatService can produce, whereas a RemoteChatOutput represents an output that *only* applies to a
62
+ RemoteChatService.
63
+ - These 2 types are intended to form flat, disjoint, unrelated families of subtypes, and Request and Response are
64
+ intended to be parameterized by the unions of all such families they may contain.
65
+ - Because of this, one's visual intuition regarding types and subtypes may be reversed: `int` is effectively a subtype
66
+ of `int | str` despite `int` being a visually shorter, less complex type.
67
+ - `int` is a *MORE SPECIFIC* / *STRICT SUBSET* subtype of `int | str`, the *LESS SPECIFIC* / *STRICT SUPERSET*
68
+ supertype.
69
+
70
+ Regarding type variance:
71
+ - Service has the classic setup of contravariant input and covariant output:
72
+ - A RemoteChatService *is a* ChatService.
73
+ - A RemoteChatService may accept less specific requests than a ChatService.
74
+ - A RemoteChatService may return more specific responses than a ChatService.
75
+ - Request is covariant on its options:
76
+ - Recall, a RemoteChatOption *is not a* ChatOption.
77
+ - A ChatRequest *is a* RemoteChatRequest as it will not contain options RemoteChatService cannot accept.
78
+ - Response is contravariant on its outputs:
79
+ - Recall, a RemoteChatOutput *is not a* ChatOutput.
80
+ - A RemoteChatResponse *is a* ChatResponse even though it may contain additional output variants not produced by
81
+ every ChatService.
82
+ - Code that calls a ChatService and is given a ChatResponse must be prepared to handle (usually by simply ignoring)
83
+ outputs not necessarily produced by a base ChatService.
84
+
85
+ Finally, in addition to a value and either options or outputs, a Request and Response each also contain a collection of
86
+ metadata. Very much unlike the Options and Outputs, the elements of these collections are simply of the types
87
+ `RequestMetadata | CommonMetadata` and `ResponseMetadata | CommonMetadata`, and are not otherwise parameterized. These
88
+ are intended for looser inputs and outputs: a generic unique id, timestamps, metrics, etc., and in general should
89
+ neither affect the behavior of services nor be depended upon by callers.
90
+
91
+ Below is a representative illustration of these types and their relationships. Note how:
92
+ - There is no subclassing of Request, Response, or Service - just type aliasing.
93
+ - There is no deep, shared subclassing of Option or Output.
94
+ - The type args passed to Request and Response are unions of all the Option and Output subtypes they may contain.
95
+ - These unions are kept in pluralized type aliases for convenience.
96
+ - There is no base ChatOption or ChatOutput class - were there, it would not be included in the base classes of any
97
+ local or remote only option or output.
98
+ - The local and remote sections take different but equivalent approaches:
99
+ - There are no base LocalChatOption or LocalChatOutput classes, but there *are* base RemoteChatOption and
100
+ RemoteChatOutput classes.
101
+ - Without any common base classes (besides the lowest level Output and Option classes), the local section treats them
102
+ as each distinct and bespoke, and the pluralized LocalChatOptions and LocalChatOutputs type aliases aggregate them
103
+ by explicitly listing them.
104
+ - With the common RemoteChatOption and RemoteChatOutput base classes, the remote section treats them as a related
105
+ family that any 'RemoteChat'-like service should accept and produce.
106
+
107
+ ```python
108
+ # Common chat
109
+
110
+ class MaxTokens(Option, tv.UniqueScalarTypedValue[int]): pass
111
+ class Temperature(Option, tv.UniqueScalarTypedValue[float]): pass
112
+
113
+ ChatOptions: ta.TypeAlias = MaxTokens | Temperature
114
+ ChatRequest: ta.TypeAlias = Request[Chat, ChatOptions]
115
+
116
+ class TokenUsage(Output, tv.UniqueScalarTypedValue[int]): pass
117
+ class ElapsedTime(Output, tv.UniqueScalarTypedValue[float]): pass
118
+
119
+ ChatOutputs: ta.TypeAlias = TokenUsage | ElapsedTime
120
+ ChatResponse: ta.TypeAlias = Response[Message, ChatOutputs]
121
+
122
+ ChatService: ta.TypeAlias = Service[ChatRequest, ChatResponse]
123
+
124
+ # Local chat
125
+
126
+ class ModelPath(Option, tv.ScalarTypedValue[str]): pass
127
+
128
+ LocalChatOptions: ta.TypeAlias = ChatOptions | ModelPath
129
+ LocalChatRequest: ta.TypeAlias = Request[Chat, LocalChatOptions]
130
+
131
+ class LogPath(Output, tv.ScalarTypedValue[str]): pass
132
+
133
+ LocalChatOutputs: ta.TypeAlias = ChatOutputs | LogPath
134
+ LocalChatResponse: ta.TypeAlias = Response[Message, LocalChatOutputs]
135
+
136
+ LocalChatService: ta.TypeAlias = Service[LocalChatRequest, LocalChatResponse]
137
+
138
+ # Remote chat
139
+
140
+ class RemoteChatOption(Option, lang.Abstract): pass
141
+ class ApiKey(RemoteChatOption, tv.ScalarTypedValue[str]): pass
142
+
143
+ RemoteChatOptions: ta.TypeAlias = ChatOptions | RemoteChatOption
144
+ RemoteChatRequest: ta.TypeAlias = Request[Chat, RemoteChatOptions]
145
+
146
+ class RemoteChatOutput(Output, lang.Abstract): pass
147
+ class BilledCostInUsd(RemoteChatOutput, tv.UniqueScalarTypedValue[float]): pass
148
+
149
+ RemoteChatOutputs: ta.TypeAlias = ChatOutputs | RemoteChatOutput
150
+ RemoteChatResponse: ta.TypeAlias = Response[Message, RemoteChatOutputs]
151
+
152
+ RemoteChatService: ta.TypeAlias = Service[RemoteChatRequest, RemoteChatResponse]
153
+ ```
154
+
@@ -1,6 +1,4 @@
1
1
  # ruff: noqa: I001
2
-
3
-
4
2
  from .facades import ( # noqa
5
3
  ServiceFacade,
6
4
 
@@ -8,10 +6,16 @@ from .facades import ( # noqa
8
6
  )
9
7
 
10
8
  from .requests import ( # noqa
9
+ RequestMetadata,
10
+ RequestMetadatas,
11
+
11
12
  Request,
12
13
  )
13
14
 
14
15
  from .responses import ( # noqa
16
+ ResponseMetadata,
17
+ ResponseMetadatas,
18
+
15
19
  Response,
16
20
  )
17
21