docs: 📜 Small Updates in prep

This commit is contained in:
2025-09-02 18:45:00 +01:00
parent 17f33dfdd8
commit f8816b1da6
4 changed files with 162 additions and 94 deletions
+29 -84
View File
@@ -1,5 +1,9 @@
Below is a “readytohack” checklist that covers everything youll need to set up before the hack day starts. Its broken into three phases **preplanning**, **environment & tooling**, and **projectspecific prep** so you can tackle each in order. Below is a “readytohack” checklist that covers everything youll need to set up before the hack day starts.
Its broken into three phases
* **preplanning**
* **environment & tooling**
* **projectspecific prep**
--- ---
@@ -7,8 +11,8 @@ Below is a “readytohack” checklist that covers everything youll nee
| Item | Why it matters | How to decide | | Item | Why it matters | How to decide |
|------|----------------|---------------| |------|----------------|---------------|
| **Problem statement + success metric** | Keeps the hack focused; avoids “well just keep adding features” trap. | Write a onesentence goal and a concrete KPI (e.g., 80% of user intents correctly handled). | | **Problem statement + success metric** | Keeps the hack focused; avoids “well just keep adding features” trap. | Write a onesentence goal and a concrete KPI (e.g., 80 % of user intents correctly handled). |
| **Scope & MVP** | Defines what you can finish in 2448h. | List core features, then prune until only 35 “musthave” items remain. | | **Scope & MVP** | Defines what you can finish in 2448 h. | List core features, then prune until only 35 “musthave” items remain. |
| **User stories / personas** | Helps surface edge cases early. | Draft 23 short scenarios (e.g., “As a student, I want the agent to schedule a meeting”). | | **User stories / personas** | Helps surface edge cases early. | Draft 23 short scenarios (e.g., “As a student, I want the agent to schedule a meeting”). |
| **Success criteria & demo plan** | Gives you a clear finish line and a demo script. | Write bullet points for each feature that can be shown in the final demo. | | **Success criteria & demo plan** | Gives you a clear finish line and a demo script. | Write bullet points for each feature that can be shown in the final demo. |
| **Team roles** | Prevents overlap and gaps (e.g., one person on NLP, another on UI). | Assign: Lead dev, AI/ML engineer, frontend/UI, documentation & testing. | | **Team roles** | Prevents overlap and gaps (e.g., one person on NLP, another on UI). | Assign: Lead dev, AI/ML engineer, frontend/UI, documentation & testing. |
@@ -17,48 +21,29 @@ Below is a “readytohack” checklist that covers everything youll nee
## 2️⃣ Environment & Tooling ## 2️⃣ Environment & Tooling
### a) Code Repository ### UV To handle virtual environment, package and dependancy handling.
- **Git + GitHub/GitLab/Bitbucket** set up the repo now; use a `main` branch and an `dev` branch. > uv add {package name}
- Add a **`.gitignore`** for Python (or use the template).
- Create a simple README with project name, goal, and how to run.
### b) Virtual Environment ### Language Model
```bash
python -m venv .venv
source .venv/bin/activate # Linux/macOS
.venv\Scripts\activate # Windows
```
### c) Dependency Management
- **`requirements.txt`** or **`pyproject.toml`** (Poetry / Pipenv).
- Pin major packages (e.g., `langchain==0.1.*`, `openai==0.*`).
### d) Language Model & API Keys
| Service | What you need | Notes | | Service | What you need | Notes |
|---------|---------------|-------| |---------|---------------|-------|
| OpenAI GPT4o or GPT4 Turbo | API key, set in env var (`OPENAI_API_KEY`) | Make sure quota is enough; consider a free tier for quick tests. | | local running LLMs | lmstudio | Keeping things local (for LLMs) is one of the Goals. |
| Anthropic Claude | `ANTHROPIC_API_KEY` | Good for “multimodal” prompts if you need images. |
| Hugging Face models (optional) | Token for private repos | For local inference if you want to avoid API calls. |
Store keys in a **`.env.example`** file and load them with `python-dotenv`.
### e) Agent Framework ### Agent Framework
- **LangChain/Agentic** or **OpenAIs new `ChatCompletion` agents**. TBC, need to plan this
- Install: `pip install langchain openai python-dotenv` Think about agent LLMs and tool callers
- If you want modularity, consider the **MCP (Modular Conversational Protocol)** library if it exists; otherwise use a custom messagepassing protocol.
### f) Development Tools ### Development Tools
| Tool | Purpose | | Tool | Purpose |
|------|---------| |------|---------|
| VS Code / PyCharm | IDE with Python support. | | VSCode / Zed | IDE with Python support. |
| `black`, `ruff` | Autoformatting & linting. | | ruff | Autoformatting & linting. |
| `pytest` or `unittest` | Quick unit tests for critical functions. | | pytest | Quick unit tests for critical functions. |
| Docker (optional) | Snapshot environment for later deployment. |
### g) Data / Knowledge Base ### Data / Knowledge Base
- **Static docs**: Markdown/HTML files you want the agent to read. - **Static docs**: Markdown/HTML files you want the agent to read.
- **Vector store**: Use FAISS, Pinecone, or Chroma for embeddings if youll do RAG. - **Vector store**: Use FAISS, Pinecone, or Chroma for embeddings if youll do RAG.
- Precompute embeddings before hack day (script in repo).
- **Sample user intents**: Create a JSON file with example queries. - **Sample user intents**: Create a JSON file with example queries.
--- ---
@@ -68,9 +53,9 @@ Store keys in a **`.env.example`** file and load them with `python-dotenv`.
### 1. Architecture Sketch ### 1. Architecture Sketch
``` ```
┌─────────────────────┐ ┌───────────────┐ ┌─────────────────────┐ ┌───────────────┐
│ Frontend UI / CLI │ │ API Layer │ │ Frontend UI / CLI │ │ API Layer │
├─────────────────────┤ ├───────────────┤ ├─────────────────────┤ ├───────────────┤
│ Request handler │◄─►│ Agent core │ │ Request handler │◄─►│ Agent core │
├─────────────────────┤ │ (MCP) │ ├─────────────────────┤ │ (MCP) │
│ State manager │ └───────────────┘ │ State manager │ └───────────────┘
└─────────────────────┘ └─────────────────────┘
@@ -96,7 +81,6 @@ Store keys in a **`.env.example`** file and load them with `python-dotenv`.
- Run tests nightly in a CI (GitHub Actions) if time permits. - Run tests nightly in a CI (GitHub Actions) if time permits.
### 5. Security & RateLimiting ### 5. Security & RateLimiting
- Add simple `sleep(1)` between API calls to avoid hitting rate limits during the hack.
- Sanitize user input before sending to LLM (avoid injection attacks). - Sanitize user input before sending to LLM (avoid injection attacks).
--- ---
@@ -105,14 +89,14 @@ Store keys in a **`.env.example`** file and load them with `python-dotenv`.
| Time | Task | | Time | Task |
|------|------| |------|------|
| **030min** | Finalise repo, install deps, load env vars. | | **030 min** | Finalise repo, install deps, load env vars. |
| **3060min** | Build minimal UI (CLI or web). | | **3060 min** | Build minimal UI (CLI or web). |
| **12h** | Implement core agent loop & prompt templates. | | **12 h** | Implement core agent loop & prompt templates. |
| **23h** | Wire vector store / RAG if chosen. | | **23 h** | Wire vector store / RAG if chosen. |
| **34h** | Write unit tests for the most critical parts. | | **34 h** | Write unit tests for the most critical parts. |
| **45h** | Run integration test, debug. | | **45 h** | Run integration test, debug. |
| **56h** | Prepare demo script; record or capture demo. | | **56 h** | Prepare demo script; record or capture demo. |
| **6+h** | Polish README, add usage instructions, commit final changes. | | **6+ h** | Polish README, add usage instructions, commit final changes. |
--- ---
@@ -125,45 +109,6 @@ Store keys in a **`.env.example`** file and load them with `python-dotenv`.
--- ---
### Quick Starter Code Skeleton
```python
# main.py
import os
from dotenv import load_dotenv
from fastapi import FastAPI, Request
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
load_dotenv()
app = FastAPI()
llm = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
system_prompt = "You are a helpful assistant."
prompt_template = PromptTemplate(
input_variables=["user_input"],
template="{system}\nUser: {user_input}\nAssistant:",
)
@app.post("/chat")
async def chat(req: Request):
data = await req.json()
user_text = data.get("message", "")
prompt = prompt_template.format(system=system_prompt, user_input=user_text)
response = llm([prompt])
return {"response": response[0].content}
```
Run with:
```bash
uvicorn main:app --reload
curl -X POST http://localhost:8000/chat -H "Content-Type: application/json" -d '{"message":"Hello"}'
```
---
## 🎉 Final Tips ## 🎉 Final Tips
- **Keep it simple** you can always extend later. - **Keep it simple** you can always extend later.
+43 -8
View File
@@ -1,12 +1,47 @@
from rich import print, pretty from rich import print
from rich.console import Console
from rich.table import Table
from rich.panel import Panel from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, BarColumn, track
from rich.markdown import Markdown
from rich.syntax import Syntax
from rich.live import Live
from rich.prompt import Prompt
def main(): import random
print("Hello from devin!") import time
print("[italic red]Hello[/italic red] World!", locals())
print(["Rich and pretty", True])
print(Panel.fit("[bold yellow]Hi, I'm a Panel", border_style="red"))
console = Console()
if __name__ == "__main__": def ask_name() -> str:
main() """Ask for a name and keep asking until it's not empty."""
while True:
name = Prompt.ask("[bold cyan]What is your name?[/]")
if name.strip():
return name.strip()
console.print("[red]Name cannot be empty![/]", style="bold")
def ask_age() -> int:
"""Ask for age and validate it's a positive integer."""
while True:
age_str = Prompt.ask("[bold cyan]How old are you?[/]")
try:
age = int(age_str)
if age <= 0:
raise ValueError
return age
except ValueError:
console.print("[red]Please enter a valid positive integer.[/]", style="bold")
name = ask_name()
age = ask_age()
panel_narrow = Panel(
f"[bold green]Your Name is: {name}[/bold green]\n"
f"[blue]And you are {age} Years Old.[/blue]",
title="About You",
subtitle="The info you gave",
expand=False,
)
console.print(panel_narrow)
+5 -1
View File
@@ -4,4 +4,8 @@ version = "0.1.0"
description = "Devin is your very own AI command centre" description = "Devin is your very own AI command centre"
readme = "README.md" readme = "README.md"
requires-python = ">=3.13" requires-python = ">=3.13"
dependencies = ["rich>=14.1.0"] dependencies = [
"pytest>=8.4.1",
"rich>=14.1.0",
"ruff>=0.12.11",
]
Generated
+85 -1
View File
@@ -2,16 +2,40 @@ version = 1
revision = 3 revision = 3
requires-python = ">=3.13" requires-python = ">=3.13"
[[package]]
name = "colorama"
version = "0.4.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
]
[[package]] [[package]]
name = "devin" name = "devin"
version = "0.1.0" version = "0.1.0"
source = { virtual = "." } source = { virtual = "." }
dependencies = [ dependencies = [
{ name = "pytest" },
{ name = "rich" }, { name = "rich" },
{ name = "ruff" },
] ]
[package.metadata] [package.metadata]
requires-dist = [{ name = "rich", specifier = ">=14.1.0" }] requires-dist = [
{ name = "pytest", specifier = ">=8.4.1" },
{ name = "rich", specifier = ">=14.1.0" },
{ name = "ruff", specifier = ">=0.12.11" },
]
[[package]]
name = "iniconfig"
version = "2.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" },
]
[[package]] [[package]]
name = "markdown-it-py" name = "markdown-it-py"
@@ -34,6 +58,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
] ]
[[package]]
name = "packaging"
version = "25.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
]
[[package]]
name = "pluggy"
version = "1.6.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
]
[[package]] [[package]]
name = "pygments" name = "pygments"
version = "2.19.2" version = "2.19.2"
@@ -43,6 +85,22 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
] ]
[[package]]
name = "pytest"
version = "8.4.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "iniconfig" },
{ name = "packaging" },
{ name = "pluggy" },
{ name = "pygments" },
]
sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" },
]
[[package]] [[package]]
name = "rich" name = "rich"
version = "14.1.0" version = "14.1.0"
@@ -55,3 +113,29 @@ sdist = { url = "https://files.pythonhosted.org/packages/fe/75/af448d8e52bf1d8fa
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" }, { url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" },
] ]
[[package]]
name = "ruff"
version = "0.12.11"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/de/55/16ab6a7d88d93001e1ae4c34cbdcfb376652d761799459ff27c1dc20f6fa/ruff-0.12.11.tar.gz", hash = "sha256:c6b09ae8426a65bbee5425b9d0b82796dbb07cb1af045743c79bfb163001165d", size = 5347103, upload-time = "2025-08-28T13:59:08.87Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d6/a2/3b3573e474de39a7a475f3fbaf36a25600bfeb238e1a90392799163b64a0/ruff-0.12.11-py3-none-linux_armv6l.whl", hash = "sha256:93fce71e1cac3a8bf9200e63a38ac5c078f3b6baebffb74ba5274fb2ab276065", size = 11979885, upload-time = "2025-08-28T13:58:26.654Z" },
{ url = "https://files.pythonhosted.org/packages/76/e4/235ad6d1785a2012d3ded2350fd9bc5c5af8c6f56820e696b0118dfe7d24/ruff-0.12.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8e33ac7b28c772440afa80cebb972ffd823621ded90404f29e5ab6d1e2d4b93", size = 12742364, upload-time = "2025-08-28T13:58:30.256Z" },
{ url = "https://files.pythonhosted.org/packages/2c/0d/15b72c5fe6b1e402a543aa9d8960e0a7e19dfb079f5b0b424db48b7febab/ruff-0.12.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d69fb9d4937aa19adb2e9f058bc4fbfe986c2040acb1a4a9747734834eaa0bfd", size = 11920111, upload-time = "2025-08-28T13:58:33.677Z" },
{ url = "https://files.pythonhosted.org/packages/3e/c0/f66339d7893798ad3e17fa5a1e587d6fd9806f7c1c062b63f8b09dda6702/ruff-0.12.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:411954eca8464595077a93e580e2918d0a01a19317af0a72132283e28ae21bee", size = 12160060, upload-time = "2025-08-28T13:58:35.74Z" },
{ url = "https://files.pythonhosted.org/packages/03/69/9870368326db26f20c946205fb2d0008988aea552dbaec35fbacbb46efaa/ruff-0.12.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a2c0a2e1a450f387bf2c6237c727dd22191ae8c00e448e0672d624b2bbd7fb0", size = 11799848, upload-time = "2025-08-28T13:58:38.051Z" },
{ url = "https://files.pythonhosted.org/packages/25/8c/dd2c7f990e9b3a8a55eee09d4e675027d31727ce33cdb29eab32d025bdc9/ruff-0.12.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ca4c3a7f937725fd2413c0e884b5248a19369ab9bdd850b5781348ba283f644", size = 13536288, upload-time = "2025-08-28T13:58:40.046Z" },
{ url = "https://files.pythonhosted.org/packages/7a/30/d5496fa09aba59b5e01ea76775a4c8897b13055884f56f1c35a4194c2297/ruff-0.12.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4d1df0098124006f6a66ecf3581a7f7e754c4df7644b2e6704cd7ca80ff95211", size = 14490633, upload-time = "2025-08-28T13:58:42.285Z" },
{ url = "https://files.pythonhosted.org/packages/9b/2f/81f998180ad53445d403c386549d6946d0748e536d58fce5b5e173511183/ruff-0.12.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a8dd5f230efc99a24ace3b77e3555d3fbc0343aeed3fc84c8d89e75ab2ff793", size = 13888430, upload-time = "2025-08-28T13:58:44.641Z" },
{ url = "https://files.pythonhosted.org/packages/87/71/23a0d1d5892a377478c61dbbcffe82a3476b050f38b5162171942a029ef3/ruff-0.12.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4dc75533039d0ed04cd33fb8ca9ac9620b99672fe7ff1533b6402206901c34ee", size = 12913133, upload-time = "2025-08-28T13:58:47.039Z" },
{ url = "https://files.pythonhosted.org/packages/80/22/3c6cef96627f89b344c933781ed38329bfb87737aa438f15da95907cbfd5/ruff-0.12.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fc58f9266d62c6eccc75261a665f26b4ef64840887fc6cbc552ce5b29f96cc8", size = 13169082, upload-time = "2025-08-28T13:58:49.157Z" },
{ url = "https://files.pythonhosted.org/packages/05/b5/68b3ff96160d8b49e8dd10785ff3186be18fd650d356036a3770386e6c7f/ruff-0.12.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5a0113bd6eafd545146440225fe60b4e9489f59eb5f5f107acd715ba5f0b3d2f", size = 13139490, upload-time = "2025-08-28T13:58:51.593Z" },
{ url = "https://files.pythonhosted.org/packages/59/b9/050a3278ecd558f74f7ee016fbdf10591d50119df8d5f5da45a22c6afafc/ruff-0.12.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0d737b4059d66295c3ea5720e6efc152623bb83fde5444209b69cd33a53e2000", size = 11958928, upload-time = "2025-08-28T13:58:53.943Z" },
{ url = "https://files.pythonhosted.org/packages/f9/bc/93be37347db854806904a43b0493af8d6873472dfb4b4b8cbb27786eb651/ruff-0.12.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:916fc5defee32dbc1fc1650b576a8fed68f5e8256e2180d4d9855aea43d6aab2", size = 11764513, upload-time = "2025-08-28T13:58:55.976Z" },
{ url = "https://files.pythonhosted.org/packages/7a/a1/1471751e2015a81fd8e166cd311456c11df74c7e8769d4aabfbc7584c7ac/ruff-0.12.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c984f07d7adb42d3ded5be894fb4007f30f82c87559438b4879fe7aa08c62b39", size = 12745154, upload-time = "2025-08-28T13:58:58.16Z" },
{ url = "https://files.pythonhosted.org/packages/68/ab/2542b14890d0f4872dd81b7b2a6aed3ac1786fae1ce9b17e11e6df9e31e3/ruff-0.12.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e07fbb89f2e9249f219d88331c833860489b49cdf4b032b8e4432e9b13e8a4b9", size = 13227653, upload-time = "2025-08-28T13:59:00.276Z" },
{ url = "https://files.pythonhosted.org/packages/22/16/2fbfc61047dbfd009c58a28369a693a1484ad15441723be1cd7fe69bb679/ruff-0.12.11-py3-none-win32.whl", hash = "sha256:c792e8f597c9c756e9bcd4d87cf407a00b60af77078c96f7b6366ea2ce9ba9d3", size = 11944270, upload-time = "2025-08-28T13:59:02.347Z" },
{ url = "https://files.pythonhosted.org/packages/08/a5/34276984705bfe069cd383101c45077ee029c3fe3b28225bf67aa35f0647/ruff-0.12.11-py3-none-win_amd64.whl", hash = "sha256:a3283325960307915b6deb3576b96919ee89432ebd9c48771ca12ee8afe4a0fd", size = 13046600, upload-time = "2025-08-28T13:59:04.751Z" },
{ url = "https://files.pythonhosted.org/packages/84/a8/001d4a7c2b37623a3fd7463208267fb906df40ff31db496157549cfd6e72/ruff-0.12.11-py3-none-win_arm64.whl", hash = "sha256:bae4d6e6a2676f8fb0f98b74594a048bae1b944aab17e9f5d504062303c6dbea", size = 12135290, upload-time = "2025-08-28T13:59:06.933Z" },
]