ommlds 0.0.0.dev440__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.dev440.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.dev440.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.dev440.dist-info → ommlds-0.0.0.dev480.dist-info}/WHEEL +0 -0
  269. {ommlds-0.0.0.dev440.dist-info → ommlds-0.0.0.dev480.dist-info}/entry_points.txt +0 -0
  270. {ommlds-0.0.0.dev440.dist-info → ommlds-0.0.0.dev480.dist-info}/licenses/LICENSE +0 -0
  271. {ommlds-0.0.0.dev440.dist-info → ommlds-0.0.0.dev480.dist-info}/top_level.txt +0 -0
@@ -3,31 +3,25 @@ import uuid
3
3
 
4
4
  from omlish import dataclasses as dc
5
5
 
6
- from ..messages import AiMessage
6
+ from ..messages import Chat
7
7
  from ..messages import Message
8
- from ..messages import ToolExecRequest
8
+ from ..messages import ToolUseMessage
9
9
  from ..transforms.base import MessageTransform
10
10
 
11
11
 
12
12
  ##
13
13
 
14
14
 
15
- def simple_uuid_tool_exec_request_id_factory(m: AiMessage, ter: ToolExecRequest) -> str: # noqa
15
+ def simple_uuid_tool_exec_request_id_factory(m: ToolUseMessage) -> str: # noqa
16
16
  return str(uuid.uuid4())
17
17
 
18
18
 
19
19
  @dc.dataclass(frozen=True)
20
- class ToolExecRequestIdAddingMessageTransform(MessageTransform):
21
- id_factory: ta.Callable[[AiMessage, ToolExecRequest], str] = dc.field(default=simple_uuid_tool_exec_request_id_factory) # noqa
20
+ class ToolUseIdAddingMessageTransform(MessageTransform):
21
+ id_factory: ta.Callable[[ToolUseMessage], str] = dc.field(default=simple_uuid_tool_exec_request_id_factory) # noqa
22
22
 
23
- def transform_message(self, m: Message) -> Message:
24
- if not isinstance(m, AiMessage) or not m.tool_exec_requests:
25
- return m
23
+ def transform_message(self, m: Message) -> Chat:
24
+ if not isinstance(m, ToolUseMessage) or m.tu.id is not None:
25
+ return [m]
26
26
 
27
- lst: list[ToolExecRequest] = []
28
- for ter in m.tool_exec_requests:
29
- if ter.id is None:
30
- ter = dc.replace(ter, id=self.id_factory(m, ter))
31
- lst.append(ter)
32
-
33
- return dc.replace(m, tool_exec_requests=lst)
27
+ return [dc.replace(m, tu=dc.replace(m.tu, id=self.id_factory(m)))]
@@ -1,54 +1,45 @@
1
+ import typing as ta
2
+
1
3
  from omlish import check
2
4
  from omlish import dataclasses as dc
3
5
 
4
- from ...content.types import Content
5
6
  from ...text.toolparsing.base import ParsedToolExec
6
7
  from ...text.toolparsing.base import ToolExecParser
7
8
  from ..messages import AiMessage
8
- from ..messages import ToolExecRequest
9
- from ..transforms.base import MessageTransform
9
+ from ..messages import AnyAiMessage
10
+ from ..messages import ToolUse
11
+ from ..messages import ToolUseMessage
12
+ from ..transforms.base import AiMessageTransform
10
13
 
11
14
 
12
15
  ##
13
16
 
14
17
 
15
18
  @dc.dataclass(frozen=True)
16
- class ToolExecParsingMessageTransform(MessageTransform[AiMessage]):
19
+ class ToolExecParsingMessageTransform(AiMessageTransform):
17
20
  parser: ToolExecParser
18
21
 
