zettcode 0.2.0__tar.gz → 0.3.0__tar.gz
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.
- {zettcode-0.2.0 → zettcode-0.3.0}/.gitignore +4 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/PKG-INFO +2 -2
- {zettcode-0.2.0 → zettcode-0.3.0}/pyproject.toml +11 -2
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/__init__.py +1 -1
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/agent/commands.py +3 -3
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/rendering.py +76 -66
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/commands.py +1 -1
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/model.py +1 -1
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/plugins/__init__.py +24 -22
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/plugins/builtin_commands.py +218 -43
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/plugins/builtins.py +28 -20
- zettcode-0.2.0/src/zettcode/app/plugins/container.py → zettcode-0.3.0/src/zettcode/app/plugins/groups.py +48 -31
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/plugins/loader.py +102 -32
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/plugins/mixins.py +1 -1
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/plugins/plugin.py +11 -6
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/app.py +3 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/messaging.py +25 -1
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/notices.py +1 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/__init__.py +5 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/approval_page.py +11 -2
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/model_settings_page.py +2 -3
- zettcode-0.3.0/src/zettcode/app/ui/widgets/plugins_page.py +428 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/self_compact_page.py +9 -54
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/statusline_page.py +3 -33
- zettcode-0.3.0/src/zettcode/app/ui/widgets/switch.py +87 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/client.py +104 -6
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/hub.py +76 -2
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/models.py +5 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/protocol.py +14 -3
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/roster.py +7 -1
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/config.py +30 -1
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/config_edit.py +17 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/daemon/run.py +27 -5
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/core.py +7 -5
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/subagents.py +2 -2
- zettcode-0.3.0/src/zettcode/engine/extensions/truncation.py +156 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/messenger.py +78 -4
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/permission/sandbox.py +9 -3
- zettcode-0.3.0/src/zettcode/engine/plugins/__init__.py +73 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/plugins/builtin_agent.py +115 -91
- zettcode-0.3.0/src/zettcode/engine/plugins/commands.py +131 -0
- zettcode-0.2.0/src/zettcode/engine/plugins/container.py → zettcode-0.3.0/src/zettcode/engine/plugins/context.py +31 -8
- zettcode-0.3.0/src/zettcode/engine/plugins/groups.py +80 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/plugins/loader.py +64 -30
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/plugins/plugin.py +55 -11
- zettcode-0.3.0/src/zettcode/engine/plugins/switches.py +412 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/server_tools.py +24 -2
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/storage/__init__.py +1 -1
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/tools/boundary.py +7 -2
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/tools/files.py +42 -47
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/tools/output.py +12 -5
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/tools/shell.py +20 -10
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/tools/workspace.py +80 -77
- zettcode-0.3.0/src/zettcode/gateway/__init__.py +22 -0
- zettcode-0.3.0/src/zettcode/gateway/app.py +389 -0
- zettcode-0.3.0/src/zettcode/gateway/backend.py +291 -0
- zettcode-0.3.0/src/zettcode/gateway/chat.py +128 -0
- zettcode-0.3.0/src/zettcode/gateway/cli.py +138 -0
- zettcode-0.3.0/src/zettcode/gateway/service.py +811 -0
- zettcode-0.3.0/src/zettcode/gateway/settings.py +62 -0
- zettcode-0.3.0/src/zettcode/gateway/static/app.css +753 -0
- zettcode-0.3.0/src/zettcode/gateway/static/app.js +3 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_AMS-Regular-U6PRYMIZ.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Caligraphic-Bold-5QL5CMTE.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Caligraphic-Regular-KX5MEWCF.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Fraktur-Bold-2QVFK6NQ.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Fraktur-Regular-2PEIFJSJ.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Main-Bold-YP5VVQRP.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Main-BoldItalic-N4V3DX7S.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Main-Italic-RELBIK7M.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Main-Regular-ARRPAO67.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Math-BoldItalic-K4WTGH3J.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Math-Italic-6KGCHLFN.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_SansSerif-Bold-RRNVJFFW.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_SansSerif-Italic-HMPFTM52.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_SansSerif-Regular-XIQ62X4E.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Script-Regular-APUWIHLP.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Size1-Regular-5LRUTBFT.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Size2-Regular-LELKET5D.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Size3-Regular-WQRQ47UD.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Size4-Regular-CDMV7U5C.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/assets/KaTeX_Typewriter-Regular-VBYJ4NRC.woff2 +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/chunks/chunk-Y6SLVHK3.js +1 -0
- zettcode-0.3.0/src/zettcode/gateway/static/chunks/render-G6G3TSB3.js +341 -0
- zettcode-0.3.0/src/zettcode/gateway/static/icon.png +0 -0
- zettcode-0.3.0/src/zettcode/gateway/static/index.html +23 -0
- zettcode-0.3.0/src/zettcode/gateway/static/logo.svg +205 -0
- zettcode-0.3.0/src/zettcode/gateway/static/manifest.webmanifest +11 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/paths.py +4 -0
- zettcode-0.3.0/src/zettcode/plugin_tui.py +104 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/relay.py +3 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/sdk/__init__.py +11 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/sdk/client.py +293 -10
- zettcode-0.3.0/src/zettcode/sdk/commands.py +9 -0
- zettcode-0.3.0/src/zettcode/sdk/daemons.py +153 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/sdk/errors.py +13 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/sdk/events.py +10 -2
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/sdk/session.py +51 -24
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/sdk/translation.py +25 -2
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/sdk/types.py +184 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/server/app.py +67 -2
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/server/runner.py +41 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/server/schemas.py +90 -1
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/server/serialize.py +7 -1
- zettcode-0.2.0/src/zettcode/engine/plugins/__init__.py +0 -64
- {zettcode-0.2.0 → zettcode-0.3.0}/README.md +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/_compat.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/agent/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/agent/settings.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/changes.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/effort_gauge.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/entries.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/presenters.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/projection.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/pulse.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/replay.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/shimmer.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/stops.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/text.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/tips.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/transcript/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/transcript/fold.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/transcript/log.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/transcript/oneoff.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/transcript/stream.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/agent/conversation/transcript/turn.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/brand.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/commandline/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/commandline/arguments.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/commandline/completion.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/commandline/history.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/commandline/runner.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/cat.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/chibi.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/dog.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/kangaroo.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/penguin.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/polarbear.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/scarfy.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/seagull.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/slime.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/snowbear.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/sprout.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/tiger.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/pets/whale.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/plugins/host.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/plugins/state.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/bars.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/boot.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/clipboard.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/commands.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/config_form.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/demo.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/followups.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/gc_policy.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/keys.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/labels.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/providers.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/sessions.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/settings.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/shell.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/turns.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/updating.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/ask_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/bash_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/completer.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/composer.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/context_charts.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/context_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/effort_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/follow_up.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/form_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/input_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/model_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/panel.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/pet.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/pet_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/root.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/send_kind_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/sessions_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/steering.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/transcript.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/update_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/usage_charts.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/usage_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/app/ui/widgets/welcome.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/__main__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/files.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/finder.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/log.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/process.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/runner.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/server.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/text.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/broker/web.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/budget.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/cli.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/collector.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/daemon/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/daemon/__main__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/daemon/cli.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/daemon/process.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/daemon/state.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/doctor.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/agent/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/agent/base.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/agent/context.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/agent/exports.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/agent/interaction.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/agent/sessions.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/agent/settings.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/agent/turns.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/dialogue/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/dialogue/ask.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/dialogue/side.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/dialogue/title.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/export/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/export/trace/script.js +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/export/trace/style.css +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/export/trace/template.html +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/capabilities.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/compaction.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/context.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/files.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/harness.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/harness_switch.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/mcp.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/mcp_notice.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/messaging.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/relay.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/tool_output.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/extensions/usage.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/permission/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/permission/approval.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/permission/readonly.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/pipeline.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/plugins/extension.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/plugins/mixins.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/plugins/services.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/plugins/state.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/storage/layout.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/storage/ledger.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/storage/locks.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/storage/metadata.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/storage/records.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/storage/store.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/tools/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/engine/tools/images.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/error_text.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/filelock.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/mentions.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/oneshot.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/prompt.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/providers.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/py.typed +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/registry.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/sdk/handlers.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/sdk/models.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/server/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/server/cli.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/server/settings.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/statusline.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/capabilities.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/clipboard.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/console.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/app.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/events.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/focus.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/geometry.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/host.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/keymap.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/scheduler.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/screen.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/theme.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/core/widget.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/gallery.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/glyphs.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/input/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/input/bridge.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/input/decoder.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/input/events.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/input/keys.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/input/reader.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/layout/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/layout/box.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/layout/overlay.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/layout/scroll.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/layout/solver.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/layout/spacing.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/render/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/render/ansi.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/render/canvas.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/render/code.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/render/color.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/render/renderer.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/render/rich_text.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/render/style.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/render/sweep.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/render/text.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/runner.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/terminal.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/testing/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/testing/harness.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/testing/snapshot.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/theme_file.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/ayu-mirage.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/catppuccin-latte.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/catppuccin-mocha.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/dracula.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/github-dimmed.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/github-light.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/gruvbox-dark.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/gruvbox-light.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/kanagawa.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/nord.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/one-dark.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/rose-pine-dawn.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/rose-pine.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/solarized-dark.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/solarized-light.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/themes/tokyo-night.toml +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/__init__.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/collapsible.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/completion.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/console.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/dialog.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/diff.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/list.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/list_page.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/markdown.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/progress.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/rich_text.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/status.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/table.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/tasks.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/text.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/textarea.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/tui/widgets/toast.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/update.py +0 -0
- {zettcode-0.2.0 → zettcode-0.3.0}/src/zettcode/wording.py +0 -0
|
@@ -24,6 +24,10 @@ docs/.vitepress/.temp/
|
|
|
24
24
|
# The TypeScript client is built from its sources; only dist/ is published.
|
|
25
25
|
clients/typescript/dist/
|
|
26
26
|
|
|
27
|
+
# The gateway's page is built from clients/gateway into the package when a distribution is made (`make gateway-ui`);
|
|
28
|
+
# the build output is not kept in the repository. pyproject's `artifacts` puts it in the wheel all the same.
|
|
29
|
+
zettcode/src/zettcode/gateway/static/
|
|
30
|
+
|
|
27
31
|
# The palette gallery is generated by `make palettes`: every widget painted in
|
|
28
32
|
# every palette, written by docs/scripts/palette_gallery.py. Regenerate it
|
|
29
33
|
# rather than committing a 2 MB copy that goes stale the moment a colour moves.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: zettcode
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A focused terminal coding agent powered by zett-agent
|
|
5
5
|
Project-URL: Repository, https://github.com/Chang-LeHung/zettcode
|
|
6
6
|
Project-URL: Issues, https://github.com/Chang-LeHung/zettcode/issues
|
|
@@ -35,7 +35,7 @@ Requires-Dist: truststore<1,>=0.10
|
|
|
35
35
|
Requires-Dist: uvicorn<1,>=0.35
|
|
36
36
|
Requires-Dist: wcwidth<1,>=0.2
|
|
37
37
|
Requires-Dist: websockets<17,>=15
|
|
38
|
-
Requires-Dist: zett-agent<0.3,>=0.2.
|
|
38
|
+
Requires-Dist: zett-agent<0.3,>=0.2.2
|
|
39
39
|
Description-Content-Type: text/markdown
|
|
40
40
|
|
|
41
41
|
# ZettCode
|
|
@@ -57,13 +57,17 @@ dependencies = [
|
|
|
57
57
|
# tiktoken, and httpx behind their first use, so warming a runtime costs less
|
|
58
58
|
# than it did. An exact pin would make zettcode fight every other tool that
|
|
59
59
|
# shares the dependency — including an upgrade of zett-agent itself, which pip
|
|
60
|
-
# would downgrade to satisfy it.
|
|
61
|
-
|
|
60
|
+
# would downgrade to satisfy it. 0.2.2 is the floor for one reason this program
|
|
61
|
+
# now leans on: a hosted tool the provider left open is closed with
|
|
62
|
+
# ``output={"status": "not_reported"}`` instead of leaving the step waiting, and
|
|
63
|
+
# `engine/server_tools.describe_output` reads that to say so.
|
|
64
|
+
"zett-agent>=0.2.2,<0.3",
|
|
62
65
|
]
|
|
63
66
|
|
|
64
67
|
[project.scripts]
|
|
65
68
|
zettcode = "zettcode.cli:main"
|
|
66
69
|
zettcode-server = "zettcode.server.cli:main"
|
|
70
|
+
zettcode-gateway = "zettcode.gateway.cli:main"
|
|
67
71
|
|
|
68
72
|
[project.urls]
|
|
69
73
|
Repository = "https://github.com/Chang-LeHung/zettcode"
|
|
@@ -77,6 +81,11 @@ build-backend = "hatchling.build"
|
|
|
77
81
|
# Single source of truth: the version is written once, in the package.
|
|
78
82
|
path = "src/zettcode/__init__.py"
|
|
79
83
|
|
|
84
|
+
# The gateway's page is built (make gateway-ui) into the package and is not in git; hatchling skips what git ignores
|
|
85
|
+
# unless it is named here.
|
|
86
|
+
[tool.hatch.build]
|
|
87
|
+
artifacts = ["src/zettcode/gateway/static/**"]
|
|
88
|
+
|
|
80
89
|
[tool.hatch.build.targets.wheel]
|
|
81
90
|
packages = ["src/zettcode"]
|
|
82
91
|
|
|
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
|
|
|
7
7
|
|
|
8
8
|
#: The one place the version is written. ``pyproject.toml`` reads it from here
|
|
9
9
|
#: and the release workflow checks the tag against it, so a bump is one edit.
|
|
10
|
-
__version__ = "0.
|
|
10
|
+
__version__ = "0.3.0"
|
|
11
11
|
|
|
12
12
|
#: Where each public name lives; read by :func:`__getattr__` on first use.
|
|
13
13
|
_EXPORTS = {
|
|
@@ -10,7 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
from zettcode.app.commands import Command, CommandContext, CommandHost, CommandResult
|
|
11
11
|
from zettcode.app.pets import PetCatalog, bundled_pets
|
|
12
12
|
from zettcode.app.plugins.host import HOST_LINK, HostLink
|
|
13
|
-
from zettcode.app.plugins.plugin import
|
|
13
|
+
from zettcode.app.plugins.plugin import TuiPlugins
|
|
14
14
|
from zettcode.app.plugins.state import TurnSegment, UiRow
|
|
15
15
|
from zettcode.engine.agent.exports import ExportsMixin
|
|
16
16
|
from zettcode.providers import BUILTIN_PROVIDERS, Provider, merge_providers
|
|
@@ -28,10 +28,10 @@ class CommandsMixin(AppearanceMixin, ExportsMixin):
|
|
|
28
28
|
"""The ``/new``, ``/compact``, and ``/export`` commands, and the plugins' commands, mentions, and rows."""
|
|
29
29
|
|
|
30
30
|
@property
|
|
31
|
-
def terminal_plugins(self) ->
|
|
31
|
+
def terminal_plugins(self) -> TuiPlugins:
|
|
32
32
|
"""Return what the plugins contributed to the terminal; the engine was built with the terminal's loader."""
|
|
33
33
|
plugins = self.runtime.plugins
|
|
34
|
-
if not isinstance(plugins,
|
|
34
|
+
if not isinstance(plugins, TuiPlugins):
|
|
35
35
|
raise TypeError("This agent's engine was not built with the terminal's plugin loader")
|
|
36
36
|
return plugins
|
|
37
37
|
|
|
@@ -59,7 +59,7 @@ def is_picture_path(path: str) -> bool:
|
|
|
59
59
|
|
|
60
60
|
#: The hint a bounded read leaves behind; it is advice for the model, not the
|
|
61
61
|
#: reader, and the row already shows the text it applies to.
|
|
62
|
-
CONTINUATION = re.compile(r"\n?\.\.\. \[(?:line truncated|more lines)[^\]]*\]\s*\Z")
|
|
62
|
+
CONTINUATION = re.compile(r"\n?\.\.\. \[(?:line truncated|output truncated|more lines)[^\]]*\]\s*\Z")
|
|
63
63
|
|
|
64
64
|
#: Wrapper tags a model may leave around its reasoning channel.
|
|
65
65
|
REASONING_TAGS = re.compile(r"</?(?:think(?:ing)?|reasoning)>|<\|(?:thinking|reasoning)\|>", re.IGNORECASE)
|
|
@@ -229,38 +229,48 @@ def argument(arguments: Mapping[str, object], key: str, default: str = "") -> st
|
|
|
229
229
|
return default
|
|
230
230
|
|
|
231
231
|
|
|
232
|
-
def
|
|
232
|
+
def edit_changes(arguments: Mapping[str, object]) -> tuple[tuple[str, str], ...]:
|
|
233
|
+
"""Return the text pairs an ``edit`` call replaces: one pair now, a list of them from an older transcript.
|
|
234
|
+
|
|
235
|
+
A call carries ``old_string`` and ``new_string``. A session stored before that shape gave the arguments an
|
|
236
|
+
``edits`` list, and it is read the same way so the row of an old transcript still shows its diff. Anything
|
|
237
|
+
that is not two strings is dropped rather than guessed at.
|
|
238
|
+
"""
|
|
239
|
+
legacy = arguments.get("edits")
|
|
240
|
+
if isinstance(legacy, Sequence) and not isinstance(legacy, str):
|
|
241
|
+
return tuple(
|
|
242
|
+
(edit["old_text"], edit["new_text"])
|
|
243
|
+
for edit in legacy
|
|
244
|
+
if isinstance(edit, Mapping)
|
|
245
|
+
and isinstance(edit.get("old_text"), str)
|
|
246
|
+
and isinstance(edit.get("new_text"), str)
|
|
247
|
+
)
|
|
248
|
+
old_string, new_string = arguments.get("old_string"), arguments.get("new_string")
|
|
249
|
+
if isinstance(old_string, str) and isinstance(new_string, str):
|
|
250
|
+
return ((old_string, new_string),)
|
|
251
|
+
return ()
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def edited_lines(changes: Sequence[tuple[str, str]]) -> tuple[int, int]:
|
|
233
255
|
"""Return the lines an ``edit`` call adds and removes.
|
|
234
256
|
|
|
235
|
-
The tool answers ``Replaced
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
rewrite, and that is what a reader comparing two rows is looking at.
|
|
257
|
+
The tool answers ``Replaced 1 occurrence in app.py``, which says that a change landed but not how large it was:
|
|
258
|
+
a two-line fix and a two-hundred-line rewrite read the same. The call carries both texts, so the difference is
|
|
259
|
+
counted here — with :class:`difflib.SequenceMatcher` rather than by subtracting lengths, because a replacement
|
|
260
|
+
that keeps the lines around it should not read as a rewrite, and that is what a reader comparing two rows is
|
|
261
|
+
looking at.
|
|
241
262
|
|
|
242
263
|
Args:
|
|
243
|
-
|
|
244
|
-
mappings with ``old_text`` and ``new_text``. Anything else is ignored
|
|
245
|
-
rather than guessed at.
|
|
264
|
+
changes: The old and new text of each change, as :func:`edit_changes` reads them.
|
|
246
265
|
|
|
247
266
|
Returns:
|
|
248
|
-
``(added, removed)`` across every
|
|
249
|
-
countable, which is also what a call with no edits at all answers.
|
|
267
|
+
``(added, removed)`` across every change; ``(0, 0)`` when the call carried nothing countable.
|
|
250
268
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
answer is where that number appears.
|
|
269
|
+
A change that replaces every occurrence counts once, not once per occurrence: how many the file holds is
|
|
270
|
+
something only the file knows, and the tool's own answer is where that number appears.
|
|
254
271
|
"""
|
|
255
|
-
if not isinstance(edits, Sequence) or isinstance(edits, str):
|
|
256
|
-
return (0, 0)
|
|
257
272
|
added = removed = 0
|
|
258
|
-
for
|
|
259
|
-
if not isinstance(edit, Mapping):
|
|
260
|
-
continue
|
|
261
|
-
old_text, new_text = edit.get("old_text"), edit.get("new_text")
|
|
262
|
-
if not isinstance(old_text, str) or not isinstance(new_text, str):
|
|
263
|
-
continue
|
|
273
|
+
for old_text, new_text in changes:
|
|
264
274
|
matcher = difflib.SequenceMatcher(None, old_text.splitlines(), new_text.splitlines())
|
|
265
275
|
for tag, old_start, old_end, new_start, new_end in matcher.get_opcodes():
|
|
266
276
|
if tag in ("replace", "delete"):
|
|
@@ -270,31 +280,24 @@ def edited_lines(edits: object) -> tuple[int, int]:
|
|
|
270
280
|
return (added, removed)
|
|
271
281
|
|
|
272
282
|
|
|
273
|
-
def edit_diff(
|
|
283
|
+
def edit_diff(changes: Sequence[tuple[str, str]], *, limit: int = MAX_DIFF_ROWS) -> tuple[DiffRow, ...]:
|
|
274
284
|
"""Return the rows of the change an ``edit`` call makes.
|
|
275
285
|
|
|
276
|
-
Each
|
|
286
|
+
Each change carries the text it replaces and the text it puts there, so the change can be shown
|
|
277
287
|
without reading the file: the lines that differ, and one unchanged line around each so it reads in
|
|
278
|
-
place.
|
|
279
|
-
cut at ``limit`` rows with a last row saying so, because the
|
|
288
|
+
place. Changes are told apart by a labelled break when there is more than one — which only an older
|
|
289
|
+
transcript has — and what is kept is cut at ``limit`` rows with a last row saying so, because the
|
|
290
|
+
arguments can be a whole file.
|
|
280
291
|
|
|
281
292
|
Args:
|
|
282
|
-
|
|
283
|
-
two texts is skipped rather than guessed at, exactly as :func:`edited_lines` does.
|
|
293
|
+
changes: The old and new text of each change, as :func:`edit_changes` reads them.
|
|
284
294
|
limit: Most rows to keep.
|
|
285
295
|
"""
|
|
286
|
-
if not isinstance(edits, Sequence) or isinstance(edits, str):
|
|
287
|
-
return ()
|
|
288
|
-
usable = [
|
|
289
|
-
edit
|
|
290
|
-
for edit in edits
|
|
291
|
-
if isinstance(edit, Mapping) and isinstance(edit.get("old_text"), str) and isinstance(edit.get("new_text"), str)
|
|
292
|
-
]
|
|
293
296
|
rows: list[DiffRow] = []
|
|
294
|
-
for number,
|
|
295
|
-
if len(
|
|
296
|
-
rows.append(("@", f"edit {number} of {len(
|
|
297
|
-
old_lines, new_lines =
|
|
297
|
+
for number, (old_text, new_text) in enumerate(changes, start=1):
|
|
298
|
+
if len(changes) > 1:
|
|
299
|
+
rows.append(("@", f"edit {number} of {len(changes)}"))
|
|
300
|
+
old_lines, new_lines = old_text.splitlines(), new_text.splitlines()
|
|
298
301
|
opcodes = difflib.SequenceMatcher(None, old_lines, new_lines).get_opcodes()
|
|
299
302
|
for index, (tag, old_start, old_end, new_start, new_end) in enumerate(opcodes):
|
|
300
303
|
if tag == "equal":
|
|
@@ -382,6 +385,15 @@ def _value_text(value: object) -> str:
|
|
|
382
385
|
return str(value)
|
|
383
386
|
|
|
384
387
|
|
|
388
|
+
def file_path(arguments: Mapping[str, object], default: str = "") -> str:
|
|
389
|
+
"""Return the path a file tool was called for.
|
|
390
|
+
|
|
391
|
+
``file_path`` is the argument now; a session stored before the rename carries ``path``, and is still shown the
|
|
392
|
+
file it changed rather than as an unknown one.
|
|
393
|
+
"""
|
|
394
|
+
return argument(arguments, "file_path") or argument(arguments, "path") or default
|
|
395
|
+
|
|
396
|
+
|
|
385
397
|
def language_for_path(path: str) -> str | None:
|
|
386
398
|
"""Return the scanner for a file's contents, or ``None`` when it is not code."""
|
|
387
399
|
language = language_for(Path(path).suffix.lstrip("."))
|
|
@@ -395,7 +407,7 @@ class ReadTool(ToolHandler):
|
|
|
395
407
|
|
|
396
408
|
def describe(self, name: str, arguments: Mapping[str, object]) -> ToolRow:
|
|
397
409
|
"""Show the file, and highlight the body as the language it is."""
|
|
398
|
-
path =
|
|
410
|
+
path = file_path(arguments, "(unknown file)")
|
|
399
411
|
return ToolRow(f"Read {path}", language_for_path(path))
|
|
400
412
|
|
|
401
413
|
def open_tool(
|
|
@@ -403,7 +415,7 @@ class ReadTool(ToolHandler):
|
|
|
403
415
|
) -> ToolEntry:
|
|
404
416
|
"""A read row, which knows the language its body is in, and whether the file is a picture."""
|
|
405
417
|
row = self.describe(name, arguments)
|
|
406
|
-
path =
|
|
418
|
+
path = file_path(arguments)
|
|
407
419
|
return ReadEntry(
|
|
408
420
|
id=id,
|
|
409
421
|
call_id=call_id,
|
|
@@ -437,7 +449,7 @@ class WriteTool(ToolHandler):
|
|
|
437
449
|
|
|
438
450
|
def describe(self, name: str, arguments: Mapping[str, object]) -> ToolRow:
|
|
439
451
|
"""Show the file being written: the row is the call, so it says what the call does, not what it did."""
|
|
440
|
-
return ToolRow(f"Write {
|
|
452
|
+
return ToolRow(f"Write {file_path(arguments, '(unknown file)')}")
|
|
441
453
|
|
|
442
454
|
def open_tool(
|
|
443
455
|
self, name: str, arguments: Mapping[str, object], *, id: int, call_id: str, started_at: float
|
|
@@ -449,7 +461,7 @@ class WriteTool(ToolHandler):
|
|
|
449
461
|
call_id=call_id,
|
|
450
462
|
tool=name,
|
|
451
463
|
title=self.describe(name, arguments).title,
|
|
452
|
-
path=
|
|
464
|
+
path=file_path(arguments),
|
|
453
465
|
added=written_lines(content),
|
|
454
466
|
diff=write_diff(content),
|
|
455
467
|
started_at=started_at,
|
|
@@ -457,25 +469,21 @@ class WriteTool(ToolHandler):
|
|
|
457
469
|
|
|
458
470
|
|
|
459
471
|
class EditTool(ToolHandler):
|
|
460
|
-
"""``edit``: the file and
|
|
472
|
+
"""``edit``: the file, and the size of the one change the call makes.
|
|
461
473
|
|
|
462
|
-
A session stored before the tool was renamed calls it ``replace_in_file``, and is still shown the same way
|
|
474
|
+
A session stored before the tool was renamed calls it ``replace_in_file``, and is still shown the same way; one
|
|
475
|
+
stored before a call carried a single change gave it a list under ``edits``, and that list is read too.
|
|
463
476
|
"""
|
|
464
477
|
|
|
465
478
|
names = frozenset({"edit", "replace_in_file"})
|
|
466
479
|
|
|
467
480
|
def describe(self, name: str, arguments: Mapping[str, object]) -> ToolRow:
|
|
468
|
-
"""
|
|
481
|
+
"""Show the file; the size of the change is drawn beside the title, before it lands.
|
|
469
482
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
a tweak or a rewrite, which is the question a reader asks the row.
|
|
483
|
+
`+12 -3` beside the file says whether this is a tweak or a rewrite, which is the question a reader asks
|
|
484
|
+
the row. One change a call is why the title counts nothing: a count of one is noise on every row.
|
|
473
485
|
"""
|
|
474
|
-
|
|
475
|
-
edits = arguments.get("edits")
|
|
476
|
-
count = len(edits) if isinstance(edits, Sequence) and not isinstance(edits, str) else 0
|
|
477
|
-
suffix = f" ({count} edit{'' if count == 1 else 's'})" if count else ""
|
|
478
|
-
return ToolRow(f"Edited {path}{suffix}")
|
|
486
|
+
return ToolRow(f"Edit {file_path(arguments, '(unknown file)')}")
|
|
479
487
|
|
|
480
488
|
def open_tool(
|
|
481
489
|
self, name: str, arguments: Mapping[str, object], *, id: int, call_id: str, started_at: float
|
|
@@ -485,17 +493,17 @@ class EditTool(ToolHandler):
|
|
|
485
493
|
The counts ride outside the title: they are drawn in the colours an addition and a
|
|
486
494
|
deletion get, which a title made of one string cannot be.
|
|
487
495
|
"""
|
|
488
|
-
|
|
489
|
-
added, removed = edited_lines(
|
|
496
|
+
changes = edit_changes(arguments)
|
|
497
|
+
added, removed = edited_lines(changes)
|
|
490
498
|
return EditEntry(
|
|
491
499
|
id=id,
|
|
492
500
|
call_id=call_id,
|
|
493
501
|
tool=name,
|
|
494
502
|
title=self.describe(name, arguments).title,
|
|
495
|
-
path=
|
|
503
|
+
path=file_path(arguments),
|
|
496
504
|
added=added,
|
|
497
505
|
removed=removed,
|
|
498
|
-
diff=edit_diff(
|
|
506
|
+
diff=edit_diff(changes),
|
|
499
507
|
started_at=started_at,
|
|
500
508
|
)
|
|
501
509
|
|
|
@@ -507,7 +515,7 @@ class DeleteTool(ToolHandler):
|
|
|
507
515
|
|
|
508
516
|
def describe(self, name: str, arguments: Mapping[str, object]) -> ToolRow:
|
|
509
517
|
"""Show the file being removed."""
|
|
510
|
-
return ToolRow(f"Deleted {
|
|
518
|
+
return ToolRow(f"Deleted {file_path(arguments, '(unknown file)')}")
|
|
511
519
|
|
|
512
520
|
def open_tool(
|
|
513
521
|
self, name: str, arguments: Mapping[str, object], *, id: int, call_id: str, started_at: float
|
|
@@ -518,19 +526,21 @@ class DeleteTool(ToolHandler):
|
|
|
518
526
|
call_id=call_id,
|
|
519
527
|
tool=name,
|
|
520
528
|
title=self.describe(name, arguments).title,
|
|
521
|
-
path=
|
|
529
|
+
path=file_path(arguments),
|
|
522
530
|
started_at=started_at,
|
|
523
531
|
)
|
|
524
532
|
|
|
525
533
|
|
|
526
534
|
class ShellTool(ToolHandler):
|
|
527
|
-
"""``bash``: the command itself,
|
|
535
|
+
"""``bash``: the command itself, and the directory it runs in when the call names one."""
|
|
528
536
|
|
|
529
537
|
names = frozenset({"bash"})
|
|
530
538
|
|
|
531
539
|
def describe(self, name: str, arguments: Mapping[str, object]) -> ToolRow:
|
|
532
|
-
"""Show the command, not a JSON copy of it."""
|
|
533
|
-
|
|
540
|
+
"""Show the command, not a JSON copy of it, and where it runs when that is not the workspace."""
|
|
541
|
+
command = argument(arguments, "command", "(unknown command)")
|
|
542
|
+
where = argument(arguments, "work_dir")
|
|
543
|
+
return ToolRow(f"Bash {command}" + (f" {SEPARATOR} {where}" if where else ""))
|
|
534
544
|
|
|
535
545
|
|
|
536
546
|
class SearchTool(ToolHandler):
|
|
@@ -543,7 +553,7 @@ class SearchTool(ToolHandler):
|
|
|
543
553
|
pattern = argument(arguments, "pattern")
|
|
544
554
|
if name == "glob":
|
|
545
555
|
return ToolRow(f"Listed {pattern}" if pattern else "Listed files")
|
|
546
|
-
where = argument(arguments, "path")
|
|
556
|
+
where = argument(arguments, "file_pattern") or argument(arguments, "path")
|
|
547
557
|
return ToolRow(f"Searched {pattern or 'the workspace'}" + (f" in {where}" if where else ""))
|
|
548
558
|
|
|
549
559
|
|
|
@@ -252,7 +252,7 @@ class Command:
|
|
|
252
252
|
its sessions, or the model, and is handled by
|
|
253
253
|
:class:`~zettcode.app.agent.TerminalAgent`; ``"plugin"`` comes from
|
|
254
254
|
an installed plugin, registered through
|
|
255
|
-
:class:`~zettcode.
|
|
255
|
+
:class:`~zettcode.engine.plugins.context.PluginContext`.
|
|
256
256
|
handler: Runs the command with a :class:`CommandContext` — the trimmed
|
|
257
257
|
argument and the UI surfaces it may write to while it works — and
|
|
258
258
|
returns a :class:`CommandResult` describing anything left to show.
|
|
@@ -7,7 +7,7 @@ it, moves it, and picks the mood.
|
|
|
7
7
|
|
|
8
8
|
Pets are offered the way palettes are: a :class:`PetSource` names one and builds it only when it is asked for,
|
|
9
9
|
the built-in plugin offers the ones that ship, and any other plugin offers its own through
|
|
10
|
-
``
|
|
10
|
+
``ctx.tui.register_pet``. :class:`PetCatalog` is what ``/pet`` and the start-up read.
|
|
11
11
|
|
|
12
12
|
Every frame of a pet is the same size, and its height is an even number of pixel rows: two pixels fit in
|
|
13
13
|
one terminal cell.
|
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
"""The terminal's
|
|
1
|
+
"""The terminal's plugins: the row hooks, the groups a shell plugin registers into, and the bundle it produces.
|
|
2
2
|
|
|
3
|
-
A plugin
|
|
3
|
+
A plugin subclasses :class:`~zettcode.engine.plugins.Plugin` (or :class:`TuiPlugin` to override a row hook) and
|
|
4
|
+
registers through ``ctx``::
|
|
4
5
|
|
|
5
|
-
from zettcode.app.plugins import
|
|
6
|
+
from zettcode.app.plugins import TuiPlugin
|
|
7
|
+
from zettcode.engine.plugins import PluginContext
|
|
6
8
|
|
|
7
|
-
class Greeter(
|
|
9
|
+
class Greeter(TuiPlugin):
|
|
8
10
|
name = "greeter"
|
|
9
11
|
|
|
10
|
-
def activate(self,
|
|
11
|
-
|
|
12
|
+
def activate(self, ctx: PluginContext) -> None:
|
|
13
|
+
ctx.tui.register_command("greet", "say hello", self.greet)
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
It is built on :mod:`zettcode.engine.plugins`, which has what the agent uses. The pieces live in
|
|
17
|
-
:mod:`~zettcode.app.plugins.state` (the snapshot and segment types), :mod:`~zettcode.app.plugins.mixins` (the row
|
|
18
|
-
hooks), :mod:`~zettcode.app.plugins.container`, :mod:`~zettcode.app.plugins.plugin`, and
|
|
19
|
-
:mod:`~zettcode.app.plugins.loader`. Names load on first use, so importing one does not build the rest.
|
|
15
|
+
:class:`TuiPlugin` is the engine's base class with :class:`PluginUiMixin`; the shell's commands, palettes, pets,
|
|
16
|
+
presenters and rows live in :class:`~zettcode.app.plugins.groups.TuiGroups`, which is ``ctx.tui`` — ``None`` in a
|
|
17
|
+
process without a terminal, which is why a shell-only plugin starts ``activate`` with ``if ctx.tui is None: return``.
|
|
20
18
|
"""
|
|
21
19
|
|
|
22
20
|
from __future__ import annotations
|
|
@@ -39,10 +37,11 @@ _EXPORTS = {
|
|
|
39
37
|
"UiSegment": ".state",
|
|
40
38
|
"UiSide": ".state",
|
|
41
39
|
"PluginUiMixin": ".mixins",
|
|
42
|
-
"
|
|
43
|
-
"UiSlots": ".
|
|
44
|
-
"
|
|
45
|
-
"
|
|
40
|
+
"PluginContext": "zettcode.engine.plugins.context",
|
|
41
|
+
"UiSlots": ".groups",
|
|
42
|
+
"TuiGroups": ".groups",
|
|
43
|
+
"TuiPlugin": ".plugin",
|
|
44
|
+
"TuiPlugins": ".plugin",
|
|
46
45
|
"TerminalLoader": ".loader",
|
|
47
46
|
"load_terminal_plugins": ".loader",
|
|
48
47
|
"HOST_LINK": ".host",
|
|
@@ -51,12 +50,14 @@ _EXPORTS = {
|
|
|
51
50
|
|
|
52
51
|
|
|
53
52
|
if TYPE_CHECKING: # pragma: no cover - for type checkers, not the runtime
|
|
53
|
+
from zettcode.engine.plugins.context import PluginContext
|
|
54
|
+
|
|
54
55
|
from .builtins import BUILTIN_PLUGINS
|
|
55
|
-
from .
|
|
56
|
+
from .groups import UiSlots
|
|
56
57
|
from .host import HOST_LINK, HostLink
|
|
57
58
|
from .loader import TerminalLoader, load_terminal_plugins
|
|
58
59
|
from .mixins import PluginUiMixin
|
|
59
|
-
from .plugin import
|
|
60
|
+
from .plugin import TuiPlugin, TuiPlugins
|
|
60
61
|
from .state import (
|
|
61
62
|
Activity,
|
|
62
63
|
ActivityState,
|
|
@@ -95,12 +96,13 @@ __all__ = [
|
|
|
95
96
|
"HostLink",
|
|
96
97
|
"ModelState",
|
|
97
98
|
"PluginUiMixin",
|
|
99
|
+
"TuiGroups",
|
|
98
100
|
"SessionState",
|
|
99
101
|
"ShellContext",
|
|
100
|
-
"
|
|
102
|
+
"PluginContext",
|
|
101
103
|
"TerminalLoader",
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
+
"TuiPlugin",
|
|
105
|
+
"TuiPlugins",
|
|
104
106
|
"UiBuilder",
|
|
105
107
|
"UiRegion",
|
|
106
108
|
"UiRow",
|