diff --git a/.claude/commands/ci.md b/.claude/commands/ci.md new file mode 100644 index 000000000..db33f805f --- /dev/null +++ b/.claude/commands/ci.md @@ -0,0 +1,42 @@ +# CI Command + +Run continuous integration workflow with automatic issue resolution. + +## Usage + +```bash +/ci +``` + +## Description + +This command executes the full CI pipeline (`mask ci`) and automatically attempts to fix any issues that arise during: + +1. **Quality Checks** - Format, lint, and dead code analysis +2. **Testing** - Run complete test suite with coverage +3. **Building** - Build and validate application containers + +If any step fails, Claude will: +- Analyze the error output +- Identify the root cause +- Apply appropriate fixes (code formatting, dependency issues, test failures, etc.) +- Re-run the failed step to verify the fix +- Continue with the remaining CI steps + +The command ensures all quality gates pass before completing, making it safe for deployment or merge requests. + +## Implementation + +The command will: +1. Run `mask ci` to execute the full CI workflow +2. Monitor output for failures or warnings +3. Automatically resolve common issues: + - Code formatting violations + - Linting errors + - Import/dependency problems + - Test failures + - Build/container issues +4. Re-run failed steps after applying fixes +5. Report final CI status and any unresolved issues + +This provides an automated "fix and retry" approach to CI, reducing manual intervention while maintaining code quality standards. \ No newline at end of file diff --git a/.claude/commands/infrastructure.md b/.claude/commands/infrastructure.md new file mode 100644 index 000000000..6fbca3520 --- /dev/null +++ b/.claude/commands/infrastructure.md @@ -0,0 +1,14 @@ +--- +argument-hint: [message] +allowed-tools: Bash(*), Git(*), Pulumi(*) +description: Manage infra (up & down) +argument-hint: up | down +model: claude-3-5-haiku-20241022 +--- + +# Task +Interpret the first token of "$ARGUMENTS" as the action (up|down). Default to up. + +Then: +- If `up`, run: `flox activate --mask infrastructure up` +- If `down`, run: `flox activate -- mask infrastructure down` diff --git a/.claude/commands/lint.md b/.claude/commands/lint.md new file mode 100644 index 000000000..9088f36e7 --- /dev/null +++ b/.claude/commands/lint.md @@ -0,0 +1,10 @@ +--- +argument-hint: [message] +allowed-tools: Bash(*), Git(*), Pulumi(*) +description: Manage infra (up & down) +model: claude-3-5-haiku-20241022 +--- + +# Task +- run: `flox activate --mask lint` +- fix any linting errors diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 478bf6ce9..9cbed98af 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,25 +1,26 @@ { "permissions": { "allow": [ + "Bash(aws lightsail:*)", + "Bash(cat:*)", + "Bash(curl:*)", + "Bash(docker:*)", + "Bash(flox activate:*)", + "Bash(gh issue:*)", + "Bash(git add:*)", + "Bash(ln:*)", + "Bash(mask:*)", + "Bash(mise:*)", "Bash(mkdir:*)", - "Bash(gh issue create:*)", - "Bash(gh issue view:*)", - "Bash(mise run test:*)", - "Bash(mise ls:*)", - "Bash(mise tasks:*)", + "Bash(open:*)", "Bash(pre-commit:*)", + "Bash(pulumi:*)", + "Bash(python -m pytest:*)", "Bash(rm:*)", + "Bash(timeout 5 curl -I http://localhost:*)", + "Bash(uv:*)", "WebFetch(domain:docs.github.com)", - "Bash(git add:*)", - "Bash(python -m pytest:*)", - "Bash(uv pip:*)", - "Bash(cat:*)", - "Bash(mise run:*)", - "Bash(gh issue close:*)", - "Bash(ln:*)", - "WebSearch", - "Bash(docker build:*)", - "Bash(uv lock:*)" + "WebSearch" ], "deny": [], "defaultMode": "acceptEdits" diff --git a/.flox/env/manifest.lock b/.flox/env/manifest.lock index ed575a585..1f44b740d 100644 --- a/.flox/env/manifest.lock +++ b/.flox/env/manifest.lock @@ -15,6 +15,9 @@ "google-cloud-sdk": { "pkg-path": "google-cloud-sdk" }, + "gum": { + "pkg-path": "gum" + }, "mise": { "pkg-path": "mise" }, @@ -56,28 +59,28 @@ { "attr_path": "awscli2", "broken": false, - "derivation": "/nix/store/v5gxglicwhyknfwswhngrbawzdwnapp5-awscli2-2.27.2.drv", + "derivation": "/nix/store/a43dgdv7nbg7jcvhxawml2igwvcswgca-awscli2-2.28.1.drv", "description": "Unified tool to manage your AWS services", "install_id": "awscli2", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "awscli2-2.27.2", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "awscli2-2.28.1", "pname": "awscli2", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T04:22:53.969182Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:38:52.178118Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "2.27.2", + "version": "2.28.1", "outputs_to_install": [ "out" ], "outputs": { - "dist": "/nix/store/sc270lyggbhz78lcxh9khqmggayqpp6i-awscli2-2.27.2-dist", - "out": "/nix/store/b5fa0fplfpiyx8zwc9y7d08a57lsk229-awscli2-2.27.2" + "dist": "/nix/store/cpxy2pkb9jvrzvhkq8h70qf3c20mkich-awscli2-2.28.1-dist", + "out": "/nix/store/jg3mq99j92671mkxsv2y595mhz1idm0z-awscli2-2.28.1" }, "system": "aarch64-darwin", "group": "toplevel", @@ -86,28 +89,28 @@ { "attr_path": "awscli2", "broken": false, - "derivation": "/nix/store/7ykn42yxjf7ncyl2z00700hq214xs4jn-awscli2-2.27.2.drv", + "derivation": "/nix/store/d5h42iqd9sd7w2ccbqama2w0x34hqvqm-awscli2-2.28.1.drv", "description": "Unified tool to manage your AWS services", "install_id": "awscli2", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "awscli2-2.27.2", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "awscli2-2.28.1", "pname": "awscli2", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T04:41:01.084855Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:05:24.537933Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "2.27.2", + "version": "2.28.1", "outputs_to_install": [ "out" ], "outputs": { - "dist": "/nix/store/ss8xqzwn1l8qdbwlml439bx1ik13vxlk-awscli2-2.27.2-dist", - "out": "/nix/store/161s22pbddllc4mabgr5rvrpmhiffsp4-awscli2-2.27.2" + "dist": "/nix/store/ff74pp94wldmpxdzizlqv2fib9qckk0h-awscli2-2.28.1-dist", + "out": "/nix/store/zysgkg1r1fkha1cniq8ypn1b4fs6qgyg-awscli2-2.28.1" }, "system": "aarch64-linux", "group": "toplevel", @@ -116,28 +119,28 @@ { "attr_path": "awscli2", "broken": false, - "derivation": "/nix/store/id7b0p6cwlkcsnfb767s820ig9xj0qnp-awscli2-2.27.2.drv", + "derivation": "/nix/store/vygdhy1930j5waqcdw2hh3br76j4mvhw-awscli2-2.28.1.drv", "description": "Unified tool to manage your AWS services", "install_id": "awscli2", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "awscli2-2.27.2", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "awscli2-2.28.1", "pname": "awscli2", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T04:56:58.790359Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:29:24.859793Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "2.27.2", + "version": "2.28.1", "outputs_to_install": [ "out" ], "outputs": { - "dist": "/nix/store/q9rzj2ikpl9vn4sns3ydsy7i8sachnha-awscli2-2.27.2-dist", - "out": "/nix/store/l18j8wgidf145m0zw6ydg8blim44hrkq-awscli2-2.27.2" + "dist": "/nix/store/ymhmqj49kkxn7c681y3m3r5rpd9j952f-awscli2-2.28.1-dist", + "out": "/nix/store/r8f0d1zjf9y9ms8cq06011xfn47ksp2n-awscli2-2.28.1" }, "system": "x86_64-darwin", "group": "toplevel", @@ -146,28 +149,28 @@ { "attr_path": "awscli2", "broken": false, - "derivation": "/nix/store/j2ajkr3y4c0fg9lxl22z30hd4spb74d9-awscli2-2.27.2.drv", + "derivation": "/nix/store/7jcbal1gy7snrzncyaaa9rvvgq57nw3w-awscli2-2.28.1.drv", "description": "Unified tool to manage your AWS services", "install_id": "awscli2", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "awscli2-2.27.2", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "awscli2-2.28.1", "pname": "awscli2", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T05:15:55.508841Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:57:25.512454Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "2.27.2", + "version": "2.28.1", "outputs_to_install": [ "out" ], "outputs": { - "dist": "/nix/store/r5cw3141myaf5lnzra9c0nc8prb2zv6y-awscli2-2.27.2-dist", - "out": "/nix/store/gx3hx0b3lbm11sishxl4k7a7ha4w405q-awscli2-2.27.2" + "dist": "/nix/store/v5djmz4hra1bph7sya08qjacw8l4n696-awscli2-2.28.1-dist", + "out": "/nix/store/44hz642ffm3dzsfwqg8mqavbrp3nli4z-awscli2-2.28.1" }, "system": "x86_64-linux", "group": "toplevel", @@ -176,27 +179,27 @@ { "attr_path": "cargo", "broken": false, - "derivation": "/nix/store/6665a8zg1cpw2fjamds6261fmg1pa458-cargo-1.86.0.drv", + "derivation": "/nix/store/bakxj3wri0v57p4cb7gxm10blaw9mdjw-cargo-1.88.0.drv", "description": "Downloads your Rust project's dependencies and builds your project", "install_id": "cargo", "license": "[ MIT, Apache-2.0 ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "cargo-1.86.0", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "cargo-1.88.0", "pname": "cargo", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T04:22:54.464772Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:38:52.294787Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "1.86.0", + "version": "1.88.0", "outputs_to_install": [ "out" ], "outputs": { - "out": "/nix/store/v9kavzgzbym8adb6p7nxgid13jz76411-cargo-1.86.0" + "out": "/nix/store/3iyviwimri8mq0cqv4abg9mibkcyc1cy-cargo-1.88.0" }, "system": "aarch64-darwin", "group": "toplevel", @@ -205,27 +208,27 @@ { "attr_path": "cargo", "broken": false, - "derivation": "/nix/store/jq0483mr9g99x5swkgvdf8w0hhj7yq73-cargo-1.86.0.drv", + "derivation": "/nix/store/xkn4nvdn6hjfm860dqgx3l6k3y12ybqv-cargo-1.88.0.drv", "description": "Downloads your Rust project's dependencies and builds your project", "install_id": "cargo", "license": "[ MIT, Apache-2.0 ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "cargo-1.86.0", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "cargo-1.88.0", "pname": "cargo", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T04:41:01.216082Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:05:24.701444Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "1.86.0", + "version": "1.88.0", "outputs_to_install": [ "out" ], "outputs": { - "out": "/nix/store/4y830m5qm2xfvdacbsy3q1afxqnawihc-cargo-1.86.0" + "out": "/nix/store/6w7lghpjhkd5pw9y0hnnmg5w341jswyd-cargo-1.88.0" }, "system": "aarch64-linux", "group": "toplevel", @@ -234,27 +237,27 @@ { "attr_path": "cargo", "broken": false, - "derivation": "/nix/store/za3xhiav2xk7z8g0synrxz3az6ai0i2f-cargo-1.86.0.drv", + "derivation": "/nix/store/x63zvjypdk7bd3fx80jkzqscfwvc4l20-cargo-1.88.0.drv", "description": "Downloads your Rust project's dependencies and builds your project", "install_id": "cargo", "license": "[ MIT, Apache-2.0 ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "cargo-1.86.0", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "cargo-1.88.0", "pname": "cargo", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T04:56:58.878560Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:29:24.987011Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "1.86.0", + "version": "1.88.0", "outputs_to_install": [ "out" ], "outputs": { - "out": "/nix/store/mdqqq9g5zrisd3ng2j56a9gijr5fawp5-cargo-1.86.0" + "out": "/nix/store/8kwb2jmbf9xjhr18nw8sa66c0kivsqc4-cargo-1.88.0" }, "system": "x86_64-darwin", "group": "toplevel", @@ -263,147 +266,27 @@ { "attr_path": "cargo", "broken": false, - "derivation": "/nix/store/3f2cdkg4a3gjsw9mnb604ihqk1kq2dp2-cargo-1.86.0.drv", + "derivation": "/nix/store/gbxirn273y3mab26yhpx2gcwsw94wmz8-cargo-1.88.0.drv", "description": "Downloads your Rust project's dependencies and builds your project", "install_id": "cargo", "license": "[ MIT, Apache-2.0 ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "cargo-1.86.0", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "cargo-1.88.0", "pname": "cargo", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T05:15:55.650404Z", - "stabilities": [ - "unstable" - ], - "unfree": false, - "version": "1.86.0", - "outputs_to_install": [ - "out" - ], - "outputs": { - "out": "/nix/store/npqlgsia03kfhv8m9mav6hfnbawpg0yg-cargo-1.86.0" - }, - "system": "x86_64-linux", - "group": "toplevel", - "priority": 5 - }, - { - "attr_path": "fselect", - "broken": false, - "derivation": "/nix/store/admmm4b6lm869qnc1d487slsr6a9hl29-awscli-1.37.21.drv", - "description": "Unified tool to manage your AWS services", - "install_id": "awscli", - "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "awscli-1.37.21", - "pname": "awscli", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T04:22:53.969106Z", - "stabilities": [ - "unstable" - ], - "unfree": false, - "version": "1.37.21", - "outputs_to_install": [ - "out" - ], - "outputs": { - "dist": "/nix/store/0kiij3r29vams4xdly1j6ib989d6dg98-awscli-1.37.21-dist", - "out": "/nix/store/kx0nyd82ar3ajzwbcdw56zzvbivh8phd-awscli-1.37.21" - }, - "system": "aarch64-darwin", - "group": "toplevel", - "priority": 5 - }, - { - "attr_path": "awscli", - "broken": false, - "derivation": "/nix/store/3q1rbz2a9c33wb3s2xj2yv4zan0kcxkr-awscli-1.37.21.drv", - "description": "Unified tool to manage your AWS services", - "install_id": "awscli", - "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "awscli-1.37.21", - "pname": "awscli", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T04:41:01.084768Z", - "stabilities": [ - "unstable" - ], - "unfree": false, - "version": "1.37.21", - "outputs_to_install": [ - "out" - ], - "outputs": { - "dist": "/nix/store/0pkrgfbvr96wp9c5n7arv3iampydwv91-awscli-1.37.21-dist", - "out": "/nix/store/smz9bm1zf8slhl5p94klwd5i9ps3azr8-awscli-1.37.21" - }, - "system": "aarch64-linux", - "group": "toplevel", - "priority": 5 - }, - { - "attr_path": "awscli", - "broken": false, - "derivation": "/nix/store/yxixxykij7vpbqsh0fzavvwrm0k7pa81-awscli-1.37.21.drv", - "description": "Unified tool to manage your AWS services", - "install_id": "awscli", - "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "awscli-1.37.21", - "pname": "awscli", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T04:56:58.790280Z", - "stabilities": [ - "unstable" - ], - "unfree": false, - "version": "1.37.21", - "outputs_to_install": [ - "out" - ], - "outputs": { - "dist": "/nix/store/6knvfncqpmxx2yjcn2gswknqh63kq33d-awscli-1.37.21-dist", - "out": "/nix/store/r5819yiy7kh0z3xzv2jz90v58ky5h0kh-awscli-1.37.21" - }, - "system": "x86_64-darwin", - "group": "toplevel", - "priority": 5 - }, - { - "attr_path": "awscli", - "broken": false, - "derivation": "/nix/store/hixh89aq7lmk94rg19xc6p0yjgl187pl-awscli-1.37.21.drv", - "description": "Unified tool to manage your AWS services", - "install_id": "awscli", - "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "name": "awscli-1.37.21", - "pname": "awscli", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", - "rev_count": 807377, - "rev_date": "2025-05-28T19:24:49Z", - "scrape_date": "2025-05-31T05:15:55.508752Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:57:25.706690Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "1.37.21", + "version": "1.88.0", "outputs_to_install": [ "out" ], "outputs": { - "dist": "/nix/store/n9rbikvnh6c8byvd7xc07193rib9caw7-awscli-1.37.21-dist", - "out": "/nix/store/l4n82nf5mq4bfx8pjm10hn38xb22s3f8-awscli-1.37.21" + "out": "/nix/store/kg6psfcz4vjcvv8bpyvw422vrndrcq50-cargo-1.88.0" }, "system": "x86_64-linux", "group": "toplevel", @@ -416,13 +299,13 @@ "description": "Find files with SQL-like queries", "install_id": "fselect", "license": "[ Apache-2.0, MIT ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "fselect-0.9.0", "pname": "fselect", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T00:26:12.620192Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:38:53.069822Z", "stabilities": [ "unstable" ], @@ -445,13 +328,13 @@ "description": "Find files with SQL-like queries", "install_id": "fselect", "license": "[ Apache-2.0, MIT ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "fselect-0.9.0", "pname": "fselect", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T01:59:39.053607Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:05:25.933250Z", "stabilities": [ "unstable" ], @@ -474,13 +357,13 @@ "description": "Find files with SQL-like queries", "install_id": "fselect", "license": "[ Apache-2.0, MIT ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "fselect-0.9.0", "pname": "fselect", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:32:16.673494Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:29:25.774613Z", "stabilities": [ "unstable" ], @@ -503,13 +386,13 @@ "description": "Find files with SQL-like queries", "install_id": "fselect", "license": "[ Apache-2.0, MIT ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "fselect-0.9.0", "pname": "fselect", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T03:13:25.966552Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:57:27.101212Z", "stabilities": [ "unstable" ], @@ -532,13 +415,13 @@ "description": "Tools for the google cloud platform", "install_id": "google-cloud-sdk", "license": "Unspecified free software license", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "google-cloud-sdk-529.0.0", "pname": "google-cloud-sdk", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T00:26:12.870512Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:38:53.921750Z", "stabilities": [ "unstable" ], @@ -561,13 +444,13 @@ "description": "Tools for the google cloud platform", "install_id": "google-cloud-sdk", "license": "Unspecified free software license", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "google-cloud-sdk-529.0.0", "pname": "google-cloud-sdk", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T01:59:39.864067Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:05:26.751810Z", "stabilities": [ "unstable" ], @@ -590,13 +473,13 @@ "description": "Tools for the google cloud platform", "install_id": "google-cloud-sdk", "license": "Unspecified free software license", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "google-cloud-sdk-529.0.0", "pname": "google-cloud-sdk", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:32:17.016315Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:29:26.137968Z", "stabilities": [ "unstable" ], @@ -619,13 +502,13 @@ "description": "Tools for the google cloud platform", "install_id": "google-cloud-sdk", "license": "Unspecified free software license", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "google-cloud-sdk-529.0.0", "pname": "google-cloud-sdk", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T03:13:26.878159Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:57:28.079182Z", "stabilities": [ "unstable" ], @@ -641,30 +524,146 @@ "group": "toplevel", "priority": 5 }, + { + "attr_path": "gum", + "broken": false, + "derivation": "/nix/store/pg3cdd51qdyvz1y4f40sppnzi48w6kql-gum-0.16.2.drv", + "description": "Tasty Bubble Gum for your shell", + "install_id": "gum", + "license": "MIT", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "gum-0.16.2", + "pname": "gum", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:38:54.054101Z", + "stabilities": [ + "unstable" + ], + "unfree": false, + "version": "0.16.2", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/s9w5fifwbcl92x3r55r9lbiwmlyrlfig-gum-0.16.2" + }, + "system": "aarch64-darwin", + "group": "toplevel", + "priority": 5 + }, + { + "attr_path": "gum", + "broken": false, + "derivation": "/nix/store/h7k81r0f4j065q10xnl4h3dib8vyw8qj-gum-0.16.2.drv", + "description": "Tasty Bubble Gum for your shell", + "install_id": "gum", + "license": "MIT", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "gum-0.16.2", + "pname": "gum", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:05:26.984400Z", + "stabilities": [ + "unstable" + ], + "unfree": false, + "version": "0.16.2", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/7z4r5akxz40nfji1jz4bdk99k1biwdkc-gum-0.16.2" + }, + "system": "aarch64-linux", + "group": "toplevel", + "priority": 5 + }, + { + "attr_path": "gum", + "broken": false, + "derivation": "/nix/store/yv03ry4f80wp5cgxdb1d13l67n89lrv0-gum-0.16.2.drv", + "description": "Tasty Bubble Gum for your shell", + "install_id": "gum", + "license": "MIT", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "gum-0.16.2", + "pname": "gum", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:29:26.288938Z", + "stabilities": [ + "unstable" + ], + "unfree": false, + "version": "0.16.2", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/r6q70l6jqmgmmv8br9dpvh23c4lqkapq-gum-0.16.2" + }, + "system": "x86_64-darwin", + "group": "toplevel", + "priority": 5 + }, + { + "attr_path": "gum", + "broken": false, + "derivation": "/nix/store/1rl9xkxjazii9zr7ci73sjk20dp4v2yp-gum-0.16.2.drv", + "description": "Tasty Bubble Gum for your shell", + "install_id": "gum", + "license": "MIT", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "gum-0.16.2", + "pname": "gum", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:57:28.362539Z", + "stabilities": [ + "unstable" + ], + "unfree": false, + "version": "0.16.2", + "outputs_to_install": [ + "out" + ], + "outputs": { + "out": "/nix/store/ghqbmfsmdhccms652yx3n0mkj86jlz8r-gum-0.16.2" + }, + "system": "x86_64-linux", + "group": "toplevel", + "priority": 5 + }, { "attr_path": "mise", "broken": false, - "derivation": "/nix/store/wvkjklbcrwqc1zb3z1l99saalqmmrbgx-mise-2025.8.6.drv", + "derivation": "/nix/store/7w57p5s1b4106h9in0lscvvs60dkwjsc-mise-2025.8.10.drv", "description": "Front-end to your dev env", "install_id": "mise", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", - "name": "mise-2025.8.6", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "mise-2025.8.10", "pname": "mise", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T00:26:15.081436Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:38:56.567392Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "2025.8.6", + "version": "2025.8.10", "outputs_to_install": [ "out" ], "outputs": { - "out": "/nix/store/nnhr9arv6p3whvdzc7xvkifi9zvkj2d8-mise-2025.8.6" + "out": "/nix/store/x94gym8q9idh94dyfjvr53d1kh6vy2qf-mise-2025.8.10" }, "system": "aarch64-darwin", "group": "toplevel", @@ -673,27 +672,27 @@ { "attr_path": "mise", "broken": false, - "derivation": "/nix/store/dqlas8pkisrd49k59qsa3riz9skq14rj-mise-2025.8.6.drv", + "derivation": "/nix/store/hqp5m0pir2gfw5nlg7hpqmb5jzlmm8s6-mise-2025.8.10.drv", "description": "Front-end to your dev env", "install_id": "mise", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", - "name": "mise-2025.8.6", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "mise-2025.8.10", "pname": "mise", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T01:59:49.801432Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:05:37.035331Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "2025.8.6", + "version": "2025.8.10", "outputs_to_install": [ "out" ], "outputs": { - "out": "/nix/store/szp56d7i8360b8r0s64fskb052vkr6wm-mise-2025.8.6" + "out": "/nix/store/z8lyj43yndbcqydydq8nvz3qkv3x68rv-mise-2025.8.10" }, "system": "aarch64-linux", "group": "toplevel", @@ -702,27 +701,27 @@ { "attr_path": "mise", "broken": false, - "derivation": "/nix/store/q7n6h077wd3xqh8m9ylvz69jr41rcmvy-mise-2025.8.6.drv", + "derivation": "/nix/store/hxz7rgbwh3v09k3p1b6zanaalfrqrvfp-mise-2025.8.10.drv", "description": "Front-end to your dev env", "install_id": "mise", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", - "name": "mise-2025.8.6", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "mise-2025.8.10", "pname": "mise", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:32:19.614307Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:29:28.790678Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "2025.8.6", + "version": "2025.8.10", "outputs_to_install": [ "out" ], "outputs": { - "out": "/nix/store/skik69gqc1kadavrd3hkhja8qmwl6n2f-mise-2025.8.6" + "out": "/nix/store/0d0hgbin6fhhigmvwi3dyxkff01wq83i-mise-2025.8.10" }, "system": "x86_64-darwin", "group": "toplevel", @@ -731,27 +730,27 @@ { "attr_path": "mise", "broken": false, - "derivation": "/nix/store/1cyg8v3wskbkg2xwjgh9dy3c27772qh6-mise-2025.8.6.drv", + "derivation": "/nix/store/32pn0bh7dz78cinkq5wf02miwpw3ppz8-mise-2025.8.10.drv", "description": "Front-end to your dev env", "install_id": "mise", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", - "name": "mise-2025.8.6", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "mise-2025.8.10", "pname": "mise", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T03:13:39.000824Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:57:40.546450Z", "stabilities": [ "unstable" ], "unfree": false, - "version": "2025.8.6", + "version": "2025.8.10", "outputs_to_install": [ "out" ], "outputs": { - "out": "/nix/store/7kxwlzg2dn4pa6ngif1hl7lcxsjpvibq-mise-2025.8.6" + "out": "/nix/store/5akarcdrqqss4rr2jipmncv71dmdpb1n-mise-2025.8.10" }, "system": "x86_64-linux", "group": "toplevel", @@ -764,13 +763,13 @@ "description": "Modern shell written in Rust", "install_id": "nushell", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "nushell-0.106.1", "pname": "nushell", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T00:26:15.733915Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:38:57.321054Z", "stabilities": [ "unstable" ], @@ -793,13 +792,13 @@ "description": "Modern shell written in Rust", "install_id": "nushell", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "nushell-0.106.1", "pname": "nushell", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T01:59:51.473137Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:05:38.806106Z", "stabilities": [ "unstable" ], @@ -822,13 +821,13 @@ "description": "Modern shell written in Rust", "install_id": "nushell", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "nushell-0.106.1", "pname": "nushell", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:32:20.392232Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:29:29.560970Z", "stabilities": [ "unstable" ], @@ -851,13 +850,13 @@ "description": "Modern shell written in Rust", "install_id": "nushell", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "nushell-0.106.1", "pname": "nushell", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T03:13:40.953445Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:57:42.522527Z", "stabilities": [ "unstable" ], @@ -880,13 +879,13 @@ "description": "Cloud development platform that makes creating cloud programs easy and productive", "install_id": "pulumi", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "pulumi-3.185.0", "pname": "pulumi", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T00:26:22.054956Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:39:05.336003Z", "stabilities": [ "unstable" ], @@ -909,13 +908,13 @@ "description": "Cloud development platform that makes creating cloud programs easy and productive", "install_id": "pulumi", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "pulumi-3.185.0", "pname": "pulumi", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:00:06.056158Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:05:53.897916Z", "stabilities": [ "unstable" ], @@ -938,13 +937,13 @@ "description": "Cloud development platform that makes creating cloud programs easy and productive", "install_id": "pulumi", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "pulumi-3.185.0", "pname": "pulumi", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:32:27.943149Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:29:37.376526Z", "stabilities": [ "unstable" ], @@ -967,13 +966,13 @@ "description": "Cloud development platform that makes creating cloud programs easy and productive", "install_id": "pulumi", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "pulumi-3.185.0", "pname": "pulumi", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T03:13:56.426861Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:57:58.544355Z", "stabilities": [ "unstable" ], @@ -996,13 +995,13 @@ "description": "Language host for Pulumi programs written in Python", "install_id": "pulumi-python", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "pulumi-python-3.185.0", "pname": "pulumi-python", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T00:26:22.064739Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:39:05.349455Z", "stabilities": [ "unstable" ], @@ -1025,13 +1024,13 @@ "description": "Language host for Pulumi programs written in Python", "install_id": "pulumi-python", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "pulumi-python-3.185.0", "pname": "pulumi-python", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:00:06.075355Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:05:53.917252Z", "stabilities": [ "unstable" ], @@ -1054,13 +1053,13 @@ "description": "Language host for Pulumi programs written in Python", "install_id": "pulumi-python", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "pulumi-python-3.185.0", "pname": "pulumi-python", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:32:27.954954Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:29:37.388944Z", "stabilities": [ "unstable" ], @@ -1083,13 +1082,13 @@ "description": "Language host for Pulumi programs written in Python", "install_id": "pulumi-python", "license": "Apache-2.0", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "pulumi-python-3.185.0", "pname": "pulumi-python", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T03:13:56.452524Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:57:58.563478Z", "stabilities": [ "unstable" ], @@ -1112,13 +1111,13 @@ "description": "Extremely fast Python linter and code formatter", "install_id": "ruff", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "ruff-0.12.4", "pname": "ruff", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T00:26:48.523662Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:39:42.999111Z", "stabilities": [ "unstable" ], @@ -1141,13 +1140,13 @@ "description": "Extremely fast Python linter and code formatter", "install_id": "ruff", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "ruff-0.12.4", "pname": "ruff", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:00:55.335510Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:06:47.837355Z", "stabilities": [ "unstable" ], @@ -1170,13 +1169,13 @@ "description": "Extremely fast Python linter and code formatter", "install_id": "ruff", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "ruff-0.12.4", "pname": "ruff", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:33:00.323658Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:30:11.549125Z", "stabilities": [ "unstable" ], @@ -1199,13 +1198,13 @@ "description": "Extremely fast Python linter and code formatter", "install_id": "ruff", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "ruff-0.12.4", "pname": "ruff", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T03:14:48.280945Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:58:51.307453Z", "stabilities": [ "unstable" ], @@ -1228,13 +1227,13 @@ "description": "Extremely fast Python package installer and resolver, written in Rust", "install_id": "uv", "license": "[ Apache-2.0, MIT ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "uv-0.8.2", "pname": "uv", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T00:27:16.729256Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:40:23.781590Z", "stabilities": [ "unstable" ], @@ -1257,13 +1256,13 @@ "description": "Extremely fast Python package installer and resolver, written in Rust", "install_id": "uv", "license": "[ Apache-2.0, MIT ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "uv-0.8.2", "pname": "uv", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:01:44.564146Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:07:42.514089Z", "stabilities": [ "unstable" ], @@ -1286,13 +1285,13 @@ "description": "Extremely fast Python package installer and resolver, written in Rust", "install_id": "uv", "license": "[ Apache-2.0, MIT ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "uv-0.8.2", "pname": "uv", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:33:35.880116Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:30:48.943480Z", "stabilities": [ "unstable" ], @@ -1315,13 +1314,13 @@ "description": "Extremely fast Python package installer and resolver, written in Rust", "install_id": "uv", "license": "[ Apache-2.0, MIT ]", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "uv-0.8.2", "pname": "uv", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T03:15:39.576767Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:59:43.505055Z", "stabilities": [ "unstable" ], @@ -1340,17 +1339,17 @@ { "attr_path": "python313Packages.vulture", "broken": false, - "derivation": "/nix/store/32nihzi1nx446pk383g78d6mw6xc734s-python3.13-vulture-2.14.drv", + "derivation": "/nix/store/1cdyhxsd5fcm42c9gnq3df14kmr7vyf2-python3.12-vulture-2.14.drv", "description": "Finds unused code in Python programs", "install_id": "vulture", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", - "name": "python3.13-vulture-2.14", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "python3.12-vulture-2.14", "pname": "vulture", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T00:26:43.523561Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:39:18.274864Z", "stabilities": [ "unstable" ], @@ -1360,8 +1359,8 @@ "out" ], "outputs": { - "dist": "/nix/store/g4w4vfh1hgm5vfxqxxy7a0rlc1hybixh-python3.13-vulture-2.14-dist", - "out": "/nix/store/cjpzb97gl8giy0awwhzs2fxrzbldjdw7-python3.13-vulture-2.14" + "dist": "/nix/store/prlwip9g83wjvjfhvn929s79fgxk309d-python3.12-vulture-2.14-dist", + "out": "/nix/store/nc3qhy5wkg2ix4xrkg2d8whq6vkq0di0-python3.12-vulture-2.14" }, "system": "aarch64-darwin", "group": "toplevel", @@ -1370,17 +1369,17 @@ { "attr_path": "python313Packages.vulture", "broken": false, - "derivation": "/nix/store/45pjsi9x9x3lk7d8gv2yl8749gfdbh6x-python3.13-vulture-2.14.drv", + "derivation": "/nix/store/d13csg2i23c6ldnq781ysc6rn0zda7id-python3.12-vulture-2.14.drv", "description": "Finds unused code in Python programs", "install_id": "vulture", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", - "name": "python3.13-vulture-2.14", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "python3.12-vulture-2.14", "pname": "vulture", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:00:45.953676Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:06:13.274078Z", "stabilities": [ "unstable" ], @@ -1390,8 +1389,8 @@ "out" ], "outputs": { - "dist": "/nix/store/4c6lq83d3q593vrs8x22fmv052i9gfb7-python3.13-vulture-2.14-dist", - "out": "/nix/store/nk1cwmm3n2zwmhv1134sq5yh8mpkgc2b-python3.13-vulture-2.14" + "dist": "/nix/store/3843mxlcpkcp0hz508477fckxciw6iqq-python3.12-vulture-2.14-dist", + "out": "/nix/store/yxl6yjn3wirqzmsy648xjzi8567jx69c-python3.12-vulture-2.14" }, "system": "aarch64-linux", "group": "toplevel", @@ -1400,17 +1399,17 @@ { "attr_path": "python313Packages.vulture", "broken": false, - "derivation": "/nix/store/ndpdvvqw75hnr9p4gq0sa0q1sanjf3rn-python3.13-vulture-2.14.drv", + "derivation": "/nix/store/a5432g3swgky0xdg7l2mxr2d49qj9iyz-python3.12-vulture-2.14.drv", "description": "Finds unused code in Python programs", "install_id": "vulture", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", - "name": "python3.13-vulture-2.14", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "python3.12-vulture-2.14", "pname": "vulture", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:32:54.078468Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:29:48.871215Z", "stabilities": [ "unstable" ], @@ -1420,8 +1419,8 @@ "out" ], "outputs": { - "dist": "/nix/store/9q4vnqp0rpggp04c5w9pjk7sp21d0xsy-python3.13-vulture-2.14-dist", - "out": "/nix/store/6bhr50lfglxdmpv9n3jhmi98hbzacggj-python3.13-vulture-2.14" + "dist": "/nix/store/8an3lm4pc8m5wk5nr0c83rnmh1641nwc-python3.12-vulture-2.14-dist", + "out": "/nix/store/kfdv2lsh0wls4x5fqgyc8kqpvqwzyryc-python3.12-vulture-2.14" }, "system": "x86_64-darwin", "group": "toplevel", @@ -1430,17 +1429,17 @@ { "attr_path": "python313Packages.vulture", "broken": false, - "derivation": "/nix/store/4sgflvdh30xvfd2a55025afj6v97m664-python3.13-vulture-2.14.drv", + "derivation": "/nix/store/3mwcz6b8jk8vf5dz5f3yhpxzl8mwiy8q-python3.12-vulture-2.14.drv", "description": "Finds unused code in Python programs", "install_id": "vulture", "license": "MIT", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", - "name": "python3.13-vulture-2.14", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", + "name": "python3.12-vulture-2.14", "pname": "vulture", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T03:14:38.091751Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:58:17.484983Z", "stabilities": [ "unstable" ], @@ -1450,8 +1449,8 @@ "out" ], "outputs": { - "dist": "/nix/store/b4hhs9y36f2b96l505bpp54hp7lifpwm-python3.13-vulture-2.14-dist", - "out": "/nix/store/gnffvcxchixrzy552h98v2jccav27bnf-python3.13-vulture-2.14" + "dist": "/nix/store/cc5pk4ic26v348ww0yd0qy05hdd3b3mp-python3.12-vulture-2.14-dist", + "out": "/nix/store/cq7g4h7p69vy01wkrk1yv7mf9b0h5kcg-python3.12-vulture-2.14" }, "system": "x86_64-linux", "group": "toplevel", @@ -1464,13 +1463,13 @@ "description": "Linter for YAML files", "install_id": "yamllint", "license": "GPL-3.0-or-later", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "python3.13-yamllint-1.37.1", "pname": "yamllint", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T00:27:24.798276Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T15:40:35.150003Z", "stabilities": [ "unstable" ], @@ -1494,13 +1493,13 @@ "description": "Linter for YAML files", "install_id": "yamllint", "license": "GPL-3.0-or-later", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "python3.13-yamllint-1.37.1", "pname": "yamllint", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:01:59.340541Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:07:58.981342Z", "stabilities": [ "unstable" ], @@ -1524,13 +1523,13 @@ "description": "Linter for YAML files", "install_id": "yamllint", "license": "GPL-3.0-or-later", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "python3.13-yamllint-1.37.1", "pname": "yamllint", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T02:33:46.012406Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:30:59.574663Z", "stabilities": [ "unstable" ], @@ -1554,13 +1553,13 @@ "description": "Linter for YAML files", "install_id": "yamllint", "license": "GPL-3.0-or-later", - "locked_url": "https://github.com/flox/nixpkgs?rev=005433b926e16227259a1843015b5b2b7f7d1fc3", + "locked_url": "https://github.com/flox/nixpkgs?rev=20075955deac2583bb12f07151c2df830ef346b4", "name": "python3.13-yamllint-1.37.1", "pname": "yamllint", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", - "rev_count": 843472, - "rev_date": "2025-08-12T19:39:21Z", - "scrape_date": "2025-08-14T03:15:55.394937Z", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev_count": 846535, + "rev_date": "2025-08-19T15:00:17Z", + "scrape_date": "2025-08-24T16:59:59.715484Z", "stabilities": [ "unstable" ], diff --git a/.flox/env/manifest.toml b/.flox/env/manifest.toml index 881c74c8a..2f6e15072 100644 --- a/.flox/env/manifest.toml +++ b/.flox/env/manifest.toml @@ -13,6 +13,7 @@ fselect.pkg-path = "fselect" google-cloud-sdk.pkg-path = "google-cloud-sdk" awscli2.pkg-path = "awscli2" cargo.pkg-path = "cargo" +gum.pkg-path = "gum" [hook] diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index bccc1fe82..000000000 --- a/AGENTS.md +++ /dev/null @@ -1,21 +0,0 @@ -# Codex Agent Instructions - -This project uses **mise** tasks for code quality and testing. Before committing, run the following steps: - -1. Install dependencies with `mise run python:install`. -2. Format code with `mise run python:format`. -3. Run lint checks with `mise run python:lint`. -4. Execute tests with `mise run python:test`. - -## Code Style - -- Write tested, self-documenting code. Avoid comments unless the code is complex. - -## Pull Requests - -- Use the Pull Request template: `.github/PULL_REQUEST_TEMPLATE.md`. - -## GitHub Issues - -- When creating an issue, use the templates under `.github/ISSUE_TEMPLATE`. -- Include a clear title, the reason the feature or fix is needed, and two implementation options with cost-benefit analysis. diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 120000 index 47dc3e3d8..000000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -AGENTS.md \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..593d28cbf --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,107 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Development Commands + +### Core Development +- **Install dependencies**: `mask development python install` (after `flox activate`) +- **Format code**: `mask development python format` (uses ruff) +- **Lint code**: `mask development python lint` (ruff with comprehensive ruleset) +- **Run tests**: `mask development python test` (pytest with coverage) +- **Check for dead code**: `mask development python dead-code` (vulture) +- **Run all quality checks**: `mask development quality` + +### Testing +- **Run tests with coverage**: `uv run coverage run --parallel-mode -m pytest && uv run coverage combine && uv run coverage report` +- **Single test file**: `uv run pytest applications/*/tests/test_.py` +- **Coverage output**: Available in `coverage_output/.python_coverage.xml` + +### Infrastructure & Deployment +- **Deploy infrastructure**: `mask infrastructure base up` +- **Teardown infrastructure**: `mask infrastructure base down` +- **Deploy applications**: `mask applications up` +- **Test endpoints**: `mask test` +- **Check Docker contexts**: `docker context ls` + +### Development Environment +- **Environment manager**: Flox (`flox activate` to enter development shell) +- **Package manager**: uv (workspace with `applications/*` and `libraries/python`) +- **Python version**: 3.12.10 (strict requirement across all projects) + +## Architecture Overview + +### Workspace Structure +This is a **UV workspace** with multiple applications and shared libraries: + +- **Root workspace** (`pyproject.toml`): Main project configuration with workspace members +- **Applications** (`applications/*/`): Microservices deployed as Docker containers + - `datamanager`: Data collection service (FastAPI on port 8080) + - `portfoliomanager`: Portfolio prediction service (FastAPI on port 8081) + - `models`: ML model training and data processing workflows +- **Libraries** (`libraries/python/`): Shared `internal` package with common utilities +- **Infrastructure** (`infrastructure/`): Pulumi-based cloud deployment + +### Shared Internal Library (`libraries/python/src/internal/`) +Core components used across applications: +- **ML Components**: TFT models, LSTM/MHSA networks, loss functions +- **Data Types**: Equity bars, datasets, cloud events, money types +- **Utilities**: Date handling, data summaries + +### Deployment Architecture +- **Local Development**: Docker Swarm on localhost +- **Production**: Pulumi-managed cloud infrastructure with Docker Swarm +- **Container Registry**: DockerHub (`pocketsizefund/*` images) +- **Monitoring**: Grafana, Prometheus, Portainer +- **Networking**: Traefik reverse proxy with Let's Encrypt TLS + +### Service Communication +- **HTTP APIs**: FastAPI applications with health endpoints (`/health`) +- **Cloud Events**: Standardized event format for inter-service communication +- **Docker Networks**: Overlay networks (`public`, `internal`, `app-network`) + +## Code Standards + +### Python Configuration +- **Formatter**: Ruff (replaces black/isort) +- **Linter**: Ruff with comprehensive ruleset (90+ rule categories enabled) +- **Type Checking**: Pyright with relaxed import resolution +- **Testing**: Pytest with strict configuration +- **Coverage**: Line coverage tracking with parallel execution + +### Key Dependencies +- **Web Framework**: FastAPI (consistent across services) +- **ML Stack**: TinyGrad, NumPy, Polars +- **Data**: PyArrow, Polars for data processing +- **Cloud**: Boto3, Azure libraries, Google Cloud SDK +- **Monitoring**: Structlog for structured logging + +## Development Principles + +From the project README, the team follows these principles: +- Test in production +- Always roll forward +- Systems over process +- No code is good code +- Never write documentation +- Git is truth + +## Infrastructure Secrets + +Required Docker Swarm secrets for deployment: +- `GRAFANA_ADMIN_PASSWORD` +- `ALPACA_API_KEY`, `ALPACA_API_SECRET`, `ALPACA_BASE_URL` +- `EDGAR_USER_AGENT`, `DATA_BUCKET` +- `POLYGON_API_KEY`, `DUCKDB_ACCESS_KEY`, `DUCKDB_SECRET` +- `WEIGHTS_AND_BIASES_API_KEY` + +Create with: `echo "value" | docker secret create SECRET_NAME -` + +## Common Workflow + +1. **Setup**: `flox activate && mise run python:install` +2. **Develop**: Make changes to application or shared library code +3. **Quality**: `mise run lint` (format, lint, test, dead code check) +4. **Local Deploy**: `mask infrastructure base up` (deploys to both local and production) +5. **Test**: `mask test` (validates service endpoints) +6. **Monitor**: Access Grafana, Portainer, or service logs via Docker contexts \ No newline at end of file diff --git a/applications/datamanager/.claude/settings.local.json b/applications/datamanager/.claude/settings.local.json new file mode 100644 index 000000000..357bdf46f --- /dev/null +++ b/applications/datamanager/.claude/settings.local.json @@ -0,0 +1,10 @@ +{ + "permissions": { + "allow": [ + "Bash(cat:*)", + "Bash(docker:*)" + ], + "deny": [], + "defaultMode": "acceptEdits" + } +} \ No newline at end of file diff --git a/applications/datamanager/Dockerfile b/applications/datamanager/Dockerfile new file mode 100644 index 000000000..c0840f4bd --- /dev/null +++ b/applications/datamanager/Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.12.10 +COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv + +ENV PYTHONPATH=/app/src + +WORKDIR /app + +COPY pyproject.toml ./ +RUN uv sync --no-dev + +COPY ./src ./src + +EXPOSE 8080 + +ENTRYPOINT ["uv", "run", "uvicorn", "datamanager.main:application", "--host", "0.0.0.0", "--port", "8080", "--app-dir", "src"] diff --git a/applications/datamanager/pyproject.toml b/applications/datamanager/pyproject.toml index 1dca620af..dfc9b4e75 100644 --- a/applications/datamanager/pyproject.toml +++ b/applications/datamanager/pyproject.toml @@ -4,16 +4,7 @@ version = "0.1.0" description = "Data collection and management service" requires-python = "==3.12.10" dependencies = [ - "internal", - "loguru>=0.7.3", - "alpaca-py>=0.42.0", - "boto3>=1.38.23", - "duckdb>=1.2.2", + "fastapi>=0.116.1", + "structlog>=25.4.0", + "uvicorn>=0.35.0", ] - -[tool.uv] -package = true -src = ["src"] - -[tool.uv.sources] -internal = { workspace = true } diff --git a/applications/datamanager/src/datamanager/main.py b/applications/datamanager/src/datamanager/main.py index e69de29bb..9d41a1e77 100644 --- a/applications/datamanager/src/datamanager/main.py +++ b/applications/datamanager/src/datamanager/main.py @@ -0,0 +1,21 @@ +from fastapi import FastAPI, Response, status +from structlog import get_logger + +logger = get_logger() + +app: FastAPI = FastAPI() + + +@app.get("/health") +def health_check() -> Response: + return Response(status_code=status.HTTP_200_OK) + + +@app.get("/portfolio-check") +def check_portfolio() -> Response: + logger.info("I was called by the portfoliomanager") + + return Response(status_code=status.HTTP_200_OK) + + +application = app diff --git a/applications/models/Dockerfile b/applications/models/Dockerfile new file mode 100644 index 000000000..8a22e5e12 --- /dev/null +++ b/applications/models/Dockerfile @@ -0,0 +1 @@ +FROM python:3.12.10 diff --git a/applications/portfoliomanager/Dockerfile b/applications/portfoliomanager/Dockerfile new file mode 100644 index 000000000..9f92512ad --- /dev/null +++ b/applications/portfoliomanager/Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.12.10 +COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv + +ENV PYTHONPATH=/app/src + +WORKDIR /app + +COPY pyproject.toml ./ +RUN uv sync --no-dev + +COPY ./src ./src + +EXPOSE 8081 + +ENTRYPOINT ["uv", "run", "uvicorn", "portfoliomanager.main:application", "--host", "0.0.0.0", "--port", "8081", "--app-dir", "src"] \ No newline at end of file diff --git a/applications/portfoliomanager/pyproject.toml b/applications/portfoliomanager/pyproject.toml index d780991c9..ca75ff1e2 100644 --- a/applications/portfoliomanager/pyproject.toml +++ b/applications/portfoliomanager/pyproject.toml @@ -3,11 +3,8 @@ name = "portfoliomanager" version = "0.1.0" description = "Portfolio prediction and construction service" requires-python = "==3.12.10" -dependencies = ["internal"] - -[tool.uv] -package = true -src = ["src"] - -[tool.uv.sources] -internal = { workspace = true } +dependencies = [ + "fastapi>=0.116.1", + "uvicorn>=0.35.0", + "httpx>=0.27.0", +] diff --git a/applications/portfoliomanager/src/portfoliomanager/main.py b/applications/portfoliomanager/src/portfoliomanager/main.py index e69de29bb..4856c8b29 100644 --- a/applications/portfoliomanager/src/portfoliomanager/main.py +++ b/applications/portfoliomanager/src/portfoliomanager/main.py @@ -0,0 +1,38 @@ +import os +from typing import Any + +import httpx +from fastapi import FastAPI, HTTPException, Response, status + +app: FastAPI = FastAPI() + +DATAMANAGER_URL = os.getenv("DATAMANAGER_URL", "http://datamanager:8080") +HTTP_200_OK = 200 + + +@app.get("/health") +def health_check() -> Response: + return Response(status_code=status.HTTP_200_OK) + + +@app.get("/datamanager/health") +async def check_datamanager_health() -> dict[str, Any]: + """Check if datamanager service is healthy""" + try: + async with httpx.AsyncClient() as client: + response = await client.get( + f"{DATAMANAGER_URL}/portfolio-check", timeout=5.0 + ) + return { + "datamanager_status": "healthy" + if response.status_code == HTTP_200_OK + else "unhealthy", + "status_code": response.status_code, + } + except httpx.RequestError as e: + raise HTTPException( + status_code=503, detail=f"Cannot reach datamanager: {e!s}" + ) from e + + +application = app diff --git a/applications/stack.yml b/applications/stack.yml new file mode 100644 index 000000000..c6f8edb2f --- /dev/null +++ b/applications/stack.yml @@ -0,0 +1,72 @@ +version: '3.8' + +services: + datamanager: + image: pocketsizefund/datamanager:latest + ports: + - "8080:8080" + networks: + - app-network + deploy: + replicas: 2 + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + window: 120s + update_config: + parallelism: 1 + delay: 10s + failure_action: rollback + rollback_config: + parallelism: 1 + delay: 10s + placement: + constraints: [] + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + environment: + - PYTHONPATH=/app/src + + portfoliomanager: + image: pocketsizefund/portfoliomanager:latest + ports: + - "8081:8081" + networks: + - app-network + depends_on: + - datamanager + deploy: + replicas: 2 + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + window: 120s + update_config: + parallelism: 1 + delay: 10s + failure_action: rollback + rollback_config: + parallelism: 1 + delay: 10s + placement: + constraints: [] + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8081/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + environment: + - PYTHONPATH=/app/src + - DATAMANAGER_URL=http://datamanager:8080 + +networks: + app-network: + driver: overlay + attachable: true diff --git a/infrastructure/__main__.py b/infrastructure/__main__.py index 13c6ceb3c..d314bd1b3 100644 --- a/infrastructure/__main__.py +++ b/infrastructure/__main__.py @@ -7,6 +7,13 @@ blueprint_id = pulumi.Config().get("blueprintId") or "ubuntu_24_04" bundle_mgr = pulumi.Config().get("bundleIdMgr") or "medium_2_0" bundle_wkr = pulumi.Config().get("bundleIdWkr") or "small_2_0" +allowed_ssh_cidrs = pulumi.Config().get_object("allowedSshCidrs") or ["0.0.0.0/0"] +swarm_manager_allowed_cidrs = pulumi.Config().get_object( + "swarmManagerAllowedCidrs" +) or ["10.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12"] +swarm_cluster_allowed_cidrs = pulumi.Config().get_object( + "swarmClusterAllowedCidrs" +) or ["10.0.0.0/16"] ssh_key = tls.PrivateKey("swarm-key", algorithm="RSA", rsa_bits=4096) ls_key = aws.lightsail.KeyPair( @@ -68,16 +75,28 @@ def mk_instance(name: str, bundle_id: str): # noqa: ANN201 from_port=22, to_port=22, protocol="tcp", cidrs=["0.0.0.0/0"] ), aws.lightsail.InstancePublicPortsPortInfoArgs( - from_port=2377, to_port=2377, protocol="tcp", cidrs=["0.0.0.0/0"] + from_port=2377, + to_port=2377, + protocol="tcp", + cidrs=swarm_manager_allowed_cidrs, ), aws.lightsail.InstancePublicPortsPortInfoArgs( - from_port=7946, to_port=7946, protocol="tcp", cidrs=["0.0.0.0/0"] + from_port=7946, + to_port=7946, + protocol="tcp", + cidrs=swarm_cluster_allowed_cidrs, ), aws.lightsail.InstancePublicPortsPortInfoArgs( - from_port=7946, to_port=7946, protocol="udp", cidrs=["0.0.0.0/0"] + from_port=7946, + to_port=7946, + protocol="udp", + cidrs=swarm_cluster_allowed_cidrs, ), aws.lightsail.InstancePublicPortsPortInfoArgs( - from_port=4789, to_port=4789, protocol="udp", cidrs=["0.0.0.0/0"] + from_port=4789, + to_port=4789, + protocol="udp", + cidrs=swarm_cluster_allowed_cidrs, ), aws.lightsail.InstancePublicPortsPortInfoArgs( from_port=80, to_port=80, protocol="tcp", cidrs=["0.0.0.0/0"] diff --git a/infrastructure/stack.yml b/infrastructure/stack.yml index 72034a416..3d1a5bff5 100644 --- a/infrastructure/stack.yml +++ b/infrastructure/stack.yml @@ -14,6 +14,10 @@ volumes: prom_data: grafana_data: +secrets: + GRAFANA_ADMIN_PASSWORD: + external: true + configs: prometheus.yml: name: prometheus.yml @@ -120,8 +124,9 @@ services: image: grafana/grafana:10.4.2 environment: GF_SECURITY_ADMIN_USER: admin - # TODO: Change this to a random password - GF_SECURITY_ADMIN_PASSWORD: admin123 + GF_SECURITY_ADMIN_PASSWORD_FILE: /run/secrets/GRAFANA_ADMIN_PASSWORD + secrets: + - GRAFANA_ADMIN_PASSWORD volumes: - grafana_data:/var/lib/grafana deploy: diff --git a/infrastructure/uv.lock b/infrastructure/uv.lock new file mode 100644 index 000000000..6692f07a1 --- /dev/null +++ b/infrastructure/uv.lock @@ -0,0 +1,201 @@ +version = 1 +revision = 2 +requires-python = "==3.12.10" + +[[package]] +name = "arpeggio" +version = "2.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/12/c4/516bb54456f85ad1947702ea4cef543a59de66d31a9887dbc3d9df36e3e1/Arpeggio-2.0.2.tar.gz", hash = "sha256:c790b2b06e226d2dd468e4fbfb5b7f506cec66416031fde1441cf1de2a0ba700", size = 766643, upload-time = "2023-07-09T12:30:04.737Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/4f/d28bf30a19d4649b40b501d531b44e73afada99044df100380fd9567e92f/Arpeggio-2.0.2-py2.py3-none-any.whl", hash = "sha256:f7c8ae4f4056a89e020c24c7202ac8df3e2bc84e416746f20b0da35bb1de0250", size = 55287, upload-time = "2023-07-09T12:30:01.87Z" }, +] + +[[package]] +name = "attrs" +version = "25.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, +] + +[[package]] +name = "debugpy" +version = "1.8.16" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/d4/722d0bcc7986172ac2ef3c979ad56a1030e3afd44ced136d45f8142b1f4a/debugpy-1.8.16.tar.gz", hash = "sha256:31e69a1feb1cf6b51efbed3f6c9b0ef03bc46ff050679c4be7ea6d2e23540870", size = 1643809, upload-time = "2025-08-06T18:00:02.647Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/fb/0387c0e108d842c902801bc65ccc53e5b91d8c169702a9bbf4f7efcedf0c/debugpy-1.8.16-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:b202e2843e32e80b3b584bcebfe0e65e0392920dc70df11b2bfe1afcb7a085e4", size = 2511822, upload-time = "2025-08-06T18:00:18.526Z" }, + { url = "https://files.pythonhosted.org/packages/37/44/19e02745cae22bf96440141f94e15a69a1afaa3a64ddfc38004668fcdebf/debugpy-1.8.16-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64473c4a306ba11a99fe0bb14622ba4fbd943eb004847d9b69b107bde45aa9ea", size = 4230135, upload-time = "2025-08-06T18:00:19.997Z" }, + { url = "https://files.pythonhosted.org/packages/f3/0b/19b1ba5ee4412f303475a2c7ad5858efb99c90eae5ec627aa6275c439957/debugpy-1.8.16-cp312-cp312-win32.whl", hash = "sha256:833a61ed446426e38b0dd8be3e9d45ae285d424f5bf6cd5b2b559c8f12305508", size = 5281271, upload-time = "2025-08-06T18:00:21.281Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e0/bc62e2dc141de53bd03e2c7cb9d7011de2e65e8bdcdaa26703e4d28656ba/debugpy-1.8.16-cp312-cp312-win_amd64.whl", hash = "sha256:75f204684581e9ef3dc2f67687c3c8c183fde2d6675ab131d94084baf8084121", size = 5323149, upload-time = "2025-08-06T18:00:23.033Z" }, + { url = "https://files.pythonhosted.org/packages/52/57/ecc9ae29fa5b2d90107cd1d9bf8ed19aacb74b2264d986ae9d44fe9bdf87/debugpy-1.8.16-py2.py3-none-any.whl", hash = "sha256:19c9521962475b87da6f673514f7fd610328757ec993bf7ec0d8c96f9a325f9e", size = 5287700, upload-time = "2025-08-06T18:00:42.333Z" }, +] + +[[package]] +name = "dill" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", size = 186976, upload-time = "2025-04-16T00:41:48.867Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668, upload-time = "2025-04-16T00:41:47.671Z" }, +] + +[[package]] +name = "grpcio" +version = "1.74.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/38/b4/35feb8f7cab7239c5b94bd2db71abb3d6adb5f335ad8f131abb6060840b6/grpcio-1.74.0.tar.gz", hash = "sha256:80d1f4fbb35b0742d3e3d3bb654b7381cd5f015f8497279a1e9c21ba623e01b1", size = 12756048, upload-time = "2025-07-24T18:54:23.039Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4c/5d/e504d5d5c4469823504f65687d6c8fb97b7f7bf0b34873b7598f1df24630/grpcio-1.74.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8533e6e9c5bd630ca98062e3a1326249e6ada07d05acf191a77bc33f8948f3d8", size = 5445551, upload-time = "2025-07-24T18:53:23.641Z" }, + { url = "https://files.pythonhosted.org/packages/43/01/730e37056f96f2f6ce9f17999af1556df62ee8dab7fa48bceeaab5fd3008/grpcio-1.74.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:2918948864fec2a11721d91568effffbe0a02b23ecd57f281391d986847982f6", size = 10979810, upload-time = "2025-07-24T18:53:25.349Z" }, + { url = "https://files.pythonhosted.org/packages/79/3d/09fd100473ea5c47083889ca47ffd356576173ec134312f6aa0e13111dee/grpcio-1.74.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:60d2d48b0580e70d2e1954d0d19fa3c2e60dd7cbed826aca104fff518310d1c5", size = 5941946, upload-time = "2025-07-24T18:53:27.387Z" }, + { url = "https://files.pythonhosted.org/packages/8a/99/12d2cca0a63c874c6d3d195629dcd85cdf5d6f98a30d8db44271f8a97b93/grpcio-1.74.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3601274bc0523f6dc07666c0e01682c94472402ac2fd1226fd96e079863bfa49", size = 6621763, upload-time = "2025-07-24T18:53:29.193Z" }, + { url = "https://files.pythonhosted.org/packages/9d/2c/930b0e7a2f1029bbc193443c7bc4dc2a46fedb0203c8793dcd97081f1520/grpcio-1.74.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:176d60a5168d7948539def20b2a3adcce67d72454d9ae05969a2e73f3a0feee7", size = 6180664, upload-time = "2025-07-24T18:53:30.823Z" }, + { url = "https://files.pythonhosted.org/packages/db/d5/ff8a2442180ad0867717e670f5ec42bfd8d38b92158ad6bcd864e6d4b1ed/grpcio-1.74.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e759f9e8bc908aaae0412642afe5416c9f983a80499448fcc7fab8692ae044c3", size = 6301083, upload-time = "2025-07-24T18:53:32.454Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ba/b361d390451a37ca118e4ec7dccec690422e05bc85fba2ec72b06cefec9f/grpcio-1.74.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9e7c4389771855a92934b2846bd807fc25a3dfa820fd912fe6bd8136026b2707", size = 6994132, upload-time = "2025-07-24T18:53:34.506Z" }, + { url = "https://files.pythonhosted.org/packages/3b/0c/3a5fa47d2437a44ced74141795ac0251bbddeae74bf81df3447edd767d27/grpcio-1.74.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cce634b10aeab37010449124814b05a62fb5f18928ca878f1bf4750d1f0c815b", size = 6489616, upload-time = "2025-07-24T18:53:36.217Z" }, + { url = "https://files.pythonhosted.org/packages/ae/95/ab64703b436d99dc5217228babc76047d60e9ad14df129e307b5fec81fd0/grpcio-1.74.0-cp312-cp312-win32.whl", hash = "sha256:885912559974df35d92219e2dc98f51a16a48395f37b92865ad45186f294096c", size = 3807083, upload-time = "2025-07-24T18:53:37.911Z" }, + { url = "https://files.pythonhosted.org/packages/84/59/900aa2445891fc47a33f7d2f76e00ca5d6ae6584b20d19af9c06fa09bf9a/grpcio-1.74.0-cp312-cp312-win_amd64.whl", hash = "sha256:42f8fee287427b94be63d916c90399ed310ed10aadbf9e2e5538b3e497d269bc", size = 4490123, upload-time = "2025-07-24T18:53:39.528Z" }, +] + +[[package]] +name = "infrastructure" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "pulumi" }, + { name = "pulumi-aws" }, + { name = "pulumi-command" }, + { name = "pulumi-tls" }, +] + +[package.metadata] +requires-dist = [ + { name = "pulumi", specifier = ">=3.189.0" }, + { name = "pulumi-aws", specifier = ">=7.4.0" }, + { name = "pulumi-command", specifier = ">=1.1.0" }, + { name = "pulumi-tls", specifier = ">=5.2.1" }, +] + +[[package]] +name = "parver" +version = "0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "arpeggio" }, + { name = "attrs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cc/e5/1c774688a90f0b76e872e30f6f1ba3f5e14056cd0d96a684047d4a986226/parver-0.5.tar.gz", hash = "sha256:b9fde1e6bb9ce9f07e08e9c4bea8d8825c5e78e18a0052d02e02bf9517eb4777", size = 26908, upload-time = "2023-10-03T21:06:54.506Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/4c/f98024021bef4d44dce3613feebd702c7ad8883f777ff8488384c59e9774/parver-0.5-py3-none-any.whl", hash = "sha256:2281b187276c8e8e3c15634f62287b2fb6fe0efe3010f739a6bd1e45fa2bf2b2", size = 15172, upload-time = "2023-10-03T21:06:52.796Z" }, +] + +[[package]] +name = "pip" +version = "25.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/16/650289cd3f43d5a2fadfd98c68bd1e1e7f2550a1a5326768cddfbcedb2c5/pip-25.2.tar.gz", hash = "sha256:578283f006390f85bb6282dffb876454593d637f5d1be494b5202ce4877e71f2", size = 1840021, upload-time = "2025-07-30T21:50:15.401Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa/pip-25.2-py3-none-any.whl", hash = "sha256:6d67a2b4e7f14d8b31b8b52648866fa717f45a1eb70e83002f4331d07e953717", size = 1752557, upload-time = "2025-07-30T21:50:13.323Z" }, +] + +[[package]] +name = "protobuf" +version = "5.29.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/29/d09e70352e4e88c9c7a198d5645d7277811448d76c23b00345670f7c8a38/protobuf-5.29.5.tar.gz", hash = "sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84", size = 425226, upload-time = "2025-05-28T23:51:59.82Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/11/6e40e9fc5bba02988a214c07cf324595789ca7820160bfd1f8be96e48539/protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079", size = 422963, upload-time = "2025-05-28T23:51:41.204Z" }, + { url = "https://files.pythonhosted.org/packages/81/7f/73cefb093e1a2a7c3ffd839e6f9fcafb7a427d300c7f8aef9c64405d8ac6/protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc", size = 434818, upload-time = "2025-05-28T23:51:44.297Z" }, + { url = "https://files.pythonhosted.org/packages/dd/73/10e1661c21f139f2c6ad9b23040ff36fee624310dc28fba20d33fdae124c/protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671", size = 418091, upload-time = "2025-05-28T23:51:45.907Z" }, + { url = "https://files.pythonhosted.org/packages/6c/04/98f6f8cf5b07ab1294c13f34b4e69b3722bb609c5b701d6c169828f9f8aa/protobuf-5.29.5-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015", size = 319824, upload-time = "2025-05-28T23:51:47.545Z" }, + { url = "https://files.pythonhosted.org/packages/85/e4/07c80521879c2d15f321465ac24c70efe2381378c00bf5e56a0f4fbac8cd/protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61", size = 319942, upload-time = "2025-05-28T23:51:49.11Z" }, + { url = "https://files.pythonhosted.org/packages/7e/cc/7e77861000a0691aeea8f4566e5d3aa716f2b1dece4a24439437e41d3d25/protobuf-5.29.5-py3-none-any.whl", hash = "sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5", size = 172823, upload-time = "2025-05-28T23:51:58.157Z" }, +] + +[[package]] +name = "pulumi" +version = "3.190.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "debugpy" }, + { name = "dill" }, + { name = "grpcio" }, + { name = "pip" }, + { name = "protobuf" }, + { name = "pyyaml" }, + { name = "semver" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/c7/25246c8bd05b72986f42d9c2adf561162dbade160a2b52adfa7873b30dc0/pulumi-3.190.0-py3-none-any.whl", hash = "sha256:aff2de5098e7ab24bee0e22b2fde81e0775b65ca03e5f13e9fe9c6cc8a420b63", size = 375069, upload-time = "2025-08-15T17:57:34.315Z" }, +] + +[[package]] +name = "pulumi-aws" +version = "7.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parver" }, + { name = "pulumi" }, + { name = "semver" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d4/20/315ba5d2b9f909dbb5ade876bfdeabad79f1234034afd094be804dd7efdc/pulumi_aws-7.4.0.tar.gz", hash = "sha256:a6d75b04c2a92e33ef2ec22f17ca6ed69040cbbbb655374010b1674ce39382a6", size = 8048045, upload-time = "2025-08-13T18:07:29.381Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/ba/ba48586cd1b8da9c6ea605bcaeb2d3812fce8ef37391829ea60a77dcd585/pulumi_aws-7.4.0-py3-none-any.whl", hash = "sha256:f478977de19567f96851c7c9ac2555f90f0afdaa2098550d810f303f5f96570e", size = 10933831, upload-time = "2025-08-13T18:07:25.769Z" }, +] + +[[package]] +name = "pulumi-command" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parver" }, + { name = "pulumi" }, + { name = "semver" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/b4/03d37a61e49b636b7cd5ba72a28996f07a18d815e6ba2343f6071b77fc51/pulumi_command-1.1.0.tar.gz", hash = "sha256:509b2709938aacfb13717b7b537d728375cd90b409093bf24dacab17d9294a4a", size = 33072, upload-time = "2025-05-27T18:25:11.671Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/f4/c89295ca63e2555cda4b4e16069200cf04262ac87ae263c48562f8297cc8/pulumi_command-1.1.0-py3-none-any.whl", hash = "sha256:d6a62444a1a9a26ded354b668a9cf88c0becd4faacabe4adafbc8dbb65af96c4", size = 36859, upload-time = "2025-05-27T18:25:10.401Z" }, +] + +[[package]] +name = "pulumi-tls" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parver" }, + { name = "pulumi" }, + { name = "semver" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/3a/fca66fb609fa557da5bc7f504c607a4e2be624367e6f7cc6de66aee713f8/pulumi_tls-5.2.1.tar.gz", hash = "sha256:c4eae9d74b40fcc4a50a5b572e53b8564d5cda8172484f4abf273ede7e97147e", size = 26547, upload-time = "2025-07-24T23:30:36.781Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/12/f5035bbfe624279a4838ec824ec8a6d34e9351f6780def8c2ab0ce965a0c/pulumi_tls-5.2.1-py3-none-any.whl", hash = "sha256:021752347ee0381be3183969195d3dbea39696d3d6bad1c19f790b976e2db622", size = 34982, upload-time = "2025-07-24T23:30:35.466Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, +] + +[[package]] +name = "semver" +version = "3.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/d1/d3159231aec234a59dd7d601e9dd9fe96f3afff15efd33c1070019b26132/semver-3.0.4.tar.gz", hash = "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602", size = 269730, upload-time = "2025-01-24T13:19:27.617Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746", size = 17912, upload-time = "2025-01-24T13:19:24.949Z" }, +] diff --git a/libraries/python/src/internal/mhsa_network.py b/libraries/python/src/internal/mhsa_network.py index 89e50b97b..a4b1ce800 100644 --- a/libraries/python/src/internal/mhsa_network.py +++ b/libraries/python/src/internal/mhsa_network.py @@ -36,7 +36,7 @@ def forward(self, inputs: Tensor) -> tuple[Tensor, Tensor]: shape = (batch_size, sequence_length, self.heads_count, self.heads_dimension) - # shape: (batch, heads_count, sequence_length, head_dimension) # noqa: ERA001 + # shape: (batch, heads_count, sequence_length, head_dimension) query_weights = query_weights.view(shape).transpose(1, 2) key_weights = key_weights.view(shape).transpose(1, 2) value_weights = value_weights.view(shape).transpose(1, 2) diff --git a/libraries/python/src/internal/tft_model.py b/libraries/python/src/internal/tft_model.py index 7d30617c8..b891c67f4 100644 --- a/libraries/python/src/internal/tft_model.py +++ b/libraries/python/src/internal/tft_model.py @@ -121,7 +121,7 @@ def forward(self, inputs: dict[str, Tensor]) -> dict[str, Tensor]: ) static_categorical_features = inputs["static_categorical_features"] - # TODO: static_continuous_features = Tensor.zeros(self.batch_size, 1, 0) # noqa: E501, FIX002 + # TODO: static_continuous_features = Tensor.zeros(self.batch_size, 1, 0) static_context = None # NOTE: maybe remove @@ -165,8 +165,8 @@ def forward(self, inputs: dict[str, Tensor]) -> dict[str, Tensor]: attended_output, _ = self.self_attention.forward( Tensor(sequence + expanded_static_context), - # sequence, # NOTE: unused (?) # noqa: ERA001 - # sequence, # NOTE: unused (?) # noqa: ERA001 + # sequence, # NOTE: unused (?) + # sequence, # NOTE: unused (?) ) decoder_attended = attended_output[:, -self.output_length :, :] diff --git a/maskfile.md b/maskfile.md new file mode 100644 index 000000000..68e48d482 --- /dev/null +++ b/maskfile.md @@ -0,0 +1,960 @@ +# PocketSizeFund Task Manager + +## setup +> Initial system setup and prerequisite configuration +```bash +set -euo pipefail + +echo "๐Ÿš€ Setting up PocketSizeFund development environment" +echo "==================================================" + +# Check prerequisites +echo "๐Ÿ” Checking prerequisites..." +missing_deps=() + +if ! command -v docker >/dev/null 2>&1; then + missing_deps+=("Docker") +fi + +if ! command -v pulumi >/dev/null 2>&1; then + missing_deps+=("Pulumi CLI") +fi + +if [[ ${#missing_deps[@]} -gt 0 ]]; then + echo "โŒ Missing prerequisites: ${missing_deps[*]}" + echo "" + echo "Please install the following:" + for dep in "${missing_deps[@]}"; do + case $dep in + "Docker") + echo " - Docker: https://docs.docker.com/get-docker/" + ;; + "Pulumi CLI") + echo " - Pulumi CLI: https://www.pulumi.com/docs/get-started/install/" + ;; + esac + done + exit 1 +fi + +# Check Docker login +echo "๐Ÿณ Checking DockerHub authentication..." +if ! docker info >/dev/null 2>&1; then + echo "โŒ Docker daemon not running" + exit 1 +fi + +if ! docker system info --format '{{.Username}}' 2>/dev/null | grep -q .; then + echo "โš ๏ธ Not logged into DockerHub. Run 'docker login' first" + exit 1 +fi + +# Set up environment variable +echo "๐ŸŒ Setting up environment..." +if [[ -z "${ACME_EMAIL:-}" ]]; then + echo "โš ๏ธ ACME_EMAIL environment variable not set" + echo " Add this to your shell profile: export ACME_EMAIL=\"your-email@example.com\"" + read -p "Enter your email for ACME certificates: " email + if [[ -n "$email" ]]; then + export ACME_EMAIL="$email" + echo "โœ… ACME_EMAIL set to: $ACME_EMAIL" + echo " Add 'export ACME_EMAIL=\"$ACME_EMAIL\"' to your shell profile" + fi +else + echo "โœ… ACME_EMAIL: $ACME_EMAIL" +fi + +echo "โœ… Prerequisites check completed" +echo "" +echo "๐Ÿ“‹ Next steps:" +echo " mask secrets create # Set up Docker secrets" +echo " mask infrastructure base up # Deploy infrastructure" +echo " mask development python install # Install Python dependencies" +echo "" +echo "๐Ÿ“– Service URLs (after deployment):" +echo " - DataManager: http://[manager-ip]:8080" +echo " - PortfolioManager: http://[manager-ip]:8081" +echo " - Grafana: https://grafana.example.com" +echo " - Portainer: https://[manager-ip]:9443" +``` + +## dev +> Full development cycle (install, format, lint, test) +```bash +set -euo pipefail + +echo "๐Ÿ”„ Running full development workflow" +echo "===================================" + +echo "1๏ธโƒฃ Installing dependencies..." +mask development python install + +echo "" +echo "2๏ธโƒฃ Running quality checks..." +mask development quality + +echo "" +echo "3๏ธโƒฃ Running tests..." +mask development python test + +echo "" +echo "โœ… Development workflow completed successfully!" +``` + +## ci +> Continuous integration workflow +```bash +set -euo pipefail + +echo "๐Ÿค– Running CI workflow" +echo "=====================" + +echo "1๏ธโƒฃ Quality checks..." +mask development quality + +echo "" +echo "2๏ธโƒฃ Testing..." +mask development python test + +echo "" +echo "3๏ธโƒฃ Building applications..." +mask infrastructure applications build + +echo "" +echo "โœ… CI workflow completed successfully!" +``` + +## infrastructure +> Manage infrastructure deployments +### base +> Base infrastructure deployment +#### up +> Deploy complete infrastructure stack (Pulumi + Docker) to local and production environments. Creates cloud resources, SSH configuration, Docker contexts, and deploys both infrastructure and application services. +```bash +set -euo pipefail + +echo "๐Ÿš€ Starting infrastructure deployment..." + +cd infrastructure + +# Deploy infrastructure with Pulumi +echo "๐Ÿ“ก Deploying infrastructure with Pulumi..." +if ! pulumi up --yes; then + echo "โŒ Pulumi deployment failed" + exit 1 +fi + +echo "๐Ÿ“‹ Getting infrastructure outputs..." +MANAGER_IP=$(pulumi stack output managerIp | tr -d '\r\n') +if [[ -z "$MANAGER_IP" ]]; then + echo "โŒ Failed to get manager IP from Pulumi" + exit 1 +fi + +echo "๐Ÿ”‘ Setting up SSH configuration..." +pulumi stack output --show-secrets sshPrivateKeyPem | tr -d '\r' > swarm.pem +chmod 600 swarm.pem + +# Verify SSH key format +if ! ssh-keygen -l -f swarm.pem >/dev/null 2>&1; then + echo "โŒ Invalid SSH key format" + exit 1 +fi + +# Setup SSH config +SSH_CONFIG="$HOME/.ssh/config" +mkdir -p "$(dirname "$SSH_CONFIG")" + +# Remove existing pocketsizefund-production host config +if [[ -f "$SSH_CONFIG" ]]; then + sed -i.bak '/^Host pocketsizefund-production$/,/^Host /{ /^Host pocketsizefund-production$/d; /^Host /!d; }' "$SSH_CONFIG" || true + sed -i.bak '${ /^Host /!d; }' "$SSH_CONFIG" || true +fi + +# Add new SSH config +cat >> "$SSH_CONFIG" << EOF + +Host pocketsizefund-production + HostName $MANAGER_IP + User ubuntu + IdentityFile $PWD/swarm.pem + IdentitiesOnly yes + StrictHostKeyChecking accept-new + ServerAliveInterval 60 + ServerAliveCountMax 3 +EOF + +echo "๐Ÿ” Updating SSH known hosts..." +# Remove old host key and add new one +ssh-keygen -R "$MANAGER_IP" >/dev/null 2>&1 || true +ssh-keyscan -H "$MANAGER_IP" >> "$HOME/.ssh/known_hosts" 2>/dev/null + +# Test SSH connection and Docker +echo "๐Ÿงช Testing SSH connection..." +MAX_RETRIES=5 +RETRY_COUNT=0 + +while [[ $RETRY_COUNT -lt $MAX_RETRIES ]]; do + if ssh -o ConnectTimeout=10 pocketsizefund-production 'docker info -f "{{.ServerVersion}} {{.Swarm.LocalNodeState}}"' 2>/dev/null; then + echo "โœ… SSH connection successful" + break + else + ((RETRY_COUNT++)) + echo "โณ SSH connection attempt $RETRY_COUNT/$MAX_RETRIES failed, retrying in 5 seconds..." + sleep 5 + fi +done + +if [[ $RETRY_COUNT -eq $MAX_RETRIES ]]; then + echo "โŒ Failed to establish SSH connection after $MAX_RETRIES attempts" + exit 1 +fi + +echo "๐Ÿณ Setting up Docker contexts..." + +# Remove existing contexts safely +for context in pocketsizefund-production pocketsizefund-local; do + if docker context ls --format '{{.Name}}' | grep -q "^${context}$"; then + docker context use default >/dev/null 2>&1 || true + docker context rm -f "$context" >/dev/null 2>&1 || true + fi +done + +# Create Docker contexts +if ! docker context create pocketsizefund-production --docker "host=ssh://pocketsizefund-production"; then + echo "โŒ Failed to create production Docker context" + exit 1 +fi + +if ! docker context create pocketsizefund-local --docker "host=unix:///var/run/docker.sock"; then + echo "โŒ Failed to create local Docker context" + exit 1 +fi + +# Initialize local swarm if needed +echo "๐Ÿ”„ Ensuring local Docker swarm is initialized..." +docker context use pocketsizefund-local +if ! docker info --format '{{.Swarm.LocalNodeState}}' | grep -q active; then + docker swarm init --advertise-addr 127.0.0.1 >/dev/null 2>&1 || true +fi + +# Deploy infrastructure stack to production +echo "๐Ÿš€ Deploying infrastructure stack to production..." +docker context use pocketsizefund-production +if ! docker stack deploy -c stack.yml infrastructure --with-registry-auth; then + echo "โŒ Failed to deploy infrastructure stack to production" + exit 1 +fi + +# Deploy infrastructure stack to local +echo "๐Ÿ  Deploying infrastructure stack to local..." +docker context use pocketsizefund-local +if ! docker stack deploy -c stack.yml infrastructure --with-registry-auth; then + echo "โŒ Failed to deploy infrastructure stack to local" + exit 1 +fi + +# Deploy application services +echo "๐Ÿ“ฑ Deploying application services..." +cd ../applications +# Deploy to production +echo "๐ŸŒ Deploying applications to production..." +docker context use pocketsizefund-production +if ! docker stack deploy -c stack.yml applications --with-registry-auth; then + echo "โŒ Failed to deploy applications to production" + exit 1 +fi + +# Deploy to local +echo "๐Ÿ  Deploying applications to local..." +docker context use pocketsizefund-local +if ! docker stack deploy -c stack.yml applications --with-registry-auth; then + echo "โŒ Failed to deploy applications to local" + exit 1 +fi + +# Show cluster status +echo "๐Ÿ“Š Cluster status:" +docker context use pocketsizefund-production +echo "Production cluster:" +docker node ls 2>/dev/null || echo " Unable to list production nodes" + +docker context use pocketsizefund-local +echo "Local cluster:" +docker node ls 2>/dev/null || echo " Unable to list local nodes" + +echo "โœ… Infrastructure deployment completed successfully!" +echo "" +echo "Next steps:" +echo " mask test all # Test complete deployment" +echo " mask docker stack ps # Check stack status" +echo " mask docker context production # Switch to production context" +``` + +#### down + +> Completely tear down infrastructure and services. Removes Docker stacks, destroys Pulumi cloud resources, cleans up SSH configuration and Docker contexts. + +```bash +set -euo pipefail + +echo "๐Ÿ›‘ Taking down infrastructure..." + +cd infrastructure + +echo "๐Ÿ“ฑ Removing application stacks..." +for context in pocketsizefund-production pocketsizefund-local; do + echo " Removing from $context..." + if docker context ls --format '{{.Name}}' | grep -q "^${context}$"; then + docker context use "$context" + docker stack rm applications 2>/dev/null || echo " applications not found in $context" + docker stack rm infrastructure 2>/dev/null || echo " infrastructure stack not found in $context" + else + echo " Context $context not found" + fi +done + +# Wait for services to be removed +echo "โณ Waiting for services to stop..." +sleep 10 + +# Destroy Pulumi infrastructure +echo "โ˜๏ธ Destroying cloud infrastructure..." +if ! pulumi destroy --yes; then + echo "โŒ Pulumi destroy failed" + exit 1 +fi + +# Clean up SSH config +echo "๐Ÿงน Cleaning up SSH configuration..." +SSH_CONFIG="$HOME/.ssh/config" +if [[ -f "$SSH_CONFIG" ]]; then + sed -i.bak '/^Host pocketsizefund-production$/,/^Host /{ /^Host pocketsizefund-production$/d; /^Host /!d; }' "$SSH_CONFIG" || true + sed -i.bak '${ /^Host /!d; }' "$SSH_CONFIG" || true +fi + +# Remove SSH key +rm -f swarm.pem + +# Remove Docker contexts +echo "๐Ÿณ Removing Docker contexts..." +docker context use default >/dev/null 2>&1 || true +for context in pocketsizefund-production pocketsizefund-local; do + docker context rm -f "$context" >/dev/null 2>&1 || true +done + +echo "โœ… Infrastructure taken down successfully!" +echo "" +echo "๐Ÿ“ Summary: All cloud resources destroyed, contexts removed, SSH config cleaned" +``` + +### applications +> Build and deploy application containers +#### build +> Build and push application Docker images to DockerHub +```bash +set -euo pipefail + +echo "๐Ÿ—๏ธ Building and pushing application images..." + +for app_dir in applications/*/; do + app_name=$(basename "$app_dir") + if [[ -f "$app_dir/Dockerfile" ]]; then + echo "๐Ÿ“ฆ Building $app_name..." + cd "$app_dir" + + # Get version from uv + version=$(uv version --short 2>/dev/null || echo "latest") + + # Build with both latest and version tags + docker build -t "pocketsizefund/$app_name:latest" -t "pocketsizefund/$app_name:$version" . + + # Push both tags + docker push "pocketsizefund/$app_name:latest" + docker push "pocketsizefund/$app_name:$version" + + cd .. + echo "โœ… $app_name built and pushed" + else + echo "โš ๏ธ Skipping $app_name (no Dockerfile found)" + fi +done + +echo "๐ŸŽ‰ All application images built and pushed successfully!" +``` + +#### deploy +> Deploy applications to both local and production Docker swarm +```bash +set -euo pipefail + +echo "๐Ÿš€ Deploying applications..." + +# Deploy to production context +if docker context ls --format '{{.Name}}' | grep -q "^pocketsizefund-production$"; then + echo "๐ŸŒ Deploying to production..." + docker context use pocketsizefund-production + docker stack deploy -c applications/stack.yml applications --with-registry-auth +else + echo "โš ๏ธ Production context not found, skipping production deployment" +fi + +# Deploy to local context +if docker context ls --format '{{.Name}}' | grep -q "^pocketsizefund-local$"; then + echo "๐Ÿ  Deploying to local..." + docker context use pocketsizefund-local + docker stack deploy -c applications/stack.yml applications --with-registry-auth +else + echo "โš ๏ธ Local context not found, skipping local deployment" +fi + +# Reset to default context +docker context use default >/dev/null 2>&1 || true + +echo "โœ… Application deployment completed!" +echo "" +echo "Next steps:" +echo " mask test endpoints # Test service endpoints" +echo " mask docker services ls # Check service status" +``` + +## test +> Test application endpoints and service health across environments + +### endpoints +> Test HTTP endpoints for DataManager and PortfolioManager services +```bash +set -euo pipefail + +echo "๐Ÿงช Testing Application Endpoints" +echo "=================================" + +# Function to test HTTP endpoints +test_endpoint() { + local name="$1" + local url="$2" + local context="$3" + + printf "%-25s %-15s " "$name" "[$context]" + + if timeout 10 curl -sf "$url" >/dev/null 2>&1; then + echo "โœ… OK" + return 0 + elif timeout 10 curl -s "$url" >/dev/null 2>&1; then + echo "๐Ÿ”ถ RESPONDING (non-200)" + return 1 + else + echo "โŒ FAILED" + return 1 + fi +} + +# Get production manager IP +cd infrastructure +MANAGER_IP="" +if pulumi stack --show-name 2>/dev/null; then + MANAGER_IP=$(pulumi stack output managerIp 2>/dev/null || echo "") +fi +cd .. + +echo "๐Ÿ  Local endpoints:" +test_endpoint "DataManager" "http://localhost:8080/health" "local" +test_endpoint "DataManager (root)" "http://localhost:8080/" "local" +test_endpoint "PortfolioManager" "http://localhost:8081/health" "local" +test_endpoint "PortfolioManager (root)" "http://localhost:8081/" "local" + +# Production tests (if manager IP available) +if [[ -n "$MANAGER_IP" ]]; then + echo "" + echo "๐ŸŒ Production endpoints (IP: $MANAGER_IP):" + test_endpoint "DataManager" "http://$MANAGER_IP:8080/health" "production" + test_endpoint "DataManager (root)" "http://$MANAGER_IP:8080/" "production" + test_endpoint "PortfolioManager" "http://$MANAGER_IP:8081/health" "production" + test_endpoint "PortfolioManager (root)" "http://$MANAGER_IP:8081/" "production" +else + echo "" + echo "โš ๏ธ Production manager IP not available - skipping production tests" +fi + +docker context use default >/dev/null 2>&1 || true +echo "โœ… Endpoint testing completed" +``` + +### health +> Check Docker service health across all contexts +```bash +set -euo pipefail + +test_service_health() { + local context="$1" + echo "๐Ÿ” Docker Services in $context:" + + if docker context ls --format '{{.Name}}' | grep -q "^${context}$"; then + docker context use "$context" >/dev/null 2>&1 + + if docker service ls --format "table {{.Name}}\t{{.Replicas}}\t{{.Image}}" 2>/dev/null; then + echo "โœ… Services listed successfully" + else + echo " No services found or connection error" + fi + else + echo " Context $context not available" + fi + echo "" +} + +echo "๐Ÿ“Š Service Health Check" +echo "======================" +test_service_health "pocketsizefund-local" +test_service_health "pocketsizefund-production" + +docker context use default >/dev/null 2>&1 || true +``` + +### all +> Run complete test suite (endpoints + health checks) +```bash +set -euo pipefail + +echo "๐Ÿง  Running complete test suite..." +echo "====================================" + +mask test endpoints +echo "" +mask test health + +echo "๐ŸŽ‰ Complete test suite finished" +``` + +## docker +> Docker context and service management commands + +### context +> Switch Docker context between local and production environments +#### local +> Switch to local Docker swarm context +```bash +docker context use pocketsizefund-local +echo "โœ… Switched to local context" +docker context ls | grep "\*" +``` + +#### production +> Switch to production Docker swarm context +```bash +docker context use pocketsizefund-production +echo "โœ… Switched to production context" +docker context ls | grep "\*" +``` + +#### default +> Switch back to default Docker context +```bash +docker context use default +echo "โœ… Switched to default context" +``` + +### services +> Docker swarm service management +#### ls +> List all Docker services with health status +```bash +echo "๐Ÿ“Š Docker Services Status:" +docker service ls +echo "" +echo "๐Ÿ“‹ Service Health Details:" +docker service ls --format "table {{.Name}}\t{{.Replicas}}\t{{.Image}}\t{{.Ports}}" | \ + while IFS=$'\t' read -r name replicas image ports; do + if [[ "$name" != "NAME" ]]; then + printf "%-30s %s\n" "$name" "$replicas" + fi + done +``` + +#### logs +> View logs for a specific service (interactive selection) +```bash +echo "๐Ÿ“‹ Available services:" +services=($(docker service ls --format '{{.Name}}')) + +if [[ ${#services[@]} -eq 0 ]]; then + echo "โŒ No services found" + exit 1 +fi + +echo "Select a service:" +select service in "${services[@]}"; do + if [[ -n "$service" ]]; then + echo "๐Ÿ“œ Showing logs for $service (press Ctrl+C to exit):" + docker service logs -f "$service" + break + else + echo "Invalid selection. Please try again." + fi +done +``` + +#### inspect +> Inspect service configuration and status +```bash +echo "๐Ÿ“‹ Available services:" +services=($(docker service ls --format '{{.Name}}')) + +if [[ ${#services[@]} -eq 0 ]]; then + echo "โŒ No services found" + exit 1 +fi + +echo "Select a service to inspect:" +select service in "${services[@]}"; do + if [[ -n "$service" ]]; then + echo "๐Ÿ” Inspecting $service:" + echo "--- Service Tasks ---" + docker service ps "$service" + echo "" + echo "--- Service Details ---" + docker service inspect "$service" --pretty + break + else + echo "Invalid selection. Please try again." + fi +done +``` + +### stack +> Docker stack operations for infrastructure and applications +#### ls +> List all deployed stacks +```bash +echo "๐Ÿ“š Deployed Docker Stacks:" +docker stack ls +``` + +#### ps +> Show tasks for infrastructure and application stacks +```bash +echo "๐Ÿ—๏ธ Infrastructure Stack:" +docker stack ps infrastructure 2>/dev/null || echo "Infrastructure stack not deployed" +echo "" +echo "๐Ÿ“ฑ Applications Stack:" +docker stack ps applications 2>/dev/null || echo "Applications stack not deployed" +``` + +#### rm +> Remove infrastructure and application stacks +```bash +echo "๐Ÿ›‘ Removing Docker stacks..." +docker stack rm applications 2>/dev/null && echo "โœ… Applications stack removed" || echo "โš ๏ธ Applications stack not found" +docker stack rm infrastructure 2>/dev/null && echo "โœ… Infrastructure stack removed" || echo "โš ๏ธ Infrastructure stack not found" +echo "๐Ÿงน Waiting for cleanup..." +sleep 5 +echo "โœ… Stack removal completed" +``` + +## status +> Show comprehensive system status across all environments +```bash +set -euo pipefail + +echo "๐Ÿ“Š PocketSizeFund System Status" +echo "===============================" +echo "" + +# Docker contexts +echo "๐Ÿณ Docker Contexts:" +docker context ls +echo "" + +# Pulumi stack info +echo "โ˜๏ธ Infrastructure Status:" +cd infrastructure +if pulumi stack --show-name 2>/dev/null; then + echo "Current stack: $(pulumi stack --show-name)" + if MANAGER_IP=$(pulumi stack output managerIp 2>/dev/null); then + echo "Manager IP: $MANAGER_IP" + else + echo "Manager IP: Not available (stack may be down)" + fi +else + echo "No active Pulumi stack found" +fi +cd .. +echo "" + +# Docker stacks +echo "๐Ÿ“š Docker Stacks:" +if docker context use pocketsizefund-local >/dev/null 2>&1; then + echo "Local stacks:" + docker stack ls 2>/dev/null || echo " No stacks deployed locally" +fi +echo "" +if docker context use pocketsizefund-production >/dev/null 2>&1; then + echo "Production stacks:" + docker stack ls 2>/dev/null || echo " No stacks deployed in production" +fi + +# Reset context +docker context use default >/dev/null 2>&1 || true +echo "" +echo "โœ… Status check completed" +``` + +## secrets +> Manage Docker Swarm secrets for application configuration + +### list +> List all Docker secrets (requires active swarm context) +```bash +echo "๐Ÿ” Docker Secrets:" +if docker info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q active; then + docker secret ls +else + echo "โŒ Not connected to Docker swarm - switch context first:" + echo " mask docker context local" + echo " mask docker context production" +fi +``` + +### create +> Interactively create required Docker secrets +```bash +set -euo pipefail + +if ! docker info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q active; then + echo "โŒ Not connected to Docker swarm - switch context first:" + echo " mask docker context local" + echo " mask docker context production" + exit 1 +fi + +echo "๐Ÿ” Creating Docker Secrets" +echo "=========================" +echo "Leave blank to skip a secret" +echo "" + +secrets=( + "GRAFANA_ADMIN_PASSWORD:Grafana admin password" + "ALPACA_API_KEY:Alpaca API key" + "ALPACA_API_SECRET:Alpaca API secret" + "ALPACA_BASE_URL:Alpaca base URL" + "EDGAR_USER_AGENT:EDGAR user agent string" + "DATA_BUCKET:Data storage bucket name" + "POLYGON_API_KEY:Polygon API key" + "DUCKDB_ACCESS_KEY:DuckDB access key" + "DUCKDB_SECRET:DuckDB secret" + "WEIGHTS_AND_BIASES_API_KEY:Weights & Biases API key" +) + +for secret_info in "${secrets[@]}"; do + secret_name="${secret_info%%:*}" + secret_desc="${secret_info#*:}" + + echo -n "Enter $secret_desc ($secret_name): " + read -r secret_value + + if [[ -n "$secret_value" ]]; then + if echo "$secret_value" | docker secret create "$secret_name" - 2>/dev/null; then + echo "โœ… Created $secret_name" + else + echo "โš ๏ธ $secret_name already exists or creation failed" + fi + else + echo "โญ๏ธ Skipped $secret_name" + fi + echo "" +done + +echo "๐Ÿ” Secret creation completed" +``` + +## development +> Python development tools and code quality checks + +### python +> Python development workflow commands +#### install +> Install Python dependencies using uv with all packages and groups +```bash +set -euo pipefail + +echo "๐Ÿ“ฆ Installing Python dependencies..." +export COMPOSE_BAKE=true +uv sync --all-packages --all-groups + +echo "โœ… Python dependencies installed successfully" +echo "" +echo "Next steps:" +echo " mask development python format # Format code" +echo " mask development python lint # Run quality checks" +echo " mask development python test # Run tests" +``` + +#### format +> Format Python code using ruff formatter +```bash +set -euo pipefail + +echo "๐ŸŽจ Formatting Python code..." +ruff format + +echo "โœ… Python code formatted successfully" +``` + +#### dead-code +> Check for dead Python code using vulture (runs after formatting) +```bash +set -euo pipefail + +echo "๐Ÿงน Checking for dead Python code..." +mask development python format + +echo "๐Ÿ” Running vulture dead code analysis..." +uvx vulture \ + --min-confidence 80 \ + --exclude '.flox,.venv,target' \ + . + +echo "โœ… Dead code check completed" +``` + +#### lint +> Run comprehensive Python code quality checks (includes formatting and dead code check) +```bash +set -euo pipefail + +echo "๐Ÿ” Running Python code quality checks..." + +# Run dead code check first (which includes formatting) +mask development python dead-code + +echo "๐Ÿ“‹ Running ruff linting..." +ruff check \ + --output-format=github \ + . + +# Note: ty check commented out in original +# uvx ty check + +echo "โœ… Python linting completed successfully" +``` + +#### test +> Run Python tests using Docker Compose with coverage reporting +```bash +set -euo pipefail + +echo "๐Ÿงช Running Python tests..." + +# Create coverage output directory +mkdir -p coverage_output + +# Clean up any existing test containers +echo "๐Ÿงน Cleaning up previous test runs..." +docker compose --file tests.yaml down --volumes --remove-orphans + +# Build test containers +echo "๐Ÿ—๏ธ Building test containers..." +docker compose --file tests.yaml build tests + +# Run tests +echo "๐Ÿš€ Running tests with coverage..." +docker compose --file tests.yaml run --rm --no-TTY tests + +# Clean up after tests +echo "๐Ÿงน Cleaning up test containers..." +docker compose --file tests.yaml down --volumes --remove-orphans + +echo "โœ… Python tests completed successfully" +echo "๐Ÿ“Š Coverage report available in coverage_output/.python_coverage.xml" +``` + +### quality +> Run all code quality checks across the entire project +```bash +set -euo pipefail + +echo "๐Ÿ” Running comprehensive code quality checks..." + +# Run Python quality checks +mask development python lint + +# Run additional linting tools +echo "๐Ÿ“‹ Running additional linters..." +nu linter.nu +yamllint -d "{extends: relaxed, rules: {line-length: {max: 110}}}" . + +echo "โœ… All quality checks completed successfully" +echo "" +echo "๐ŸŽ‰ Code is ready for review!" +``` + +## logs +> Quick access to service logs across environments + +### infrastructure +> View logs for infrastructure services (Grafana, Prometheus, Traefik) +```bash +echo "๐Ÿ“‹ Infrastructure Service Logs" +echo "Select environment:" +select env in "local" "production"; do + case $env in + local|production) + context="pocketsizefund-$env" + docker context use "$context" + echo "Infrastructure services in $env:" + services=($(docker service ls --filter "name=infrastructure_" --format '{{.Name}}')) + if [[ ${#services[@]} -eq 0 ]]; then + echo "No infrastructure services found" + exit 1 + fi + echo "Select service:" + select service in "${services[@]}"; do + if [[ -n "$service" ]]; then + echo "๐Ÿ“œ Logs for $service (press Ctrl+C to exit):" + docker service logs -f "$service" + break + fi + done + break + ;; + *) + echo "Invalid selection" + ;; + esac +done +docker context use default >/dev/null 2>&1 || true +``` + +### applications +> View logs for application services (DataManager, PortfolioManager) +```bash +echo "๐Ÿ“‹ Application Service Logs" +echo "Select environment:" +select env in "local" "production"; do + case $env in + local|production) + context="pocketsizefund-$env" + docker context use "$context" + echo "Application services in $env:" + services=($(docker service ls --filter "name=applications_" --format '{{.Name}}')) + if [[ ${#services[@]} -eq 0 ]]; then + echo "No application services found" + exit 1 + fi + echo "Select service:" + select service in "${services[@]}"; do + if [[ -n "$service" ]]; then + echo "๐Ÿ“œ Logs for $service (press Ctrl+C to exit):" + docker service logs -f "$service" + break + fi + done + break + ;; + *) + echo "Invalid selection" + ;; + esac +done +docker context use default >/dev/null 2>&1 || true +``` diff --git a/uv.lock b/uv.lock index 185b8b62c..fcad15ea8 100644 --- a/uv.lock +++ b/uv.lock @@ -141,6 +141,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] +[[package]] +name = "anyio" +version = "4.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252, upload-time = "2025-08-04T08:54:26.451Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213, upload-time = "2025-08-04T08:54:24.882Z" }, +] + [[package]] name = "attrs" version = "25.3.0" @@ -358,22 +372,22 @@ wheels = [ [[package]] name = "coverage" -version = "7.10.3" +version = "7.10.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f4/2c/253cc41cd0f40b84c1c34c5363e0407d73d4a1cae005fed6db3b823175bd/coverage-7.10.3.tar.gz", hash = "sha256:812ba9250532e4a823b070b0420a36499859542335af3dca8f47fc6aa1a05619", size = 822936, upload-time = "2025-08-10T21:27:39.968Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/4e/08b493f1f1d8a5182df0044acc970799b58a8d289608e0d891a03e9d269a/coverage-7.10.4.tar.gz", hash = "sha256:25f5130af6c8e7297fd14634955ba9e1697f47143f289e2a23284177c0061d27", size = 823798, upload-time = "2025-08-17T00:26:43.314Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b8/62/13c0b66e966c43d7aa64dadc8cd2afa1f5a2bf9bb863bdabc21fb94e8b63/coverage-7.10.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:449c1e2d3a84d18bd204258a897a87bc57380072eb2aded6a5b5226046207b42", size = 216262, upload-time = "2025-08-10T21:25:55.367Z" }, - { url = "https://files.pythonhosted.org/packages/b5/f0/59fdf79be7ac2f0206fc739032f482cfd3f66b18f5248108ff192741beae/coverage-7.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d4f9ce50b9261ad196dc2b2e9f1fbbee21651b54c3097a25ad783679fd18294", size = 216496, upload-time = "2025-08-10T21:25:56.759Z" }, - { url = "https://files.pythonhosted.org/packages/34/b1/bc83788ba31bde6a0c02eb96bbc14b2d1eb083ee073beda18753fa2c4c66/coverage-7.10.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4dd4564207b160d0d45c36a10bc0a3d12563028e8b48cd6459ea322302a156d7", size = 247989, upload-time = "2025-08-10T21:25:58.067Z" }, - { url = "https://files.pythonhosted.org/packages/0c/29/f8bdf88357956c844bd872e87cb16748a37234f7f48c721dc7e981145eb7/coverage-7.10.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5ca3c9530ee072b7cb6a6ea7b640bcdff0ad3b334ae9687e521e59f79b1d0437", size = 250738, upload-time = "2025-08-10T21:25:59.406Z" }, - { url = "https://files.pythonhosted.org/packages/ae/df/6396301d332b71e42bbe624670af9376f63f73a455cc24723656afa95796/coverage-7.10.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b6df359e59fa243c9925ae6507e27f29c46698359f45e568fd51b9315dbbe587", size = 251868, upload-time = "2025-08-10T21:26:00.65Z" }, - { url = "https://files.pythonhosted.org/packages/91/21/d760b2df6139b6ef62c9cc03afb9bcdf7d6e36ed4d078baacffa618b4c1c/coverage-7.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a181e4c2c896c2ff64c6312db3bda38e9ade2e1aa67f86a5628ae85873786cea", size = 249790, upload-time = "2025-08-10T21:26:02.009Z" }, - { url = "https://files.pythonhosted.org/packages/69/91/5dcaa134568202397fa4023d7066d4318dc852b53b428052cd914faa05e1/coverage-7.10.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a374d4e923814e8b72b205ef6b3d3a647bb50e66f3558582eda074c976923613", size = 247907, upload-time = "2025-08-10T21:26:03.757Z" }, - { url = "https://files.pythonhosted.org/packages/38/ed/70c0e871cdfef75f27faceada461206c1cc2510c151e1ef8d60a6fedda39/coverage-7.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:daeefff05993e5e8c6e7499a8508e7bd94502b6b9a9159c84fd1fe6bce3151cb", size = 249344, upload-time = "2025-08-10T21:26:05.11Z" }, - { url = "https://files.pythonhosted.org/packages/5f/55/c8a273ed503cedc07f8a00dcd843daf28e849f0972e4c6be4c027f418ad6/coverage-7.10.3-cp312-cp312-win32.whl", hash = "sha256:187ecdcac21f9636d570e419773df7bd2fda2e7fa040f812e7f95d0bddf5f79a", size = 218693, upload-time = "2025-08-10T21:26:06.534Z" }, - { url = "https://files.pythonhosted.org/packages/94/58/dd3cfb2473b85be0b6eb8c5b6d80b6fc3f8f23611e69ef745cef8cf8bad5/coverage-7.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:4a50ad2524ee7e4c2a95e60d2b0b83283bdfc745fe82359d567e4f15d3823eb5", size = 219501, upload-time = "2025-08-10T21:26:08.195Z" }, - { url = "https://files.pythonhosted.org/packages/56/af/7cbcbf23d46de6f24246e3f76b30df099d05636b30c53c158a196f7da3ad/coverage-7.10.3-cp312-cp312-win_arm64.whl", hash = "sha256:c112f04e075d3495fa3ed2200f71317da99608cbb2e9345bdb6de8819fc30571", size = 218135, upload-time = "2025-08-10T21:26:09.584Z" }, - { url = "https://files.pythonhosted.org/packages/84/19/e67f4ae24e232c7f713337f3f4f7c9c58afd0c02866fb07c7b9255a19ed7/coverage-7.10.3-py3-none-any.whl", hash = "sha256:416a8d74dc0adfd33944ba2f405897bab87b7e9e84a391e09d241956bd953ce1", size = 207921, upload-time = "2025-08-10T21:27:38.254Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4a/781c9e4dd57cabda2a28e2ce5b00b6be416015265851060945a5ed4bd85e/coverage-7.10.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a1f0264abcabd4853d4cb9b3d164adbf1565da7dab1da1669e93f3ea60162d79", size = 216706, upload-time = "2025-08-17T00:24:51.528Z" }, + { url = "https://files.pythonhosted.org/packages/6a/8c/51255202ca03d2e7b664770289f80db6f47b05138e06cce112b3957d5dfd/coverage-7.10.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:536cbe6b118a4df231b11af3e0f974a72a095182ff8ec5f4868c931e8043ef3e", size = 216939, upload-time = "2025-08-17T00:24:53.171Z" }, + { url = "https://files.pythonhosted.org/packages/06/7f/df11131483698660f94d3c847dc76461369782d7a7644fcd72ac90da8fd0/coverage-7.10.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9a4c0d84134797b7bf3f080599d0cd501471f6c98b715405166860d79cfaa97e", size = 248429, upload-time = "2025-08-17T00:24:54.934Z" }, + { url = "https://files.pythonhosted.org/packages/eb/fa/13ac5eda7300e160bf98f082e75f5c5b4189bf3a883dd1ee42dbedfdc617/coverage-7.10.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7c155fc0f9cee8c9803ea0ad153ab6a3b956baa5d4cd993405dc0b45b2a0b9e0", size = 251178, upload-time = "2025-08-17T00:24:56.353Z" }, + { url = "https://files.pythonhosted.org/packages/9a/bc/f63b56a58ad0bec68a840e7be6b7ed9d6f6288d790760647bb88f5fea41e/coverage-7.10.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a5f2ab6e451d4b07855d8bcf063adf11e199bff421a4ba57f5bb95b7444ca62", size = 252313, upload-time = "2025-08-17T00:24:57.692Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b6/79338f1ea27b01266f845afb4485976211264ab92407d1c307babe3592a7/coverage-7.10.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:685b67d99b945b0c221be0780c336b303a7753b3e0ec0d618c795aada25d5e7a", size = 250230, upload-time = "2025-08-17T00:24:59.293Z" }, + { url = "https://files.pythonhosted.org/packages/bc/93/3b24f1da3e0286a4dc5832427e1d448d5296f8287464b1ff4a222abeeeb5/coverage-7.10.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0c079027e50c2ae44da51c2e294596cbc9dbb58f7ca45b30651c7e411060fc23", size = 248351, upload-time = "2025-08-17T00:25:00.676Z" }, + { url = "https://files.pythonhosted.org/packages/de/5f/d59412f869e49dcc5b89398ef3146c8bfaec870b179cc344d27932e0554b/coverage-7.10.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3749aa72b93ce516f77cf5034d8e3c0dfd45c6e8a163a602ede2dc5f9a0bb927", size = 249788, upload-time = "2025-08-17T00:25:02.354Z" }, + { url = "https://files.pythonhosted.org/packages/cc/52/04a3b733f40a0cc7c4a5b9b010844111dbf906df3e868b13e1ce7b39ac31/coverage-7.10.4-cp312-cp312-win32.whl", hash = "sha256:fecb97b3a52fa9bcd5a7375e72fae209088faf671d39fae67261f37772d5559a", size = 219131, upload-time = "2025-08-17T00:25:03.79Z" }, + { url = "https://files.pythonhosted.org/packages/83/dd/12909fc0b83888197b3ec43a4ac7753589591c08d00d9deda4158df2734e/coverage-7.10.4-cp312-cp312-win_amd64.whl", hash = "sha256:26de58f355626628a21fe6a70e1e1fad95702dafebfb0685280962ae1449f17b", size = 219939, upload-time = "2025-08-17T00:25:05.494Z" }, + { url = "https://files.pythonhosted.org/packages/83/c7/058bb3220fdd6821bada9685eadac2940429ab3c97025ce53549ff423cc1/coverage-7.10.4-cp312-cp312-win_arm64.whl", hash = "sha256:67e8885408f8325198862bc487038a4980c9277d753cb8812510927f2176437a", size = 218572, upload-time = "2025-08-17T00:25:06.897Z" }, + { url = "https://files.pythonhosted.org/packages/bb/78/983efd23200921d9edb6bd40512e1aa04af553d7d5a171e50f9b2b45d109/coverage-7.10.4-py3-none-any.whl", hash = "sha256:065d75447228d05121e5c938ca8f0e91eed60a1eb2d1258d42d5084fecfc3302", size = 208365, upload-time = "2025-08-17T00:26:41.479Z" }, ] [[package]] @@ -461,20 +475,16 @@ name = "datamanager" version = "0.1.0" source = { editable = "applications/datamanager" } dependencies = [ - { name = "alpaca-py" }, - { name = "boto3" }, - { name = "duckdb" }, - { name = "internal" }, - { name = "loguru" }, + { name = "fastapi" }, + { name = "structlog" }, + { name = "uvicorn" }, ] [package.metadata] requires-dist = [ - { name = "alpaca-py", specifier = ">=0.42.0" }, - { name = "boto3", specifier = ">=1.38.23" }, - { name = "duckdb", specifier = ">=1.2.2" }, - { name = "internal", editable = "libraries/python" }, - { name = "loguru", specifier = ">=0.7.3" }, + { name = "fastapi", specifier = ">=0.116.1" }, + { name = "structlog", specifier = ">=25.4.0" }, + { name = "uvicorn", specifier = ">=0.35.0" }, ] [[package]] @@ -531,18 +541,17 @@ wheels = [ ] [[package]] -name = "duckdb" -version = "1.3.2" +name = "fastapi" +version = "0.116.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/47/24/a2e7fb78fba577641c286fe33185789ab1e1569ccdf4d142e005995991d2/duckdb-1.3.2.tar.gz", hash = "sha256:c658df8a1bc78704f702ad0d954d82a1edd4518d7a04f00027ec53e40f591ff5", size = 11627775, upload-time = "2025-07-08T10:41:14.444Z" } +dependencies = [ + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/d7/6c8b3bfe33eeffa208183ec037fee0cce9f7f024089ab1c5d12ef04bd27c/fastapi-0.116.1.tar.gz", hash = "sha256:ed52cbf946abfd70c5a0dccb24673f0670deeb517a88b3544d03c2a6bf283143", size = 296485, upload-time = "2025-07-11T16:22:32.057Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6c/5d/77f15528857c2b186ebec07778dc199ccc04aafb69fb7b15227af4f19ac9/duckdb-1.3.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2455b1ffef4e3d3c7ef8b806977c0e3973c10ec85aa28f08c993ab7f2598e8dd", size = 15538413, upload-time = "2025-07-08T10:40:29.551Z" }, - { url = "https://files.pythonhosted.org/packages/78/67/7e4964f688b846676c813a4acc527cd3454be8a9cafa10f3a9aa78d0d165/duckdb-1.3.2-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:9d0ae509713da3461c000af27496d5413f839d26111d2a609242d9d17b37d464", size = 32535307, upload-time = "2025-07-08T10:40:31.632Z" }, - { url = "https://files.pythonhosted.org/packages/95/3d/2d7f8078194130dbf30b5ae154ce454bfc208c91aa5f3e802531a3e09bca/duckdb-1.3.2-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:72ca6143d23c0bf6426396400f01fcbe4785ad9ceec771bd9a4acc5b5ef9a075", size = 17110219, upload-time = "2025-07-08T10:40:34.072Z" }, - { url = "https://files.pythonhosted.org/packages/cd/05/36ff9000b9c6d2a68c1b248f133ee316fcac10c0ff817112cbf5214dbe91/duckdb-1.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b49a11afba36b98436db83770df10faa03ebded06514cb9b180b513d8be7f392", size = 19178569, upload-time = "2025-07-08T10:40:35.995Z" }, - { url = "https://files.pythonhosted.org/packages/ac/73/f85acbb3ac319a86abbf6b46103d58594d73529123377219980f11b388e9/duckdb-1.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36abdfe0d1704fe09b08d233165f312dad7d7d0ecaaca5fb3bb869f4838a2d0b", size = 21129975, upload-time = "2025-07-08T10:40:38.3Z" }, - { url = "https://files.pythonhosted.org/packages/32/40/9aa3267f3631ae06b30fb1045a48628f4dba7beb2efb485c0282b4a73367/duckdb-1.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3380aae1c4f2af3f37b0bf223fabd62077dd0493c84ef441e69b45167188e7b6", size = 22781859, upload-time = "2025-07-08T10:40:41.691Z" }, - { url = "https://files.pythonhosted.org/packages/8c/8d/47bf95f6999b327cf4da677e150cfce802abf9057b61a93a1f91e89d748c/duckdb-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:11af73963ae174aafd90ea45fb0317f1b2e28a7f1d9902819d47c67cc957d49c", size = 11395337, upload-time = "2025-07-08T10:40:43.651Z" }, + { url = "https://files.pythonhosted.org/packages/e5/47/d63c60f59a59467fda0f93f46335c9d18526d7071f025cb5b89d5353ea42/fastapi-0.116.1-py3-none-any.whl", hash = "sha256:c46ac7c312df840f0c9e220f7964bada936781bc4e2e6eb71f1c4d7553786565", size = 95631, upload-time = "2025-07-11T16:22:30.485Z" }, ] [[package]] @@ -825,6 +834,43 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/28/aa/1b1fe7d8ab699e1ec26d3a36b91d3df9f83a30abc07d4c881d0296b17b67/grpcio_status-1.74.0-py3-none-any.whl", hash = "sha256:52cdbd759a6760fc8f668098a03f208f493dd5c76bf8e02598bbbaf1f6fc2876", size = 14425, upload-time = "2025-07-24T19:01:19.963Z" }, ] +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + [[package]] name = "idna" version = "3.10" @@ -1368,11 +1414,17 @@ name = "portfoliomanager" version = "0.1.0" source = { editable = "applications/portfoliomanager" } dependencies = [ - { name = "internal" }, + { name = "fastapi" }, + { name = "httpx" }, + { name = "uvicorn" }, ] [package.metadata] -requires-dist = [{ name = "internal", editable = "libraries/python" }] +requires-dist = [ + { name = "fastapi", specifier = ">=0.116.1" }, + { name = "httpx", specifier = ">=0.27.0" }, + { name = "uvicorn", specifier = ">=0.35.0" }, +] [[package]] name = "propcache" @@ -1639,7 +1691,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.4" +version = "2.32.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -1647,9 +1699,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, ] [[package]] @@ -1774,6 +1826,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e", size = 24303, upload-time = "2025-01-02T07:14:38.724Z" }, ] +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + [[package]] name = "sseclient-py" version = "1.8.0" @@ -1783,6 +1844,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/49/58/97655efdfeb5b4eeab85b1fc5d3fa1023661246c2ab2a26ea8e47402d4f2/sseclient_py-1.8.0-py2.py3-none-any.whl", hash = "sha256:4ecca6dc0b9f963f8384e9d7fd529bf93dd7d708144c4fb5da0e0a1a926fee83", size = 8828, upload-time = "2023-09-01T19:39:17.627Z" }, ] +[[package]] +name = "starlette" +version = "0.47.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/57/d062573f391d062710d4088fa1369428c38d51460ab6fedff920efef932e/starlette-0.47.2.tar.gz", hash = "sha256:6ae9aa5db235e4846decc1e7b79c4f346adf41e9777aebeb49dfd09bbd7023d8", size = 2583948, upload-time = "2025-07-20T17:31:58.522Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/1f/b876b1f83aef204198a42dc101613fefccb32258e5428b5f9259677864b4/starlette-0.47.2-py3-none-any.whl", hash = "sha256:c5847e96134e5c5371ee9fac6fdf1a67336d5815e09eb2a01fdb57a351ef915b", size = 72984, upload-time = "2025-07-20T17:31:56.738Z" }, +] + [[package]] name = "statsd" version = "4.0.1" @@ -1792,13 +1866,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/d0/c9543b52c067a390ae6ae632d7fd1b97a35cdc8d69d40c0b7d334b326410/statsd-4.0.1-py2.py3-none-any.whl", hash = "sha256:c2676519927f7afade3723aca9ca8ea986ef5b059556a980a867721ca69df093", size = 13118, upload-time = "2022-11-06T14:17:34.258Z" }, ] +[[package]] +name = "structlog" +version = "25.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/b9/6e672db4fec07349e7a8a8172c1a6ae235c58679ca29c3f86a61b5e59ff3/structlog-25.4.0.tar.gz", hash = "sha256:186cd1b0a8ae762e29417095664adf1d6a31702160a46dacb7796ea82f7409e4", size = 1369138, upload-time = "2025-06-02T08:21:12.971Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/4a/97ee6973e3a73c74c8120d59829c3861ea52210667ec3e7a16045c62b64d/structlog-25.4.0-py3-none-any.whl", hash = "sha256:fe809ff5c27e557d14e613f45ca441aabda051d119ee5a0102aaba6ce40eed2c", size = 68720, upload-time = "2025-06-02T08:21:11.43Z" }, +] + [[package]] name = "tinygrad" -version = "0.10.3" +version = "0.11.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/26/ed13ccfe488d550726caaaacaf245aa79f40b9153ad6d5c99012a940cc5a/tinygrad-0.10.3.tar.gz", hash = "sha256:e79184ce68a42599e313bacd7283425f4ae2772cc117e0bb5b437465115cb1bf", size = 10352294, upload-time = "2025-05-14T22:46:28.606Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/74/e3bca9f8e361296c19bd2b038d0be8013a76b68a83757864b6751f0d592b/tinygrad-0.11.0.tar.gz", hash = "sha256:d9d468a55906cc49a1b4df5b69be78a58ab4d15714b7f238f2b0876d2bc09bc1", size = 1849541, upload-time = "2025-08-19T21:11:46.557Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/23/92/6cab3019b093cda0ca863d72d37dc033e0e859ebd3828a89ae56d1145cc1/tinygrad-0.10.3-py3-none-any.whl", hash = "sha256:2b3e19cc427ed9d55d70e785d7e540b4ed2a3460b89a8ef411e4911b13b7e4c1", size = 10561815, upload-time = "2025-05-14T22:46:25.882Z" }, + { url = "https://files.pythonhosted.org/packages/40/ac/38878fef46f9ce2cc4d624ac061f5bb5bb8ef98594fff96730d9947c3af0/tinygrad-0.11.0-py3-none-any.whl", hash = "sha256:b901d98880f04ad9f796734a013151ba851dbb9a340f1a516099adcd6fd3b3e3", size = 1745076, upload-time = "2025-08-19T21:11:44.723Z" }, ] [[package]] @@ -1865,6 +1948,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] +[[package]] +name = "uvicorn" +version = "0.35.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, +] + [[package]] name = "wandb" version = "0.21.1"