ommlds 0.0.0.dev456__py3-none-any.whl → 0.0.0.dev485__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 +314 -33
- ommlds/__about__.py +15 -9
- ommlds/_hacks/__init__.py +4 -0
- ommlds/_hacks/funcs.py +110 -0
- ommlds/_hacks/names.py +158 -0
- ommlds/_hacks/params.py +73 -0
- ommlds/_hacks/patches.py +0 -3
- ommlds/backends/anthropic/protocol/__init__.py +13 -1
- ommlds/backends/anthropic/protocol/_dataclasses.py +1625 -0
- ommlds/backends/anthropic/protocol/sse/assemble.py +22 -6
- ommlds/backends/anthropic/protocol/sse/events.py +13 -0
- ommlds/backends/google/protocol/__init__.py +13 -0
- ommlds/backends/google/protocol/_dataclasses.py +5997 -0
- ommlds/backends/google/protocol/types.py +5 -1
- ommlds/backends/groq/__init__.py +7 -0
- ommlds/backends/groq/_dataclasses.py +3901 -0
- ommlds/backends/groq/_marshal.py +23 -0
- ommlds/backends/groq/protocol.py +249 -0
- ommlds/backends/llamacpp/logging.py +4 -1
- ommlds/backends/mlx/caching.py +7 -3
- ommlds/backends/mlx/cli.py +10 -7
- ommlds/backends/mlx/generation.py +18 -16
- ommlds/backends/mlx/limits.py +10 -6
- ommlds/backends/mlx/loading.py +65 -5
- ommlds/backends/ollama/__init__.py +7 -0
- ommlds/backends/ollama/_dataclasses.py +3458 -0
- ommlds/backends/ollama/protocol.py +170 -0
- ommlds/backends/openai/protocol/__init__.py +15 -1
- ommlds/backends/openai/protocol/_dataclasses.py +7708 -0
- ommlds/backends/tavily/__init__.py +7 -0
- ommlds/backends/tavily/_dataclasses.py +1734 -0
- ommlds/backends/tavily/protocol.py +301 -0
- ommlds/backends/tinygrad/models/llama3/__init__.py +22 -14
- ommlds/backends/transformers/__init__.py +14 -0
- ommlds/backends/transformers/filecache.py +109 -0
- ommlds/backends/transformers/streamers.py +73 -0
- ommlds/cli/__init__.py +7 -0
- ommlds/cli/_dataclasses.py +2562 -0
- ommlds/cli/asyncs.py +30 -0
- ommlds/cli/backends/catalog.py +93 -0
- ommlds/cli/backends/configs.py +9 -0
- ommlds/cli/backends/inject.py +31 -36
- ommlds/cli/backends/injection.py +16 -0
- ommlds/cli/backends/types.py +46 -0
- ommlds/cli/content/messages.py +34 -0
- ommlds/cli/content/strings.py +42 -0
- ommlds/cli/inject.py +15 -32
- ommlds/cli/inputs/__init__.py +0 -0
- ommlds/cli/inputs/asyncs.py +32 -0
- ommlds/cli/inputs/sync.py +75 -0
- ommlds/cli/main.py +267 -128
- ommlds/cli/rendering/__init__.py +0 -0
- ommlds/cli/rendering/configs.py +9 -0
- ommlds/cli/rendering/inject.py +31 -0
- ommlds/cli/rendering/markdown.py +52 -0
- ommlds/cli/rendering/raw.py +73 -0
- ommlds/cli/rendering/types.py +21 -0
- ommlds/cli/secrets.py +21 -0
- ommlds/cli/sessions/base.py +1 -1
- ommlds/cli/sessions/chat/chat/__init__.py +0 -0
- ommlds/cli/sessions/chat/chat/ai/__init__.py +0 -0
- ommlds/cli/sessions/chat/chat/ai/configs.py +11 -0
- ommlds/cli/sessions/chat/chat/ai/inject.py +74 -0
- ommlds/cli/sessions/chat/chat/ai/injection.py +14 -0
- ommlds/cli/sessions/chat/chat/ai/rendering.py +70 -0
- ommlds/cli/sessions/chat/chat/ai/services.py +79 -0
- ommlds/cli/sessions/chat/chat/ai/tools.py +44 -0
- ommlds/cli/sessions/chat/chat/ai/types.py +28 -0
- ommlds/cli/sessions/chat/chat/state/__init__.py +0 -0
- ommlds/cli/sessions/chat/chat/state/configs.py +11 -0
- ommlds/cli/sessions/chat/chat/state/inject.py +36 -0
- ommlds/cli/sessions/chat/chat/state/inmemory.py +33 -0
- ommlds/cli/sessions/chat/chat/state/storage.py +52 -0
- ommlds/cli/sessions/chat/chat/state/types.py +38 -0
- ommlds/cli/sessions/chat/chat/user/__init__.py +0 -0
- ommlds/cli/sessions/chat/chat/user/configs.py +17 -0
- ommlds/cli/sessions/chat/chat/user/inject.py +62 -0
- ommlds/cli/sessions/chat/chat/user/interactive.py +31 -0
- ommlds/cli/sessions/chat/chat/user/oneshot.py +25 -0
- ommlds/cli/sessions/chat/chat/user/types.py +15 -0
- ommlds/cli/sessions/chat/configs.py +27 -0
- ommlds/cli/sessions/chat/driver.py +43 -0
- ommlds/cli/sessions/chat/inject.py +33 -65
- ommlds/cli/sessions/chat/phases/__init__.py +0 -0
- ommlds/cli/sessions/chat/phases/inject.py +27 -0
- ommlds/cli/sessions/chat/phases/injection.py +14 -0
- ommlds/cli/sessions/chat/phases/manager.py +29 -0
- ommlds/cli/sessions/chat/phases/types.py +29 -0
- ommlds/cli/sessions/chat/session.py +27 -0
- ommlds/cli/sessions/chat/tools/__init__.py +0 -0
- ommlds/cli/sessions/chat/tools/configs.py +22 -0
- ommlds/cli/sessions/chat/tools/confirmation.py +46 -0
- ommlds/cli/sessions/chat/tools/execution.py +66 -0
- ommlds/cli/sessions/chat/tools/fs/__init__.py +0 -0
- ommlds/cli/sessions/chat/tools/fs/configs.py +12 -0
- ommlds/cli/sessions/chat/tools/fs/inject.py +35 -0
- ommlds/cli/sessions/chat/tools/inject.py +88 -0
- ommlds/cli/sessions/chat/tools/injection.py +44 -0
- ommlds/cli/sessions/chat/tools/rendering.py +58 -0
- ommlds/cli/sessions/chat/tools/todo/__init__.py +0 -0
- ommlds/cli/sessions/chat/tools/todo/configs.py +12 -0
- ommlds/cli/sessions/chat/tools/todo/inject.py +31 -0
- ommlds/cli/sessions/chat/tools/weather/__init__.py +0 -0
- ommlds/cli/sessions/chat/tools/weather/configs.py +12 -0
- ommlds/cli/sessions/chat/tools/weather/inject.py +22 -0
- ommlds/cli/{tools/weather.py → sessions/chat/tools/weather/tools.py} +1 -1
- ommlds/cli/sessions/completion/configs.py +21 -0
- ommlds/cli/sessions/completion/inject.py +42 -0
- ommlds/cli/sessions/completion/session.py +35 -0
- ommlds/cli/sessions/embedding/configs.py +21 -0
- ommlds/cli/sessions/embedding/inject.py +42 -0
- ommlds/cli/sessions/embedding/session.py +33 -0
- ommlds/cli/sessions/inject.py +28 -11
- ommlds/cli/state/__init__.py +0 -0
- ommlds/cli/state/inject.py +28 -0
- ommlds/cli/{state.py → state/storage.py} +41 -24
- ommlds/minichain/__init__.py +46 -17
- ommlds/minichain/_dataclasses.py +15401 -0
- ommlds/minichain/backends/catalogs/base.py +20 -1
- ommlds/minichain/backends/catalogs/simple.py +2 -2
- ommlds/minichain/backends/catalogs/strings.py +10 -8
- ommlds/minichain/backends/impls/anthropic/chat.py +31 -65
- ommlds/minichain/backends/impls/anthropic/names.py +3 -4
- ommlds/minichain/backends/impls/anthropic/protocol.py +109 -0
- ommlds/minichain/backends/impls/anthropic/stream.py +53 -31
- ommlds/minichain/backends/impls/duckduckgo/search.py +5 -1
- ommlds/minichain/backends/impls/dummy/__init__.py +0 -0
- ommlds/minichain/backends/impls/dummy/chat.py +69 -0
- ommlds/minichain/backends/impls/google/chat.py +9 -2
- ommlds/minichain/backends/impls/google/search.py +6 -1
- ommlds/minichain/backends/impls/google/stream.py +122 -32
- ommlds/minichain/backends/impls/groq/__init__.py +0 -0
- ommlds/minichain/backends/impls/groq/chat.py +75 -0
- ommlds/minichain/backends/impls/groq/names.py +48 -0
- ommlds/minichain/backends/impls/groq/protocol.py +143 -0
- ommlds/minichain/backends/impls/groq/stream.py +125 -0
- ommlds/minichain/backends/impls/huggingface/repos.py +1 -5
- ommlds/minichain/backends/impls/llamacpp/chat.py +15 -3
- ommlds/minichain/backends/impls/llamacpp/completion.py +7 -3
- ommlds/minichain/backends/impls/llamacpp/stream.py +38 -19
- ommlds/minichain/backends/impls/mistral.py +9 -2
- ommlds/minichain/backends/impls/mlx/chat.py +100 -23
- ommlds/minichain/backends/impls/ollama/__init__.py +0 -0
- ommlds/minichain/backends/impls/ollama/chat.py +199 -0
- ommlds/minichain/backends/impls/openai/chat.py +14 -7
- ommlds/minichain/backends/impls/openai/completion.py +9 -2
- ommlds/minichain/backends/impls/openai/embedding.py +9 -2
- ommlds/minichain/backends/impls/openai/format.py +115 -109
- ommlds/minichain/backends/impls/openai/names.py +31 -5
- ommlds/minichain/backends/impls/openai/stream.py +33 -27
- ommlds/minichain/backends/impls/sentencepiece/tokens.py +9 -6
- ommlds/minichain/backends/impls/tavily.py +66 -0
- ommlds/minichain/backends/impls/tinygrad/chat.py +17 -14
- ommlds/minichain/backends/impls/tokenizers/tokens.py +9 -6
- ommlds/minichain/backends/impls/transformers/sentence.py +5 -2
- ommlds/minichain/backends/impls/transformers/tokens.py +10 -7
- ommlds/minichain/backends/impls/transformers/transformers.py +139 -20
- ommlds/minichain/backends/strings/parsing.py +1 -1
- ommlds/minichain/backends/strings/resolving.py +4 -1
- ommlds/minichain/chat/choices/stream/__init__.py +0 -0
- ommlds/minichain/chat/choices/stream/adapters.py +35 -0
- ommlds/minichain/chat/choices/stream/joining.py +31 -0
- ommlds/minichain/chat/choices/stream/services.py +45 -0
- ommlds/minichain/chat/choices/stream/types.py +43 -0
- ommlds/minichain/chat/stream/_marshal.py +4 -4
- ommlds/minichain/chat/stream/joining.py +85 -0
- ommlds/minichain/chat/stream/services.py +15 -15
- ommlds/minichain/chat/stream/types.py +24 -18
- ommlds/minichain/llms/types.py +4 -0
- ommlds/minichain/registries/globals.py +18 -4
- ommlds/minichain/resources.py +28 -3
- ommlds/minichain/search.py +1 -1
- ommlds/minichain/standard.py +8 -0
- ommlds/minichain/stream/services.py +19 -16
- ommlds/minichain/tools/reflect.py +5 -1
- ommlds/nanochat/LICENSE +21 -0
- ommlds/nanochat/__init__.py +0 -0
- ommlds/nanochat/rustbpe/LICENSE +21 -0
- ommlds/nanochat/tokenizers.py +406 -0
- ommlds/specs/__init__.py +0 -0
- ommlds/specs/mcp/__init__.py +0 -0
- ommlds/specs/mcp/_marshal.py +23 -0
- ommlds/specs/mcp/clients.py +146 -0
- ommlds/specs/mcp/protocol.py +371 -0
- ommlds/tools/git.py +13 -6
- ommlds/tools/ocr.py +1 -8
- ommlds/wiki/analyze.py +2 -2
- ommlds/wiki/text/mfh.py +1 -5
- ommlds/wiki/text/wtp.py +1 -3
- ommlds/wiki/utils/xml.py +5 -5
- {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/METADATA +22 -19
- {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/RECORD +198 -95
- ommlds/cli/backends/standard.py +0 -20
- ommlds/cli/sessions/chat/base.py +0 -42
- ommlds/cli/sessions/chat/code.py +0 -129
- ommlds/cli/sessions/chat/interactive.py +0 -71
- ommlds/cli/sessions/chat/printing.py +0 -97
- ommlds/cli/sessions/chat/prompt.py +0 -151
- ommlds/cli/sessions/chat/state.py +0 -110
- ommlds/cli/sessions/chat/tools.py +0 -100
- ommlds/cli/sessions/completion/completion.py +0 -44
- ommlds/cli/sessions/embedding/embedding.py +0 -42
- ommlds/cli/tools/config.py +0 -14
- ommlds/cli/tools/inject.py +0 -75
- ommlds/minichain/backends/impls/openai/format2.py +0 -210
- ommlds/minichain/chat/stream/adapters.py +0 -80
- /ommlds/{huggingface.py → backends/huggingface.py} +0 -0
- /ommlds/cli/{tools → content}/__init__.py +0 -0
- {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev456.dist-info → ommlds-0.0.0.dev485.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import check
|
|
4
|
+
from omlish.formats import json
|
|
5
|
+
|
|
6
|
+
from ...tools.types import ToolUse
|
|
7
|
+
from ..messages import AiChat
|
|
8
|
+
from ..messages import AiMessage
|
|
9
|
+
from ..messages import AnyAiMessage
|
|
10
|
+
from ..messages import ToolUseMessage
|
|
11
|
+
from .types import AiDelta
|
|
12
|
+
from .types import AiDeltas
|
|
13
|
+
from .types import ContentAiDelta
|
|
14
|
+
from .types import PartialToolUseAiDelta
|
|
15
|
+
from .types import ToolUseAiDelta
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AiDeltaJoiner:
|
|
22
|
+
def __init__(self) -> None:
|
|
23
|
+
super().__init__()
|
|
24
|
+
|
|
25
|
+
self._deltas: list[AiDelta] = []
|
|
26
|
+
self._messages: list[AnyAiMessage] = []
|
|
27
|
+
|
|
28
|
+
def _build_joined(self, deltas: ta.Sequence[AiDelta]) -> AnyAiMessage:
|
|
29
|
+
dty = check.single(set(map(type, check.not_empty(deltas))))
|
|
30
|
+
|
|
31
|
+
if dty is ContentAiDelta:
|
|
32
|
+
cds = ta.cast(ta.Sequence[ContentAiDelta], deltas)
|
|
33
|
+
return AiMessage(''.join(check.isinstance(cd.c, str) for cd in cds))
|
|
34
|
+
|
|
35
|
+
elif dty is ToolUseAiDelta:
|
|
36
|
+
raise TypeError(dty)
|
|
37
|
+
|
|
38
|
+
elif dty is PartialToolUseAiDelta:
|
|
39
|
+
tds = ta.cast(ta.Sequence[PartialToolUseAiDelta], deltas)
|
|
40
|
+
for td in ta.cast(ta.Sequence[PartialToolUseAiDelta], deltas)[1:]:
|
|
41
|
+
check.none(td.id)
|
|
42
|
+
check.none(td.name)
|
|
43
|
+
|
|
44
|
+
ra = ''.join(filter(None, (td.raw_args for td in tds)))
|
|
45
|
+
|
|
46
|
+
return ToolUseMessage(ToolUse(
|
|
47
|
+
id=tds[0].id,
|
|
48
|
+
name=check.non_empty_str(tds[0].name),
|
|
49
|
+
args=json.loads(ra),
|
|
50
|
+
raw_args=ra,
|
|
51
|
+
))
|
|
52
|
+
|
|
53
|
+
else:
|
|
54
|
+
raise TypeError(dty)
|
|
55
|
+
|
|
56
|
+
def _maybe_join(self) -> None:
|
|
57
|
+
if not self._deltas:
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
self._messages.append(self._build_joined(self._deltas))
|
|
61
|
+
self._deltas.clear()
|
|
62
|
+
|
|
63
|
+
def _add_one(self, d: AiDelta) -> None:
|
|
64
|
+
if self._deltas and type(self._deltas[0]) is not type(d):
|
|
65
|
+
self._maybe_join()
|
|
66
|
+
|
|
67
|
+
if isinstance(d, ToolUseAiDelta):
|
|
68
|
+
self._messages.append(ToolUseMessage(ToolUse(
|
|
69
|
+
id=d.id,
|
|
70
|
+
name=check.not_none(d.name),
|
|
71
|
+
args=d.args or {},
|
|
72
|
+
raw_args=json.dumps_compact(d.args),
|
|
73
|
+
)))
|
|
74
|
+
|
|
75
|
+
else:
|
|
76
|
+
self._deltas.append(d)
|
|
77
|
+
|
|
78
|
+
def add(self, deltas: AiDeltas) -> None:
|
|
79
|
+
for d in deltas:
|
|
80
|
+
self._add_one(d)
|
|
81
|
+
|
|
82
|
+
def build(self) -> AiChat:
|
|
83
|
+
self._maybe_join()
|
|
84
|
+
|
|
85
|
+
return list(self._messages)
|
|
@@ -7,39 +7,39 @@ from ...registries.globals import register_type
|
|
|
7
7
|
from ...services import Request
|
|
8
8
|
from ...services import Service
|
|
9
9
|
from ...stream.services import StreamResponse
|
|
10
|
-
from ..choices.types import ChatChoicesOutputs
|
|
11
10
|
from ..messages import Chat
|
|
12
|
-
from
|
|
13
|
-
from .types import
|
|
14
|
-
from .types import
|
|
11
|
+
from ..types import ChatOutputs
|
|
12
|
+
from .types import AiDeltas
|
|
13
|
+
from .types import ChatStreamOptions
|
|
14
|
+
from .types import ChatStreamOutputs
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
##
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
ChatStreamRequest: ta.TypeAlias = Request[Chat, ChatStreamOptions]
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
ChatStreamResponse: ta.TypeAlias = StreamResponse[
|
|
23
|
+
AiDeltas,
|
|
24
|
+
ChatOutputs,
|
|
25
|
+
ChatStreamOutputs,
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
# @omlish-manifest $.minichain.registries.manifests.RegistryTypeManifest
|
|
29
|
-
|
|
29
|
+
ChatStreamService: ta.TypeAlias = Service[ChatStreamRequest, ChatStreamResponse]
|
|
30
30
|
|
|
31
|
-
register_type(
|
|
31
|
+
register_type(ChatStreamService, module=__name__)
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
def
|
|
34
|
+
def static_check_is_chat_stream_service[T: ChatStreamService](t: type[T]) -> type[T]:
|
|
35
35
|
return t
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
##
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
@
|
|
42
|
-
class
|
|
41
|
+
@static_check_is_chat_stream_service
|
|
42
|
+
class AbstractChatStreamService(lang.Abstract):
|
|
43
43
|
@abc.abstractmethod
|
|
44
|
-
def invoke(self, request:
|
|
44
|
+
def invoke(self, request: ChatStreamRequest) -> ta.Awaitable[ChatStreamResponse]:
|
|
45
45
|
raise NotImplementedError
|
|
@@ -6,10 +6,9 @@ from omlish import marshal as msh
|
|
|
6
6
|
|
|
7
7
|
from ...content.types import Content
|
|
8
8
|
from ...stream.services import StreamOptions
|
|
9
|
-
from ...tools.types import ToolUse
|
|
10
9
|
from ...types import Option
|
|
11
10
|
from ...types import Output
|
|
12
|
-
from ..
|
|
11
|
+
from ..types import ChatOptions
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
msh.register_global_module_import('._marshal', __package__)
|
|
@@ -18,49 +17,56 @@ msh.register_global_module_import('._marshal', __package__)
|
|
|
18
17
|
##
|
|
19
18
|
|
|
20
19
|
|
|
21
|
-
class
|
|
20
|
+
class ChatStreamOption(Option, lang.Abstract, lang.PackageSealed):
|
|
22
21
|
pass
|
|
23
22
|
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
ChatStreamOptions: ta.TypeAlias = ChatStreamOption | StreamOptions | ChatOptions
|
|
26
25
|
|
|
27
26
|
|
|
28
27
|
##
|
|
29
28
|
|
|
30
29
|
|
|
31
|
-
class
|
|
30
|
+
class ChatStreamOutput(Output, lang.Abstract, lang.PackageSealed):
|
|
32
31
|
pass
|
|
33
32
|
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
ChatStreamOutputs: ta.TypeAlias = ChatStreamOutput
|
|
36
35
|
|
|
37
36
|
|
|
38
37
|
##
|
|
39
38
|
|
|
40
39
|
|
|
41
40
|
@dc.dataclass(frozen=True)
|
|
42
|
-
class
|
|
41
|
+
class AiDelta(lang.Sealed, lang.Abstract):
|
|
43
42
|
pass
|
|
44
43
|
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
AiDeltas: ta.TypeAlias = ta.Sequence[AiDelta]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
#
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
@dc.dataclass(frozen=True)
|
|
52
|
-
class
|
|
53
|
-
|
|
52
|
+
class ContentAiDelta(AiDelta, lang.Final):
|
|
53
|
+
c: Content
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
#
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
@dc.dataclass(frozen=True)
|
|
60
|
-
class
|
|
61
|
-
|
|
59
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
|
60
|
+
class AnyToolUseAiDelta(AiDelta, lang.Abstract):
|
|
61
|
+
id: str | None = None
|
|
62
|
+
name: str | None = None
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
@dc.dataclass(frozen=True)
|
|
65
|
-
class
|
|
66
|
-
|
|
65
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
|
66
|
+
class ToolUseAiDelta(AnyToolUseAiDelta, lang.Final):
|
|
67
|
+
args: ta.Mapping[str, ta.Any] | None = None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
|
71
|
+
class PartialToolUseAiDelta(AnyToolUseAiDelta, lang.Final):
|
|
72
|
+
raw_args: ta.Any | None = None
|
ommlds/minichain/llms/types.py
CHANGED
|
@@ -98,20 +98,34 @@ def register_type(
|
|
|
98
98
|
|
|
99
99
|
|
|
100
100
|
@ta.overload
|
|
101
|
-
def
|
|
101
|
+
def get_registry_cls(cls: type[T], name: str) -> type[T]:
|
|
102
102
|
...
|
|
103
103
|
|
|
104
104
|
|
|
105
105
|
@ta.overload
|
|
106
|
-
def
|
|
106
|
+
def get_registry_cls(cls: ta.Any, name: str) -> ta.Any:
|
|
107
107
|
...
|
|
108
108
|
|
|
109
109
|
|
|
110
|
-
def
|
|
110
|
+
def get_registry_cls(cls, name, *args, **kwargs):
|
|
111
111
|
be_cls = _GlobalRegistry.instance().get_registry_cls(cls, name)
|
|
112
112
|
if isinstance(cls, type):
|
|
113
113
|
be_cls = check.issubclass(be_cls, cls) # noqa
|
|
114
|
-
return be_cls
|
|
114
|
+
return be_cls
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@ta.overload
|
|
118
|
+
def registry_new(cls: type[T], name: str, *args: ta.Any, **kwargs: ta.Any) -> T:
|
|
119
|
+
...
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@ta.overload
|
|
123
|
+
def registry_new(cls: ta.Any, name: str, *args: ta.Any, **kwargs: ta.Any) -> ta.Any:
|
|
124
|
+
...
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def registry_new(cls, name, *args, **kwargs):
|
|
128
|
+
return get_registry_cls(cls, name)(*args, **kwargs)
|
|
115
129
|
|
|
116
130
|
|
|
117
131
|
#
|
ommlds/minichain/resources.py
CHANGED
|
@@ -31,6 +31,7 @@ class ResourcesRefNotRegisteredError(Exception):
|
|
|
31
31
|
pass
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
@ta.final
|
|
34
35
|
class Resources(lang.Final, lang.NotPicklable):
|
|
35
36
|
def __init__(
|
|
36
37
|
self,
|
|
@@ -145,24 +146,48 @@ class Resources(lang.Final, lang.NotPicklable):
|
|
|
145
146
|
##
|
|
146
147
|
|
|
147
148
|
|
|
149
|
+
@ta.final
|
|
148
150
|
class ResourceManaged(ResourcesRef, lang.Final, lang.NotPicklable, ta.Generic[T]):
|
|
151
|
+
"""
|
|
152
|
+
A class to 'handoff' a ref to a `Resources`, allowing the `Resources` to temporarily survive being passed from
|
|
153
|
+
instantiation within a callee to being `__aenter__`'d in the caller.
|
|
154
|
+
|
|
155
|
+
The ref to the `Resources` is allocated in the ctor, so the contract is that an instance of this must be immediately
|
|
156
|
+
`__aenter__`'d before doing anything else with the return value of the call. Failure to do so leaks the `Resources`.
|
|
157
|
+
"""
|
|
158
|
+
|
|
149
159
|
def __init__(self, v: T, resources: Resources) -> None:
|
|
150
160
|
super().__init__()
|
|
151
161
|
|
|
152
|
-
self.
|
|
162
|
+
self.__v = v
|
|
153
163
|
self.__resources = resources
|
|
154
164
|
|
|
155
165
|
resources.add_ref(self)
|
|
156
166
|
|
|
167
|
+
__state: ta.Literal['new', 'entered', 'exited'] = 'new'
|
|
168
|
+
|
|
157
169
|
def __repr__(self) -> str:
|
|
158
|
-
return f'{self.__class__.__name__}<{self.
|
|
170
|
+
return f'{self.__class__.__name__}<{self.__v!r}, {self.__state}>'
|
|
159
171
|
|
|
160
172
|
async def __aenter__(self) -> T:
|
|
161
|
-
|
|
173
|
+
check.state(self.__state == 'new')
|
|
174
|
+
self.__state = 'entered'
|
|
175
|
+
return self.__v
|
|
162
176
|
|
|
163
177
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
178
|
+
check.state(self.__state == 'entered')
|
|
179
|
+
self.__state = 'exited'
|
|
164
180
|
await self.__resources.remove_ref(self)
|
|
165
181
|
|
|
182
|
+
def __del__(self) -> None:
|
|
183
|
+
if self.__state != 'exited':
|
|
184
|
+
log.error(
|
|
185
|
+
f'{__package__}.{self.__class__.__name__}.__del__: ' # noqa
|
|
186
|
+
f'%r deleted without being entered and exited! '
|
|
187
|
+
f'resources: %s',
|
|
188
|
+
repr(self),
|
|
189
|
+
repr(self.__resources),
|
|
190
|
+
)
|
|
166
191
|
|
|
167
192
|
##
|
|
168
193
|
|
ommlds/minichain/search.py
CHANGED
ommlds/minichain/standard.py
CHANGED
|
@@ -25,6 +25,14 @@ class Device(tv.UniqueScalarTypedValue[ta.Any], Config):
|
|
|
25
25
|
##
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
# TODO: ApiEndpointPath, ApiEndpointUrl, ApiBaseUrl, ...
|
|
29
|
+
class ApiUrl(tv.UniqueScalarTypedValue[str], Config):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
|
|
35
|
+
|
|
28
36
|
@dc.dataclass(frozen=True)
|
|
29
37
|
class SecretConfig(Config, lang.Abstract):
|
|
30
38
|
v: sec.SecretRefOrStr = dc.field() | sec.secret_field
|
|
@@ -125,17 +125,18 @@ class _StreamServiceResponse(StreamResponseIterator[V, OutputT]):
|
|
|
125
125
|
return
|
|
126
126
|
if self._cr.cr_running or self._cr.cr_suspended:
|
|
127
127
|
cex = StreamServiceCancelledError()
|
|
128
|
-
|
|
128
|
+
i = None
|
|
129
|
+
for n in itertools.count():
|
|
129
130
|
try:
|
|
130
|
-
if not
|
|
131
|
+
if not n:
|
|
131
132
|
x = self._g.throw(cex)
|
|
132
133
|
else:
|
|
133
|
-
x = self._g.send(
|
|
134
|
+
x = self._g.send(i)
|
|
134
135
|
except StreamServiceCancelledError as cex2:
|
|
135
136
|
if cex2 is cex:
|
|
136
137
|
break
|
|
137
138
|
raise
|
|
138
|
-
yield x
|
|
139
|
+
i = yield x
|
|
139
140
|
if self._cr.cr_running:
|
|
140
141
|
raise RuntimeError(f'Coroutine {self._cr!r} not terminated')
|
|
141
142
|
if self._g is not self._a:
|
|
@@ -155,9 +156,10 @@ class _StreamServiceResponse(StreamResponseIterator[V, OutputT]):
|
|
|
155
156
|
@types.coroutine
|
|
156
157
|
def _anext(self):
|
|
157
158
|
check.state(self._state == 'running')
|
|
159
|
+
i = None
|
|
158
160
|
while True:
|
|
159
161
|
try:
|
|
160
|
-
x = self._g.send(
|
|
162
|
+
x = self._g.send(i)
|
|
161
163
|
except StopIteration as e:
|
|
162
164
|
if e.value is not None:
|
|
163
165
|
self._outputs = tv.TypedValues(*check.isinstance(e.value, ta.Sequence))
|
|
@@ -170,7 +172,7 @@ class _StreamServiceResponse(StreamResponseIterator[V, OutputT]):
|
|
|
170
172
|
x.done = True
|
|
171
173
|
return x.value
|
|
172
174
|
|
|
173
|
-
yield x
|
|
175
|
+
i = yield x
|
|
174
176
|
|
|
175
177
|
async def __anext__(self) -> V:
|
|
176
178
|
return await self._anext()
|
|
@@ -195,13 +197,14 @@ async def new_stream_response(
|
|
|
195
197
|
fn: ta.Callable[[StreamResponseSink[V]], ta.Awaitable[ta.Sequence[OutputT] | None]],
|
|
196
198
|
outputs: ta.Sequence[StreamOutputT] | None = None,
|
|
197
199
|
) -> StreamResponse[V, OutputT, StreamOutputT]:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
200
|
+
ssr = _StreamServiceResponse(fn)
|
|
201
|
+
|
|
202
|
+
v = rs.new_managed(await rs.enter_async_context(ssr))
|
|
203
|
+
try:
|
|
204
|
+
return StreamResponse(v, outputs or [])
|
|
205
|
+
except BaseException: # noqa
|
|
206
|
+
# The StreamResponse ctor can raise - for example in `_tv_field_coercer` - in which case we need to clean up the
|
|
207
|
+
# resources ref we have already allocated before reraising.
|
|
208
|
+
async with v:
|
|
209
|
+
pass
|
|
210
|
+
raise
|
|
@@ -15,10 +15,10 @@ import textwrap
|
|
|
15
15
|
import types
|
|
16
16
|
import typing as ta
|
|
17
17
|
|
|
18
|
-
from omdev.py import docstrings
|
|
19
18
|
from omlish import check
|
|
20
19
|
from omlish import collections as col
|
|
21
20
|
from omlish import dataclasses as dc
|
|
21
|
+
from omlish import lang
|
|
22
22
|
from omlish import metadata as md
|
|
23
23
|
from omlish import reflect as rfl
|
|
24
24
|
from omlish.lite.cached import cached_nullary
|
|
@@ -37,6 +37,10 @@ from .types import TupleToolDtype
|
|
|
37
37
|
from .types import UnionToolDtype
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
with lang.auto_proxy_import(globals()):
|
|
41
|
+
from omdev.py import docstrings
|
|
42
|
+
|
|
43
|
+
|
|
40
44
|
##
|
|
41
45
|
|
|
42
46
|
|
ommlds/nanochat/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Andrej Karpathy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Andrej Karpathy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|