ommlds 0.0.0.dev466__py3-none-any.whl → 0.0.0.dev512__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 +404 -31
- ommlds/README.md +11 -0
- ommlds/__about__.py +21 -12
- 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/events.py +2 -0
- ommlds/backends/anthropic/protocol/types.py +5 -7
- ommlds/backends/cerebras/__init__.py +7 -0
- ommlds/backends/cerebras/_dataclasses.py +4254 -0
- ommlds/backends/cerebras/_marshal.py +24 -0
- ommlds/backends/cerebras/clients.py +9 -0
- ommlds/backends/cerebras/protocol.py +310 -0
- ommlds/backends/google/protocol/__init__.py +13 -0
- ommlds/backends/google/protocol/_dataclasses.py +5997 -0
- ommlds/backends/google/protocol/types.py +6 -8
- ommlds/backends/groq/__init__.py +7 -0
- ommlds/backends/groq/_dataclasses.py +3901 -0
- ommlds/backends/groq/_marshal.py +23 -0
- ommlds/backends/groq/clients.py +9 -0
- ommlds/backends/groq/protocol.py +247 -0
- ommlds/{huggingface.py → backends/huggingface/cache.py} +1 -6
- ommlds/backends/huggingface/cli.py +208 -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 +7 -4
- ommlds/backends/ollama/__init__.py +7 -0
- ommlds/backends/ollama/_dataclasses.py +3940 -0
- ommlds/backends/ollama/cli.py +36 -0
- ommlds/backends/ollama/protocol.py +201 -0
- ommlds/backends/openai/protocol/__init__.py +15 -1
- ommlds/backends/openai/protocol/_common.py +3 -5
- 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 +299 -0
- ommlds/backends/tinygrad/models/llama3/__init__.py +22 -14
- ommlds/backends/torch/backends.py +1 -1
- 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 +3835 -0
- ommlds/cli/asyncs.py +30 -0
- ommlds/cli/backends/catalog.py +88 -0
- ommlds/cli/backends/configs.py +9 -0
- ommlds/cli/backends/inject.py +100 -42
- ommlds/cli/{sessions/chat/backends → backends}/injection.py +1 -1
- ommlds/cli/backends/meta.py +82 -0
- ommlds/cli/{sessions/chat/backends → backends}/types.py +11 -1
- ommlds/cli/{sessions/chat/content → content}/messages.py +2 -2
- ommlds/cli/{sessions/chat/content → content}/strings.py +1 -1
- ommlds/cli/inject.py +17 -8
- ommlds/cli/inputs/asyncs.py +32 -0
- ommlds/cli/inputs/sync.py +75 -0
- ommlds/cli/main.py +346 -114
- ommlds/cli/rendering/configs.py +9 -0
- ommlds/cli/{sessions/chat/rendering → rendering}/inject.py +4 -5
- ommlds/cli/{sessions/chat/rendering → rendering}/markdown.py +1 -1
- ommlds/cli/{sessions/chat/rendering → rendering}/raw.py +1 -1
- ommlds/cli/{sessions/chat/rendering → rendering}/types.py +7 -1
- ommlds/cli/secrets.py +22 -0
- ommlds/cli/sessions/base.py +1 -10
- ommlds/cli/sessions/chat/configs.py +13 -30
- ommlds/cli/sessions/chat/drivers/ai/configs.py +13 -0
- ommlds/cli/sessions/chat/drivers/ai/events.py +57 -0
- ommlds/cli/sessions/chat/{chat → drivers}/ai/inject.py +15 -12
- ommlds/cli/sessions/chat/{chat → drivers}/ai/rendering.py +8 -8
- ommlds/cli/sessions/chat/{chat → drivers}/ai/services.py +5 -5
- ommlds/cli/sessions/chat/{chat → drivers}/ai/tools.py +4 -8
- ommlds/cli/sessions/chat/{chat → drivers}/ai/types.py +10 -1
- ommlds/cli/sessions/chat/drivers/configs.py +25 -0
- ommlds/cli/sessions/chat/drivers/events/inject.py +27 -0
- ommlds/cli/sessions/chat/drivers/events/injection.py +14 -0
- ommlds/cli/sessions/chat/drivers/events/manager.py +16 -0
- ommlds/cli/sessions/chat/drivers/events/types.py +44 -0
- ommlds/cli/sessions/chat/drivers/impl.py +50 -0
- ommlds/cli/sessions/chat/drivers/inject.py +70 -0
- ommlds/cli/sessions/chat/drivers/state/configs.py +13 -0
- ommlds/cli/sessions/chat/drivers/state/ids.py +25 -0
- ommlds/cli/sessions/chat/drivers/state/inject.py +83 -0
- ommlds/cli/sessions/chat/{chat → drivers}/state/inmemory.py +1 -6
- ommlds/cli/sessions/chat/{chat → drivers}/state/storage.py +18 -12
- ommlds/cli/sessions/chat/{chat → drivers}/state/types.py +11 -6
- ommlds/cli/sessions/chat/drivers/tools/configs.py +22 -0
- ommlds/cli/sessions/chat/drivers/tools/confirmation.py +44 -0
- ommlds/cli/sessions/chat/drivers/tools/errorhandling.py +39 -0
- ommlds/cli/sessions/chat/{tools → drivers/tools}/execution.py +3 -4
- ommlds/cli/sessions/chat/drivers/tools/fs/__init__.py +0 -0
- ommlds/cli/sessions/chat/drivers/tools/fs/configs.py +12 -0
- ommlds/cli/sessions/chat/drivers/tools/fs/inject.py +35 -0
- ommlds/cli/sessions/chat/drivers/tools/inject.py +83 -0
- ommlds/cli/sessions/chat/{tools → drivers/tools}/injection.py +20 -5
- ommlds/cli/sessions/chat/{tools → drivers/tools}/rendering.py +3 -3
- ommlds/cli/sessions/chat/drivers/tools/todo/__init__.py +0 -0
- ommlds/cli/sessions/chat/drivers/tools/todo/configs.py +12 -0
- ommlds/cli/sessions/chat/drivers/tools/todo/inject.py +31 -0
- ommlds/cli/sessions/chat/drivers/tools/weather/__init__.py +0 -0
- ommlds/cli/sessions/chat/drivers/tools/weather/configs.py +12 -0
- ommlds/cli/sessions/chat/drivers/tools/weather/inject.py +22 -0
- ommlds/cli/sessions/chat/{tools/weather.py → drivers/tools/weather/tools.py} +1 -1
- ommlds/cli/sessions/chat/drivers/types.py +31 -0
- ommlds/cli/sessions/chat/drivers/user/__init__.py +0 -0
- ommlds/cli/sessions/chat/drivers/user/configs.py +14 -0
- ommlds/cli/sessions/chat/drivers/user/inject.py +41 -0
- ommlds/cli/sessions/chat/facades/__init__.py +0 -0
- ommlds/cli/sessions/chat/facades/commands/__init__.py +0 -0
- ommlds/cli/sessions/chat/facades/commands/base.py +83 -0
- ommlds/cli/sessions/chat/facades/commands/configs.py +9 -0
- ommlds/cli/sessions/chat/facades/commands/inject.py +41 -0
- ommlds/cli/sessions/chat/facades/commands/injection.py +15 -0
- ommlds/cli/sessions/chat/facades/commands/manager.py +59 -0
- ommlds/cli/sessions/chat/facades/commands/simple.py +34 -0
- ommlds/cli/sessions/chat/facades/commands/types.py +13 -0
- ommlds/cli/sessions/chat/facades/configs.py +11 -0
- ommlds/cli/sessions/chat/facades/facade.py +26 -0
- ommlds/cli/sessions/chat/facades/inject.py +35 -0
- ommlds/cli/sessions/chat/facades/ui.py +34 -0
- ommlds/cli/sessions/chat/inject.py +10 -49
- ommlds/cli/sessions/chat/interfaces/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/bare/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/bare/configs.py +15 -0
- ommlds/cli/sessions/chat/interfaces/bare/inject.py +69 -0
- ommlds/cli/sessions/chat/interfaces/bare/interactive.py +49 -0
- ommlds/cli/sessions/chat/interfaces/bare/oneshot.py +21 -0
- ommlds/cli/sessions/chat/{tools/confirmation.py → interfaces/bare/tools.py} +3 -22
- ommlds/cli/sessions/chat/interfaces/base.py +13 -0
- ommlds/cli/sessions/chat/interfaces/configs.py +11 -0
- ommlds/cli/sessions/chat/interfaces/inject.py +29 -0
- ommlds/cli/sessions/chat/interfaces/textual/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/textual/app.py +429 -0
- ommlds/cli/sessions/chat/interfaces/textual/configs.py +11 -0
- ommlds/cli/sessions/chat/interfaces/textual/facades.py +19 -0
- ommlds/cli/sessions/chat/interfaces/textual/inject.py +111 -0
- ommlds/cli/sessions/chat/interfaces/textual/inputhistory.py +174 -0
- ommlds/cli/sessions/chat/interfaces/textual/interface.py +24 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/__init__.py +29 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/input.tcss +53 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/markdown.tcss +7 -0
- ommlds/cli/sessions/chat/interfaces/textual/styles/messages.tcss +167 -0
- ommlds/cli/sessions/chat/interfaces/textual/tools.py +38 -0
- ommlds/cli/sessions/chat/interfaces/textual/widgets/__init__.py +0 -0
- ommlds/cli/sessions/chat/interfaces/textual/widgets/input.py +70 -0
- ommlds/cli/sessions/chat/interfaces/textual/widgets/messages.py +207 -0
- ommlds/cli/sessions/chat/session.py +8 -13
- ommlds/cli/sessions/completion/configs.py +5 -6
- ommlds/cli/sessions/completion/inject.py +15 -2
- ommlds/cli/sessions/completion/session.py +10 -18
- ommlds/cli/sessions/configs.py +10 -0
- ommlds/cli/sessions/embedding/configs.py +5 -6
- ommlds/cli/sessions/embedding/inject.py +15 -2
- ommlds/cli/sessions/embedding/session.py +10 -18
- ommlds/cli/sessions/inject.py +15 -15
- ommlds/cli/state/storage.py +8 -2
- ommlds/minichain/__init__.py +217 -60
- ommlds/minichain/_dataclasses.py +20640 -0
- ommlds/minichain/_typedvalues.py +15 -8
- ommlds/minichain/backends/catalogs/base.py +20 -1
- ommlds/minichain/backends/catalogs/simple.py +2 -2
- ommlds/minichain/backends/catalogs/strings.py +13 -10
- ommlds/minichain/backends/impls/anthropic/chat.py +28 -5
- ommlds/minichain/backends/impls/anthropic/names.py +3 -3
- ommlds/minichain/backends/impls/anthropic/protocol.py +2 -2
- ommlds/minichain/backends/impls/anthropic/stream.py +23 -18
- ommlds/minichain/backends/impls/cerebras/__init__.py +0 -0
- ommlds/minichain/backends/impls/cerebras/chat.py +82 -0
- ommlds/minichain/backends/impls/cerebras/names.py +45 -0
- ommlds/minichain/backends/impls/cerebras/protocol.py +143 -0
- ommlds/minichain/backends/impls/cerebras/stream.py +114 -0
- 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 +20 -84
- ommlds/minichain/backends/impls/google/names.py +6 -0
- ommlds/minichain/backends/impls/google/protocol.py +105 -0
- ommlds/minichain/backends/impls/google/search.py +10 -5
- ommlds/minichain/backends/impls/google/stream.py +64 -142
- ommlds/minichain/backends/impls/google/tools.py +2 -2
- ommlds/minichain/backends/impls/groq/__init__.py +0 -0
- ommlds/minichain/backends/impls/groq/chat.py +77 -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 +114 -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 +193 -0
- ommlds/minichain/backends/impls/ollama/protocol.py +144 -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 +117 -115
- ommlds/minichain/backends/impls/openai/names.py +33 -5
- ommlds/minichain/backends/impls/openai/stream.py +61 -70
- 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 +9 -6
- ommlds/minichain/backends/impls/transformers/transformers.py +139 -20
- ommlds/minichain/backends/strings/parsing.py +2 -2
- ommlds/minichain/backends/strings/resolving.py +7 -2
- ommlds/minichain/chat/choices/stream/__init__.py +0 -0
- ommlds/minichain/chat/{stream → choices/stream}/adapters.py +7 -7
- 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/content.py +42 -0
- ommlds/minichain/chat/messages.py +46 -42
- ommlds/minichain/chat/stream/_marshal.py +4 -4
- ommlds/minichain/chat/stream/joining.py +56 -43
- ommlds/minichain/chat/stream/services.py +15 -15
- ommlds/minichain/chat/stream/types.py +17 -24
- ommlds/minichain/chat/templating.py +3 -3
- ommlds/minichain/content/__init__.py +20 -3
- ommlds/minichain/content/_marshal.py +181 -55
- ommlds/minichain/content/code.py +26 -0
- ommlds/minichain/content/composite.py +28 -0
- ommlds/minichain/content/content.py +27 -0
- ommlds/minichain/content/dynamic.py +12 -0
- ommlds/minichain/content/emphasis.py +27 -0
- ommlds/minichain/content/images.py +2 -2
- ommlds/minichain/content/json.py +2 -2
- ommlds/minichain/content/link.py +13 -0
- ommlds/minichain/content/markdown.py +12 -0
- ommlds/minichain/content/metadata.py +10 -0
- ommlds/minichain/content/namespaces.py +8 -0
- ommlds/minichain/content/placeholders.py +10 -9
- ommlds/minichain/content/quote.py +26 -0
- ommlds/minichain/content/raw.py +49 -0
- ommlds/minichain/content/recursive.py +12 -0
- ommlds/minichain/content/resources.py +22 -0
- ommlds/minichain/content/section.py +26 -0
- ommlds/minichain/content/sequence.py +17 -3
- ommlds/minichain/content/standard.py +32 -0
- ommlds/minichain/content/tag.py +28 -0
- ommlds/minichain/content/templates.py +13 -0
- ommlds/minichain/content/text.py +2 -2
- ommlds/minichain/content/transform/__init__.py +0 -0
- ommlds/minichain/content/transform/json.py +55 -0
- ommlds/minichain/content/transform/markdown.py +8 -0
- ommlds/minichain/content/transform/materialize.py +59 -0
- ommlds/minichain/content/transform/metadata.py +16 -0
- ommlds/minichain/content/transform/namespaces.py +20 -0
- ommlds/minichain/content/transform/placeholders.py +60 -0
- ommlds/minichain/content/{prepare.py → transform/prepare.py} +10 -15
- ommlds/minichain/content/transform/recursive.py +54 -0
- ommlds/minichain/content/transform/resources.py +58 -0
- ommlds/minichain/content/transform/standard.py +43 -0
- ommlds/minichain/content/{transforms → transform}/stringify.py +1 -7
- ommlds/minichain/content/transform/strings.py +33 -0
- ommlds/minichain/content/transform/templates.py +25 -0
- ommlds/minichain/content/transform/types.py +18 -0
- ommlds/minichain/content/transform/visitors.py +38 -0
- ommlds/minichain/content/visitors.py +218 -0
- ommlds/minichain/http/__init__.py +0 -0
- ommlds/minichain/http/stream.py +195 -0
- ommlds/minichain/lib/fs/tools/read.py +1 -1
- ommlds/minichain/lib/fs/tools/recursivels/rendering.py +1 -1
- ommlds/minichain/lib/fs/tools/recursivels/running.py +1 -1
- ommlds/minichain/lib/todo/tools/write.py +2 -1
- ommlds/minichain/lib/todo/types.py +1 -1
- ommlds/minichain/llms/types.py +4 -0
- ommlds/minichain/metadata.py +56 -2
- ommlds/minichain/models/configs.py +2 -2
- ommlds/minichain/models/names.py +2 -0
- ommlds/minichain/registries/globals.py +18 -4
- ommlds/minichain/resources.py +49 -3
- ommlds/minichain/search.py +1 -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/standard.py +8 -0
- ommlds/minichain/stream/services.py +43 -17
- ommlds/minichain/text/applypatch.py +2 -1
- ommlds/minichain/text/toolparsing/llamacpp/types.py +1 -1
- ommlds/minichain/tokens/specials.py +1 -1
- ommlds/minichain/tools/execution/catalog.py +2 -2
- ommlds/minichain/tools/execution/errorhandling.py +36 -0
- ommlds/minichain/tools/execution/errors.py +2 -2
- ommlds/minichain/tools/execution/executors.py +1 -1
- ommlds/minichain/tools/fns.py +1 -1
- ommlds/minichain/tools/jsonschema.py +2 -2
- ommlds/minichain/tools/reflect.py +11 -7
- ommlds/minichain/tools/types.py +16 -19
- ommlds/minichain/vectors/_marshal.py +1 -1
- ommlds/minichain/vectors/embeddings.py +1 -1
- ommlds/minichain/wrappers/__init__.py +7 -0
- ommlds/minichain/wrappers/firstinwins.py +144 -0
- ommlds/minichain/wrappers/instrument.py +146 -0
- ommlds/minichain/wrappers/retry.py +168 -0
- ommlds/minichain/wrappers/services.py +98 -0
- ommlds/minichain/wrappers/stream.py +57 -0
- ommlds/nanochat/LICENSE +21 -0
- ommlds/nanochat/__init__.py +0 -0
- ommlds/nanochat/rustbpe/LICENSE +21 -0
- ommlds/nanochat/rustbpe/README.md +10 -0
- ommlds/nanochat/tokenizers.py +440 -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 +369 -0
- ommlds/tools/git.py +84 -64
- ommlds/tools/ocr.py +1 -1
- ommlds/wiki/analyze.py +2 -2
- ommlds/wiki/models.py +4 -4
- ommlds/wiki/text/mfh.py +9 -9
- ommlds/wiki/utils/xml.py +5 -5
- {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/METADATA +28 -21
- ommlds-0.0.0.dev512.dist-info/RECORD +534 -0
- {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/WHEEL +1 -1
- ommlds/cli/backends/standard.py +0 -20
- ommlds/cli/sessions/chat/backends/catalog.py +0 -56
- ommlds/cli/sessions/chat/backends/inject.py +0 -37
- ommlds/cli/sessions/chat/chat/state/inject.py +0 -40
- ommlds/cli/sessions/chat/chat/user/inject.py +0 -61
- ommlds/cli/sessions/chat/chat/user/interactive.py +0 -29
- ommlds/cli/sessions/chat/chat/user/oneshot.py +0 -25
- ommlds/cli/sessions/chat/chat/user/types.py +0 -15
- ommlds/cli/sessions/chat/driver.py +0 -43
- ommlds/cli/sessions/chat/tools/inject.py +0 -145
- ommlds/minichain/backends/impls/openai/format2.py +0 -210
- ommlds/minichain/content/materialize.py +0 -196
- ommlds/minichain/content/simple.py +0 -47
- ommlds/minichain/content/transforms/base.py +0 -46
- ommlds/minichain/content/transforms/interleave.py +0 -70
- ommlds/minichain/content/transforms/squeeze.py +0 -72
- ommlds/minichain/content/transforms/strings.py +0 -24
- ommlds/minichain/content/types.py +0 -43
- ommlds/minichain/stream/wrap.py +0 -62
- ommlds-0.0.0.dev466.dist-info/RECORD +0 -376
- /ommlds/{cli/sessions/chat/backends → backends/huggingface}/__init__.py +0 -0
- /ommlds/cli/{sessions/chat/chat → content}/__init__.py +0 -0
- /ommlds/cli/{sessions/chat/chat/ai → inputs}/__init__.py +0 -0
- /ommlds/cli/{sessions/chat/chat/state → rendering}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{chat/user → drivers}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{content → drivers/ai}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{chat → drivers}/ai/injection.py +0 -0
- /ommlds/cli/sessions/chat/{phases → drivers/events}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{rendering → drivers/phases}/__init__.py +0 -0
- /ommlds/cli/sessions/chat/{phases → drivers/phases}/inject.py +0 -0
- /ommlds/cli/sessions/chat/{phases → drivers/phases}/injection.py +0 -0
- /ommlds/cli/sessions/chat/{phases → drivers/phases}/manager.py +0 -0
- /ommlds/cli/sessions/chat/{phases → drivers/phases}/types.py +0 -0
- /ommlds/cli/sessions/chat/{tools → drivers/state}/__init__.py +0 -0
- /ommlds/{minichain/content/transforms → cli/sessions/chat/drivers/tools}/__init__.py +0 -0
- {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev466.dist-info → ommlds-0.0.0.dev512.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from omlish import inject as inj
|
|
2
|
+
from omlish import lang
|
|
3
|
+
|
|
4
|
+
from .bare.configs import BareInterfaceConfig
|
|
5
|
+
from .configs import InterfaceConfig
|
|
6
|
+
from .textual.configs import TextualInterfaceConfig
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
with lang.auto_proxy_import(globals()):
|
|
10
|
+
from .bare import inject as _bare
|
|
11
|
+
from .textual import inject as _textual
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def bind_interface(cfg: InterfaceConfig = BareInterfaceConfig()) -> inj.Elements:
|
|
18
|
+
els: list[inj.Elemental] = []
|
|
19
|
+
|
|
20
|
+
if isinstance(cfg, TextualInterfaceConfig):
|
|
21
|
+
els.append(_textual.bind_textual(cfg))
|
|
22
|
+
|
|
23
|
+
elif isinstance(cfg, BareInterfaceConfig):
|
|
24
|
+
els.append(_bare.bind_bare(cfg))
|
|
25
|
+
|
|
26
|
+
else:
|
|
27
|
+
raise TypeError(cfg)
|
|
28
|
+
|
|
29
|
+
return inj.as_elements(*els)
|
|
File without changes
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- textual.getters.query_one
|
|
4
|
+
- AUTO_FOCUS
|
|
5
|
+
"""
|
|
6
|
+
import asyncio
|
|
7
|
+
import os
|
|
8
|
+
import typing as ta
|
|
9
|
+
import weakref
|
|
10
|
+
|
|
11
|
+
from omdev.tui import textual as tx
|
|
12
|
+
from omlish import check
|
|
13
|
+
from omlish import dataclasses as dc
|
|
14
|
+
from omlish import lang
|
|
15
|
+
from omlish.logs import all as logs
|
|
16
|
+
|
|
17
|
+
from ...... import minichain as mc
|
|
18
|
+
from .....backends.types import BackendName
|
|
19
|
+
from ...drivers.events.types import AiDeltaChatEvent
|
|
20
|
+
from ...drivers.events.types import AiMessagesChatEvent
|
|
21
|
+
from ...drivers.types import ChatDriver
|
|
22
|
+
from ...facades.facade import ChatFacade
|
|
23
|
+
from .inputhistory import InputHistoryManager
|
|
24
|
+
from .styles import read_app_css
|
|
25
|
+
from .widgets.input import InputOuter
|
|
26
|
+
from .widgets.input import InputTextArea
|
|
27
|
+
from .widgets.messages import AiMessage
|
|
28
|
+
from .widgets.messages import MessageDivider
|
|
29
|
+
from .widgets.messages import MessagesContainer
|
|
30
|
+
from .widgets.messages import StaticAiMessage
|
|
31
|
+
from .widgets.messages import StreamAiMessage
|
|
32
|
+
from .widgets.messages import ToolConfirmationMessage
|
|
33
|
+
from .widgets.messages import UiMessage
|
|
34
|
+
from .widgets.messages import UserMessage
|
|
35
|
+
from .widgets.messages import WelcomeMessage
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
log, alog = logs.get_module_loggers(globals())
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
ChatEventQueue = ta.NewType('ChatEventQueue', asyncio.Queue)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ChatAppGetter(lang.AsyncCachedFunc0['ChatApp']):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ChatAppScreen(tx.Screen):
|
|
55
|
+
BINDINGS: ta.ClassVar[ta.Sequence[tx.BindingType]] = [
|
|
56
|
+
tx.Binding(
|
|
57
|
+
'alt+c,super+c',
|
|
58
|
+
'screen.copy_text',
|
|
59
|
+
'Copy selected text',
|
|
60
|
+
show=False,
|
|
61
|
+
),
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def _merge_bindings(cls) -> tx.BindingsMap:
|
|
66
|
+
return tx.unbind_map_keys(super()._merge_bindings(), ['ctrl+c'])
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ChatApp(
|
|
70
|
+
tx.ClipboardAppMixin,
|
|
71
|
+
tx.DevtoolsAppMixin,
|
|
72
|
+
tx.App,
|
|
73
|
+
):
|
|
74
|
+
ENABLE_COMMAND_PALETTE: ta.ClassVar[bool] = False
|
|
75
|
+
|
|
76
|
+
BINDINGS: ta.ClassVar[ta.Sequence[tx.BindingType]] = [
|
|
77
|
+
*tx.App.BINDINGS,
|
|
78
|
+
|
|
79
|
+
tx.Binding(
|
|
80
|
+
'escape',
|
|
81
|
+
'cancel',
|
|
82
|
+
'Cancel current operation',
|
|
83
|
+
show=False,
|
|
84
|
+
priority=True,
|
|
85
|
+
),
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
def __init__(
|
|
89
|
+
self,
|
|
90
|
+
*,
|
|
91
|
+
chat_facade: ChatFacade,
|
|
92
|
+
chat_driver: ChatDriver,
|
|
93
|
+
chat_event_queue: ChatEventQueue,
|
|
94
|
+
backend_name: BackendName | None = None,
|
|
95
|
+
devtools_setup: tx.DevtoolsSetup | None = None,
|
|
96
|
+
input_history_manager: InputHistoryManager,
|
|
97
|
+
) -> None:
|
|
98
|
+
super().__init__()
|
|
99
|
+
|
|
100
|
+
if devtools_setup is not None:
|
|
101
|
+
devtools_setup(self)
|
|
102
|
+
|
|
103
|
+
self._chat_facade = chat_facade
|
|
104
|
+
self._chat_driver = chat_driver
|
|
105
|
+
self._chat_event_queue = chat_event_queue
|
|
106
|
+
self._backend_name = backend_name
|
|
107
|
+
self._input_history_manager = input_history_manager
|
|
108
|
+
|
|
109
|
+
self._chat_action_queue: asyncio.Queue[ta.Any] = asyncio.Queue()
|
|
110
|
+
|
|
111
|
+
self._input_focused_key_events: weakref.WeakSet[tx.Key] = weakref.WeakSet()
|
|
112
|
+
|
|
113
|
+
def get_driver_class(self) -> type[tx.Driver]:
|
|
114
|
+
return tx.get_pending_writes_driver_class(super().get_driver_class())
|
|
115
|
+
|
|
116
|
+
def get_default_screen(self) -> tx.Screen:
|
|
117
|
+
return ChatAppScreen(id='_default')
|
|
118
|
+
|
|
119
|
+
CSS: ta.ClassVar[str] = read_app_css()
|
|
120
|
+
|
|
121
|
+
##
|
|
122
|
+
# Compose
|
|
123
|
+
|
|
124
|
+
def compose(self) -> tx.ComposeResult:
|
|
125
|
+
yield MessagesContainer(id='messages-container')
|
|
126
|
+
|
|
127
|
+
yield InputOuter(id='input-outer')
|
|
128
|
+
|
|
129
|
+
##
|
|
130
|
+
# Widget getters
|
|
131
|
+
|
|
132
|
+
def _get_input_text_area(self) -> InputTextArea:
|
|
133
|
+
return self.query_one('#input', InputTextArea)
|
|
134
|
+
|
|
135
|
+
def _get_messages_container(self) -> tx.VerticalScroll:
|
|
136
|
+
return self.query_one('#messages-container', MessagesContainer)
|
|
137
|
+
|
|
138
|
+
##
|
|
139
|
+
# Messages
|
|
140
|
+
|
|
141
|
+
def _is_messages_at_bottom(self, threshold: int = 3) -> bool:
|
|
142
|
+
return (ms := self._get_messages_container()).scroll_y >= (ms.max_scroll_y - threshold)
|
|
143
|
+
|
|
144
|
+
def _scroll_messages_to_bottom(self) -> None:
|
|
145
|
+
self._get_messages_container().scroll_end(animate=False)
|
|
146
|
+
|
|
147
|
+
def _anchor_messages(self) -> None:
|
|
148
|
+
if (ms := self._get_messages_container()).max_scroll_y:
|
|
149
|
+
ms.anchor()
|
|
150
|
+
|
|
151
|
+
def _scroll_messages_to_bottom_and_anchor(self) -> None:
|
|
152
|
+
self._scroll_messages_to_bottom()
|
|
153
|
+
self._anchor_messages()
|
|
154
|
+
|
|
155
|
+
#
|
|
156
|
+
|
|
157
|
+
_pending_mount_messages: list[tx.Widget] | None = None
|
|
158
|
+
|
|
159
|
+
async def _enqueue_mount_messages(self, *messages: tx.Widget) -> None:
|
|
160
|
+
if (lst := self._pending_mount_messages) is None:
|
|
161
|
+
lst = self._pending_mount_messages = []
|
|
162
|
+
|
|
163
|
+
lst.extend(messages)
|
|
164
|
+
|
|
165
|
+
_stream_ai_message: StreamAiMessage | None = None
|
|
166
|
+
|
|
167
|
+
async def _finalize_stream_ai_message(self) -> None:
|
|
168
|
+
if self._stream_ai_message is None:
|
|
169
|
+
return
|
|
170
|
+
|
|
171
|
+
await self._stream_ai_message.stop_stream()
|
|
172
|
+
self._stream_ai_message = None
|
|
173
|
+
|
|
174
|
+
async def _append_stream_ai_message_content(self, content: str) -> None:
|
|
175
|
+
if (sam := self._stream_ai_message) is not None:
|
|
176
|
+
was_at_bottom = self._is_messages_at_bottom()
|
|
177
|
+
|
|
178
|
+
await sam.append_content(content)
|
|
179
|
+
|
|
180
|
+
if was_at_bottom:
|
|
181
|
+
self.call_after_refresh(self._scroll_messages_to_bottom_and_anchor)
|
|
182
|
+
|
|
183
|
+
else:
|
|
184
|
+
await self._mount_messages(StreamAiMessage(content))
|
|
185
|
+
|
|
186
|
+
_num_mounted_messages = 0
|
|
187
|
+
|
|
188
|
+
async def _mount_messages(self, *messages: tx.Widget) -> None:
|
|
189
|
+
was_at_bottom = self._is_messages_at_bottom()
|
|
190
|
+
|
|
191
|
+
msg_ctr = self._get_messages_container()
|
|
192
|
+
|
|
193
|
+
for msg in [*(self._pending_mount_messages or []), *messages]:
|
|
194
|
+
if isinstance(msg, (AiMessage, ToolConfirmationMessage)):
|
|
195
|
+
await self._finalize_stream_ai_message()
|
|
196
|
+
|
|
197
|
+
if self._num_mounted_messages:
|
|
198
|
+
await msg_ctr.mount(MessageDivider())
|
|
199
|
+
|
|
200
|
+
await msg_ctr.mount(msg)
|
|
201
|
+
|
|
202
|
+
self._num_mounted_messages += 1
|
|
203
|
+
|
|
204
|
+
if isinstance(msg, StreamAiMessage):
|
|
205
|
+
self._stream_ai_message = check.replacing_none(self._stream_ai_message, msg)
|
|
206
|
+
await msg.write_initial_content()
|
|
207
|
+
|
|
208
|
+
self._pending_mount_messages = None
|
|
209
|
+
|
|
210
|
+
self.call_after_refresh(self._scroll_messages_to_bottom)
|
|
211
|
+
|
|
212
|
+
if was_at_bottom:
|
|
213
|
+
self.call_after_refresh(self._anchor_messages)
|
|
214
|
+
|
|
215
|
+
##
|
|
216
|
+
# Chat events
|
|
217
|
+
|
|
218
|
+
_chat_event_queue_task: asyncio.Task[None] | None = None
|
|
219
|
+
|
|
220
|
+
@logs.async_exception_logging(alog, BaseException)
|
|
221
|
+
async def _chat_event_queue_task_main(self) -> None:
|
|
222
|
+
while True:
|
|
223
|
+
ev = await self._chat_event_queue.get()
|
|
224
|
+
if ev is None:
|
|
225
|
+
break
|
|
226
|
+
|
|
227
|
+
await alog.debug(lambda: f'Got chat event: {ev!r}')
|
|
228
|
+
|
|
229
|
+
if isinstance(ev, AiMessagesChatEvent):
|
|
230
|
+
wx: list[tx.Widget] = []
|
|
231
|
+
|
|
232
|
+
for ai_msg in ev.chat:
|
|
233
|
+
if isinstance(ai_msg, mc.AiMessage):
|
|
234
|
+
wx.append(
|
|
235
|
+
StaticAiMessage(
|
|
236
|
+
check.isinstance(ai_msg.c, str),
|
|
237
|
+
markdown=True,
|
|
238
|
+
),
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
if wx:
|
|
242
|
+
await self._enqueue_mount_messages(*wx)
|
|
243
|
+
self.call_later(self._mount_messages)
|
|
244
|
+
|
|
245
|
+
elif isinstance(ev, AiDeltaChatEvent):
|
|
246
|
+
if isinstance(ev.delta, mc.ContentAiDelta):
|
|
247
|
+
cc = check.isinstance(ev.delta.c, str)
|
|
248
|
+
self.call_later(self._append_stream_ai_message_content, cc)
|
|
249
|
+
|
|
250
|
+
elif isinstance(ev.delta, mc.ToolUseAiDelta):
|
|
251
|
+
pass
|
|
252
|
+
|
|
253
|
+
##
|
|
254
|
+
# Chat actions
|
|
255
|
+
|
|
256
|
+
@dc.dataclass(frozen=True)
|
|
257
|
+
class UserInput:
|
|
258
|
+
text: str
|
|
259
|
+
|
|
260
|
+
async def _execute_user_input(self, ac: UserInput) -> None:
|
|
261
|
+
try:
|
|
262
|
+
await self._chat_facade.handle_user_input(ac.text)
|
|
263
|
+
except Exception as e: # noqa
|
|
264
|
+
# raise
|
|
265
|
+
await self.display_ui_message(repr(e))
|
|
266
|
+
|
|
267
|
+
#
|
|
268
|
+
|
|
269
|
+
_cur_chat_action: asyncio.Task[None] | None = None
|
|
270
|
+
|
|
271
|
+
async def _execute_chat_action(self, fn: ta.Callable[[], ta.Any]) -> None:
|
|
272
|
+
check.state(self._cur_chat_action is None)
|
|
273
|
+
|
|
274
|
+
self._cur_chat_action = asyncio.create_task(fn())
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
await self._cur_chat_action
|
|
278
|
+
|
|
279
|
+
except asyncio.CancelledError:
|
|
280
|
+
pass
|
|
281
|
+
|
|
282
|
+
except BaseException as e: # noqa
|
|
283
|
+
raise
|
|
284
|
+
|
|
285
|
+
finally:
|
|
286
|
+
self._cur_chat_action = None
|
|
287
|
+
|
|
288
|
+
#
|
|
289
|
+
|
|
290
|
+
_chat_action_queue_task: asyncio.Task[None] | None = None
|
|
291
|
+
|
|
292
|
+
@logs.async_exception_logging(alog, BaseException)
|
|
293
|
+
async def _chat_action_queue_task_main(self) -> None:
|
|
294
|
+
while True:
|
|
295
|
+
ac = await self._chat_action_queue.get()
|
|
296
|
+
if ac is None:
|
|
297
|
+
break
|
|
298
|
+
|
|
299
|
+
await alog.debug(lambda: f'Got chat action: {ac!r}')
|
|
300
|
+
|
|
301
|
+
if isinstance(ac, ChatApp.UserInput):
|
|
302
|
+
await self._execute_chat_action(lambda: self._execute_user_input(ac))
|
|
303
|
+
|
|
304
|
+
else:
|
|
305
|
+
raise TypeError(ac) # noqa
|
|
306
|
+
|
|
307
|
+
##
|
|
308
|
+
# Mounting
|
|
309
|
+
|
|
310
|
+
async def on_mount(self) -> None:
|
|
311
|
+
check.state(self._chat_event_queue_task is None)
|
|
312
|
+
self._chat_event_queue_task = asyncio.create_task(self._chat_event_queue_task_main())
|
|
313
|
+
|
|
314
|
+
await self._chat_driver.start()
|
|
315
|
+
|
|
316
|
+
check.state(self._chat_action_queue_task is None)
|
|
317
|
+
self._chat_action_queue_task = asyncio.create_task(self._chat_action_queue_task_main())
|
|
318
|
+
|
|
319
|
+
self._get_input_text_area().focus()
|
|
320
|
+
|
|
321
|
+
await self._mount_messages(
|
|
322
|
+
WelcomeMessage('\n'.join([
|
|
323
|
+
f'Backend: {self._backend_name or "?"}',
|
|
324
|
+
f'Dir: {os.getcwd()}',
|
|
325
|
+
])),
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
async def on_unmount(self) -> None:
|
|
329
|
+
if (cat := self._chat_action_queue_task) is not None:
|
|
330
|
+
await self._chat_event_queue.put(None)
|
|
331
|
+
await cat
|
|
332
|
+
|
|
333
|
+
await self._chat_driver.stop()
|
|
334
|
+
|
|
335
|
+
if (cet := self._chat_event_queue_task) is not None:
|
|
336
|
+
await self._chat_event_queue.put(None)
|
|
337
|
+
await cet
|
|
338
|
+
|
|
339
|
+
##
|
|
340
|
+
# Input
|
|
341
|
+
|
|
342
|
+
@tx.on(InputTextArea.Submitted)
|
|
343
|
+
async def on_input_text_area_submitted(self, event: InputTextArea.Submitted) -> None:
|
|
344
|
+
self._get_input_text_area().clear()
|
|
345
|
+
|
|
346
|
+
await self._finalize_stream_ai_message()
|
|
347
|
+
|
|
348
|
+
await self._mount_messages(
|
|
349
|
+
UserMessage(
|
|
350
|
+
event.text,
|
|
351
|
+
),
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
self._input_history_manager.add(event.text)
|
|
355
|
+
|
|
356
|
+
await self._chat_action_queue.put(ChatApp.UserInput(event.text))
|
|
357
|
+
|
|
358
|
+
def _move_input_cursor_to_end(self) -> None:
|
|
359
|
+
ita = self._get_input_text_area()
|
|
360
|
+
ln = ita.document.line_count - 1
|
|
361
|
+
lt = ita.document.lines[ln]
|
|
362
|
+
ita.move_cursor((ln, len(lt)))
|
|
363
|
+
|
|
364
|
+
@tx.on(InputTextArea.HistoryPrevious)
|
|
365
|
+
async def on_input_text_area_history_previous(self, event: InputTextArea.HistoryPrevious) -> None:
|
|
366
|
+
if (entry := self._input_history_manager.get_previous(event.text)) is not None:
|
|
367
|
+
self._get_input_text_area().text = entry
|
|
368
|
+
self._move_input_cursor_to_end()
|
|
369
|
+
|
|
370
|
+
@tx.on(InputTextArea.HistoryNext)
|
|
371
|
+
async def on_input_text_area_history_next(self, event: InputTextArea.HistoryNext) -> None:
|
|
372
|
+
if (entry := self._input_history_manager.get_next(event.text)) is not None:
|
|
373
|
+
ita = self._get_input_text_area()
|
|
374
|
+
ita.text = entry
|
|
375
|
+
self._move_input_cursor_to_end()
|
|
376
|
+
else:
|
|
377
|
+
# At the end of history, clear the input
|
|
378
|
+
ita = self._get_input_text_area()
|
|
379
|
+
ita.clear()
|
|
380
|
+
self._input_history_manager.reset_position()
|
|
381
|
+
|
|
382
|
+
@tx.on(tx.Key)
|
|
383
|
+
async def on_key(self, event: tx.Key) -> None:
|
|
384
|
+
if event in self._input_focused_key_events:
|
|
385
|
+
return
|
|
386
|
+
|
|
387
|
+
chat_input = self._get_input_text_area()
|
|
388
|
+
|
|
389
|
+
if not chat_input.has_focus:
|
|
390
|
+
self._input_focused_key_events.add(event)
|
|
391
|
+
|
|
392
|
+
chat_input.focus()
|
|
393
|
+
|
|
394
|
+
self.screen.post_message(tx.Key(event.key, event.character))
|
|
395
|
+
|
|
396
|
+
##
|
|
397
|
+
# User interaction
|
|
398
|
+
|
|
399
|
+
async def confirm_tool_use(
|
|
400
|
+
self,
|
|
401
|
+
outer_message: str,
|
|
402
|
+
inner_message: str,
|
|
403
|
+
) -> bool:
|
|
404
|
+
fut: asyncio.Future[bool] = asyncio.get_running_loop().create_future()
|
|
405
|
+
|
|
406
|
+
tcm = ToolConfirmationMessage(
|
|
407
|
+
outer_message,
|
|
408
|
+
inner_message,
|
|
409
|
+
fut,
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
async def inner() -> None:
|
|
413
|
+
await self._mount_messages(tcm)
|
|
414
|
+
|
|
415
|
+
self.call_later(inner)
|
|
416
|
+
|
|
417
|
+
ret = await fut
|
|
418
|
+
|
|
419
|
+
return ret
|
|
420
|
+
|
|
421
|
+
async def display_ui_message(
|
|
422
|
+
self,
|
|
423
|
+
content: str,
|
|
424
|
+
) -> None:
|
|
425
|
+
await self._mount_messages(UiMessage(content))
|
|
426
|
+
|
|
427
|
+
async def action_cancel(self) -> None:
|
|
428
|
+
if (cat := self._cur_chat_action) is not None:
|
|
429
|
+
cat.cancel()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from ...facades.ui import UiMessageDisplayer
|
|
2
|
+
from .app import ChatAppGetter
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ChatAppUiMessageDisplayer(UiMessageDisplayer):
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
*,
|
|
12
|
+
app: ChatAppGetter,
|
|
13
|
+
) -> None:
|
|
14
|
+
super().__init__()
|
|
15
|
+
|
|
16
|
+
self._app = app
|
|
17
|
+
|
|
18
|
+
async def display_ui_message(self, content: str) -> None:
|
|
19
|
+
await (await self._app()).display_ui_message(content)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FIXME:
|
|
3
|
+
- too lazy to lazy import guts like every other proper inject module lol >_<
|
|
4
|
+
"""
|
|
5
|
+
import asyncio
|
|
6
|
+
import contextlib
|
|
7
|
+
|
|
8
|
+
from omlish import inject as inj
|
|
9
|
+
from omlish import lang
|
|
10
|
+
|
|
11
|
+
from ...drivers.events.injection import event_callbacks
|
|
12
|
+
from ..base import ChatInterface
|
|
13
|
+
from .configs import TextualInterfaceConfig
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
with lang.auto_proxy_import(globals()):
|
|
17
|
+
from omdev.tui import textual as tx
|
|
18
|
+
|
|
19
|
+
from ...drivers.tools import confirmation as _tools_confirmation
|
|
20
|
+
from ...facades import ui as _facades_ui
|
|
21
|
+
from . import app as _app
|
|
22
|
+
from . import facades as _facades
|
|
23
|
+
from . import inputhistory as _inputhistory
|
|
24
|
+
from . import interface as _interface
|
|
25
|
+
from . import tools as _tools
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def bind_textual(cfg: TextualInterfaceConfig = TextualInterfaceConfig()) -> inj.Elements:
|
|
32
|
+
els: list[inj.Elemental] = [
|
|
33
|
+
inj.bind(ChatInterface, to_ctor=_interface.TextualChatInterface, singleton=True),
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
#
|
|
37
|
+
|
|
38
|
+
els.extend([
|
|
39
|
+
inj.bind(_app.ChatApp, singleton=True),
|
|
40
|
+
inj.bind_async_late(_app.ChatApp, _app.ChatAppGetter),
|
|
41
|
+
])
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
|
|
45
|
+
els.extend([
|
|
46
|
+
inj.bind(_app.ChatEventQueue, to_const=asyncio.Queue()),
|
|
47
|
+
|
|
48
|
+
event_callbacks().bind_item(to_fn=inj.target(eq=_app.ChatEventQueue)(lambda eq: lambda ev: eq.put(ev))),
|
|
49
|
+
])
|
|
50
|
+
|
|
51
|
+
#
|
|
52
|
+
|
|
53
|
+
if cfg.enable_tools:
|
|
54
|
+
if cfg.dangerous_no_tool_confirmation:
|
|
55
|
+
els.append(inj.bind(
|
|
56
|
+
_tools_confirmation.ToolExecutionConfirmation,
|
|
57
|
+
to_ctor=_tools_confirmation.UnsafeAlwaysAllowToolExecutionConfirmation,
|
|
58
|
+
singleton=True,
|
|
59
|
+
))
|
|
60
|
+
|
|
61
|
+
else:
|
|
62
|
+
els.append(inj.bind(
|
|
63
|
+
_tools_confirmation.ToolExecutionConfirmation,
|
|
64
|
+
to_ctor=_tools.ChatAppToolExecutionConfirmation,
|
|
65
|
+
singleton=True,
|
|
66
|
+
))
|
|
67
|
+
|
|
68
|
+
#
|
|
69
|
+
|
|
70
|
+
els.extend([
|
|
71
|
+
inj.bind(tx.DevtoolsConfig(port=41932)), # FIXME: lol
|
|
72
|
+
|
|
73
|
+
inj.bind(
|
|
74
|
+
tx.DevtoolsManager,
|
|
75
|
+
singleton=True,
|
|
76
|
+
to_async_fn=inj.make_async_managed_provider(
|
|
77
|
+
tx.DevtoolsManager,
|
|
78
|
+
contextlib.aclosing,
|
|
79
|
+
),
|
|
80
|
+
),
|
|
81
|
+
|
|
82
|
+
inj.bind(
|
|
83
|
+
tx.DevtoolsSetup,
|
|
84
|
+
to_async_fn=inj.target(mgr=tx.DevtoolsManager)(lambda mgr: mgr.get_setup()),
|
|
85
|
+
singleton=True,
|
|
86
|
+
),
|
|
87
|
+
])
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
|
|
91
|
+
els.extend([
|
|
92
|
+
inj.bind(_facades.ChatAppUiMessageDisplayer, singleton=True),
|
|
93
|
+
inj.bind(_facades_ui.UiMessageDisplayer, to_key=_facades.ChatAppUiMessageDisplayer),
|
|
94
|
+
])
|
|
95
|
+
|
|
96
|
+
#
|
|
97
|
+
|
|
98
|
+
def _make_input_history_storage() -> _inputhistory.InputHistoryStorage:
|
|
99
|
+
if cfg.input_history_file is not None:
|
|
100
|
+
return _inputhistory.FileInputHistoryStorage(path=cfg.input_history_file)
|
|
101
|
+
else:
|
|
102
|
+
return _inputhistory.InMemoryInputHistoryStorage()
|
|
103
|
+
|
|
104
|
+
els.extend([
|
|
105
|
+
inj.bind(_inputhistory.InputHistoryStorage, to_fn=_make_input_history_storage, singleton=True),
|
|
106
|
+
inj.bind(_inputhistory.InputHistoryManager, singleton=True),
|
|
107
|
+
])
|
|
108
|
+
|
|
109
|
+
#
|
|
110
|
+
|
|
111
|
+
return inj.as_elements(*els)
|