ommlds 0.0.0.dev491__py3-none-any.whl → 0.0.0.dev492__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.
@@ -459,7 +459,7 @@
459
459
  "module": ".minichain.backends.impls.ollama.chat",
460
460
  "attr": null,
461
461
  "file": "ommlds/minichain/backends/impls/ollama/chat.py",
462
- "line": 35,
462
+ "line": 61,
463
463
  "value": {
464
464
  "!.minichain.backends.strings.manifests.BackendStringsManifest": {
465
465
  "service_cls_names": [
@@ -475,7 +475,7 @@
475
475
  "module": ".minichain.backends.impls.ollama.chat",
476
476
  "attr": null,
477
477
  "file": "ommlds/minichain/backends/impls/ollama/chat.py",
478
- "line": 68,
478
+ "line": 94,
479
479
  "value": {
480
480
  "!.minichain.registries.manifests.RegistryManifest": {
481
481
  "module": "ommlds.minichain.backends.impls.ollama.chat",
@@ -490,7 +490,7 @@
490
490
  "module": ".minichain.backends.impls.ollama.chat",
491
491
  "attr": null,
492
492
  "file": "ommlds/minichain/backends/impls/ollama/chat.py",
493
- "line": 111,
493
+ "line": 137,
494
494
  "value": {
495
495
  "!.minichain.registries.manifests.RegistryManifest": {
496
496
  "module": "ommlds.minichain.backends.impls.ollama.chat",
@@ -550,7 +550,7 @@
550
550
  "module": ".minichain.backends.impls.openai.names",
551
551
  "attr": "_CHAT_BACKEND_STRINGS_MANIFEST",
552
552
  "file": "ommlds/minichain/backends/impls/openai/names.py",
553
- "line": 65,
553
+ "line": 67,
554
554
  "value": {
555
555
  "!.minichain.backends.strings.manifests.BackendStringsManifest": {
556
556
  "service_cls_names": [
@@ -575,6 +575,7 @@
575
575
  "gpt-5-mini": null,
576
576
  "gpt-5-nano": null,
577
577
  "gpt-5.1": null,
578
+ "gpt-5.2": null,
578
579
  "gpt3.5-turbo": "gpt-3.5-turbo",
579
580
  "gpt3.5-turbo-instruct": "gpt-3.5-turbo-instruct",
580
581
  "gpt4": "gpt-4",
@@ -589,7 +590,8 @@
589
590
  "gpt5-mini": "gpt-5-mini",
590
591
  "gpt5-nano": "gpt-5-nano",
591
592
  "gpt5.1": "gpt-5.1",
592
- "gpt": "gpt-5.1",
593
+ "gpt5.2": "gpt-5.2",
594
+ "gpt": "gpt-5.2",
593
595
  "gpt-mini": "gpt-5-mini",
594
596
  "o3": null,
595
597
  "o3-mini": null,
@@ -604,7 +606,7 @@
604
606
  "module": ".minichain.backends.impls.openai.names",
605
607
  "attr": "_COMPLETION_BACKEND_STRINGS_MANIFEST",
606
608
  "file": "ommlds/minichain/backends/impls/openai/names.py",
607
- "line": 79,
609
+ "line": 81,
608
610
  "value": {
609
611
  "!.minichain.backends.strings.manifests.BackendStringsManifest": {
610
612
  "service_cls_names": [
@@ -619,7 +621,7 @@
619
621
  "module": ".minichain.backends.impls.openai.names",
620
622
  "attr": "_EMBEDDING_BACKEND_STRINGS_MANIFEST",
621
623
  "file": "ommlds/minichain/backends/impls/openai/names.py",
622
- "line": 91,
624
+ "line": 93,
623
625
  "value": {
624
626
  "!.minichain.backends.strings.manifests.BackendStringsManifest": {
625
627
  "service_cls_names": [
ommlds/cli/main.py CHANGED
@@ -36,7 +36,8 @@ def _process_main_extra_args(args: ap.Namespace) -> None:
36
36
  logs.configure_standard_logging('DEBUG')
37
37
  else:
38
38
  logs.configure_standard_logging('INFO')
39
- logs.silence_noisy_loggers()
39
+
40
+ logs.silence_noisy_loggers()
40
41
 
41
42
 
42
43
  ##
@@ -3,6 +3,8 @@ TODO:
3
3
  - lifecycles
4
4
  - StreamService
5
5
  """
6
+ from omlish import lang
7
+
6
8
  from ..... import minichain as mc
7
9
  from .ai.types import AiChatGenerator
8
10
  from .events.manager import ChatEventsManager
@@ -15,6 +17,10 @@ from .state.types import ChatStateManager
15
17
  ##
16
18
 
17
19
 
20
+ class ChatDriverGetter(lang.Func0['ChatDriver']):
21
+ pass
22
+
23
+
18
24
  class ChatDriver:
19
25
  def __init__(
20
26
  self,
@@ -53,7 +53,7 @@ def bind_driver(cfg: DriverConfig) -> inj.Elements:
53
53
  els.extend([
54
54
  inj.bind(_driver.ChatDriver, singleton=True),
55
55
 
56
- inj.bind_late(_driver.ChatDriver),
56
+ inj.bind_late(_driver.ChatDriver, _driver.ChatDriverGetter),
57
57
  ])
58
58
 
59
59
  #
@@ -29,12 +29,12 @@ def bind_user(cfg: UserConfig = UserConfig()) -> inj.Elements:
29
29
  )))
30
30
 
31
31
  if cfg.initial_user_content is not None:
32
- async def add_initial_user_content(ca: '_driver.ChatDriver') -> None:
33
- await ca.send_user_messages([mc.UserMessage(cfg.initial_user_content)])
32
+ async def add_initial_user_content(cd: '_driver.ChatDriver') -> None:
33
+ await cd.send_user_messages([mc.UserMessage(cfg.initial_user_content)])
34
34
 
35
35
  els.append(phase_callbacks().bind_item(to_fn=inj.KwargsTarget.of(
36
- lambda ca: ChatPhaseCallback(ChatPhase.STARTED, lambda: add_initial_user_content(ca())),
37
- ca=inj.Late[_driver.ChatDriver],
36
+ lambda cdg: ChatPhaseCallback(ChatPhase.STARTED, lambda: add_initial_user_content(cdg())),
37
+ cdg=_driver.ChatDriverGetter,
38
38
  )))
39
39
 
40
40
  return inj.as_elements(*els)
@@ -36,6 +36,12 @@ class InteractiveBareChatInterface(ChatInterface):
36
36
  except EOFError:
37
37
  break
38
38
 
39
+ print()
40
+ print('<')
41
+ print()
42
+
39
43
  await self._driver.send_user_messages([mc.UserMessage(s)])
40
44
 
45
+ print()
46
+
41
47
  await self._driver.stop()
@@ -16,7 +16,7 @@ def bind_interface(cfg: InterfaceConfig = InterfaceConfig()) -> inj.Elements:
16
16
  els: list[inj.Elemental] = []
17
17
 
18
18
  if cfg.use_textual:
19
- els.append(_textual.bind_textual())
19
+ els.append(_textual.bind_textual(cfg))
20
20
 
21
21
  else:
22
22
  els.append(_bare.bind_bare(cfg))
@@ -3,6 +3,8 @@ import typing as ta
3
3
 
4
4
  from omdev.tui import textual as tx
5
5
  from omlish import check
6
+ from omlish import lang
7
+ from omlish.logs import all as logs
6
8
 
7
9
  from ...... import minichain as mc
8
10
  from ...drivers.driver import ChatDriver
@@ -14,10 +16,14 @@ from .widgets.input import InputTextArea
14
16
  from .widgets.messages import AiMessage
15
17
  from .widgets.messages import StaticAiMessage
16
18
  from .widgets.messages import StreamAiMessage
19
+ from .widgets.messages import ToolConfirmationMessage
17
20
  from .widgets.messages import UserMessage
18
21
  from .widgets.messages import WelcomeMessage
19
22
 
20
23
 
24
+ log, alog = logs.get_module_loggers(globals())
25
+
26
+
21
27
  ##
22
28
 
23
29
 
@@ -27,19 +33,27 @@ ChatDriverEventQueue = ta.NewType('ChatDriverEventQueue', asyncio.Queue)
27
33
  ##
28
34
 
29
35
 
36
+ class ChatAppGetter(lang.CachedFunc0['ChatApp']):
37
+ pass
38
+
39
+
30
40
  class ChatApp(tx.App):
31
41
  ENABLE_COMMAND_PALETTE: ta.ClassVar[bool] = False
32
42
 
33
43
  def __init__(
34
44
  self,
35
45
  *,
36
- driver: ChatDriver,
37
- event_queue: ChatDriverEventQueue,
46
+ chat_driver: ChatDriver,
47
+ chat_driver_event_queue: ChatDriverEventQueue,
38
48
  ) -> None:
39
49
  super().__init__()
40
50
 
41
- self._chat_driver = driver
42
- self._event_queue = event_queue
51
+ tx.setup_app_devtools(self, port=41932)
52
+
53
+ self._chat_driver = chat_driver
54
+ self._chat_driver_event_queue = chat_driver_event_queue
55
+
56
+ self._chat_driver_action_queue: asyncio.Queue[ta.Any] = asyncio.Queue()
43
57
 
44
58
  def get_driver_class(self) -> type[tx.Driver]:
45
59
  return tx.get_pending_writes_driver_class(super().get_driver_class())
@@ -49,8 +63,7 @@ class ChatApp(tx.App):
49
63
  #
50
64
 
51
65
  def compose(self) -> tx.ComposeResult:
52
- with tx.VerticalScroll(id='messages-scroll'):
53
- yield tx.Static(id='messages-container')
66
+ yield tx.VerticalScroll(id='messages-container')
54
67
 
55
68
  yield InputOuter(id='input-outer')
56
69
 
@@ -59,22 +72,19 @@ class ChatApp(tx.App):
59
72
  def _get_input_text_area(self) -> InputTextArea:
60
73
  return self.query_one('#input', InputTextArea)
61
74
 
62
- def _get_messages_scroll(self) -> tx.VerticalScroll:
63
- return self.query_one('#messages-scroll', tx.VerticalScroll)
64
-
65
- def _get_messages_container(self) -> tx.Static:
66
- return self.query_one('#messages-container', tx.Static)
75
+ def _get_messages_container(self) -> tx.VerticalScroll:
76
+ return self.query_one('#messages-container', tx.VerticalScroll)
67
77
 
68
78
  #
69
79
 
70
80
  def _is_messages_at_bottom(self, threshold: int = 3) -> bool:
71
- return (ms := self._get_messages_scroll()).scroll_y >= (ms.max_scroll_y - threshold)
81
+ return (ms := self._get_messages_container()).scroll_y >= (ms.max_scroll_y - threshold)
72
82
 
73
83
  def _scroll_messages_to_bottom(self) -> None:
74
- self._get_messages_scroll().scroll_end(animate=False)
84
+ self._get_messages_container().scroll_end(animate=False)
75
85
 
76
86
  def _anchor_messages(self) -> None:
77
- if (ms := self._get_messages_scroll()).max_scroll_y:
87
+ if (ms := self._get_messages_container()).max_scroll_y:
78
88
  ms.anchor()
79
89
 
80
90
  #
@@ -102,7 +112,7 @@ class ChatApp(tx.App):
102
112
 
103
113
  await sam.append_content(content)
104
114
 
105
- self.call_after_refresh(lambda: self._get_messages_container().scroll_end(animate=False))
115
+ self.call_after_refresh(self._scroll_messages_to_bottom)
106
116
 
107
117
  if was_at_bottom:
108
118
  self.call_after_refresh(self._anchor_messages)
@@ -116,7 +126,7 @@ class ChatApp(tx.App):
116
126
  msg_ctr = self._get_messages_container()
117
127
 
118
128
  for msg in [*(self._pending_mount_messages or []), *messages]:
119
- if isinstance(msg, AiMessage):
129
+ if isinstance(msg, (AiMessage, ToolConfirmationMessage)):
120
130
  await self._finalize_stream_ai_message()
121
131
 
122
132
  await msg_ctr.mount(msg)
@@ -127,21 +137,24 @@ class ChatApp(tx.App):
127
137
 
128
138
  self._pending_mount_messages = None
129
139
 
130
- self.call_after_refresh(lambda: msg_ctr.scroll_end(animate=False))
140
+ self.call_after_refresh(self._scroll_messages_to_bottom)
131
141
 
132
142
  if was_at_bottom:
133
143
  self.call_after_refresh(self._anchor_messages)
134
144
 
135
145
  #
136
146
 
137
- _event_queue_task: asyncio.Task[None] | None = None
147
+ _chat_driver_event_task: asyncio.Task[None] | None = None
138
148
 
139
- async def _event_queue_task_main(self) -> None:
149
+ @logs.async_exception_logging(alog)
150
+ async def _chat_driver_event_task_main(self) -> None:
140
151
  while True:
141
- ev = await self._event_queue.get()
152
+ ev = await self._chat_driver_event_queue.get()
142
153
  if ev is None:
143
154
  break
144
155
 
156
+ await alog.debug(lambda: f'Got chat driver event: {ev!r}')
157
+
145
158
  if isinstance(ev, AiMessagesChatEvent):
146
159
  wx: list[tx.Widget] = []
147
160
 
@@ -159,35 +172,46 @@ class ChatApp(tx.App):
159
172
  self.call_later(self._mount_messages)
160
173
 
161
174
  elif isinstance(ev, AiDeltaChatEvent):
162
- cd = check.isinstance(ev.delta, mc.ContentAiDelta)
163
- cc = check.isinstance(cd.c, str)
164
- self.call_later(self. _append_stream_ai_message_content, cc)
175
+ if isinstance(ev.delta, mc.ContentAiDelta):
176
+ cc = check.isinstance(ev.delta.c, str)
177
+ self.call_later(self._append_stream_ai_message_content, cc)
178
+
179
+ elif isinstance(ev.delta, mc.ToolUseAiDelta):
180
+ pass
165
181
 
166
182
  #
167
183
 
168
- # def _schedule_after_refresh(self) -> None:
169
- # self.call_after_refresh(self._after_refresh)
184
+ _chat_driver_action_task: asyncio.Task[None] | None = None
170
185
 
171
- # def _after_refresh(self) -> None:
172
- # self.after_repaint()
173
- #
174
- # self._schedule_after_refresh()
186
+ @logs.async_exception_logging(alog)
187
+ async def _chat_driver_action_task_main(self) -> None:
188
+ while True:
189
+ ac = await self._chat_driver_action_queue.get()
190
+ if ac is None:
191
+ break
175
192
 
176
- # def after_repaint(self) -> None:
177
- # # from omdev.tui.textual.debug.dominfo import inspect_dom_node # noqa
178
- #
179
- # pass
193
+ await alog.debug(lambda: f'Got chat driver action: {ac!r}')
194
+
195
+ if isinstance(ac, mc.UserMessage):
196
+ try:
197
+ await self._chat_driver.send_user_messages([ac])
198
+ except Exception as e: # noqa
199
+ raise
200
+
201
+ else:
202
+ raise TypeError(ac) # noqa
180
203
 
181
204
  #
182
205
 
183
206
  async def on_mount(self) -> None:
184
- # self._schedule_after_refresh()
185
-
186
- check.state(self._event_queue_task is None)
187
- self._event_queue_task = asyncio.create_task(self._event_queue_task_main())
207
+ check.state(self._chat_driver_event_task is None)
208
+ self._chat_driver_event_task = asyncio.create_task(self._chat_driver_event_task_main())
188
209
 
189
210
  await self._chat_driver.start()
190
211
 
212
+ check.state(self._chat_driver_action_task is None)
213
+ self._chat_driver_action_task = asyncio.create_task(self._chat_driver_action_task_main())
214
+
191
215
  self._get_input_text_area().focus()
192
216
 
193
217
  await self._mount_messages(
@@ -197,12 +221,17 @@ class ChatApp(tx.App):
197
221
  )
198
222
 
199
223
  async def on_unmount(self) -> None:
224
+ if (cdt := self._chat_driver_event_task) is not None:
225
+ await self._chat_driver_event_queue.put(None)
226
+ await cdt
227
+
200
228
  await self._chat_driver.stop()
201
229
 
202
- if (eqt := self._event_queue_task) is not None:
203
- await self._event_queue.put(None)
204
- await eqt
230
+ if (cet := self._chat_driver_event_task) is not None:
231
+ await self._chat_driver_event_queue.put(None)
232
+ await cet
205
233
 
234
+ @tx.on(InputTextArea.Submitted)
206
235
  async def on_input_text_area_submitted(self, event: InputTextArea.Submitted) -> None:
207
236
  self._get_input_text_area().clear()
208
237
 
@@ -214,4 +243,20 @@ class ChatApp(tx.App):
214
243
  ),
215
244
  )
216
245
 
217
- await self._chat_driver.send_user_messages([mc.UserMessage(event.text)])
246
+ await self._chat_driver_action_queue.put(mc.UserMessage(event.text))
247
+
248
+ #
249
+
250
+ async def confirm_tool_use(self, message: str) -> bool:
251
+ fut: asyncio.Future[bool] = asyncio.get_running_loop().create_future()
252
+
253
+ tcm = ToolConfirmationMessage(message, fut)
254
+
255
+ async def inner() -> None:
256
+ await self._mount_messages(tcm)
257
+
258
+ self.call_later(inner)
259
+
260
+ ret = await fut
261
+
262
+ return ret
@@ -10,13 +10,13 @@ from omlish import lang
10
10
  from ...drivers.events.injection import event_callbacks
11
11
  from ..base import ChatInterface
12
12
  from ..configs import InterfaceConfig
13
- from .app import ChatApp
14
- from .app import ChatDriverEventQueue
15
- from .interface import TextualChatInterface
16
13
 
17
14
 
18
15
  with lang.auto_proxy_import(globals()):
19
16
  from ...drivers.tools import confirmation as _tools_confirmation
17
+ from . import app as _app
18
+ from . import interface as _interface
19
+ from . import tools as _tools
20
20
 
21
21
 
22
22
  ##
@@ -24,23 +24,25 @@ with lang.auto_proxy_import(globals()):
24
24
 
25
25
  def bind_textual(cfg: InterfaceConfig = InterfaceConfig()) -> inj.Elements:
26
26
  els: list[inj.Elemental] = [
27
- inj.bind(ChatInterface, to_ctor=TextualChatInterface, singleton=True),
27
+ inj.bind(ChatInterface, to_ctor=_interface.TextualChatInterface, singleton=True),
28
28
  ]
29
29
 
30
30
  #
31
31
 
32
32
  els.extend([
33
- inj.bind(ChatApp, singleton=True),
33
+ inj.bind(_app.ChatApp, singleton=True),
34
+
35
+ inj.bind_late(_app.ChatApp, _app.ChatAppGetter),
34
36
  ])
35
37
 
36
38
  #
37
39
 
38
40
  els.extend([
39
- inj.bind(ChatDriverEventQueue, to_const=asyncio.Queue()),
41
+ inj.bind(_app.ChatDriverEventQueue, to_const=asyncio.Queue()),
40
42
 
41
43
  event_callbacks().bind_item(to_fn=inj.KwargsTarget.of(
42
44
  lambda eq: lambda ev: eq.put(ev),
43
- eq=ChatDriverEventQueue,
45
+ eq=_app.ChatDriverEventQueue,
44
46
  )),
45
47
  ])
46
48
 
@@ -55,12 +57,11 @@ def bind_textual(cfg: InterfaceConfig = InterfaceConfig()) -> inj.Elements:
55
57
  ))
56
58
 
57
59
  else:
58
- # els.append(inj.bind(
59
- # _tools_confirmation.ToolExecutionConfirmation,
60
- # to_ctor=_tools.InteractiveToolExecutionConfirmation,
61
- # singleton=True,
62
- # ))
63
- raise NotImplementedError
60
+ els.append(inj.bind(
61
+ _tools_confirmation.ToolExecutionConfirmation,
62
+ to_ctor=_tools.ChatAppToolExecutionConfirmation,
63
+ singleton=True,
64
+ ))
64
65
 
65
66
  #
66
67
 
@@ -1,7 +1,90 @@
1
+ import inspect
2
+ import logging
3
+ import typing as ta
4
+
5
+ from omdev.tui import textual as tx
6
+
1
7
  from ..base import ChatInterface
2
8
  from .app import ChatApp
3
9
 
4
10
 
11
+ if ta.TYPE_CHECKING:
12
+ from textual_dev.client import DevtoolsClient
13
+
14
+
15
+ ##
16
+
17
+
18
+ def _translate_log_level(level: int) -> tuple['tx.LogGroup', 'tx.LogVerbosity']:
19
+ if level >= logging.ERROR:
20
+ return (tx.LogGroup.ERROR, tx.LogVerbosity.HIGH)
21
+ elif level >= logging.WARNING:
22
+ return (tx.LogGroup.ERROR, tx.LogVerbosity.HIGH)
23
+ elif level >= logging.INFO:
24
+ return (tx.LogGroup.INFO, tx.LogVerbosity.NORMAL)
25
+ elif level >= logging.DEBUG:
26
+ return (tx.LogGroup.DEBUG, tx.LogVerbosity.NORMAL)
27
+ else:
28
+ return (tx.LogGroup.UNDEFINED, tx.LogVerbosity.NORMAL)
29
+
30
+
31
+ class _HackLoggingHandler(logging.Handler):
32
+ """
33
+ TODO:
34
+ - reify caller from LogContextInfos
35
+ - queue worker, this blocks the asyncio thread lol
36
+ - move to omdev.tui.textual obviously
37
+ """
38
+
39
+ def __init__(self, devtools: ta.Optional['DevtoolsClient']) -> None:
40
+ super().__init__()
41
+
42
+ self._devtools = devtools
43
+
44
+ def emit(self, record: logging.LogRecord) -> None:
45
+ if (devtools := self._devtools) is not None and devtools.is_connected:
46
+ from textual_dev.client import DevtoolsLog
47
+
48
+ msg = self.format(record)
49
+
50
+ caller = inspect.Traceback(
51
+ filename=record.filename,
52
+ lineno=record.lineno,
53
+ function=record.funcName,
54
+ code_context=None,
55
+ index=None,
56
+ )
57
+
58
+ group, verbosity = _translate_log_level(record.levelno)
59
+
60
+ devtools.log(
61
+ DevtoolsLog(
62
+ msg,
63
+ caller=caller,
64
+ ),
65
+ group=group,
66
+ verbosity=verbosity,
67
+ )
68
+
69
+
70
+ def _hack_loggers(devtools: ta.Optional['DevtoolsClient']) -> None:
71
+ from omlish.logs.std.standard import _locking_logging_module_lock # noqa
72
+ from omlish.logs.std.standard import StandardConfiguredLoggingHandler
73
+
74
+ with _locking_logging_module_lock():
75
+ std_handler = next((h for h in logging.root.handlers if isinstance(h, StandardConfiguredLoggingHandler)), None)
76
+
77
+ hack_handler = _HackLoggingHandler(devtools)
78
+
79
+ if std_handler is not None:
80
+ hack_handler.setFormatter(std_handler.formatter)
81
+
82
+ for std_filter in std_handler.filters:
83
+ hack_handler.addFilter(std_filter)
84
+
85
+ logging.root.handlers = [hack_handler]
86
+
87
+
5
88
  ##
6
89
 
7
90
 
@@ -16,4 +99,6 @@ class TextualChatInterface(ChatInterface):
16
99
  self._app = app
17
100
 
18
101
  async def run(self) -> None:
102
+ _hack_loggers(self._app.devtools)
103
+
19
104
  await self._app.run_async()
@@ -1,13 +1,15 @@
1
1
  #input-outer {
2
2
  width: 100%;
3
3
  height: auto;
4
+
5
+ background: $background-darken-3;
4
6
  }
5
7
 
6
8
  #input-vertical {
7
9
  width: 100%;
8
10
  height: auto;
9
11
 
10
- margin: 0 2 1 2;
12
+ margin: 0 1 1 1;
11
13
 
12
14
  padding: 0;
13
15
  }
@@ -1,33 +1,47 @@
1
1
  /* Container */
2
2
 
3
- #messages-scroll {
3
+ #messages-container {
4
4
  width: 100%;
5
5
  height: 1fr;
6
6
 
7
- padding: 0 2 0 2;
7
+ scrollbar-gutter: stable;
8
+
9
+ background: $background-darken-3;
10
+
11
+ text-align: left;
12
+
13
+ scrollbar-size: 1 1;
8
14
  }
9
15
 
10
- #messages-container {
11
- width: 100%;
16
+
17
+ /* Base */
18
+
19
+ .message {
20
+ width: 1fr;
12
21
  height: auto;
13
22
 
14
- margin-top: 1;
15
- margin-bottom: 0;
23
+ margin: 1 0 0 0;
24
+
25
+ padding-right: 1;
16
26
 
17
27
  layout: stream;
18
- text-align: left;
19
28
  }
20
29
 
21
30
 
22
31
  /* Welcome */
23
32
 
24
33
  .welcome-message {
25
- margin: 1;
34
+ padding: 1 2 1 1;
26
35
 
27
36
  border: round;
37
+ }
28
38
 
29
- padding: 1;
39
+ .welcome-message-outer {
40
+ width: 1fr;
41
+ height: auto;
42
+ }
30
43
 
44
+ .welcome-message-content {
31
45
  text-align: center;
32
46
  }
33
47
 
@@ -35,14 +49,10 @@
35
49
  /* User */
36
50
 
37
51
  .user-message {
38
- width: 100%;
39
- height: auto;
40
-
41
- margin-top: 1;
42
52
  }
43
53
 
44
54
  .user-message-outer {
45
- width: 100%;
55
+ width: 1fr;
46
56
  height: auto;
47
57
  }
48
58
 
@@ -57,7 +67,7 @@
57
67
  }
58
68
 
59
69
  .user-message-inner {
60
- width: 100%;
70
+ width: 1fr;
61
71
  height: auto;
62
72
  }
63
73
 
@@ -65,14 +75,10 @@
65
75
  /* Ai */
66
76
 
67
77
  .ai-message {
68
- width: 100%;
69
- height: auto;
70
-
71
- margin-top: 1;
72
78
  }
73
79
 
74
80
  .ai-message-outer {
75
- width: 100%;
81
+ width: 1fr;
76
82
  height: auto;
77
83
 
78
84
  align: left top;
@@ -89,7 +95,7 @@
89
95
  }
90
96
 
91
97
  .ai-message-inner {
92
- width: 100%;
98
+ width: 1fr;
93
99
  height: auto;
94
100
 
95
101
  padding: 0;
@@ -102,3 +108,48 @@
102
108
  padding: 0;
103
109
  }
104
110
  }
111
+
112
+
113
+ /* Tool Confirmation */
114
+
115
+ .tool-confirmation-message {
116
+ }
117
+
118
+ .tool-confirmation-message-outer {
119
+ width: 1fr;
120
+ height: auto;
121
+
122
+ align: left top;
123
+ }
124
+
125
+ .tool-confirmation-message-glyph {
126
+ width: auto;
127
+ height: auto;
128
+
129
+ background: transparent;
130
+ color: $primary;
131
+
132
+ text-style: bold;
133
+ }
134
+
135
+ .tool-confirmation-message-inner {
136
+ width: 1fr;
137
+ height: auto;
138
+
139
+ padding: 1;
140
+ }
141
+
142
+ .tool-confirmation-message-inner-open {
143
+ background: $warning-lighten-3 15%;
144
+ }
145
+
146
+ .tool-confirmation-message-inner-closed {
147
+ }
148
+
149
+ .tool-confirmation-message-content {
150
+ background: $background;
151
+ }
152
+
153
+ .tool-confirmation-message-controls {
154
+ margin-top: 1;
155
+ }
@@ -0,0 +1,37 @@
1
+ from omlish.formats import json
2
+
3
+ from ...... import minichain as mc
4
+ from ...drivers.tools.confirmation import ToolExecutionConfirmation
5
+ from ...drivers.tools.confirmation import ToolExecutionRequestDeniedError
6
+ from .app import ChatAppGetter
7
+
8
+
9
+ ##
10
+
11
+
12
+ class ChatAppToolExecutionConfirmation(ToolExecutionConfirmation):
13
+ def __init__(
14
+ self,
15
+ *,
16
+ app: ChatAppGetter,
17
+ ) -> None:
18
+ super().__init__()
19
+
20
+ self._app = app
21
+
22
+ async def confirm_tool_execution_or_raise(
23
+ self,
24
+ use: 'mc.ToolUse',
25
+ entry: 'mc.ToolCatalogEntry',
26
+ ) -> None:
27
+ tr_dct = dict(
28
+ id=use.id,
29
+ name=entry.spec.name,
30
+ args=use.args,
31
+ # spec=msh.marshal(tce.spec),
32
+ )
33
+
34
+ msg = f'Execute requested tool?\n\n{json.dumps_pretty(tr_dct)}' # noqa
35
+
36
+ if not await self._app().confirm_tool_use(msg):
37
+ raise ToolExecutionRequestDeniedError
@@ -1,4 +1,5 @@
1
1
  import abc
2
+ import asyncio
2
3
  import typing as ta
3
4
 
4
5
  from omdev.tui import textual as tx
@@ -9,7 +10,10 @@ from omlish import lang
9
10
 
10
11
 
11
12
  class Message(tx.Static, lang.Abstract):
12
- pass
13
+ def __init__(self, *args: ta.Any, **kwargs: ta.Any) -> None:
14
+ super().__init__(*args, **kwargs)
15
+
16
+ self.add_class('message')
13
17
 
14
18
 
15
19
  ##
@@ -17,10 +21,16 @@ class Message(tx.Static, lang.Abstract):
17
21
 
18
22
  class WelcomeMessage(Message):
19
23
  def __init__(self, content: str) -> None:
20
- super().__init__(content)
24
+ super().__init__()
21
25
 
22
26
  self.add_class('welcome-message')
23
27
 
28
+ self._content = content
29
+
30
+ def compose(self) -> tx.ComposeResult:
31
+ with tx.Vertical(classes='welcome-message-outer'):
32
+ yield tx.Static(self._content, classes='welcome-message-content')
33
+
24
34
 
25
35
  ##
26
36
 
@@ -112,3 +122,43 @@ class StreamAiMessage(AiMessage):
112
122
 
113
123
  await stream.stop()
114
124
  self._stream_ = None
125
+
126
+
127
+ ##
128
+
129
+
130
+ class ToolConfirmationControls(tx.Static):
131
+ class Allowed(tx.Message):
132
+ pass
133
+
134
+ def compose(self) -> tx.ComposeResult:
135
+ yield tx.Button('Allow', action='allow')
136
+
137
+ def action_allow(self) -> None:
138
+ self.post_message(self.Allowed())
139
+
140
+
141
+ class ToolConfirmationMessage(Message):
142
+ def __init__(self, content: str, fut: asyncio.Future[bool]) -> None:
143
+ super().__init__()
144
+
145
+ self.add_class('tool-confirmation-message')
146
+
147
+ self._content = content
148
+ self._fut = fut
149
+
150
+ def compose(self) -> tx.ComposeResult:
151
+ with tx.Horizontal(classes='tool-confirmation-message-outer'):
152
+ yield tx.Static('? ', classes='tool-confirmation-message-glyph')
153
+ with tx.Vertical(classes='tool-confirmation-message-inner tool-confirmation-message-inner-open'):
154
+ yield tx.Static(self._content, classes='tool-confirmation-message-content')
155
+ yield ToolConfirmationControls(classes='tool-confirmation-message-controls')
156
+
157
+ @tx.on(ToolConfirmationControls.Allowed)
158
+ async def on_allowed(self, event: ToolConfirmationControls.Allowed) -> None:
159
+ inner = self.query_one(tx.Vertical)
160
+ await inner.query_one(ToolConfirmationControls).remove()
161
+ inner.remove_class('tool-confirmation-message-inner-open')
162
+ inner.add_class('tool-confirmation-message-inner-closed')
163
+
164
+ self._fut.set_result(True)
@@ -1,3 +1,29 @@
1
+ """
2
+ devstral-small-2:24b 24277f07f62d 15 GB 15 hours ago
3
+
4
+ dolphin3:latest d5ab9ae8e1f2 4.9 GB 11 months ago (no tools)
5
+
6
+ gemma3:27b a418f5838eaf 17 GB 7 weeks ago (no tools)
7
+ gemma3:4b a2af6cc3eb7f 3.3 GB 7 weeks ago (no tools)
8
+
9
+ llama3.2:1b baf6a787fdff 1.3 GB 13 months ago (too stupid for tools)
10
+ llama3.2:latest a80c4f17acd5 2.0 GB 13 months ago
11
+
12
+ ministral-3:14b 4760c35aeb9d 9.1 GB 11 hours ago
13
+ mistral:latest 6577803aa9a0 4.4 GB 3 seconds ago
14
+
15
+ nemotron-3-nano:30b b725f1117407 24 GB 15 hours ago
16
+
17
+ olmo-3.1:32b-instruct a16b6a5be6cf 19 GB 11 hours ago (no tools)
18
+ olmo-3.1:32b-think 223d4ec84d91 19 GB 11 hours ago (no tools)
19
+
20
+ phi4-mini:latest 78fad5d182a7 2.5 GB 8 months ago (no tools)
21
+
22
+ qwen3-coder:30b 06c1097efce0 18 GB 11 hours ago
23
+ qwen3-next:80b b2ebb986e4e9 50 GB 11 hours ago
24
+ qwen3:30b ad815644918f 18 GB 11 hours ago
25
+ qwen3:32b 030ee887880f 20 GB 11 hours ago
26
+ """
1
27
  import typing as ta
2
28
 
3
29
  from omlish import check
@@ -32,6 +32,8 @@ _GPT_MODEL_NAMES = [
32
32
  'gpt-5-nano',
33
33
 
34
34
  'gpt-5.1',
35
+
36
+ 'gpt-5.2',
35
37
  ]
36
38
 
37
39
 
@@ -48,7 +50,7 @@ CHAT_MODEL_NAMES = ModelNameCollection(
48
50
  for n in _GPT_MODEL_NAMES
49
51
  },
50
52
 
51
- 'gpt': 'gpt-5.1',
53
+ 'gpt': 'gpt-5.2',
52
54
  'gpt-mini': 'gpt-5-mini',
53
55
 
54
56
  #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ommlds
3
- Version: 0.0.0.dev491
3
+ Version: 0.0.0.dev492
4
4
  Summary: ommlds
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,9 +14,9 @@ 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.dev491
17
+ Requires-Dist: omlish==0.0.0.dev492
18
18
  Provides-Extra: all
19
- Requires-Dist: omdev==0.0.0.dev491; extra == "all"
19
+ Requires-Dist: omdev==0.0.0.dev492; 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"
@@ -38,7 +38,7 @@ Requires-Dist: mwparserfromhell~=0.7; extra == "all"
38
38
  Requires-Dist: wikitextparser~=0.56; extra == "all"
39
39
  Requires-Dist: lxml>=5.3; python_version < "3.13" and extra == "all"
40
40
  Provides-Extra: omdev
41
- Requires-Dist: omdev==0.0.0.dev491; extra == "omdev"
41
+ Requires-Dist: omdev==0.0.0.dev492; extra == "omdev"
42
42
  Provides-Extra: backends
43
43
  Requires-Dist: llama-cpp-python~=0.3; extra == "backends"
44
44
  Requires-Dist: mlx~=0.30; sys_platform == "darwin" and extra == "backends"
@@ -1,4 +1,4 @@
1
- ommlds/.omlish-manifests.json,sha256=Xz1zqDGjmcuUgaWaK454DizBTKTg5Qj8eRN_vRP-nLw,27810
1
+ ommlds/.omlish-manifests.json,sha256=HQMkRy6laT2rf3PmlTpd0BCs5tTWLi-9d09xRptM2Uw,27872
2
2
  ommlds/README.md,sha256=xhbl2n19GznXrIzAGdlX8PAYJYsOo_Zu63I7G1UFRZE,398
3
3
  ommlds/__about__.py,sha256=cRA9AUVZmvQaibdmACDEpd5T2VWWVWtJT_zpgt9I0Wg,1900
4
4
  ommlds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -104,7 +104,7 @@ ommlds/cli/__main__.py,sha256=1ffCb0fcUOJMzxROJmJRXQ8PSOVYv7KrcuBtT95cf0c,140
104
104
  ommlds/cli/_dataclasses.py,sha256=z-bFKj4I8bBufNzSPexvqdfqEmDpr7CdgqtGC-si1qg,150661
105
105
  ommlds/cli/asyncs.py,sha256=NAMzzaZq7ORjlbbBB_Y9vcM9qoBpGf4VJNtl_3p_8G4,629
106
106
  ommlds/cli/inject.py,sha256=CdG-Zgq3T0pDWLhHRZSqlkR4W2mS7LlCOHD2uP1llf0,610
107
- ommlds/cli/main.py,sha256=PQoe6vCcQ5tuYYo5cgXtb7p38K1h7BzLdg415Y9fhyc,10813
107
+ ommlds/cli/main.py,sha256=Jii-_pW551fl4muJi2m3dpF1s01oCoQb1UepIZL8Zxk,10810
108
108
  ommlds/cli/secrets.py,sha256=8GHlewS3yeFDfFNekaYwRm4nG9l3nd-Mc8tKl9Ma_Uo,469
109
109
  ommlds/cli/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
110
110
  ommlds/cli/backends/catalog.py,sha256=hLcBXBCiB7eKT_2yv8kyLD5f94LV7vCcOe144URuJxs,3225
@@ -133,8 +133,8 @@ ommlds/cli/sessions/chat/inject.py,sha256=BTrORil0zpK6jhYpBmMqpZQODueGfu89mfUjXR
133
133
  ommlds/cli/sessions/chat/session.py,sha256=gjwCDh8-fDuFD5OvZpJa3C8GShOhbRNZwQv5wreGHR4,801
134
134
  ommlds/cli/sessions/chat/drivers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
135
135
  ommlds/cli/sessions/chat/drivers/configs.py,sha256=eKJTI1y29L6PUnE5SXDkXdPfpBFeyHxMGTrOOIdYFFk,524
136
- ommlds/cli/sessions/chat/drivers/driver.py,sha256=MJSLto_wk0J_EkAL404etP4DnccY8u55QAg4J_7ip7A,1521
137
- ommlds/cli/sessions/chat/drivers/inject.py,sha256=KeQeaCPj7jfPcihAF9BSBIXWYGDth_FECEv2lAgVIVI,1332
136
+ ommlds/cli/sessions/chat/drivers/driver.py,sha256=uewbCaMEjOcSgfKRM93hs1Zrn7NGkgi87mftCmDLLT4,1607
137
+ ommlds/cli/sessions/chat/drivers/inject.py,sha256=5qX1Kbear_iGPwKJkWhI0UuzRLpITEicqXGZGCoBTWM,1358
138
138
  ommlds/cli/sessions/chat/drivers/types.py,sha256=KNDkgdX6FdihIYty5S7HHzsGPE-zdAbqFmxwyZF8CZE,124
139
139
  ommlds/cli/sessions/chat/drivers/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
140
140
  ommlds/cli/sessions/chat/drivers/ai/configs.py,sha256=MjuJicX53mrSHCDTpBTHLUyrovXFkKGqrVguuYbrwNg,185
@@ -180,28 +180,29 @@ ommlds/cli/sessions/chat/drivers/tools/weather/inject.py,sha256=HSB6gCp23T2HME07
180
180
  ommlds/cli/sessions/chat/drivers/tools/weather/tools.py,sha256=tGkr97D-60Lgsnjs1nSqV5BEZrTNlcaU_TFCY4ZRQyE,304
181
181
  ommlds/cli/sessions/chat/drivers/user/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
182
182
  ommlds/cli/sessions/chat/drivers/user/configs.py,sha256=tBSP2j1Bynn0Qt_S0GNUuNniMWivVSCFad3H4UCS3qY,280
183
- ommlds/cli/sessions/chat/drivers/user/inject.py,sha256=LYvB2vSpcBZZ1eM9z8Hxow4uBo_d-MkESVhnZNkLJII,1394
183
+ ommlds/cli/sessions/chat/drivers/user/inject.py,sha256=8Kf0CbeIK2_fMaXTrSXlYCJRk_Ipi39XJK4-gj6Ty6Q,1393
184
184
  ommlds/cli/sessions/chat/interfaces/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
185
185
  ommlds/cli/sessions/chat/interfaces/base.py,sha256=3z7yI-ow7037_n6VanQYZjOgKL_iRZ8FB6JP553SY7M,198
186
186
  ommlds/cli/sessions/chat/interfaces/configs.py,sha256=toI23cp2YVT_m-l-ICwg11xeD0_wkI-NLpBRkjRJyJI,473
187
- ommlds/cli/sessions/chat/interfaces/inject.py,sha256=Ip-srA7ONGF-YgbLikwfTd3O1UoxeDTMI6CnPpc6A80,493
187
+ ommlds/cli/sessions/chat/interfaces/inject.py,sha256=qyD0MrWlfwFF5d_ofhG83sp4UH3tDlwUkfQ7X9e2lzs,496
188
188
  ommlds/cli/sessions/chat/interfaces/bare/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
189
189
  ommlds/cli/sessions/chat/interfaces/bare/inject.py,sha256=y_iYbVlVn1YCWLUYT0iZ7p3z8Wzfn-RWQZMOkNLKoBQ,1866
190
- ommlds/cli/sessions/chat/interfaces/bare/interactive.py,sha256=oIBHkRrfLVGhPiVH_7wg79WMwJeNr8cTht20PMNxlho,1096
190
+ ommlds/cli/sessions/chat/interfaces/bare/interactive.py,sha256=kKZyrAnm8gy4bupVFPGWBsgU57MklZS49DcdungEwgs,1181
191
191
  ommlds/cli/sessions/chat/interfaces/bare/oneshot.py,sha256=1TNhTtg6KwzbG8GGxrT64tg9TDFakZ32qxrsT-djTwk,388
192
192
  ommlds/cli/sessions/chat/interfaces/bare/tools.py,sha256=_UsuoXLIvfpFP_We5DBBlhm6rwB3_cFA3lmFvpG9b-A,824
193
193
  ommlds/cli/sessions/chat/interfaces/bare/user.py,sha256=gZgfuQAnU_MH_Awb-Ut6sJE_Di4jvquKOkBT415NmR0,877
194
194
  ommlds/cli/sessions/chat/interfaces/textual/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
195
- ommlds/cli/sessions/chat/interfaces/textual/app.py,sha256=UKaPnLUNqb8_u1L4PigJyDBfDqgk00lNU4gUogsg_0M,6465
196
- ommlds/cli/sessions/chat/interfaces/textual/inject.py,sha256=dI7ZeQNVegL5MCwKJ_uNf-ZpBuUim9G84etHSkTHWOI,1672
197
- ommlds/cli/sessions/chat/interfaces/textual/interface.py,sha256=tvS8ORiunBxTIkTW2YmqRRyL7p46FrVpZEeix-ez9FA,322
195
+ ommlds/cli/sessions/chat/interfaces/textual/app.py,sha256=jRgm05Kxokw2Iy_cQz2NqR4TawiGo5rpVQUK-teRGHc,7885
196
+ ommlds/cli/sessions/chat/interfaces/textual/inject.py,sha256=bklFLLxzOHv02LZEC4Wf2dD_K8hlt_quyMp3YiH3JzU,1703
197
+ ommlds/cli/sessions/chat/interfaces/textual/interface.py,sha256=cNgkZq5Q8SxPhqirdZN-1tlh_fLvfop-hUamIPPMOnE,2837
198
+ ommlds/cli/sessions/chat/interfaces/textual/tools.py,sha256=svxDS2kUybojbLVQ42x8JzEx_yvUyQa6mEOqWf-XIFs,966
198
199
  ommlds/cli/sessions/chat/interfaces/textual/styles/__init__.py,sha256=7_U5oUjwegOymeWgt6nLpFfWfjGTrlWL8m4Au8MsaFE,542
199
- ommlds/cli/sessions/chat/interfaces/textual/styles/input.tcss,sha256=6aYFNxZ-GmTLirWnJcxVNPeq8YqgjS4GJDuxwXbOBhI,601
200
+ ommlds/cli/sessions/chat/interfaces/textual/styles/input.tcss,sha256=9LLwsuYjY8y1XTEnBy_ADKzpRaPPvpe-mNHhiAjEIdo,640
200
201
  ommlds/cli/sessions/chat/interfaces/textual/styles/markdown.tcss,sha256=KCKlgt_EEjHVZSTwP_w2YMrR6mURLYVryOwOziAFlTw,105
201
- ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss,sha256=PpBc7IfCJyhHdsFftDY1YHb4-ccVpTlpcYxg-6NGWW0,1171
202
+ ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss,sha256=v20cVDQQzCZWhWz1qW29EBKazJ0uoWtUuTGBQ-8uFew,1864
202
203
  ommlds/cli/sessions/chat/interfaces/textual/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
203
204
  ommlds/cli/sessions/chat/interfaces/textual/widgets/input.py,sha256=7PrKv6ZqPoDOTOE2V-Pz2hru1n1Dwz_4Fxc1eBwqdr0,944
204
- ommlds/cli/sessions/chat/interfaces/textual/widgets/messages.py,sha256=8h-pCaUOpEdimZUnyWmiQiHPAwARfqCi9SosskhR7Bk,2656
205
+ ommlds/cli/sessions/chat/interfaces/textual/widgets/messages.py,sha256=HqBrx4-5J6wD8Zj09CTECMw4Pw_zwUjPLjQ7UZN41s8,4421
205
206
  ommlds/cli/sessions/completion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
206
207
  ommlds/cli/sessions/completion/configs.py,sha256=ZibOyJxIMbclzKDK_mj8jVzFJxjkyVWmo1Tb9ZnQQ1M,240
207
208
  ommlds/cli/sessions/completion/inject.py,sha256=vk3ewhXWGemKcOllr1iG_nMz5523qEu40MI62Dlx9AQ,933
@@ -275,14 +276,14 @@ ommlds/minichain/backends/impls/llamacpp/stream.py,sha256=XMKNMGzn5dFIZCqfEQdUvy
275
276
  ommlds/minichain/backends/impls/mlx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
276
277
  ommlds/minichain/backends/impls/mlx/chat.py,sha256=tmZZAmVg-XcbxZYGNHrKC0hiJbxW88pgEHqIEC5D2Xc,7536
277
278
  ommlds/minichain/backends/impls/ollama/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
278
- ommlds/minichain/backends/impls/ollama/chat.py,sha256=xggP89xsZZ73QQnlxw7vn5G7swN10JAhVCpW1OWFf6g,5604
279
+ ommlds/minichain/backends/impls/ollama/chat.py,sha256=Ugdi--BM77tCwXezSBUgnE8BbClMCSaZ4wUkxaFNcC4,6751
279
280
  ommlds/minichain/backends/impls/ollama/protocol.py,sha256=1G5B1dtLdfOQVI32fSgzMaqN0iPv_WZkn1p6KKVgUNM,4749
280
281
  ommlds/minichain/backends/impls/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
281
282
  ommlds/minichain/backends/impls/openai/chat.py,sha256=G1IK94PwB16rYCkRos9JEuiAu1GgCK4CnZFOIShhpig,2856
282
283
  ommlds/minichain/backends/impls/openai/completion.py,sha256=4Mi4Zvrq5fCqUd0asL3WiCbCdmxOdo0NFkoZMfdsYXY,1939
283
284
  ommlds/minichain/backends/impls/openai/embedding.py,sha256=BNtvKYLTsnQwQR9Tv3Fr8zCYN1kr1UNdJ15lcsjz6X0,1765
284
285
  ommlds/minichain/backends/impls/openai/format.py,sha256=dAvaqi3LhPu7N9S8BDBkuGSWdD_cxkBEIXPLChcGWdk,7414
285
- ommlds/minichain/backends/impls/openai/names.py,sha256=5Q6tJbdEtAAsM6mzYLo6cCcMdbgzfbFXLwxVXafqYvo,1534
286
+ ommlds/minichain/backends/impls/openai/names.py,sha256=M1spn4Yio6LEnKWEzPqXSrzJg3wsf2M1iZIYFAvxb80,1550
286
287
  ommlds/minichain/backends/impls/openai/stream.py,sha256=bsZeGUepqOl9AcN44kWk03V6q-v1ewBCfZqb_MJEfxg,5454
287
288
  ommlds/minichain/backends/impls/sentencepiece/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
288
289
  ommlds/minichain/backends/impls/sentencepiece/tokens.py,sha256=S32bkN5bbAeLrRLW0VW2N4dEOKvBwt2mMS3CGbcmzQI,1679
@@ -467,9 +468,9 @@ ommlds/wiki/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
467
468
  ommlds/wiki/utils/io.py,sha256=UKgDJGtmpnWvIqVd2mJc2QNPOqlToEY1GEveNp6_pMo,7088
468
469
  ommlds/wiki/utils/progress.py,sha256=EhvKcMFYtsarCQhIahlO6f0SboyAKP3UwUyrnVnP-Vk,3222
469
470
  ommlds/wiki/utils/xml.py,sha256=sNJNkZ9rT8B-kJMO6bRz8J1USy4fyPx0m2PwTX7vxYY,3846
470
- ommlds-0.0.0.dev491.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
471
- ommlds-0.0.0.dev491.dist-info/METADATA,sha256=5AhDRw276qD3ClTCg_Wh8x4iyQ-LhrVpZ8K3BRGAOhI,3493
472
- ommlds-0.0.0.dev491.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
473
- ommlds-0.0.0.dev491.dist-info/entry_points.txt,sha256=Z5YWtX7ClfiCKdW-dd_CSVvM0h4yQpJPi-2G3q6gNFo,35
474
- ommlds-0.0.0.dev491.dist-info/top_level.txt,sha256=Rbnk5d5wi58vnAXx13WFZqdQ4VX8hBCS2hEL3WeXOhY,7
475
- ommlds-0.0.0.dev491.dist-info/RECORD,,
471
+ ommlds-0.0.0.dev492.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
472
+ ommlds-0.0.0.dev492.dist-info/METADATA,sha256=Wr6m1PkP3_nshtFnuS5mMHM5eRGMT2o_7CXbwB3heyc,3493
473
+ ommlds-0.0.0.dev492.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
474
+ ommlds-0.0.0.dev492.dist-info/entry_points.txt,sha256=Z5YWtX7ClfiCKdW-dd_CSVvM0h4yQpJPi-2G3q6gNFo,35
475
+ ommlds-0.0.0.dev492.dist-info/top_level.txt,sha256=Rbnk5d5wi58vnAXx13WFZqdQ4VX8hBCS2hEL3WeXOhY,7
476
+ ommlds-0.0.0.dev492.dist-info/RECORD,,