From 355624d6becd1d231ecddb85b5a4dd4d13452365 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Wed, 28 Oct 2026 11:34:19 -0400 Subject: [PATCH 1/4] Carry Toad's retired prompt preferences and track formbridge main in the stack Toad's settings menu PR replaces ui.compact-input (a flag every prompt part branched on) with the ui.input.box choice and moves ui.prompt_message (declared, never read) to ui.input.placeholder. Settings decoding refuses unknown keys, so a saved file holding either retired key must cross once: compact-input true becomes the Flush layout, false is the default and is dropped, and the message becomes the placeholder. formbridge now owns the declared-field semantics Toad's forms read, so the stack overrides it to main like the other OpenHCSDev packages. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01RnH6dR85kyFKcc2tQAJLhK --- stack/pyproject.toml | 2 + stack/uv.lock | 5 +- tools/cutover/carry_toad_input_settings.py | 72 ++++++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 tools/cutover/carry_toad_input_settings.py diff --git a/stack/pyproject.toml b/stack/pyproject.toml index e9e240bd86..4c026b5814 100644 --- a/stack/pyproject.toml +++ b/stack/pyproject.toml @@ -14,6 +14,7 @@ package = false # This stack owns source selection, including Toad's transitive requirements. override-dependencies = [ "agent-comms", + "formbridge", "metaclass-registry", "textual[syntax]", "ui-theme", @@ -21,6 +22,7 @@ override-dependencies = [ [tool.uv.sources] agent-comms = { path = "..", editable = true } +formbridge = { git = "https://github.com/OpenHCSDev/formbridge.git", branch = "main" } metaclass-registry = { git = "https://github.com/OpenHCSDev/metaclass-registry", branch = "main" } batrachian-toad = { git = "https://github.com/OpenHCSDev/toad.git", branch = "main" } textual = { git = "https://github.com/OpenHCSDev/textual.git", branch = "main" } diff --git a/stack/uv.lock b/stack/uv.lock index eafbf79c7e..fb963e3dee 100644 --- a/stack/uv.lock +++ b/stack/uv.lock @@ -1,10 +1,11 @@ version = 1 -revision = 3 +revision = 5 requires-python = ">=3.14.8, <3.15" [manifest] overrides = [ { name = "agent-comms", editable = "../" }, + { name = "formbridge", git = "https://github.com/OpenHCSDev/formbridge.git?branch=main" }, { name = "metaclass-registry", git = "https://github.com/OpenHCSDev/metaclass-registry?branch=main" }, { name = "textual", extras = ["syntax"], git = "https://github.com/OpenHCSDev/textual.git?branch=main" }, { name = "ui-theme", git = "https://github.com/OpenHCSDev/ui-theme.git?branch=main" }, @@ -332,7 +333,7 @@ wheels = [ [[package]] name = "formbridge" version = "0.2.0" -source = { git = "https://github.com/OpenHCSDev/formbridge.git?rev=ebe2fa9173428e2bd7154a0de23698757677c3c2#ebe2fa9173428e2bd7154a0de23698757677c3c2" } +source = { git = "https://github.com/OpenHCSDev/formbridge.git?branch=main#ebe2fa9173428e2bd7154a0de23698757677c3c2" } dependencies = [ { name = "docutils" }, { name = "metaclass-registry" }, diff --git a/tools/cutover/carry_toad_input_settings.py b/tools/cutover/carry_toad_input_settings.py new file mode 100644 index 0000000000..68004a0c9d --- /dev/null +++ b/tools/cutover/carry_toad_input_settings.py @@ -0,0 +1,72 @@ +"""Carry the retired prompt preferences into Toad's input box settings group.""" + +from dataclasses import dataclass +from typing import Annotated, ClassVar + +from pydantic import JsonValue + +from agent_comms.errors import RelationViolationError +from agent_comms.field_codec import FieldCodec, WireName +from agent_comms.installer.probes.carry import Carried, Carry +from agent_comms.locked_store import RootFile +from agent_comms.store_files import AtomicFile +from toad.preferences import InputSettings, SavedSettings, ToadSettings, UiSettings +from toad.setting_choices import FlushInputBox, InputBox + + +@dataclass(frozen=True) +class PreviousCompactInput: + """The retired flag only. True removed the prompt's spacing, which is now Flush.""" + + compact_input: Annotated[bool, WireName("compact-input")] + + +@dataclass(frozen=True) +class PreviousPromptMessage: + """The retired placeholder text, which no widget read; it is now the live placeholder.""" + + prompt_message: str + + +class ToadInputSettings(Carry): + opened_files: ClassVar[tuple[type[RootFile], ...]] = () + writer_owned = (SavedSettings,) + + def carry(self, *, apply: bool) -> Carried: + resource, = SavedSettings.resources(self.files) + path = self.files.location(resource) + self.require_confined(path) + if not path.exists(): + return Carried(0) + document = FieldCodec.decode(dict[str, JsonValue], FieldCodec.parse(path.read_text())) + ui_key = FieldCodec.record_key(ToadSettings, "ui") + ui = FieldCodec.decode(dict[str, JsonValue], document.get(ui_key, {})) + compact_key = FieldCodec.record_key(PreviousCompactInput, "compact_input") + message_key = FieldCodec.record_key(PreviousPromptMessage, "prompt_message") + if compact_key not in ui and message_key not in ui: + FieldCodec.decode(ToadSettings, document) + return Carried(0) + input_key = FieldCodec.record_key(UiSettings, "input") + if input_key in ui: + raise RelationViolationError(f"{path}: both old and current prompt preferences exist") + carried: dict[str, JsonValue] = {} + if compact_key in ui: + previous = FieldCodec.decode(PreviousCompactInput, {compact_key: ui.pop(compact_key)}) + if previous.compact_input: + carried[FieldCodec.record_key(InputSettings, "box")] = FieldCodec.encode( + FlushInputBox, type[InputBox] + ) + if message_key in ui: + previous_message = FieldCodec.decode( + PreviousPromptMessage, {message_key: ui.pop(message_key)} + ) + carried[FieldCodec.record_key(InputSettings, "placeholder")] = ( + previous_message.prompt_message + ) + if carried: + ui[input_key] = carried + document[ui_key] = ui + FieldCodec.decode(ToadSettings, document) + if apply: + AtomicFile(path).write_text(FieldCodec.compact(document, allow_nan=False)) + return Carried(1, rewritten=(resource.path,) if apply else ()) From e3201a1b0a5ae185a74070f2294594d073ff60df Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Fri, 30 Oct 2026 06:54:24 -0400 Subject: [PATCH 2/4] Relock the stack on Toad main with the settings menu (OpenHCSDev/toad#1304, 35770a0c2) batrachian-toad 35770a0c, formbridge b67c97e5; the carry's toad.preferences InputSettings and toad.setting_choices FlushInputBox now resolve, and every cutover module imports against this lock. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XbFMSoWgC3ZwKzjT4SwMDu --- stack/uv.lock | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/stack/uv.lock b/stack/uv.lock index 861ba9d933..f136ac412c 100644 --- a/stack/uv.lock +++ b/stack/uv.lock @@ -33,6 +33,7 @@ dependencies = [ { name = "nominal-refactor-advisor" }, { name = "packaging" }, { name = "pydantic" }, + { name = "python-introspect" }, ] [package.metadata] @@ -50,6 +51,7 @@ requires-dist = [ { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=4.0" }, { name = "pytest-timeout", marker = "extra == 'dev'", specifier = ">=2.3" }, { name = "pytest-xdist", marker = "extra == 'dev'", specifier = ">=3.6" }, + { name = "python-introspect", git = "https://github.com/OpenHCSDev/python-introspect?rev=main" }, { name = "ruff", marker = "extra == 'dev'", specifier = "==0.16.0" }, { name = "uv", marker = "extra == 'dev'", specifier = "==0.13.1" }, ] @@ -207,7 +209,7 @@ wheels = [ [[package]] name = "batrachian-toad" version = "0.6.20" -source = { git = "https://github.com/OpenHCSDev/toad.git?branch=main#fe7f140ac13cb0e264c1e32f8dd0b5698405a4ec" } +source = { git = "https://github.com/OpenHCSDev/toad.git?branch=main#35770a0c212906cba9bbf6c0059c8f64237b0cb8" } dependencies = [ { name = "agent-client-protocol" }, { name = "agent-comms" }, @@ -218,6 +220,7 @@ dependencies = [ { name = "httpx" }, { name = "jeepney", marker = "sys_platform == 'linux'" }, { name = "metaclass-registry" }, + { name = "msgpack" }, { name = "notify-py" }, { name = "objectstate" }, { name = "packaging" }, @@ -334,8 +337,9 @@ wheels = [ [[package]] name = "formbridge" version = "0.2.0" -source = { git = "https://github.com/OpenHCSDev/formbridge.git?branch=main#ebe2fa9173428e2bd7154a0de23698757677c3c2" } +source = { git = "https://github.com/OpenHCSDev/formbridge.git?branch=main#b67c97e5c3ad1eda5c06a464fdc578038d01e3e8" } dependencies = [ + { name = "annotated-types" }, { name = "docutils" }, { name = "metaclass-registry" }, { name = "objectstate" }, @@ -561,6 +565,36 @@ name = "metaclass-registry" version = "0.4.1" source = { git = "https://github.com/OpenHCSDev/metaclass-registry?branch=main#60138d533ef0758c5f093d9110ba9f5656f0934a" } +[[package]] +name = "msgpack" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/44/ea2100ec54d30c46ee9dba10a3bfb79b655e96c6df237238a3234c75869b/msgpack-1.2.2.tar.gz", hash = "sha256:9eb0b0e602064527a045ea28c4f174ed69383587e29cebe28947e3b84106eb2a", size = 187025, upload-time = "2026-08-27T10:03:47.793Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/50/3e92c403346652cabd08cb8faceef847bae917ea3b3c81b64a5b6d09ed41/msgpack-1.2.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e497ee34e8a3342bbde51b27c22d8db05a651df3361dd3daef5b3ab0d66f3e04", size = 84315, upload-time = "2026-08-27T10:02:41.181Z" }, + { url = "https://files.pythonhosted.org/packages/b6/dc/8efe6dd96a12ab043930cb4cffb40b6e7f061491d6ec7a3d2b75ef1fda42/msgpack-1.2.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0dd9173c5ebaf5ecc5ca86e7ae1db92934e1d57b856f3dd90698941431f4fd77", size = 84634, upload-time = "2026-08-27T10:02:42.621Z" }, + { url = "https://files.pythonhosted.org/packages/1b/89/996573095bf7b038c04dd65ddbc4f1a4d381b0f7a44ff9186f3c7b8325c2/msgpack-1.2.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8dc4487097571f7311188c3eca2a3e86cd1f1db4c37c7a017bcc3fd38486cbfe", size = 404194, upload-time = "2026-08-27T10:02:44.096Z" }, + { url = "https://files.pythonhosted.org/packages/b6/4e/46f5a5d949dbd054dab60cb15aac7ac6ae6774c134532893414689bf2f53/msgpack-1.2.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73b0e05c32c3cfc3cd84994908e57430c0ebc6813abf905d3f18ff115d54df3f", size = 412343, upload-time = "2026-08-27T10:02:45.747Z" }, + { url = "https://files.pythonhosted.org/packages/da/e8/739a94197358a313307e6e9e7d8d22ef66add39222de911a44161aa96920/msgpack-1.2.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa1120c653b76d8eafa50423b5eba06b5c9737f8692c74fa3afe03e84b8978ea", size = 372620, upload-time = "2026-08-27T10:02:47.578Z" }, + { url = "https://files.pythonhosted.org/packages/03/d4/09b92e1fcdccea9466bfae45455367ac52362ae445d96a602e51b7a8df73/msgpack-1.2.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccfd880988f8438d1c91c77d7edc58e70f4d2012e999167bc154c64c6f06ea6b", size = 394603, upload-time = "2026-08-27T10:02:49.172Z" }, + { url = "https://files.pythonhosted.org/packages/47/db/d11bd6f258a60703dcdc7a3772818ad0c2f602ee4c2acfb24088c6c3ebc3/msgpack-1.2.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:6195257a107bf25872ef84aab7295078271eea3ac6413f0506b631f6c9586ed5", size = 372666, upload-time = "2026-08-27T10:02:50.886Z" }, + { url = "https://files.pythonhosted.org/packages/71/cf/fbbbac0c6e5fbb9d51abc23e3b5fe8620f5c01e0588797cf664a623bb9e1/msgpack-1.2.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b8dd6c71d20c28d2d0eb0c51e7cccf3584afde3b1364f6629596186c9025bd54", size = 410889, upload-time = "2026-08-27T10:02:52.51Z" }, + { url = "https://files.pythonhosted.org/packages/94/60/8366558da954095e04e7fbc351f9387d87a682feaee9a235ceda966f794b/msgpack-1.2.2-cp314-cp314-win32.whl", hash = "sha256:d242f3c4ccf55b056e6cf901720dccde58f1df117898f2bbf3bcd6e38ec7c248", size = 66774, upload-time = "2026-08-27T10:02:53.984Z" }, + { url = "https://files.pythonhosted.org/packages/4b/3d/1ce873c8057c65e4fbb076ffe1c99c9ae39d90a00a2540d7b06c652a292f/msgpack-1.2.2-cp314-cp314-win_amd64.whl", hash = "sha256:1510f24612d4b983dff6935d9273e02c320cfd525727fbcb58836a75f589fdbc", size = 73424, upload-time = "2026-08-27T10:02:55.277Z" }, + { url = "https://files.pythonhosted.org/packages/d5/55/e36f2a33e38657f33850d74e0bf256838a0d45802c298cc501a32bffcc08/msgpack-1.2.2-cp314-cp314-win_arm64.whl", hash = "sha256:7826f16edc763e768404f55605ef85dfcf5857e729c1ed29e0d7c180be4fe6d8", size = 67657, upload-time = "2026-08-27T10:02:56.493Z" }, + { url = "https://files.pythonhosted.org/packages/64/58/7e764b957bae80ae281a9cb28761068c8bae8d5c6ac0873e43cc69d176c7/msgpack-1.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:f466049b8e1ec0854287bbe9a074316826fe0e08dcf707245f98b1ae49e92650", size = 86594, upload-time = "2026-08-27T10:02:57.796Z" }, + { url = "https://files.pythonhosted.org/packages/ae/f0/250f5985b6ee533e60d357571a808aaae03c54118294dc3db7158e27feb1/msgpack-1.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f6b6f8deb07d49090e1808c6ef9cb7d23ca17bef3aa6ed3e5e03df16606e60c", size = 87374, upload-time = "2026-08-27T10:02:59.256Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2c/126ec8f187877c5f688631c543d1d3a3d75b2e66b83fb9de3ed7c13a39b6/msgpack-1.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b542ffc0a5c531eedc40419f291f1bd659aa8d4223408a5b51c88a2796083fd3", size = 428157, upload-time = "2026-08-27T10:03:00.9Z" }, + { url = "https://files.pythonhosted.org/packages/95/21/d2d81d50aaedb14147d01f22094185794db3ad8a8791b60afacba0627c89/msgpack-1.2.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d095df2627e5dd59ac7b0c5ad627a671c76e6020171e03cbe4621a61f0562c3", size = 426669, upload-time = "2026-08-27T10:03:02.457Z" }, + { url = "https://files.pythonhosted.org/packages/c6/fc/f7d484ee5b572719608e7ffad569bea22ff11309a96ca2fae85eec94226b/msgpack-1.2.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ffdd2f4950daf7815490f23087963e3420175b9609520b7ff5df64d351159c22", size = 380625, upload-time = "2026-08-27T10:03:04.244Z" }, + { url = "https://files.pythonhosted.org/packages/0a/c4/b924cbd5516676f4e612329f18602a833bd055ffbe27f808eeba0f01bfea/msgpack-1.2.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:652d1bf13d01bac8fd569def0fe76745e55bcda01e30aa6332d5947ea3788839", size = 411328, upload-time = "2026-08-27T10:03:05.869Z" }, + { url = "https://files.pythonhosted.org/packages/27/9d/0c1d9683a951a80f270c3b7dac1022c18b9307617344dd44d904135d5e12/msgpack-1.2.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:9bf452ff4d4981f25a18e9476e002bcc9263e7928024aa4d7148e25f7be3f929", size = 377892, upload-time = "2026-08-27T10:03:07.37Z" }, + { url = "https://files.pythonhosted.org/packages/06/bb/bf22338cdd22e0b40c8f28468cea5f3d9c320244c095d8303364bc012c41/msgpack-1.2.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:55faa6f8395e23b848c535ad5dcb96b3462f37f5e7f4ac500d500434f7345da7", size = 419426, upload-time = "2026-08-27T10:03:09Z" }, + { url = "https://files.pythonhosted.org/packages/7d/42/6d02c19a01abd8d7ce817c321d2ee6af1a8e24d584dca619d1b6576a83bf/msgpack-1.2.2-cp314-cp314t-win32.whl", hash = "sha256:419a45c67a5c04213172a14b1864657e014665b77d7081b107a51707923dd39e", size = 71810, upload-time = "2026-08-27T10:03:10.498Z" }, + { url = "https://files.pythonhosted.org/packages/af/df/fda3a204415dab0a8c0db5461ef7205416ea52bd8581c5cafd361be07f3b/msgpack-1.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:935b1cfad9b908b0fa845010f4271df4c2f04e1cd26e3f18acd61a45f93c9e36", size = 78919, upload-time = "2026-08-27T10:03:12.016Z" }, + { url = "https://files.pythonhosted.org/packages/63/d4/4b4b0ef25a86deca91feaf7252ca885ba4f2ada40461379120122a04fe96/msgpack-1.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11e8c421e117d1c36728b423d0402555cccbf0c6f53e288f0e75b6b12100d70f", size = 71925, upload-time = "2026-08-27T10:03:13.332Z" }, +] + [[package]] name = "multidict" version = "7.2.1" @@ -616,7 +650,7 @@ wheels = [ [[package]] name = "nominal-refactor-advisor" version = "0.1.0" -source = { git = "https://github.com/OpenHCSDev/NominalRefactorAdvisor?rev=main#595d19725deba0b37158c05cc05f1c7d8af6bec7" } +source = { git = "https://github.com/OpenHCSDev/NominalRefactorAdvisor?rev=main#d0667af3c2733b3de298be1af4bd69f963cb9e23" } dependencies = [ { name = "metaclass-registry" }, { name = "tree-sitter" }, @@ -901,15 +935,11 @@ wheels = [ [[package]] name = "python-introspect" version = "0.3.0" -source = { registry = "https://pypi.org/simple" } +source = { git = "https://github.com/OpenHCSDev/python-introspect?rev=main#f2876b9ee089c65789607284949e11a9f58283fe" } dependencies = [ { name = "annotated-types" }, { name = "metaclass-registry" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6d/71/55abd50b3f5da2560950c17de878021012f1c033618ad08187916a6f23fe/python_introspect-0.3.0.tar.gz", hash = "sha256:1b305b7976c5620b137edcb013a7a97356031d1abb0eec552a467e85633a7534", size = 62345, upload-time = "2026-10-12T21:00:11.236Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/09/59afdbb10c00e3df9ed3f537a5d657a7b1df7189b7542dc9df5ba7d0810b/python_introspect-0.3.0-py3-none-any.whl", hash = "sha256:95155269ea563a5486e0c3851c868fdf0e15065097cd894efad949c69b69b777", size = 46792, upload-time = "2026-10-12T21:00:09.755Z" }, -] [[package]] name = "pyzmq" @@ -998,7 +1028,7 @@ wheels = [ [[package]] name = "textual" version = "8.2.8" -source = { git = "https://github.com/OpenHCSDev/textual.git?branch=main#79a8a6d69eed1d3300b54b12c490bc7d3753ee9c" } +source = { git = "https://github.com/OpenHCSDev/textual.git?branch=main#e9f681e40c9923edec45990552e082276b23cc0b" } dependencies = [ { name = "markdown-it-py", extra = ["linkify"] }, { name = "mdit-py-plugins" }, From bff6f6f4f367d08d3696d6591b91f8e384dcabd7 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Fri, 30 Oct 2026 13:46:29 -0400 Subject: [PATCH 3/4] Refresh settings carry stack to current Toad and Textual mains --- stack/uv.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stack/uv.lock b/stack/uv.lock index f136ac412c..a3d1aad8ae 100644 --- a/stack/uv.lock +++ b/stack/uv.lock @@ -209,7 +209,7 @@ wheels = [ [[package]] name = "batrachian-toad" version = "0.6.20" -source = { git = "https://github.com/OpenHCSDev/toad.git?branch=main#35770a0c212906cba9bbf6c0059c8f64237b0cb8" } +source = { git = "https://github.com/OpenHCSDev/toad.git?branch=main#1d85311339556d30182f6bd8fe90bc372093082b" } dependencies = [ { name = "agent-client-protocol" }, { name = "agent-comms" }, @@ -1028,7 +1028,7 @@ wheels = [ [[package]] name = "textual" version = "8.2.8" -source = { git = "https://github.com/OpenHCSDev/textual.git?branch=main#e9f681e40c9923edec45990552e082276b23cc0b" } +source = { git = "https://github.com/OpenHCSDev/textual.git?branch=main#76f9ef770bfa0630d09aeaee931ca4356996120b" } dependencies = [ { name = "markdown-it-py", extra = ["linkify"] }, { name = "mdit-py-plugins" }, From 64512ffcef934147c8e0cc793e8e5e96cc7042bb Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Fri, 30 Oct 2026 14:05:27 -0400 Subject: [PATCH 4/4] Derive input preference carry from the saved-settings lifecycle owner --- tools/cutover/carry_toad_input_settings.py | 31 ++++++---------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/tools/cutover/carry_toad_input_settings.py b/tools/cutover/carry_toad_input_settings.py index 68004a0c9d..feff87d32b 100644 --- a/tools/cutover/carry_toad_input_settings.py +++ b/tools/cutover/carry_toad_input_settings.py @@ -1,16 +1,14 @@ """Carry the retired prompt preferences into Toad's input box settings group.""" from dataclasses import dataclass -from typing import Annotated, ClassVar +from typing import Annotated from pydantic import JsonValue from agent_comms.errors import RelationViolationError from agent_comms.field_codec import FieldCodec, WireName -from agent_comms.installer.probes.carry import Carried, Carry -from agent_comms.locked_store import RootFile -from agent_comms.store_files import AtomicFile -from toad.preferences import InputSettings, SavedSettings, ToadSettings, UiSettings +from cutover.carry_toad_key_mode import ToadSettingsCarry +from toad.preferences import InputSettings, ToadSettings, UiSettings from toad.setting_choices import FlushInputBox, InputBox @@ -28,27 +26,17 @@ class PreviousPromptMessage: prompt_message: str -class ToadInputSettings(Carry): - opened_files: ClassVar[tuple[type[RootFile], ...]] = () - writer_owned = (SavedSettings,) - - def carry(self, *, apply: bool) -> Carried: - resource, = SavedSettings.resources(self.files) - path = self.files.location(resource) - self.require_confined(path) - if not path.exists(): - return Carried(0) - document = FieldCodec.decode(dict[str, JsonValue], FieldCodec.parse(path.read_text())) +class ToadInputSettings(ToadSettingsCarry): + def rewrite(self, document: dict[str, JsonValue]) -> int: ui_key = FieldCodec.record_key(ToadSettings, "ui") ui = FieldCodec.decode(dict[str, JsonValue], document.get(ui_key, {})) compact_key = FieldCodec.record_key(PreviousCompactInput, "compact_input") message_key = FieldCodec.record_key(PreviousPromptMessage, "prompt_message") if compact_key not in ui and message_key not in ui: - FieldCodec.decode(ToadSettings, document) - return Carried(0) + return 0 input_key = FieldCodec.record_key(UiSettings, "input") if input_key in ui: - raise RelationViolationError(f"{path}: both old and current prompt preferences exist") + raise RelationViolationError("Both old and current prompt preferences exist") carried: dict[str, JsonValue] = {} if compact_key in ui: previous = FieldCodec.decode(PreviousCompactInput, {compact_key: ui.pop(compact_key)}) @@ -66,7 +54,4 @@ def carry(self, *, apply: bool) -> Carried: if carried: ui[input_key] = carried document[ui_key] = ui - FieldCodec.decode(ToadSettings, document) - if apply: - AtomicFile(path).write_text(FieldCodec.compact(document, allow_nan=False)) - return Carried(1, rewritten=(resource.path,) if apply else ()) + return 1