19
- def transform_message(self, message: AiMessage) -> AiMessage:
22
+ def transform_message(self, message: AnyAiMessage) -> ta.Sequence[AnyAiMessage]:
23
+ if not isinstance(message, AiMessage):
24
+ return [message]
25
+
20
26
  pts = self.parser.parse_tool_execs_(check.isinstance(message.c or '', str))
21
27
 
22
- sl: list[str] = []
23
- xl: list[ToolExecRequest] = []
28
+ out: list[AnyAiMessage] = []
29
+
24
30
  for pt in pts:
25
31
  if isinstance(pt, ParsedToolExec):
26
- xl.append(ToolExecRequest(
32
+ out.append(ToolUseMessage(ToolUse(
27
33
  id=pt.id,
28
34
  name=pt.name,
29
35
  args=pt.args,
30
36
  raw_args=pt.raw_body,
31
- ))
37
+ )))
32
38
 
33
39
  elif isinstance(pt, str):
34
- sl.append(pt)
40
+ out.append(AiMessage(pt))
35
41
 
36
42
  else:
37
43
  raise TypeError(pt)
38
44
 
39
- c: Content | None
40
- if len(sl) == 1:
41
- [c] = sl
42
- elif sl:
43
- c = sl
44
- else:
45
- c = None
46
-
47
- return dc.replace(
48
- message,
49
- c=c,
50
- tool_exec_requests=[
51
- *(message.tool_exec_requests or []),
52
- *xl,
53
- ],
54
- )
45
+ return out
@@ -1,76 +1,67 @@
1
+ """
2
+ Mirrors omlish.funcs.pairs.
3
+
4
+ TODO:
5
+ - MessagesTransform ? MessageTransformMessagesTransform? :| ...
6
+ """
1
7
  import abc
2
8
  import typing as ta
3
9
 
4
10
  from omlish import dataclasses as dc
5
11
  from omlish import lang
6
12
 
13
+ from ..messages import AnyAiMessage
14
+ from ..messages import AnyUserMessage
7
15
  from ..messages import Chat
8
16
  from ..messages import Message
9
17
 
10
18
 
19
+ MessageF = ta.TypeVar('MessageF', bound=Message)
11
20
  MessageT = ta.TypeVar('MessageT', bound=Message)
12
21
 
13
22
 
14
23
  ##
15
24
 
16
25
 
17
- class MessageTransform(lang.Abstract, ta.Generic[MessageT]):
26
+ class MessageTransform(lang.Abstract, ta.Generic[MessageF, MessageT]):
18
27
  @abc.abstractmethod
19
- def transform_message(self, message: MessageT) -> MessageT:
28
+ def transform_message(self, message: MessageF) -> ta.Sequence[MessageT]:
20
29
  raise NotImplementedError
21
30
 
22
31
 
32
+ AiMessageTransform: ta.TypeAlias = MessageTransform[AnyAiMessage, AnyAiMessage]
33
+ UserMessageTransform: ta.TypeAlias = MessageTransform[AnyUserMessage, AnyUserMessage]
34
+
35
+
23
36
  @dc.dataclass(frozen=True)
24
37
  class CompositeMessageTransform(MessageTransform):
25
38
  mts: ta.Sequence[MessageTransform]
26
39
 
27
- def transform_message(self, message: Message) -> Message:
40
+ def transform_message(self, message: Message) -> Chat:
41
+ chat: Chat = [message]
28
42
  for mt in self.mts:
29
- message = mt.transform_message(message)
30
- return message
43
+ chat = [o for i in chat for o in mt.transform_message(i)]
44
+ return chat
31
45
 
32
46
 
33
47
  @dc.dataclass(frozen=True)
34
- class FnMessageTransform(MessageTransform, ta.Generic[MessageT]):
35
- fn: ta.Callable[[MessageT], MessageT]
48
+ class FnMessageTransform(MessageTransform, ta.Generic[MessageF, MessageT]):
49
+ fn: ta.Callable[[MessageF], ta.Sequence[MessageT]]
36
50
 
