codex-bot 0.3.1__tar.gz → 0.4.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.
- {codex_bot-0.3.1 → codex_bot-0.4.0}/.gitignore +6 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/CHANGELOG.md +32 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/PKG-INFO +6 -4
- {codex_bot-0.3.1 → codex_bot-0.4.0}/README.md +2 -0
- codex_bot-0.4.0/docs/agent-skills/codex-bot/SKILL.md +14 -0
- codex_bot-0.4.0/docs/agent-skills/codex-bot/references/feature-workflow.md +7 -0
- codex_bot-0.4.0/docs/agent-skills/codex-bot/references/runtime-contracts.md +9 -0
- codex_bot-0.4.0/docs/agent-skills/codex-bot/references/skill-delivery.md +7 -0
- codex_bot-0.4.0/docs/en_EN/guide/agent-skills.md +16 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/roadmap.md +6 -4
- codex_bot-0.4.0/docs/ru_RU/guide/agent-skills.md +14 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/roadmap.md +6 -4
- {codex_bot-0.3.1 → codex_bot-0.4.0}/mkdocs.yml +2 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/pyproject.toml +18 -2
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/__init__.py +1 -1
- codex_bot-0.4.0/src/codex_bot/agent_skills/__init__.py +1 -0
- codex_bot-0.4.0/src/codex_bot/agent_skills/__main__.py +4 -0
- codex_bot-0.4.0/src/codex_bot/agent_skills/cli.py +39 -0
- codex_bot-0.4.0/src/codex_bot/agent_skills/fs_transaction.py +174 -0
- codex_bot-0.4.0/src/codex_bot/agent_skills/manifest_rules.py +153 -0
- codex_bot-0.4.0/src/codex_bot/agent_skills/orchestrator.py +224 -0
- codex_bot-0.4.0/src/codex_bot/agent_skills/resources/SKILL.md +14 -0
- codex_bot-0.4.0/src/codex_bot/agent_skills/resources/__init__.py +1 -0
- codex_bot-0.4.0/src/codex_bot/agent_skills/resources/references/features.md +12 -0
- codex_bot-0.4.0/src/codex_bot/agent_skills/resources/references/runtime.md +13 -0
- codex_bot-0.4.0/src/codex_bot/agent_skills/resources/references/views-and-state.md +14 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/discovery/service.py +8 -3
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/stream/dispatcher.py +1 -1
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/stream/router.py +1 -1
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/root/pyproject.toml.j2 +1 -1
- codex_bot-0.4.0/tests/agent_skills/test_installer.py +164 -0
- codex_bot-0.4.0/tests/engine/discovery/test_service.py +59 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/uv.lock +498 -316
- codex_bot-0.3.1/.github/workflows/ci.yml +0 -88
- codex_bot-0.3.1/.github/workflows/docs.yml +0 -68
- codex_bot-0.3.1/.github/workflows/publish.yml +0 -42
- codex_bot-0.3.1/.pre-commit-config.yaml +0 -38
- codex_bot-0.3.1/.secrets.baseline +0 -127
- codex_bot-0.3.1/graphify-out/GRAPH_REPORT.md +0 -306
- codex_bot-0.3.1/graphify-out/cache/02c739920c02003cd0b6a08c6b7b08789f1ca400d156657f25273195ad2bcc77.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/058f08bd4d7bc2f36df7e8c16b4cc941f2590bbe61bef5b109b5a0c3b6281934.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/061d5eef3ba32c5e102eddef6c384b87d515f3a555e7f49106e90c9142825eb3.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/0b275bf6bf5efbf0d805b2cadb425a82ab1271e5c93a61c5e7c0f1f12bd30c61.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/0cb6740123a8c326c79b78ffde93e643318b7a22b63c749ec0670f371d0c6115.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/0f050a741199a9a9b9511fadb422952246251d7cd9c77ce8bf725f6825435eeb.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/0f56114b4afab5d90ff6317f116deb923b5d4decdb8c8cd2659a4ce26bf45704.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/0fbc6f81dc3d9601c4105f8b5cc8190b7be8218ae710689e869b98609ffbaac0.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/0fbd595d5e0ae3a4c0d3bc7a34e712898f62812d2f73ac4683f9a8fca7703c7d.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/1186ca0761fbf521658a826f5d3e94a91999f0b3369992a65c2d6cf268597eeb.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/131e224cfe01a42aacc6f37498eb391f2db47e38aab2ed4ec3864dc87474f3f1.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/1557c6d5dbb4d2e444225d0ddbaa44b42b828fe4457b2d8cf2185323bdb4adfc.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/1671512938748da1ef9a781fd34692ace652f9772c915d3de476c316ba562975.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/192b2b84e291186c70d144eb5acdec9165be18a5b2ed1617a06e22cfa92bfb8d.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/1f4a20ef34c90e5b91afbdfd908c0e3bb9fbd01b6cf6a349409c8252f4930478.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/1fd7943166072f2f9d307a2eec9c481f1c9a1e4afbd273ba68ab7d236df14a96.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/20af4485c7e1df41c981ea065c49e8550e4b802cb7cbd19ea45b0e47584650f9.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/21a0cc1b19214d1e52d398b4d9a2381bcf0c2c7462f6fa0324e0882c2ba281f4.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/2586a38f9a3211befdbf5bb8622f9b6f67a2c48aa0997d9f3e95f5b6214db3aa.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/28194cca79c0143d01dd73d04d44fd8dbd81db4bbee846f312046131c93ecae1.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/2964b22653f75df313e236117a307db5d8f865fd2af45340345aa34da174b789.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/2b6fc93989a6ea5b3a06a5547c3891f1013c07845336e6c33d418a0b1dea7697.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/2e47c91ed556d32862da33b6e2e47a8d0621e235e593bc1a5a6c16e7764bfaa3.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/2f17714cc5f80ac8f34c3c5bc148ee369514a1cb807bd5aca36a33f1436881d1.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/2f417bb4927dce5f62face8f79525746ccc6467ae1bcb7082f9ae27fd28a5c82.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/308b5cc5bfb97b6b26462214550c5816d4c30857062860f72daa22db6580b3a8.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/30f6391f548b086c786f651248bb19dcc4b1db42a622d64a934d7a390ad4ceb7.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/35a34256f8462f1c108a2b9770978ffd52ec702e9c410a918c0aa60c00994c7d.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/366a94fb95d619261dd9cfe51602029ba2dfe60290d59ee11007967104615865.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/3c698fae59cd5dca849fbb588513951ecc19ff968b135cd6550216eb69c4f6d3.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/3c7c135936c887d0d0fbfaf4cd9f61162f20680aa1f9841af97db127612fd71a.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/41b1f2326a2dbea1f07f82cab82007a50b36ca3e4709834916a0c8fe6cd7aa64.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/4298d0b8d27ff2a2f88c98ee1e173c5ce956c4322c4135e03e3471498e7c3c0d.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/46d97019c3f81598cbfae098024f7827a391ef64dc5e069acbd614859b5da4db.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/47986c14f3d6dc3769f4e138b941efb4ab91d9ca5324a119244f62e64a39099d.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/49a1b585dcc5e14fe3002a4cfd0650b34e437ac3172220a4dc2f1a8b40d5740b.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/49eda2f3fa438bff31437638c46a8aac14ea4896e6550f41b4c7c7936e6b0cf4.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/4af5bcff20451c60fad6b35d6b2fec1a2d55737e75e7b2097bac440700baca48.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/4d9e7d0c5382372ba6d1771e3d9c07326ebfc645597b1c0d4f92293a6f318708.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/4e9ade04f830f5ee3ced867e464378f20aafdbb2edaee7a9cd410adf3e375e5f.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/4fe5d7597784a41b780c79886a9faa009b1f32e6b0ef79f18fd2e8ca57125b95.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/513c1e7b28340f00cef4b912553038aff550d58e441f9f5801aaff80b169caed.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/51e3344dfc9f1cd8be829c2a6aba4728f49744ff83c36b1adf603e2ce2db9187.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/526fb2ddc9d4b9bf65f063b1879bba443109feabe1c695f5b0504b461227f7a3.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/52f0dedbbad4851fee4e662b64cb1a1d130cd65a336c58b381b8b4397785058e.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/554a190c85419d543119950ba356d140b35a5f20814ff301605cfba7c9a8268b.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/55a2e44f44d027b5d5bcca50b9418e612eea73d9833866c33dfa3ef8d9f10634.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/5948e5658afc343537c56ff3bb280b998dc9e077ef566cdc6944c4a47032aeaf.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/5b29dae845c198601072273b785e5a8f59d377b02f35cfa2834b3fab37ba0713.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/5fcbd13204c2403b6e0bd8ce27338e1caba80d99b3b814b3d5996c7668c78e5f.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/5fe723ddbbb78b13754008ec7e9561a49a1389ee96228fc47244bcf92ffd9810.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/60312d1f7b215419e48fe63043df4b9c89d328f8d961586e4bb1cd9d84dde0c9.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/6061fc68cf5f36f273d3093d22c38890f8cf38628aac6ae3d787581f8ae324c7.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/61f77b7abdc97f89041344334913959ca2e0042d39899edfd1a3a2bc5cee8b5e.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/642c6f9c4f27ede109ded0bb8418fbac000c1b6904165eb8020adb95f8babaf0.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/6a3cf1939b4eecbc8f705d159fd7c3d7006f9fb1a0ee1aabad835886206174ef.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/6a9dc858f9c053056d281f7c0fd03574a97dd41a4399cfdecd42f27dbe4f57a3.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/6af8f14fbb2c1da3075a324b4ff902ec1f0608a10df7572cf1ca41a0f27fedf2.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/6bed2bea09622e5396ad0aea658c868e975233eb3b3d0c81c86bc129d648cc15.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/6c7d7d0e5dc60154ac10b6efd09c6e11777388da7bc205b6747eb8aa153ccae8.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/6d3f2ed54a044be136ee901fc42f82bd1ffbfc5ac458fba542d1d26802e7e866.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/6dd26136ca5067660f017440bc35fec0fc3fc57e4d3f1fb03c055065e2623d95.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/6ebd5c79b49c9b2f1637a85410a18656251f1a2e7dcaa2cd988791737154b628.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/6f5eb2e8614593c593f239cab337e2ab41ba5565007f9993eb0947c99519dfbd.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/705afbc83dad11f38d735c3d92293f772bbad8d244ea9c7ad4b86d83e8caa655.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/70b1fff23c88fc4ab4fcf38975473b9096cf39c1ee94adc06a006b4d808f2cb4.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/710aa9e72407e1ab81aa0248bf64b736771a425af84287933a0130b7f13198f7.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/717b62b38c2c5264271286106f8fd0482164511c52c38646989ae8fc64562bde.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/72e33a23c384964928b7e3a6a26e18b5d651ab4bc00d46a39c1f932d68cde085.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/7842cdaebd8d47941f3214d9aebe821c53435ea250a83d49bf0362eb14d1721d.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/7d799ecc6f9c6fd51db462b2d040b368aa84d6612af1657071edcc9a101a554d.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/7d8c779dd53bb599c4ed432ea257a6a566ddc4354e9630e2d83e1e17bfd385b0.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/80043c80f2a479eee2ce1c40d30159e9c3dc55ebbf47784e6a12c89c7e6d4a9b.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/837ffea887f32efe34086141f94a593e0eacbdfb21befe19aa0d6c6097fb5797.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/8496265977d8628a44d0732e7128e3889e3c0794e8d3c38cef40bdab7428c0f1.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/885ad2c69710238d16c5164d36e7e47b851846a4eca5ff95ff1a768696398398.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/8a2b5211067bce65e4a60fee6d7627174e724ab127bf7ffb5c7622fc04cb504c.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/8c733da7e0f83075f2fe4692e5d46ff98db4de44747bccdb2186d1d3a6ba930a.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/8e75f208dab58fad09091a7cb2757452ba34e2df4f9b61f6334e7651ab74b739.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/9070654051bc62dfe3e4ade57660764f50eb5355da01723f1fc00b5521643c68.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/912055a9e59d162fc9769ca740e3e7ee518614c989884e514ac3d5327182eb08.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/93bbbc808f6a280060284116d7b881df6d1da0ef92d19461e08c76eadee2eeed.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/93df4ed36b8f909dd760ec88e0ffa42dc4cd931bab91a1a7eaa38d48ee92a74b.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/94771fa53fd180967689e3bb50578116d8bdc585443ae2c9a86ae8a2fed2a432.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/963670749591b693e49763019383c6132b089d281470417806cd709a4a98c4cf.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/987cb6ce61864b4c55d3c1f621302d65bbab72c666a323e219089735aba6dfaa.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/99549964ad14aadde44419374e3be292610b1dc62c222eacc46f181cd8dd460a.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/999a99fa9de49c4f3d4e22006bb52f1c82f6cdbf3a6c98012991d731456df242.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/9b38cdef794316fb55eccda5470673cb8bca127f0cfac3dcd1e371e7c9fb1523.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/9fd2a11d85bc0d3ff38a36f4d50c867ff470103b1e375432d552304fa0b691a8.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/a50ea786ab9b97d8b8d6c7f7e8a3379dee3873c60e4a79e735ae508aef406f49.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/a5b5ed169e90d270ae5d214ae6fb4f1418bfa23e434bbe1e275a4fb4ea2c277a.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/a6e732effceed373849f5d92cd78e06266afe27e9afa55c9763e073bf425629c.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/a8e7191d69da9c12307fba671c9912969d6be754249509102d6e9addc2d028d5.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/aa40dce194e0a25fc78f0328ac03cb81b6d49210476990c78ccee3b111accd73.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/b077d8793a5754064f1b26ffc9caa9bf4719e1d076cda65df24d835e7866eee1.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/b24a586f30b939dcaa5102891f41740a2de7a683334219ff2aa8093f79be9984.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/b89b89422916cf5a00cc62253b988312ce391e11dde765d5cbdf185d4d094f96.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/bd4762ac8506093822c424e8739c3f37bcc2e14e740131cf4321103b836a35c3.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/bd9d42bf193648f651820f3a3a1a03dca2a6d18ad0187beb3813f91d896c43c5.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/bf6468c1ddcd5d916a5521427058d26202fa63c18b37ef393f31bc01d28543e0.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/bf7fd466685ae346aafdb0a48be566e062057f94bbe085fe8efe28d161c69a93.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/c2e25f5261aac057766b4cd368f5fa20f873914f24d110854472914d366d0597.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/c36fe78465cacfb07b3c07c022bee4529fb29371024814754958c3a3a67c7a89.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/c3c7767238efb7fc510f806c36b0eb38e37cd73b065401262352352edb8aa9ea.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/c3fc52dfccea56f6436bec8874b20bd79ca21f1f52d5ae5bd2db958fa1161973.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/c4f1fe525004f9700aad9f447a96cae59ec8d7513949a83309a9ed2e89f0dce9.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/c5a4471caa826393df8dcfa9ef701b9793b4e3f01a452cb983ea8a67e86158ba.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/c5e1b53a5c90984bcd47d4796154460206e00b7e18294e602a2adad050417f65.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/c6c408777cf065f6f51f807a7c620888339e67eb20202011dc5c48d071dd34df.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/c81c93fce2e3b6ffdaaa122939db8b6dac9c2c08efcc51130c6f4bcfa6ded68d.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/ca8b5504fa7a784dddeb61bf3873df3b063d573d9024884b6f7aef5cc4c68234.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/cddce7a9022f9b9acb73b704b75bfa85fb13c4e1c2fd93c424cf11aad0c2fb73.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/ceb290a10b46d062e7d842132d92f0f7ed47d1d767cc0342f8614a2a66efc860.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/cfa59a1446dc903c8a397dd0e91912ffb58ead75e8972c8fc8fac950534e7e70.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/d22e14a93e6ff6320575834566c10dedf928d2b75590a1414f46e43cb090d0b8.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/d9b02777657049099c9a0e07bc3a9a99ae7893884f8e4155acb74955ece5840d.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/da45d2ae9fe68490049cfc7abd22a0ae2134d460c628d8055d559f26d12eaa67.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/dbe8487bd68f2ce38a8be40db561519be455bfdbb027ba9b3ec36ca0ef46c80c.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/defe0ff34dce8a32787718ae9341f330e69ce1f5ca33b8395b1d0f2c77ac3a05.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/df249f6d0df0c13648f78bf335ff11a9dcd037881149abb2eb9cef4b9e308a17.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/e18d8446947e85fb7d3dae080a1c94af592518d19815dd4346963b77d7f0bf41.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/e25022df9ad640e763d126da65e0e2c46e442b7422b71b2a1abf6981e7495585.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/e488a16b7cbc47aac50017a36778c0fc2613260a681b4b609578465428f17f3d.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/e516f1e4fb8af3629c7820c39a5ca9599478900ec9bc39d7461b0ddf4058d714.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/e61ae1c0f3494e06a8d53e1392f3a06a414947f771706408271a551c1db2d197.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/eb0305068db0d00bfd16f63b50d5fe9c9c052b318afea46b2763fc3909d2b8a5.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/ed06a386bca6f13cfeb70c788d2255ec37bc882d6954816cd623083ee8f417ad.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/efeae122d57f1f2c1f468660dec482c004f05d0c580ffaab1df50ce5b6cf7879.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/f12a5d8b8679a77da05f0a9e12dc328d8c8a728e8e45f72e257a8cf0133c1dc5.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/f14a58b36e8bdb893ee2b6c5dcd3fe064bc24d3200104e231f2d27deca8c4c3b.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/f1b58747f578cc2a8f31554c50f638de12f848c81f05fba28fcffe37bf88fb5f.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/fbb420f005e630def79505ed7935bccc7d8fbd26e9174bcbcf0dfa4a4d7dede5.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/fbd5c39b07ac111debc40006d5637fce307b14a3ac9e183ee5c7ee3278afbd7e.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/fc4ddb1271002c27ba5ca68ccbb481490478f2e890e4df94e799b14a8c18dedc.json +0 -1
- codex_bot-0.3.1/graphify-out/cache/fcd146f236526c2a0f9d45657066e52fd4f52e6d0485b1c19e8d5bdec875b0c3.json +0 -1
- codex_bot-0.3.1/graphify-out/graph.html +0 -257
- codex_bot-0.3.1/graphify-out/graph.json +0 -49051
- codex_bot-0.3.1/project_structure.txt +0 -589
- {codex_bot-0.3.1 → codex_bot-0.4.0}/.python-version +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/LICENSE +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/NOTICE +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/DOCUMENTATION_STANDARD.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/animation.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/base.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/director.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/discovery.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/factory.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/fsm.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/helper.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/http.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/i18n.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/middlewares.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/redis.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/router_builder.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/sender.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/api/url_signer.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/changelog.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/cli/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/engine/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/engine/container.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/engine/discovery.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/engine/factory.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/engine/http_db.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/engine/i18n.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/engine/middlewares.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/services/animation/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/services/base/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/services/director/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/services/fsm/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/services/helper/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/services/helper/url_signer.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/services/redis/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/architecture/services/view_sender/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/guide/getting_started.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/001_high_integrated_debug_system.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/002_med_docker_infrastructure.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/003_high_in_bot_guide_system.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/004_high_redis_fsm_integration.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/005_med_header_driven_navigation.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/006_med_redis_stream_contract.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/007_med_sqlalchemy_sender_storage.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/008_high_multi_broker_support.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/009_high_webhook_server.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/ARCHIVE.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/en_EN/tasks/backlog.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/cli/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/engine/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/engine/container.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/engine/discovery.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/engine/factory.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/engine/http_db.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/engine/i18n.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/engine/middlewares.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/services/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/services/animation/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/services/base/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/services/director/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/services/fsm/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/services/helper/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/services/helper/url_signer.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/services/redis/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/architecture/services/view_sender/README.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/guide/getting_started.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/001_high_integrated_debug_system.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/002_med_docker_infrastructure.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/003_high_in_bot_guide_system.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/004_high_redis_fsm_integration.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/005_med_header_driven_navigation.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/006_med_redis_stream_contract.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/007_med_sqlalchemy_sender_storage.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/008_high_multi_broker_support.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/009_high_webhook_server.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/ARCHIVE.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/docs/ru_RU/tasks/backlog.md +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/animation/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/animation/animation_service.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/base/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/base/base_orchestrator.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/base/context_dto.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/base/view_dto.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/cli/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/cli/commands/create_feature.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/cli/commands/migrations.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/cli/commands/startproject.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/cli/commands/utils.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/cli/main.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/cli/management.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/cli/templating.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/director/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/director/director.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/director/protocols.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/container.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/database/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/database/engine.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/database/models.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/database/repository.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/discovery/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/factory/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/factory/bot_builder.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/http/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/http/api_client.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/i18n/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/i18n/locales_compiler.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/middlewares/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/middlewares/container.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/middlewares/database.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/middlewares/director_middleware.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/middlewares/i18n.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/middlewares/throttling.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/middlewares/user_validation.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/protocols.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/router_builder/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/router_builder/router_builder.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/engine/runner.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/features/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/features/errors/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/features/errors/default_errors.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/features/errors/handlers.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/features/errors/orchestrator.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/features/errors/ui.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/fsm/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/fsm/common_fsm_handlers.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/fsm/garbage_collector.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/fsm/state_helper.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/fsm/state_manager.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/helper/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/helper/context_helper.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/helper/id_inspector.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/py.typed +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/redis/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/redis/dispatcher.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/redis/router.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/redis/stream_processor.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/sender/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/sender/memory_storage.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/sender/protocols.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/sender/redis_storage.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/sender/sender_keys.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/sender/sender_manager.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/sender/view_sender.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/stream/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/feature_setting.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/handlers/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/handlers/handlers.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/logic/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/logic/orchestrator.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/resources/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/resources/callbacks.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/resources/dto.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/resources/keyboards.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/redis/resources/texts.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/contracts/contract.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/feature_setting.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/handlers/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/handlers/handlers.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/logic/orchestrator.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/logic/state_manager.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/resources/callbacks.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/resources/dto.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/resources/formatters.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/resources/keyboards.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/resources/texts.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/feature/telegram/ui/ui.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/root/.env.example.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/root/.env.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/root/.gitignore.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/root/.python-version.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/root/README.md.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/root/docs/architecture_cheat_sheet.md.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/root/docs/message_flow.md.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/root/manage.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/alembic.ini.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/core/config.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/core/container.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/core/errors.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/core/factory.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/core/logging.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/core/settings.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/contracts/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/contracts/menu_contract.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/feature_setting.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/handlers/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/handlers/handlers.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/logic/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/logic/orchestrator.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/orchestrator.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/callbacks.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/dto.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/keyboards.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/texts.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/ui/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/ui/menu_ui.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/ui/ui.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/contracts/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/contracts/auth_contract.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/contracts/contract.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/feature_setting.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/handlers/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/handlers/handlers.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/logic/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/logic/orchestrator.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/callbacks.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/formatters.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/keyboards.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/texts.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/ui/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/features/telegram/commands/ui/commands_ui.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/infrastructure/database/__init__.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/infrastructure/database/migrations/env.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/infrastructure/database/migrations/script.py.mako.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/infrastructure/migrations/env.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/infrastructure/models/base.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/infrastructure/redis/container.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/infrastructure/repositories/base.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/launcher.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/resources/locales/en/messages.ftl.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/resources/locales/ru/messages.ftl.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/templates/project/src/shared/schemas/user.py.j2 +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/url_signer/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/src/codex_bot/url_signer/service.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/animation/test_animation_service.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/base/test_base_orchestrator.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/base/test_view_dto.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/conftest.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/director/test_director.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/engine/factory/test_bot_builder.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/engine/http/test_api_client.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/engine/middlewares/test_i18n.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/engine/middlewares/test_throttling.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/fsm/test_garbage_collector.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/fsm/test_state_manager.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/helper/test_context_helper.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/integration/test_templates_e2e.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/redis/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/redis/test_dispatcher.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/redis/test_router.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/sender/test_sender_keys.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/test_template_consistency.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/test_templates.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tests/url_signer/test_url_signer.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tools/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tools/dev/__init__.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tools/dev/check.py +0 -0
- {codex_bot-0.3.1 → codex_bot-0.4.0}/tools/dev/generate_project_tree.py +0 -0
|
@@ -7,6 +7,7 @@ __pycache__/
|
|
|
7
7
|
env/
|
|
8
8
|
venv/
|
|
9
9
|
.venv/
|
|
10
|
+
.venv-*/
|
|
10
11
|
ENV/
|
|
11
12
|
|
|
12
13
|
# --- Build & Distribution ---
|
|
@@ -49,6 +50,7 @@ docs/_build/
|
|
|
49
50
|
.mypy_cache/
|
|
50
51
|
.ruff_cache/
|
|
51
52
|
.uv-cache/
|
|
53
|
+
.uv-cache-*/
|
|
52
54
|
.dmypy.json
|
|
53
55
|
dmypy.json
|
|
54
56
|
.pyre/
|
|
@@ -72,3 +74,7 @@ sandbox/
|
|
|
72
74
|
# Agent instructions (local-only, points to local knowledge graph)
|
|
73
75
|
AGENTS.md
|
|
74
76
|
CLAUDE.md
|
|
77
|
+
|
|
78
|
+
# Generated local navigation artifacts
|
|
79
|
+
/graphify-out/
|
|
80
|
+
/project_structure.txt
|
|
@@ -5,6 +5,38 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.4.0] - 2026-10-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Versioned agent skill for projects using `codex-bot`, with an offline install, update, status, and delete command.
|
|
15
|
+
- Maintained project skill and English/Russian consumer installation guides.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Moved maintained repository guidance to `docs/agent-skills/` and stopped tracking local Claude configuration and generated navigation artifacts.
|
|
20
|
+
- Restricted source distributions to release files and excluded local caches, virtual environments, and generated graph output from Git tracking.
|
|
21
|
+
- Updated the locked `codex-core` dependency from 0.4.0 to 0.5.0.
|
|
22
|
+
- Raised the `aiohttp` and `pydantic-settings` minimum versions, aligned generated project dependencies, and refreshed vulnerable locked runtime, development, and documentation dependencies.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- Aligned the package's `__license__` attribute with its Apache-2.0 license and removed obsolete stream type-checker suppressions.
|
|
27
|
+
- Kept Telegram feature discovery usable without the optional Redis dependencies by loading stream integrations only when Redis handlers are registered.
|
|
28
|
+
|
|
29
|
+
## [0.3.1] - 2026-05-21
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- Updated stream router and dispatcher integration for `codex-platform` 0.5.2.
|
|
34
|
+
- Raised the development `pygments` floor to 2.20.0.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- Added recovery of stale pending Redis stream messages so unacknowledged events can be processed again.
|
|
39
|
+
|
|
8
40
|
## [0.3.0] - 2026-04-23
|
|
9
41
|
|
|
10
42
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: codex-bot
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Feature-based Aiogram framework library — reusable infrastructure for Telegram bots
|
|
5
5
|
Project-URL: Homepage, https://github.com/codexdlc/codex-bot
|
|
6
6
|
Project-URL: Documentation, https://codexdlc.github.io/codex-bot/
|
|
@@ -22,9 +22,9 @@ Classifier: Topic :: Communications :: Chat
|
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
23
23
|
Requires-Python: >=3.12
|
|
24
24
|
Requires-Dist: aiogram<4.0,>=3.27.0
|
|
25
|
-
Requires-Dist: aiohttp>=3.
|
|
25
|
+
Requires-Dist: aiohttp>=3.14.3
|
|
26
26
|
Requires-Dist: jinja2>=3.1.0
|
|
27
|
-
Requires-Dist: pydantic-settings>=2.
|
|
27
|
+
Requires-Dist: pydantic-settings>=2.14.2
|
|
28
28
|
Requires-Dist: pydantic<3.0,>=2.0
|
|
29
29
|
Requires-Dist: python-dotenv>=1.0.0
|
|
30
30
|
Requires-Dist: questionary>=2.0.0
|
|
@@ -141,6 +141,8 @@ if __name__ == "__main__":
|
|
|
141
141
|
|
|
142
142
|
## Documentation
|
|
143
143
|
|
|
144
|
+
Repository contributors can use the [project agent skill](docs/agent-skills/codex-bot/SKILL.md). To install the versioned library skill in a consuming project, see the [agent skill guide](docs/en_EN/guide/agent-skills.md).
|
|
145
|
+
|
|
144
146
|
Full documentation with architecture diagrams, API reference, and guides:
|
|
145
147
|
|
|
146
148
|
**[https://codexdlc.github.io/codex-bot/](https://codexdlc.github.io/codex-bot/)**
|
|
@@ -51,6 +51,8 @@ if __name__ == "__main__":
|
|
|
51
51
|
|
|
52
52
|
## Documentation
|
|
53
53
|
|
|
54
|
+
Repository contributors can use the [project agent skill](docs/agent-skills/codex-bot/SKILL.md). To install the versioned library skill in a consuming project, see the [agent skill guide](docs/en_EN/guide/agent-skills.md).
|
|
55
|
+
|
|
54
56
|
Full documentation with architecture diagrams, API reference, and guides:
|
|
55
57
|
|
|
56
58
|
**[https://codexdlc.github.io/codex-bot/](https://codexdlc.github.io/codex-bot/)**
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: codex-bot-project
|
|
3
|
+
description: Use when changing codex-bot source, templates, or public API in this repository.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# codex-bot project work
|
|
7
|
+
|
|
8
|
+
This is the canonical source of the `codex-bot` Python package. Read the relevant implementation and tests before changing behavior. Library usage instructions for consumers live in `src/codex_bot/agent_skills/resources/`; installed copies in other projects are managed outputs.
|
|
9
|
+
|
|
10
|
+
- For feature scaffolding or CLI changes, read [feature workflow](references/feature-workflow.md).
|
|
11
|
+
- For routing, orchestration, DTOs, or sender changes, read [runtime contracts](references/runtime-contracts.md).
|
|
12
|
+
- For agent-skill delivery changes, read [skill delivery](references/skill-delivery.md).
|
|
13
|
+
|
|
14
|
+
Run focused tests for changed behavior. The project configuration is `pyproject.toml`; the source package is under `src/codex_bot`. Follow the root `AGENTS.md` graphify instructions after code changes.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Feature generation and discovery
|
|
2
|
+
|
|
3
|
+
`codex_bot.cli.main` exposes `startproject`, `create-feature`, migration, and inspect commands. `startproject` renders files from `src/codex_bot/templates/project`; `create-feature` renders `telegram` or `redis` templates. Check the command implementation and template source together before changing generated output.
|
|
4
|
+
|
|
5
|
+
`FeatureDiscoveryService` in `src/codex_bot/engine/discovery/service.py` imports configured feature modules by convention. Telegram and Redis features use `features.telegram.<name>.feature_setting` and `features.redis.<name>.feature_setting`. When a feature's package layout changes, check discovery and generated templates together; tests in `tests/test_templates.py`, `tests/test_template_consistency.py`, and `tests/integration/test_templates_e2e.py` cover generated projects.
|
|
6
|
+
|
|
7
|
+
The CLI's `--force` option can overwrite existing project files. Inspect its actual merge behavior before changing it or recommending it for an existing user project.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Runtime contracts
|
|
2
|
+
|
|
3
|
+
`BaseBotOrchestrator` in `src/codex_bot/base/base_orchestrator.py` accepts a request-scoped `Director` and returns `ViewResultDTO` or `UnifiedViewDTO` from `render_content`. Keep per-request mutable data in arguments or the director, since orchestrator instances may be shared.
|
|
4
|
+
|
|
5
|
+
`ViewResultDTO` and `UnifiedViewDTO` in `src/codex_bot/base/view_dto.py` are frozen Pydantic models. Use `model_copy(update=...)` to derive a changed view. `ViewSender.send` needs `chat_id` and `session_key`; it persists message coordinates through `SenderManager`. It does not handle `alert_text`, which the callback handler must answer.
|
|
6
|
+
|
|
7
|
+
`BotBuilder` in `src/codex_bot/engine/factory/bot_builder.py` registers core middleware before project middleware. Changes to middleware registration affect request context and should be checked in `tests/engine/factory/test_bot_builder.py` and relevant middleware tests. `BaseStateManager` stores feature drafts under `draft:<feature_key>` and clears only its namespace.
|
|
8
|
+
|
|
9
|
+
`ThrottlingMiddleware` in `src/codex_bot/engine/middlewares/throttling.py` uses Redis `SET` with `nx=True` and a millisecond TTL for atomic rate limiting. Preserve that single-operation check when changing throttling; an `EXISTS` then `SET` sequence would permit concurrent requests through.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Shipped agent skill
|
|
2
|
+
|
|
3
|
+
Canonical consumer instructions live in `src/codex_bot/agent_skills/resources/`. The `python -m codex_bot.agent_skills` installer copies those resources into a consuming project's `.agents/skills/codex-bot/`, records managed hashes, and adds a bounded root `AGENTS.md` pointer. Consumer copies and manifests are managed; application-specific guidance belongs in a separate project skill.
|
|
4
|
+
|
|
5
|
+
When changing the public API, inspect the corresponding consumer reference for stale examples. When changing delivery, run `tests/agent_skills/test_installer.py`, build a wheel, inspect its payload, and test the module command from an isolated install. Installation and update must not replace local edits to managed files.
|
|
6
|
+
|
|
7
|
+
The source distribution uses an explicit include list in `pyproject.toml`. When adding release assets, check both the source archive and the wheel built from it. Local agent settings, generated graphs, caches, and `project_structure.txt` must stay outside both Git tracking and release artifacts; maintained skills under `docs/agent-skills` and packaged skill resources remain versioned.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Agent skill for consuming projects
|
|
2
|
+
|
|
3
|
+
`codex-bot` includes an optional offline skill for coding agents. It is packaged in the core Python distribution; no running Telegram bot or extra dependency is needed to install the guidance. Run these commands with the Python environment where `codex-bot` is installed and point `--project` to an existing project root:
|
|
4
|
+
|
|
5
|
+
```shell
|
|
6
|
+
python -m codex_bot.agent_skills status --project /path/to/bot
|
|
7
|
+
python -m codex_bot.agent_skills install --project /path/to/bot
|
|
8
|
+
python -m codex_bot.agent_skills update --project /path/to/bot
|
|
9
|
+
python -m codex_bot.agent_skills delete --project /path/to/bot
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Installation creates `.agents/skills/codex-bot/`, a `.manifest.json` containing the installed package version and file hashes, and a bounded pointer in the project's root `AGENTS.md`. Existing project instructions outside that block are preserved. `status` exits 0 only if the installation matches the installed package and its files. It exits 1 if absent, stale, modified, or corrupt.
|
|
13
|
+
|
|
14
|
+
After upgrading the package, run `update` to refresh the skill. Update and delete refuse to change locally modified managed files; copy your edits into a separate project-owned skill first. The installer also refuses unowned destination collisions and symlinks or Windows reparse points in the target path. It stages writes with rollback for ordinary filesystem errors; it does not promise crash-safe multi-file transactions or safe concurrent installer runs.
|
|
15
|
+
|
|
16
|
+
The repository's own maintenance skill is [separate](../../agent-skills/codex-bot/SKILL.md). Consumer-specific rules should not be written into the managed library skill.
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
The development path of **codex-bot** from a base framework to a complete Telegram development ecosystem.
|
|
4
4
|
|
|
5
|
+
Release 0.4.0 adds managed agent skills, offline skill installation, and dependency and packaging maintenance. See the [installation guide](guide/agent-skills.md). The unchecked items below are future work, without assigned release versions.
|
|
6
|
+
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
## ✅ Phase 1: Foundation (v0.1.0) — COMPLETED
|
|
@@ -10,7 +12,7 @@ The development path of **codex-bot** from a base framework to a complete Telegr
|
|
|
10
12
|
- [x] Basic Redis Integration: FSM and Storage.
|
|
11
13
|
- [x] CLI: `startproject` command and base templates.
|
|
12
14
|
|
|
13
|
-
## 🏗️ Phase 2: Protocols & Standardization
|
|
15
|
+
## 🏗️ Phase 2: Protocols & Standardization — IN PROGRESS
|
|
14
16
|
- [x] **Smart Merge**: Safe integration into existing projects via CLI.
|
|
15
17
|
- [x] **FSM Isolation**: Namespacing feature data (BaseStateManager).
|
|
16
18
|
- [x] **Smart Resolver**: `director.resolve()` pattern for navigation control.
|
|
@@ -19,20 +21,20 @@ The development path of **codex-bot** from a base framework to a complete Telegr
|
|
|
19
21
|
- [x] **Metadata-Driven Navigation**: Full support for `__next_scene__`. [**(Backlog)**](./tasks/backlog.md)
|
|
20
22
|
- [ ] **Redis Stream FSM Integration**: Automatic Director injection in Redis handlers. [**(Task #004b)**](./tasks/004_high_redis_fsm_integration.md)
|
|
21
23
|
|
|
22
|
-
## 🧩 Phase 3: DX & Tooling
|
|
24
|
+
## 🧩 Phase 3: DX & Tooling — PLANNED
|
|
23
25
|
- [ ] **In-Bot Guide System**: Interactive documentation navigator. [**(Task #003)**](./tasks/003_high_in_bot_guide_system.md)
|
|
24
26
|
- [ ] **Status Commands**: Built-in system health diagnostics (DB, Redis, API).
|
|
25
27
|
- [ ] **Strict Typing**: Transition to Enums for states and transitions.
|
|
26
28
|
- [ ] **Contextual Hints**: Educational mode in CLI during feature creation.
|
|
27
29
|
|
|
28
|
-
## 🚀 Phase 4: Scaling & Infrastructure
|
|
30
|
+
## 🚀 Phase 4: Scaling & Infrastructure — PLANNED
|
|
29
31
|
- [ ] **Webhooks Service**: Native support for incoming webhooks (FastAPI/Aiohttp). [**(Task #009)**](./tasks/009_high_webhook_server.md)
|
|
30
32
|
- [ ] **Docker Infrastructure**: Ready-to-use containerization templates. [**(Task #002)**](./tasks/002_med_docker_infrastructure.md)
|
|
31
33
|
- [ ] **Smart Recovery**: Automated retry logic for API and DB.
|
|
32
34
|
- [ ] **Animation Engine**: Expanding the library of visual waiting effects.
|
|
33
35
|
- [ ] **SQLAlchemy Sender Storage**: Persistent UI coordinate storage without Redis. [**(Task #007)**](./tasks/007_med_sqlalchemy_sender_storage.md)
|
|
34
36
|
|
|
35
|
-
## 📡 Phase 5: Event-Driven Ecosystem
|
|
37
|
+
## 📡 Phase 5: Event-Driven Ecosystem — PLANNED
|
|
36
38
|
- [ ] **Multi-Broker Support**: Adapters for RabbitMQ and Kafka with unified router syntax. [**(Task #008)**](./tasks/008_high_multi_broker_support.md)
|
|
37
39
|
- [ ] **Remote FSM Management**: User state management via brokers without Aiogram involvement.
|
|
38
40
|
- [ ] **Smart Routing**: Automated message distribution between multiple bot instances.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Навык для проектов на codex-bot
|
|
2
|
+
|
|
3
|
+
Пакет `codex-bot` содержит необязательный навык для кодовых агентов и автономный офлайн-установщик. Запускайте его через Python окружения, где установлен пакет; `--project` должен указывать на существующий корень проекта:
|
|
4
|
+
|
|
5
|
+
```shell
|
|
6
|
+
python -m codex_bot.agent_skills status --project /path/to/bot
|
|
7
|
+
python -m codex_bot.agent_skills install --project /path/to/bot
|
|
8
|
+
python -m codex_bot.agent_skills update --project /path/to/bot
|
|
9
|
+
python -m codex_bot.agent_skills delete --project /path/to/bot
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Установщик создаёт `.agents/skills/codex-bot/`, манифест с версией пакета и хешами файлов, а также ограниченный маркерами указатель в корневом `AGENTS.md`. Остальные инструкции проекта сохраняются. `status` возвращает код 0 только для актуальной и целой установки. После обновления пакета вызовите `update`. Команды `update` и `delete` отказываются перезаписывать локально изменённые управляемые файлы: сначала перенесите собственные правила в отдельный проектный навык.
|
|
13
|
+
|
|
14
|
+
Установщик отклоняет конфликтующие неуправляемые файлы, ссылки и Windows reparse points. Обычные ошибки записи обрабатываются откатом; гарантий атомарности при падении процесса или одновременных запусках нет. Навык для разработки самой библиотеки находится [отдельно](../../agent-skills/codex-bot/SKILL.md).
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Путь развития **codex-bot** от базового фреймворка до полноценной экосистемы разработки Telegram-ботов.
|
|
4
4
|
|
|
5
|
+
Выпуск 0.4.0 добавляет управляемые навыки агента, их офлайн-установку и обновления зависимостей и упаковки. См. [инструкцию установки](guide/agent-skills.md). Незавершённые пункты ниже остаются планами без привязки к номерам выпусков.
|
|
6
|
+
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
## ✅ Фаза 1: Фундамент (v0.1.0) — ЗАВЕРШЕНО
|
|
@@ -10,7 +12,7 @@
|
|
|
10
12
|
- [x] Базовая интеграция с Redis (FSM и Сторадж).
|
|
11
13
|
- [x] CLI: Команда `startproject` и базовые шаблоны.
|
|
12
14
|
|
|
13
|
-
## 🏗️ Фаза 2: Протоколы и Стандартизация
|
|
15
|
+
## 🏗️ Фаза 2: Протоколы и Стандартизация — В РАБОТЕ
|
|
14
16
|
- [x] **Smart Merge**: Безопасная интеграция в существующие проекты через CLI.
|
|
15
17
|
- [x] **Изоляция FSM**: Namespacing данных фич (BaseStateManager).
|
|
16
18
|
- [x] **Умный Резолвер**: Паттерн `director.resolve()` для управления навигацией.
|
|
@@ -19,20 +21,20 @@
|
|
|
19
21
|
- [x] **Metadata-Driven Navigation**: Полная поддержка `__next_scene__`. [**(Бэклог)**](./tasks/backlog.md)
|
|
20
22
|
- [x] **Интеграция Redis Stream с FSM**: Автоматическая инъекция Director в Redis-хендлеры. [**(Задача #004b)**](./tasks/004_high_redis_fsm_integration.md)
|
|
21
23
|
|
|
22
|
-
## 🧩 Фаза 3: DX & Tooling
|
|
24
|
+
## 🧩 Фаза 3: DX & Tooling — В ПЛАНАХ
|
|
23
25
|
- [ ] **Система Гидов**: Интерактивный навигатор по документации прямо в боте. [**(Задача #003)**](./tasks/003_high_in_bot_guide_system.md)
|
|
24
26
|
- [ ] **Команды Статуса**: Встроенная диагностика здоровья системы (БД, Redis, API).
|
|
25
27
|
- [ ] **Строгая Типизация**: Полный переход на Enums для состояний и переходов.
|
|
26
28
|
- [ ] **Контекстные подсказки**: Обучающий режим в CLI при создании фич.
|
|
27
29
|
|
|
28
|
-
## 🚀 Фаза 4: Масштабирование и Инфраструктура
|
|
30
|
+
## 🚀 Фаза 4: Масштабирование и Инфраструктура — В ПЛАНАХ
|
|
29
31
|
- [ ] **Webhooks Service**: Нативная поддержка входящих вебхуков (FastAPI/Aiohttp). [**(Задача #009)**](../en_EN/tasks/009_high_webhook_server.md)
|
|
30
32
|
- [ ] **Инфраструктура Docker**: Готовые шаблоны контейнеризации. [**(Задача #002)**](./tasks/002_med_docker_infrastructure.md)
|
|
31
33
|
- [ ] **Smart Recovery**: Автоматическая логика повторов (Retries) для API и БД.
|
|
32
34
|
- [ ] **SQLAlchemy Sender Storage**: Персистентное хранение координат UI без Redis. [**(Задача #007)**](../en_EN/tasks/007_med_sqlalchemy_sender_storage.md)
|
|
33
35
|
- [ ] **Animation Engine**: Расширение библиотеки визуальных эффектов ожидания.
|
|
34
36
|
|
|
35
|
-
## 📡 Фаза 5: Event-Driven Ecosystem
|
|
37
|
+
## 📡 Фаза 5: Event-Driven Ecosystem — БУДУЩЕЕ
|
|
36
38
|
- [ ] **Multi-Broker Support**: Адаптеры для RabbitMQ и Kafka с унифицированным синтаксисом роутеров. [**(Задача #008)**](../en_EN/tasks/008_high_multi_broker_support.md)
|
|
37
39
|
- [ ] **Remote FSM Management**: Управление состоянием пользователя через брокеры без участия aiogram.
|
|
38
40
|
- [ ] **Smart Routing**: Автоматическое распределение сообщений между разными инстансами бота.
|
|
@@ -50,6 +50,7 @@ nav:
|
|
|
50
50
|
- Guide (EN):
|
|
51
51
|
- Overview: en_EN/README.md
|
|
52
52
|
- Getting Started: en_EN/guide/getting_started.md
|
|
53
|
+
- Agent Skill: en_EN/guide/agent-skills.md
|
|
53
54
|
- Architecture: en_EN/architecture/README.md
|
|
54
55
|
- Roadmap: en_EN/roadmap.md
|
|
55
56
|
- CLI Engine: en_EN/architecture/cli/README.md
|
|
@@ -74,6 +75,7 @@ nav:
|
|
|
74
75
|
- Руководство (RU):
|
|
75
76
|
- Обзор: ru_RU/README.md
|
|
76
77
|
- Начало работы: ru_RU/guide/getting_started.md
|
|
78
|
+
- Навык агента: ru_RU/guide/agent-skills.md
|
|
77
79
|
- Обзор архитектуры: ru_RU/architecture/README.md
|
|
78
80
|
- Роадмап: ru_RU/roadmap.md
|
|
79
81
|
- Движок CLI: ru_RU/architecture/cli/README.md
|
|
@@ -23,9 +23,9 @@ classifiers = [
|
|
|
23
23
|
]
|
|
24
24
|
dependencies = [
|
|
25
25
|
"aiogram>=3.27.0,<4.0",
|
|
26
|
-
"aiohttp>=3.
|
|
26
|
+
"aiohttp>=3.14.3",
|
|
27
27
|
"pydantic>=2.0,<3.0",
|
|
28
|
-
"pydantic-settings>=2.
|
|
28
|
+
"pydantic-settings>=2.14.2",
|
|
29
29
|
"jinja2>=3.1.0",
|
|
30
30
|
"python-dotenv>=1.0.0",
|
|
31
31
|
"questionary>=2.0.0",
|
|
@@ -85,6 +85,22 @@ source = "vcs"
|
|
|
85
85
|
[tool.hatch.build.targets.wheel]
|
|
86
86
|
packages = ["src/codex_bot"]
|
|
87
87
|
|
|
88
|
+
[tool.hatch.build.targets.sdist]
|
|
89
|
+
include = [
|
|
90
|
+
"/src",
|
|
91
|
+
"/tests",
|
|
92
|
+
"/docs",
|
|
93
|
+
"/tools",
|
|
94
|
+
"/pyproject.toml",
|
|
95
|
+
"/uv.lock",
|
|
96
|
+
"/README.md",
|
|
97
|
+
"/CHANGELOG.md",
|
|
98
|
+
"/LICENSE",
|
|
99
|
+
"/NOTICE",
|
|
100
|
+
"/mkdocs.yml",
|
|
101
|
+
"/.python-version",
|
|
102
|
+
]
|
|
103
|
+
|
|
88
104
|
[tool.ruff]
|
|
89
105
|
target-version = "py312"
|
|
90
106
|
line-length = 120
|
|
@@ -15,7 +15,7 @@ except importlib.metadata.PackageNotFoundError:
|
|
|
15
15
|
__version__ = "unknown"
|
|
16
16
|
|
|
17
17
|
__author__ = "Codex Team"
|
|
18
|
-
__license__ = "
|
|
18
|
+
__license__ = "Apache-2.0"
|
|
19
19
|
|
|
20
20
|
from codex_bot.base.base_orchestrator import BaseBotOrchestrator, PayloadT
|
|
21
21
|
from codex_bot.director.director import Director
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# empty module
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import sys
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from codex_bot.agent_skills.fs_transaction import FSError
|
|
7
|
+
from codex_bot.agent_skills.orchestrator import OrchestratorError, check_status, perform_delete, perform_install
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main(args: Sequence[str] | None = None) -> None:
|
|
11
|
+
parser = argparse.ArgumentParser(prog="python -m codex_bot.agent_skills")
|
|
12
|
+
parser.add_argument("action", choices=["install", "update", "delete", "status"])
|
|
13
|
+
parser.add_argument("--project", required=True, help="Path to project root")
|
|
14
|
+
|
|
15
|
+
parsed = parser.parse_args(args)
|
|
16
|
+
|
|
17
|
+
project_dir = Path(parsed.project).absolute()
|
|
18
|
+
if not project_dir.is_dir():
|
|
19
|
+
print(f"Error: Project directory does not exist or is not a directory: {project_dir}", file=sys.stderr)
|
|
20
|
+
sys.exit(1)
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
if parsed.action == "install":
|
|
24
|
+
perform_install(project_dir, update=False)
|
|
25
|
+
print("Installed successfully.")
|
|
26
|
+
elif parsed.action == "update":
|
|
27
|
+
perform_install(project_dir, update=True)
|
|
28
|
+
print("Updated successfully.")
|
|
29
|
+
elif parsed.action == "delete":
|
|
30
|
+
perform_delete(project_dir)
|
|
31
|
+
print("Deleted successfully.")
|
|
32
|
+
elif parsed.action == "status":
|
|
33
|
+
is_valid, msg = check_status(project_dir)
|
|
34
|
+
print(msg)
|
|
35
|
+
if not is_valid:
|
|
36
|
+
sys.exit(1)
|
|
37
|
+
except (OrchestratorError, FSError) as e:
|
|
38
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
39
|
+
sys.exit(1)
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"""Same-volume staged writes with best-effort rollback after ordinary I/O errors."""
|
|
2
|
+
|
|
3
|
+
import errno
|
|
4
|
+
import os
|
|
5
|
+
import shutil
|
|
6
|
+
import stat
|
|
7
|
+
import tempfile
|
|
8
|
+
from contextlib import suppress
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class FSError(Exception):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def validate_no_symlinks(path: Path) -> Path:
|
|
17
|
+
"""Inspect every existing component with lstat, including dangling links."""
|
|
18
|
+
path = path.absolute()
|
|
19
|
+
parts = list(reversed((path, *path.parents)))
|
|
20
|
+
for index, part in enumerate(parts):
|
|
21
|
+
try:
|
|
22
|
+
info = part.lstat()
|
|
23
|
+
except FileNotFoundError:
|
|
24
|
+
continue
|
|
25
|
+
except OSError as exc:
|
|
26
|
+
raise FSError(f"Cannot inspect {part}: {exc}") from exc
|
|
27
|
+
if stat.S_ISLNK(info.st_mode) or getattr(info, "st_file_attributes", 0) & getattr(
|
|
28
|
+
stat, "FILE_ATTRIBUTE_REPARSE_POINT", 0
|
|
29
|
+
):
|
|
30
|
+
raise FSError(f"Symlink or reparse point detected: {part}")
|
|
31
|
+
if index < len(parts) - 1 and not stat.S_ISDIR(info.st_mode):
|
|
32
|
+
raise FSError(f"Non-directory ancestor: {part}")
|
|
33
|
+
return path
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def check_regular_file(path: Path) -> None:
|
|
37
|
+
validate_no_symlinks(path)
|
|
38
|
+
try:
|
|
39
|
+
info = path.lstat()
|
|
40
|
+
except FileNotFoundError:
|
|
41
|
+
return
|
|
42
|
+
except OSError as exc:
|
|
43
|
+
raise FSError(f"Cannot inspect {path}: {exc}") from exc
|
|
44
|
+
if not stat.S_ISREG(info.st_mode):
|
|
45
|
+
raise FSError(f"Not a regular file: {path}")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class FSTransaction:
|
|
49
|
+
def __init__(self, project_dir: Path):
|
|
50
|
+
self.project_dir = validate_no_symlinks(project_dir)
|
|
51
|
+
if not self.project_dir.is_dir():
|
|
52
|
+
raise FSError("Project is not a directory")
|
|
53
|
+
self.temp_dir = Path(tempfile.mkdtemp(prefix=".codex-bot-tx-", dir=self.project_dir))
|
|
54
|
+
self.backup_dir = self.temp_dir / "backup"
|
|
55
|
+
self.stage_dir = self.temp_dir / "stage"
|
|
56
|
+
self.backup_dir.mkdir()
|
|
57
|
+
self.stage_dir.mkdir()
|
|
58
|
+
self.to_write: list[tuple[Path, bytes]] = []
|
|
59
|
+
self.to_delete: list[Path] = []
|
|
60
|
+
self.to_prune: list[Path] = []
|
|
61
|
+
self._created_dirs: list[Path] = []
|
|
62
|
+
self._removed_dirs: list[Path] = []
|
|
63
|
+
self._snapshots: dict[Path, Path | None] = {}
|
|
64
|
+
self._retain = False
|
|
65
|
+
|
|
66
|
+
def _target(self, target: Path) -> Path:
|
|
67
|
+
target = validate_no_symlinks(target)
|
|
68
|
+
if not target.is_relative_to(self.project_dir) or target.is_relative_to(self.temp_dir):
|
|
69
|
+
raise FSError("Target outside project or inside transaction directory")
|
|
70
|
+
check_regular_file(target)
|
|
71
|
+
return target
|
|
72
|
+
|
|
73
|
+
def stage_write(self, target: Path, content: bytes) -> None:
|
|
74
|
+
self.to_write.append((self._target(target), content))
|
|
75
|
+
|
|
76
|
+
def stage_delete(self, target: Path) -> None:
|
|
77
|
+
target = self._target(target)
|
|
78
|
+
if target.exists():
|
|
79
|
+
self.to_delete.append(target)
|
|
80
|
+
|
|
81
|
+
def stage_prune_empty(self, directory: Path) -> None:
|
|
82
|
+
directory = validate_no_symlinks(directory)
|
|
83
|
+
if not directory.is_relative_to(self.project_dir) or directory == self.project_dir:
|
|
84
|
+
raise FSError("Unsafe directory cleanup target")
|
|
85
|
+
self.to_prune.append(directory)
|
|
86
|
+
|
|
87
|
+
def _make_parent(self, parent: Path) -> None:
|
|
88
|
+
missing: list[Path] = []
|
|
89
|
+
current = parent
|
|
90
|
+
while not current.exists():
|
|
91
|
+
missing.append(current)
|
|
92
|
+
current = current.parent
|
|
93
|
+
for directory in reversed(missing):
|
|
94
|
+
directory.mkdir()
|
|
95
|
+
self._created_dirs.append(directory)
|
|
96
|
+
|
|
97
|
+
def apply(self) -> None:
|
|
98
|
+
targets = list(dict.fromkeys([*self.to_delete, *(p for p, _ in self.to_write)]))
|
|
99
|
+
if len(targets) != len(self.to_delete) + len(self.to_write):
|
|
100
|
+
raise FSError("A target appears in multiple operations")
|
|
101
|
+
try:
|
|
102
|
+
# Snapshot every existing destination before the first mutation.
|
|
103
|
+
for index, target in enumerate(targets):
|
|
104
|
+
self._target(target)
|
|
105
|
+
backup = None
|
|
106
|
+
if target.exists():
|
|
107
|
+
backup = self.backup_dir / f"backup_{index}"
|
|
108
|
+
shutil.copy2(target, backup)
|
|
109
|
+
self._snapshots[target] = backup
|
|
110
|
+
for index, (_, data) in enumerate(self.to_write):
|
|
111
|
+
(self.stage_dir / f"write_stg_{index}").write_bytes(data)
|
|
112
|
+
for target in self.to_delete:
|
|
113
|
+
target.unlink()
|
|
114
|
+
for index, (target, _) in enumerate(self.to_write):
|
|
115
|
+
self._make_parent(target.parent)
|
|
116
|
+
os.replace(self.stage_dir / f"write_stg_{index}", target)
|
|
117
|
+
for directory in sorted(set(self.to_prune), key=lambda p: len(p.parts), reverse=True):
|
|
118
|
+
validate_no_symlinks(directory)
|
|
119
|
+
try:
|
|
120
|
+
directory.rmdir()
|
|
121
|
+
self._removed_dirs.append(directory)
|
|
122
|
+
except FileNotFoundError:
|
|
123
|
+
pass
|
|
124
|
+
except OSError as exc:
|
|
125
|
+
if exc.errno not in {errno.ENOTEMPTY, errno.EEXIST} and getattr(exc, "winerror", None) != 145:
|
|
126
|
+
raise
|
|
127
|
+
except Exception as exc:
|
|
128
|
+
try:
|
|
129
|
+
self.rollback()
|
|
130
|
+
except FSError as recovery:
|
|
131
|
+
self._retain = True
|
|
132
|
+
raise FSError(
|
|
133
|
+
f"Transaction failed: {exc}. Recovery failed: {recovery}. Backups retained at {self.temp_dir}"
|
|
134
|
+
) from exc
|
|
135
|
+
raise FSError(f"Transaction failed and was rolled back: {exc}") from exc
|
|
136
|
+
|
|
137
|
+
def rollback(self) -> None:
|
|
138
|
+
errors: list[str] = []
|
|
139
|
+
for directory in reversed(self._removed_dirs):
|
|
140
|
+
try:
|
|
141
|
+
directory.mkdir(exist_ok=True)
|
|
142
|
+
except Exception as exc:
|
|
143
|
+
errors.append(f"{directory}: {exc}")
|
|
144
|
+
for target, backup in reversed(list(self._snapshots.items())):
|
|
145
|
+
try:
|
|
146
|
+
if backup is None:
|
|
147
|
+
if target.exists():
|
|
148
|
+
target.unlink()
|
|
149
|
+
else:
|
|
150
|
+
self._make_parent(target.parent)
|
|
151
|
+
# Copy leaves the sole recovery copy intact if restoration fails.
|
|
152
|
+
shutil.copy2(backup, target)
|
|
153
|
+
except Exception as exc:
|
|
154
|
+
errors.append(f"{target}: {exc}")
|
|
155
|
+
for directory in reversed(self._created_dirs):
|
|
156
|
+
with suppress(OSError):
|
|
157
|
+
directory.rmdir()
|
|
158
|
+
if errors:
|
|
159
|
+
raise FSError("; ".join(errors))
|
|
160
|
+
|
|
161
|
+
def cleanup(self) -> None:
|
|
162
|
+
if self._retain:
|
|
163
|
+
return
|
|
164
|
+
root = self.temp_dir.absolute()
|
|
165
|
+
if root.parent != self.project_dir or not root.name.startswith(".codex-bot-tx-"):
|
|
166
|
+
raise FSError("Unsafe transaction cleanup path")
|
|
167
|
+
validate_no_symlinks(root)
|
|
168
|
+
shutil.rmtree(root)
|
|
169
|
+
|
|
170
|
+
def __enter__(self) -> "FSTransaction":
|
|
171
|
+
return self
|
|
172
|
+
|
|
173
|
+
def __exit__(self, _type: object, _value: object, _traceback: object) -> None:
|
|
174
|
+
self.cleanup()
|