zettcode 0.3.1__tar.gz → 0.3.2__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.3.1 → zettcode-0.3.2}/PKG-INFO +7 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/pyproject.toml +6 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/__init__.py +1 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/agent/commands.py +41 -5
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/entries.py +4 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/presenters.py +4 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/projection.py +56 -7
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/rendering.py +38 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/text.py +8 -5
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/tips.py +1 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/transcript/oneoff.py +2 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/transcript/stream.py +11 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/transcript/turn.py +10 -3
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/commands.py +23 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/plugins/builtin_commands.py +57 -69
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/plugins/builtins.py +4 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/plugins/groups.py +51 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/plugins/loader.py +36 -11
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/plugins/plugin.py +7 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/plugins/state.py +4 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/app.py +272 -29
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/bars.py +11 -7
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/boot.py +8 -3
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/commands.py +78 -58
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/followups.py +17 -13
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/keys.py +21 -3
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/labels.py +19 -3
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/messaging.py +57 -4
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/notices.py +2 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/providers.py +21 -10
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/sessions.py +8 -4
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/settings.py +3 -3
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/shell.py +43 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/__init__.py +8 -0
- zettcode-0.3.2/src/zettcode/app/ui/widgets/document_page.py +159 -0
- zettcode-0.3.2/src/zettcode/app/ui/widgets/harness_page.py +47 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/plugins_page.py +3 -3
- zettcode-0.3.2/src/zettcode/app/ui/widgets/sessions_page.py +512 -0
- zettcode-0.3.2/src/zettcode/broker/cli.py +236 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/client.py +169 -19
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/files.py +2 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/finder.py +2 -5
- zettcode-0.3.2/src/zettcode/broker/hub.py +723 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/models.py +46 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/process.py +2 -49
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/protocol.py +74 -16
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/runner.py +33 -5
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/server.py +5 -7
- zettcode-0.3.2/src/zettcode/broker/store.py +330 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/web.py +67 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/cli.py +134 -6
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/config.py +121 -36
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/config_edit.py +73 -15
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/daemon/__init__.py +4 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/daemon/cli.py +281 -42
- zettcode-0.3.2/src/zettcode/daemon/companions.py +62 -0
- zettcode-0.3.2/src/zettcode/daemon/process.py +486 -0
- zettcode-0.3.2/src/zettcode/daemon/run.py +639 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/daemon/state.py +53 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/agent/context.py +30 -6
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/agent/exports.py +8 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/agent/sessions.py +1 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/agent/settings.py +33 -14
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/agent/turns.py +30 -3
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/core.py +62 -11
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/dialogue/side.py +1 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/export/__init__.py +0 -5
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/compaction.py +74 -3
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/harness.py +11 -2
- zettcode-0.3.2/src/zettcode/engine/extensions/messaging.py +279 -0
- zettcode-0.3.2/src/zettcode/engine/extensions/usage.py +348 -0
- zettcode-0.3.2/src/zettcode/engine/harness_paths.py +74 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/messenger.py +38 -9
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/__init__.py +1 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/builtin_agent.py +41 -10
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/commands.py +22 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/context.py +6 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/groups.py +0 -6
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/loader.py +107 -20
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/plugin.py +2 -2
- zettcode-0.3.2/src/zettcode/engine/plugins/settings.py +117 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/switches.py +216 -75
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/storage/store.py +95 -30
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/__init__.py +2 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/app.py +42 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/backend.py +57 -2
- zettcode-0.3.2/src/zettcode/gateway/cli.py +494 -0
- zettcode-0.3.2/src/zettcode/gateway/runfile.py +145 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/service.py +205 -23
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/app.css +617 -20
- zettcode-0.3.2/src/zettcode/gateway/static/app.js +3 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/index.html +1 -1
- zettcode-0.3.2/src/zettcode/logging_setup.py +196 -0
- zettcode-0.3.2/src/zettcode/modes.py +18 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/paths.py +36 -0
- zettcode-0.3.2/src/zettcode/plugin_cli.py +742 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/plugin_tui.py +29 -0
- zettcode-0.3.2/src/zettcode/processes.py +126 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/relay.py +24 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/__init__.py +3 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/client.py +109 -14
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/daemons.py +62 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/models.py +10 -12
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/session.py +70 -13
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/translation.py +1 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/types.py +49 -9
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/server/app.py +20 -11
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/server/runner.py +108 -87
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/server/schemas.py +14 -2
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/server/serialize.py +1 -0
- zettcode-0.3.2/src/zettcode/table.py +95 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/app.py +92 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/input/bridge.py +3 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/input/decoder.py +11 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/input/events.py +5 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/layout/scroll.py +82 -7
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/runner.py +4 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/terminal.py +12 -1
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/markdown.py +17 -8
- zettcode-0.3.1/src/zettcode/app/ui/widgets/sessions_page.py +0 -268
- zettcode-0.3.1/src/zettcode/broker/hub.py +0 -349
- zettcode-0.3.1/src/zettcode/daemon/process.py +0 -270
- zettcode-0.3.1/src/zettcode/daemon/run.py +0 -343
- zettcode-0.3.1/src/zettcode/engine/extensions/messaging.py +0 -130
- zettcode-0.3.1/src/zettcode/engine/extensions/usage.py +0 -184
- zettcode-0.3.1/src/zettcode/gateway/cli.py +0 -138
- zettcode-0.3.1/src/zettcode/gateway/static/app.js +0 -3
- {zettcode-0.3.1 → zettcode-0.3.2}/.gitignore +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/README.md +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/_compat.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/agent/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/agent/settings.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/changes.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/effort_gauge.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/pulse.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/replay.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/shimmer.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/stops.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/transcript/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/transcript/fold.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/agent/conversation/transcript/log.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/brand.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/commandline/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/commandline/arguments.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/commandline/completion.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/commandline/history.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/commandline/runner.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/cat.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/chibi.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/dog.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/kangaroo.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/model.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/penguin.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/polarbear.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/scarfy.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/seagull.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/slime.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/snowbear.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/sprout.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/tiger.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/pets/whale.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/plugins/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/plugins/host.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/plugins/mixins.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/clipboard.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/config_form.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/demo.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/gc_policy.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/turns.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/updating.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/approval_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/ask_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/bash_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/completer.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/composer.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/context_charts.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/context_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/effort_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/follow_up.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/form_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/input_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/model_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/model_settings_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/panel.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/pet.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/pet_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/root.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/self_compact_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/send_kind_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/statusline_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/steering.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/switch.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/transcript.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/update_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/usage_charts.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/usage_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/app/ui/widgets/welcome.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/__main__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/log.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/roster.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/broker/text.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/budget.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/collector.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/daemon/__main__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/doctor.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/agent/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/agent/base.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/agent/interaction.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/dialogue/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/dialogue/ask.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/dialogue/title.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/export/trace/script.js +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/export/trace/style.css +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/export/trace/template.html +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/capabilities.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/context.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/files.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/harness_switch.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/mcp.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/mcp_notice.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/relay.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/subagents.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/tool_output.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/extensions/truncation.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/permission/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/permission/approval.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/permission/readonly.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/permission/sandbox.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/pipeline.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/extension.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/mixins.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/services.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/plugins/state.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/server_tools.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/storage/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/storage/layout.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/storage/ledger.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/storage/locks.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/storage/metadata.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/storage/records.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/tools/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/tools/boundary.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/tools/files.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/tools/images.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/tools/output.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/tools/shell.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/engine/tools/workspace.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/error_text.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/filelock.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/chat.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/settings.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_AMS-Regular-U6PRYMIZ.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Caligraphic-Bold-5QL5CMTE.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Caligraphic-Regular-KX5MEWCF.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Fraktur-Bold-2QVFK6NQ.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Fraktur-Regular-2PEIFJSJ.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Main-Bold-YP5VVQRP.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Main-BoldItalic-N4V3DX7S.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Main-Italic-RELBIK7M.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Main-Regular-ARRPAO67.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Math-BoldItalic-K4WTGH3J.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Math-Italic-6KGCHLFN.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_SansSerif-Bold-RRNVJFFW.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_SansSerif-Italic-HMPFTM52.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_SansSerif-Regular-XIQ62X4E.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Script-Regular-APUWIHLP.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Size1-Regular-5LRUTBFT.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Size2-Regular-LELKET5D.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Size3-Regular-WQRQ47UD.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Size4-Regular-CDMV7U5C.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/assets/KaTeX_Typewriter-Regular-VBYJ4NRC.woff2 +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/chunks/chunk-Y6SLVHK3.js +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/chunks/render-G6G3TSB3.js +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/icon.png +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/logo.svg +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/gateway/static/manifest.webmanifest +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/mentions.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/oneshot.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/prompt.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/providers.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/py.typed +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/registry.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/commands.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/errors.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/events.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/sdk/handlers.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/server/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/server/cli.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/server/settings.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/statusline.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/capabilities.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/clipboard.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/console.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/events.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/focus.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/geometry.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/host.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/keymap.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/scheduler.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/screen.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/theme.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/core/widget.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/gallery.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/glyphs.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/input/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/input/keys.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/input/reader.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/layout/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/layout/box.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/layout/overlay.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/layout/solver.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/layout/spacing.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/render/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/render/ansi.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/render/canvas.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/render/code.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/render/color.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/render/renderer.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/render/rich_text.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/render/style.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/render/sweep.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/render/text.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/testing/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/testing/harness.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/testing/snapshot.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/theme_file.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/ayu-mirage.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/catppuccin-latte.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/catppuccin-mocha.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/dracula.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/github-dimmed.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/github-light.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/gruvbox-dark.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/gruvbox-light.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/kanagawa.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/nord.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/one-dark.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/rose-pine-dawn.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/rose-pine.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/solarized-dark.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/solarized-light.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/themes/tokyo-night.toml +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/__init__.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/collapsible.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/completion.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/console.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/dialog.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/diff.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/list.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/list_page.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/progress.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/rich_text.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/status.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/table.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/tasks.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/text.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/textarea.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/tui/widgets/toast.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/update.py +0 -0
- {zettcode-0.3.1 → zettcode-0.3.2}/src/zettcode/wording.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: zettcode
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
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,9 +35,14 @@ 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.4
|
|
39
|
+
Provides-Extra: all
|
|
40
|
+
Requires-Dist: zettcode-monitor<0.3,>=0.2; extra == 'all'
|
|
41
|
+
Requires-Dist: zettcode-recap<0.2,>=0.1; extra == 'all'
|
|
39
42
|
Provides-Extra: monitor
|
|
40
43
|
Requires-Dist: zettcode-monitor<0.3,>=0.2; extra == 'monitor'
|
|
44
|
+
Provides-Extra: recap
|
|
45
|
+
Requires-Dist: zettcode-recap<0.2,>=0.1; extra == 'recap'
|
|
41
46
|
Description-Content-Type: text/markdown
|
|
42
47
|
|
|
43
48
|
# ZettCode
|
|
@@ -61,7 +61,7 @@ dependencies = [
|
|
|
61
61
|
# now leans on: a hosted tool the provider left open is closed with
|
|
62
62
|
# ``output={"status": "not_reported"}`` instead of leaving the step waiting, and
|
|
63
63
|
# `engine/server_tools.describe_output` reads that to say so.
|
|
64
|
-
"zett-agent>=0.2.
|
|
64
|
+
"zett-agent>=0.2.4,<0.3",
|
|
65
65
|
]
|
|
66
66
|
|
|
67
67
|
[project.optional-dependencies]
|
|
@@ -72,11 +72,15 @@ dependencies = [
|
|
|
72
72
|
# that accepts it (its range has to allow both lines in between), or `pip install zettcode==<new>` would fail to
|
|
73
73
|
# resolve, and so would the environment the VS Code extension builds for itself.
|
|
74
74
|
monitor = ["zettcode-monitor>=0.2,<0.3"]
|
|
75
|
+
# `/recap` for a reader who steps away. Published on its own line like the one above, and an extra for the same
|
|
76
|
+
# reason: a hard edge would tie the two releases together.
|
|
77
|
+
recap = ["zettcode-recap>=0.1,<0.2"]
|
|
78
|
+
# Every plugin this repository publishes, for a reader who wants the lot: `pip install "zettcode[all]"`.
|
|
79
|
+
all = ["zettcode-monitor>=0.2,<0.3", "zettcode-recap>=0.1,<0.2"]
|
|
75
80
|
|
|
76
81
|
[project.scripts]
|
|
77
82
|
zettcode = "zettcode.cli:main"
|
|
78
83
|
zettcode-server = "zettcode.server.cli:main"
|
|
79
|
-
zettcode-gateway = "zettcode.gateway.cli:main"
|
|
80
84
|
|
|
81
85
|
[project.urls]
|
|
82
86
|
Repository = "https://github.com/Chang-LeHung/zettcode"
|
|
@@ -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.3.
|
|
10
|
+
__version__ = "0.3.2"
|
|
11
11
|
|
|
12
12
|
#: Where each public name lives; read by :func:`__getattr__` on first use.
|
|
13
13
|
_EXPORTS = {
|
|
@@ -7,6 +7,9 @@ agent is where the shell asks for everything the runtime loaded.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
import asyncio
|
|
11
|
+
from collections.abc import Callable
|
|
12
|
+
|
|
10
13
|
from zettcode.app.commands import Command, CommandContext, CommandHost, CommandResult
|
|
11
14
|
from zettcode.app.pets import PetCatalog, bundled_pets
|
|
12
15
|
from zettcode.app.plugins.host import HOST_LINK, HostLink
|
|
@@ -116,6 +119,21 @@ class CommandsMixin(AppearanceMixin, ExportsMixin):
|
|
|
116
119
|
"""Return the header and status rows plugins asked the shell to draw."""
|
|
117
120
|
return self.terminal_plugins.rows
|
|
118
121
|
|
|
122
|
+
@property
|
|
123
|
+
def plugin_focus_handlers(self) -> tuple[Callable[[bool], None], ...]:
|
|
124
|
+
"""Return the handlers told when the terminal window gains or loses focus."""
|
|
125
|
+
return self.terminal_plugins.focus_handlers
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def plugin_turn_start_handlers(self) -> tuple[Callable[[], None], ...]:
|
|
129
|
+
"""Return the handlers told when a turn of the conversation starts."""
|
|
130
|
+
return self.terminal_plugins.turn_start_handlers
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def plugin_turn_end_handlers(self) -> tuple[Callable[[bool], None], ...]:
|
|
134
|
+
"""Return the handlers told when a turn of the conversation ends."""
|
|
135
|
+
return self.terminal_plugins.turn_end_handlers
|
|
136
|
+
|
|
119
137
|
async def _command_new(self, context: CommandContext) -> CommandResult:
|
|
120
138
|
"""Start a fresh session."""
|
|
121
139
|
session_id = self.new_session()
|
|
@@ -218,10 +236,28 @@ class CommandsMixin(AppearanceMixin, ExportsMixin):
|
|
|
218
236
|
async def _command_compact(self, context: CommandContext) -> CommandResult:
|
|
219
237
|
"""Summarize the conversation now, whatever its size.
|
|
220
238
|
|
|
221
|
-
The row
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
239
|
+
The row is opened only after the refusal check. That check may read a
|
|
240
|
+
cold session on a worker, so the interface stays live while it runs;
|
|
241
|
+
once the row is up, the shell draws it before the pass starts. What
|
|
242
|
+
follows the first ``await`` is still synchronous token counting and the
|
|
243
|
+
summary request, so a row created only by ``CompactionStarted`` would
|
|
244
|
+
reach the screen after the work it was meant to explain.
|
|
225
245
|
"""
|
|
226
|
-
|
|
246
|
+
host = context.host
|
|
247
|
+
if host is not None:
|
|
248
|
+
await self.ensure_compactable()
|
|
249
|
+
host.transcript.start_compaction()
|
|
250
|
+
try:
|
|
251
|
+
if host is not None:
|
|
252
|
+
await host.wait_for_frame()
|
|
253
|
+
await self._compact_pass()
|
|
254
|
+
else:
|
|
255
|
+
await self.compact()
|
|
256
|
+
except asyncio.CancelledError:
|
|
257
|
+
if host is not None:
|
|
258
|
+
host.transcript.complete_compaction("Compacting stopped")
|
|
259
|
+
raise
|
|
260
|
+
finally:
|
|
261
|
+
if host is not None:
|
|
262
|
+
host.transcript.complete_compaction()
|
|
227
263
|
return CommandResult()
|
|
@@ -321,6 +321,8 @@ class MessageEntry(ToolEntry):
|
|
|
321
321
|
|
|
322
322
|
to: str = ""
|
|
323
323
|
message: str = ""
|
|
324
|
+
#: The group chat it was written to (without the ``#``), or empty for one session: the row says which.
|
|
325
|
+
group: str = ""
|
|
324
326
|
|
|
325
327
|
@property
|
|
326
328
|
def foldable(self) -> bool:
|
|
@@ -378,3 +380,5 @@ class RelayEntry(Entry):
|
|
|
378
380
|
by_agent: bool = True
|
|
379
381
|
external: bool = False
|
|
380
382
|
note: str = ""
|
|
383
|
+
#: The group chat it was written in (without the ``#``); empty for a one-to-one message.
|
|
384
|
+
group: str = ""
|
|
@@ -440,6 +440,10 @@ class RelayPresenter(Presenter[RelayEntry]):
|
|
|
440
440
|
else f"\u2190 {'agent' if entry.by_agent else 'user'} of session {peer}"
|
|
441
441
|
)
|
|
442
442
|
detail = ""
|
|
443
|
+
if entry.group:
|
|
444
|
+
# A group message is read by every member: say so in the header, where a one-to-one message has nothing.
|
|
445
|
+
label += f" in #{terminal_safe(entry.group)}"
|
|
446
|
+
detail = f" {SEPARATOR} to the whole group"
|
|
443
447
|
|
|
444
448
|
def row(*spans: Span) -> TextLine:
|
|
445
449
|
used = sum(display_width(span.text) for span in spans)
|
|
@@ -7,6 +7,7 @@ terminal shows and what the SDK reports cannot drift apart.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
import logging
|
|
10
11
|
from collections.abc import Callable
|
|
11
12
|
|
|
12
13
|
from zett_agent.dispatcher import AgentEventDispatcher
|
|
@@ -55,6 +56,9 @@ class _NobodyAnswers:
|
|
|
55
56
|
raise RuntimeError("This projector has no agent to carry an answer to")
|
|
56
57
|
|
|
57
58
|
|
|
59
|
+
logger = logging.getLogger("zettcode.terminal")
|
|
60
|
+
|
|
61
|
+
|
|
58
62
|
class TranscriptProjector(AgentEventDispatcher):
|
|
59
63
|
"""Turn AgentClient callbacks into transcript blocks.
|
|
60
64
|
|
|
@@ -71,8 +75,9 @@ class TranscriptProjector(AgentEventDispatcher):
|
|
|
71
75
|
on_approval: Callable[[ApprovalRequested], None] | None = None,
|
|
72
76
|
on_ask: Callable[[QuestionAsked], None] | None = None,
|
|
73
77
|
on_usage: Callable[[Usage, str], None] | None = None,
|
|
74
|
-
on_steering_started: Callable[[str], None] | None = None,
|
|
78
|
+
on_steering_started: Callable[[str], Relayed | str | None] | None = None,
|
|
75
79
|
on_steering_interrupted: Callable[[str], None] | None = None,
|
|
80
|
+
side_running: Callable[[], bool] | None = None,
|
|
76
81
|
) -> None:
|
|
77
82
|
"""Send projected events to ``transcript``; approvals go to ``on_approval``.
|
|
78
83
|
|
|
@@ -89,9 +94,18 @@ class TranscriptProjector(AgentEventDispatcher):
|
|
|
89
94
|
the shell can refresh the status line without polling the store.
|
|
90
95
|
on_steering_started: Called with the text of a queued steering
|
|
91
96
|
message the agent just adopted, so the shell can drop it from
|
|
92
|
-
the pending queue before the row is echoed.
|
|
97
|
+
the pending queue before the row is echoed. What it returns, when
|
|
98
|
+
it is a :class:`~zettcode.relay.Relayed`, is drawn as that session's
|
|
99
|
+
message — what its sender wrote, not the line the model reads; a
|
|
100
|
+
string is drawn as the row's text.
|
|
93
101
|
on_steering_interrupted: Called with the text of a steering message
|
|
94
102
|
a newer one superseded, so the shell can drop it too.
|
|
103
|
+
side_running: Asked whether the run in flight is a side question — a question the model answers without
|
|
104
|
+
the exchange joining the conversation. Such a run is drawn only when the shell began it, so a
|
|
105
|
+
plugin that asks one for itself (a recap) is not also drawn as an answer of its own. ``None``
|
|
106
|
+
treats every run as one the shell began. Two plain flags are enough here because the SDK runs one
|
|
107
|
+
request at a time: a second run is refused while one is in flight, so a plugin's ask cannot
|
|
108
|
+
overlap a turn the shell began and a stale answer cannot be drawn as a turn's.
|
|
95
109
|
"""
|
|
96
110
|
self.transcript = transcript
|
|
97
111
|
self.bridge: Bridge = bridge if bridge is not None else _NobodyAnswers()
|
|
@@ -103,27 +117,58 @@ class TranscriptProjector(AgentEventDispatcher):
|
|
|
103
117
|
#: What a hosted tool's input has streamed so far, by call. The translation fills it as fragments arrive
|
|
104
118
|
#: and reads the query out of it when the call reports back.
|
|
105
119
|
self._hosted: dict[str, str] = {}
|
|
120
|
+
#: Whether the shell began the run in flight, and so draws it.
|
|
121
|
+
self._begun = False
|
|
122
|
+
#: Whether a run nobody began has been reported as left out, so dropping one is a line and not one per
|
|
123
|
+
#: token; it is cleared when a turn is begun, so it reports the next run that way too.
|
|
124
|
+
self._reported_side = False
|
|
125
|
+
self._side_running = side_running
|
|
106
126
|
|
|
107
127
|
def begin_turn(self, prompt: str, *, side: bool = False, relayed: Relayed | None = None) -> None:
|
|
108
|
-
"""
|
|
128
|
+
"""Begin drawing one run into the transcript, echoing the prompt that asked for it.
|
|
129
|
+
|
|
130
|
+
The shell begins a turn before every run it shows on screen, which is also how a side question it asked
|
|
131
|
+
is told apart from one a plugin asked for itself: see ``side_running``.
|
|
109
132
|
|
|
110
133
|
Args:
|
|
111
|
-
prompt: What the reader asked.
|
|
134
|
+
prompt: What the reader asked, echoed as the turn's first row.
|
|
112
135
|
side: The question is a side one, which the transcript shows as such.
|
|
113
136
|
relayed: The turn answers a message another session sent, which the transcript shows as that.
|
|
114
137
|
"""
|
|
138
|
+
# The row first, the flag second: an echo that raises leaves no run to draw, and a flag set before it would
|
|
139
|
+
# stay set, drawing every later side question as an answer of its own.
|
|
115
140
|
if relayed is None:
|
|
116
141
|
self.transcript.begin_turn(prompt, side=side)
|
|
117
142
|
else:
|
|
118
143
|
self.transcript.begin_turn(prompt, side=side, relayed=relayed)
|
|
144
|
+
self._begun = True
|
|
145
|
+
self._reported_side = False
|
|
146
|
+
|
|
147
|
+
def end_turn(self) -> None:
|
|
148
|
+
"""Stop drawing, once the run the shell began has ended.
|
|
149
|
+
|
|
150
|
+
Nothing of whatever runs next is drawn until a turn is begun for it, which is what keeps a plugin's own
|
|
151
|
+
side question out of the transcript between turns.
|
|
152
|
+
"""
|
|
153
|
+
self._begun = False
|
|
119
154
|
|
|
120
155
|
async def dispatch(self, event: AgentEvent) -> None:
|
|
121
156
|
"""Note that the agent spoke, then draw what the event stands for.
|
|
122
157
|
|
|
123
158
|
Every event ends a silence, whichever it is: the waiting row counts how long it has been since the model
|
|
124
159
|
last said anything, and has to be told each time it does.
|
|
160
|
+
|
|
161
|
+
A side question the shell did not begin is left out: its answer would land under the last turn's line as a
|
|
162
|
+
reply nobody asked for, and whoever asked for it — a plugin's recap — draws the part it wants itself. The
|
|
163
|
+
drop is logged, a line rather than one per token, so an answer that is missing from the transcript can be
|
|
164
|
+
explained from the log.
|
|
125
165
|
"""
|
|
126
166
|
self.transcript.heard()
|
|
167
|
+
if not self._begun and self._side_running is not None and self._side_running():
|
|
168
|
+
if not self._reported_side:
|
|
169
|
+
self._reported_side = True
|
|
170
|
+
logger.debug("projector.side_not_drawn", extra={"session": event.session_id})
|
|
171
|
+
return
|
|
127
172
|
for translated in translate(event, self.bridge, self._hosted):
|
|
128
173
|
self.project(translated, event)
|
|
129
174
|
|
|
@@ -147,8 +192,10 @@ class TranscriptProjector(AgentEventDispatcher):
|
|
|
147
192
|
case ReasoningFinished():
|
|
148
193
|
transcript.complete_thinking()
|
|
149
194
|
case ToolStarted(call_id=call_id, name=name, arguments=arguments):
|
|
195
|
+
logger.debug("tool.start", extra={"tool": name, "call": call_id})
|
|
150
196
|
transcript.start_tool(call_id, name, arguments)
|
|
151
197
|
case ToolFinished(call_id=call_id, name=name, output=output, ok=ok, skipped=skipped):
|
|
198
|
+
logger.debug("tool.finish", extra={"tool": name, "call": call_id, "ok": ok, "skipped": skipped})
|
|
152
199
|
self._tool_finished(call_id, name, output, ok, skipped)
|
|
153
200
|
case ServerToolStarted(call_id=call_id, name=name, arguments=arguments):
|
|
154
201
|
transcript.start_tool(call_id, name, arguments)
|
|
@@ -174,9 +221,11 @@ class TranscriptProjector(AgentEventDispatcher):
|
|
|
174
221
|
if stop is not None and not stop.ok:
|
|
175
222
|
transcript.error(stop_text(stop))
|
|
176
223
|
case Steered(text=text):
|
|
177
|
-
if self.on_steering_started is not None
|
|
178
|
-
|
|
179
|
-
|
|
224
|
+
adopted = self.on_steering_started(text) if self.on_steering_started is not None else None
|
|
225
|
+
if isinstance(adopted, Relayed):
|
|
226
|
+
transcript.begin_turn(adopted.text, relayed=adopted)
|
|
227
|
+
else:
|
|
228
|
+
transcript.begin_turn(adopted or text)
|
|
180
229
|
case SteeringFinished():
|
|
181
230
|
transcript.complete_thinking()
|
|
182
231
|
case SteeringInterrupted(text=text):
|
|
@@ -667,7 +667,10 @@ class MessageTool(ToolHandler):
|
|
|
667
667
|
names = frozenset({"send_message"})
|
|
668
668
|
|
|
669
669
|
def describe(self, name: str, arguments: Mapping[str, object]) -> ToolRow:
|
|
670
|
-
"""Say who it is for
|
|
670
|
+
"""Say who it is for: a group as ``#name`` (everyone in it reads it), a session by name or the end of its id."""
|
|
671
|
+
group = argument(arguments, "group")
|
|
672
|
+
if group:
|
|
673
|
+
return ToolRow(f"Message to group #{group.lstrip('#')}")
|
|
671
674
|
return ToolRow(f"Message to {self._recipient(argument(arguments, 'to', '(unknown)'))}")
|
|
672
675
|
|
|
673
676
|
@staticmethod
|
|
@@ -686,11 +689,43 @@ class MessageTool(ToolHandler):
|
|
|
686
689
|
tool=name,
|
|
687
690
|
title=self.describe(name, arguments).title,
|
|
688
691
|
to=argument(arguments, "to"),
|
|
692
|
+
group=argument(arguments, "group").lstrip("#"),
|
|
689
693
|
message=limit_output(message) if isinstance(message, str) else "",
|
|
690
694
|
started_at=started_at,
|
|
691
695
|
)
|
|
692
696
|
|
|
693
697
|
|
|
698
|
+
class HistoryTool(ToolHandler):
|
|
699
|
+
"""``message_history``: what was said before, with one session or in a group."""
|
|
700
|
+
|
|
701
|
+
names = frozenset({"message_history"})
|
|
702
|
+
|
|
703
|
+
def describe(self, name: str, arguments: Mapping[str, object]) -> ToolRow:
|
|
704
|
+
"""Say whose history it reads: a group's as ``#name``, one session's by name or the end of its id."""
|
|
705
|
+
group = argument(arguments, "group")
|
|
706
|
+
if group:
|
|
707
|
+
return ToolRow(f"Read history of group #{group.lstrip('#')}")
|
|
708
|
+
session = argument(arguments, "session")
|
|
709
|
+
if session:
|
|
710
|
+
return ToolRow(f"Read history with {MessageTool._recipient(session)}")
|
|
711
|
+
return ToolRow("Read message history")
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
class GroupTool(ToolHandler):
|
|
715
|
+
"""``manage_group``: make or change a group chat."""
|
|
716
|
+
|
|
717
|
+
names = frozenset({"manage_group"})
|
|
718
|
+
|
|
719
|
+
_VERBS = {"create": "Create", "add": "Add to", "remove": "Remove from", "leave": "Leave", "delete": "Delete"}
|
|
720
|
+
|
|
721
|
+
def describe(self, name: str, arguments: Mapping[str, object]) -> ToolRow:
|
|
722
|
+
"""Say what is done to which group, and with whom."""
|
|
723
|
+
verb = self._VERBS.get(argument(arguments, "action"), "Change")
|
|
724
|
+
members = argument(arguments, "members")
|
|
725
|
+
with_ = f" with {members}" if members and verb in ("Create", "Add to", "Remove from") else ""
|
|
726
|
+
return ToolRow(f"{verb} group #{argument(arguments, 'group').lstrip('#') or '(unknown)'}{with_}")
|
|
727
|
+
|
|
728
|
+
|
|
694
729
|
class NamespacedTool(ToolHandler):
|
|
695
730
|
"""A tool whose name carries where it came from: ``server__tool``, so the row names the server.
|
|
696
731
|
|
|
@@ -785,6 +820,8 @@ DEFAULT_RENDERERS = Renderers(
|
|
|
785
820
|
SkillTool(),
|
|
786
821
|
TaskTool(),
|
|
787
822
|
MessageTool(),
|
|
823
|
+
HistoryTool(),
|
|
824
|
+
GroupTool(),
|
|
788
825
|
NamespacedTool(),
|
|
789
826
|
FallbackTool(),
|
|
790
827
|
ReasoningHandler(),
|
|
@@ -245,11 +245,14 @@ def calls_text(usage: Usage) -> str | None:
|
|
|
245
245
|
|
|
246
246
|
|
|
247
247
|
def speed_text(usage: Usage) -> str | None:
|
|
248
|
-
"""Say how fast the model generated, when it can be told and is at least one token a second.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
248
|
+
"""Say how fast the model generated, when it can be told and is at least one token a second.
|
|
249
|
+
|
|
250
|
+
Reads :attr:`Usage.output_rate`, which leaves the opening chunk's tokens out of the numerator, so this line and the
|
|
251
|
+
status line a reader sees above it never disagree.
|
|
252
|
+
"""
|
|
253
|
+
rate = usage.output_rate
|
|
254
|
+
if usage.requests and rate is not None and rate >= 1:
|
|
255
|
+
return f"{rate:.1f} tok/s" if rate < 10 else f"{rate:.0f} tok/s"
|
|
253
256
|
return None
|
|
254
257
|
|
|
255
258
|
|
|
@@ -44,7 +44,7 @@ TIPS: tuple[str, ...] = (
|
|
|
44
44
|
"/usage shows tokens, cache and cost by day, model and session; /resume lists them per session.",
|
|
45
45
|
"/statusline chooses what the header and the status line show, and turns the pet on.",
|
|
46
46
|
"/pet picks a companion that sleeps while idle and works while a request runs; drag it anywhere.",
|
|
47
|
-
"/self-
|
|
47
|
+
"/plugins can turn self-compaction on or off: the model decides when to compact its own context.",
|
|
48
48
|
"zettcode resume <id> opens a stored session; zettcode update installs the newest release.",
|
|
49
49
|
"zettcode doctor checks every configured model from a shell, with no session started.",
|
|
50
50
|
"zettcode --full skips every shell question and the sandbox for that run; /permission can change it later.",
|
|
@@ -31,8 +31,8 @@ class OneOffMixin(EntryLog):
|
|
|
31
31
|
self._add(TextEntry(id=self._next_id, kind=EntryKind.ANNOUNCEMENT, text=text))
|
|
32
32
|
|
|
33
33
|
def model_changed(self, previous: str, current: str) -> None:
|
|
34
|
-
"""Announce a model change in the conversation."""
|
|
35
|
-
self.announce(f"Model changed from {previous} to {current}.")
|
|
34
|
+
"""Announce a model change in the conversation; an empty previous is the first model there has been."""
|
|
35
|
+
self.announce(f"Model changed from {previous} to {current}." if previous else f"Model set to {current}.")
|
|
36
36
|
|
|
37
37
|
def permission_changed(self, previous: str, current: str) -> None:
|
|
38
38
|
"""Announce a shell-permission change the way a model change is shown."""
|
|
@@ -87,11 +87,20 @@ class StreamMixin(TurnMixin):
|
|
|
87
87
|
row.text += delta
|
|
88
88
|
self._changed(row)
|
|
89
89
|
|
|
90
|
-
def complete_compaction(self) -> None:
|
|
91
|
-
"""Close the running compaction row and stamp its elapsed time.
|
|
90
|
+
def complete_compaction(self, text: str = "") -> None:
|
|
91
|
+
"""Close the running compaction row and stamp its elapsed time.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
text: What to leave in place of the streamed summary, when the pass
|
|
95
|
+
ended before writing one — a stop, for example. The row is
|
|
96
|
+
expanded so the note is on its face rather than in a fold.
|
|
97
|
+
"""
|
|
92
98
|
row = self._last(ThinkingEntry)
|
|
93
99
|
if row is None or row.title != COMPACTING_LABEL or not row.running:
|
|
94
100
|
return
|
|
101
|
+
if text:
|
|
102
|
+
row.text = text
|
|
103
|
+
row.expanded = True
|
|
95
104
|
row.finish(EntryStatus.COMPLETED, self.clock())
|
|
96
105
|
self._changed(row)
|
|
97
106
|
|
|
@@ -75,6 +75,7 @@ class TurnMixin(EntryLog):
|
|
|
75
75
|
outgoing=False,
|
|
76
76
|
by_agent=relayed.by_agent,
|
|
77
77
|
external=relayed.via == VIA_EXTERNAL,
|
|
78
|
+
group=relayed.group,
|
|
78
79
|
)
|
|
79
80
|
)
|
|
80
81
|
|
|
@@ -104,9 +105,15 @@ class TurnMixin(EntryLog):
|
|
|
104
105
|
self.user_message(prompt, side=side)
|
|
105
106
|
self.wait_for_model()
|
|
106
107
|
|
|
107
|
-
def wait_for_model(self) -> bool:
|
|
108
|
+
def wait_for_model(self, title: str = PROCESSING, *, tips: bool = True) -> bool:
|
|
108
109
|
"""Open the pinned wait row for a request, and report whether it opened.
|
|
109
110
|
|
|
111
|
+
Args:
|
|
112
|
+
title: What the row says is happening; ``Processing`` for a request, and a command's own words
|
|
113
|
+
(``Recap · writing``) for work it started that will take a while.
|
|
114
|
+
tips: Attach the deck's tip for a model request. A command's row is about the command, so it takes
|
|
115
|
+
none.
|
|
116
|
+
|
|
110
117
|
Nothing is known about the response yet, and a call can take seconds, so
|
|
111
118
|
the row goes up as soon as the request starts and stays for all of it:
|
|
112
119
|
the loop calls the model again after every tool batch, and one row that
|
|
@@ -123,8 +130,8 @@ class TurnMixin(EntryLog):
|
|
|
123
130
|
if any(self._is_open_row(entry) for entry in self.entries):
|
|
124
131
|
return False
|
|
125
132
|
self._turn_from = len(self.entries)
|
|
126
|
-
|
|
127
|
-
self._add(WaitEntry(id=self._next_id, title=
|
|
133
|
+
shown = self.tip_deck.next() if tips and self.tip_deck is not None else ()
|
|
134
|
+
self._add(WaitEntry(id=self._next_id, title=title, started_at=self.clock(), tips=shown))
|
|
128
135
|
return True
|
|
129
136
|
|
|
130
137
|
def summarize_changes(self, workspace: PurePath | None = None) -> bool:
|
|
@@ -77,6 +77,14 @@ class CommandHost(Protocol):
|
|
|
77
77
|
def request_layout(self) -> None:
|
|
78
78
|
"""Ask for the screen to be laid out again, after a change in what it shows."""
|
|
79
79
|
|
|
80
|
+
async def wait_for_frame(self) -> None:
|
|
81
|
+
"""Wait until the next frame has reached the terminal.
|
|
82
|
+
|
|
83
|
+
A command that has just put a row on screen and is about to start work
|
|
84
|
+
with no ``await`` in it asks for this first: the row is drawn before the
|
|
85
|
+
work begins instead of after it.
|
|
86
|
+
"""
|
|
87
|
+
|
|
80
88
|
def offer(self, command: str) -> None:
|
|
81
89
|
"""Put ``command`` and a space in the draft, which opens the menu of the words it takes."""
|
|
82
90
|
|
|
@@ -101,7 +109,7 @@ class CommandHost(Protocol):
|
|
|
101
109
|
async def run_side_question(self, question: str) -> None:
|
|
102
110
|
"""Answer a question that is kept out of the conversation."""
|
|
103
111
|
|
|
104
|
-
async def prompt(self, text: str, *, shown: str | None = None) -> bool:
|
|
112
|
+
async def prompt(self, text: str, *, shown: str | None = None, cache: str | None = None) -> bool:
|
|
105
113
|
"""Run ``text`` as one turn of this conversation, exactly as if the reader had typed it.
|
|
106
114
|
|
|
107
115
|
The text reaches the model the way a draft does: stored in the session, streamed as it is answered, and
|
|
@@ -120,6 +128,11 @@ class CommandHost(Protocol):
|
|
|
120
128
|
shown: What the transcript shows, when it differs from ``text``. The message the session keeps is
|
|
121
129
|
the same either way: ``text`` is in it, and ``shown`` is what a reader is shown of it.
|
|
122
130
|
|
|
131
|
+
cache: How the turn may use the provider's prompt cache: ``"read_write"`` (the default) extends it for
|
|
132
|
+
the next turn, ``"read"`` reuses a warm prefix without marking this turn's new content, and
|
|
133
|
+
``"off"`` sends no cache directive. A one-off report a reader is not going to follow is worth
|
|
134
|
+
``"read"``.
|
|
135
|
+
|
|
123
136
|
Returns:
|
|
124
137
|
Whether a turn was started and has ended. A request already running, a blank text and a session held
|
|
125
138
|
by another process answer ``False``, and nothing is started. A command that means to be usable
|
|
@@ -199,12 +212,21 @@ class CommandResult:
|
|
|
199
212
|
relayout: Re-measure the widget tree after applying the result. Set it
|
|
200
213
|
when the change affects geometry a fixed-height row already
|
|
201
214
|
measured, such as the header showing a new model name.
|
|
215
|
+
intro: What a result that is still working is doing, in one line. The shell shows it in the pinned row
|
|
216
|
+
while it waits, which is how a command that takes seconds says so.
|
|
217
|
+
run: The rest of a result, when the command has not finished. The shell opens the pinned row with
|
|
218
|
+
``intro``, awaits this, and shows what it returned; Ctrl-C, Escape, sending the next line, and Enter on an
|
|
219
|
+
empty draft stop it — a command that is working does not hold the composer. A command returns
|
|
220
|
+
this instead of awaiting the slow part itself, so the reader sees it working. The other fields of
|
|
221
|
+
*this* result are then names to the wind: only what ``run`` answers is applied.
|
|
202
222
|
"""
|
|
203
223
|
|
|
204
224
|
message: str = ""
|
|
205
225
|
notification: str | None = None
|
|
206
226
|
widget: Widget | None = None
|
|
207
227
|
relayout: bool = False
|
|
228
|
+
intro: str = ""
|
|
229
|
+
run: Awaitable[CommandResult] | None = None
|
|
208
230
|
|
|
209
231
|
|
|
210
232
|
@dataclass(frozen=True, slots=True)
|