37
- def transform_message(self, message: MessageT) -> MessageT:
51
+ def transform_message(self, message: MessageF) -> ta.Sequence[MessageT]:
38
52
  return self.fn(message)
39
53
 
40
54
 
41
55
  @dc.dataclass(frozen=True)
42
- class TypeFilteredMessageTransform(MessageTransform[Message], ta.Generic[MessageT]):
56
+ class TypeFilteredMessageTransform(MessageTransform, ta.Generic[MessageF, MessageT]):
43
57
  ty: type | tuple[type, ...]
44
- mt: MessageTransform[MessageT]
58
+ mt: MessageTransform[MessageF, MessageT]
45
59
 
46
- def transform_message(self, message: Message) -> Message:
60
+ def transform_message(self, message: Message) -> Chat:
47
61
  if isinstance(message, self.ty):
48
- return self.mt.transform_message(ta.cast(MessageT, message))
62
+ return self.mt.transform_message(ta.cast(MessageF, message))
49
63
  else:
50
- return message
51
-
52
-
53
- @ta.overload
54
- def fn_message_transform(
55
- fn: ta.Callable[[MessageT], MessageT],
56
- ty: type[MessageT],
57
- ) -> MessageTransform[MessageT]:
58
- ...
59
-
60
-
61
- @ta.overload
62
- def fn_message_transform(
63
- fn: ta.Callable[[Message], Message],
64
- ty: type | tuple[type, ...] | None = None,
65
- ) -> MessageTransform:
66
- ...
67
-
68
-
69
- def fn_message_transform(fn, ty=None) -> MessageTransform[MessageT]:
70
- mt: MessageTransform = FnMessageTransform(fn)
71
- if ty is not None:
72
- mt = TypeFilteredMessageTransform(ty, mt)
73
- return mt
64
+ return [message]
74
65
 
75
66
 
76
67
  ##
@@ -108,7 +99,7 @@ class MessageTransformChatTransform(ChatTransform):
108
99
  mt: MessageTransform
109
100
 
110
101
  def transform_chat(self, chat: Chat) -> Chat:
111
- return [self.mt.transform_message(m) for m in chat]
102
+ return [o for i in chat for o in self.mt.transform_message(i)]
112
103
 
113
104
 
114
105
  @dc.dataclass(frozen=True)
@@ -117,6 +108,6 @@ class LastMessageTransformChatTransform(ChatTransform):
117
108
 
118
109
  def transform_chat(self, chat: Chat) -> Chat:
119
110
  if chat:
120
- return [*chat[:-1], self.mt.transform_message(chat[-1])]
111
+ return [*chat[:-1], *self.mt.transform_message(chat[-1])]
121
112
  else:
122
113
  return []
@@ -3,13 +3,20 @@ import typing as ta
3
3
  import uuid
4
4
 
5
5
  from omlish import dataclasses as dc
6
+ from omlish import lang
7
+ from omlish import typedvalues as tv
6
8
 
7
9
  from ...metadata import CreatedAt
8
10
  from ...metadata import Uuid
11
+ from ..messages import Chat
9
12
  from ..messages import Message
13
+ from ..metadata import MessageMetadata
10
14
  from .base import MessageTransform
11
15
 
12
16
 
17
+ MessageT = ta.TypeVar('MessageT', bound=Message)
18
+
19
+
13
20
  ##
14
21
 
15
22
 
@@ -17,17 +24,36 @@ from .base import MessageTransform
17
24
  class UuidAddingMessageTransform(MessageTransform):
18
25
  uuid_factory: ta.Callable[[], uuid.UUID] = dc.field(default_factory=lambda: uuid.uuid4)
19
26
 
20
- def transform_message(self, m: Message) -> Message:
27
+ def transform_message(self, m: Message) -> Chat:
21
28
  if Uuid not in m.metadata:
22
29
  m = m.with_metadata(Uuid(self.uuid_factory()))
