ommlds 0.0.0.dev511__py3-none-any.whl → 0.0.0.dev513__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.
@@ -102,7 +102,7 @@
102
102
  "module": ".minichain.backends.impls.cerebras.chat",
103
103
  "attr": null,
104
104
  "file": "ommlds/minichain/backends/impls/cerebras/chat.py",
105
- "line": 26,
105
+ "line": 27,
106
106
  "value": {
107
107
  "!.minichain.registries.manifests.RegistryManifest": {
108
108
  "module": "ommlds.minichain.backends.impls.cerebras.chat",
@@ -148,7 +148,7 @@
148
148
  "module": ".minichain.backends.impls.cerebras.stream",
149
149
  "attr": null,
150
150
  "file": "ommlds/minichain/backends/impls/cerebras/stream.py",
151
- "line": 30,
151
+ "line": 31,
152
152
  "value": {
153
153
  "!.minichain.registries.manifests.RegistryManifest": {
154
154
  "module": "ommlds.minichain.backends.impls.cerebras.stream",
ommlds/__about__.py CHANGED
@@ -24,7 +24,7 @@ class Project(ProjectBase):
24
24
  'mlx ~= 0.30; sys_platform == "darwin"',
25
25
  'mlx-lm ~= 0.29; sys_platform == "darwin"',
26
26
 
27
- # 'sentencepiece ~= 0.2', # FIXME: https://github.com/google/sentencepiece/issues/1121
27
+ 'sentencepiece ~= 0.2',
28
28
 
29
29
  'tiktoken ~= 0.12',
30
30
 
@@ -0,0 +1,9 @@
1
+ import typing as ta
2
+
3
+
4
+ ##
5
+
6
+
7
+ REQUIRED_HTTP_HEADERS: ta.Mapping[bytes, bytes] = {
8
+ b'User-Agent': b'python-httpx/0.28.1', # required or it 403's lol
9
+ }
@@ -49,7 +49,7 @@ class ChatCompletionRequest(lang.Final):
49
49
  class UserMessage(Message, lang.Final):
50
50
  content: str | ta.Sequence[str]
51
51
  name: str | None = None
52
- role: ta.Literal['system'] = 'system'
52
+ role: ta.Literal['user'] = 'user'
53
53
 
54
54
  @dc.dataclass(frozen=True, kw_only=True)
55
55
  @_set_class_marshal_options
ommlds/cli/main.py CHANGED
@@ -4,6 +4,7 @@ TODO:
4
4
  """
5
5
  import abc
6
6
  import functools
7
+ import sys
7
8
  import typing as ta
8
9
 
9
10
  import anyio
@@ -136,14 +137,28 @@ class ChatProfile(Profile):
136
137
  check.arg(not self._args.message)
137
138
 
138
139
  elif self._args.message:
139
- # TODO: '-' -> stdin
140
+ ps: list[str] = []
141
+
142
+ for a in self._args.message:
143
+ if a == '-':
144
+ ps.append(sys.stdin.read())
145
+
146
+ elif a.startswith('@'):
147
+ with open(a[1:]) as f:
148
+ ps.append(f.read())
149
+
150
+ else:
151
+ ps.append(a)
152
+
153
+ c = ' '.join(ps)
154
+
140
155
  cfg = dc.replace(
141
156
  cfg,
142
157
  driver=dc.replace(
143
158
  cfg.driver,
144
159
  user=dc.replace(
145
160
  cfg.driver.user,
146
- initial_user_content=' '.join(self._args.message),
161
+ initial_user_content=c,
147
162
  ),
148
163
  ),
149
164
  )
@@ -25,6 +25,7 @@ from .styles import read_app_css
25
25
  from .widgets.input import InputOuter
26
26
  from .widgets.input import InputTextArea
27
27
  from .widgets.messages import AiMessage
28
+ from .widgets.messages import MessageDivider
28
29
  from .widgets.messages import MessagesContainer
29
30
  from .widgets.messages import StaticAiMessage
30
31
  from .widgets.messages import StreamAiMessage
@@ -50,6 +51,21 @@ class ChatAppGetter(lang.AsyncCachedFunc0['ChatApp']):
50
51
  pass
51
52
 
52
53
 
54
+ class ChatAppScreen(tx.Screen):
55
+ BINDINGS: ta.ClassVar[ta.Sequence[tx.BindingType]] = [
56
+ tx.Binding(
57
+ 'alt+c,super+c',
58
+ 'screen.copy_text',
59
+ 'Copy selected text',
60
+ show=False,
61
+ ),
62
+ ]
63
+
64
+ @classmethod
65
+ def _merge_bindings(cls) -> tx.BindingsMap:
66
+ return tx.unbind_map_keys(super()._merge_bindings(), ['ctrl+c'])
67
+
68
+
53
69
  class ChatApp(
54
70
  tx.ClipboardAppMixin,
55
71
  tx.DevtoolsAppMixin,
@@ -61,10 +77,11 @@ class ChatApp(
61
77
  *tx.App.BINDINGS,
62
78
 
63
79
  tx.Binding(
64
- 'alt+c,ctrl+c,super+c',
65
- 'screen.copy_text',
66
- 'Copy selected text',
80
+ 'escape',
81
+ 'cancel',
82
+ 'Cancel current operation',
67
83
  show=False,
84
+ priority=True,
68
85
  ),
69
86
  ]
70
87
 
@@ -96,16 +113,21 @@ class ChatApp(
96
113
  def get_driver_class(self) -> type[tx.Driver]:
97
114
  return tx.get_pending_writes_driver_class(super().get_driver_class())
98
115
 
116
+ def get_default_screen(self) -> tx.Screen:
117
+ return ChatAppScreen(id='_default')
118
+
99
119
  CSS: ta.ClassVar[str] = read_app_css()
100
120
 
101
- #
121
+ ##
122
+ # Compose
102
123
 
103
124
  def compose(self) -> tx.ComposeResult:
104
125
  yield MessagesContainer(id='messages-container')
105
126
 
106
127
  yield InputOuter(id='input-outer')
107
128
 
108
- #
129
+ ##
130
+ # Widget getters
109
131
 
110
132
  def _get_input_text_area(self) -> InputTextArea:
111
133
  return self.query_one('#input', InputTextArea)
@@ -113,7 +135,8 @@ class ChatApp(
113
135
  def _get_messages_container(self) -> tx.VerticalScroll:
114
136
  return self.query_one('#messages-container', MessagesContainer)
115
137
 
116
- #
138
+ ##
139
+ # Messages
117
140
 
118
141
  def _is_messages_at_bottom(self, threshold: int = 3) -> bool:
119
142
  return (ms := self._get_messages_container()).scroll_y >= (ms.max_scroll_y - threshold)
@@ -125,6 +148,10 @@ class ChatApp(
125
148
  if (ms := self._get_messages_container()).max_scroll_y:
126
149
  ms.anchor()
127
150
 
151
+ def _scroll_messages_to_bottom_and_anchor(self) -> None:
152
+ self._scroll_messages_to_bottom()
153
+ self._anchor_messages()
154
+
128
155
  #
129
156
 
130
157
  _pending_mount_messages: list[tx.Widget] | None = None
@@ -150,14 +177,14 @@ class ChatApp(
150
177
 
151
178
  await sam.append_content(content)
152
179
 
153
- self.call_after_refresh(self._scroll_messages_to_bottom)
154
-
155
180
  if was_at_bottom:
156
- self.call_after_refresh(self._anchor_messages)
181
+ self.call_after_refresh(self._scroll_messages_to_bottom_and_anchor)
157
182
 
158
183
  else:
159
184
  await self._mount_messages(StreamAiMessage(content))
160
185
 
186
+ _num_mounted_messages = 0
187
+
161
188
  async def _mount_messages(self, *messages: tx.Widget) -> None:
162
189
  was_at_bottom = self._is_messages_at_bottom()
163
190
 
@@ -167,8 +194,13 @@ class ChatApp(
167
194
  if isinstance(msg, (AiMessage, ToolConfirmationMessage)):
168
195
  await self._finalize_stream_ai_message()
169
196
 
197
+ if self._num_mounted_messages:
198
+ await msg_ctr.mount(MessageDivider())
199
+
170
200
  await msg_ctr.mount(msg)
171
201
 
202
+ self._num_mounted_messages += 1
203
+
172
204
  if isinstance(msg, StreamAiMessage):
173
205
  self._stream_ai_message = check.replacing_none(self._stream_ai_message, msg)
174
206
  await msg.write_initial_content()
@@ -180,12 +212,13 @@ class ChatApp(
180
212
  if was_at_bottom:
181
213
  self.call_after_refresh(self._anchor_messages)
182
214
 
183
- #
215
+ ##
216
+ # Chat events
184
217
 
185
- _chat_event_task: asyncio.Task[None] | None = None
218
+ _chat_event_queue_task: asyncio.Task[None] | None = None
186
219
 
187
- @logs.async_exception_logging(alog)
188
- async def _chat_event_task_main(self) -> None:
220
+ @logs.async_exception_logging(alog, BaseException)
221
+ async def _chat_event_queue_task_main(self) -> None:
189
222
  while True:
190
223
  ev = await self._chat_event_queue.get()
191
224
  if ev is None:
@@ -217,16 +250,47 @@ class ChatApp(
217
250
  elif isinstance(ev.delta, mc.ToolUseAiDelta):
218
251
  pass
219
252
 
220
- #
253
+ ##
254
+ # Chat actions
221
255
 
222
256
  @dc.dataclass(frozen=True)
223
257
  class UserInput:
224
258
  text: str
225
259
 
226
- _chat_action_task: asyncio.Task[None] | None = None
260
+ async def _execute_user_input(self, ac: UserInput) -> None:
261
+ try:
262
+ await self._chat_facade.handle_user_input(ac.text)
263
+ except Exception as e: # noqa
264
+ # raise
265
+ await self.display_ui_message(repr(e))
266
+
267
+ #
268
+
269
+ _cur_chat_action: asyncio.Task[None] | None = None
270
+
271
+ async def _execute_chat_action(self, fn: ta.Callable[[], ta.Any]) -> None:
272
+ check.state(self._cur_chat_action is None)
273
+
274
+ self._cur_chat_action = asyncio.create_task(fn())
275
+
276
+ try:
277
+ await self._cur_chat_action
278
+
279
+ except asyncio.CancelledError:
280
+ pass
227
281
 
228
- @logs.async_exception_logging(alog)
229
- async def _chat_action_task_main(self) -> None:
282
+ except BaseException as e: # noqa
283
+ raise
284
+
285
+ finally:
286
+ self._cur_chat_action = None
287
+
288
+ #
289
+
290
+ _chat_action_queue_task: asyncio.Task[None] | None = None
291
+
292
+ @logs.async_exception_logging(alog, BaseException)
293
+ async def _chat_action_queue_task_main(self) -> None:
230
294
  while True:
231
295
  ac = await self._chat_action_queue.get()
232
296
  if ac is None:
@@ -235,25 +299,22 @@ class ChatApp(
235
299
  await alog.debug(lambda: f'Got chat action: {ac!r}')
236
300
 
237
301
  if isinstance(ac, ChatApp.UserInput):
238
- try:
239
- await self._chat_facade.handle_user_input(ac.text)
240
- except Exception as e: # noqa
241
- # raise
242
- await self.display_ui_message(repr(e))
302
+ await self._execute_chat_action(lambda: self._execute_user_input(ac))
243
303
 
244
304
  else:
245
305
  raise TypeError(ac) # noqa
246
306
 
247
- #
307
+ ##
308
+ # Mounting
248
309
 
249
310
  async def on_mount(self) -> None:
250
- check.state(self._chat_event_task is None)
251
- self._chat_event_task = asyncio.create_task(self._chat_event_task_main())
311
+ check.state(self._chat_event_queue_task is None)
312
+ self._chat_event_queue_task = asyncio.create_task(self._chat_event_queue_task_main())
252
313
 
253
314
  await self._chat_driver.start()
254
315
 
255
- check.state(self._chat_action_task is None)
256
- self._chat_action_task = asyncio.create_task(self._chat_action_task_main())
316
+ check.state(self._chat_action_queue_task is None)
317
+ self._chat_action_queue_task = asyncio.create_task(self._chat_action_queue_task_main())
257
318
 
258
319
  self._get_input_text_area().focus()
259
320
 
@@ -265,16 +326,19 @@ class ChatApp(
265
326
  )
266
327
 
267
328
  async def on_unmount(self) -> None:
268
- if (cdt := self._chat_event_task) is not None:
329
+ if (cat := self._chat_action_queue_task) is not None:
269
330
  await self._chat_event_queue.put(None)
270
- await cdt
331
+ await cat
271
332
 
272
333
  await self._chat_driver.stop()
273
334
 
274
- if (cet := self._chat_event_task) is not None:
335
+ if (cet := self._chat_event_queue_task) is not None:
275
336
  await self._chat_event_queue.put(None)
276
337
  await cet
277
338
 
339
+ ##
340
+ # Input
341
+
278
342
  @tx.on(InputTextArea.Submitted)
279
343
  async def on_input_text_area_submitted(self, event: InputTextArea.Submitted) -> None:
280
344
  self._get_input_text_area().clear()
@@ -329,7 +393,8 @@ class ChatApp(
329
393
 
330
394
  self.screen.post_message(tx.Key(event.key, event.character))
331
395
 
332
- #
396
+ ##
397
+ # User interaction
333
398
 
334
399
  async def confirm_tool_use(
335
400
  self,
@@ -358,3 +423,7 @@ class ChatApp(
358
423
  content: str,
359
424
  ) -> None:
360
425
  await self._mount_messages(UiMessage(content))
426
+
427
+ async def action_cancel(self) -> None:
428
+ if (cat := self._cur_chat_action) is not None:
429
+ cat.cancel()
@@ -14,7 +14,17 @@
14
14
  }
15
15
 
16
16
 
17
- /* Base */
17
+ /* Divider */
18
+
19
+ .message-divider {
20
+ height: 1;
21
+ margin: 1 0 0 0;
22
+
23
+ border-top: solid $primary;
24
+ }
25
+
26
+
27
+ /* Base Message */
18
28
 
19
29
  .message {
20
30
  width: 1fr;
@@ -50,7 +60,7 @@
50
60
  }
51
61
 
52
62
 
53
- /* Welcome */
63
+ /* Welcome Message */
54
64
 
55
65
  .welcome-message {
56
66
  margin: 0;
@@ -67,7 +77,7 @@
67
77
  }
68
78
 
69
79
 
70
- /* User */
80
+ /* User Message */
71
81
 
72
82
  .user-message {
73
83
  }
@@ -82,7 +92,7 @@
82
92
  }
83
93
 
84
94
 
85
- /* Ai */
95
+ /* Ai Message */
86
96
 
87
97
  .ai-message {
88
98
  }
@@ -106,7 +116,7 @@
106
116
  }
107
117
 
108
118
 
109
- /* Tool Confirmation */
119
+ /* Tool Confirmation Message */
110
120
 
111
121
  .tool-confirmation-message {
112
122
  }
@@ -142,7 +152,7 @@
142
152
  }
143
153
 
144
154
 
145
- /* Ui */
155
+ /* Ui Message */
146
156
 
147
157
  .ui-message {
148
158
  }
@@ -16,6 +16,16 @@ class MessagesContainer(tx.VerticalScroll):
16
16
  ##
17
17
 
18
18
 
19
+ class MessageDivider(tx.Static):
20
+ def __init__(self) -> None:
21
+ super().__init__()
22
+
23
+ self.add_class('message-divider')
24
+
25
+
26
+ ##
27
+
28
+
19
29
  class Message(tx.Static, lang.Abstract):
20
30
  def __init__(self, *args: ta.Any, **kwargs: ta.Any) -> None:
21
31
  super().__init__(*args, **kwargs)
@@ -7,6 +7,7 @@ from omlish.formats import json
7
7
  from omlish.http import all as http
8
8
 
9
9
  from .....backends.cerebras import protocol as pt
10
+ from .....backends.cerebras.clients import REQUIRED_HTTP_HEADERS
10
11
  from ....chat.choices.services import ChatChoicesRequest
11
12
  from ....chat.choices.services import ChatChoicesResponse
12
13
  from ....chat.choices.services import static_check_is_chat_choices_service
@@ -70,6 +71,7 @@ class CerebrasChatChoicesService:
70
71
  headers={
71
72
  http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
72
73
  http.consts.HEADER_AUTH: http.consts.format_bearer_auth_header(check.not_none(self._api_key).reveal()),
74
+ **REQUIRED_HTTP_HEADERS,
73
75
  },
74
76
  data=json.dumps(raw_request).encode('utf-8'),
75
77
  client=self._http_client,
@@ -8,6 +8,7 @@ from omlish.http import all as http
8
8
  from omlish.http import sse
9
9
 
10
10
  from .....backends.cerebras import protocol as pt
11
+ from .....backends.cerebras.clients import REQUIRED_HTTP_HEADERS
11
12
  from ....chat.choices.stream.services import ChatChoicesStreamRequest
12
13
  from ....chat.choices.stream.services import ChatChoicesStreamResponse
13
14
  from ....chat.choices.stream.services import static_check_is_chat_choices_stream_service
@@ -98,6 +99,7 @@ class CerebrasChatChoicesStreamService:
98
99
  headers={
99
100
  http.consts.HEADER_CONTENT_TYPE: http.consts.CONTENT_TYPE_JSON,
100
101
  http.consts.HEADER_AUTH: http.consts.format_bearer_auth_header(check.not_none(self._api_key).reveal()),
102
+ **REQUIRED_HTTP_HEADERS,
101
103
  },
102
104
  data=json.dumps(raw_request).encode('utf-8'),
103
105
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ommlds
3
- Version: 0.0.0.dev511
3
+ Version: 0.0.0.dev513
4
4
  Summary: ommlds
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,12 +14,13 @@ Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: omlish==0.0.0.dev511
17
+ Requires-Dist: omlish==0.0.0.dev513
18
18
  Provides-Extra: all
19
- Requires-Dist: omdev==0.0.0.dev511; extra == "all"
19
+ Requires-Dist: omdev==0.0.0.dev513; extra == "all"
20
20
  Requires-Dist: llama-cpp-python~=0.3; extra == "all"
21
21
  Requires-Dist: mlx~=0.30; sys_platform == "darwin" and extra == "all"
22
22
  Requires-Dist: mlx-lm~=0.29; sys_platform == "darwin" and extra == "all"
23
+ Requires-Dist: sentencepiece~=0.2; extra == "all"
23
24
  Requires-Dist: tiktoken~=0.12; extra == "all"
24
25
  Requires-Dist: tinygrad~=0.12; extra == "all"
25
26
  Requires-Dist: tokenizers~=0.22; extra == "all"
@@ -38,11 +39,12 @@ Requires-Dist: mwparserfromhell~=0.7; extra == "all"
38
39
  Requires-Dist: wikitextparser~=0.56; extra == "all"
39
40
  Requires-Dist: lxml>=5.3; python_version < "3.13" and extra == "all"
40
41
  Provides-Extra: omdev
41
- Requires-Dist: omdev==0.0.0.dev511; extra == "omdev"
42
+ Requires-Dist: omdev==0.0.0.dev513; extra == "omdev"
42
43
  Provides-Extra: backends
43
44
  Requires-Dist: llama-cpp-python~=0.3; extra == "backends"
44
45
  Requires-Dist: mlx~=0.30; sys_platform == "darwin" and extra == "backends"
45
46
  Requires-Dist: mlx-lm~=0.29; sys_platform == "darwin" and extra == "backends"
47
+ Requires-Dist: sentencepiece~=0.2; extra == "backends"
46
48
  Requires-Dist: tiktoken~=0.12; extra == "backends"
47
49
  Requires-Dist: tinygrad~=0.12; extra == "backends"
48
50
  Requires-Dist: tokenizers~=0.22; extra == "backends"
@@ -1,6 +1,6 @@
1
- ommlds/.omlish-manifests.json,sha256=PihtJmB7EFRQ5MHZTzfq6GOST1683niUqHZJDFc0vmw,28921
1
+ ommlds/.omlish-manifests.json,sha256=fAltqnrgKoclgjSh60TjFimcKrcmyLgHAQv39V1ibaY,28921
2
2
  ommlds/README.md,sha256=xhbl2n19GznXrIzAGdlX8PAYJYsOo_Zu63I7G1UFRZE,398
3
- ommlds/__about__.py,sha256=xHpcF4Ek0Wia5P3X-SePUtGmGzXpXo-Q36a7-X9P6-A,1902
3
+ ommlds/__about__.py,sha256=HgYf-9_4V8-o3MkmYbjeHCkqyQugFN3u6at613N522Y,1838
4
4
  ommlds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  ommlds/_hacks/__init__.py,sha256=ajfw7dMKH8UuloeQ5MSxWwgAmdWf2v8gm-K3uLP9wtY,196
6
6
  ommlds/_hacks/funcs.py,sha256=8XseIblP7yolDUD7WQSGn1LP90IQzByVejSzphAPDyM,2861
@@ -20,7 +20,8 @@ ommlds/backends/anthropic/protocol/sse/events.py,sha256=77xVcT6H22uRIxZcxc0_-79j
20
20
  ommlds/backends/cerebras/__init__.py,sha256=-RtLrdEGN2da1KCf7YNs32jN-kJhT_kNVrcOv4x_J-w,101
21
21
  ommlds/backends/cerebras/_dataclasses.py,sha256=VPR97XO7Qka5_R6GERCgrtNEFuYCaMM5JGfjPcbx0Xw,215108
22
22
  ommlds/backends/cerebras/_marshal.py,sha256=KqhIymYaVUJ5-XubSHLDiEagK_jmp-738mbduazlEE8,658
23
- ommlds/backends/cerebras/protocol.py,sha256=nbgDYKHyjxbzFgK1ot4VU5fytrvOdOS6XX8bPspqfyY,8789
23
+ ommlds/backends/cerebras/clients.py,sha256=n1zvVPvk5lJ42JMSSU3EFGYUJ9Az-YAOU6DTGNsJ8_M,152
24
+ ommlds/backends/cerebras/protocol.py,sha256=nrYZ6SfU1lK_K92hXOQkjsaJxzEnInQs6T7YUXPvPnc,8785
24
25
  ommlds/backends/google/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
26
  ommlds/backends/google/protocol/__init__.py,sha256=5fguMBg9qGfTEvEBCgjFbDBfRzaiRdil6d1DakJGvPY,214
26
27
  ommlds/backends/google/protocol/_dataclasses.py,sha256=KECT4r6gBPVtiEvb1y0kj_HLeH-Y8Rgp_a5CTbd4Q14,304996
@@ -108,7 +109,7 @@ ommlds/cli/__main__.py,sha256=1ffCb0fcUOJMzxROJmJRXQ8PSOVYv7KrcuBtT95cf0c,140
108
109
  ommlds/cli/_dataclasses.py,sha256=UO9UdIEGJkqfUhpS3IaISxwyPX5aNJgMarfpUjY3f38,180545
109
110
  ommlds/cli/asyncs.py,sha256=NAMzzaZq7ORjlbbBB_Y9vcM9qoBpGf4VJNtl_3p_8G4,629
110
111
  ommlds/cli/inject.py,sha256=Bt-T-vQIbp8vh6q21Tt3wDztFZ9FPxNhH2ocrAfjArE,815
111
- ommlds/cli/main.py,sha256=n_13EimSCt2x9wkn4tULk9gNOvuCHuHeDcuEYtrcUgQ,11172
112
+ ommlds/cli/main.py,sha256=qFi7TqkdUYlWLuj1g0-1g9aSMniop2fTxfNktF8pTt0,11488
112
113
  ommlds/cli/secrets.py,sha256=wwtcKjDH34wywfs5zixx3TMbWXCvlZj-PwQoLMM7Fqs,473
113
114
  ommlds/cli/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
115
  ommlds/cli/backends/catalog.py,sha256=snQSdUyFiNJhvzVRShBqqp1bZpZlmoKvonypNMZz3HI,3002
@@ -213,7 +214,7 @@ ommlds/cli/sessions/chat/interfaces/bare/interactive.py,sha256=ZnYoePvXtUbhkDQ0j
213
214
  ommlds/cli/sessions/chat/interfaces/bare/oneshot.py,sha256=b758OIa0gf9I_0UdxYJ6re-g8-8xndgr3R0OotUOsmc,387
214
215
  ommlds/cli/sessions/chat/interfaces/bare/tools.py,sha256=_UsuoXLIvfpFP_We5DBBlhm6rwB3_cFA3lmFvpG9b-A,824
215
216
  ommlds/cli/sessions/chat/interfaces/textual/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
216
- ommlds/cli/sessions/chat/interfaces/textual/app.py,sha256=mmTqrQanXKiKr7TekiyJ72Zd4ircENcbjqFmzTMRRtU,10837
217
+ ommlds/cli/sessions/chat/interfaces/textual/app.py,sha256=glO32FiPn4T1nLXBOe2QpTwkFv0yGKchGZQHGFQVaOw,12614
217
218
  ommlds/cli/sessions/chat/interfaces/textual/configs.py,sha256=-pvG2_Uai70ohDfK4Tt8yaHnvdCs10_gaoQkr-CsOqA,213
218
219
  ommlds/cli/sessions/chat/interfaces/textual/facades.py,sha256=zXVG7DKVl-Xtdc893O_yktHCMvM0do6hLesMd8hbqeo,411
219
220
  ommlds/cli/sessions/chat/interfaces/textual/inject.py,sha256=eBhFVZ2VmQdoTPSZvi2OSkZ-fX8Mw2TKo28bHZeACJY,3056
@@ -223,10 +224,10 @@ ommlds/cli/sessions/chat/interfaces/textual/tools.py,sha256=KVlUmIyzqUuOHMzB9ZXG
223
224
  ommlds/cli/sessions/chat/interfaces/textual/styles/__init__.py,sha256=7_U5oUjwegOymeWgt6nLpFfWfjGTrlWL8m4Au8MsaFE,542
224
225
  ommlds/cli/sessions/chat/interfaces/textual/styles/input.tcss,sha256=9LLwsuYjY8y1XTEnBy_ADKzpRaPPvpe-mNHhiAjEIdo,640
225
226
  ommlds/cli/sessions/chat/interfaces/textual/styles/markdown.tcss,sha256=KCKlgt_EEjHVZSTwP_w2YMrR6mURLYVryOwOziAFlTw,105
226
- ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss,sha256=QBpHJkBT76OkT8srUwhZOt0ZT5ZCzXuM4l8P9hP9ALw,1665
227
+ ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss,sha256=tl0ZPnYY3jsumj_Y_AFaA1Vbz7AvgWC7xMuS-JOAPEk,1820
227
228
  ommlds/cli/sessions/chat/interfaces/textual/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
228
229
  ommlds/cli/sessions/chat/interfaces/textual/widgets/input.py,sha256=MMONcOi3Aq8ZzmvJn6tHNPbfV3EOol25fABxtW1h--E,1827
229
- ommlds/cli/sessions/chat/interfaces/textual/widgets/messages.py,sha256=hZcentzdznaE_YPId1KsW4k8mAqsSu5zwMdTA5tIj5s,5472
230
+ ommlds/cli/sessions/chat/interfaces/textual/widgets/messages.py,sha256=_xu24596FT0MZMWOdE0-2SkPF_na_J6lG35CstKCI94,5614
230
231
  ommlds/cli/sessions/completion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
231
232
  ommlds/cli/sessions/completion/configs.py,sha256=jOtadH46Esx6CztbQazAgIx9Tt5uuu4pGPov3G3O5Ac,286
232
233
  ommlds/cli/sessions/completion/inject.py,sha256=oWRS2D4d-mdCwi7jT_Is462k1UBlCruz4nrUeT9xedY,848
@@ -270,10 +271,10 @@ ommlds/minichain/backends/impls/anthropic/names.py,sha256=t70dOuzqpSu9LE_MxfOl2m
270
271
  ommlds/minichain/backends/impls/anthropic/protocol.py,sha256=eMqkl7ML5btqJ27_9l6RY2zdTMsQe0k3Kn_keNq0-Mk,3337
271
272
  ommlds/minichain/backends/impls/anthropic/stream.py,sha256=86nYXeJGwz86n_PXZ-2Azli7FTtgBZPYw8eqO6d3LbQ,8803
272
273
  ommlds/minichain/backends/impls/cerebras/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
273
- ommlds/minichain/backends/impls/cerebras/chat.py,sha256=FbwXrOMbHIIzO8gLZsyI3faYJYFYWPcxZTMxcpIaB4Y,2858
274
+ ommlds/minichain/backends/impls/cerebras/chat.py,sha256=chnwRUpDJPjm5FwAFOdMbr5Ze0WFkgbuGusLev6eSPU,2964
274
275
  ommlds/minichain/backends/impls/cerebras/names.py,sha256=g0Chpq80JIha4xdV7coxJblLgckKY2bNfLnn1pe_6zk,874
275
276
  ommlds/minichain/backends/impls/cerebras/protocol.py,sha256=9ldK0_XM7il0JX3jjcLL8svBiRANrgY65V1Dq4ANevw,5268
276
- ommlds/minichain/backends/impls/cerebras/stream.py,sha256=o-GUC3y34HzfP0ibOndPe1eSCkgv0J9I0uZqkbR8kVo,3956
277
+ ommlds/minichain/backends/impls/cerebras/stream.py,sha256=4r0hcE-vEeV-jUkMasgNQ4DD0n_HzlFkhWFjk5jLebQ,4062
277
278
  ommlds/minichain/backends/impls/duckduckgo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
278
279
  ommlds/minichain/backends/impls/duckduckgo/search.py,sha256=HA5UriBVvNw6-6vmeYJsm83LxsFsksLtzFxj-kdzoPE,1010
279
280
  ommlds/minichain/backends/impls/dummy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -525,9 +526,9 @@ ommlds/wiki/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
525
526
  ommlds/wiki/utils/io.py,sha256=UKgDJGtmpnWvIqVd2mJc2QNPOqlToEY1GEveNp6_pMo,7088
526
527
  ommlds/wiki/utils/progress.py,sha256=EhvKcMFYtsarCQhIahlO6f0SboyAKP3UwUyrnVnP-Vk,3222
527
528
  ommlds/wiki/utils/xml.py,sha256=sNJNkZ9rT8B-kJMO6bRz8J1USy4fyPx0m2PwTX7vxYY,3846
528
- ommlds-0.0.0.dev511.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
529
- ommlds-0.0.0.dev511.dist-info/METADATA,sha256=2hVXzjn7T4pux2qqxd7ejIadMtYSziF3lBS29UhKM-Y,3497
530
- ommlds-0.0.0.dev511.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
531
- ommlds-0.0.0.dev511.dist-info/entry_points.txt,sha256=Z5YWtX7ClfiCKdW-dd_CSVvM0h4yQpJPi-2G3q6gNFo,35
532
- ommlds-0.0.0.dev511.dist-info/top_level.txt,sha256=Rbnk5d5wi58vnAXx13WFZqdQ4VX8hBCS2hEL3WeXOhY,7
533
- ommlds-0.0.0.dev511.dist-info/RECORD,,
529
+ ommlds-0.0.0.dev513.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
530
+ ommlds-0.0.0.dev513.dist-info/METADATA,sha256=hjYsfB2_iBou440IpGgVuJC6zvpRLoJ8UQ79M5VCBhE,3602
531
+ ommlds-0.0.0.dev513.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
532
+ ommlds-0.0.0.dev513.dist-info/entry_points.txt,sha256=Z5YWtX7ClfiCKdW-dd_CSVvM0h4yQpJPi-2G3q6gNFo,35
533
+ ommlds-0.0.0.dev513.dist-info/top_level.txt,sha256=Rbnk5d5wi58vnAXx13WFZqdQ4VX8hBCS2hEL3WeXOhY,7
534
+ ommlds-0.0.0.dev513.dist-info/RECORD,,