ommlds 0.0.0.dev514__py3-none-any.whl → 0.0.0.dev515__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.
- ommlds/cli/sessions/chat/interfaces/textual/app.py +4 -2
- ommlds/cli/sessions/chat/interfaces/textual/inputhistory.py +67 -30
- ommlds/minichain/backends/impls/transformers/transformers.py +2 -2
- {ommlds-0.0.0.dev514.dist-info → ommlds-0.0.0.dev515.dist-info}/METADATA +4 -4
- {ommlds-0.0.0.dev514.dist-info → ommlds-0.0.0.dev515.dist-info}/RECORD +9 -9
- {ommlds-0.0.0.dev514.dist-info → ommlds-0.0.0.dev515.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev514.dist-info → ommlds-0.0.0.dev515.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev514.dist-info → ommlds-0.0.0.dev515.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev514.dist-info → ommlds-0.0.0.dev515.dist-info}/top_level.txt +0 -0
|
@@ -335,7 +335,7 @@ class ChatApp(
|
|
|
335
335
|
|
|
336
336
|
async def on_unmount(self) -> None:
|
|
337
337
|
if (cat := self._chat_action_queue_task) is not None:
|
|
338
|
-
await self.
|
|
338
|
+
await self._chat_action_queue.put(None)
|
|
339
339
|
await cat
|
|
340
340
|
|
|
341
341
|
await self._chat_driver.stop()
|
|
@@ -359,7 +359,7 @@ class ChatApp(
|
|
|
359
359
|
),
|
|
360
360
|
)
|
|
361
361
|
|
|
362
|
-
self._input_history_manager.add(event.text)
|
|
362
|
+
await self._input_history_manager.add(event.text)
|
|
363
363
|
|
|
364
364
|
await self._chat_action_queue.put(ChatApp.UserInput(event.text))
|
|
365
365
|
|
|
@@ -371,12 +371,14 @@ class ChatApp(
|
|
|
371
371
|
|
|
372
372
|
@tx.on(InputTextArea.HistoryPrevious)
|
|
373
373
|
async def on_input_text_area_history_previous(self, event: InputTextArea.HistoryPrevious) -> None:
|
|
374
|
+
await self._input_history_manager.load_if_necessary()
|
|
374
375
|
if (entry := self._input_history_manager.get_previous(event.text)) is not None:
|
|
375
376
|
self._get_input_text_area().text = entry
|
|
376
377
|
self._move_input_cursor_to_end()
|
|
377
378
|
|
|
378
379
|
@tx.on(InputTextArea.HistoryNext)
|
|
379
380
|
async def on_input_text_area_history_next(self, event: InputTextArea.HistoryNext) -> None:
|
|
381
|
+
await self._input_history_manager.load_if_necessary()
|
|
380
382
|
if (entry := self._input_history_manager.get_next(event.text)) is not None:
|
|
381
383
|
ita = self._get_input_text_area()
|
|
382
384
|
ita.text = entry
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import abc
|
|
2
|
-
import json
|
|
3
2
|
import os
|
|
4
3
|
import typing as ta
|
|
5
4
|
|
|
6
5
|
from omlish import lang
|
|
6
|
+
from omlish.formats import json
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
##
|
|
@@ -11,11 +11,11 @@ from omlish import lang
|
|
|
11
11
|
|
|
12
12
|
class InputHistoryStorage(lang.Abstract):
|
|
13
13
|
@abc.abstractmethod
|
|
14
|
-
def load(self) -> list[str]:
|
|
14
|
+
def load(self) -> ta.Awaitable[list[str]]:
|
|
15
15
|
raise NotImplementedError
|
|
16
16
|
|
|
17
17
|
@abc.abstractmethod
|
|
18
|
-
def save(self, entries: ta.Sequence[str]) -> None:
|
|
18
|
+
def save(self, entries: ta.Sequence[str]) -> ta.Awaitable[None]:
|
|
19
19
|
raise NotImplementedError
|
|
20
20
|
|
|
21
21
|
|
|
@@ -25,10 +25,10 @@ class InMemoryInputHistoryStorage(InputHistoryStorage):
|
|
|
25
25
|
|
|
26
26
|
self._entries: list[str] = []
|
|
27
27
|
|
|
28
|
-
def load(self) -> list[str]:
|
|
28
|
+
async def load(self) -> list[str]:
|
|
29
29
|
return list(self._entries)
|
|
30
30
|
|
|
31
|
-
def save(self, entries: ta.Sequence[str]) -> None:
|
|
31
|
+
async def save(self, entries: ta.Sequence[str]) -> None:
|
|
32
32
|
self._entries = list(entries)
|
|
33
33
|
|
|
34
34
|
|
|
@@ -38,26 +38,31 @@ class FileInputHistoryStorage(InputHistoryStorage):
|
|
|
38
38
|
|
|
39
39
|
self._path = path
|
|
40
40
|
|
|
41
|
-
def load(self) -> list[str]:
|
|
41
|
+
async def load(self) -> list[str]:
|
|
42
42
|
if not os.path.exists(self._path):
|
|
43
43
|
return []
|
|
44
44
|
|
|
45
45
|
try:
|
|
46
|
-
with open(self._path) as f:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return data
|
|
50
|
-
return []
|
|
51
|
-
except (json.JSONDecodeError, OSError):
|
|
46
|
+
with open(self._path) as f: # noqa
|
|
47
|
+
content = f.read()
|
|
48
|
+
except OSError:
|
|
52
49
|
return []
|
|
53
50
|
|
|
54
|
-
|
|
51
|
+
data = json.loads(content)
|
|
52
|
+
|
|
53
|
+
if isinstance(data, list) and all(isinstance(e, str) for e in data):
|
|
54
|
+
return data
|
|
55
|
+
return []
|
|
56
|
+
|
|
57
|
+
async def save(self, entries: ta.Sequence[str]) -> None:
|
|
58
|
+
content = json.dumps_pretty(list(entries))
|
|
59
|
+
dir_path = os.path.dirname(self._path)
|
|
60
|
+
|
|
55
61
|
try:
|
|
56
|
-
dir_path = os.path.dirname(self._path)
|
|
57
62
|
if dir_path:
|
|
58
63
|
os.makedirs(dir_path, exist_ok=True)
|
|
59
|
-
with open(self._path, 'w') as f:
|
|
60
|
-
|
|
64
|
+
with open(self._path, 'w') as f: # noqa
|
|
65
|
+
f.write(content)
|
|
61
66
|
except OSError:
|
|
62
67
|
pass
|
|
63
68
|
|
|
@@ -88,16 +93,34 @@ class InputHistoryManager:
|
|
|
88
93
|
self._storage = storage
|
|
89
94
|
self._max_entries = max_entries
|
|
90
95
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
96
|
+
#
|
|
97
|
+
|
|
98
|
+
_entries: list[str]
|
|
99
|
+
_position: int = 0
|
|
100
|
+
|
|
101
|
+
async def load_if_necessary(self) -> None:
|
|
102
|
+
try:
|
|
103
|
+
self._entries # noqa
|
|
104
|
+
except AttributeError:
|
|
105
|
+
pass
|
|
106
|
+
else:
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
self._entries = await self._storage.load()
|
|
110
|
+
self._position = len(self._entries)
|
|
94
111
|
|
|
95
|
-
|
|
112
|
+
#
|
|
113
|
+
|
|
114
|
+
_current_draft: str = ''
|
|
115
|
+
|
|
116
|
+
async def add(self, text: str) -> None:
|
|
96
117
|
"""Add a new history entry and reset position."""
|
|
97
118
|
|
|
98
119
|
if not text.strip():
|
|
99
120
|
return
|
|
100
121
|
|
|
122
|
+
await self.load_if_necessary()
|
|
123
|
+
|
|
101
124
|
# Don't add duplicate consecutive entries
|
|
102
125
|
if self._entries and self._entries[-1] == text:
|
|
103
126
|
self.reset_position()
|
|
@@ -109,7 +132,7 @@ class InputHistoryManager:
|
|
|
109
132
|
if len(self._entries) > self._max_entries:
|
|
110
133
|
self._entries = self._entries[-self._max_entries:]
|
|
111
134
|
|
|
112
|
-
self._storage.save(self._entries)
|
|
135
|
+
await self._storage.save(self._entries)
|
|
113
136
|
self.reset_position()
|
|
114
137
|
|
|
115
138
|
def get_previous(self, text: str | None = None) -> str | None:
|
|
@@ -123,20 +146,24 @@ class InputHistoryManager:
|
|
|
123
146
|
The previous history entry, or None if at the beginning
|
|
124
147
|
"""
|
|
125
148
|
|
|
126
|
-
|
|
149
|
+
try:
|
|
150
|
+
entries = self._entries
|
|
151
|
+
except AttributeError:
|
|
152
|
+
return None
|
|
153
|
+
if entries:
|
|
127
154
|
return None
|
|
128
155
|
|
|
129
156
|
# Save current draft if we're at the end
|
|
130
|
-
if self._position == len(
|
|
157
|
+
if self._position == len(entries) and text is not None:
|
|
131
158
|
self._current_draft = text
|
|
132
159
|
|
|
133
160
|
# Move to previous entry
|
|
134
161
|
if self._position > 0:
|
|
135
162
|
self._position -= 1
|
|
136
|
-
return
|
|
163
|
+
return entries[self._position]
|
|
137
164
|
|
|
138
165
|
# Already at oldest entry
|
|
139
|
-
return
|
|
166
|
+
return entries[0] if entries else None
|
|
140
167
|
|
|
141
168
|
def get_next(self, text: str | None = None) -> str | None:
|
|
142
169
|
"""
|
|
@@ -149,20 +176,24 @@ class InputHistoryManager:
|
|
|
149
176
|
The next history entry, the saved draft if moving past the end, or None
|
|
150
177
|
"""
|
|
151
178
|
|
|
152
|
-
|
|
179
|
+
try:
|
|
180
|
+
entries = self._entries
|
|
181
|
+
except AttributeError:
|
|
182
|
+
return None
|
|
183
|
+
if entries:
|
|
153
184
|
return None
|
|
154
185
|
|
|
155
186
|
# Move to next entry
|
|
156
|
-
if self._position < len(
|
|
187
|
+
if self._position < len(entries):
|
|
157
188
|
self._position += 1
|
|
158
189
|
|
|
159
190
|
# If we moved past the end, return the draft
|
|
160
|
-
if self._position == len(
|
|
191
|
+
if self._position == len(entries):
|
|
161
192
|
draft = self._current_draft
|
|
162
193
|
self._current_draft = ''
|
|
163
194
|
return draft
|
|
164
195
|
|
|
165
|
-
return
|
|
196
|
+
return entries[self._position]
|
|
166
197
|
|
|
167
198
|
# Already at newest position
|
|
168
199
|
return None
|
|
@@ -170,5 +201,11 @@ class InputHistoryManager:
|
|
|
170
201
|
def reset_position(self) -> None:
|
|
171
202
|
"""Reset history position to the end (no history item selected)."""
|
|
172
203
|
|
|
173
|
-
|
|
204
|
+
try:
|
|
205
|
+
entries = self._entries
|
|
206
|
+
except AttributeError:
|
|
207
|
+
self._position = 0
|
|
208
|
+
else:
|
|
209
|
+
self._position = len(entries)
|
|
210
|
+
|
|
174
211
|
self._current_draft = ''
|
|
@@ -10,7 +10,7 @@ import typing as ta
|
|
|
10
10
|
from omlish import check
|
|
11
11
|
from omlish import lang
|
|
12
12
|
from omlish import typedvalues as tv
|
|
13
|
-
from omlish.asyncs.asyncio.sync import
|
|
13
|
+
from omlish.asyncs.asyncio.sync import AsyncioSyncBufferRelay
|
|
14
14
|
|
|
15
15
|
from ....chat.choices.services import ChatChoicesRequest
|
|
16
16
|
from ....chat.choices.services import ChatChoicesResponse
|
|
@@ -242,7 +242,7 @@ class TransformersChatChoicesStreamService(BaseTransformersChatChoicesService):
|
|
|
242
242
|
for m in request.v
|
|
243
243
|
]
|
|
244
244
|
|
|
245
|
-
relay:
|
|
245
|
+
relay: AsyncioSyncBufferRelay = AsyncioSyncBufferRelay()
|
|
246
246
|
|
|
247
247
|
def streamer_callback(text: str, *, stream_end: bool) -> None:
|
|
248
248
|
if text or stream_end:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ommlds
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev515
|
|
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.
|
|
17
|
+
Requires-Dist: omlish==0.0.0.dev515
|
|
18
18
|
Provides-Extra: all
|
|
19
|
-
Requires-Dist: omdev==0.0.0.
|
|
19
|
+
Requires-Dist: omdev==0.0.0.dev515; 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"
|
|
@@ -39,7 +39,7 @@ Requires-Dist: mwparserfromhell~=0.7; extra == "all"
|
|
|
39
39
|
Requires-Dist: wikitextparser~=0.56; extra == "all"
|
|
40
40
|
Requires-Dist: lxml>=5.3; python_version < "3.13" and extra == "all"
|
|
41
41
|
Provides-Extra: omdev
|
|
42
|
-
Requires-Dist: omdev==0.0.0.
|
|
42
|
+
Requires-Dist: omdev==0.0.0.dev515; extra == "omdev"
|
|
43
43
|
Provides-Extra: backends
|
|
44
44
|
Requires-Dist: llama-cpp-python~=0.3; extra == "backends"
|
|
45
45
|
Requires-Dist: mlx~=0.30; sys_platform == "darwin" and extra == "backends"
|
|
@@ -214,11 +214,11 @@ ommlds/cli/sessions/chat/interfaces/bare/interactive.py,sha256=ZnYoePvXtUbhkDQ0j
|
|
|
214
214
|
ommlds/cli/sessions/chat/interfaces/bare/oneshot.py,sha256=b758OIa0gf9I_0UdxYJ6re-g8-8xndgr3R0OotUOsmc,387
|
|
215
215
|
ommlds/cli/sessions/chat/interfaces/bare/tools.py,sha256=_UsuoXLIvfpFP_We5DBBlhm6rwB3_cFA3lmFvpG9b-A,824
|
|
216
216
|
ommlds/cli/sessions/chat/interfaces/textual/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
217
|
-
ommlds/cli/sessions/chat/interfaces/textual/app.py,sha256=
|
|
217
|
+
ommlds/cli/sessions/chat/interfaces/textual/app.py,sha256=QVLD4ZT4-SJ4UQhKSfm6MAjOtqeLtYhW3tMMXxg7h88,13432
|
|
218
218
|
ommlds/cli/sessions/chat/interfaces/textual/configs.py,sha256=-pvG2_Uai70ohDfK4Tt8yaHnvdCs10_gaoQkr-CsOqA,213
|
|
219
219
|
ommlds/cli/sessions/chat/interfaces/textual/facades.py,sha256=zXVG7DKVl-Xtdc893O_yktHCMvM0do6hLesMd8hbqeo,411
|
|
220
220
|
ommlds/cli/sessions/chat/interfaces/textual/inject.py,sha256=eBhFVZ2VmQdoTPSZvi2OSkZ-fX8Mw2TKo28bHZeACJY,3056
|
|
221
|
-
ommlds/cli/sessions/chat/interfaces/textual/inputhistory.py,sha256=
|
|
221
|
+
ommlds/cli/sessions/chat/interfaces/textual/inputhistory.py,sha256=hUGrIpSmI0wlg0jwqdT42hLkrzeQF4wnN6wdom9HDJU,5332
|
|
222
222
|
ommlds/cli/sessions/chat/interfaces/textual/interface.py,sha256=lHeuiMtA7DW9knuapZEOZSl9-9SmOfUxiPnd4-plLHE,445
|
|
223
223
|
ommlds/cli/sessions/chat/interfaces/textual/tools.py,sha256=KVlUmIyzqUuOHMzB9ZXGUaGsb-Tp5LAmMpB1agAHYjo,985
|
|
224
224
|
ommlds/cli/sessions/chat/interfaces/textual/styles/__init__.py,sha256=7_U5oUjwegOymeWgt6nLpFfWfjGTrlWL8m4Au8MsaFE,542
|
|
@@ -320,7 +320,7 @@ ommlds/minichain/backends/impls/tokenizers/tokens.py,sha256=wLz9UTWhHrrJm56ZSLZD
|
|
|
320
320
|
ommlds/minichain/backends/impls/transformers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
321
321
|
ommlds/minichain/backends/impls/transformers/sentence.py,sha256=0T01aY0rVauw--AdchroNkcwaK3ku0ZdP8ikcsYeHyA,1462
|
|
322
322
|
ommlds/minichain/backends/impls/transformers/tokens.py,sha256=ozlTX0c3sixgcgz87OwEBoVxTF69MTz46LbHzuS8r2Y,2166
|
|
323
|
-
ommlds/minichain/backends/impls/transformers/transformers.py,sha256=
|
|
323
|
+
ommlds/minichain/backends/impls/transformers/transformers.py,sha256=6eQa95I4PEcUap3bhpRujEDRsVG3MX768bZk4944fPg,9064
|
|
324
324
|
ommlds/minichain/backends/strings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
325
325
|
ommlds/minichain/backends/strings/manifests.py,sha256=kmlanVUAZqIh0P95Mm8H20e8ib3gEgYHHUlkCXDQGFk,413
|
|
326
326
|
ommlds/minichain/backends/strings/parsing.py,sha256=FbijHuHiIkOwC3jecUD-IXs7y12PS0ByCQeCfjJKuE8,1781
|
|
@@ -526,9 +526,9 @@ ommlds/wiki/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
526
526
|
ommlds/wiki/utils/io.py,sha256=UKgDJGtmpnWvIqVd2mJc2QNPOqlToEY1GEveNp6_pMo,7088
|
|
527
527
|
ommlds/wiki/utils/progress.py,sha256=EhvKcMFYtsarCQhIahlO6f0SboyAKP3UwUyrnVnP-Vk,3222
|
|
528
528
|
ommlds/wiki/utils/xml.py,sha256=sNJNkZ9rT8B-kJMO6bRz8J1USy4fyPx0m2PwTX7vxYY,3846
|
|
529
|
-
ommlds-0.0.0.
|
|
530
|
-
ommlds-0.0.0.
|
|
531
|
-
ommlds-0.0.0.
|
|
532
|
-
ommlds-0.0.0.
|
|
533
|
-
ommlds-0.0.0.
|
|
534
|
-
ommlds-0.0.0.
|
|
529
|
+
ommlds-0.0.0.dev515.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
|
530
|
+
ommlds-0.0.0.dev515.dist-info/METADATA,sha256=Ymblue2sqaQ1fupD_pdxYWr0xwhiL2JytUMrqYk_XFQ,3602
|
|
531
|
+
ommlds-0.0.0.dev515.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
532
|
+
ommlds-0.0.0.dev515.dist-info/entry_points.txt,sha256=Z5YWtX7ClfiCKdW-dd_CSVvM0h4yQpJPi-2G3q6gNFo,35
|
|
533
|
+
ommlds-0.0.0.dev515.dist-info/top_level.txt,sha256=Rbnk5d5wi58vnAXx13WFZqdQ4VX8hBCS2hEL3WeXOhY,7
|
|
534
|
+
ommlds-0.0.0.dev515.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|