23
- return m
30
+ return [m]
24
31
 
25
32
 
26
33
  @dc.dataclass(frozen=True)
27
34
  class CreatedAtAddingMessageTransform(MessageTransform):
28
35
  clock: ta.Callable[[], datetime.datetime] = dc.field(default=datetime.datetime.now)
29
36
 
30
- def transform_message(self, m: Message) -> Message:
37
+ def transform_message(self, m: Message) -> Chat:
31
38
  if CreatedAt not in m.metadata:
32
39
  m = m.with_metadata(CreatedAt(self.clock()))
33
- return m
40
+ return [m]
41
+
42
+
43
+ ##
44
+
45
+
46
+ # FIXME: Unique?
47
+ class TransformedMessageOrigin(tv.ScalarTypedValue[Message], MessageMetadata, lang.Final):
48
+ pass
49
+
50
+
51
+ @dc.dataclass(frozen=True)
52
+ class OriginAddingMessageTransform(MessageTransform):
53
+ child: MessageTransform
54
+
55
+ def transform_message(self, m: Message) -> Chat:
56
+ return [
57
+ o.with_metadata(TransformedMessageOrigin(m)) if TransformedMessageOrigin not in o.metadata else m
58
+ for o in self.child.transform_message(m)
59
+ ]
@@ -1,13 +1,11 @@
1
- from omlish import check
2
1
  from omlish import dataclasses as dc
3
2
 
4
- from ..messages import AiMessage
3
+ from ..messages import check_ai_chat
5
4
  from ..services import ChatRequest
6
5
  from ..services import ChatResponse
7
6
  from ..services import ChatService
8
7
  from ..services import static_check_is_chat_service
9
8
  from .base import ChatTransform
10
- from .base import MessageTransform
11
9
 
12
10
 
13
11
  ##
@@ -19,10 +17,10 @@ class RequestChatTransformingChatService:
19
17
  ct: ChatTransform
20
18
  svc: ChatService
21
19
 
22
- def invoke(self, request: ChatRequest) -> ChatResponse:
20
+ async def invoke(self, request: ChatRequest) -> ChatResponse:
23
21
  new_chat = self.ct.transform_chat(request.v)
24
22
  new_req = dc.replace(request, v=new_chat)
25
- return self.svc.invoke(new_req)
23
+ return await self.svc.invoke(new_req)
26
24
 
27
25
 
28
26
  #
@@ -30,11 +28,11 @@ class RequestChatTransformingChatService:
30
28
 
31
29
  @static_check_is_chat_service
32
30
  @dc.dataclass(frozen=True)
33
- class ResponseMessageTransformingChatService:
34
- mt: MessageTransform[AiMessage]
31
+ class ResponseChatTransformingChatService:
32
+ ct: ChatTransform
35
33
  svc: ChatService
36
34
 
37
- def invoke(self, request: ChatRequest) -> ChatResponse:
38
- orig_resp = self.svc.invoke(request)
39
- new_msg = self.mt.transform_message(orig_resp.v)
40
- return dc.replace(orig_resp, v=check.isinstance(new_msg, AiMessage))
35
+ async def invoke(self, request: ChatRequest) -> ChatResponse:
36
+ orig_resp = await self.svc.invoke(request)
37
+ new_chat = check_ai_chat(self.ct.transform_chat(orig_resp.v))
38
+ return dc.replace(orig_resp, v=new_chat)
@@ -6,9 +6,9 @@ from omlish import check
6
6
  from omlish import lang
7
7
  from omlish import marshal as msh
8
8
  from omlish import reflect as rfl
9
- from omlish.funcs import match as mfs
10
9
 
11
10
  from .images import ImageContent # noqa
11
+ from .json import JsonContent # noqa
12
12
  from .materialize import CanContent
13
13
  from .materialize import _InnerCanContent
14
14
  from .sequence import BlockContent # noqa
