ommlds 0.0.0.dev499__py3-none-any.whl → 0.0.0.dev503__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ommlds/.omlish-manifests.json +20 -9
- ommlds/__about__.py +1 -1
- ommlds/backends/anthropic/protocol/sse/events.py +2 -0
- ommlds/backends/groq/clients.py +9 -0
- ommlds/cli/_dataclasses.py +22 -72
- ommlds/cli/backends/inject.py +20 -0
- ommlds/cli/backends/meta.py +47 -0
- ommlds/cli/sessions/chat/drivers/ai/tools.py +3 -7
- ommlds/cli/sessions/chat/facades/commands/base.py +1 -1
- ommlds/cli/sessions/chat/interfaces/textual/app.py +1 -1
- ommlds/minichain/__init__.py +47 -6
- ommlds/minichain/_dataclasses.py +533 -132
- ommlds/minichain/backends/impls/anthropic/names.py +3 -3
- ommlds/minichain/backends/impls/anthropic/stream.py +1 -1
- ommlds/minichain/backends/impls/cerebras/names.py +15 -0
- ommlds/minichain/backends/impls/cerebras/stream.py +1 -1
- ommlds/minichain/backends/impls/google/names.py +6 -0
- ommlds/minichain/backends/impls/google/stream.py +1 -1
- ommlds/minichain/backends/impls/groq/chat.py +2 -0
- ommlds/minichain/backends/impls/groq/stream.py +3 -1
- ommlds/minichain/backends/impls/ollama/chat.py +1 -1
- ommlds/minichain/backends/impls/openai/format.py +2 -1
- ommlds/minichain/backends/impls/openai/stream.py +33 -1
- ommlds/minichain/chat/messages.py +1 -1
- ommlds/minichain/chat/stream/joining.py +36 -12
- ommlds/minichain/chat/transforms/metadata.py +3 -3
- ommlds/minichain/content/standard.py +1 -1
- ommlds/minichain/content/transform/json.py +1 -1
- ommlds/minichain/content/transform/metadata.py +1 -1
- ommlds/minichain/content/transform/standard.py +2 -2
- ommlds/minichain/content/transform/strings.py +1 -1
- ommlds/minichain/content/transform/templates.py +1 -1
- ommlds/minichain/metadata.py +13 -16
- ommlds/minichain/resources.py +22 -1
- ommlds/minichain/services/README.md +154 -0
- ommlds/minichain/services/__init__.py +6 -2
- ommlds/minichain/services/_marshal.py +46 -10
- ommlds/minichain/services/_origclasses.py +11 -0
- ommlds/minichain/services/_typedvalues.py +8 -3
- ommlds/minichain/services/requests.py +73 -3
- ommlds/minichain/services/responses.py +73 -3
- ommlds/minichain/services/services.py +9 -0
- ommlds/minichain/stream/services.py +24 -1
- ommlds/minichain/tools/reflect.py +3 -3
- ommlds/minichain/wrappers/firstinwins.py +29 -2
- ommlds/minichain/wrappers/instrument.py +146 -0
- ommlds/minichain/wrappers/retry.py +93 -3
- ommlds/minichain/wrappers/services.py +26 -0
- {ommlds-0.0.0.dev499.dist-info → ommlds-0.0.0.dev503.dist-info}/METADATA +6 -6
- {ommlds-0.0.0.dev499.dist-info → ommlds-0.0.0.dev503.dist-info}/RECORD +54 -52
- ommlds/minichain/stream/wrap.py +0 -62
- {ommlds-0.0.0.dev499.dist-info → ommlds-0.0.0.dev503.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev499.dist-info → ommlds-0.0.0.dev503.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev499.dist-info → ommlds-0.0.0.dev503.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev499.dist-info → ommlds-0.0.0.dev503.dist-info}/top_level.txt +0 -0
|
@@ -178,14 +178,14 @@ class ToolReflector:
|
|
|
178
178
|
for o in md.get_object_metadata(fn, type=_ToolSpecOverride):
|
|
179
179
|
ts_ovr.update({
|
|
180
180
|
k: v
|
|
181
|
-
for k, v in dc.
|
|
181
|
+
for k, v in dc.shallow_asdict(o).items()
|
|
182
182
|
if k != 'params'
|
|
183
183
|
and v is not None
|
|
184
184
|
})
|
|
185
185
|
for op in (o.params or []):
|
|
186
186
|
p_ovr_dct.setdefault(check.non_empty_str(op.name), {}).update({
|
|
187
187
|
k: v
|
|
188
|
-
for k, v in dc.
|
|
188
|
+
for k, v in dc.shallow_asdict(op).items()
|
|
189
189
|
if v is not None
|
|
190
190
|
})
|
|
191
191
|
|
|
@@ -286,7 +286,7 @@ class ToolReflector:
|
|
|
286
286
|
if md_tp is not None:
|
|
287
287
|
tp_kw.update({
|
|
288
288
|
k: v
|
|
289
|
-
for k, v in dc.
|
|
289
|
+
for k, v in dc.shallow_asdict(md_tp).items()
|
|
290
290
|
if v is not None
|
|
291
291
|
})
|
|
292
292
|
|
|
@@ -17,16 +17,24 @@ from .services import WrappedRequest
|
|
|
17
17
|
from .services import WrappedRequestV
|
|
18
18
|
from .services import WrappedResponse
|
|
19
19
|
from .services import WrappedResponseV
|
|
20
|
+
from .stream import WrappedStreamOutputT
|
|
21
|
+
from .stream import WrapperStreamService
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
with lang.auto_proxy_import(globals()):
|
|
23
25
|
import asyncio
|
|
24
26
|
|
|
25
27
|
|
|
28
|
+
AnyFirstInWinsService: ta.TypeAlias = ta.Union[
|
|
29
|
+
'FirstInWinsService',
|
|
30
|
+
'FirstInWinsStreamService',
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
|
|
26
34
|
##
|
|
27
35
|
|
|
28
36
|
|
|
29
|
-
@dc.dataclass(
|
|
37
|
+
@dc.dataclass()
|
|
30
38
|
class FirstInWinsServiceCancelledError(Exception):
|
|
31
39
|
e: BaseException
|
|
32
40
|
|
|
@@ -37,11 +45,14 @@ class FirstInWinsServiceExceptionGroup(ExceptionGroup):
|
|
|
37
45
|
|
|
38
46
|
@dc.dataclass(frozen=True)
|
|
39
47
|
class FirstInWinsServiceOutput(Output):
|
|
40
|
-
first_in_wins_service:
|
|
48
|
+
first_in_wins_service: AnyFirstInWinsService
|
|
41
49
|
response_service: Service
|
|
42
50
|
service_exceptions: ta.Mapping[Service, Exception] | None = None
|
|
43
51
|
|
|
44
52
|
|
|
53
|
+
##
|
|
54
|
+
|
|
55
|
+
|
|
45
56
|
class FirstInWinsService(
|
|
46
57
|
MultiWrapperService[
|
|
47
58
|
WrappedRequestV,
|
|
@@ -57,6 +68,22 @@ class FirstInWinsService(
|
|
|
57
68
|
##
|
|
58
69
|
|
|
59
70
|
|
|
71
|
+
class FirstInWinsStreamService(
|
|
72
|
+
WrapperStreamService[
|
|
73
|
+
WrappedRequestV,
|
|
74
|
+
WrappedOptionT,
|
|
75
|
+
WrappedResponseV,
|
|
76
|
+
WrappedOutputT,
|
|
77
|
+
WrappedStreamOutputT,
|
|
78
|
+
],
|
|
79
|
+
lang.Abstract,
|
|
80
|
+
):
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
##
|
|
85
|
+
|
|
86
|
+
|
|
60
87
|
class AsyncioFirstInWinsService(
|
|
61
88
|
FirstInWinsService[
|
|
62
89
|
WrappedRequestV,
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- final stream outputs
|
|
4
|
+
"""
|
|
5
|
+
import datetime
|
|
6
|
+
import typing as ta
|
|
7
|
+
|
|
8
|
+
from omlish import dataclasses as dc
|
|
9
|
+
from omlish import lang
|
|
10
|
+
|
|
11
|
+
from ..services.requests import Request
|
|
12
|
+
from ..services.responses import Response
|
|
13
|
+
from .services import WrappedOptionT
|
|
14
|
+
from .services import WrappedOutputT
|
|
15
|
+
from .services import WrappedRequest
|
|
16
|
+
from .services import WrappedRequestV
|
|
17
|
+
from .services import WrappedResponse
|
|
18
|
+
from .services import WrappedResponseV
|
|
19
|
+
from .services import WrappedService
|
|
20
|
+
from .services import WrapperService
|
|
21
|
+
from .stream import WrappedStreamOutputT
|
|
22
|
+
from .stream import WrappedStreamResponse
|
|
23
|
+
from .stream import WrappedStreamService
|
|
24
|
+
from .stream import WrapperStreamService
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
|
31
|
+
@dc.extra_class_params(default_repr_fn=lang.opt_or_just_repr)
|
|
32
|
+
class InstrumentedServiceEvent:
|
|
33
|
+
dt: datetime.datetime = dc.field(default_factory=lang.utcnow)
|
|
34
|
+
|
|
35
|
+
req: Request | None = None
|
|
36
|
+
|
|
37
|
+
resp: Response | None = None
|
|
38
|
+
exc: BaseException | None = None
|
|
39
|
+
|
|
40
|
+
stream_v: lang.Maybe[ta.Any] = lang.empty()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class InstrumentedServiceEventSink(ta.Protocol):
|
|
44
|
+
def __call__(self, ev: InstrumentedServiceEvent) -> ta.Awaitable[None]: ...
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ListInstrumentedServiceEventSink:
|
|
48
|
+
def __init__(self, lst: list[InstrumentedServiceEvent] | None = None) -> None:
|
|
49
|
+
super().__init__()
|
|
50
|
+
|
|
51
|
+
if lst is None:
|
|
52
|
+
lst = []
|
|
53
|
+
self._lst = lst
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def events(self) -> ta.Sequence[InstrumentedServiceEvent]:
|
|
57
|
+
return self._lst
|
|
58
|
+
|
|
59
|
+
async def __call__(self, ev: InstrumentedServiceEvent) -> None:
|
|
60
|
+
self._lst.append(ev)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class InstrumentedService(
|
|
67
|
+
WrapperService[
|
|
68
|
+
WrappedRequestV,
|
|
69
|
+
WrappedOptionT,
|
|
70
|
+
WrappedResponseV,
|
|
71
|
+
WrappedOutputT,
|
|
72
|
+
],
|
|
73
|
+
):
|
|
74
|
+
def __init__(
|
|
75
|
+
self,
|
|
76
|
+
service: WrappedService,
|
|
77
|
+
sink: InstrumentedServiceEventSink | None = None,
|
|
78
|
+
) -> None:
|
|
79
|
+
super().__init__(service)
|
|
80
|
+
|
|
81
|
+
if sink is None:
|
|
82
|
+
sink = ListInstrumentedServiceEventSink()
|
|
83
|
+
self._sink = sink
|
|
84
|
+
|
|
85
|
+
async def invoke(self, request: WrappedRequest) -> WrappedResponse:
|
|
86
|
+
await self._sink(InstrumentedServiceEvent(req=request))
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
resp = await self._service.invoke(request)
|
|
90
|
+
|
|
91
|
+
except Exception as e: # noqa
|
|
92
|
+
await self._sink(InstrumentedServiceEvent(req=request, exc=e))
|
|
93
|
+
|
|
94
|
+
raise
|
|
95
|
+
|
|
96
|
+
await self._sink(InstrumentedServiceEvent(req=request, resp=resp))
|
|
97
|
+
|
|
98
|
+
return resp
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
##
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class InstrumentedStreamService(
|
|
105
|
+
WrapperStreamService[
|
|
106
|
+
WrappedRequestV,
|
|
107
|
+
WrappedOptionT,
|
|
108
|
+
WrappedResponseV,
|
|
109
|
+
WrappedOutputT,
|
|
110
|
+
WrappedStreamOutputT,
|
|
111
|
+
],
|
|
112
|
+
):
|
|
113
|
+
def __init__(
|
|
114
|
+
self,
|
|
115
|
+
service: WrappedStreamService,
|
|
116
|
+
sink: InstrumentedServiceEventSink | None = None,
|
|
117
|
+
) -> None:
|
|
118
|
+
super().__init__(service)
|
|
119
|
+
|
|
120
|
+
if sink is None:
|
|
121
|
+
sink = ListInstrumentedServiceEventSink()
|
|
122
|
+
self._sink = sink
|
|
123
|
+
|
|
124
|
+
async def invoke(self, request: WrappedRequest) -> WrappedStreamResponse:
|
|
125
|
+
await self._sink(InstrumentedServiceEvent(req=request))
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
resp = await self._service.invoke(request)
|
|
129
|
+
|
|
130
|
+
except Exception as e: # noqa
|
|
131
|
+
await self._sink(InstrumentedServiceEvent(req=request, exc=e))
|
|
132
|
+
|
|
133
|
+
raise
|
|
134
|
+
|
|
135
|
+
await self._sink(InstrumentedServiceEvent(req=request, resp=resp))
|
|
136
|
+
|
|
137
|
+
async def inner(sink): # noqa
|
|
138
|
+
async with resp.v as st:
|
|
139
|
+
async for v in st:
|
|
140
|
+
await self._sink(InstrumentedServiceEvent(req=request, resp=resp, stream_v=v))
|
|
141
|
+
|
|
142
|
+
await sink(v)
|
|
143
|
+
|
|
144
|
+
# return resp.with_v(inner())
|
|
145
|
+
|
|
146
|
+
raise NotImplementedError
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
"""
|
|
2
2
|
TODO:
|
|
3
3
|
- tenacity shit
|
|
4
|
-
- exception filter
|
|
4
|
+
- exception filter - retryable vs not
|
|
5
|
+
- explicit RetryableError wrapper?
|
|
5
6
|
- sleep
|
|
6
7
|
- jitter
|
|
8
|
+
- log, on retry / on except callbacks, blah blah
|
|
9
|
+
- stream retry:
|
|
10
|
+
- failed to open
|
|
11
|
+
- failed during stream
|
|
12
|
+
- buffer and replay??
|
|
13
|
+
- accept death mid-stream?
|
|
14
|
+
- ** probably **: cannot sanely impose any nontrivial stream retry strat at this layer -
|
|
7
15
|
"""
|
|
8
16
|
import typing as ta
|
|
9
17
|
|
|
10
18
|
from omlish import dataclasses as dc
|
|
11
19
|
|
|
20
|
+
from ..resources import Resources
|
|
21
|
+
from ..stream.services import StreamResponseSink
|
|
22
|
+
from ..stream.services import new_stream_response
|
|
12
23
|
from ..types import Output
|
|
13
24
|
from .services import WrappedOptionT
|
|
14
25
|
from .services import WrappedOutputT
|
|
@@ -18,22 +29,35 @@ from .services import WrappedResponse
|
|
|
18
29
|
from .services import WrappedResponseV
|
|
19
30
|
from .services import WrappedService
|
|
20
31
|
from .services import WrapperService
|
|
32
|
+
from .stream import WrappedStreamOutputT
|
|
33
|
+
from .stream import WrappedStreamResponse
|
|
34
|
+
from .stream import WrappedStreamService
|
|
35
|
+
from .stream import WrapperStreamService
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
AnyRetryService: ta.TypeAlias = ta.Union[
|
|
39
|
+
'RetryService',
|
|
40
|
+
'RetryStreamService',
|
|
41
|
+
]
|
|
21
42
|
|
|
22
43
|
|
|
23
44
|
##
|
|
24
45
|
|
|
25
46
|
|
|
26
|
-
@dc.dataclass(
|
|
47
|
+
@dc.dataclass()
|
|
27
48
|
class RetryServiceMaxRetriesExceededError(Exception):
|
|
28
49
|
pass
|
|
29
50
|
|
|
30
51
|
|
|
31
52
|
@dc.dataclass(frozen=True)
|
|
32
53
|
class RetryServiceOutput(Output):
|
|
33
|
-
retry_service:
|
|
54
|
+
retry_service: AnyRetryService
|
|
34
55
|
num_retries: int
|
|
35
56
|
|
|
36
57
|
|
|
58
|
+
##
|
|
59
|
+
|
|
60
|
+
|
|
37
61
|
class RetryService(
|
|
38
62
|
WrapperService[
|
|
39
63
|
WrappedRequestV,
|
|
@@ -76,3 +100,69 @@ class RetryService(
|
|
|
76
100
|
))
|
|
77
101
|
|
|
78
102
|
raise RuntimeError # unreachable
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
##
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class RetryStreamService(
|
|
109
|
+
WrapperStreamService[
|
|
110
|
+
WrappedRequestV,
|
|
111
|
+
WrappedOptionT,
|
|
112
|
+
WrappedResponseV,
|
|
113
|
+
WrappedOutputT,
|
|
114
|
+
WrappedStreamOutputT,
|
|
115
|
+
],
|
|
116
|
+
):
|
|
117
|
+
DEFAULT_MAX_RETRIES: ta.ClassVar[int] = 3
|
|
118
|
+
|
|
119
|
+
def __init__(
|
|
120
|
+
self,
|
|
121
|
+
service: WrappedStreamService,
|
|
122
|
+
*,
|
|
123
|
+
max_retries: int | None = None,
|
|
124
|
+
) -> None:
|
|
125
|
+
super().__init__(service)
|
|
126
|
+
|
|
127
|
+
if max_retries is None:
|
|
128
|
+
max_retries = self.DEFAULT_MAX_RETRIES
|
|
129
|
+
self._max_retries = max_retries
|
|
130
|
+
|
|
131
|
+
async def invoke(self, request: WrappedRequest) -> WrappedStreamResponse:
|
|
132
|
+
n = 0
|
|
133
|
+
|
|
134
|
+
while True:
|
|
135
|
+
try:
|
|
136
|
+
async with Resources.new() as rs:
|
|
137
|
+
in_resp = await self._service.invoke(request)
|
|
138
|
+
in_vs = await rs.enter_async_context(in_resp.v)
|
|
139
|
+
|
|
140
|
+
async def inner(sink: StreamResponseSink[WrappedResponseV]) -> ta.Sequence[WrappedOutputT] | None:
|
|
141
|
+
async for v in in_vs:
|
|
142
|
+
await sink.emit(v)
|
|
143
|
+
|
|
144
|
+
return in_vs.outputs
|
|
145
|
+
|
|
146
|
+
outs = [
|
|
147
|
+
*in_resp.outputs,
|
|
148
|
+
RetryServiceOutput(
|
|
149
|
+
retry_service=self,
|
|
150
|
+
num_retries=n,
|
|
151
|
+
),
|
|
152
|
+
]
|
|
153
|
+
|
|
154
|
+
# FIXME: ??
|
|
155
|
+
# if (ur := tv.as_collection(request.options).get(UseResources)) is not None:
|
|
156
|
+
|
|
157
|
+
return await new_stream_response(
|
|
158
|
+
rs,
|
|
159
|
+
inner,
|
|
160
|
+
outs,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
except Exception as e: # noqa
|
|
164
|
+
if n < self._max_retries:
|
|
165
|
+
n += 1
|
|
166
|
+
continue
|
|
167
|
+
|
|
168
|
+
raise RetryServiceMaxRetriesExceededError from e
|
|
@@ -10,6 +10,9 @@ from ..types import Option
|
|
|
10
10
|
from ..types import Output
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
P = ta.ParamSpec('P')
|
|
14
|
+
|
|
15
|
+
|
|
13
16
|
WrappedRequestV = ta.TypeVar('WrappedRequestV')
|
|
14
17
|
WrappedOptionT = ta.TypeVar('WrappedOptionT', bound=Option)
|
|
15
18
|
|
|
@@ -70,3 +73,26 @@ class MultiWrapperService(
|
|
|
70
73
|
super().__init__()
|
|
71
74
|
|
|
72
75
|
self._services = check.not_empty(services)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def wrap_service(
|
|
82
|
+
wrapped: WrappedService,
|
|
83
|
+
wrapper: ta.Callable[
|
|
84
|
+
ta.Concatenate[
|
|
85
|
+
WrappedService,
|
|
86
|
+
P,
|
|
87
|
+
],
|
|
88
|
+
WrapperService[
|
|
89
|
+
WrappedRequestV,
|
|
90
|
+
WrappedOptionT,
|
|
91
|
+
WrappedResponseV,
|
|
92
|
+
WrappedOutputT,
|
|
93
|
+
],
|
|
94
|
+
],
|
|
95
|
+
*args: P.args,
|
|
96
|
+
**kwargs: P.kwargs,
|
|
97
|
+
) -> WrappedService:
|
|
98
|
+
return ta.cast(ta.Any, wrapper(wrapped, *args, **kwargs))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ommlds
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev503
|
|
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.dev503
|
|
18
18
|
Provides-Extra: all
|
|
19
|
-
Requires-Dist: omdev==0.0.0.
|
|
19
|
+
Requires-Dist: omdev==0.0.0.dev503; 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"
|
|
@@ -32,13 +32,13 @@ Requires-Dist: regex>=2025.0; extra == "all"
|
|
|
32
32
|
Requires-Dist: numpy>=1.26; extra == "all"
|
|
33
33
|
Requires-Dist: pytesseract~=0.3; extra == "all"
|
|
34
34
|
Requires-Dist: rapidocr-onnxruntime~=1.4; extra == "all"
|
|
35
|
-
Requires-Dist: pillow~=12.
|
|
35
|
+
Requires-Dist: pillow~=12.1; extra == "all"
|
|
36
36
|
Requires-Dist: ddgs~=9.10; extra == "all"
|
|
37
37
|
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.
|
|
41
|
+
Requires-Dist: omdev==0.0.0.dev503; 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"
|
|
@@ -60,7 +60,7 @@ Provides-Extra: ocr
|
|
|
60
60
|
Requires-Dist: pytesseract~=0.3; extra == "ocr"
|
|
61
61
|
Requires-Dist: rapidocr-onnxruntime~=1.4; extra == "ocr"
|
|
62
62
|
Provides-Extra: pillow
|
|
63
|
-
Requires-Dist: pillow~=12.
|
|
63
|
+
Requires-Dist: pillow~=12.1; extra == "pillow"
|
|
64
64
|
Provides-Extra: search
|
|
65
65
|
Requires-Dist: ddgs~=9.10; extra == "search"
|
|
66
66
|
Provides-Extra: wiki
|