@@ -52,10 +52,11 @@ class _ContentMarshaler(msh.Marshaler):
52
52
  raise TypeError(o)
53
53
 
54
54
 
55
- class _ContentMarshalerFactory(msh.MarshalerFactoryMatchClass):
56
- @mfs.simple(lambda _, ctx, rty: rty is MarshalContent or rty == _MARSHAL_CONTENT_UNION_RTY)
57
- def _build(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
58
- return _ContentMarshaler(ctx.make(ExtendedContent))
55
+ class _ContentMarshalerFactory(msh.MarshalerFactory):
56
+ def make_marshaler(self, ctx: msh.MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Marshaler] | None:
57
+ if not (rty is MarshalContent or rty == _MARSHAL_CONTENT_UNION_RTY):
58
+ return None
59
+ return lambda: _ContentMarshaler(ctx.make_marshaler(ExtendedContent))
59
60
 
60
61
 
61
62
  @dc.dataclass(frozen=True)
@@ -73,10 +74,11 @@ class _ContentUnmarshaler(msh.Unmarshaler):
73
74
  raise TypeError(v)
74
75
 
75
76
 
76
- class _ContentUnmarshalerFactory(msh.UnmarshalerFactoryMatchClass):
77
- @mfs.simple(lambda _, ctx, rty: rty is MarshalContent or rty == _MARSHAL_CONTENT_UNION_RTY)
78
- def _build(self, ctx: msh.UnmarshalContext, rty: rfl.Type) -> msh.Unmarshaler:
79
- return _ContentUnmarshaler(ctx.make(ExtendedContent))
77
+ class _ContentUnmarshalerFactory(msh.UnmarshalerFactory):
78
+ def make_unmarshaler(self, ctx: msh.UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Unmarshaler] | None: # noqa
79
+ if not (rty is MarshalContent or rty == _MARSHAL_CONTENT_UNION_RTY):
80
+ return None
81
+ return lambda: _ContentUnmarshaler(ctx.make_unmarshaler(ExtendedContent))
80
82
 
81
83
 
82
84
  ##
@@ -103,10 +105,11 @@ class _CanContentMarshaler(msh.Marshaler):
103
105
  return self.c.marshal(ctx, check.isinstance(o, CONTENT_RUNTIME_TYPES))
104
106
 
105
107
 
106
- class _CanContentMarshalerFactory(msh.MarshalerFactoryMatchClass):
107
- @mfs.simple(lambda _, ctx, rty: rty is MarshalCanContent or rty == _MARSHAL_CAN_CONTENT_UNION_RTY)
108
- def _build(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
109
- return _CanContentMarshaler(ctx.make(Content))
108
+ class _CanContentMarshalerFactory(msh.MarshalerFactory):
109
+ def make_marshaler(self, ctx: msh.MarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Marshaler] | None:
110
+ if not (rty is MarshalCanContent or rty == _MARSHAL_CAN_CONTENT_UNION_RTY):
111
+ return None
112
+ return lambda: _CanContentMarshaler(ctx.make_marshaler(Content))
110
113
 
111
114
 
112
115
  @dc.dataclass(frozen=True)
@@ -117,10 +120,11 @@ class _CanContentUnmarshaler(msh.Unmarshaler):
117
120
  return self.c.unmarshal(ctx, v)
118
121
 
119
122
 
120
- class _CanContentUnmarshalerFactory(msh.UnmarshalerFactoryMatchClass):
121
- @mfs.simple(lambda _, ctx, rty: rty is MarshalCanContent or rty == _MARSHAL_CAN_CONTENT_UNION_RTY)
122
- def _build(self, ctx: msh.UnmarshalContext, rty: rfl.Type) -> msh.Unmarshaler:
123
- return _CanContentUnmarshaler(ctx.make(Content))
123
+ class _CanContentUnmarshalerFactory(msh.UnmarshalerFactory):
124
+ def make_unmarshaler(self, ctx: msh.UnmarshalFactoryContext, rty: rfl.Type) -> ta.Callable[[], msh.Unmarshaler] | None: # noqa
125
+ if not (rty is MarshalCanContent or rty == _MARSHAL_CAN_CONTENT_UNION_RTY):
126
+ return None
127
+ return lambda: _CanContentUnmarshaler(ctx.make_unmarshaler(Content))
124
128
 
125
129
 
126
130
  ##
@@ -139,28 +143,48 @@ class _ImageContentUnmarshaler(msh.Unmarshaler):
139
143
  ##
140
144
 
141
145
 
146
+ class _JsonContentMarshaler(msh.Marshaler):
147
+ def marshal(self, ctx: msh.MarshalContext, o: ta.Any) -> msh.Value:
148
+ return ta.cast(msh.Value, check.isinstance(o, JsonContent).v)
149
+
150
+
151
+ class _JsonContentUnmarshaler(msh.Unmarshaler):
152
+ def unmarshal(self, ctx: msh.UnmarshalContext, v: msh.Value) -> ta.Any:
153
+ return JsonContent(v)
154
+
155
+
156
+ ##
157
+
158
+
142
159
  @lang.static_init
143
- def _install_standard_marshalling() -> None:
160
+ def _install_standard_marshaling() -> None:
144
161
  extended_content_poly = msh.Polymorphism(
145
162
  ExtendedContent,
146
163
  [
147
164
  msh.Impl(InlineContent, 'inline'),
148
165
  msh.Impl(BlockContent, 'block'),
149
166
  msh.Impl(ImageContent, 'image'),
167
+ msh.Impl(JsonContent, 'json'),
150
168
  msh.Impl(TextContent, 'text'),
151
169
  ],
152
170
  )
153
171
 
154
172
  msh.install_standard_factories(
155
173
  msh.PolymorphismMarshalerFactory(extended_content_poly),
156
- msh.TypeMapMarshalerFactory({ImageContent: _ImageContentMarshaler()}),
174
+ msh.TypeMapMarshalerFactory({
175
+ ImageContent: _ImageContentMarshaler(),
176
+ JsonContent: _JsonContentMarshaler(),
177
+ }),
157
178
  _ContentMarshalerFactory(),
158
179
  _CanContentMarshalerFactory(),
159
180
  )
160
181
 
161
182
  msh.install_standard_factories(
162
183
  msh.PolymorphismUnmarshalerFactory(extended_content_poly),
163
- msh.TypeMapUnmarshalerFactory({ImageContent: _ImageContentUnmarshaler()}),
184
+ msh.TypeMapUnmarshalerFactory({
185
+ ImageContent: _ImageContentUnmarshaler(),
186
+ JsonContent: _JsonContentUnmarshaler(),
187
+ }),
164
188
  _ContentUnmarshalerFactory(),
165
189
  _CanContentUnmarshalerFactory(),
166
190
  )
@@ -0,0 +1,13 @@
1
+ from omlish import dataclasses as dc
2
+ from omlish import lang
3
+
4
+ from ..json import JsonValue
5
+ from .simple import SimpleSingleExtendedContent
6
+
7
+
8
+ ##
9
+
10
+
11
+ @dc.dataclass(frozen=True)
12
+ class JsonContent(SimpleSingleExtendedContent, lang.Final):
13
+ v: JsonValue
@@ -112,7 +112,7 @@ class ContentMaterializer:
112
112
  finally:
113
113
  self._cur_depth -= 1
114
114
 
115
- @dispatch.method
115
+ @dispatch.method()
116
116
  def _materialize(self, o: CanContent) -> Content:
117
117
  raise TypeError(o)
118
118
 
@@ -130,7 +130,13 @@ class ContentMaterializer:
130
130
 
131
131
  @_materialize.register
132
132
  def _materialize_iterable(self, o: ta.Iterable) -> Content:
133
- return [self.materialize(e) for e in o]
133
+ # `collections.abc.Iterable` appears as a virtual base in the dispatch c3.mro for ContentNamespace before `type`
134
+ # does (due to NamespaceMeta having `__iter__`), so handle that here too.
135
+ if isinstance(o, type) and issubclass(o, ContentNamespace):
136
+ return self._materialize_namespace_type(o)
137
+
138
+ else:
139
+ return [self.materialize(e) for e in o]
134
140
 
135
141
  @_materialize.register
136
142
  def _materialize_none(self, o: None) -> Content:
@@ -151,25 +157,12 @@ class ContentMaterializer:
151
157
  def _materialize_namespace_type(self, o: type[ContentNamespace]) -> Content:
152
158
  check.issubclass(o, ContentNamespace)
153
159
 
154
- def rec(v: ta.Any) -> ta.Generator[Content]:
155
- if isinstance(v, (bytes, bytearray, ta.Mapping)):
156
- return
157
-
158
- elif isinstance(v, type):
159
- if issubclass(v, ContentNamespace):
160
- for n, e in v:
161
- if n.startswith('_'):
162
- continue
163
- yield from rec(e)
164
-
165
- elif isinstance(v, ta.Iterable):
166
- for e in v:
167
- yield from rec(e)
168
-
169
- else:
170
- yield self.materialize(v)
171
-
172
- return list(rec(o))
160
+ out: list[Content] = []
161
+ for n, e in o:
162
+ if n.startswith('_'):
163
+ continue
164
+ out.append(self.materialize(e))
165
+ return out
173
166
 
174
167
  #
175
168
 
@@ -1,3 +1,7 @@
1
+ """
2
+ TODO:
3
+ - re-softwrap
4
+ """
1
5
  import abc
2
6
  import dataclasses as dc
3
7
  import typing as ta
@@ -33,7 +33,7 @@ class ContentInterleaver:
33
33
  cs = lang.interleave(cs, separator)
34
34
  return list(cs)
35
35
 
36
- @dispatch.method
36
+ @dispatch.method()
37
37
  def interleave(self, c: Content) -> Content:
38
38
  return c
39
39
 
@@ -22,7 +22,7 @@ class ContentSqueezer:
22
22
 
23
23
  self._strip_strings = strip_strings
24
24
 
25
- @dispatch.method
25
+ @dispatch.method()
26
26
  def squeeze(self, c: Content) -> ta.Iterable[SingleContent]:
27
27
  raise TypeError(c)
28
28
 
@@ -24,7 +24,7 @@ class ContentStringWriter:
24
24
 
25
25
  self._out = out
26
26
 
27
- @dispatch.method
27
+ @dispatch.method()
28
28
  def write(self, c: Content) -> None:
29
29
  raise TypeError(c)
30
30
 
ommlds/minichain/json.py CHANGED
@@ -1,3 +1,4 @@
1
+ # ruff: noqa: UP007
1
2
  import typing as ta
2
3
 
3
4
  from omlish import dataclasses as dc
@@ -11,3 +12,22 @@ from omlish import lang
11
12
  class JsonSchema(lang.Final):
12
13
  name: str
13
14
  root: ta.Any
15
+
16
+
17
+ ##
18
+
19
+
20
+ JsonValue: ta.TypeAlias = ta.Union[
21
+ ta.Mapping[str, 'JsonValue'],
22
+
23
+ ta.Sequence['JsonValue'],
24
+
25
+ str,
26
+
27
+ int,
28
+ float,
29
+
30
+ bool,
31
+
32
+ None,
33
+ ]
File without changes
@@ -0,0 +1,6 @@
1
+ CODE_AGENT_SYSTEM_PROMPT = """
2
+ You are an interactive assistant specializing in programming tasks.
3
+
4
+ Your goal is to assist the user by accomplishing the tasks and answering the questions given to you by the user using
5
+ your available tools.
6
+ """