diff --git a/.gitignore b/.gitignore index 0596fac50..928e73c91 100644 --- a/.gitignore +++ b/.gitignore @@ -281,7 +281,7 @@ frontend/typings frontend/.DS_Store Thumbs.db -executions +/executions openai-realtime-console src/django_app/staticfiles/* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c531b17ce..fb5477fb1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,8 +29,7 @@ repos: - id: ruff-format files: ^backend/ - # Backend - Ruff check (强制检查,不允许错误) - # 注意:此 hook 会检查整个 backend 目录,确保没有 lint 错误 + # Backend - Ruff strict check - repo: local hooks: - id: backend-ruff-check @@ -39,22 +38,10 @@ repos: language: system files: ^backend/.*\.py$ pass_filenames: false - always_run: false # 只在有 Python 文件更改时运行 - stages: [commit] + always_run: false + stages: [pre-commit] - # Python - Type checking (mypy runs in Backend CI job only; skipped in pre-commit) - # - repo: https://github.com/pre-commit/mirrors-mypy - # rev: v1.13.0 - # hooks: - # - id: mypy - # files: ^backend/app/ - # args: [--ignore-missing-imports] - # additional_dependencies: - # - types-requests - # - types-PyYAML - - # Frontend - ESLint (强制检查,不允许错误) - # 注意:此 hook 会检查整个 frontend 目录,确保没有 lint 错误 + # Frontend - ESLint + TypeScript type-check + Prettier format check - repo: local hooks: - id: frontend-lint @@ -63,8 +50,26 @@ repos: language: system files: ^frontend/.*\.(ts|tsx|js|jsx)$ pass_filenames: false - always_run: false # 只在有前端文件更改时运行 - stages: [commit] + always_run: false + stages: [pre-commit] + + - id: frontend-type-check + name: Frontend TypeScript Check + entry: bash -c 'cd frontend && bun run type-check || exit 1' + language: system + files: ^frontend/.*\.(ts|tsx)$ + pass_filenames: false + always_run: false + stages: [pre-commit] + + - id: frontend-format-check + name: Frontend Prettier Check + entry: bash -c 'cd frontend && bun run format:check || exit 1' + language: system + files: ^frontend/.*\.(ts|tsx|js|jsx|json|css|md)$ + pass_filenames: false + always_run: false + stages: [pre-commit] # CI configuration ci: diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 29640ebe7..5b91822e6 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -28,8 +28,8 @@ This document provides detailed instructions for setting up and running the JoyS Using Docker (recommended): ```bash -cd backend/docker -./start.sh +cd deploy +docker compose -f docker-compose-middleware.yml up -d ``` Or manually start PostgreSQL and Redis on your system. diff --git a/backend/alembic/versions/20260415_000000_b4b3b2b1b0a9_add_mission_agent_execution_tables.py b/backend/alembic/versions/20260415_000000_b4b3b2b1b0a9_add_mission_agent_execution_tables.py new file mode 100644 index 000000000..f02456dbb --- /dev/null +++ b/backend/alembic/versions/20260415_000000_b4b3b2b1b0a9_add_mission_agent_execution_tables.py @@ -0,0 +1,274 @@ +"""add_mission_agent_execution_tables + +Revision ID: b4b3b2b1b0a9 +Revises: 0f7082711f20 +Create Date: 2026-04-15 00:00:00.000000 + +""" + +from typing import Sequence, Union + +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "b4b3b2b1b0a9" +down_revision: Union[str, None] = "0f7082711f20" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # --- Enum types --- + op.execute(""" + DO $$ BEGIN + CREATE TYPE missionstatus AS ENUM ('backlog','todo','in_progress','in_review','done','blocked','cancelled'); + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + """) + op.execute(""" + DO $$ BEGIN + CREATE TYPE missionpriority AS ENUM ('none','low','medium','high','urgent'); + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + """) + op.execute(""" + DO $$ BEGIN + CREATE TYPE agentstatus AS ENUM ('idle','working','blocked','error','offline'); + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + """) + op.execute(""" + DO $$ BEGIN + CREATE TYPE missionexecutionstatus AS ENUM ('queued','dispatched','running','interrupt_wait','approval_wait','completed','failed','cancelled'); + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + """) + op.execute(""" + DO $$ BEGIN + CREATE TYPE executionsource AS ENUM ('mission','chat','graph','coordinator','api'); + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + """) + + # --- missions --- + op.create_table( + "missions", + sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), + sa.Column( + "workspace_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("workspaces.id", ondelete="CASCADE"), + nullable=False, + ), + sa.Column("title", sa.String(500), nullable=False), + sa.Column("description", sa.Text(), nullable=True), + sa.Column("objective", sa.Text(), nullable=True), + sa.Column( + "status", + postgresql.ENUM( + "backlog", + "todo", + "in_progress", + "in_review", + "done", + "blocked", + "cancelled", + name="missionstatus", + create_type=False, + ), + nullable=False, + server_default="backlog", + ), + sa.Column( + "priority", + postgresql.ENUM("none", "low", "medium", "high", "urgent", name="missionpriority", create_type=False), + nullable=False, + server_default="none", + ), + sa.Column("assignee_type", sa.String(50), nullable=True), + sa.Column("assignee_id", postgresql.UUID(as_uuid=True), nullable=True), + sa.Column("creator_id", sa.String(255), sa.ForeignKey("user.id", ondelete="CASCADE"), nullable=False), + sa.Column( + "parent_mission_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("missions.id", ondelete="SET NULL"), + nullable=True, + ), + sa.Column("current_execution_id", postgresql.UUID(as_uuid=True), nullable=True), + sa.Column("due_date", sa.DateTime(timezone=True), nullable=True), + sa.Column("position", sa.Float(), nullable=False, server_default="0.0"), + sa.Column("tags", postgresql.JSONB(), nullable=True), + sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + ) + op.create_index("missions_workspace_status_idx", "missions", ["workspace_id", "status"]) + op.create_index("missions_assignee_idx", "missions", ["assignee_type", "assignee_id"]) + op.create_index("missions_creator_idx", "missions", ["creator_id", "created_at"]) + + # --- agent_profiles --- + op.create_table( + "agent_profiles", + sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), + sa.Column( + "workspace_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("workspaces.id", ondelete="CASCADE"), + nullable=False, + ), + sa.Column("name", sa.String(255), nullable=False), + sa.Column("avatar", sa.String(500), nullable=True), + sa.Column("description", sa.Text(), nullable=True), + sa.Column("runtime_type", sa.String(50), nullable=False), + sa.Column( + "status", + postgresql.ENUM("idle", "working", "blocked", "error", "offline", name="agentstatus", create_type=False), + nullable=False, + server_default="offline", + ), + sa.Column("max_concurrent_tasks", sa.Integer(), nullable=False, server_default="1"), + sa.Column("skill_ids", postgresql.JSONB(), nullable=True), + sa.Column("instructions", sa.Text(), nullable=True), + sa.Column("custom_env", postgresql.JSONB(), nullable=True), + sa.Column("runtime_config", postgresql.JSONB(), nullable=True), + sa.Column("visibility", sa.String(50), nullable=False, server_default="workspace"), + sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + ) + op.create_index("agent_profiles_workspace_idx", "agent_profiles", ["workspace_id"]) + op.create_index("agent_profiles_workspace_status_idx", "agent_profiles", ["workspace_id", "status"]) + + # --- executions --- + op.create_table( + "executions", + sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), + sa.Column( + "workspace_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("workspaces.id", ondelete="CASCADE"), + nullable=False, + ), + sa.Column("user_id", sa.String(255), sa.ForeignKey("user.id", ondelete="CASCADE"), nullable=False), + sa.Column( + "source", + postgresql.ENUM( + "mission", "chat", "graph", "coordinator", "api", name="executionsource", create_type=False + ), + nullable=False, + ), + sa.Column("source_id", sa.String(255), nullable=True), + sa.Column( + "status", + postgresql.ENUM( + "queued", + "dispatched", + "running", + "interrupt_wait", + "approval_wait", + "completed", + "failed", + "cancelled", + name="missionexecutionstatus", + create_type=False, + ), + nullable=False, + server_default="queued", + ), + sa.Column("title", sa.String(500), nullable=True), + sa.Column( + "mission_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("missions.id", ondelete="SET NULL"), + nullable=True, + ), + sa.Column( + "agent_profile_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("agent_profiles.id", ondelete="SET NULL"), + nullable=True, + ), + sa.Column( + "parent_execution_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("executions.id", ondelete="SET NULL"), + nullable=True, + ), + sa.Column("result_summary", postgresql.JSONB(), nullable=True), + sa.Column("error_code", sa.String(100), nullable=True), + sa.Column("error_message", sa.Text(), nullable=True), + sa.Column("runtime_type", sa.String(50), nullable=False), + sa.Column("runtime_config", postgresql.JSONB(), nullable=True), + sa.Column("container_id", sa.String(255), nullable=True), + sa.Column("started_at", sa.DateTime(timezone=True), nullable=True), + sa.Column("finished_at", sa.DateTime(timezone=True), nullable=True), + sa.Column("last_heartbeat_at", sa.DateTime(timezone=True), nullable=True), + sa.Column("last_seq", sa.BigInteger(), nullable=False, server_default="0"), + sa.Column("prior_session_id", sa.String(255), nullable=True), + sa.Column("session_id", sa.String(255), nullable=True), + sa.Column("work_dir", sa.String(500), nullable=True), + sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + ) + op.create_index("executions_workspace_status_idx", "executions", ["workspace_id", "status"]) + op.create_index("executions_mission_idx", "executions", ["mission_id"]) + op.create_index("executions_agent_profile_idx", "executions", ["agent_profile_id"]) + op.create_index("executions_parent_idx", "executions", ["parent_execution_id"]) + op.create_index("executions_user_created_idx", "executions", ["user_id", "created_at"]) + + # --- execution_events --- + op.create_table( + "execution_events", + sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), + sa.Column( + "execution_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("executions.id", ondelete="CASCADE"), + nullable=False, + ), + sa.Column("seq", sa.BigInteger(), nullable=False), + sa.Column("event_type", sa.String(100), nullable=False), + sa.Column("payload", postgresql.JSONB(), nullable=False, server_default="{}"), + sa.Column("trace_id", postgresql.UUID(as_uuid=True), nullable=True), + sa.Column("observation_id", postgresql.UUID(as_uuid=True), nullable=True), + sa.Column("parent_observation_id", postgresql.UUID(as_uuid=True), nullable=True), + sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + ) + op.create_unique_constraint("uq_execution_events_exec_seq", "execution_events", ["execution_id", "seq"]) + op.create_index("execution_events_exec_created_idx", "execution_events", ["execution_id", "created_at"]) + + # --- execution_snapshots --- + op.create_table( + "execution_snapshots", + sa.Column( + "execution_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("executions.id", ondelete="CASCADE"), + primary_key=True, + ), + sa.Column("last_seq", sa.BigInteger(), nullable=False, server_default="0"), + sa.Column("status", sa.String(100), nullable=False), + sa.Column("projection", postgresql.JSONB(), nullable=False, server_default="{}"), + sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + ) + + +def downgrade() -> None: + op.drop_table("execution_snapshots") + op.drop_table("execution_events") + op.drop_table("executions") + op.drop_table("agent_profiles") + op.drop_table("missions") + op.execute("DROP TYPE IF EXISTS executionsource") + op.execute("DROP TYPE IF EXISTS missionexecutionstatus") + op.execute("DROP TYPE IF EXISTS agentstatus") + op.execute("DROP TYPE IF EXISTS missionpriority") + op.execute("DROP TYPE IF EXISTS missionstatus") diff --git a/backend/alembic/versions/20260416_000000_c5c4c3c2c1c0_add_mission_comments.py b/backend/alembic/versions/20260416_000000_c5c4c3c2c1c0_add_mission_comments.py new file mode 100644 index 000000000..c39a6113c --- /dev/null +++ b/backend/alembic/versions/20260416_000000_c5c4c3c2c1c0_add_mission_comments.py @@ -0,0 +1,111 @@ +"""add_mission_comments + +Revision ID: c5c4c3c2c1c0 +Revises: b4b3b2b1b0a9 +Create Date: 2026-04-16 00:00:00.000000 + +""" + +from typing import Sequence, Union + +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "c5c4c3c2c1c0" +down_revision: Union[str, None] = "b4b3b2b1b0a9" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # --- Enum types --- + op.execute(""" + DO $$ BEGIN + CREATE TYPE commentauthortype AS ENUM ('member','agent'); + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + """) + op.execute(""" + DO $$ BEGIN + CREATE TYPE commenttype AS ENUM ('comment','status_change','progress_update','system'); + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + """) + + # --- mission_comments --- + op.create_table( + "mission_comments", + sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), + sa.Column( + "mission_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("missions.id", ondelete="CASCADE"), + nullable=False, + ), + sa.Column( + "workspace_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("workspaces.id", ondelete="CASCADE"), + nullable=False, + ), + sa.Column( + "author_type", + postgresql.ENUM("member", "agent", name="commentauthortype", create_type=False), + nullable=False, + ), + sa.Column("author_id", sa.String(255), nullable=False), + sa.Column("content", sa.Text(), nullable=False), + sa.Column( + "type", + postgresql.ENUM( + "comment", "status_change", "progress_update", "system", name="commenttype", create_type=False + ), + nullable=False, + server_default="comment", + ), + sa.Column( + "parent_comment_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("mission_comments.id", ondelete="SET NULL"), + nullable=True, + ), + sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), + ) + op.create_index("mission_comments_mission_created_idx", "mission_comments", ["mission_id", "created_at"]) + op.create_index("mission_comments_workspace_idx", "mission_comments", ["workspace_id"]) + op.create_index("mission_comments_author_idx", "mission_comments", ["author_type", "author_id"]) + op.create_index("mission_comments_parent_idx", "mission_comments", ["parent_comment_id"]) + + # --- Add trigger_comment_id to executions --- + op.add_column( + "executions", + sa.Column( + "trigger_comment_id", + postgresql.UUID(as_uuid=True), + sa.ForeignKey("mission_comments.id", ondelete="SET NULL"), + nullable=True, + ), + ) + op.create_index("executions_trigger_comment_idx", "executions", ["trigger_comment_id"]) + + # --- Dedup guard: at most one pending execution per (mission, agent) --- + op.execute(""" + CREATE UNIQUE INDEX uq_executions_mission_agent_pending + ON executions (mission_id, agent_profile_id) + WHERE status IN ('queued', 'dispatched'); + """) + + +def downgrade() -> None: + op.execute("DROP INDEX IF EXISTS uq_executions_mission_agent_pending") + op.drop_index("executions_trigger_comment_idx", table_name="executions") + op.drop_column("executions", "trigger_comment_id") + op.drop_table("mission_comments") + op.execute("DROP TYPE IF EXISTS commenttype") + op.execute("DROP TYPE IF EXISTS commentauthortype") diff --git a/backend/alembic/versions/20260418_000000_d6d5d4d3d2d1_remove_mission_blocked_status.py b/backend/alembic/versions/20260418_000000_d6d5d4d3d2d1_remove_mission_blocked_status.py new file mode 100644 index 000000000..05a5d63a8 --- /dev/null +++ b/backend/alembic/versions/20260418_000000_d6d5d4d3d2d1_remove_mission_blocked_status.py @@ -0,0 +1,46 @@ +"""remove_mission_blocked_status + +Revision ID: d6d5d4d3d2d1 +Revises: c5c4c3c2c1c0 +Create Date: 2026-04-18 00:00:00.000000 + +""" + +from typing import Sequence, Union + +from alembic import op + +revision: str = "d6d5d4d3d2d1" +down_revision: Union[str, None] = "c5c4c3c2c1c0" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # Move any blocked missions to todo before dropping the enum value + op.execute("UPDATE missions SET status = 'todo' WHERE status = 'blocked'") + + # Drop the default before changing type — PG can't auto-cast the default + op.execute("ALTER TABLE missions ALTER COLUMN status DROP DEFAULT") + + # PostgreSQL cannot DROP a value from an existing enum, so recreate it + op.execute("ALTER TYPE missionstatus RENAME TO missionstatus_old") + op.execute("CREATE TYPE missionstatus AS ENUM ('backlog','todo','in_progress','in_review','done','cancelled')") + op.execute("ALTER TABLE missions ALTER COLUMN status TYPE missionstatus USING status::text::missionstatus") + op.execute("DROP TYPE missionstatus_old") + + # Restore the default + op.execute("ALTER TABLE missions ALTER COLUMN status SET DEFAULT 'backlog'") + + +def downgrade() -> None: + op.execute("ALTER TABLE missions ALTER COLUMN status DROP DEFAULT") + + op.execute("ALTER TYPE missionstatus RENAME TO missionstatus_old") + op.execute( + "CREATE TYPE missionstatus AS ENUM ('backlog','todo','in_progress','in_review','done','blocked','cancelled')" + ) + op.execute("ALTER TABLE missions ALTER COLUMN status TYPE missionstatus USING status::text::missionstatus") + op.execute("DROP TYPE missionstatus_old") + + op.execute("ALTER TABLE missions ALTER COLUMN status SET DEFAULT 'backlog'") diff --git a/backend/alembic/versions/20260418_000001_e7e6e5e4e3e2_add_mission_auto_approve.py b/backend/alembic/versions/20260418_000001_e7e6e5e4e3e2_add_mission_auto_approve.py new file mode 100644 index 000000000..51778181c --- /dev/null +++ b/backend/alembic/versions/20260418_000001_e7e6e5e4e3e2_add_mission_auto_approve.py @@ -0,0 +1,29 @@ +"""add_mission_auto_approve + +Revision ID: e7e6e5e4e3e2 +Revises: d6d5d4d3d2d1 +Create Date: 2026-04-18 00:00:01.000000 + +""" + +from typing import Sequence, Union + +import sqlalchemy as sa + +from alembic import op + +revision: str = "e7e6e5e4e3e2" +down_revision: Union[str, None] = "d6d5d4d3d2d1" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + op.add_column( + "missions", + sa.Column("auto_approve", sa.Boolean(), nullable=False, server_default=sa.text("false")), + ) + + +def downgrade() -> None: + op.drop_column("missions", "auto_approve") diff --git a/backend/alembic/versions/20260418_000002_f8f7f6f5f4f3_add_current_execution_fk.py b/backend/alembic/versions/20260418_000002_f8f7f6f5f4f3_add_current_execution_fk.py new file mode 100644 index 000000000..3e7a1d876 --- /dev/null +++ b/backend/alembic/versions/20260418_000002_f8f7f6f5f4f3_add_current_execution_fk.py @@ -0,0 +1,31 @@ +"""Add FK constraint on missions.current_execution_id -> executions.id""" + +from typing import Union + +from alembic import op + +revision: str = "f8f7f6f5f4f3" +down_revision: Union[str, None] = "e7e6e5e4e3e2" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.execute(""" + UPDATE missions + SET current_execution_id = NULL + WHERE current_execution_id IS NOT NULL + AND current_execution_id NOT IN (SELECT id FROM executions) + """) + op.create_foreign_key( + "fk_missions_current_execution_id", + "missions", + "executions", + ["current_execution_id"], + ["id"], + ondelete="SET NULL", + ) + + +def downgrade() -> None: + op.drop_constraint("fk_missions_current_execution_id", "missions", type_="foreignkey") diff --git a/backend/alembic/versions/20260418_000003_a9a8a7a6a5a4_drop_source_id_column.py b/backend/alembic/versions/20260418_000003_a9a8a7a6a5a4_drop_source_id_column.py new file mode 100644 index 000000000..9442c8732 --- /dev/null +++ b/backend/alembic/versions/20260418_000003_a9a8a7a6a5a4_drop_source_id_column.py @@ -0,0 +1,20 @@ +"""Drop redundant source_id column from executions table.""" + +from typing import Union + +from alembic import op + +revision: str = "a9a8a7a6a5a4" +down_revision: Union[str, None] = "f8f7f6f5f4f3" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.drop_column("executions", "source_id") + + +def downgrade() -> None: + import sqlalchemy as sa + + op.add_column("executions", sa.Column("source_id", sa.String(255), nullable=True)) diff --git a/backend/app/MODEL.md b/backend/app/MODEL.md index 88794a092..ba30a3b45 100644 --- a/backend/app/MODEL.md +++ b/backend/app/MODEL.md @@ -227,12 +227,14 @@ backend/app/ - `POST /api/v1/models/instances` - 创建模型实例配置 - `GET /api/v1/models/instances` - 获取模型实例配置列表 - `POST /api/v1/models/test-output` - 测试模型输出 +- `POST /api/v1/models/test-output-stream` - 测试模型输出(SSE 流式) ### 模型供应商 API - `GET /api/v1/model-providers` - 获取所有供应商列表 - `GET /api/v1/model-providers/{provider_name}` - 获取单个供应商详情 - `POST /api/v1/model-providers/sync` - 同步供应商、模型和认证信息 +- `POST /api/v1/model-providers/custom` - 添加自定义供应商 ### 模型凭据 API @@ -279,7 +281,7 @@ backend/app/ ## 注意事项 1. **全局可见性**: 当前实现中,模型实例和凭据对所有用户和工作空间可见(user_id 和 workspace_id 为 NULL 的记录) -2. **认证**: 当前代码中用户认证部分被注释,使用匿名用户ID,后续需要恢复认证机制 +2. **认证**: 所有 API 端点使用 `get_current_user` 依赖进行用户认证 3. **同步机制**: 供应商和模型信息通过工厂模式从代码同步到数据库 4. **凭据管理**: 凭据加密存储,解密操作只在 Service 层进行 @@ -290,7 +292,6 @@ backend/app/ - [Repository 层文档](./repositories/MODEL.md) - [Model 层文档](./models/MODEL.md) - [Core 层文档](./core/model/MODEL.md) -- [Core 层详细文档](./core/model/README_CN.md) ## 未来改进 diff --git a/backend/app/api/v1/MODEL.md b/backend/app/api/v1/MODEL.md index 157f0195f..2f67306b3 100644 --- a/backend/app/api/v1/MODEL.md +++ b/backend/app/api/v1/MODEL.md @@ -50,6 +50,15 @@ - `workspaceId`: 工作空间ID(可选) - **返回**: 模型输出结果 +#### 5. 测试模型输出(流式) +- **端点**: `POST /api/v1/models/test-output-stream` +- **功能**: 以 SSE 流式方式测试指定模型的输出 +- **请求体**: + - `model_name`: 模型名称 + - `input`: 输入文本 + - `workspaceId`: 工作空间ID(可选) +- **返回**: SSE 事件流 + ### 模型供应商 API (`model_providers.py`) #### 1. 获取所有供应商列表 @@ -79,6 +88,11 @@ - 同步认证信息(从 .env 读取并同步到 model_credential 表,全局记录) - **返回**: 同步结果统计 +#### 4. 添加自定义供应商 +- **端点**: `POST /api/v1/model-providers/custom` +- **功能**: 一步创建自定义供应商(含 provider + credential + model_instance) +- **返回**: 创建结果 + ### 模型凭据 API (`model_credentials.py`) #### 1. 创建或更新凭据 @@ -140,7 +154,7 @@ Repository 层 (ModelInstanceRepository, ModelProviderRepository, ModelCredentia ## 注意事项 -1. **认证**: 当前代码中用户认证部分被注释,使用匿名用户ID,后续需要恢复认证机制 +1. **认证**: 所有 API 端点使用 `get_current_user` 依赖进行用户认证 2. **全局可见性**: 模型实例和凭据对所有用户和工作空间可见(user_id 和 workspace_id 为 NULL 的记录) 3. **凭据加密**: 所有凭据在存储前都会进行加密处理 4. **同步机制**: 供应商和模型信息通过工厂模式从代码同步到数据库 diff --git a/backend/app/api/v1/__init__.py b/backend/app/api/v1/__init__.py index 8bd3e1831..fee0c8d2a 100644 --- a/backend/app/api/v1/__init__.py +++ b/backend/app/api/v1/__init__.py @@ -6,17 +6,22 @@ from fastapi import APIRouter +from .agent_profiles import router as agent_profiles_router from .artifacts import router as artifacts_router from .auth import router as auth_router from .conversations import router as conversations_router from .custom_tools import router as custom_tools_router from .environment import router as environment_router +from .executions import router as executions_router from .files import router as files_router from .graph_code import router as graph_code_router from .graph_deployments import router as graph_deployments_router from .graphs import router as graphs_router from .mcp import router as mcp_router from .memory import router as memory_router +from .mission_comments import router as mission_comments_router +from .mission_execution import router as mission_execution_router +from .missions import router as missions_router from .model_credentials import router as model_credentials_router from .model_providers import router as model_providers_router from .model_usage import router as model_usage_router @@ -78,6 +83,11 @@ openclaw_proxy_router, openapi_graph_router, version_router, + missions_router, + executions_router, + agent_profiles_router, + mission_comments_router, + mission_execution_router, ] diff --git a/backend/app/api/v1/agent_profiles.py b/backend/app/api/v1/agent_profiles.py new file mode 100644 index 000000000..27b9bf9bc --- /dev/null +++ b/backend/app/api/v1/agent_profiles.py @@ -0,0 +1,140 @@ +"""Agent Profiles API.""" + +from __future__ import annotations + +import uuid + +from fastapi import APIRouter, Depends, Query +from sqlalchemy.ext.asyncio import AsyncSession + +from app.common.dependencies import CurrentUser, require_workspace_role +from app.common.exceptions import ForbiddenException +from app.core.database import get_db +from app.models.agent_profile import AgentProfile +from app.models.auth import AuthUser as User +from app.models.workspace import WorkspaceMemberRole +from app.schemas import BaseResponse +from app.schemas.execution import ( + AgentProfileListResponse, + AgentProfileSummary, + CreateAgentProfileRequest, + UpdateAgentProfileRequest, +) +from app.services.agent_profile_service import AgentProfileService +from app.services.workspace_permission import check_workspace_access + +router = APIRouter(prefix="/v1/agent-profiles", tags=["Agent Profiles"]) + + +def _to_summary(p: AgentProfile) -> AgentProfileSummary: + return AgentProfileSummary( + id=p.id, + workspace_id=p.workspace_id, + name=p.name, + runtime_type=p.runtime_type, + status=p.status.value if hasattr(p.status, "value") else str(p.status), + description=p.description, + avatar=p.avatar, + instructions=p.instructions, + skill_ids=p.skill_ids, + has_custom_env=bool(p.custom_env), + runtime_config=p.runtime_config, + visibility=p.visibility or "workspace", + max_concurrent_tasks=p.max_concurrent_tasks, + created_at=p.created_at, + updated_at=p.updated_at, + ) + + +@router.get("", response_model=BaseResponse[AgentProfileListResponse]) +async def list_agent_profiles( + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + status: str | None = Query(None), + runtime_type: str | None = Query(None), + limit: int = Query(100, ge=1, le=500), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[AgentProfileListResponse]: + service = AgentProfileService(db) + profiles = await service.list_profiles( + workspace_id=workspace_id, + status=status, + runtime_type=runtime_type, + limit=limit, + ) + return BaseResponse( + success=True, + code=200, + msg="ok", + data=AgentProfileListResponse(items=[_to_summary(p) for p in profiles]), + ) + + +@router.post("", response_model=BaseResponse[AgentProfileSummary]) +async def create_agent_profile( + request: CreateAgentProfileRequest, + current_user: CurrentUser, + db: AsyncSession = Depends(get_db), +) -> BaseResponse[AgentProfileSummary]: + has_access = await check_workspace_access(db, request.workspace_id, current_user, WorkspaceMemberRole.member) + if not has_access: + raise ForbiddenException("No access to workspace") + + service = AgentProfileService(db) + profile = await service.create_profile( + workspace_id=request.workspace_id, + name=request.name, + runtime_type=request.runtime_type, + description=request.description, + avatar=request.avatar, + instructions=request.instructions, + skill_ids=request.skill_ids, + custom_env=request.custom_env, + runtime_config=request.runtime_config, + max_concurrent_tasks=request.max_concurrent_tasks, + ) + return BaseResponse(success=True, code=200, msg="Agent profile created", data=_to_summary(profile)) + + +@router.get("/{profile_id}", response_model=BaseResponse[AgentProfileSummary]) +async def get_agent_profile( + profile_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[AgentProfileSummary]: + service = AgentProfileService(db) + profile = await service.get_profile(profile_id, workspace_id) + if not profile: + return BaseResponse(success=False, code=404, msg="Agent profile not found", data=None) + return BaseResponse(success=True, code=200, msg="ok", data=_to_summary(profile)) + + +@router.patch("/{profile_id}", response_model=BaseResponse[AgentProfileSummary]) +async def update_agent_profile( + profile_id: uuid.UUID, + request: UpdateAgentProfileRequest, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[AgentProfileSummary]: + service = AgentProfileService(db) + updates = request.model_dump(exclude_unset=True) + profile = await service.update_profile(profile_id, workspace_id, **updates) + if not profile: + return BaseResponse(success=False, code=404, msg="Agent profile not found", data=None) + return BaseResponse(success=True, code=200, msg="Agent profile updated", data=_to_summary(profile)) + + +@router.delete("/{profile_id}", response_model=BaseResponse) +async def delete_agent_profile( + profile_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse: + service = AgentProfileService(db) + deleted = await service.delete_profile(profile_id, workspace_id) + if not deleted: + return BaseResponse(success=False, code=404, msg="Agent profile not found", data=None) + return BaseResponse(success=True, code=200, msg="Agent profile deleted") diff --git a/backend/app/api/v1/executions.py b/backend/app/api/v1/executions.py new file mode 100644 index 000000000..34b45da76 --- /dev/null +++ b/backend/app/api/v1/executions.py @@ -0,0 +1,299 @@ +"""Executions API.""" + +from __future__ import annotations + +import uuid + +from fastapi import APIRouter, Depends, Query +from sqlalchemy.ext.asyncio import AsyncSession + +from app.common.dependencies import require_workspace_role +from app.common.exceptions import NotFoundException +from app.core.agent.cli_backends.base import build_control_response +from app.core.agent.cli_backends.session_registry import session_registry +from app.core.database import get_db +from app.models.auth import AuthUser as User +from app.models.execution import TERMINAL_EXECUTION_STATUSES, Execution, MissionExecutionStatus +from app.models.workspace import WorkspaceMemberRole +from app.schemas import BaseResponse +from app.schemas.execution import ( + ApproveActionRequest, + ExecutionEventResponse, + ExecutionEventsPageResponse, + ExecutionListResponse, + ExecutionSnapshotResponse, + ExecutionSummary, + InjectMessageRequest, +) +from app.services.execution_service import ExecutionService + +router = APIRouter(prefix="/v1/executions", tags=["Executions"]) + + +def _to_summary(e: Execution) -> ExecutionSummary: + return ExecutionSummary( + id=e.id, + workspace_id=e.workspace_id, + user_id=e.user_id, + source=e.source.value if hasattr(e.source, "value") else str(e.source), + status=e.status.value if hasattr(e.status, "value") else str(e.status), + title=e.title, + mission_id=e.mission_id, + agent_profile_id=e.agent_profile_id, + runtime_type=e.runtime_type, + container_id=e.container_id, + session_id=e.session_id, + started_at=e.started_at, + finished_at=e.finished_at, + last_seq=e.last_seq, + result_summary=e.result_summary, + error_code=e.error_code, + error_message=e.error_message, + created_at=e.created_at, + updated_at=e.updated_at, + ) + + +@router.get("", response_model=BaseResponse[ExecutionListResponse]) +async def list_executions( + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + status: str | None = Query(None), + source: str | None = Query(None), + mission_id: uuid.UUID | None = Query(None), + limit: int = Query(50, ge=1, le=200), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[ExecutionListResponse]: + service = ExecutionService(db) + executions = await service.list_executions( + workspace_id=workspace_id, + user_id=str(current_user.id), + status=status, + source=source, + mission_id=mission_id, + limit=limit, + ) + return BaseResponse( + success=True, + code=200, + msg="ok", + data=ExecutionListResponse(items=[_to_summary(e) for e in executions]), + ) + + +@router.get("/{execution_id}", response_model=BaseResponse[ExecutionSummary]) +async def get_execution( + execution_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[ExecutionSummary]: + service = ExecutionService(db) + execution = await service.get_execution(execution_id, str(current_user.id)) + if not execution: + return BaseResponse(success=False, code=404, msg="Execution not found", data=None) + if execution.workspace_id != workspace_id: + return BaseResponse(success=False, code=403, msg="Execution does not belong to this workspace", data=None) + return BaseResponse(success=True, code=200, msg="ok", data=_to_summary(execution)) + + +@router.get("/{execution_id}/children", response_model=BaseResponse[ExecutionListResponse]) +async def list_child_executions( + execution_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[ExecutionListResponse]: + """List child executions spawned by a coordinator.""" + service = ExecutionService(db) + # Verify the parent execution belongs to the user + parent = await service.get_execution(execution_id, str(current_user.id)) + if not parent: + return BaseResponse(success=False, code=404, msg="Execution not found", data=None) + if parent.workspace_id != workspace_id: + return BaseResponse(success=False, code=403, msg="Execution does not belong to this workspace", data=None) + children = await service.list_children(execution_id) + return BaseResponse( + success=True, + code=200, + msg="ok", + data=ExecutionListResponse(items=[_to_summary(e) for e in children]), + ) + + +@router.get("/{execution_id}/snapshot", response_model=BaseResponse[ExecutionSnapshotResponse]) +async def get_execution_snapshot( + execution_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[ExecutionSnapshotResponse]: + service = ExecutionService(db) + execution = await service.get_execution(execution_id, str(current_user.id)) + if not execution: + return BaseResponse(success=False, code=404, msg="Execution not found", data=None) + if execution.workspace_id != workspace_id: + return BaseResponse(success=False, code=403, msg="Execution does not belong to this workspace", data=None) + snapshot = await service.repo.get_snapshot(execution_id) + if not snapshot: + return BaseResponse(success=False, code=404, msg="Snapshot not found", data=None) + return BaseResponse( + success=True, + code=200, + msg="ok", + data=ExecutionSnapshotResponse( + execution_id=execution_id, + status=snapshot.status, + last_seq=snapshot.last_seq, + projection=snapshot.projection or {}, + ), + ) + + +@router.get("/{execution_id}/events", response_model=BaseResponse[ExecutionEventsPageResponse]) +async def get_execution_events( + execution_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + after_seq: int = Query(0, ge=0), + limit: int = Query(500, ge=1, le=1000), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[ExecutionEventsPageResponse]: + service = ExecutionService(db) + execution = await service.get_execution(execution_id, str(current_user.id)) + if not execution: + return BaseResponse(success=False, code=404, msg="Execution not found", data=None) + if execution.workspace_id != workspace_id: + return BaseResponse(success=False, code=403, msg="Execution does not belong to this workspace", data=None) + events = await service.list_events_after( + execution_id, + str(current_user.id), + after_seq=after_seq, + limit=limit, + ) + return BaseResponse( + success=True, + code=200, + msg="ok", + data=ExecutionEventsPageResponse( + execution_id=execution_id, + events=[ + ExecutionEventResponse( + seq=event.seq, + event_type=event.event_type, + payload=event.payload or {}, + created_at=event.created_at, + ) + for event in events + ], + next_after_seq=events[-1].seq if events else after_seq, + ), + ) + + +@router.post("/{execution_id}/cancel", response_model=BaseResponse[ExecutionSummary]) +async def cancel_execution( + execution_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[ExecutionSummary]: + from app.services.execution_lifecycle_service import ExecutionLifecycleService + + lifecycle = ExecutionLifecycleService(db) + execution = await lifecycle.cancel_execution(execution_id, str(current_user.id)) + if not execution: + return BaseResponse(success=False, code=404, msg="Execution not found", data=None) + if execution.workspace_id != workspace_id: + return BaseResponse(success=False, code=403, msg="Execution does not belong to this workspace", data=None) + if execution.status in TERMINAL_EXECUTION_STATUSES and execution.error_code != "cancelled": + return BaseResponse( + success=False, + code=409, + msg=f"Execution already in terminal state: {execution.status.value}", + data=_to_summary(execution), + ) + return BaseResponse(success=True, code=200, msg="Execution cancelled", data=_to_summary(execution)) + + +@router.post("/{execution_id}/message", response_model=BaseResponse) +async def inject_message( + execution_id: uuid.UUID, + request: InjectMessageRequest, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse: + """Inject a user message into a running execution.""" + session = session_registry.get(execution_id) + if not session: + raise NotFoundException("No active session for this execution") + + svc = ExecutionService(db) + execution = await svc.get_execution(execution_id, str(current_user.id)) + if not execution: + raise NotFoundException("Execution not found") + if execution.workspace_id != workspace_id: + return BaseResponse(success=False, code=403, msg="Execution does not belong to this workspace", data=None) + + await session.inject_message(request.message) + + await svc.append_event( + execution_id=execution_id, + event_type="user_message", + payload={"content": request.message}, + ) + + return BaseResponse(success=True, code=200, msg="Message injected") + + +@router.post("/{execution_id}/approve", response_model=BaseResponse) +async def approve_action( + execution_id: uuid.UUID, + request: ApproveActionRequest, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse: + """Approve or reject a pending approval request.""" + session = session_registry.get(execution_id) + if not session: + raise NotFoundException("No active session for this execution") + + svc = ExecutionService(db) + execution = await svc.get_execution(execution_id, str(current_user.id)) + if not execution: + raise NotFoundException("Execution not found") + if execution.workspace_id != workspace_id: + return BaseResponse(success=False, code=403, msg="Execution does not belong to this workspace", data=None) + + # Get request_id from the pending approval snapshot + snapshot = await svc.repo.get_snapshot(execution_id) + request_id = "" + if snapshot and snapshot.projection: + meta = snapshot.projection.get("meta", {}) + pending = meta.get("pending_approval", {}) + if isinstance(pending, dict): + request_id = pending.get("request_id", "") + + if request.approved: + await session.inject_message(build_control_response(request_id, "allow")) + await svc.append_event( + execution_id=execution_id, + event_type="approval_resolved", + payload={"decision": "approved", "request_id": request_id}, + ) + await svc.mark_status( + execution_id=execution_id, + status=MissionExecutionStatus.RUNNING, + ) + else: + await session.inject_message(build_control_response(request_id, "deny")) + await svc.append_event( + execution_id=execution_id, + event_type="approval_resolved", + payload={"decision": "rejected", "request_id": request_id}, + ) + # Keep running — the agent will decide how to handle the rejection + + return BaseResponse(success=True, code=200, msg="Action processed") diff --git a/backend/app/api/v1/mission_comments.py b/backend/app/api/v1/mission_comments.py new file mode 100644 index 000000000..2cee28299 --- /dev/null +++ b/backend/app/api/v1/mission_comments.py @@ -0,0 +1,162 @@ +"""Mission Comments API.""" + +from __future__ import annotations + +import uuid + +from fastapi import APIRouter, Depends, Query +from sqlalchemy.ext.asyncio import AsyncSession + +from app.common.dependencies import require_workspace_role +from app.core.database import get_db +from app.models.auth import AuthUser as User +from app.models.mission_comment import CommentAuthorType, CommentType +from app.models.workspace import WorkspaceMemberRole +from app.schemas import BaseResponse +from app.schemas.mission_comment import ( + CreateMissionCommentRequest, + MissionCommentListResponse, + MissionCommentResponse, + UpdateMissionCommentRequest, +) +from app.services.mission_comment_service import MissionCommentService +from app.websocket.notification_manager import NotificationType, notification_manager + +router = APIRouter(prefix="/v1/missions/{mission_id}/comments", tags=["Mission Comments"]) + + +@router.get("", response_model=BaseResponse[MissionCommentListResponse]) +async def list_comments( + mission_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + cursor: str | None = Query(None), + limit: int = Query(50, ge=1, le=200), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[MissionCommentListResponse]: + service = MissionCommentService(db) + comments, has_more, next_cursor = await service.list_comments( + mission_id=mission_id, + workspace_id=workspace_id, + cursor=cursor, + limit=limit, + ) + + return BaseResponse( + success=True, + code=200, + msg="ok", + data=MissionCommentListResponse( + items=[MissionCommentResponse.model_validate(c) for c in comments], + has_more=has_more, + next_cursor=next_cursor, + ), + ) + + +@router.post("", response_model=BaseResponse[MissionCommentResponse]) +async def create_comment( + mission_id: uuid.UUID, + request: CreateMissionCommentRequest, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[MissionCommentResponse]: + service = MissionCommentService(db) + comment, mission, should_dispatch, mentioned_agent_ids = await service.create_comment( + mission_id=mission_id, + workspace_id=workspace_id, + author_type=CommentAuthorType.MEMBER, + author_id=str(current_user.id), + content=request.content, + comment_type=CommentType.COMMENT, + parent_comment_id=request.parent_comment_id, + ) + + # Trigger executions via lifecycle service + if should_dispatch or mentioned_agent_ids: + from app.services.execution_lifecycle_service import ExecutionLifecycleService + + lifecycle = ExecutionLifecycleService(db) + if should_dispatch: + await lifecycle.dispatch_for_comment( + mission=mission, + trigger_comment=comment, + user_id=str(current_user.id), + ) + if mentioned_agent_ids: + await lifecycle.dispatch_for_mention( + mission=mission, + trigger_comment=comment, + user_id=str(current_user.id), + ) + + # Push notification to mission creator (if not the commenter) + if mission.creator_id != str(current_user.id): + await notification_manager.send_to_user( + mission.creator_id, + { + "type": NotificationType.MISSION_COMMENT_ADDED.value, + "mission_id": str(mission_id), + "comment_id": str(comment.id), + "author_type": comment.author_type.value, + "author_id": comment.author_id, + }, + ) + + return BaseResponse( + success=True, + code=200, + msg="Comment created", + data=MissionCommentResponse.model_validate(comment), + ) + + +@router.patch("/{comment_id}", response_model=BaseResponse[MissionCommentResponse]) +async def update_comment( + mission_id: uuid.UUID, + comment_id: uuid.UUID, + request: UpdateMissionCommentRequest, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[MissionCommentResponse]: + service = MissionCommentService(db) + comment = await service.update_comment( + comment_id=comment_id, + mission_id=mission_id, + workspace_id=workspace_id, + author_id=str(current_user.id), + content=request.content, + ) + + if not comment: + return BaseResponse(success=False, code=404, msg="Comment not found", data=None) + + return BaseResponse( + success=True, + code=200, + msg="Comment updated", + data=MissionCommentResponse.model_validate(comment), + ) + + +@router.delete("/{comment_id}", response_model=BaseResponse[None]) +async def delete_comment( + mission_id: uuid.UUID, + comment_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[None]: + service = MissionCommentService(db) + deleted = await service.delete_comment( + comment_id=comment_id, + mission_id=mission_id, + workspace_id=workspace_id, + author_id=str(current_user.id), + ) + + if not deleted: + return BaseResponse(success=False, code=404, msg="Comment not found", data=None) + return BaseResponse(success=True, code=200, msg="Comment deleted", data=None) diff --git a/backend/app/api/v1/mission_execution.py b/backend/app/api/v1/mission_execution.py new file mode 100644 index 000000000..186ae3d64 --- /dev/null +++ b/backend/app/api/v1/mission_execution.py @@ -0,0 +1,153 @@ +"""Mission-scoped execution endpoints — the frontend's primary interface.""" + +from __future__ import annotations + +import uuid + +from fastapi import APIRouter, Depends, Query +from sqlalchemy.ext.asyncio import AsyncSession + +from app.common.dependencies import require_workspace_role +from app.common.exceptions import NotFoundException +from app.core.agent.cli_backends.session_registry import session_registry +from app.core.database import get_db +from app.models.auth import AuthUser as User +from app.models.execution import MissionExecutionStatus +from app.models.workspace import WorkspaceMemberRole +from app.schemas import BaseResponse +from app.schemas.execution import ( + ApproveActionRequest, + ExecutionEventResponse, + ExecutionEventsPageResponse, + ExecutionSnapshotResponse, + InjectMessageRequest, +) +from app.services.execution_service import ExecutionService +from app.services.mission_service import MissionService + +router = APIRouter(prefix="/v1/missions/{mission_id}/execution", tags=["Mission Execution"]) + + +async def _get_current_execution_id( + mission_id: uuid.UUID, + workspace_id: uuid.UUID, + db: AsyncSession, +) -> uuid.UUID: + svc = MissionService(db) + mission = await svc.get_mission(mission_id, workspace_id) + if not mission or not mission.current_execution_id: + raise NotFoundException("No active execution for this mission") + return mission.current_execution_id + + +@router.post("/message", response_model=BaseResponse) +async def inject_message( + mission_id: uuid.UUID, + request: InjectMessageRequest, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse: + exec_id = await _get_current_execution_id(mission_id, workspace_id, db) + session = session_registry.get(exec_id) + if not session: + raise NotFoundException("Execution session not found") + + svc = ExecutionService(db) + await session.inject_message(request.message) + await svc.append_event( + execution_id=exec_id, + event_type="user_message", + payload={"content": request.message}, + ) + return BaseResponse(success=True, code=200, msg="Message injected") + + +@router.post("/approve", response_model=BaseResponse) +async def approve_action( + mission_id: uuid.UUID, + request: ApproveActionRequest, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse: + exec_id = await _get_current_execution_id(mission_id, workspace_id, db) + session = session_registry.get(exec_id) + if not session: + raise NotFoundException("Execution session not found") + + svc = ExecutionService(db) + snapshot = await svc.repo.get_snapshot(exec_id) + if not snapshot: + raise NotFoundException("Execution snapshot not found") + + from app.core.agent.cli_backends.base import build_control_response + + pending = (snapshot.projection or {}).get("meta", {}).get("pending_approval", {}) + request_id = pending.get("request_id", "") + + if request.approved: + await session.inject_message(build_control_response(request_id, "allow")) + await svc.append_event( + execution_id=exec_id, + event_type="approval_resolved", + payload={"decision": "approved"}, + ) + await svc.mark_status(execution_id=exec_id, status=MissionExecutionStatus.RUNNING) + else: + await session.inject_message(build_control_response(request_id, "deny")) + await svc.append_event( + execution_id=exec_id, + event_type="approval_resolved", + payload={"decision": "rejected"}, + ) + + return BaseResponse(success=True, code=200, msg="Action processed") + + +@router.get("/events", response_model=BaseResponse[ExecutionEventsPageResponse]) +async def get_events( + mission_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + after_seq: int = Query(0, ge=0), + limit: int = Query(500, ge=1, le=1000), + db: AsyncSession = Depends(get_db), +) -> BaseResponse: + exec_id = await _get_current_execution_id(mission_id, workspace_id, db) + svc = ExecutionService(db) + events = list(await svc.repo.list_events_after(exec_id, after_seq=after_seq, limit=limit)) + event_responses = [ + ExecutionEventResponse( + seq=e.seq, + event_type=e.event_type, + payload=e.payload, + created_at=e.created_at, + ) + for e in events + ] + return BaseResponse( + success=True, + code=200, + msg="ok", + data=ExecutionEventsPageResponse( + execution_id=exec_id, + events=event_responses, + next_after_seq=events[-1].seq if events else after_seq, + ), + ) + + +@router.get("/snapshot", response_model=BaseResponse[ExecutionSnapshotResponse]) +async def get_snapshot( + mission_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse: + exec_id = await _get_current_execution_id(mission_id, workspace_id, db) + svc = ExecutionService(db) + snapshot = await svc.repo.get_snapshot(exec_id) + if not snapshot: + raise NotFoundException("Snapshot not found") + return BaseResponse(success=True, code=200, msg="ok", data=snapshot) diff --git a/backend/app/api/v1/missions.py b/backend/app/api/v1/missions.py new file mode 100644 index 000000000..6aa0cc6d1 --- /dev/null +++ b/backend/app/api/v1/missions.py @@ -0,0 +1,205 @@ +"""Missions API.""" + +from __future__ import annotations + +import uuid + +from fastapi import APIRouter, Depends, Query +from sqlalchemy.ext.asyncio import AsyncSession + +from app.common.dependencies import CurrentUser, require_workspace_role +from app.common.exceptions import BadRequestException, ForbiddenException +from app.core.database import get_db +from app.models.auth import AuthUser as User +from app.models.mission import Mission, MissionPriority +from app.models.workspace import WorkspaceMemberRole +from app.schemas import BaseResponse +from app.schemas.execution import ( + AssignMissionRequest, + CreateMissionRequest, + DispatchMissionRequest, + MissionListResponse, + MissionSummary, + UpdateMissionRequest, +) +from app.services.mission_service import MissionService +from app.services.workspace_permission import check_workspace_access + +router = APIRouter(prefix="/v1/missions", tags=["Missions"]) + + +def _to_summary(m: Mission) -> MissionSummary: + return MissionSummary( + id=m.id, + workspace_id=m.workspace_id, + title=m.title, + description=m.description, + objective=m.objective, + status=m.status.value if hasattr(m.status, "value") else str(m.status), + priority=m.priority.value if hasattr(m.priority, "value") else str(m.priority), + assignee_type=m.assignee_type, + assignee_id=m.assignee_id, + creator_id=m.creator_id, + current_execution_id=m.current_execution_id, + parent_mission_id=m.parent_mission_id, + tags=m.tags, + position=m.position, + auto_approve=m.auto_approve, + due_date=m.due_date, + created_at=m.created_at, + updated_at=m.updated_at, + ) + + +@router.get("", response_model=BaseResponse[MissionListResponse]) +async def list_missions( + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + status: str | None = Query(None), + parent_mission_id: uuid.UUID | None = Query(None), + assignee_id: uuid.UUID | None = Query(None), + limit: int = Query(50, ge=1, le=200), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[MissionListResponse]: + service = MissionService(db) + missions = await service.list_missions( + workspace_id=workspace_id, + status=status, + parent_mission_id=parent_mission_id, + assignee_id=assignee_id, + limit=limit, + ) + return BaseResponse( + success=True, + code=200, + msg="ok", + data=MissionListResponse(items=[_to_summary(m) for m in missions]), + ) + + +@router.post("", response_model=BaseResponse[MissionSummary]) +async def create_mission( + request: CreateMissionRequest, + current_user: CurrentUser, + db: AsyncSession = Depends(get_db), +) -> BaseResponse[MissionSummary]: + service = MissionService(db) + + try: + priority = MissionPriority(request.priority) + except ValueError: + raise BadRequestException(f"Invalid priority: {request.priority}") + + has_access = await check_workspace_access(db, request.workspace_id, current_user, WorkspaceMemberRole.member) + if not has_access: + raise ForbiddenException("No access to workspace") + + mission = await service.create_mission( + workspace_id=request.workspace_id, + creator_id=str(current_user.id), + title=request.title, + description=request.description, + objective=request.objective, + priority=priority, + parent_mission_id=request.parent_mission_id, + tags=request.tags, + position=request.position, + auto_approve=request.auto_approve, + ) + return BaseResponse(success=True, code=200, msg="Mission created", data=_to_summary(mission)) + + +@router.get("/meta/transitions", response_model=BaseResponse) +async def get_transitions( + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), +) -> BaseResponse: + return BaseResponse( + success=True, + code=200, + msg="ok", + data=MissionService.get_transitions(), + ) + + +@router.get("/{mission_id}", response_model=BaseResponse[MissionSummary]) +async def get_mission( + mission_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.viewer), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[MissionSummary]: + service = MissionService(db) + mission = await service.get_mission(mission_id, workspace_id) + if not mission: + return BaseResponse(success=False, code=404, msg="Mission not found", data=None) + return BaseResponse(success=True, code=200, msg="ok", data=_to_summary(mission)) + + +@router.patch("/{mission_id}", response_model=BaseResponse[MissionSummary]) +async def update_mission( + mission_id: uuid.UUID, + request: UpdateMissionRequest, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[MissionSummary]: + service = MissionService(db) + updates = request.model_dump(exclude_unset=True) + mission = await service.update_mission(mission_id, workspace_id, **updates) + if not mission: + return BaseResponse(success=False, code=404, msg="Mission not found", data=None) + return BaseResponse(success=True, code=200, msg="Mission updated", data=_to_summary(mission)) + + +@router.post("/{mission_id}/assign", response_model=BaseResponse[MissionSummary]) +async def assign_mission( + mission_id: uuid.UUID, + request: AssignMissionRequest, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[MissionSummary]: + service = MissionService(db) + mission = await service.assign_to_agent( + mission_id=mission_id, + workspace_id=workspace_id, + agent_profile_id=request.agent_profile_id, + ) + return BaseResponse(success=True, code=200, msg="Mission assigned", data=_to_summary(mission)) + + +@router.post("/{mission_id}/dispatch", response_model=BaseResponse[MissionSummary]) +async def dispatch_mission( + mission_id: uuid.UUID, + request: DispatchMissionRequest, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[MissionSummary]: + from app.services.execution_lifecycle_service import ExecutionLifecycleService + + lifecycle = ExecutionLifecycleService(db) + mission, _execution = await lifecycle.dispatch_mission( + mission_id=mission_id, + workspace_id=workspace_id, + user_id=str(current_user.id), + runtime_config=request.runtime_config, + ) + return BaseResponse(success=True, code=200, msg="Mission dispatched", data=_to_summary(mission)) + + +@router.post("/{mission_id}/cancel", response_model=BaseResponse[MissionSummary]) +async def cancel_mission( + mission_id: uuid.UUID, + current_user: User = require_workspace_role(WorkspaceMemberRole.member), + workspace_id: uuid.UUID = Query(...), + db: AsyncSession = Depends(get_db), +) -> BaseResponse[MissionSummary]: + from app.services.execution_lifecycle_service import ExecutionLifecycleService + + lifecycle = ExecutionLifecycleService(db) + mission = await lifecycle.cancel_mission(mission_id=mission_id, workspace_id=workspace_id) + if not mission: + return BaseResponse(success=False, code=404, msg="Mission not found", data=None) + return BaseResponse(success=True, code=200, msg="Mission cancelled", data=_to_summary(mission)) diff --git a/backend/app/api/v1/openclaw_proxy.py b/backend/app/api/v1/openclaw_proxy.py index b2b36ca66..a3f1dcece 100644 --- a/backend/app/api/v1/openclaw_proxy.py +++ b/backend/app/api/v1/openclaw_proxy.py @@ -26,6 +26,7 @@ from app.models.auth import AuthUser as User from app.models.enums import InstanceStatus from app.services.openclaw_instance_service import OpenClawInstanceService +from app.utils.safe_task import safe_create_task router = APIRouter(prefix="/v1/openclaw/proxy", tags=["OpenClaw Proxy"]) @@ -134,7 +135,10 @@ async def proxy_to_openclaw( # Auto device pair: wait for the client to connect WebSocket and then approve if is_entry and instance.container_id: - asyncio.create_task(_poll_approve_devices(instance.container_id)) + safe_create_task( + _poll_approve_devices(instance.container_id), + name=f"device-approve-{instance.container_id[:12]}", + ) query_params = {k: v for k, v in parse_qs(request.url.query).items()} if is_entry: diff --git a/backend/app/api/v1/skills.py b/backend/app/api/v1/skills.py index 4d23dd4b5..c775dac4e 100644 --- a/backend/app/api/v1/skills.py +++ b/backend/app/api/v1/skills.py @@ -25,15 +25,23 @@ ) from app.services.openclaw_instance_service import OpenClawInstanceService from app.services.skill_service import SkillService +from app.utils.safe_task import safe_create_task -async def _trigger_openclaw_skill_sync(user_id: str, db: AsyncSession): - """Trigger a sync of skills to the user's OpenClaw container if it is running.""" +async def _trigger_openclaw_skill_sync(user_id: str): + """Trigger a sync of skills to the user's OpenClaw container if it is running. + + Uses its own DB session since this runs as a background task after the + request-scoped session is closed. + """ + from app.core.database import AsyncSessionLocal + try: - instance_service = OpenClawInstanceService(db) - instance = await instance_service.get_instance_by_user(user_id) - if instance and instance.container_id and instance.status == InstanceStatus.RUNNING: - await instance_service.sync_skills_to_container(user_id, instance.container_id) + async with AsyncSessionLocal() as db: + instance_service = OpenClawInstanceService(db) + instance = await instance_service.get_instance_by_user(user_id) + if instance and instance.container_id and instance.status == InstanceStatus.RUNNING: + await instance_service.sync_skills_to_container(user_id, instance.container_id) except Exception as e: logger.error(f"Failed to trigger openclaw skill sync for user {user_id}: {e}", exc_info=True) @@ -94,9 +102,7 @@ async def create_skill( skill = await service.get_skill(skill.id, current_user.id) # Trigger sync to OpenClaw container - import asyncio - - asyncio.create_task(_trigger_openclaw_skill_sync(current_user.id, db)) + safe_create_task(_trigger_openclaw_skill_sync(current_user.id)) return { "success": True, @@ -154,9 +160,7 @@ async def update_skill( skill = await service.get_skill(skill.id, current_user.id) # Trigger sync to OpenClaw container - import asyncio - - asyncio.create_task(_trigger_openclaw_skill_sync(current_user.id, db)) + safe_create_task(_trigger_openclaw_skill_sync(current_user.id)) return { "success": True, @@ -187,25 +191,22 @@ async def delete_skill( if skill_name: # Trigger incremental sync to OpenClaw container async def _delete_from_container(): + from app.core.database import AsyncSessionLocal + try: - from app.services.openclaw_instance_service import OpenClawInstanceService - - instance_service = OpenClawInstanceService(db) - instance = await instance_service.get_instance_by_user(current_user.id) - if instance and instance.container_id and instance.status == InstanceStatus.RUNNING: - await instance_service.delete_skill_from_container( - current_user.id, instance.container_id, skill_name - ) + async with AsyncSessionLocal() as bg_db: + instance_service = OpenClawInstanceService(bg_db) + instance = await instance_service.get_instance_by_user(current_user.id) + if instance and instance.container_id and instance.status == InstanceStatus.RUNNING: + await instance_service.delete_skill_from_container( + current_user.id, instance.container_id, skill_name + ) except Exception as e: - from loguru import logger - logger.error( f"Failed to delete skill {skill_name} from container for user {current_user.id}: {e}", exc_info=True ) - import asyncio - - asyncio.create_task(_delete_from_container()) + safe_create_task(_delete_from_container()) return {"success": True} @@ -232,9 +233,7 @@ async def add_file( ) # Trigger sync to OpenClaw container - import asyncio - - asyncio.create_task(_trigger_openclaw_skill_sync(current_user.id, db)) + safe_create_task(_trigger_openclaw_skill_sync(current_user.id)) return { "success": True, @@ -253,9 +252,7 @@ async def delete_file( await service.delete_file(file_id, current_user.id) # Trigger sync to OpenClaw container - import asyncio - - asyncio.create_task(_trigger_openclaw_skill_sync(current_user.id, db)) + safe_create_task(_trigger_openclaw_skill_sync(current_user.id)) return {"success": True} @@ -278,9 +275,7 @@ async def update_file( ) # Trigger sync to OpenClaw container - import asyncio - - asyncio.create_task(_trigger_openclaw_skill_sync(current_user.id, db)) + safe_create_task(_trigger_openclaw_skill_sync(current_user.id)) return { "success": True, diff --git a/backend/app/common/exceptions.py b/backend/app/common/exceptions.py index 5a4dfbc12..e200938a1 100644 --- a/backend/app/common/exceptions.py +++ b/backend/app/common/exceptions.py @@ -232,13 +232,29 @@ async def request_validation_exception_handler(request: Request, exc: Exception) async def general_exception_handler(request: Request, exc: Exception) -> Response: - """Handle uncaught exceptions (500).""" + """Handle uncaught exceptions — auto-translate common service-layer exceptions.""" + + # ValueError → 400 (or 404 if message says "not found") + if isinstance(exc, ValueError): + msg = str(exc) + if "not found" in msg.lower(): + return await app_exception_handler(request, NotFoundException(msg)) + return await app_exception_handler(request, BadRequestException(msg)) + + # PermissionError → 403 + if isinstance(exc, PermissionError): + return await app_exception_handler(request, ForbiddenException(str(exc))) + + # RuntimeError → 400 (service-layer operational errors) + if isinstance(exc, RuntimeError): + return await app_exception_handler(request, BadRequestException(str(exc))) + + # Truly unexpected — 500 try: from loguru import logger logger.exception("Unhandled exception: {}", exc) except Exception: - # fallback when logger is unavailable pass debug = False @@ -267,6 +283,9 @@ def register_exception_handlers(app: Any) -> None: app.add_exception_handler(HTTPException, http_exception_handler) app.add_exception_handler(RequestValidationError, request_validation_exception_handler) app.add_exception_handler(PydanticValidationError, request_validation_exception_handler) + app.add_exception_handler(ValueError, general_exception_handler) + app.add_exception_handler(PermissionError, general_exception_handler) + app.add_exception_handler(RuntimeError, general_exception_handler) app.add_exception_handler(Exception, general_exception_handler) diff --git a/backend/app/common/logging.py b/backend/app/common/logging.py index c208194c1..433a9a8be 100644 --- a/backend/app/common/logging.py +++ b/backend/app/common/logging.py @@ -8,11 +8,9 @@ import logging import os import time -from collections.abc import Callable -from fastapi import Request, Response from loguru import logger -from starlette.middleware.base import BaseHTTPMiddleware +from starlette.types import ASGIApp, Message, Receive, Scope, Send from app.core.trace_context import get_trace_id, set_trace_id @@ -35,45 +33,65 @@ def emit(self, record): logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage()) -class LoggingMiddleware(BaseHTTPMiddleware): - """HTTP request logging middleware.""" +class LoggingMiddleware: + """Pure ASGI logging middleware (avoids BaseHTTPMiddleware re-raise issues).""" + + def __init__(self, app: ASGIApp) -> None: + self.app = app + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] != "http": + await self.app(scope, receive, send) + return - async def dispatch(self, request: Request, call_next: Callable) -> Response: - """Process the request and log details.""" start_time = time.time() - method = request.method - path = request.url.path - client_host = request.client.host if request.client else "unknown" + method = scope.get("method", "-") + path = scope.get("path", "-") + client = scope.get("client") + client_host = client[0] if client else "unknown" + + request_id = None + for key, value in scope.get("headers", []): + if key == b"x-request-id": + request_id = value.decode() + break + trace_id = set_trace_id(request_id) - trace_id = set_trace_id(request.headers.get("X-Request-ID") or None) - request.state.trace_id = trace_id log = logger.bind(trace_id=trace_id, method=method, path=path, client=client_host) - log.info("request.start") - try: - response = await call_next(request) - - process_time = time.time() - start_time - status_code = response.status_code - message = f"request.completed status={status_code} duration={process_time:.3f}s" - - if status_code >= 500: - log.error(message) - elif status_code >= 400: - log.warning(message) - else: - log.info(message) - - response.headers["X-Process-Time"] = str(process_time) - response.headers["X-Trace-Id"] = trace_id - return response + status_code = 500 + response_process_time = 0.0 + + async def send_wrapper(message: Message) -> None: + nonlocal status_code, response_process_time + if message["type"] == "http.response.start": + status_code = message["status"] + response_process_time = time.time() - start_time + if "headers" not in message: + message["headers"] = [] + message["headers"] = list(message["headers"]) + [ + [b"x-process-time", str(response_process_time).encode()], + [b"x-trace-id", trace_id.encode()], + ] + await send(message) + try: + await self.app(scope, receive, send_wrapper) except Exception as e: process_time = time.time() - start_time log.opt(exception=True).error(f"request.failed duration={process_time:.3f}s error={type(e).__name__}") raise + process_time = response_process_time or (time.time() - start_time) + message = f"request.completed status={status_code} duration={process_time:.3f}s" + if status_code >= 500: + log.error(message) + elif status_code >= 400: + log.warning(message) + else: + log.info(message) + def setup_logging(): """ diff --git a/backend/app/core/agent/backends/pydantic_adapter.py b/backend/app/core/agent/backends/pydantic_adapter.py index ea523b370..b530bb833 100644 --- a/backend/app/core/agent/backends/pydantic_adapter.py +++ b/backend/app/core/agent/backends/pydantic_adapter.py @@ -44,6 +44,7 @@ list_builtin_runtimes, resolve_runtime, ) +from app.core.agent.backends.utils.command_executor import DANGEROUS_RE from app.utils.backend_utils import create_execute_response # Re-export for backward compatibility @@ -368,23 +369,6 @@ def start(self) -> None: logger.error(f"Failed to start sandbox {self._id}: {e}") raise RuntimeError(f"Failed to start sandbox {self._id}: {e}") from e - # Dangerous command patterns (defense-in-depth, not sole security boundary) - _DANGEROUS_PATTERNS = [ - r"rm\s+-rf\s+/\s*$", # rm -rf / - r"mkfs\.", # format disk - r"dd\s+.*of=/dev/", # write to device - r":\(\)\s*\{", # fork bomb :(){ :|:& };: - ] - _DANGEROUS_RE = None # Lazy-compiled combined regex - - @classmethod - def _get_dangerous_re(cls): - if cls._DANGEROUS_RE is None: - import re - - cls._DANGEROUS_RE = re.compile("|".join(f"(?:{p})" for p in cls._DANGEROUS_PATTERNS)) - return cls._DANGEROUS_RE - def _exec_command(self, command: str) -> tuple[str, int]: """Execute command in sandbox with safety checks. @@ -394,7 +378,7 @@ def _exec_command(self, command: str) -> tuple[str, int]: Returns: Tuple of (output, exit_code) """ - if self._get_dangerous_re().search(command): + if DANGEROUS_RE.search(command): logger.warning(f"[{self._id}] Blocked dangerous command: {command[:100]}") return "Error: command blocked by security policy", 1 diff --git a/backend/app/core/agent/backends/utils/command_executor.py b/backend/app/core/agent/backends/utils/command_executor.py index 6195772db..7f6c48c4c 100644 --- a/backend/app/core/agent/backends/utils/command_executor.py +++ b/backend/app/core/agent/backends/utils/command_executor.py @@ -10,6 +10,7 @@ - Output truncation support """ +import re import subprocess from typing import Optional @@ -21,6 +22,16 @@ ) from app.utils.backend_utils import create_execute_response +# Shared denylist for obviously destructive commands. +# Defense-in-depth — shell=True is kept for LLM agent pipe/redirect support. +DANGEROUS_PATTERNS = [ + r"rm\s+-rf\s+/\s*$", # rm -rf / + r"mkfs\.", # format disk + r"dd\s+.*of=/dev/", # write to device + r":\(\)\s*\{", # fork bomb :(){ :|:& };: +] +DANGEROUS_RE = re.compile("|".join(f"(?:{p})" for p in DANGEROUS_PATTERNS)) + def combine_stdout_stderr(stdout: Optional[str], stderr: Optional[str]) -> str: """Combine stdout and stderr into a single output string. @@ -106,6 +117,9 @@ def execute_local_command( total 0 ... """ + if DANGEROUS_RE.search(command): + return create_error_response("Command blocked by security policy") + try: result = subprocess.run( command, diff --git a/backend/app/core/agent/cli_backends/__init__.py b/backend/app/core/agent/cli_backends/__init__.py new file mode 100644 index 000000000..e648e1f7e --- /dev/null +++ b/backend/app/core/agent/cli_backends/__init__.py @@ -0,0 +1,13 @@ +from .base import CLIMessage, CLIResult, RuntimeProvider, RuntimeSession +from .registry import RuntimeProviderRegistry +from .session_registry import SessionRegistry, session_registry + +__all__ = [ + "CLIMessage", + "CLIResult", + "RuntimeProvider", + "RuntimeSession", + "RuntimeProviderRegistry", + "SessionRegistry", + "session_registry", +] diff --git a/backend/app/core/agent/cli_backends/base.py b/backend/app/core/agent/cli_backends/base.py new file mode 100644 index 000000000..3ce1e76a1 --- /dev/null +++ b/backend/app/core/agent/cli_backends/base.py @@ -0,0 +1,82 @@ +from __future__ import annotations + +import asyncio +import json +from dataclasses import dataclass +from typing import AsyncIterator, Awaitable, Callable, Protocol + + +@dataclass +class CLIMessage: + type: str # "text" | "thinking" | "tool_use" | "tool_result" | "error" | "artifact" | "approval_request" + content: str = "" + tool: str = "" + call_id: str = "" + input: dict | None = None + output: str = "" + + +def build_control_response(request_id: str, behavior: str) -> str: + return json.dumps( + { + "type": "control_response", + "response": { + "subtype": "success", + "request_id": request_id, + "response": {"behavior": behavior}, + }, + } + ) + + +@dataclass +class CLIResult: + status: str # "completed" | "failed" | "timeout" | "blocked" + output: str = "" + error: str = "" + session_id: str = "" + branch_name: str = "" + usage: dict | None = None + + +@dataclass +class RuntimeSession: + messages: asyncio.Queue[CLIMessage | None] + result: asyncio.Future[CLIResult] + _inject_fn: Callable[[str], Awaitable[None]] | None = None + _cancel_fn: Callable[[], Awaitable[None]] | None = None + _drain_task: asyncio.Task | None = None + + async def inject_message(self, message: str) -> None: + if self._inject_fn: + await self._inject_fn(message) + + async def cancel(self) -> None: + if self._cancel_fn: + await self._cancel_fn() + if self._drain_task: + self._drain_task.cancel() + + async def iter_messages(self) -> AsyncIterator[CLIMessage]: + while True: + msg = await self.messages.get() + if msg is None: + break + yield msg + + +class RuntimeProvider(Protocol): + provider_type: str + + async def execute( + self, + prompt: str, + *, + container_id: str, + cwd: str | None = None, + model: str | None = None, + timeout: int = 7200, + resume_session_id: str | None = None, + env: dict[str, str] | None = None, + auto_approve: bool = True, + ) -> RuntimeSession: ... diff --git a/backend/app/core/agent/cli_backends/claude_code.py b/backend/app/core/agent/cli_backends/claude_code.py new file mode 100644 index 000000000..aabc26851 --- /dev/null +++ b/backend/app/core/agent/cli_backends/claude_code.py @@ -0,0 +1,236 @@ +from __future__ import annotations + +import asyncio +import json + +from loguru import logger + +from .base import CLIMessage, CLIResult, RuntimeSession +from .container_bridge import ContainerProcessBridge + + +class ClaudeCodeProvider: + provider_type = "claude_code" + + def __init__(self, executable_path: str = "claude"): + self.executable_path = executable_path + self.bridge = ContainerProcessBridge() + + async def execute( + self, + prompt: str, + *, + container_id: str, + cwd: str | None = None, + model: str | None = None, + timeout: int = 7200, + resume_session_id: str | None = None, + env: dict[str, str] | None = None, + auto_approve: bool = True, + ) -> RuntimeSession: + cmd = [ + self.executable_path, + "-p", + "--output-format", + "stream-json", + "--input-format", + "stream-json", + "--verbose", + "--max-turns", + "200", + "--permission-mode", + "bypassPermissions" if auto_approve else "default", + ] + if model: + cmd.extend(["--model", model]) + if resume_session_id: + cmd.extend(["--resume", resume_session_id]) + + process = await self.bridge.exec_streaming( + container_id, + cmd, + env=env, + workdir=cwd, + ) + logger.info(f"[claude] docker exec started for container {container_id[:12]}, pid={process.pid}") + + # Send the initial prompt via stdin as stream-json (not --print) + if not resume_session_id and process.stdin: + user_msg = json.dumps( + { + "type": "user", + "message": { + "role": "user", + "content": [{"type": "text", "text": prompt}], + }, + } + ) + process.stdin.write(f"{user_msg}\n".encode()) + await process.stdin.drain() + logger.info(f"[claude] Sent initial prompt via stdin ({len(prompt)} chars)") + + queue: asyncio.Queue[CLIMessage | None] = asyncio.Queue(maxsize=512) + loop = asyncio.get_event_loop() + result_future: asyncio.Future[CLIResult] = loop.create_future() + + drain_task = asyncio.create_task( + self._drain(process, queue, result_future, timeout), + name=f"claude-drain-{container_id[:12]}", + ) + + async def inject(message: str) -> None: + if process.stdin and not process.stdin.is_closing(): + process.stdin.write(f"{message}\n".encode()) + await process.stdin.drain() + + async def cancel() -> None: + process.terminate() + + return RuntimeSession( + messages=queue, + result=result_future, + _inject_fn=inject, + _cancel_fn=cancel, + _drain_task=drain_task, + ) + + async def _drain( + self, + process: asyncio.subprocess.Process, + queue: asyncio.Queue[CLIMessage | None], + result_future: asyncio.Future[CLIResult], + timeout: int, + ) -> None: + accumulated_text: list[str] = [] + session_id = "" + usage: dict = {} + is_error = False + + try: + async with asyncio.timeout(timeout): + assert process.stdout is not None + logger.info("[claude] Drain loop started, reading stdout...") + async for raw_line in process.stdout: + line = raw_line.decode().strip() + if not line: + continue + try: + event = json.loads(line) + except json.JSONDecodeError: + logger.warning(f"[claude] Non-JSON line from stdout: {line[:200]}") + continue + + if not isinstance(event, dict): + continue + + event_type = event.get("type", "unknown") + logger.info(f"[claude] Received event: type={event_type}") + + for msg in self._parse_event(event): + if msg.type == "text": + accumulated_text.append(msg.content) + await queue.put(msg) + + if event.get("type") == "result": + result_data = event.get("result", {}) + if isinstance(result_data, dict): + session_id = result_data.get("session_id", "") + if "usage" in event: + usage = event["usage"] + if event.get("is_error"): + is_error = True + # result received — close stdin so the process exits cleanly + if process.stdin and not process.stdin.is_closing(): + process.stdin.close() + break + + except TimeoutError: + if not result_future.done(): + result_future.set_result(CLIResult(status="timeout", error="Agent timed out")) + except Exception as e: + logger.error(f"Claude drain error: {e}") + if not result_future.done(): + result_future.set_result(CLIResult(status="failed", error=str(e))) + finally: + if not result_future.done(): + exit_code = await process.wait() + if is_error: + result_future.set_result( + CLIResult( + status="failed", + output="\n".join(accumulated_text), + error="\n".join(accumulated_text) or "Claude Code reported an error", + session_id=session_id, + usage=usage, + ) + ) + elif exit_code == 0 or accumulated_text: + result_future.set_result( + CLIResult( + status="completed", + output="\n".join(accumulated_text), + session_id=session_id, + usage=usage, + ) + ) + else: + stderr_bytes = await process.stderr.read() if process.stderr else b"" + result_future.set_result( + CLIResult( + status="failed", + error=f"Exit code {exit_code}: {stderr_bytes.decode()[:2000]}", + usage=usage, + ) + ) + await queue.put(None) + + def _parse_event(self, event: dict) -> list[CLIMessage]: + messages: list[CLIMessage] = [] + event_type = event.get("type", "") + + if event_type == "assistant" and "message" in event: + msg = event["message"] + for block in msg.get("content", []) if isinstance(msg, dict) else []: + if isinstance(block, str): + messages.append(CLIMessage(type="text", content=block)) + continue + if not isinstance(block, dict): + continue + block_type = block.get("type", "") + if block_type == "text": + messages.append(CLIMessage(type="text", content=block.get("text", ""))) + elif block_type == "tool_use": + messages.append( + CLIMessage( + type="tool_use", + tool=block.get("name", ""), + call_id=block.get("id", ""), + input=block.get("input"), + ) + ) + elif block_type == "thinking": + messages.append(CLIMessage(type="thinking", content=block.get("thinking", ""))) + + elif event_type == "tool_result": + messages.append( + CLIMessage( + type="tool_result", + tool=event.get("tool", ""), + call_id=event.get("call_id", ""), + output=str(event.get("output", ""))[:8192], + ) + ) + + elif event_type == "control_request": + request = event.get("request", {}) + messages.append( + CLIMessage( + type="approval_request", + tool=request.get("tool_name", ""), + call_id=event.get("request_id", ""), + input=request.get("input"), + content=request.get("subtype", ""), + ) + ) + + return messages diff --git a/backend/app/core/agent/cli_backends/codex.py b/backend/app/core/agent/cli_backends/codex.py new file mode 100644 index 000000000..e1817f9b7 --- /dev/null +++ b/backend/app/core/agent/cli_backends/codex.py @@ -0,0 +1,459 @@ +from __future__ import annotations + +import asyncio +import json + +from loguru import logger + +from app.utils.safe_task import safe_create_task + +from .base import CLIMessage, CLIResult, RuntimeSession +from .container_bridge import ContainerProcessBridge + + +class CodexProvider: + """Runtime provider for OpenAI Codex CLI. + + Codex uses JSON-RPC 2.0 over stdio. We spawn ``codex app-server --listen + stdio://``, perform the initialize / thread/start / turn/start handshake, + then read NDJSON lines from stdout. Each line is either: + + * A *response* (has ``id`` + ``result`` or ``error``) — matched to a + pending request. + * A *server request* (has ``id`` + ``method``) — auto-approved. + * A *notification* (has ``method``, no ``id``) — mapped to CLIMessage. + """ + + provider_type = "codex" + + def __init__(self, executable_path: str = "codex") -> None: + self.executable_path = executable_path + self.bridge = ContainerProcessBridge() + + # ── public API ────────────────────────────────────────────────────── + + async def execute( + self, + prompt: str, + *, + container_id: str, + cwd: str | None = None, + model: str | None = None, + timeout: int = 7200, + resume_session_id: str | None = None, + env: dict[str, str] | None = None, + auto_approve: bool = True, + ) -> RuntimeSession: + cmd = [self.executable_path, "app-server", "--listen", "stdio://"] + + process = await self.bridge.exec_streaming( + container_id, + cmd, + env=env, + workdir=cwd, + ) + + queue: asyncio.Queue[CLIMessage | None] = asyncio.Queue(maxsize=512) + loop = asyncio.get_event_loop() + result_future: asyncio.Future[CLIResult] = loop.create_future() + + drain_task = asyncio.create_task( + self._drain(process, queue, result_future, prompt, model, timeout), + name=f"codex-drain-{container_id[:12]}", + ) + + async def inject(message: str) -> None: + if process.stdin and not process.stdin.is_closing(): + process.stdin.write(f"{message}\n".encode()) + await process.stdin.drain() + + async def cancel() -> None: + process.terminate() + + return RuntimeSession( + messages=queue, + result=result_future, + _inject_fn=inject, + _cancel_fn=cancel, + _drain_task=drain_task, + ) + + # ── JSON-RPC helpers ──────────────────────────────────────────────── + + _next_id: int = 0 + + async def _rpc_request( + self, + process: asyncio.subprocess.Process, + method: str, + params: dict, + ) -> dict: + """Send a JSON-RPC request and wait for the matching response.""" + self._next_id += 1 + req_id = self._next_id + msg = {"jsonrpc": "2.0", "id": req_id, "method": method, "params": params} + line = json.dumps(msg) + "\n" + assert process.stdin is not None + process.stdin.write(line.encode()) + await process.stdin.drain() + return {"_pending_id": req_id} + + async def _rpc_notify( + self, + process: asyncio.subprocess.Process, + method: str, + ) -> None: + msg = {"jsonrpc": "2.0", "method": method} + line = json.dumps(msg) + "\n" + assert process.stdin is not None + process.stdin.write(line.encode()) + await process.stdin.drain() + + async def _rpc_respond( + self, + process: asyncio.subprocess.Process, + req_id: int, + result: dict, + ) -> None: + msg = {"jsonrpc": "2.0", "id": req_id, "result": result} + line = json.dumps(msg) + "\n" + assert process.stdin is not None + process.stdin.write(line.encode()) + await process.stdin.drain() + + # ── drain loop ────────────────────────────────────────────────────── + + async def _drain( + self, + process: asyncio.subprocess.Process, + queue: asyncio.Queue[CLIMessage | None], + result_future: asyncio.Future[CLIResult], + prompt: str, + model: str | None, + timeout: int, + ) -> None: + accumulated_text: list[str] = [] + pending: dict[int, asyncio.Future[dict]] = {} + turn_done: asyncio.Future[bool] = asyncio.get_event_loop().create_future() + + async def wait_response(req_id: int) -> dict: + """Register a pending request and wait for its response.""" + fut: asyncio.Future[dict] = asyncio.get_event_loop().create_future() + pending[req_id] = fut + return await fut + + def handle_line(line: str) -> None: + """Route a single JSON-RPC line.""" + try: + raw = json.loads(line) + except json.JSONDecodeError: + return + if not isinstance(raw, dict): + return + + has_id = "id" in raw + + # Response to our request + if has_id and ("result" in raw or "error" in raw): + req_id = raw.get("id") + if req_id in pending and not pending[req_id].done(): + if "error" in raw: + pending[req_id].set_exception(RuntimeError(f"RPC error: {raw['error']}")) + else: + pending[req_id].set_result(raw.get("result", {})) + return + + # Server request (has id + method) — auto-approve + if has_id and "method" in raw: + method = raw.get("method", "") + safe_create_task( + self._rpc_respond(process, raw["id"], {"decision": "accept"}), + name=f"codex-rpc-{raw['id']}", + ) + return + + # Notification (no id, has method) + if "method" in raw: + for msg in self._parse_notification(raw): + if msg.type == "text": + accumulated_text.append(msg.content) + try: + queue.put_nowait(msg) + except asyncio.QueueFull: + logger.warning(f"Codex event queue full, dropping message: {msg.type}") + + # Detect turn completion + method = raw.get("method", "") + params = raw.get("params", {}) + if method == "turn/completed": + status = _nested_str(params, "turn", "status") + aborted = status in ("cancelled", "canceled", "aborted", "interrupted") + if not turn_done.done(): + turn_done.set_result(aborted) + elif method == "codex/event": + msg_data = (params or {}).get("msg", {}) + if isinstance(msg_data, dict): + msg_type = msg_data.get("type", "") + if msg_type == "task_complete": + if not turn_done.done(): + turn_done.set_result(False) + elif msg_type == "turn_aborted": + if not turn_done.done(): + turn_done.set_result(True) + + try: + async with asyncio.timeout(timeout): + # 1. Send initialize + await self._rpc_request( + process, + "initialize", + { + "clientInfo": { + "name": "joysafeter-agent", + "title": "JoySafeter Agent", + "version": "0.1.0", + }, + "capabilities": {"experimentalApi": True}, + }, + ) + init_id = self._next_id + + # Read lines until we get the initialize response + assert process.stdout is not None + async for raw_line in process.stdout: + line = raw_line.decode().strip() + if not line: + continue + try: + raw = json.loads(line) + except json.JSONDecodeError: + continue + if isinstance(raw, dict) and raw.get("id") == init_id and "result" in raw: + break + handle_line(line) + + # 2. Send initialized notification + await self._rpc_notify(process, "initialized") + + # 3. Start thread + await self._rpc_request( + process, + "thread/start", + { + "model": model, + "cwd": None, + "approvalPolicy": None, + "sandbox": None, + }, + ) + thread_start_id = self._next_id + thread_id = "" + + assert process.stdout is not None + async for raw_line in process.stdout: + line = raw_line.decode().strip() + if not line: + continue + try: + raw = json.loads(line) + except json.JSONDecodeError: + continue + if isinstance(raw, dict) and raw.get("id") == thread_start_id and "result" in raw: + result_data = raw.get("result", {}) + thread_data = result_data.get("thread", {}) if isinstance(result_data, dict) else {} + thread_id = thread_data.get("id", "") if isinstance(thread_data, dict) else "" + break + handle_line(line) + + if not thread_id: + raise RuntimeError("codex thread/start returned no thread ID") + + logger.info(f"codex thread started: {thread_id}") + + # 4. Start turn + await self._rpc_request( + process, + "turn/start", + { + "threadId": thread_id, + "input": [{"type": "text", "text": prompt}], + }, + ) + + # 5. Read events until turn completes + assert process.stdout is not None + async for raw_line in process.stdout: + line = raw_line.decode().strip() + if not line: + continue + handle_line(line) + if turn_done.done(): + break + + except TimeoutError: + if not result_future.done(): + result_future.set_result(CLIResult(status="timeout", error="Codex agent timed out")) + except Exception as e: + logger.error(f"Codex drain error: {e}") + if not result_future.done(): + result_future.set_result(CLIResult(status="failed", error=str(e))) + finally: + if not result_future.done(): + exit_code = await process.wait() + aborted = turn_done.done() and turn_done.result() + if aborted: + result_future.set_result( + CLIResult( + status="failed", + output="\n".join(accumulated_text), + error="Turn was aborted", + ) + ) + elif exit_code == 0 or accumulated_text: + result_future.set_result( + CLIResult( + status="completed", + output="\n".join(accumulated_text), + ) + ) + else: + stderr_bytes = await process.stderr.read() if process.stderr else b"" + result_future.set_result( + CLIResult( + status="failed", + error=f"Exit code {exit_code}: {stderr_bytes.decode()[:2000]}", + ) + ) + await queue.put(None) + + # ── event parsing (testable without Docker) ───────────────────────── + + def _parse_notification(self, raw: dict) -> list[CLIMessage]: + """Parse a JSON-RPC notification into CLIMessage list. + + Handles both legacy ``codex/event`` notifications and raw v2 + ``item/*`` / ``turn/*`` notifications. + """ + method = raw.get("method", "") + params = raw.get("params", {}) or {} + + # Legacy codex/event format + if method == "codex/event" or method.startswith("codex/event/"): + return self._parse_legacy_event(params) + + # Raw v2 item notifications + if method.startswith("item/"): + return self._parse_item_notification(method, params) + + return [] + + def _parse_legacy_event(self, params: dict) -> list[CLIMessage]: + msg_data = params.get("msg") + if not isinstance(msg_data, dict): + return [] + + msg_type = msg_data.get("type", "") + messages: list[CLIMessage] = [] + + if msg_type == "agent_message": + text = msg_data.get("message", "") + if text: + messages.append(CLIMessage(type="text", content=text)) + elif msg_type == "exec_command_begin": + messages.append( + CLIMessage( + type="tool_use", + tool="exec_command", + call_id=msg_data.get("call_id", ""), + input={"command": msg_data.get("command", "")}, + ) + ) + elif msg_type == "exec_command_end": + messages.append( + CLIMessage( + type="tool_result", + tool="exec_command", + call_id=msg_data.get("call_id", ""), + output=msg_data.get("output", ""), + ) + ) + elif msg_type == "patch_apply_begin": + messages.append( + CLIMessage( + type="tool_use", + tool="patch_apply", + call_id=msg_data.get("call_id", ""), + ) + ) + elif msg_type == "patch_apply_end": + messages.append( + CLIMessage( + type="tool_result", + tool="patch_apply", + call_id=msg_data.get("call_id", ""), + ) + ) + + return messages + + def _parse_item_notification(self, method: str, params: dict) -> list[CLIMessage]: + item = params.get("item", {}) + if not isinstance(item, dict): + return [] + + item_type = item.get("type", "") + item_id = item.get("id", "") + + if method == "item/started" and item_type == "commandExecution": + return [ + CLIMessage( + type="tool_use", + tool="exec_command", + call_id=item_id, + input={"command": item.get("command", "")}, + ) + ] + + if method == "item/completed" and item_type == "commandExecution": + return [ + CLIMessage( + type="tool_result", + tool="exec_command", + call_id=item_id, + output=item.get("aggregatedOutput", ""), + ) + ] + + if method == "item/started" and item_type == "fileChange": + return [ + CLIMessage( + type="tool_use", + tool="patch_apply", + call_id=item_id, + ) + ] + + if method == "item/completed" and item_type == "fileChange": + return [ + CLIMessage( + type="tool_result", + tool="patch_apply", + call_id=item_id, + ) + ] + + if method == "item/completed" and item_type == "agentMessage": + text = item.get("text", "") + if text: + return [CLIMessage(type="text", content=text)] + + return [] + + +def _nested_str(m: dict, *keys: str) -> str: + current = m + for key in keys: + if not isinstance(current, dict): + return "" + current = current.get(key, {}) + return current if isinstance(current, str) else "" diff --git a/backend/app/core/agent/cli_backends/container_bridge.py b/backend/app/core/agent/cli_backends/container_bridge.py new file mode 100644 index 000000000..6b00b0166 --- /dev/null +++ b/backend/app/core/agent/cli_backends/container_bridge.py @@ -0,0 +1,32 @@ +from __future__ import annotations + +import asyncio + +from loguru import logger + + +class ContainerProcessBridge: + async def exec_streaming( + self, + container_id: str, + cmd: list[str], + workdir: str | None = None, + env: dict[str, str] | None = None, + ) -> asyncio.subprocess.Process: + docker_cmd = ["docker", "exec", "-i"] + if workdir: + docker_cmd.extend(["-w", workdir]) + if env: + for key, value in env.items(): + docker_cmd.extend(["-e", f"{key}={value}"]) + docker_cmd.append(container_id) + docker_cmd.extend(cmd) + + logger.debug(f"container exec: {' '.join(docker_cmd[:6])}...") + + return await asyncio.create_subprocess_exec( + *docker_cmd, + stdin=asyncio.subprocess.PIPE, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) diff --git a/backend/app/core/agent/cli_backends/container_pool.py b/backend/app/core/agent/cli_backends/container_pool.py new file mode 100644 index 000000000..dd6da4c3a --- /dev/null +++ b/backend/app/core/agent/cli_backends/container_pool.py @@ -0,0 +1,193 @@ +""" +CLI agent container pool with TTL-based eviction and session resume. + +Keeps containers alive after execution for reuse by the same agent. +Idle containers are cleaned up after `idle_timeout` seconds (default 30 min). +On app shutdown, containers are NOT destroyed — they survive restarts. +""" + +from __future__ import annotations + +import asyncio +import time +import uuid +from dataclasses import dataclass +from typing import Optional + +from loguru import logger + +from .container_service import CLIContainerService, ContainerInfo + + +@dataclass +class PoolEntry: + container: ContainerInfo + agent_profile_id: uuid.UUID + last_used: float + created_at: float + active_count: int = 0 + last_session_id: Optional[str] = None + + +class ContainerPool: + """Pool of CLI agent containers keyed by agent_profile_id.""" + + def __init__( + self, + container_service: Optional[CLIContainerService] = None, + idle_timeout: int = 1800, + max_size: int = 20, + ): + self._pool: dict[uuid.UUID, PoolEntry] = {} + self._lock = asyncio.Lock() + self._idle_timeout = idle_timeout + self._max_size = max_size + self._shutdown = False + self.container_service = container_service or CLIContainerService() + + async def get(self, agent_profile_id: uuid.UUID) -> tuple[Optional[ContainerInfo], Optional[str]]: + """Return (container, last_session_id) if a pooled container exists.""" + async with self._lock: + if self._shutdown: + return None, None + entry = self._pool.get(agent_profile_id) + if entry: + entry.last_used = time.time() + entry.active_count += 1 + return entry.container, entry.last_session_id + return None, None + + async def put( + self, + agent_profile_id: uuid.UUID, + container: ContainerInfo, + ) -> None: + """Register a newly created container in the pool.""" + old: Optional[PoolEntry] = None + evicted: Optional[PoolEntry] = None + shutdown = False + + async with self._lock: + if self._shutdown: + shutdown = True + else: + if len(self._pool) >= self._max_size and agent_profile_id not in self._pool: + evicted = self._evict_lru_entry() + + old = self._pool.pop(agent_profile_id, None) + self._pool[agent_profile_id] = PoolEntry( + container=container, + agent_profile_id=agent_profile_id, + last_used=time.time(), + created_at=time.time(), + active_count=1, + ) + logger.info( + f"Pooled container {container.container_id[:12]} for agent " + f"{agent_profile_id} (pool_size={len(self._pool)})" + ) + + if shutdown: + await self._safe_remove(container.container_id) + return + if evicted: + await self._safe_remove(evicted.container.container_id) + if old: + await self._safe_remove(old.container.container_id) + + async def release(self, agent_profile_id: uuid.UUID) -> None: + """Decrement active count after execution finishes.""" + async with self._lock: + entry = self._pool.get(agent_profile_id) + if entry: + entry.active_count = max(0, entry.active_count - 1) + entry.last_used = time.time() + + async def release_and_destroy_if_idle(self, agent_profile_id: uuid.UUID) -> bool: + """Decrement active count; if no other executions are using it, remove the container. + + Returns True if the container was destroyed.""" + entry: Optional[PoolEntry] = None + async with self._lock: + e = self._pool.get(agent_profile_id) + if not e: + return False + e.active_count = max(0, e.active_count - 1) + if e.active_count == 0: + entry = self._pool.pop(agent_profile_id) + if entry: + await self._safe_remove(entry.container.container_id) + logger.info( + f"Destroyed idle container {entry.container.container_id[:12]} " + f"for agent {agent_profile_id} after cancel" + ) + return True + return False + + async def set_session_id(self, agent_profile_id: uuid.UUID, session_id: str) -> None: + """Store Claude session_id for next --resume.""" + async with self._lock: + entry = self._pool.get(agent_profile_id) + if entry and session_id: + entry.last_session_id = session_id + + async def remove(self, agent_profile_id: uuid.UUID) -> None: + """Force-remove a container (e.g., on execution failure).""" + entry: Optional[PoolEntry] = None + async with self._lock: + entry = self._pool.pop(agent_profile_id, None) + if entry: + await self._safe_remove(entry.container.container_id) + + async def cleanup_idle(self) -> int: + """Remove containers idle longer than idle_timeout. Returns count removed.""" + now = time.time() + to_remove: list[tuple[uuid.UUID, str]] = [] + + async with self._lock: + for agent_id, entry in list(self._pool.items()): + idle = entry.active_count == 0 and (now - entry.last_used) > self._idle_timeout + if idle: + self._pool.pop(agent_id) + to_remove.append((agent_id, entry.container.container_id)) + + for agent_id, container_id in to_remove: + await self._safe_remove(container_id) + logger.info(f"Evicted idle container {container_id[:12]} for agent {agent_id}") + + return len(to_remove) + + async def shutdown(self) -> None: + """Mark pool as shut down. Containers are NOT destroyed.""" + async with self._lock: + self._shutdown = True + self._pool.clear() + logger.info("Container pool shut down (containers left running for reuse after restart)") + + async def _evict_lru(self) -> None: + """Evict the least-recently-used idle container. Called outside lock.""" + entry = self._evict_lru_entry() + if entry: + await self._safe_remove(entry.container.container_id) + + def _evict_lru_entry(self) -> Optional[PoolEntry]: + """Pop the LRU idle entry from the pool. Must be called inside lock.""" + lru_id: Optional[uuid.UUID] = None + lru_time = float("inf") + for agent_id, entry in self._pool.items(): + if entry.active_count == 0 and entry.last_used < lru_time: + lru_time = entry.last_used + lru_id = agent_id + if lru_id: + return self._pool.pop(lru_id) + return None + + async def _safe_remove(self, container_id: str) -> None: + try: + await self.container_service.remove_container(container_id, force=True) + except Exception as exc: + logger.warning(f"Failed to remove pooled container {container_id[:12]}: {exc}") + + +# Module-level singleton +container_pool = ContainerPool() diff --git a/backend/app/core/agent/cli_backends/container_service.py b/backend/app/core/agent/cli_backends/container_service.py new file mode 100644 index 000000000..65ac3941d --- /dev/null +++ b/backend/app/core/agent/cli_backends/container_service.py @@ -0,0 +1,150 @@ +""" +CLI container lifecycle management via Docker. +""" + +from __future__ import annotations + +import asyncio +import os +import tempfile +import uuid +from dataclasses import dataclass, field +from typing import Optional + +from loguru import logger + + +@dataclass +class ContainerConfig: + image: str = "joysafeter/cli-agent:latest" + memory_limit: str = "2g" + cpu_quota: int = 200000 + network_mode: str = "bridge" + working_dir: str = "/workspace" + labels: dict[str, str] = field(default_factory=dict) + + +@dataclass +class ContainerInfo: + container_id: str + name: str + status: str + working_dir: str + + +class CLIContainerService: + """Manages Docker container lifecycle for CLI agent executions.""" + + def __init__(self, default_config: Optional[ContainerConfig] = None): + self.default_config = default_config or ContainerConfig() + + async def create_container( + self, + *, + execution_id: uuid.UUID, + config: Optional[ContainerConfig] = None, + env: Optional[dict[str, str]] = None, + ) -> ContainerInfo: + cfg = config or self.default_config + name = f"cli-agent-{execution_id!s:.12}" + + docker_cmd = [ + "docker", + "create", + "--name", + name, + "-w", + cfg.working_dir, + f"--memory={cfg.memory_limit}", + f"--cpu-quota={cfg.cpu_quota}", + f"--network={cfg.network_mode}", + ] + for k, v in cfg.labels.items(): + docker_cmd.extend(["--label", f"{k}={v}"]) + docker_cmd.extend(["--label", f"execution_id={execution_id}"]) + + env_file_path: Optional[str] = None + if env: + env_file_path = self._write_env_file(env) + docker_cmd.extend(["--env-file", env_file_path]) + + docker_cmd.append(cfg.image) + docker_cmd.append("sleep") + docker_cmd.append("infinity") + + try: + container_id = await self._run_docker(docker_cmd) + container_id = container_id.strip() + finally: + if env_file_path: + try: + os.unlink(env_file_path) + except OSError: + pass + + await self._run_docker(["docker", "start", container_id]) + + logger.info(f"Created container {container_id[:12]} for execution {execution_id}") + return ContainerInfo( + container_id=container_id, + name=name, + status="running", + working_dir=cfg.working_dir, + ) + + @staticmethod + def _write_env_file(env: dict[str, str]) -> str: + """Write env vars to a temp file (mode 0600) and return its path.""" + fd, path = tempfile.mkstemp(prefix="cli_agent_env_", suffix=".env") + try: + with os.fdopen(fd, "w") as f: + for k, v in env.items(): + f.write(f"{k}={v}\n") + os.chmod(path, 0o600) + except Exception: + os.unlink(path) + raise + return path + + async def stop_container(self, container_id: str, timeout: int = 10) -> None: + try: + await self._run_docker(["docker", "stop", "-t", str(timeout), container_id]) + logger.info(f"Stopped container {container_id[:12]}") + except RuntimeError as exc: + logger.warning(f"Failed to stop container {container_id[:12]}: {exc}") + + async def remove_container(self, container_id: str, force: bool = True) -> None: + cmd = ["docker", "rm"] + if force: + cmd.append("-f") + cmd.append(container_id) + try: + await self._run_docker(cmd) + logger.info(f"Removed container {container_id[:12]}") + except RuntimeError as exc: + logger.warning(f"Failed to remove container {container_id[:12]}: {exc}") + + async def copy_to_container(self, container_id: str, src_path: str, dest_path: str) -> None: + await self._run_docker(["docker", "cp", src_path, f"{container_id}:{dest_path}"]) + + async def exec_in_container(self, container_id: str, cmd: list[str], workdir: Optional[str] = None) -> str: + docker_cmd = ["docker", "exec"] + if workdir: + docker_cmd.extend(["-w", workdir]) + docker_cmd.append(container_id) + docker_cmd.extend(cmd) + return await self._run_docker(docker_cmd) + + async def inspect_container(self, container_id: str) -> str: + return await self._run_docker(["docker", "inspect", "--format", "{{.State.Status}}", container_id]) + + async def _run_docker(self, cmd: list[str]) -> str: + proc = await asyncio.create_subprocess_exec( + *cmd, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) + stdout, stderr = await proc.communicate() + if proc.returncode != 0: + raise RuntimeError(f"Docker command failed (exit {proc.returncode}): {stderr.decode()[:1000]}") + return stdout.decode() diff --git a/backend/app/core/agent/cli_backends/execution_runner.py b/backend/app/core/agent/cli_backends/execution_runner.py new file mode 100644 index 000000000..cc403693c --- /dev/null +++ b/backend/app/core/agent/cli_backends/execution_runner.py @@ -0,0 +1,467 @@ +""" +ExecutionRunner — end-to-end orchestrator for CLI agent executions. + +Lifecycle: + 1. Get or create container (from pool) + 2. Inject credentials, skills, and CLAUDE.md config + 3. Execute via RuntimeProvider (with session resume if available) + 4. Drain messages → append as ExecutionEvents + 5. Mark final status, store session_id back to pool + 6. Release container back to pool (NOT destroyed) +""" + +from __future__ import annotations + +import asyncio +import uuid +from typing import Any, Optional + +from loguru import logger +from sqlalchemy.ext.asyncio import AsyncSession + +from app.core.agent.cli_backends.base import CLIMessage, CLIResult, RuntimeSession, build_control_response +from app.core.agent.cli_backends.container_pool import container_pool +from app.core.agent.cli_backends.container_service import ( + CLIContainerService, + ContainerConfig, + ContainerInfo, +) +from app.core.agent.cli_backends.injectors import ( + CLISkillInjector, + RuntimeConfigInjector, +) +from app.core.agent.cli_backends.registry import runtime_registry +from app.core.agent.cli_backends.runner_callbacks import RunnerCallbacks +from app.core.agent.cli_backends.session_registry import session_registry +from app.models.agent_profile import AgentProfile, AgentStatus +from app.models.execution import Execution, MissionExecutionStatus +from app.repositories.agent_profile import AgentProfileRepository +from app.services.execution_service import ExecutionService + + +class ExecutionRunner: + """Orchestrates the full lifecycle of a CLI agent execution.""" + + def __init__( + self, + db: AsyncSession, + container_service: Optional[CLIContainerService] = None, + callbacks: Optional[RunnerCallbacks] = None, + ): + self.db = db + self.execution_service = ExecutionService(db) + self.agent_repo = AgentProfileRepository(db) + self.container_service = container_service or CLIContainerService() + self.callbacks = callbacks + self._auto_approve: bool = True + self._session: Optional[RuntimeSession] = None + + async def run( + self, + *, + execution_id: uuid.UUID, + prompt: str, + credentials: Optional[dict[str, str]] = None, + skills: Optional[list[dict[str, Any]]] = None, + container_config: Optional[ContainerConfig] = None, + model: Optional[str] = None, + timeout: int = 7200, + ) -> CLIResult: + """Run a full execution lifecycle. + + Returns the final CLIResult after the agent completes or fails. + """ + container: Optional[ContainerInfo] = None + execution = await self._get_execution(execution_id) + agent_profile = await self._get_agent_profile(execution) + pooled = False # whether the container came from the pool + + logger.info( + f"[exec:{execution_id}] Starting execution " + f"(agent={agent_profile.id if agent_profile else 'none'}, " + f"runtime={execution.runtime_type})" + ) + + try: + # 1. Mark as dispatched + await self.execution_service.mark_status( + execution_id=execution_id, + status=MissionExecutionStatus.DISPATCHED, + ) + + # 2. Get or create container + prior_session_id: Optional[str] = None + if agent_profile: + container, prior_session_id = await container_pool.get(agent_profile.id) + + if container: + pooled = True + # Verify container is still running + try: + status = await self.container_service.inspect_container(container.container_id) + if "running" not in status.strip().lower(): + logger.warning( + f"[exec:{execution_id}] Pooled container {container.container_id[:12]} " + f"not running (status={status.strip()}), creating new one" + ) + assert agent_profile is not None + await container_pool.remove(agent_profile.id) + container = None + prior_session_id = None + pooled = False + except Exception as inspect_exc: + logger.warning(f"[exec:{execution_id}] Failed to inspect pooled container: {inspect_exc}") + assert agent_profile is not None + await container_pool.remove(agent_profile.id) + container = None + prior_session_id = None + pooled = False + + if not container: + logger.info(f"[exec:{execution_id}] Creating new container") + container = await self.container_service.create_container( + execution_id=execution_id, + config=container_config, + env=credentials, + ) + if agent_profile: + await container_pool.put(agent_profile.id, container) + pooled = True + + if prior_session_id: + logger.info( + f"[exec:{execution_id}] Reusing pooled container " + f"{container.container_id[:12]} with session {prior_session_id}" + ) + + await self.execution_service.mark_status( + execution_id=execution_id, + status=MissionExecutionStatus.RUNNING, + container_id=container.container_id, + ) + + if agent_profile: + await self._update_agent_status(agent_profile, AgentStatus.WORKING) + + # 3. Inject skills and config (idempotent — safe to re-run on reuse) + await self._inject( + container_id=container.container_id, + skills=skills, + agent_profile=agent_profile, + working_dir=container.working_dir, + ) + + # 4. Record execution_started event + await self.execution_service.append_event( + execution_id=execution_id, + event_type="execution_started", + payload={ + "container_id": container.container_id, + "runtime_type": execution.runtime_type, + "reused": prior_session_id is not None, + }, + ) + + # 5. Execute via provider (with session resume + credentials) + provider = runtime_registry.get(execution.runtime_type) + + # Determine auto_approve from mission settings + self._auto_approve = await self._get_mission_auto_approve(execution) + + session = await provider.execute( + prompt, + container_id=container.container_id, + cwd=container.working_dir, + model=model, + timeout=timeout, + resume_session_id=prior_session_id, + env=credentials, + auto_approve=self._auto_approve, + ) + + # 5b. Register session so the API layer can inject messages + session_registry.register(execution_id, session) + self._session = session + + # 6. Drain messages → events + await self._drain_to_events(execution_id) + + # 7. Await final result + result = await session.result + + # 8. Mark final status + await self._finalize(execution_id, result, agent_profile) + + # 9. Store session_id back to pool for next resume + if result.session_id and agent_profile: + await container_pool.set_session_id(agent_profile.id, result.session_id) + logger.info(f"[exec:{execution_id}] Stored session {result.session_id} for agent {agent_profile.id}") + + return result + + except Exception as exc: + logger.error(f"[exec:{execution_id}] ExecutionRunner error: {exc}") + await self._mark_failed(execution_id, str(exc), agent_profile) + return CLIResult(status="failed", error=str(exc)) + + finally: + # 10. Unregister session; release container back to pool + session_registry.unregister(execution_id) + if container and agent_profile and pooled: + await container_pool.release(agent_profile.id) + logger.info(f"[exec:{execution_id}] Released container {container.container_id[:12]} back to pool") + elif container: + await self._cleanup_container(container.container_id) + logger.info( + f"[exec:{execution_id}] Destroyed container {container.container_id[:12]} (no agent profile)" + ) + + async def _get_execution(self, execution_id: uuid.UUID) -> Execution: + from sqlalchemy import select + + from app.models.execution import Execution as ExecModel + + result = await self.db.execute(select(ExecModel).where(ExecModel.id == execution_id)) + execution = result.scalar_one_or_none() + if not execution: + raise ValueError(f"Execution not found: {execution_id}") + return execution + + async def _get_agent_profile(self, execution: Execution) -> Optional[AgentProfile]: + if not execution.agent_profile_id: + return None + return await self.agent_repo.get(execution.agent_profile_id) + + async def _get_mission_auto_approve(self, execution: Execution) -> bool: + if not execution.mission_id: + return True + from sqlalchemy import select + + from app.models.mission import Mission + + result = await self.db.execute(select(Mission.auto_approve).where(Mission.id == execution.mission_id)) + val = result.scalar_one_or_none() + return val if val is not None else True + + async def _inject( + self, + *, + container_id: str, + skills: Optional[list[dict[str, Any]]], + agent_profile: Optional[AgentProfile], + working_dir: str, + ) -> None: + skill_injector = CLISkillInjector(self.container_service) + config_injector = RuntimeConfigInjector(self.container_service) + + if skills: + await skill_injector.inject(container_id, skills) + + instructions = agent_profile.instructions if agent_profile else None + skill_names = None + if skills: + skill_names = [s.get("name", "") for s in skills if s.get("name")] + + await config_injector.inject( + container_id, + instructions=instructions, + skill_names=skill_names, + working_dir=working_dir, + ) + + _DRAIN_BATCH_SIZE = 5 + _DRAIN_FLUSH_INTERVAL = 0.5 # seconds — flush at least every 500ms + + async def _drain_to_events( + self, + execution_id: uuid.UUID, + ) -> None: + assert self._session is not None, "_drain_to_events called before session was set" + pending: list[tuple[CLIMessage, str, dict[str, Any]]] = [] + logger.info(f"[exec:{execution_id}] _drain_to_events started") + queue = self._session.messages + + while True: + try: + msg = await asyncio.wait_for(queue.get(), timeout=self._DRAIN_FLUSH_INTERVAL) + except asyncio.TimeoutError: + # Timeout — flush whatever we have so far + if pending: + await self._flush_pending(execution_id, pending) + pending.clear() + continue + + if msg is None: + break + + event_type = self._msg_to_event_type(msg) + payload = self._msg_to_payload(msg) + pending.append((msg, event_type, payload)) + + needs_flush = len(pending) >= self._DRAIN_BATCH_SIZE or msg.type == "approval_request" + if needs_flush: + await self._flush_pending(execution_id, pending) + pending.clear() + + if pending: + await self._flush_pending(execution_id, pending) + logger.info(f"[exec:{execution_id}] _drain_to_events finished") + + async def _flush_pending( + self, + execution_id: uuid.UUID, + pending: list[tuple[CLIMessage, str, dict[str, Any]]], + ) -> None: + try: + await self.execution_service.batch_append_events( + execution_id=execution_id, + events=[{"event_type": event_type, "payload": payload} for _, event_type, payload in pending], + ) + for msg, _, payload in pending: + if msg.type == "approval_request": + if self._auto_approve: + request_id = payload.get("request_id", "") + assert self._session is not None + await self._session.inject_message(build_control_response(request_id, "allow")) + await self.execution_service.append_event( + execution_id=execution_id, + event_type="approval_resolved", + payload={"decision": "auto_approved", "request_id": request_id}, + ) + else: + await self.execution_service.mark_status( + execution_id=execution_id, + status=MissionExecutionStatus.APPROVAL_WAIT, + ) + break + except Exception as exc: + logger.warning(f"Failed to flush {len(pending)} events for {execution_id}: {exc}") + + async def _finalize( + self, + execution_id: uuid.UUID, + result: CLIResult, + agent_profile: Optional[AgentProfile], + ) -> None: + if result.status == "completed": + status = MissionExecutionStatus.COMPLETED + else: + status = MissionExecutionStatus.FAILED + + await self.execution_service.append_event( + execution_id=execution_id, + event_type="execution_completed" if status == MissionExecutionStatus.COMPLETED else "error", + payload={ + "result_summary": {"output_length": len(result.output)}, + "message": result.error or "", + }, + ) + + await self.execution_service.mark_status( + execution_id=execution_id, + status=status, + session_id=result.session_id, + error_message=result.error if result.error else None, + result_summary=result.usage, + ) + + if agent_profile: + await self._update_agent_status(agent_profile, AgentStatus.IDLE) + + if self.callbacks: + try: + await self.callbacks.on_execution_finalized(execution_id, status, result) + except Exception as exc: + logger.warning(f"Callback on_execution_finalized failed for {execution_id}: {exc}") + + async def _mark_failed( + self, + execution_id: uuid.UUID, + error: str, + agent_profile: Optional[AgentProfile], + ) -> None: + try: + await self.execution_service.append_event( + execution_id=execution_id, + event_type="error", + payload={"message": error}, + ) + await self.execution_service.mark_status( + execution_id=execution_id, + status=MissionExecutionStatus.FAILED, + error_message=error[:2000], + ) + except Exception as exc: + logger.error(f"Failed to mark execution {execution_id} as failed: {exc}") + + if agent_profile: + await self._update_agent_status(agent_profile, AgentStatus.ERROR) + + if self.callbacks: + try: + await self.callbacks.on_execution_failed(execution_id, error) + except Exception as exc: + logger.warning(f"Callback on_execution_failed failed for {execution_id}: {exc}") + + async def _update_agent_status(self, agent_profile: AgentProfile, status: AgentStatus) -> None: + try: + profile = await self.agent_repo.get_for_update(agent_profile.id) + if profile: + profile.status = status + await self.db.commit() + except Exception as exc: + logger.warning(f"Failed to update agent status: {exc}") + + async def _cleanup_container(self, container_id: str) -> None: + try: + await self.container_service.remove_container(container_id, force=True) + except Exception as exc: + logger.warning(f"Failed to cleanup container {container_id[:12]}: {exc}") + + @staticmethod + def _msg_to_event_type(msg: CLIMessage) -> str: + mapping = { + "text": "assistant_text", + "thinking": "thinking", + "tool_use": "tool_use_start", + "tool_result": "tool_use_end", + "error": "error", + "artifact": "artifact_created", + "approval_request": "approval_requested", + } + return mapping.get(msg.type, msg.type) + + @staticmethod + def _msg_to_payload(msg: CLIMessage) -> dict[str, Any]: + if msg.type == "text": + return {"content": msg.content} + if msg.type == "thinking": + return {"content": msg.content} + if msg.type == "tool_use": + return { + "tool": { + "name": msg.tool, + "call_id": msg.call_id, + "input": msg.input, + "status": "running", + }, + } + if msg.type == "tool_result": + return { + "call_id": msg.call_id, + "tool_name": msg.tool, + "output": msg.output, + } + if msg.type == "error": + return {"message": msg.content} + if msg.type == "artifact": + return {"artifact": {"content": msg.content}} + if msg.type == "approval_request": + return { + "request_id": msg.call_id, + "subtype": msg.content, + "tool_name": msg.tool, + "input": msg.input, + "message": f"Agent wants to use: {msg.tool or 'unknown tool'}", + } + return {"content": msg.content} diff --git a/backend/app/core/agent/cli_backends/injectors.py b/backend/app/core/agent/cli_backends/injectors.py new file mode 100644 index 000000000..4e997b7b6 --- /dev/null +++ b/backend/app/core/agent/cli_backends/injectors.py @@ -0,0 +1,155 @@ +""" +Credential, skill, and runtime config injectors for CLI agent containers. +""" + +from __future__ import annotations + +from typing import Any, Optional + +from loguru import logger + +from app.utils.path_utils import sanitize_skill_name + +from .container_service import CLIContainerService + + +class CredentialInjector: + """Builds the env dict for CLI agent containers. + + Credentials are passed to ``create_container()`` which sets them via + Docker's ``-e`` / ``--env-file`` flags. This class only resolves and + returns the dict — it never writes to the container filesystem. + """ + + def build_env(self, credentials: dict[str, str]) -> dict[str, str]: + """Return a sanitised copy of *credentials* suitable for Docker env.""" + return dict(credentials) if credentials else {} + + +class CLISkillInjector: + """Writes skill file trees into the container filesystem. + + Each skill is written as a directory under ``target_dir``: + /workspace/skills/{skill_name}/ + SKILL.md + scripts/rotate_pdf.py + references/tools.md + ... + """ + + def __init__(self, container_service: CLIContainerService): + self.container_service = container_service + + async def inject( + self, + container_id: str, + skills: list[dict[str, Any]], + target_dir: str = "/workspace/skills", + ) -> None: + if not skills: + return + await self.container_service.exec_in_container(container_id, ["mkdir", "-p", target_dir]) + + total_files = 0 + for skill in skills: + name = sanitize_skill_name(skill.get("name", "unnamed")) + skill_dir = f"{target_dir}/{name}" + await self.container_service.exec_in_container(container_id, ["mkdir", "-p", skill_dir]) + + files: list[dict[str, str]] = skill.get("files", []) + if files: + for f in files: + content = f.get("content", "") + if not content: + continue + rel_path = f.get("path", f.get("file_name", "unknown")) + full_path = f"{skill_dir}/{rel_path}" + parent = "/".join(full_path.rsplit("/", 1)[:-1]) + if parent: + await self.container_service.exec_in_container(container_id, ["mkdir", "-p", parent]) + escaped = content.replace("\\", "\\\\").replace("'", "'\\''") + await self.container_service.exec_in_container( + container_id, + ["sh", "-c", f"cat > '{full_path}' << 'SKILLEOF'\n{escaped}\nSKILLEOF"], + ) + total_files += 1 + else: + # Fallback: write SKILL.md from top-level content field + body = skill.get("content", "") + if body: + desc = skill.get("description", "") + skill_md = f"---\nname: {name}\ndescription: {desc}\n---\n\n{body}" + await self.container_service.exec_in_container( + container_id, + ["sh", "-c", f"cat > '{skill_dir}/SKILL.md' << 'SKILLEOF'\n{skill_md}\nSKILLEOF"], + ) + total_files += 1 + + logger.info(f"Injected {len(skills)} skills ({total_files} files) into {container_id[:12]}") + + +class RuntimeConfigInjector: + """Generates and writes CLAUDE.md configuration into the container.""" + + def __init__(self, container_service: CLIContainerService): + self.container_service = container_service + + async def inject( + self, + container_id: str, + *, + instructions: Optional[str] = None, + skill_names: Optional[list[str]] = None, + project_context: Optional[str] = None, + working_dir: str = "/workspace", + ) -> None: + claude_md = self._build_claude_md( + instructions=instructions, + skill_names=skill_names, + project_context=project_context, + ) + target = f"{working_dir}/CLAUDE.md" + await self.container_service.exec_in_container( + container_id, + ["sh", "-c", f"cat > {target} << 'CLAUDEEOF'\n{claude_md}\nCLAUDEEOF"], + ) + logger.debug(f"Injected CLAUDE.md into {container_id[:12]}") + + def _build_claude_md( + self, + *, + instructions: Optional[str] = None, + skill_names: Optional[list[str]] = None, + project_context: Optional[str] = None, + ) -> str: + sections: list[str] = [] + sections.append("# Agent Configuration") + sections.append("") + sections.append("You are an autonomous coding agent executing a mission.") + sections.append("Complete the task thoroughly and commit your work when done.") + + if instructions: + sections.append("") + sections.append("## Instructions") + sections.append("") + sections.append(instructions) + + if skill_names: + sections.append("") + sections.append("## Available Skills") + sections.append("") + sections.append( + "Skills are located in `/workspace/skills/`. Each skill directory contains a SKILL.md and related files." + ) + sections.append("") + for name in skill_names: + safe = sanitize_skill_name(name) + sections.append(f"- **{name}** → `/workspace/skills/{safe}/SKILL.md`") + + if project_context: + sections.append("") + sections.append("## Project Context") + sections.append("") + sections.append(project_context) + + return "\n".join(sections) diff --git a/backend/app/core/agent/cli_backends/openclaw.py b/backend/app/core/agent/cli_backends/openclaw.py new file mode 100644 index 000000000..e3204ea4b --- /dev/null +++ b/backend/app/core/agent/cli_backends/openclaw.py @@ -0,0 +1,267 @@ +from __future__ import annotations + +import asyncio +import json +import time + +from loguru import logger + +from .base import CLIMessage, CLIResult, RuntimeSession +from .container_bridge import ContainerProcessBridge + + +class OpenClawProvider: + """Runtime provider for OpenClaw CLI. + + OpenClaw outputs NDJSON events on *stderr* (not stdout). We spawn + ``openclaw agent --local --json --session-id --message `` + and read stderr line-by-line. + + Event types (from the wire protocol): + text, tool_use, tool_result, error, lifecycle, step_start, step_finish + """ + + provider_type = "openclaw" + + def __init__(self, executable_path: str = "openclaw") -> None: + self.executable_path = executable_path + self.bridge = ContainerProcessBridge() + + # ── public API ────────────────────────────────────────────────────── + + async def execute( + self, + prompt: str, + *, + container_id: str, + cwd: str | None = None, + model: str | None = None, + timeout: int = 7200, + resume_session_id: str | None = None, + env: dict[str, str] | None = None, + auto_approve: bool = True, + ) -> RuntimeSession: + session_id = resume_session_id or f"joysafeter-{int(time.time() * 1e9)}" + + cmd = [ + self.executable_path, + "agent", + "--local", + "--json", + "--session-id", + session_id, + ] + if model: + cmd.extend(["--model", model]) + cmd.extend(["--message", prompt]) + + process = await self.bridge.exec_streaming( + container_id, + cmd, + env=env, + workdir=cwd, + ) + + queue: asyncio.Queue[CLIMessage | None] = asyncio.Queue(maxsize=512) + loop = asyncio.get_event_loop() + result_future: asyncio.Future[CLIResult] = loop.create_future() + + drain_task = asyncio.create_task( + self._drain(process, queue, result_future, session_id, timeout), + name=f"openclaw-drain-{container_id[:12]}", + ) + + async def inject(message: str) -> None: + if process.stdin and not process.stdin.is_closing(): + process.stdin.write(f"{message}\n".encode()) + await process.stdin.drain() + + async def cancel() -> None: + process.terminate() + + return RuntimeSession( + messages=queue, + result=result_future, + _inject_fn=inject, + _cancel_fn=cancel, + _drain_task=drain_task, + ) + + # ── drain loop ────────────────────────────────────────────────────── + + async def _drain( + self, + process: asyncio.subprocess.Process, + queue: asyncio.Queue[CLIMessage | None], + result_future: asyncio.Future[CLIResult], + session_id: str, + timeout: int, + ) -> None: + accumulated_text: list[str] = [] + final_status = "completed" + final_error = "" + + try: + async with asyncio.timeout(timeout): + # OpenClaw writes JSON events to stderr + assert process.stderr is not None + async for raw_line in process.stderr: + line = raw_line.decode().strip() + if not line: + continue + + for msg in self._parse_line(line): + if msg.type == "text": + accumulated_text.append(msg.content) + if msg.type == "error": + final_status = "failed" + final_error = msg.content + await queue.put(msg) + + except TimeoutError: + if not result_future.done(): + result_future.set_result( + CLIResult( + status="timeout", + error="OpenClaw agent timed out", + session_id=session_id, + ) + ) + except Exception as e: + logger.error(f"OpenClaw drain error: {e}") + if not result_future.done(): + result_future.set_result( + CLIResult( + status="failed", + error=str(e), + session_id=session_id, + ) + ) + finally: + if not result_future.done(): + exit_code = await process.wait() + if final_status == "failed": + result_future.set_result( + CLIResult( + status="failed", + output="\n".join(accumulated_text), + error=final_error, + session_id=session_id, + ) + ) + elif exit_code == 0 or accumulated_text: + result_future.set_result( + CLIResult( + status="completed", + output="\n".join(accumulated_text), + session_id=session_id, + ) + ) + else: + stdout_bytes = await process.stdout.read() if process.stdout else b"" + result_future.set_result( + CLIResult( + status="failed", + error=f"Exit code {exit_code}: {stdout_bytes.decode()[:2000]}", + session_id=session_id, + ) + ) + await queue.put(None) + + # ── event parsing (testable without Docker) ───────────────────────── + + def _parse_line(self, line: str) -> list[CLIMessage]: + """Parse a single stderr line into CLIMessage list. + + Non-JSON lines (plain log output) are silently skipped. + """ + if not line or line[0] != "{": + return [] + + try: + event = json.loads(line) + except json.JSONDecodeError: + return [] + + if not isinstance(event, dict) or "type" not in event: + return [] + + return self._parse_event(event) + + def _parse_event(self, event: dict) -> list[CLIMessage]: + """Map an OpenClaw NDJSON event to CLIMessage(s).""" + event_type = event.get("type", "") + + if event_type == "text": + text = event.get("text", "") + if text: + return [CLIMessage(type="text", content=text)] + return [] + + if event_type == "tool_use": + input_data = event.get("input") + if isinstance(input_data, str): + try: + input_data = json.loads(input_data) + except json.JSONDecodeError: + input_data = None + return [ + CLIMessage( + type="tool_use", + tool=event.get("tool", ""), + call_id=event.get("callId", ""), + input=input_data if isinstance(input_data, dict) else None, + ) + ] + + if event_type == "tool_result": + return [ + CLIMessage( + type="tool_result", + tool=event.get("tool", ""), + call_id=event.get("callId", ""), + output=event.get("text", ""), + ) + ] + + if event_type == "error": + error_msg = _extract_error_message(event) + return [CLIMessage(type="error", content=error_msg)] + + if event_type == "lifecycle": + phase = event.get("phase", "") + if phase in ("error", "failed", "cancelled"): + error_msg = _extract_error_message(event) + return [CLIMessage(type="error", content=error_msg)] + return [] + + if event_type == "step_start": + return [CLIMessage(type="text", content="[step started]")] + + if event_type == "step_finish": + return [CLIMessage(type="text", content="[step finished]")] + + # Unknown event type — skip + return [] + + +def _extract_error_message(event: dict) -> str: + """Extract a human-readable error from an OpenClaw event.""" + # Structured error object + err_obj = event.get("error") + if isinstance(err_obj, dict): + data = err_obj.get("data") + if isinstance(data, dict) and data.get("message"): + return str(data["message"]) + if err_obj.get("message"): + return str(err_obj["message"]) + if err_obj.get("name"): + return str(err_obj["name"]) + + # Flat fields + if event.get("text"): + return str(event["text"]) + if event.get("message"): + return str(event["message"]) + + return "unknown openclaw error" diff --git a/backend/app/core/agent/cli_backends/registry.py b/backend/app/core/agent/cli_backends/registry.py new file mode 100644 index 000000000..18215e70c --- /dev/null +++ b/backend/app/core/agent/cli_backends/registry.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +from loguru import logger + +from .base import RuntimeProvider + + +class RuntimeProviderRegistry: + def __init__(self) -> None: + self._providers: dict[str, RuntimeProvider] = {} + + def register(self, provider: RuntimeProvider) -> None: + self._providers[provider.provider_type] = provider + logger.info(f"Registered runtime provider: {provider.provider_type}") + + def get(self, provider_type: str) -> RuntimeProvider: + if provider_type not in self._providers: + raise ValueError(f"Unknown runtime provider: {provider_type}") + return self._providers[provider_type] + + def list_providers(self) -> list[str]: + return list(self._providers.keys()) + + +runtime_registry = RuntimeProviderRegistry() + + +def init_providers() -> None: + from .claude_code import ClaudeCodeProvider + from .codex import CodexProvider + from .openclaw import OpenClawProvider + + runtime_registry.register(ClaudeCodeProvider()) + runtime_registry.register(CodexProvider()) + runtime_registry.register(OpenClawProvider()) diff --git a/backend/app/core/agent/cli_backends/runner_callbacks.py b/backend/app/core/agent/cli_backends/runner_callbacks.py new file mode 100644 index 000000000..f684f6c53 --- /dev/null +++ b/backend/app/core/agent/cli_backends/runner_callbacks.py @@ -0,0 +1,36 @@ +""" +Callback protocol for ExecutionRunner — breaks circular dependency. + +ExecutionRunner calls these hooks after finalize/failure. +The concrete implementation lives in ExecutionLifecycleService. +""" + +from __future__ import annotations + +import uuid +from typing import Protocol, runtime_checkable + +from app.core.agent.cli_backends.base import CLIResult +from app.models.execution import MissionExecutionStatus + + +@runtime_checkable +class RunnerCallbacks(Protocol): + """Interface that ExecutionRunner uses to notify lifecycle events.""" + + async def on_execution_finalized( + self, + execution_id: uuid.UUID, + status: MissionExecutionStatus, + result: CLIResult, + ) -> None: + """Called after execution reaches terminal state (COMPLETED/FAILED).""" + ... + + async def on_execution_failed( + self, + execution_id: uuid.UUID, + error: str, + ) -> None: + """Called when runner catches an unhandled exception.""" + ... diff --git a/backend/app/core/agent/cli_backends/session_registry.py b/backend/app/core/agent/cli_backends/session_registry.py new file mode 100644 index 000000000..b3b92cd1a --- /dev/null +++ b/backend/app/core/agent/cli_backends/session_registry.py @@ -0,0 +1,28 @@ +"""In-memory registry of active RuntimeSessions, keyed by execution_id.""" + +from __future__ import annotations + +import uuid +from typing import Optional + +from .base import RuntimeSession + + +class SessionRegistry: + """Thread-safe registry of active execution sessions.""" + + def __init__(self) -> None: + self._sessions: dict[uuid.UUID, RuntimeSession] = {} + + def register(self, execution_id: uuid.UUID, session: RuntimeSession) -> None: + self._sessions[execution_id] = session + + def get(self, execution_id: uuid.UUID) -> Optional[RuntimeSession]: + return self._sessions.get(execution_id) + + def unregister(self, execution_id: uuid.UUID) -> None: + self._sessions.pop(execution_id, None) + + +# Module-level singleton +session_registry = SessionRegistry() diff --git a/backend/app/core/agent/code_agent/interpreter/ast_evaluator.py b/backend/app/core/agent/code_agent/interpreter/ast_evaluator.py index 93b63ca66..d68063416 100644 --- a/backend/app/core/agent/code_agent/interpreter/ast_evaluator.py +++ b/backend/app/core/agent/code_agent/interpreter/ast_evaluator.py @@ -1335,13 +1335,6 @@ def evaluate_ast( elif isinstance(expression, ast.Delete): return evaluate_delete(expression, *common_params) - # Python 3.8 Index node (backward compatibility) - elif hasattr(ast, "Index") and isinstance(expression, ast.Index): - value = getattr(expression, "value", None) - if value is not None: - return evaluate_ast(value, *common_params) - raise InterpreterError("Index node has no value attribute") - else: raise InterpreterError(f"{expression.__class__.__name__} is not supported.") diff --git a/backend/app/core/agent/coordinator_tools.py b/backend/app/core/agent/coordinator_tools.py new file mode 100644 index 000000000..1b400b983 --- /dev/null +++ b/backend/app/core/agent/coordinator_tools.py @@ -0,0 +1,171 @@ +"""LangGraph tools for Coordinator agents to spawn and manage CLI agents.""" + +from __future__ import annotations + +import asyncio +import uuid + +from loguru import logger + +from app.core.agent.cli_backends.base import CLIResult +from app.core.agent.cli_backends.execution_runner import ExecutionRunner +from app.core.database import async_session_factory +from app.models.execution import ExecutionSource, MissionExecutionStatus +from app.services.execution_service import ExecutionService +from app.utils.safe_task import safe_create_task + + +async def spawn_agent( + agent_name: str, + prompt: str, + *, + workspace_id: str, + user_id: str, + parent_execution_id: str, + runtime_type: str = "claude_code", + model: str | None = None, + wait: bool = True, + timeout: int = 3600, +) -> dict: + """ + Spawn a CLI agent to execute a sub-task. + + Args: + agent_name: Display name for the spawned agent + prompt: Task description for the agent + workspace_id: Workspace context + user_id: User who initiated the parent execution + parent_execution_id: The coordinator's execution ID + runtime_type: CLI type ("claude_code", "codex", "openclaw") + model: Optional model override + wait: If True, wait for completion and return result + timeout: Max wait time in seconds + + Returns: + dict with execution_id, status, and output (if wait=True) + """ + ws_id = uuid.UUID(workspace_id) + parent_id = uuid.UUID(parent_execution_id) + + # Create child execution + async with async_session_factory() as db: + svc = ExecutionService(db) + execution = await svc.create_execution( + user_id=user_id, + workspace_id=ws_id, + source=ExecutionSource.COORDINATOR, + runtime_type=runtime_type, + title=f"[Sub] {agent_name}: {prompt[:80]}", + parent_execution_id=parent_id, + ) + exec_id = execution.id + + logger.info(f"Coordinator spawned {agent_name} ({runtime_type}) -> execution {exec_id}") + + if wait: + return await _run_and_wait(exec_id, prompt, ws_id, user_id, runtime_type, model, timeout, agent_name) + else: + _fire_and_forget(exec_id, prompt, ws_id, user_id, runtime_type, model) + return { + "execution_id": str(exec_id), + "status": "dispatched", + "output": "", + } + + +async def _run_and_wait( + exec_id: uuid.UUID, + prompt: str, + ws_id: uuid.UUID, + user_id: str, + runtime_type: str, + model: str | None, + timeout: int, + agent_name: str, +) -> dict: + """Run the execution synchronously and return the result.""" + try: + async with async_session_factory() as db: + runner = ExecutionRunner(db) + result: CLIResult = await asyncio.wait_for( + runner.run( + execution_id=exec_id, + prompt=prompt, + model=model, + timeout=timeout, + ), + timeout=timeout, + ) + return { + "execution_id": str(exec_id), + "status": result.status, + "output": result.output[:5000], + "session_id": result.session_id, + } + except asyncio.TimeoutError: + return { + "execution_id": str(exec_id), + "status": "timeout", + "output": f"Agent '{agent_name}' timed out after {timeout}s", + } + except Exception as e: + logger.error(f"spawn_agent error for {exec_id}: {e}") + return { + "execution_id": str(exec_id), + "status": "failed", + "output": str(e)[:2000], + } + + +def _fire_and_forget( + exec_id: uuid.UUID, + prompt: str, + ws_id: uuid.UUID, + user_id: str, + runtime_type: str, + model: str | None, +) -> None: + """Dispatch execution as a background task.""" + + async def _background(): + async with async_session_factory() as db: + runner = ExecutionRunner(db) + await runner.run(execution_id=exec_id, prompt=prompt, model=model) + + safe_create_task( + _background(), + name=f"coordinator-child-{exec_id}", + ) + + +async def get_agent_result(execution_id: str, *, user_id: str) -> dict: + """ + Get the result of a previously spawned agent. + + Args: + execution_id: The execution ID returned by spawn_agent + user_id: The user who owns the execution + + Returns: + dict with status and output + """ + exec_id = uuid.UUID(execution_id) + + async with async_session_factory() as db: + svc = ExecutionService(db) + execution = await svc.get_execution(exec_id, user_id) + + if not execution: + return {"status": "not_found", "output": ""} + + status = execution.status.value if hasattr(execution.status, "value") else str(execution.status) + + if status == MissionExecutionStatus.COMPLETED.value: + output = "" + if execution.result_summary: + output = execution.result_summary.get("output", "") + return {"status": "completed", "output": output} + elif status == MissionExecutionStatus.FAILED.value: + return {"status": "failed", "output": execution.error_message or "Unknown error"} + else: + return {"status": status, "output": f"Agent is still {status}"} diff --git a/backend/app/core/agent/memory/manager.py b/backend/app/core/agent/memory/manager.py index b76872031..e55fdff32 100644 --- a/backend/app/core/agent/memory/manager.py +++ b/backend/app/core/agent/memory/manager.py @@ -394,9 +394,9 @@ def clear(self) -> None: if self.db: result = self.db.clear_memories() if hasattr(result, "__await__"): - import asyncio + from app.utils.safe_task import safe_create_task - asyncio.create_task(result) # type: ignore[unused-coroutine] + safe_create_task(result, name="memory-clear") # type: ignore[arg-type] def delete_user_memory( self, @@ -683,13 +683,13 @@ def _upsert_db_memory(self, memory: UserMemory) -> str: raise ValueError("Memory db not initialized") result = self.db.upsert_user_memory(memory=memory) if hasattr(result, "__await__"): - import asyncio + from app.utils.safe_task import safe_create_task - asyncio.create_task(result) # type: ignore[unused-coroutine] - return "Memory added successfully" + safe_create_task(result, name="memory-upsert") # type: ignore[arg-type] except Exception as e: logger.warning(f"Error storing memory in db: {e}") return f"Error adding memory: {e}" + return "" def _delete_db_memory(self, memory_id: str, user_id: Optional[str] = None) -> str: """Use this function to delete a memory from the database.""" @@ -702,13 +702,13 @@ def _delete_db_memory(self, memory_id: str, user_id: Optional[str] = None) -> st result = self.db.delete_user_memory(memory_id=memory_id, user_id=user_id) if hasattr(result, "__await__"): - import asyncio + from app.utils.safe_task import safe_create_task - asyncio.create_task(result) # type: ignore[unused-coroutine] - return "Memory deleted successfully" + safe_create_task(result, name="memory-delete") # type: ignore[arg-type] except Exception as e: logger.warning(f"Error deleting memory in db: {e}") return f"Error deleting memory: {e}" + return "" # -*- Utility Functions def search_user_memories( diff --git a/backend/app/core/ai_adapter.py b/backend/app/core/ai_adapter.py index fc997a160..7468e66f5 100644 --- a/backend/app/core/ai_adapter.py +++ b/backend/app/core/ai_adapter.py @@ -64,7 +64,7 @@ def __init__( self.engine = engine # Create per-session directories using configured workspace root - workspace_root = Path(settings.WORKSPACE_ROOT) + workspace_root = Path(settings.workspace_root) self.session_dir = workspace_root / "sessions" / session_id self.session_dir.mkdir(parents=True, exist_ok=True) diff --git a/backend/app/core/copilot_deepagents/manager.py b/backend/app/core/copilot_deepagents/manager.py index ab28e2450..56cb21dd0 100644 --- a/backend/app/core/copilot_deepagents/manager.py +++ b/backend/app/core/copilot_deepagents/manager.py @@ -193,10 +193,3 @@ def create_copilot_manager( logger.info(f"[DeepAgentsCopilot] Created manager run_id={run_id} run_dir={run_dir}") return manager, store - - -# ==================== Schema Validation Helpers (Moved to .utils) ==================== - -# Re-exporting from .utils if needed, but better to import directly from .utils - -# ==================== Helpers (Moved to .utils) ==================== diff --git a/backend/app/core/scheduler.py b/backend/app/core/scheduler.py new file mode 100644 index 000000000..a22eb7050 --- /dev/null +++ b/backend/app/core/scheduler.py @@ -0,0 +1,119 @@ +""" +Background scheduler loops for mission auto-dispatch and stale execution reaping. + +Registered in app lifespan (main.py). Each function is an infinite async loop +following the same pattern as _container_reaper. +""" + +from __future__ import annotations + +import asyncio +from datetime import timedelta + +from loguru import logger + +from app.core.agent.cli_backends.session_registry import session_registry +from app.core.database import AsyncSessionLocal +from app.models.execution import MissionExecutionStatus +from app.repositories.execution import ExecutionRepository +from app.services.execution_lifecycle_service import ExecutionLifecycleService +from app.services.execution_service import ExecutionService +from app.utils.datetime import utc_now + +_DISPATCH_INTERVAL = 30 +_REAPER_INTERVAL = 30 + +_STALE_THRESHOLDS: list[tuple[tuple[MissionExecutionStatus, ...], timedelta]] = [ + ( + (MissionExecutionStatus.QUEUED, MissionExecutionStatus.DISPATCHED), + timedelta(minutes=5), + ), + ( + (MissionExecutionStatus.RUNNING,), + timedelta(minutes=10), + ), + ( + (MissionExecutionStatus.APPROVAL_WAIT,), + timedelta(minutes=60), + ), +] + + +async def mission_dispatcher_loop() -> None: + """Every 30s, find TODO missions with agent assignees and dispatch them.""" + while True: + await asyncio.sleep(_DISPATCH_INTERVAL) + try: + async with AsyncSessionLocal() as db: + lifecycle = ExecutionLifecycleService(db) + count = await lifecycle.dispatch_all_ready_missions() + if count: + logger.info(f"Scheduler: auto-dispatched {count} missions") + except Exception as exc: + logger.warning(f"Mission dispatcher error: {exc}") + + +async def execution_reaper_loop() -> None: + """Every 30s, find stale executions and mark them failed.""" + while True: + await asyncio.sleep(_REAPER_INTERVAL) + try: + reaped = await _reap_stale_executions() + if reaped: + logger.info(f"Scheduler: reaped {reaped} stale executions") + except Exception as exc: + logger.warning(f"Execution reaper error: {exc}") + + +async def recover_stale_on_startup() -> None: + """One-shot: catch executions that went stale during downtime.""" + try: + reaped = await _reap_stale_executions() + if reaped: + logger.info(f"Startup recovery: reaped {reaped} stale executions") + else: + logger.info("Startup recovery: no stale executions found") + except Exception as exc: + logger.warning(f"Startup stale execution recovery failed: {exc}") + + +async def _reap_stale_executions() -> int: + """Shared logic for reaper loop and startup recovery.""" + now = utc_now() + total = 0 + + async with AsyncSessionLocal() as db: + exec_repo = ExecutionRepository(db) + exec_svc = ExecutionService(db) + lifecycle = ExecutionLifecycleService(db) + + for statuses, threshold in _STALE_THRESHOLDS: + stale = await exec_repo.list_recoverable_stale( + statuses=statuses, + stale_before=now - threshold, + ) + for execution in stale: + try: + session = session_registry.get(execution.id) + if session: + await session.cancel() + + await exec_svc.mark_status( + execution_id=execution.id, + status=MissionExecutionStatus.FAILED, + error_code="stale_reaped", + error_message=f"No heartbeat for {int(threshold.total_seconds() // 60)}+ minutes", + ) + + if execution.mission_id: + await lifecycle._finalize_mission(execution.id, MissionExecutionStatus.FAILED) + + total += 1 + logger.info( + f"Reaped stale execution {execution.id} " + f"(status={execution.status.value}, age={now - (execution.last_heartbeat_at or execution.updated_at)})" + ) + except Exception as exc: + logger.warning(f"Failed to reap execution {execution.id}: {exc}") + + return total diff --git a/backend/app/core/settings.py b/backend/app/core/settings.py index f1180e122..3c8de5e9d 100644 --- a/backend/app/core/settings.py +++ b/backend/app/core/settings.py @@ -368,11 +368,6 @@ def parse_cors_origins(cls, v: Union[str, List[str]]) -> List[str]: description="Workspace root directory for storing session files and workspace data", ) - @property - def WORKSPACE_ROOT(self) -> str: - """Alias for workspace_root for backward compatibility""" - return self.workspace_root - # OAuth Configuration oauth_config_path: Optional[str] = Field( default=None, diff --git a/backend/app/main.py b/backend/app/main.py index 7ef2b5f0f..4f4d477c1 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -2,29 +2,37 @@ FastAPI Main Application """ -import asyncio -from contextlib import asynccontextmanager -from datetime import datetime, timedelta, timezone -from typing import AsyncGenerator - -from fastapi import FastAPI, WebSocket, WebSocketDisconnect -from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import JSONResponse -from loguru import logger -from sqlalchemy import text - -from app.api import api_router -from app.api.v1.sessions import router as sessions_router -from app.common.exceptions import register_exception_handlers -from app.common.logging import LoggingMiddleware, setup_logging -from app.core.database import AsyncSessionLocal, close_db, engine -from app.core.redis import RedisClient -from app.core.settings import settings -from app.websocket.auth import WebSocketCloseCode, authenticate_websocket, reject_websocket -from app.websocket.chat_ws_handler import ChatWsHandler -from app.websocket.notification_manager import NotificationType, notification_manager -from app.websocket.openclaw_handler import openclaw_bridge_handler -from app.websocket.run_subscription_handler import run_subscription_handler +from __future__ import annotations + +import asyncio # noqa: E402 +from contextlib import asynccontextmanager # noqa: E402 +from datetime import datetime, timedelta, timezone # noqa: E402 +from typing import AsyncGenerator, Optional # noqa: E402 + +from dotenv import load_dotenv # noqa: E402 + +from app.core.settings import ENV_FILE # noqa: E402 + +load_dotenv(ENV_FILE, override=False) + +from fastapi import FastAPI, WebSocket, WebSocketDisconnect # noqa: E402 +from fastapi.middleware.cors import CORSMiddleware # noqa: E402 +from loguru import logger # noqa: E402 +from sqlalchemy import text # noqa: E402 + +from app.api import api_router # noqa: E402 +from app.api.v1.sessions import router as sessions_router # noqa: E402 +from app.common.exceptions import register_exception_handlers # noqa: E402 +from app.common.logging import LoggingMiddleware, setup_logging # noqa: E402 +from app.core.database import AsyncSessionLocal, close_db, engine # noqa: E402 +from app.core.redis import RedisClient # noqa: E402 +from app.core.settings import settings # noqa: E402 +from app.websocket.auth import WebSocketCloseCode, authenticate_websocket, reject_websocket # noqa: E402 +from app.websocket.chat_ws_handler import ChatWsHandler # noqa: E402 +from app.websocket.execution_subscription_handler import execution_subscription_handler # noqa: E402 +from app.websocket.notification_manager import NotificationType, notification_manager # noqa: E402 +from app.websocket.openclaw_handler import openclaw_bridge_handler # noqa: E402 +from app.websocket.run_subscription_handler import run_subscription_handler # noqa: E402 setup_logging() @@ -191,8 +199,70 @@ async def lifespan(app: FastAPI) -> AsyncGenerator: logger.warning(f" ⚠️ Checkpointer initialization failed: {e}") logger.warning(" App will continue starting, checkpoint features may be unavailable") + # Initialize CLI runtime providers + try: + from app.core.agent.cli_backends.registry import init_providers + + init_providers() + logger.info(" ✓ CLI runtime providers initialized") + except Exception as e: + logger.warning(f" ⚠️ CLI runtime provider initialization failed: {e}") + + # Start container pool reaper (idle containers cleaned up every 5 min) + _reaper_task: Optional[asyncio.Task] = None + try: + from app.core.agent.cli_backends.container_pool import container_pool + + async def _container_reaper() -> None: + while True: + await asyncio.sleep(300) + try: + removed = await container_pool.cleanup_idle() + if removed: + logger.info(f"Container reaper: removed {removed} idle containers") + except Exception as e: + logger.warning(f"Container reaper error: {e}") + + _reaper_task = asyncio.create_task(_container_reaper(), name="container-reaper") + logger.info(" ✓ Container pool reaper started (idle_timeout=30m)") + except Exception as e: + logger.warning(f" ⚠️ Container pool reaper failed to start: {e}") + + # Scheduler: stale execution recovery (one-shot) + periodic loops + _dispatcher_task: Optional[asyncio.Task] = None + _exec_reaper_task: Optional[asyncio.Task] = None + try: + from app.core.scheduler import ( + execution_reaper_loop, + mission_dispatcher_loop, + recover_stale_on_startup, + ) + + await recover_stale_on_startup() + _dispatcher_task = asyncio.create_task(mission_dispatcher_loop(), name="mission-dispatcher") + _exec_reaper_task = asyncio.create_task(execution_reaper_loop(), name="execution-reaper") + logger.info(" ✓ Mission dispatcher and execution reaper started (interval=30s)") + except Exception as e: + logger.warning(f" ⚠️ Scheduler startup failed: {e}") + yield + # Shutdown: Cancel scheduler loops + for task in (_dispatcher_task, _exec_reaper_task): + if task: + task.cancel() + + # Shutdown: Cancel container pool reaper and mark pool as shut down + try: + if _reaper_task: + _reaper_task.cancel() + from app.core.agent.cli_backends.container_pool import container_pool as _cp + + await _cp.shutdown() + logger.info(" ✓ Container pool shut down (containers left running)") + except Exception as e: + logger.warning(f" ⚠️ Container pool shutdown failed: {e}") + # Shutdown: Drain sandbox pool (stop all containers gracefully) try: from app.services.sandbox_manager import _sandbox_pool @@ -254,16 +324,6 @@ async def lifespan(app: FastAPI) -> AsyncGenerator: ) -@app.exception_handler(Exception) -async def global_exception_handler(request, exc): - """Global exception handler""" - logger.opt(exception=True).error(f"Unhandled exception: {exc}") - return JSONResponse( - status_code=500, - content={"detail": "Internal server error"}, - ) - - app.include_router(api_router, prefix="/api") # Sessions router mounted outside /api/v1 to keep /api/sessions path compatible @@ -347,6 +407,18 @@ async def runs_websocket_endpoint(websocket: WebSocket): await run_subscription_handler.handle_connection(websocket, str(user_id)) +@app.websocket("/ws/executions") +async def executions_websocket_endpoint(websocket: WebSocket): + """Subscription endpoint for CLI execution snapshot/replay/live events.""" + is_authenticated, user_id = await authenticate_websocket(websocket) + + if not is_authenticated or not user_id: + await reject_websocket(websocket, code=WebSocketCloseCode.UNAUTHORIZED, reason="Authentication required") + return + + await execution_subscription_handler.handle_connection(websocket, str(user_id)) + + @app.websocket("/ws/openclaw/dashboard") async def openclaw_dashboard_websocket_endpoint(websocket: WebSocket): """WebSocket proxy for Control UI — auth from cookie, no user_id in path.""" diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py index 761a6150f..148ecde37 100644 --- a/backend/app/models/__init__.py +++ b/backend/app/models/__init__.py @@ -11,12 +11,14 @@ WorkspaceInvitation, WorkspaceInvitationStatus, ) +from .agent_profile import AgentProfile, AgentStatus from .agent_run import AgentRun, AgentRunEvent, AgentRunSnapshot, AgentRunStatus from .auth import AuthSession, AuthUser from .auth import AuthUser as User from .base import BaseModel, SoftDeleteMixin, TimestampMixin from .chat import Chat from .custom_tool import CustomTool +from .execution import Execution, ExecutionEvent, ExecutionSnapshot, ExecutionSource, MissionExecutionStatus from .execution_trace import ( ExecutionObservation, ExecutionTrace, @@ -30,6 +32,8 @@ from .graph_execution import ExecutionStatus, GraphExecution from .mcp import McpServer from .memory import Memory +from .mission import Mission, MissionPriority, MissionStatus +from .mission_comment import CommentAuthorType, CommentType, MissionComment from .model_credential import ModelCredential from .model_instance import ModelInstance from .model_provider import ModelProvider @@ -106,4 +110,17 @@ "SkillVersion", "SkillVersionFile", "PlatformToken", + "Mission", + "MissionStatus", + "MissionPriority", + "AgentProfile", + "AgentStatus", + "Execution", + "ExecutionEvent", + "ExecutionSnapshot", + "ExecutionSource", + "MissionExecutionStatus", + "MissionComment", + "CommentAuthorType", + "CommentType", ] diff --git a/backend/app/models/agent_profile.py b/backend/app/models/agent_profile.py new file mode 100644 index 000000000..50322418b --- /dev/null +++ b/backend/app/models/agent_profile.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import enum +import uuid +from typing import Optional + +from sqlalchemy import Enum, ForeignKey, Index, Integer, String, Text +from sqlalchemy.dialects.postgresql import JSONB, UUID +from sqlalchemy.orm import Mapped, mapped_column + +from .base import BaseModel + + +class AgentStatus(str, enum.Enum): + IDLE = "idle" + WORKING = "working" + BLOCKED = "blocked" + ERROR = "error" + OFFLINE = "offline" + + +class AgentProfile(BaseModel): + __tablename__ = "agent_profiles" + + workspace_id: Mapped[uuid.UUID] = mapped_column( + UUID(as_uuid=True), + ForeignKey("workspaces.id", ondelete="CASCADE"), + nullable=False, + ) + name: Mapped[str] = mapped_column(String(255), nullable=False) + avatar: Mapped[Optional[str]] = mapped_column(String(500), nullable=True) + description: Mapped[Optional[str]] = mapped_column(Text, nullable=True) + + runtime_type: Mapped[str] = mapped_column(String(50), nullable=False) + status: Mapped[AgentStatus] = mapped_column( + Enum(AgentStatus, values_callable=lambda e: [m.value for m in e], name="agentstatus"), + nullable=False, + default=AgentStatus.OFFLINE, + ) + max_concurrent_tasks: Mapped[int] = mapped_column(Integer, nullable=False, default=1) + + skill_ids: Mapped[Optional[list]] = mapped_column(JSONB, nullable=True) + instructions: Mapped[Optional[str]] = mapped_column(Text, nullable=True) + custom_env: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True) + runtime_config: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True) + visibility: Mapped[str] = mapped_column(String(50), nullable=False, default="workspace") + + __table_args__ = ( + Index("agent_profiles_workspace_idx", "workspace_id"), + Index("agent_profiles_workspace_status_idx", "workspace_id", "status"), + ) diff --git a/backend/app/models/execution.py b/backend/app/models/execution.py new file mode 100644 index 000000000..f80c8e005 --- /dev/null +++ b/backend/app/models/execution.py @@ -0,0 +1,151 @@ +from __future__ import annotations + +import enum +import uuid +from datetime import datetime +from typing import Optional + +from sqlalchemy import BigInteger, DateTime, Enum, ForeignKey, Index, String, Text, UniqueConstraint +from sqlalchemy.dialects.postgresql import JSONB, UUID +from sqlalchemy.orm import Mapped, mapped_column + +from app.core.database import Base + +from .base import BaseModel, TimestampMixin + + +class MissionExecutionStatus(str, enum.Enum): + QUEUED = "queued" + DISPATCHED = "dispatched" + RUNNING = "running" + INTERRUPT_WAIT = "interrupt_wait" # Reserved: legacy AgentRun status, not used in execution flow + APPROVAL_WAIT = "approval_wait" + COMPLETED = "completed" + FAILED = "failed" + CANCELLED = "cancelled" + + +TERMINAL_EXECUTION_STATUSES: frozenset[MissionExecutionStatus] = frozenset( + { + MissionExecutionStatus.COMPLETED, + MissionExecutionStatus.FAILED, + MissionExecutionStatus.CANCELLED, + } +) + + +class ExecutionSource(str, enum.Enum): + MISSION = "mission" + CHAT = "chat" + GRAPH = "graph" + COORDINATOR = "coordinator" + API = "api" + + +class Execution(BaseModel): + __tablename__ = "executions" + + workspace_id: Mapped[uuid.UUID] = mapped_column( + UUID(as_uuid=True), + ForeignKey("workspaces.id", ondelete="CASCADE"), + nullable=False, + ) + user_id: Mapped[str] = mapped_column( + String(255), + ForeignKey("user.id", ondelete="CASCADE"), + nullable=False, + ) + + source: Mapped[ExecutionSource] = mapped_column( + Enum(ExecutionSource, values_callable=lambda e: [m.value for m in e], name="executionsource"), + nullable=False, + ) + status: Mapped[MissionExecutionStatus] = mapped_column( + Enum(MissionExecutionStatus, values_callable=lambda e: [m.value for m in e], name="missionexecutionstatus"), + nullable=False, + default=MissionExecutionStatus.QUEUED, + ) + title: Mapped[Optional[str]] = mapped_column(String(500), nullable=True) + + mission_id: Mapped[Optional[uuid.UUID]] = mapped_column( + UUID(as_uuid=True), + ForeignKey("missions.id", ondelete="SET NULL"), + nullable=True, + ) + agent_profile_id: Mapped[Optional[uuid.UUID]] = mapped_column( + UUID(as_uuid=True), + ForeignKey("agent_profiles.id", ondelete="SET NULL"), + nullable=True, + ) + parent_execution_id: Mapped[Optional[uuid.UUID]] = mapped_column( + UUID(as_uuid=True), + ForeignKey("executions.id", ondelete="SET NULL"), + nullable=True, + ) + + result_summary: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True) + error_code: Mapped[Optional[str]] = mapped_column(String(100), nullable=True) + error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True) + + runtime_type: Mapped[str] = mapped_column(String(50), nullable=False) + runtime_config: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True) + container_id: Mapped[Optional[str]] = mapped_column(String(255), nullable=True) + + started_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) + finished_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) + last_heartbeat_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) + + last_seq: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0) + + prior_session_id: Mapped[Optional[str]] = mapped_column(String(255), nullable=True) + session_id: Mapped[Optional[str]] = mapped_column(String(255), nullable=True) + work_dir: Mapped[Optional[str]] = mapped_column(String(500), nullable=True) + + trigger_comment_id: Mapped[Optional[uuid.UUID]] = mapped_column( + UUID(as_uuid=True), + ForeignKey("mission_comments.id", ondelete="SET NULL"), + nullable=True, + ) + + __table_args__ = ( + Index("executions_workspace_status_idx", "workspace_id", "status"), + Index("executions_mission_idx", "mission_id"), + Index("executions_agent_profile_idx", "agent_profile_id"), + Index("executions_parent_idx", "parent_execution_id"), + Index("executions_user_created_idx", "user_id", "created_at"), + Index("executions_trigger_comment_idx", "trigger_comment_id"), + ) + + +class ExecutionEvent(BaseModel): + __tablename__ = "execution_events" + + execution_id: Mapped[uuid.UUID] = mapped_column( + UUID(as_uuid=True), + ForeignKey("executions.id", ondelete="CASCADE"), + nullable=False, + ) + seq: Mapped[int] = mapped_column(BigInteger, nullable=False) + event_type: Mapped[str] = mapped_column(String(100), nullable=False) + payload: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict) + trace_id: Mapped[Optional[uuid.UUID]] = mapped_column(UUID(as_uuid=True), nullable=True) + observation_id: Mapped[Optional[uuid.UUID]] = mapped_column(UUID(as_uuid=True), nullable=True) + parent_observation_id: Mapped[Optional[uuid.UUID]] = mapped_column(UUID(as_uuid=True), nullable=True) + + __table_args__ = ( + UniqueConstraint("execution_id", "seq", name="uq_execution_events_exec_seq"), + Index("execution_events_exec_created_idx", "execution_id", "created_at"), + ) + + +class ExecutionSnapshot(Base, TimestampMixin): + __tablename__ = "execution_snapshots" + + execution_id: Mapped[uuid.UUID] = mapped_column( + UUID(as_uuid=True), + ForeignKey("executions.id", ondelete="CASCADE"), + primary_key=True, + ) + last_seq: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0) + status: Mapped[str] = mapped_column(String(100), nullable=False) + projection: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict) diff --git a/backend/app/models/mission.py b/backend/app/models/mission.py new file mode 100644 index 000000000..d275abc07 --- /dev/null +++ b/backend/app/models/mission.py @@ -0,0 +1,88 @@ +from __future__ import annotations + +import enum +import uuid +from datetime import datetime +from typing import Optional + +from sqlalchemy import Boolean, DateTime, Enum, Float, ForeignKey, Index, String, Text +from sqlalchemy.dialects.postgresql import JSONB, UUID +from sqlalchemy.orm import Mapped, mapped_column + +from .base import BaseModel + + +class MissionStatus(str, enum.Enum): + BACKLOG = "backlog" + TODO = "todo" + IN_PROGRESS = "in_progress" + IN_REVIEW = "in_review" + DONE = "done" + CANCELLED = "cancelled" + + +class AssigneeType(str, enum.Enum): + AGENT = "agent" + MEMBER = "member" + + +class MissionPriority(str, enum.Enum): + NONE = "none" + LOW = "low" + MEDIUM = "medium" + HIGH = "high" + URGENT = "urgent" + + +class Mission(BaseModel): + __tablename__ = "missions" + + workspace_id: Mapped[uuid.UUID] = mapped_column( + UUID(as_uuid=True), + ForeignKey("workspaces.id", ondelete="CASCADE"), + nullable=False, + ) + title: Mapped[str] = mapped_column(String(500), nullable=False) + description: Mapped[Optional[str]] = mapped_column(Text, nullable=True) + objective: Mapped[Optional[str]] = mapped_column(Text, nullable=True) + + status: Mapped[MissionStatus] = mapped_column( + Enum(MissionStatus, values_callable=lambda e: [m.value for m in e], name="missionstatus"), + nullable=False, + default=MissionStatus.BACKLOG, + ) + priority: Mapped[MissionPriority] = mapped_column( + Enum(MissionPriority, values_callable=lambda e: [m.value for m in e], name="missionpriority"), + nullable=False, + default=MissionPriority.NONE, + ) + + assignee_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True) + assignee_id: Mapped[Optional[uuid.UUID]] = mapped_column(UUID(as_uuid=True), nullable=True) + + creator_id: Mapped[str] = mapped_column( + String(255), + ForeignKey("user.id", ondelete="CASCADE"), + nullable=False, + ) + parent_mission_id: Mapped[Optional[uuid.UUID]] = mapped_column( + UUID(as_uuid=True), + ForeignKey("missions.id", ondelete="SET NULL"), + nullable=True, + ) + current_execution_id: Mapped[Optional[uuid.UUID]] = mapped_column( + UUID(as_uuid=True), + ForeignKey("executions.id", ondelete="SET NULL"), + nullable=True, + ) + + due_date: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) + position: Mapped[float] = mapped_column(Float, nullable=False, default=0.0) + tags: Mapped[Optional[list]] = mapped_column(JSONB, nullable=True) + auto_approve: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) + + __table_args__ = ( + Index("missions_workspace_status_idx", "workspace_id", "status"), + Index("missions_assignee_idx", "assignee_type", "assignee_id"), + Index("missions_creator_idx", "creator_id", "created_at"), + ) diff --git a/backend/app/models/mission_comment.py b/backend/app/models/mission_comment.py new file mode 100644 index 000000000..dd888fbba --- /dev/null +++ b/backend/app/models/mission_comment.py @@ -0,0 +1,61 @@ +from __future__ import annotations + +import enum +import uuid +from typing import Optional + +from sqlalchemy import Enum, ForeignKey, Index, String, Text +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import Mapped, mapped_column + +from .base import BaseModel + + +class CommentAuthorType(str, enum.Enum): + MEMBER = "member" + AGENT = "agent" + + +class CommentType(str, enum.Enum): + COMMENT = "comment" + STATUS_CHANGE = "status_change" + PROGRESS_UPDATE = "progress_update" + SYSTEM = "system" + + +class MissionComment(BaseModel): + __tablename__ = "mission_comments" + + mission_id: Mapped[uuid.UUID] = mapped_column( + UUID(as_uuid=True), + ForeignKey("missions.id", ondelete="CASCADE"), + nullable=False, + ) + workspace_id: Mapped[uuid.UUID] = mapped_column( + UUID(as_uuid=True), + ForeignKey("workspaces.id", ondelete="CASCADE"), + nullable=False, + ) + author_type: Mapped[CommentAuthorType] = mapped_column( + Enum(CommentAuthorType, values_callable=lambda e: [m.value for m in e], name="commentauthortype"), + nullable=False, + ) + author_id: Mapped[str] = mapped_column(String(255), nullable=False) + content: Mapped[str] = mapped_column(Text, nullable=False) + type: Mapped[CommentType] = mapped_column( + Enum(CommentType, values_callable=lambda e: [m.value for m in e], name="commenttype"), + nullable=False, + default=CommentType.COMMENT, + ) + parent_comment_id: Mapped[Optional[uuid.UUID]] = mapped_column( + UUID(as_uuid=True), + ForeignKey("mission_comments.id", ondelete="SET NULL"), + nullable=True, + ) + + __table_args__ = ( + Index("mission_comments_mission_created_idx", "mission_id", "created_at"), + Index("mission_comments_workspace_idx", "workspace_id"), + Index("mission_comments_author_idx", "author_type", "author_id"), + Index("mission_comments_parent_idx", "parent_comment_id"), + ) diff --git a/backend/app/repositories/agent_profile.py b/backend/app/repositories/agent_profile.py new file mode 100644 index 000000000..17bfb4097 --- /dev/null +++ b/backend/app/repositories/agent_profile.py @@ -0,0 +1,62 @@ +""" +AgentProfile repository helpers. +""" + +from __future__ import annotations + +import uuid +from typing import Optional, Sequence + +from sqlalchemy import desc, select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.agent_profile import AgentProfile, AgentStatus + +from .base import BaseRepository + + +class AgentProfileRepository(BaseRepository[AgentProfile]): + def __init__(self, db: AsyncSession): + super().__init__(AgentProfile, db) + + async def get_by_id_and_workspace(self, profile_id: uuid.UUID, workspace_id: uuid.UUID) -> Optional[AgentProfile]: + result = await self.db.execute( + select(AgentProfile).where( + AgentProfile.id == profile_id, + AgentProfile.workspace_id == workspace_id, + ) + ) + return result.scalar_one_or_none() + + async def list_by_workspace( + self, + *, + workspace_id: uuid.UUID, + status: Optional[str] = None, + runtime_type: Optional[str] = None, + limit: int = 100, + ) -> Sequence[AgentProfile]: + query = select(AgentProfile).where(AgentProfile.workspace_id == workspace_id) + if status: + query = query.where(AgentProfile.status == status) + if runtime_type: + query = query.where(AgentProfile.runtime_type == runtime_type) + result = await self.db.execute(query.order_by(desc(AgentProfile.created_at)).limit(limit)) + return result.scalars().all() + + async def find_available( + self, *, workspace_id: uuid.UUID, runtime_type: Optional[str] = None + ) -> Sequence[AgentProfile]: + """Find agents in IDLE status that can accept new tasks.""" + query = select(AgentProfile).where( + AgentProfile.workspace_id == workspace_id, + AgentProfile.status == AgentStatus.IDLE, + ) + if runtime_type: + query = query.where(AgentProfile.runtime_type == runtime_type) + result = await self.db.execute(query.order_by(AgentProfile.created_at.asc())) + return result.scalars().all() + + async def get_for_update(self, profile_id: uuid.UUID) -> Optional[AgentProfile]: + result = await self.db.execute(select(AgentProfile).where(AgentProfile.id == profile_id).with_for_update()) + return result.scalar_one_or_none() diff --git a/backend/app/repositories/agent_run.py b/backend/app/repositories/agent_run.py index afe3e8a07..1f26072ba 100644 --- a/backend/app/repositories/agent_run.py +++ b/backend/app/repositories/agent_run.py @@ -55,21 +55,6 @@ async def get_run_for_update(self, run_id: uuid.UUID, user_id: Optional[str] = N result = await self.db.execute(query.with_for_update()) return result.scalar_one_or_none() - async def find_latest_active_skill_creator_run( - self, - *, - user_id: str, - graph_id: uuid.UUID, - thread_id: Optional[str] = None, - ) -> Optional[AgentRun]: - # Wrapper kept for backward compatibility with external callers. - return await self.find_latest_active_run( - user_id=user_id, - agent_name="skill_creator", - graph_id=graph_id, - thread_id=thread_id, - ) - async def find_latest_active_run( self, *, diff --git a/backend/app/repositories/execution.py b/backend/app/repositories/execution.py new file mode 100644 index 000000000..7fbc79096 --- /dev/null +++ b/backend/app/repositories/execution.py @@ -0,0 +1,111 @@ +""" +Execution repository helpers. +""" + +from __future__ import annotations + +import uuid +from datetime import datetime +from typing import Optional, Sequence + +from sqlalchemy import and_, desc, or_, select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.execution import Execution, ExecutionEvent, ExecutionSnapshot, MissionExecutionStatus + +from .base import BaseRepository + + +class ExecutionRepository(BaseRepository[Execution]): + def __init__(self, db: AsyncSession): + super().__init__(Execution, db) + + async def get_by_id_and_user(self, execution_id: uuid.UUID, user_id: str) -> Optional[Execution]: + result = await self.db.execute( + select(Execution).where( + Execution.id == execution_id, + Execution.user_id == user_id, + ) + ) + return result.scalar_one_or_none() + + async def get_for_update(self, execution_id: uuid.UUID, user_id: Optional[str] = None) -> Optional[Execution]: + query = select(Execution).where(Execution.id == execution_id) + if user_id is not None: + query = query.where(Execution.user_id == user_id) + result = await self.db.execute(query.with_for_update()) + return result.scalar_one_or_none() + + async def get_snapshot(self, execution_id: uuid.UUID) -> Optional[ExecutionSnapshot]: + result = await self.db.execute(select(ExecutionSnapshot).where(ExecutionSnapshot.execution_id == execution_id)) + return result.scalar_one_or_none() + + async def list_events_after( + self, execution_id: uuid.UUID, after_seq: int = 0, limit: int = 500 + ) -> Sequence[ExecutionEvent]: + result = await self.db.execute( + select(ExecutionEvent) + .where( + ExecutionEvent.execution_id == execution_id, + ExecutionEvent.seq > after_seq, + ) + .order_by(ExecutionEvent.seq.asc()) + .limit(limit) + ) + return result.scalars().all() + + async def list_by_workspace( + self, + *, + workspace_id: uuid.UUID, + user_id: Optional[str] = None, + status: Optional[str] = None, + source: Optional[str] = None, + mission_id: Optional[uuid.UUID] = None, + limit: int = 50, + ) -> Sequence[Execution]: + query = select(Execution).where(Execution.workspace_id == workspace_id) + if user_id: + query = query.where(Execution.user_id == user_id) + if status: + query = query.where(Execution.status == status) + if source: + query = query.where(Execution.source == source) + if mission_id: + query = query.where(Execution.mission_id == mission_id) + result = await self.db.execute(query.order_by(desc(Execution.created_at)).limit(limit)) + return result.scalars().all() + + async def list_children(self, parent_execution_id: uuid.UUID) -> Sequence[Execution]: + result = await self.db.execute( + select(Execution).where(Execution.parent_execution_id == parent_execution_id).order_by(Execution.created_at) + ) + return result.scalars().all() + + async def list_recoverable_stale( + self, + *, + stale_before: datetime, + statuses: tuple[MissionExecutionStatus, ...] | None = None, + ) -> Sequence[Execution]: + if statuses is None: + statuses = ( + MissionExecutionStatus.QUEUED, + MissionExecutionStatus.DISPATCHED, + MissionExecutionStatus.RUNNING, + ) + result = await self.db.execute( + select(Execution) + .where( + Execution.status.in_(statuses), + or_( + and_( + Execution.last_heartbeat_at.is_(None), + Execution.updated_at < stale_before, + ), + Execution.last_heartbeat_at < stale_before, + ), + ) + .order_by(desc(Execution.updated_at)) + ) + return result.scalars().all() diff --git a/backend/app/repositories/mission.py b/backend/app/repositories/mission.py new file mode 100644 index 000000000..938a65d2e --- /dev/null +++ b/backend/app/repositories/mission.py @@ -0,0 +1,78 @@ +""" +Mission repository helpers. +""" + +from __future__ import annotations + +import uuid +from typing import Optional, Sequence + +from sqlalchemy import desc, select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.mission import AssigneeType, Mission, MissionStatus + +from .base import BaseRepository + + +class MissionRepository(BaseRepository[Mission]): + def __init__(self, db: AsyncSession): + super().__init__(Mission, db) + + async def get_by_id_and_workspace(self, mission_id: uuid.UUID, workspace_id: uuid.UUID) -> Optional[Mission]: + result = await self.db.execute( + select(Mission).where( + Mission.id == mission_id, + Mission.workspace_id == workspace_id, + ) + ) + return result.scalar_one_or_none() + + async def get_for_update( + self, mission_id: uuid.UUID, workspace_id: Optional[uuid.UUID] = None + ) -> Optional[Mission]: + query = select(Mission).where(Mission.id == mission_id) + if workspace_id is not None: + query = query.where(Mission.workspace_id == workspace_id) + result = await self.db.execute(query.with_for_update()) + return result.scalar_one_or_none() + + async def list_by_workspace( + self, + *, + workspace_id: uuid.UUID, + status: Optional[str] = None, + creator_id: Optional[str] = None, + assignee_id: Optional[uuid.UUID] = None, + parent_mission_id: Optional[uuid.UUID] = None, + limit: int = 50, + ) -> Sequence[Mission]: + query = select(Mission).where(Mission.workspace_id == workspace_id) + if status: + query = query.where(Mission.status == status) + if creator_id: + query = query.where(Mission.creator_id == creator_id) + if assignee_id: + query = query.where(Mission.assignee_id == assignee_id) + if parent_mission_id: + query = query.where(Mission.parent_mission_id == parent_mission_id) + result = await self.db.execute(query.order_by(Mission.position.asc(), desc(Mission.created_at)).limit(limit)) + return result.scalars().all() + + async def list_dispatchable( + self, *, workspace_id: Optional[uuid.UUID] = None, limit: int = 10 + ) -> Sequence[Mission]: + """Find TODO missions with an agent assignee, ready for dispatch. + + When workspace_id is None, searches across all workspaces. + """ + query = select(Mission).where( + Mission.status == MissionStatus.TODO, + Mission.assignee_type == AssigneeType.AGENT, + Mission.assignee_id.isnot(None), + Mission.current_execution_id.is_(None), + ) + if workspace_id is not None: + query = query.where(Mission.workspace_id == workspace_id) + result = await self.db.execute(query.order_by(Mission.position.asc(), Mission.created_at.asc()).limit(limit)) + return result.scalars().all() diff --git a/backend/app/repositories/mission_comment.py b/backend/app/repositories/mission_comment.py new file mode 100644 index 000000000..a83f50a43 --- /dev/null +++ b/backend/app/repositories/mission_comment.py @@ -0,0 +1,67 @@ +""" +MissionComment repository helpers. +""" + +from __future__ import annotations + +import uuid +from datetime import datetime +from typing import Optional, Sequence + +from sqlalchemy import asc, desc, literal, select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.mission_comment import CommentAuthorType, MissionComment + +from .base import BaseRepository + + +class MissionCommentRepository(BaseRepository[MissionComment]): + def __init__(self, db: AsyncSession): + super().__init__(MissionComment, db) + + async def list_by_mission( + self, + mission_id: uuid.UUID, + *, + cursor: Optional[datetime] = None, + limit: int = 50, + order_asc: bool = True, + ) -> Sequence[MissionComment]: + query = select(MissionComment).where(MissionComment.mission_id == mission_id) + if cursor is not None: + if order_asc: + query = query.where(MissionComment.created_at > cursor) + else: + query = query.where(MissionComment.created_at < cursor) + order = asc(MissionComment.created_at) if order_asc else desc(MissionComment.created_at) + result = await self.db.execute(query.order_by(order).limit(limit)) + return result.scalars().all() + + async def get_by_id_and_mission(self, comment_id: uuid.UUID, mission_id: uuid.UUID) -> Optional[MissionComment]: + result = await self.db.execute( + select(MissionComment).where( + MissionComment.id == comment_id, + MissionComment.mission_id == mission_id, + ) + ) + return result.scalar_one_or_none() + + async def has_agent_commented_since( + self, + mission_id: uuid.UUID, + agent_id: str, + since: datetime, + ) -> bool: + stmt = ( + select(literal(True)) + .where( + MissionComment.mission_id == mission_id, + MissionComment.author_type == CommentAuthorType.AGENT, + MissionComment.author_id == agent_id, + MissionComment.created_at >= since, + ) + .limit(1) + ) + result = await self.db.execute(stmt) + return result.scalar() is not None diff --git a/backend/app/repositories/model_instance.py b/backend/app/repositories/model_instance.py index 60d845e60..51c4d99a9 100644 --- a/backend/app/repositories/model_instance.py +++ b/backend/app/repositories/model_instance.py @@ -32,7 +32,6 @@ async def get_best_instance( self, model_name: str, provider_id: uuid.UUID, - provider_name: str = "", # kept for call-site compatibility; unused user_id: Optional[str] = None, ) -> ModelInstance | None: """Get an instance by provider and model name. Prefer global instances; fall back to any valid one.""" @@ -63,7 +62,6 @@ async def list_all(self) -> list[ModelInstance]: async def list_by_provider( self, provider_id: uuid.UUID, - provider_name: Optional[str] = None, # kept for call-site compatibility; unused ) -> list[ModelInstance]: """Filter model instances by provider.""" query = ( diff --git a/backend/app/repositories/skill.py b/backend/app/repositories/skill.py index 6d105607c..804bc9fe8 100644 --- a/backend/app/repositories/skill.py +++ b/backend/app/repositories/skill.py @@ -66,6 +66,14 @@ async def get_with_files(self, skill_id: uuid.UUID) -> Optional[Skill]: result = await self.db.execute(query) return result.scalar_one_or_none() # type: ignore[return-value] + async def get_by_ids(self, skill_ids: List[uuid.UUID]) -> List[Skill]: + """Get multiple skills by their IDs, with files eagerly loaded.""" + if not skill_ids: + return [] + query = select(Skill).options(selectinload(Skill.files)).where(Skill.id.in_(skill_ids)) + result = await self.db.execute(query) + return list(result.scalars().all()) + async def get_by_name_and_owner(self, name: str, owner_id: Optional[str]) -> Optional[Skill]: """Get a skill by name and owner.""" query = select(Skill).where(and_(Skill.name == name, Skill.owner_id == owner_id)) diff --git a/backend/app/schemas/execution.py b/backend/app/schemas/execution.py new file mode 100644 index 000000000..48ea61737 --- /dev/null +++ b/backend/app/schemas/execution.py @@ -0,0 +1,196 @@ +""" +Pydantic schemas for Mission, AgentProfile, and Execution APIs. +""" + +from __future__ import annotations + +import uuid +from datetime import datetime +from typing import Any, Literal, Optional + +from pydantic import BaseModel, Field + +# --------------------------------------------------------------------------- +# Mission +# --------------------------------------------------------------------------- + +MissionStatusLiteral = Literal["backlog", "todo", "in_progress", "in_review", "done", "cancelled"] +MissionPriorityLiteral = Literal["none", "low", "medium", "high", "urgent"] + + +class CreateMissionRequest(BaseModel): + workspace_id: uuid.UUID + title: str = Field(..., max_length=500) + description: Optional[str] = None + objective: Optional[str] = None + priority: MissionPriorityLiteral = "none" + parent_mission_id: Optional[uuid.UUID] = None + tags: Optional[list[str]] = None + position: float = 0.0 + auto_approve: bool = False + + +class UpdateMissionRequest(BaseModel): + title: Optional[str] = Field(None, max_length=500) + description: Optional[str] = None + objective: Optional[str] = None + priority: Optional[MissionPriorityLiteral] = None + status: Optional[MissionStatusLiteral] = None + assignee_type: Optional[str] = None + assignee_id: Optional[uuid.UUID] = None + parent_mission_id: Optional[uuid.UUID] = None + due_date: Optional[datetime] = None + position: Optional[float] = None + tags: Optional[list[str]] = None + auto_approve: Optional[bool] = None + + +class AssignMissionRequest(BaseModel): + agent_profile_id: uuid.UUID + + +class DispatchMissionRequest(BaseModel): + runtime_config: Optional[dict[str, Any]] = None + + +class MissionSummary(BaseModel): + id: uuid.UUID + workspace_id: uuid.UUID + title: str + description: Optional[str] = None + objective: Optional[str] = None + status: str + priority: str + assignee_type: Optional[str] = None + assignee_id: Optional[uuid.UUID] = None + creator_id: str + current_execution_id: Optional[uuid.UUID] = None + parent_mission_id: Optional[uuid.UUID] = None + tags: Optional[list[str]] = None + position: float + auto_approve: bool = False + due_date: Optional[datetime] = None + created_at: datetime + updated_at: datetime + + +class MissionListResponse(BaseModel): + items: list[MissionSummary] + + +# --------------------------------------------------------------------------- +# AgentProfile +# --------------------------------------------------------------------------- + + +class CreateAgentProfileRequest(BaseModel): + workspace_id: uuid.UUID + name: str = Field(..., max_length=255) + runtime_type: str = Field(..., max_length=50) + description: Optional[str] = None + avatar: Optional[str] = None + instructions: Optional[str] = None + skill_ids: Optional[list[str]] = None + custom_env: Optional[dict[str, Any]] = None + runtime_config: Optional[dict[str, Any]] = None + max_concurrent_tasks: int = 1 + + +class UpdateAgentProfileRequest(BaseModel): + name: Optional[str] = Field(None, max_length=255) + description: Optional[str] = None + avatar: Optional[str] = None + instructions: Optional[str] = None + skill_ids: Optional[list[str]] = None + custom_env: Optional[dict[str, Any]] = None + runtime_config: Optional[dict[str, Any]] = None + max_concurrent_tasks: Optional[int] = None + runtime_type: Optional[str] = None + visibility: Optional[str] = None + + +class AgentProfileSummary(BaseModel): + id: uuid.UUID + workspace_id: uuid.UUID + name: str + runtime_type: str + status: str + description: Optional[str] = None + avatar: Optional[str] = None + instructions: Optional[str] = None + skill_ids: Optional[list[str]] = None + has_custom_env: bool = False + runtime_config: Optional[dict[str, Any]] = None + visibility: str = "workspace" + max_concurrent_tasks: int + created_at: datetime + updated_at: datetime + + +class AgentProfileListResponse(BaseModel): + items: list[AgentProfileSummary] + + +# --------------------------------------------------------------------------- +# Execution +# --------------------------------------------------------------------------- + + +class ExecutionSummary(BaseModel): + id: uuid.UUID + workspace_id: uuid.UUID + user_id: str + source: str + status: str + title: Optional[str] = None + mission_id: Optional[uuid.UUID] = None + agent_profile_id: Optional[uuid.UUID] = None + runtime_type: str + container_id: Optional[str] = None + session_id: Optional[str] = None + started_at: Optional[datetime] = None + finished_at: Optional[datetime] = None + last_seq: int + result_summary: Optional[dict[str, Any]] = None + error_code: Optional[str] = None + error_message: Optional[str] = None + created_at: datetime + updated_at: datetime + + +class ExecutionListResponse(BaseModel): + items: list[ExecutionSummary] + + +class ExecutionSnapshotResponse(BaseModel): + execution_id: uuid.UUID + status: str + last_seq: int + projection: dict[str, Any] + + +class ExecutionEventResponse(BaseModel): + seq: int + event_type: str + payload: dict[str, Any] + created_at: datetime + + +class ExecutionEventsPageResponse(BaseModel): + execution_id: uuid.UUID + events: list[ExecutionEventResponse] + next_after_seq: int + + +# --------------------------------------------------------------------------- +# Intervention / Approval +# --------------------------------------------------------------------------- + + +class InjectMessageRequest(BaseModel): + message: str + + +class ApproveActionRequest(BaseModel): + approved: bool + message: str | None = None diff --git a/backend/app/schemas/mission_comment.py b/backend/app/schemas/mission_comment.py new file mode 100644 index 000000000..cf9e7b763 --- /dev/null +++ b/backend/app/schemas/mission_comment.py @@ -0,0 +1,41 @@ +""" +Pydantic schemas for Mission Comments. +""" + +from __future__ import annotations + +import uuid +from datetime import datetime +from typing import Optional + +from pydantic import BaseModel, ConfigDict, Field + + +class CreateMissionCommentRequest(BaseModel): + content: str = Field(..., min_length=1, max_length=10000) + parent_comment_id: Optional[uuid.UUID] = None + + +class UpdateMissionCommentRequest(BaseModel): + content: str = Field(..., min_length=1, max_length=10000) + + +class MissionCommentResponse(BaseModel): + model_config = ConfigDict(from_attributes=True) + + id: uuid.UUID + mission_id: uuid.UUID + workspace_id: uuid.UUID + author_type: str + author_id: str + content: str + type: str + parent_comment_id: Optional[uuid.UUID] = None + created_at: datetime + updated_at: datetime + + +class MissionCommentListResponse(BaseModel): + items: list[MissionCommentResponse] + has_more: bool = False + next_cursor: Optional[str] = None diff --git a/backend/app/services/agent_profile_service.py b/backend/app/services/agent_profile_service.py new file mode 100644 index 000000000..0ff50f158 --- /dev/null +++ b/backend/app/services/agent_profile_service.py @@ -0,0 +1,137 @@ +""" +AgentProfile service layer. +""" + +from __future__ import annotations + +import uuid +from typing import Any, Optional + +from loguru import logger +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.agent_profile import AgentProfile, AgentStatus +from app.repositories.agent_profile import AgentProfileRepository + + +class AgentProfileService: + """Manages agent profile lifecycle.""" + + def __init__(self, db: AsyncSession): + self.db = db + self.repo = AgentProfileRepository(db) + + async def create_profile( + self, + *, + workspace_id: uuid.UUID, + name: str, + runtime_type: str, + description: Optional[str] = None, + avatar: Optional[str] = None, + instructions: Optional[str] = None, + skill_ids: Optional[list] = None, + custom_env: Optional[dict[str, Any]] = None, + runtime_config: Optional[dict[str, Any]] = None, + max_concurrent_tasks: int = 1, + ) -> AgentProfile: + profile = AgentProfile( + workspace_id=workspace_id, + name=name, + runtime_type=runtime_type, + description=description, + avatar=avatar, + instructions=instructions, + skill_ids=skill_ids, + custom_env=custom_env, + runtime_config=runtime_config, + max_concurrent_tasks=max_concurrent_tasks, + status=AgentStatus.IDLE, + ) + self.db.add(profile) + await self.db.commit() + await self.db.refresh(profile) + logger.info(f"Created agent profile: {profile.id} ({name})") + return profile + + async def get_profile(self, profile_id: uuid.UUID, workspace_id: uuid.UUID) -> Optional[AgentProfile]: + return await self.repo.get_by_id_and_workspace(profile_id, workspace_id) + + async def list_profiles( + self, + *, + workspace_id: uuid.UUID, + status: Optional[str] = None, + runtime_type: Optional[str] = None, + limit: int = 100, + ) -> list[AgentProfile]: + return list( + await self.repo.list_by_workspace( + workspace_id=workspace_id, + status=status, + runtime_type=runtime_type, + limit=limit, + ) + ) + + async def update_status(self, profile_id: uuid.UUID, status: AgentStatus) -> Optional[AgentProfile]: + profile = await self.repo.get_for_update(profile_id) + if not profile: + return None + profile.status = status + await self.db.commit() + return profile + + async def find_available_agents( + self, *, workspace_id: uuid.UUID, runtime_type: Optional[str] = None + ) -> list[AgentProfile]: + return list(await self.repo.find_available(workspace_id=workspace_id, runtime_type=runtime_type)) + + async def update_profile( + self, + profile_id: uuid.UUID, + workspace_id: uuid.UUID, + **kwargs: Any, + ) -> Optional[AgentProfile]: + profile = await self.repo.get_by_id_and_workspace(profile_id, workspace_id) + if not profile: + return None + allowed = { + "name", + "description", + "avatar", + "instructions", + "skill_ids", + "custom_env", + "runtime_config", + "max_concurrent_tasks", + "runtime_type", + "visibility", + } + for key, value in kwargs.items(): + if key in allowed: + setattr(profile, key, value) + await self.db.commit() + await self.db.refresh(profile) + return profile + + async def delete_profile(self, profile_id: uuid.UUID, workspace_id: uuid.UUID) -> bool: + profile = await self.repo.get_by_id_and_workspace(profile_id, workspace_id) + if not profile: + return False + + # Clear assignee on missions pointing to this agent + from sqlalchemy import update + + from app.models.mission import Mission + + await self.db.execute( + update(Mission) + .where(Mission.assignee_id == profile_id, Mission.workspace_id == workspace_id) + .values(assignee_type=None, assignee_id=None) + ) + + await self.db.delete(profile) + await self.db.commit() + logger.info(f"Deleted agent profile: {profile_id}") + return True diff --git a/backend/app/services/base.py b/backend/app/services/base.py index 04b7eb3c0..e60723364 100644 --- a/backend/app/services/base.py +++ b/backend/app/services/base.py @@ -4,6 +4,7 @@ from typing import Generic, TypeVar +from loguru import logger from sqlalchemy.ext.asyncio import AsyncSession T = TypeVar("T") @@ -26,3 +27,12 @@ async def commit(self): async def rollback(self): """Roll back the transaction.""" await self.db.rollback() + + async def safe_commit(self): + """Commit with automatic rollback on failure.""" + try: + await self.db.commit() + except Exception: + logger.warning("DB commit failed, rolling back", exc_info=True) + await self.db.rollback() + raise diff --git a/backend/app/services/execution_lifecycle_service.py b/backend/app/services/execution_lifecycle_service.py new file mode 100644 index 000000000..854f2758c --- /dev/null +++ b/backend/app/services/execution_lifecycle_service.py @@ -0,0 +1,589 @@ +# backend/app/services/execution_lifecycle_service.py +""" +ExecutionLifecycleService — the sole cross-domain coordinator +between Mission and Execution. + +All operations that touch BOTH domains go through this service. +MissionService and ExecutionService remain single-domain and +never import each other. +""" + +from __future__ import annotations + +import asyncio +import uuid +from typing import Any, Optional + +from loguru import logger +from sqlalchemy import func, select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.common.exceptions import BadRequestException, ConflictException, NotFoundException +from app.core.agent.cli_backends.base import CLIResult +from app.core.agent.cli_backends.runner_callbacks import RunnerCallbacks +from app.core.agent.cli_backends.session_registry import session_registry +from app.models.execution import ( + TERMINAL_EXECUTION_STATUSES, + ExecutionSource, + MissionExecutionStatus, +) +from app.models.execution import ( + Execution as ExecModel, +) +from app.models.mission import AssigneeType, Mission, MissionStatus +from app.repositories.agent_profile import AgentProfileRepository +from app.repositories.mission import MissionRepository +from app.services.execution_service import ExecutionService +from app.utils.credentials import build_credentials +from app.utils.safe_task import safe_create_task + + +def build_execution_prompt(mission: Mission, trigger_comment=None) -> str: + """Build the prompt sent to the CLI agent for a mission.""" + parts: list[str] = [] + parts.append(f"# Mission: {mission.title}") + if mission.description: + parts.append(f"\n## Description\n{mission.description}") + if mission.objective: + parts.append(f"\n## Objective\n{mission.objective}") + if mission.tags: + parts.append(f"\n## Tags\n{', '.join(str(t) for t in mission.tags)}") + if trigger_comment: + parts.append( + f"\n## [NEW COMMENT]\n" + f"A user just left a new comment. You MUST respond to THIS comment:\n\n" + f"> {trigger_comment.content[:4000]}" + ) + return "\n".join(parts) + + +def _start_execution_runner( + execution_id: uuid.UUID, + prompt: str, + credentials: dict[str, str] | None, + skills: list[dict[str, Any]] | None = None, +) -> None: + """Fire-and-forget: launch an ExecutionRunner in a background task.""" + from app.core.agent.cli_backends.execution_runner import ExecutionRunner + from app.core.database import AsyncSessionLocal + from app.utils.task_manager import task_manager + + async def _run() -> None: + current_task = asyncio.current_task() + if current_task: + await task_manager.register_task(str(execution_id), current_task) + try: + async with AsyncSessionLocal() as db: + lifecycle = ExecutionLifecycleService(db) + runner = ExecutionRunner(db, callbacks=lifecycle) + await runner.run( + execution_id=execution_id, + prompt=prompt, + credentials=credentials, + skills=skills, + ) + except Exception as exc: + logger.error(f"Background runner failed for {execution_id}: {exc}") + finally: + await task_manager.unregister_task(str(execution_id)) + + safe_create_task(_run(), name=f"exec-{execution_id}") + + +class ExecutionLifecycleService(RunnerCallbacks): + """Mediator: coordinates Mission <-> Execution interactions. + + Implements RunnerCallbacks so it can be injected into ExecutionRunner. + """ + + def __init__(self, db: AsyncSession): + self.db = db + self.execution_service = ExecutionService(db) + self.mission_repo = MissionRepository(db) + self.agent_repo = AgentProfileRepository(db) + + async def _resolve_agent_skills(self, agent: Any) -> list[dict[str, Any]] | None: + """Fetch skill records for an agent's skill_ids list and serialize to dicts.""" + if not agent.skill_ids: + return None + from app.repositories.skill import SkillRepository + + skill_repo = SkillRepository(self.db) + skill_uuids = [uuid.UUID(sid) if isinstance(sid, str) else sid for sid in agent.skill_ids] + skills = await skill_repo.get_by_ids(skill_uuids) + if not skills: + return None + result = [] + for s in skills: + skill_dict: dict[str, Any] = { + "name": s.name, + "description": s.description, + "content": s.content, + "tags": s.tags or [], + "allowed_tools": s.allowed_tools or [], + } + if s.files: + skill_dict["files"] = [ + {"path": f.path, "file_name": f.file_name, "content": f.content or ""} for f in s.files + ] + result.append(skill_dict) + return result + + # ------------------------------------------------------------------ + # RunnerCallbacks implementation + # ------------------------------------------------------------------ + + async def on_execution_finalized( + self, + execution_id: uuid.UUID, + status: MissionExecutionStatus, + result: CLIResult, + ) -> None: + """Called by ExecutionRunner after terminal state reached.""" + await self._post_completion_comment(execution_id, status, result) + await self._finalize_mission(execution_id, status) + + async def on_execution_failed( + self, + execution_id: uuid.UUID, + error: str, + ) -> None: + """Called by ExecutionRunner on unhandled exception.""" + await self._post_completion_comment( + execution_id, + MissionExecutionStatus.FAILED, + error_message=error, + ) + await self._finalize_mission(execution_id, MissionExecutionStatus.FAILED) + + # ------------------------------------------------------------------ + # Finalize: update mission status after execution ends + # ------------------------------------------------------------------ + + async def _finalize_mission( + self, + execution_id: uuid.UUID, + status: MissionExecutionStatus, + ) -> None: + try: + mission = ( + await self.db.execute( + select(Mission).where(Mission.current_execution_id == execution_id).with_for_update() + ) + ).scalar_one_or_none() + if not mission: + return + + mission.current_execution_id = None + + if status == MissionExecutionStatus.COMPLETED: + if mission.status != MissionStatus.CANCELLED: + mission.status = MissionStatus.DONE if mission.auto_approve else MissionStatus.IN_REVIEW + elif status == MissionExecutionStatus.FAILED: + if mission.status == MissionStatus.IN_PROGRESS: + mission.status = MissionStatus.TODO + elif status == MissionExecutionStatus.CANCELLED: + if mission.status == MissionStatus.IN_PROGRESS: + mission.status = MissionStatus.TODO + + await self.db.commit() + + from app.websocket.notification_manager import ( + NotificationType, + notification_manager, + ) + + await notification_manager.broadcast( + { + "type": NotificationType.MISSION_UPDATED.value, + "mission_id": str(mission.id), + "status": mission.status.value, + } + ) + + logger.info( + f"Finalized mission {mission.id}: execution {execution_id} -> mission status {mission.status.value}" + ) + except Exception as exc: + logger.warning(f"Failed to finalize mission for execution {execution_id}: {exc}") + + # ------------------------------------------------------------------ + # Cancel: unified cancel path + # ------------------------------------------------------------------ + + async def cancel_execution( + self, + execution_id: uuid.UUID, + user_id: str, + ) -> Any: + execution = await self.execution_service.get_execution(execution_id, user_id) + if not execution: + return None + + if execution.status in TERMINAL_EXECUTION_STATUSES: + return execution + + execution = await self.execution_service.mark_status( + execution_id=execution_id, + user_id=user_id, + status=MissionExecutionStatus.CANCELLED, + error_code="cancelled", + error_message="Cancelled by user", + ) + + session = session_registry.get(execution_id) + if session: + try: + await session.cancel() + except Exception as exc: + logger.warning(f"Failed to cancel session {execution_id}: {exc}") + + try: + from app.utils.task_manager import task_manager + + await task_manager.cancel_task(str(execution_id)) + except Exception as exc: + logger.warning(f"Failed to cancel task {execution_id}: {exc}") + + # Force-remove the Docker container so it doesn't linger + await self._destroy_execution_container(execution) + + if execution and execution.mission_id: + await self._finalize_mission(execution_id, MissionExecutionStatus.CANCELLED) + + return execution + + async def _destroy_execution_container(self, execution: Any) -> None: + """Release this execution's container; destroy it if no other execution is using it.""" + from app.core.agent.cli_backends.container_pool import container_pool + from app.core.agent.cli_backends.container_service import CLIContainerService + + if execution.agent_profile_id: + try: + destroyed = await container_pool.release_and_destroy_if_idle(execution.agent_profile_id) + if destroyed: + logger.info( + f"Destroyed container for agent {execution.agent_profile_id} (execution {execution.id})" + ) + else: + logger.info( + f"Released container for agent {execution.agent_profile_id} " + f"(execution {execution.id}, still in use by other executions)" + ) + return + except Exception as exc: + logger.warning(f"Failed to release/destroy container for agent {execution.agent_profile_id}: {exc}") + + # No agent profile — remove by container_id directly + if execution.container_id: + try: + svc = CLIContainerService() + await svc.remove_container(execution.container_id, force=True) + logger.info(f"Removed container {execution.container_id[:12]} for execution {execution.id}") + except Exception as exc: + logger.warning(f"Failed to remove container {execution.container_id[:12]}: {exc}") + + async def cancel_mission( + self, + mission_id: uuid.UUID, + workspace_id: uuid.UUID, + ) -> Optional[Mission]: + mission = await self.mission_repo.get_for_update(mission_id, workspace_id) + if not mission: + return None + + if mission.current_execution_id: + exec_id = mission.current_execution_id + try: + await self.execution_service.mark_status( + execution_id=exec_id, + status=MissionExecutionStatus.CANCELLED, + error_code="cancelled", + error_message="Mission cancelled by user", + ) + except Exception as exc: + logger.warning(f"Failed to mark execution {exec_id} cancelled: {exc}") + + session = session_registry.get(exec_id) + if session: + try: + await session.cancel() + except Exception as exc: + logger.warning(f"Failed to cancel session {exec_id}: {exc}") + + try: + from app.utils.task_manager import task_manager + + await task_manager.cancel_task(str(exec_id)) + except Exception as exc: + logger.warning(f"Failed to cancel task {exec_id}: {exc}") + + # Force-remove the Docker container + execution = await self.execution_service.get_execution_internal(exec_id) + if execution: + await self._destroy_execution_container(execution) + + mission.status = MissionStatus.CANCELLED + mission.current_execution_id = None + await self.db.commit() + await self.db.refresh(mission) + + from app.websocket.notification_manager import ( + NotificationType, + notification_manager, + ) + + await notification_manager.broadcast( + { + "type": NotificationType.MISSION_UPDATED.value, + "mission_id": str(mission.id), + "status": mission.status.value, + } + ) + + return mission + + # ------------------------------------------------------------------ + # Auto-comment on execution completion + # ------------------------------------------------------------------ + + async def _post_completion_comment( + self, + execution_id: uuid.UUID, + status: MissionExecutionStatus, + result: Optional[CLIResult] = None, + error_message: str = "", + ) -> None: + try: + execution = await self.execution_service.get_execution_internal(execution_id) + if not execution or not execution.mission_id: + return + from app.services.mission_comment_service import MissionCommentService + + svc = MissionCommentService(self.db) + await svc.post_execution_comment( + execution=execution, + result_status=status, + result_output=(result.output[:2000] if result and result.output else ""), + error_message=error_message[:2000] if error_message else "", + ) + except Exception as exc: + logger.warning(f"Failed to post completion comment for {execution_id}: {exc}") + + # ------------------------------------------------------------------ + # Dispatch: create execution + start runner + # ------------------------------------------------------------------ + + async def dispatch_mission( + self, + *, + mission_id: uuid.UUID, + workspace_id: uuid.UUID, + user_id: str, + runtime_config: Optional[dict[str, Any]] = None, + ) -> tuple[Mission, Any]: + mission = await self.mission_repo.get_for_update(mission_id, workspace_id) + if not mission: + raise NotFoundException(f"Mission not found: {mission_id}") + + if mission.status not in { + MissionStatus.TODO, + MissionStatus.BACKLOG, + MissionStatus.IN_PROGRESS, + MissionStatus.IN_REVIEW, + }: + raise BadRequestException(f"Mission {mission_id} cannot be dispatched from status {mission.status.value}") + + if mission.status == MissionStatus.IN_PROGRESS and mission.current_execution_id: + current_exec = ( + await self.db.execute(select(ExecModel).where(ExecModel.id == mission.current_execution_id)) + ).scalar_one_or_none() + if current_exec and current_exec.status not in TERMINAL_EXECUTION_STATUSES: + raise ConflictException(f"Mission {mission_id} already has an active execution") + mission.current_execution_id = None + + if not mission.assignee_id or mission.assignee_type != AssigneeType.AGENT: + raise BadRequestException(f"Mission {mission_id} has no agent assignee") + + agent = await self.agent_repo.get_by_id_and_workspace(mission.assignee_id, workspace_id) + if not agent: + raise NotFoundException(f"Agent profile not found: {mission.assignee_id}") + + active_count_result = await self.db.execute( + select(func.count()) + .select_from(ExecModel) + .where( + ExecModel.agent_profile_id == agent.id, + ExecModel.status.in_( + [ + MissionExecutionStatus.QUEUED, + MissionExecutionStatus.DISPATCHED, + MissionExecutionStatus.RUNNING, + MissionExecutionStatus.APPROVAL_WAIT, + ] + ), + ) + ) + active_count = active_count_result.scalar() or 0 + if active_count >= agent.max_concurrent_tasks: + raise ConflictException( + f"Agent {agent.name} already has {active_count}/{agent.max_concurrent_tasks} active executions" + ) + + credentials = build_credentials(agent.custom_env) + prompt = build_execution_prompt(mission) + skills = await self._resolve_agent_skills(agent) + + execution = await self.execution_service.create_execution( + workspace_id=workspace_id, + user_id=user_id, + source=ExecutionSource.MISSION, + runtime_type=agent.runtime_type, + title=mission.title, + mission_id=mission_id, + agent_profile_id=mission.assignee_id, + runtime_config=runtime_config or agent.runtime_config, + ) + + mission.status = MissionStatus.IN_PROGRESS + mission.current_execution_id = execution.id + await self.db.commit() + await self.db.refresh(mission) + + logger.info(f"Dispatched mission {mission_id} -> execution {execution.id}") + + _start_execution_runner(execution.id, prompt, credentials, skills) + return mission, execution + + async def dispatch_all_ready_missions(self, *, limit: int = 20) -> int: + dispatchable = await self.mission_repo.list_dispatchable(limit=limit) + dispatched = 0 + for mission in dispatchable: + try: + await self.dispatch_mission( + mission_id=mission.id, + workspace_id=mission.workspace_id, + user_id=mission.creator_id, + ) + dispatched += 1 + except Exception as exc: + logger.warning(f"Failed to auto-dispatch mission {mission.id}: {exc}") + return dispatched + + async def dispatch_for_comment( + self, + *, + mission: Mission, + trigger_comment: Any, + user_id: str, + ) -> Optional[uuid.UUID]: + assert mission.assignee_id is not None + agent = await self.agent_repo.get_by_id_and_workspace(mission.assignee_id, mission.workspace_id) + if not agent: + logger.warning(f"Agent {mission.assignee_id} not found, skipping enqueue") + return None + + execution_id = await self._create_comment_execution( + mission=mission, + agent=agent, + trigger_comment=trigger_comment, + user_id=user_id, + ) + if not execution_id: + return None + + mission_for_update = await self.mission_repo.get_for_update(mission.id, mission.workspace_id) + if mission_for_update: + mission_for_update.current_execution_id = execution_id + if mission_for_update.status != MissionStatus.IN_PROGRESS: + mission_for_update.status = MissionStatus.IN_PROGRESS + await self.db.commit() + + return execution_id + + async def dispatch_for_mention( + self, + *, + mission: Mission, + trigger_comment: Any, + user_id: str, + ) -> None: + from app.utils.mentions import agent_mentions + + mentions = agent_mentions(trigger_comment.content) + if not mentions: + return + if mission.status in {MissionStatus.DONE, MissionStatus.CANCELLED, MissionStatus.BACKLOG}: + return + + seen: set[uuid.UUID] = set() + for mention in mentions: + if mention.id == mission.assignee_id or mention.id in seen: + continue + seen.add(mention.id) + agent = await self.agent_repo.get_by_id_and_workspace(mention.id, mission.workspace_id) + if not agent: + continue + await self._create_comment_execution( + mission=mission, + agent=agent, + trigger_comment=trigger_comment, + user_id=user_id, + ) + + async def _create_comment_execution( + self, + *, + mission: Mission, + agent: Any, + trigger_comment: Any, + user_id: str, + ) -> Optional[uuid.UUID]: + from sqlalchemy.exc import IntegrityError + + credentials = build_credentials(agent.custom_env) + skills = await self._resolve_agent_skills(agent) + + active_count_result = await self.db.execute( + select(func.count()) + .select_from(ExecModel) + .where( + ExecModel.agent_profile_id == agent.id, + ExecModel.status.in_( + [ + MissionExecutionStatus.QUEUED, + MissionExecutionStatus.DISPATCHED, + MissionExecutionStatus.RUNNING, + MissionExecutionStatus.APPROVAL_WAIT, + ] + ), + ) + ) + active_count = active_count_result.scalar() or 0 + if active_count >= agent.max_concurrent_tasks: + logger.info( + f"Agent {agent.name} at concurrency limit ({active_count}/{agent.max_concurrent_tasks}), " + f"skipping comment-triggered dispatch for mission {mission.id}" + ) + return None + + try: + execution = await self.execution_service.create_execution( + workspace_id=mission.workspace_id, + user_id=user_id, + source=ExecutionSource.MISSION, + runtime_type=agent.runtime_type, + title=mission.title, + mission_id=mission.id, + agent_profile_id=agent.id, + runtime_config=agent.runtime_config, + trigger_comment_id=trigger_comment.id, + ) + except IntegrityError: + await self.db.rollback() + logger.info(f"Dedup: skipped enqueue for agent {agent.id} on mission {mission.id}") + return None + + prompt = build_execution_prompt(mission, trigger_comment=trigger_comment) + _start_execution_runner(execution.id, prompt, credentials, skills) + return execution.id diff --git a/backend/app/services/execution_reducer.py b/backend/app/services/execution_reducer.py new file mode 100644 index 000000000..e3e263385 --- /dev/null +++ b/backend/app/services/execution_reducer.py @@ -0,0 +1,166 @@ +""" +Execution snapshot reducer. + +Applies execution events to build a projection of the current execution state. +Each event type updates the projection dict with shallow copies. +""" + +from __future__ import annotations + +from typing import Any + +_EMPTY_PROJECTION: dict[str, Any] = { + "version": 1, + "status": "queued", + "source": None, + "mission_id": None, + "agent_profile_id": None, + "container_id": None, + "session_id": None, + "messages": [], + "tool_calls": [], + "artifacts": [], + "meta": {}, +} + + +def _shallow_copy_projection(projection: dict[str, Any] | None) -> dict[str, Any]: + if projection is None: + return { + k: (list(v) if isinstance(v, list) else dict(v) if isinstance(v, dict) else v) + for k, v in _EMPTY_PROJECTION.items() + } + copied = dict(projection) + # Shallow-copy mutable containers so appends don't mutate the original + copied["messages"] = list(copied.get("messages") or []) + copied["tool_calls"] = list(copied.get("tool_calls") or []) + copied["artifacts"] = list(copied.get("artifacts") or []) + copied["meta"] = dict(copied.get("meta") or {}) + return copied + + +def make_initial_projection(payload: dict[str, Any], status: str) -> dict[str, Any]: + projection = _shallow_copy_projection(None) + projection["status"] = status + projection["source"] = payload.get("source") + projection["mission_id"] = payload.get("mission_id") + projection["agent_profile_id"] = payload.get("agent_profile_id") + return projection + + +def apply_execution_event( + projection: dict[str, Any] | None, + *, + event_type: str, + payload: dict[str, Any], + status: str, +) -> dict[str, Any]: + next_proj = _shallow_copy_projection(projection) + next_proj["status"] = status + + if event_type == "execution_started": + next_proj["container_id"] = payload.get("container_id") + next_proj["session_id"] = payload.get("session_id") + return next_proj + + if event_type == "prompt_sent": + msg = payload.get("message") + if isinstance(msg, dict): + next_proj["messages"].append(msg) + return next_proj + + if event_type == "assistant_text": + msg = payload.get("message") + if isinstance(msg, dict): + next_proj["messages"].append(msg) + elif isinstance(payload.get("content"), str): + next_proj["messages"].append( + { + "role": "assistant", + "content": payload["content"], + } + ) + return next_proj + + if event_type == "content_delta": + delta = payload.get("delta", "") + message_id = payload.get("message_id") + if delta and next_proj["messages"]: + last = next_proj["messages"][-1] + if last.get("role") == "assistant" and (not message_id or last.get("id") == message_id): + # Copy the message dict before mutating to avoid aliasing + updated = dict(last) + updated["content"] = f"{last.get('content', '')}{delta}" + next_proj["messages"][-1] = updated + return next_proj + + if event_type == "tool_use_start": + tool = payload.get("tool") + if isinstance(tool, dict): + next_proj["tool_calls"].append(tool) + else: + next_proj["tool_calls"].append( + { + "name": payload.get("tool_name", ""), + "call_id": payload.get("call_id", ""), + "input": payload.get("input"), + "status": "running", + } + ) + return next_proj + + if event_type == "tool_use_end": + call_id = payload.get("call_id") + for tc in reversed(next_proj["tool_calls"]): + if call_id and tc.get("call_id") != call_id: + continue + if not call_id and tc.get("status") != "running": + continue + tc["status"] = "completed" + tc["output"] = payload.get("output", "") + break + return next_proj + + if event_type == "thinking": + meta = next_proj["meta"] + meta["last_thinking"] = payload.get("content", "") + return next_proj + + if event_type == "artifact_created": + artifact = payload.get("artifact") + if isinstance(artifact, dict): + next_proj["artifacts"].append(artifact) + return next_proj + + if event_type == "user_message": + content = payload.get("content", "") + next_proj["messages"].append( + { + "role": "user", + "content": content, + } + ) + return next_proj + + if event_type == "approval_requested": + next_proj["meta"]["pending_approval"] = payload + return next_proj + + if event_type == "approval_resolved": + next_proj["meta"].pop("pending_approval", None) + return next_proj + + if event_type == "error": + next_proj["meta"]["error"] = payload.get("message", "") + return next_proj + + if event_type == "execution_completed": + next_proj["meta"]["completed"] = True + if "result_summary" in payload: + next_proj["meta"]["result_summary"] = payload["result_summary"] + return next_proj + + if event_type == "heartbeat": + return next_proj + + return next_proj diff --git a/backend/app/services/execution_service.py b/backend/app/services/execution_service.py new file mode 100644 index 000000000..eb30632ee --- /dev/null +++ b/backend/app/services/execution_service.py @@ -0,0 +1,305 @@ +""" +Service layer for CLI agent executions. +""" + +from __future__ import annotations + +import uuid +from typing import Any, Optional + +from sqlalchemy.ext.asyncio import AsyncSession + +from app.models.execution import ( + TERMINAL_EXECUTION_STATUSES, + Execution, + ExecutionEvent, + ExecutionSnapshot, + ExecutionSource, + MissionExecutionStatus, +) +from app.repositories.execution import ExecutionRepository +from app.services.execution_reducer import apply_execution_event, make_initial_projection +from app.utils.datetime import utc_now + + +class ExecutionService: + """Orchestrates execution lifecycle, event sourcing, and snapshot management.""" + + def __init__(self, db: AsyncSession): + self.db = db + self.repo = ExecutionRepository(db) + + async def create_execution( + self, + *, + workspace_id: uuid.UUID, + user_id: str, + source: ExecutionSource, + runtime_type: str, + title: Optional[str] = None, + mission_id: Optional[uuid.UUID] = None, + agent_profile_id: Optional[uuid.UUID] = None, + parent_execution_id: Optional[uuid.UUID] = None, + runtime_config: Optional[dict[str, Any]] = None, + trigger_comment_id: Optional[uuid.UUID] = None, + ) -> Execution: + execution = Execution( + workspace_id=workspace_id, + user_id=user_id, + source=source, + status=MissionExecutionStatus.QUEUED, + title=title, + mission_id=mission_id, + agent_profile_id=agent_profile_id, + parent_execution_id=parent_execution_id, + runtime_type=runtime_type, + runtime_config=runtime_config, + trigger_comment_id=trigger_comment_id, + last_heartbeat_at=utc_now(), + ) + self.db.add(execution) + await self.db.flush() + + snapshot = ExecutionSnapshot( + execution_id=execution.id, + last_seq=0, + status=execution.status.value, + projection=make_initial_projection( + { + "source": source.value, + "mission_id": str(mission_id) if mission_id else None, + "agent_profile_id": str(agent_profile_id) if agent_profile_id else None, + }, + execution.status.value, + ), + ) + self.db.add(snapshot) + await self.db.commit() + await self.db.refresh(execution) + return execution + + async def get_execution(self, execution_id: uuid.UUID, user_id: str) -> Optional[Execution]: + return await self.repo.get_by_id_and_user(execution_id, user_id) + + async def get_execution_internal(self, execution_id: uuid.UUID) -> Optional[Execution]: + """Internal use — no user-scope check, no FOR UPDATE lock.""" + from sqlalchemy import select + + from app.models.execution import Execution as ExecModel + + result = await self.db.execute(select(ExecModel).where(ExecModel.id == execution_id)) + return result.scalar_one_or_none() + + async def get_snapshot(self, execution_id: uuid.UUID, user_id: str) -> Optional[ExecutionSnapshot]: + execution = await self.get_execution(execution_id, user_id) + if not execution: + return None + return await self.repo.get_snapshot(execution_id) + + async def list_events_after( + self, execution_id: uuid.UUID, user_id: str, after_seq: int = 0, limit: int = 500 + ) -> list[ExecutionEvent]: + execution = await self.get_execution(execution_id, user_id) + if not execution: + return [] + return list(await self.repo.list_events_after(execution_id, after_seq=after_seq, limit=limit)) + + async def list_executions( + self, + *, + workspace_id: uuid.UUID, + user_id: Optional[str] = None, + status: Optional[str] = None, + source: Optional[str] = None, + mission_id: Optional[uuid.UUID] = None, + limit: int = 50, + ) -> list[Execution]: + return list( + await self.repo.list_by_workspace( + workspace_id=workspace_id, + user_id=user_id, + status=status, + source=source, + mission_id=mission_id, + limit=limit, + ) + ) + + async def list_children(self, parent_execution_id: uuid.UUID) -> list[Execution]: + return list(await self.repo.list_children(parent_execution_id)) + + async def mark_status( + self, + *, + execution_id: uuid.UUID, + user_id: Optional[str] = None, + status: MissionExecutionStatus, + container_id: Optional[str] = None, + session_id: Optional[str] = None, + error_code: Optional[str] = None, + error_message: Optional[str] = None, + result_summary: Optional[dict[str, Any]] = None, + ) -> Optional[Execution]: + execution = await self.repo.get_for_update(execution_id, user_id=user_id) + if not execution: + return None + + now = utc_now() + execution.status = status + execution.error_code = error_code + execution.error_message = error_message + execution.last_heartbeat_at = now + + if container_id is not None: + execution.container_id = container_id + if session_id is not None: + execution.session_id = session_id + if result_summary is not None: + execution.result_summary = result_summary + + if status == MissionExecutionStatus.RUNNING and not execution.started_at: + execution.started_at = now + if status in TERMINAL_EXECUTION_STATUSES: + execution.finished_at = now + + snapshot = await self.repo.get_snapshot(execution_id) + if snapshot: + snapshot.status = status.value + projection = dict(snapshot.projection or {}) + projection["status"] = status.value + if error_message: + meta = dict(projection.get("meta") or {}) + meta["error"] = error_message + projection["meta"] = meta + snapshot.projection = projection + + await self.db.commit() + + from app.websocket.execution_subscription_manager import execution_subscription_manager + + await execution_subscription_manager.broadcast_event( + str(execution_id), + {"type": "execution_status", "execution_id": str(execution_id), "status": status.value}, + ) + + return execution + + async def append_event( + self, + *, + execution_id: uuid.UUID, + event_type: str, + payload: dict[str, Any], + trace_id: Optional[uuid.UUID] = None, + observation_id: Optional[uuid.UUID] = None, + parent_observation_id: Optional[uuid.UUID] = None, + commit: bool = True, + ) -> ExecutionEvent: + execution = await self.repo.get_for_update(execution_id) + if not execution: + raise ValueError(f"Execution not found: {execution_id}") + + next_seq = int(execution.last_seq) + 1 + event = ExecutionEvent( + execution_id=execution.id, + seq=next_seq, + event_type=event_type, + payload=payload, + trace_id=trace_id, + observation_id=observation_id, + parent_observation_id=parent_observation_id, + ) + self.db.add(event) + execution.last_seq = next_seq + execution.last_heartbeat_at = utc_now() + + snapshot = await self.repo.get_snapshot(execution.id) + if snapshot is None: + snapshot = ExecutionSnapshot( + execution_id=execution.id, + last_seq=0, + status=execution.status.value, + projection={}, + ) + self.db.add(snapshot) + + snapshot.projection = apply_execution_event( + snapshot.projection, + event_type=event_type, + payload=payload, + status=execution.status.value, + ) + snapshot.last_seq = next_seq + snapshot.status = execution.status.value + + await self.db.flush() + if commit: + await self.db.commit() + from app.websocket.execution_subscription_manager import execution_subscription_manager + + await execution_subscription_manager.broadcast_event( + str(execution_id), + { + "type": "event", + "execution_id": str(execution_id), + "seq": event.seq, + "event_type": event_type, + "data": payload, + "created_at": str(event.created_at), + }, + ) + return event + + async def batch_append_events( + self, + *, + execution_id: uuid.UUID, + events: list[dict[str, Any]], + ) -> list[ExecutionEvent]: + """Append multiple events in a single commit. + + Each entry in *events* must contain 'event_type' and 'payload' keys, + and may optionally include 'trace_id', 'observation_id', and + 'parent_observation_id'. + """ + results: list[ExecutionEvent] = [] + for evt in events: + result = await self.append_event( + execution_id=execution_id, + event_type=evt["event_type"], + payload=evt["payload"], + trace_id=evt.get("trace_id"), + observation_id=evt.get("observation_id"), + parent_observation_id=evt.get("parent_observation_id"), + commit=False, + ) + results.append(result) + await self.db.commit() + + from app.websocket.execution_subscription_manager import execution_subscription_manager + + for saved_event in results: + await execution_subscription_manager.broadcast_event( + str(execution_id), + { + "type": "event", + "execution_id": str(execution_id), + "seq": saved_event.seq, + "event_type": saved_event.event_type, + "data": saved_event.payload, + "created_at": str(saved_event.created_at), + }, + ) + + return results + + async def touch_heartbeat(self, *, execution_id: uuid.UUID) -> Optional[Execution]: + execution = await self.repo.get_for_update(execution_id) + if not execution: + return None + active = {MissionExecutionStatus.QUEUED, MissionExecutionStatus.DISPATCHED, MissionExecutionStatus.RUNNING} + if execution.status not in active: + return execution + execution.last_heartbeat_at = utc_now() + await self.db.commit() + return execution diff --git a/backend/app/services/memory_service.py b/backend/app/services/memory_service.py index 2e425f2ca..61edbb096 100644 --- a/backend/app/services/memory_service.py +++ b/backend/app/services/memory_service.py @@ -284,16 +284,8 @@ async def get_user_memories( dialect = engine.dialect.name if dialect == "postgresql": # PostgreSQL: Use JSONB @> operator to check if array contains the topic - # Cast JSON to JSONB for proper containment check for topic in topics: - # Check if topics JSON array contains the topic string - # Using JSONB @> operator: topics::jsonb @> '["topic"]'::jsonb - # Escape single quotes in JSON string for SQL safety - topic_array_json = json.dumps([topic]) - # Replace single quotes with escaped single quotes for SQL - topic_array_json_escaped = topic_array_json.replace("'", "''") - # Use text() with string formatting (safe for JSON strings from json.dumps) - stmt = stmt.where(text(f"topics::jsonb @> '{topic_array_json_escaped}'::jsonb")) + stmt = stmt.where(text("topics::jsonb @> :val::jsonb").bindparams(val=json.dumps([topic]))) else: # SQLite or other: Use LIKE for compatibility for topic in topics: diff --git a/backend/app/services/mission_comment_service.py b/backend/app/services/mission_comment_service.py new file mode 100644 index 000000000..51e85cfc6 --- /dev/null +++ b/backend/app/services/mission_comment_service.py @@ -0,0 +1,233 @@ +""" +Mission comment service — create/read/update/delete with auto-enqueue and auto-comment. +""" + +from __future__ import annotations + +import uuid +from datetime import datetime +from typing import Optional + +from loguru import logger +from sqlalchemy.ext.asyncio import AsyncSession + +from app.common.exceptions import NotFoundException +from app.models.execution import MissionExecutionStatus +from app.models.mission import AssigneeType, Mission, MissionStatus +from app.models.mission_comment import CommentAuthorType, CommentType, MissionComment +from app.repositories.mission import MissionRepository +from app.repositories.mission_comment import MissionCommentRepository + + +class MissionCommentService: + """Manages mission comments and the comment→execution enqueue flow.""" + + def __init__(self, db: AsyncSession): + self.db = db + self.repo = MissionCommentRepository(db) + self.mission_repo = MissionRepository(db) + + # ------------------------------------------------------------------ + # CRUD + # ------------------------------------------------------------------ + + async def create_comment( + self, + *, + mission_id: uuid.UUID, + workspace_id: uuid.UUID, + author_type: CommentAuthorType, + author_id: str, + content: str, + comment_type: CommentType = CommentType.COMMENT, + parent_comment_id: Optional[uuid.UUID] = None, + ) -> tuple[MissionComment, Mission, bool, list[uuid.UUID]]: + """Returns (comment, mission, should_dispatch_assignee, mentioned_agent_ids).""" + mission = await self.mission_repo.get_by_id_and_workspace(mission_id, workspace_id) + if not mission: + raise NotFoundException(f"Mission not found: {mission_id}") + + if parent_comment_id is not None: + parent = await self.repo.get(parent_comment_id) + if parent and parent.parent_comment_id is not None: + parent_comment_id = parent.parent_comment_id + + comment = MissionComment( + mission_id=mission_id, + workspace_id=workspace_id, + author_type=author_type, + author_id=author_id, + content=content, + type=comment_type, + parent_comment_id=parent_comment_id, + ) + self.db.add(comment) + await self.db.commit() + await self.db.refresh(comment) + + should_dispatch = False + mentioned_agent_ids: list[uuid.UUID] = [] + + if author_type == CommentAuthorType.MEMBER and comment_type == CommentType.COMMENT: + should_dispatch = self._should_enqueue_on_comment(mission) + + from app.utils.mentions import agent_mentions + + mentions = agent_mentions(content) + seen: set[uuid.UUID] = set() + for m in mentions: + if m.id != mission.assignee_id and m.id not in seen: + seen.add(m.id) + mentioned_agent_ids.append(m.id) + + return comment, mission, should_dispatch, mentioned_agent_ids + + async def list_comments( + self, + *, + mission_id: uuid.UUID, + workspace_id: uuid.UUID, + cursor: Optional[str] = None, + limit: int = 50, + ) -> tuple[list[MissionComment], bool, Optional[str]]: + """Return (comments, has_more, next_cursor).""" + mission = await self.mission_repo.get_by_id_and_workspace(mission_id, workspace_id) + if not mission: + raise NotFoundException(f"Mission not found: {mission_id}") + + cursor_dt = None + if cursor: + cursor_dt = datetime.fromisoformat(cursor) + + comments = list(await self.repo.list_by_mission(mission_id, cursor=cursor_dt, limit=limit + 1, order_asc=True)) + + has_more = len(comments) > limit + if has_more: + comments = comments[:limit] + + next_cursor = comments[-1].created_at.isoformat() if has_more and comments else None + return comments, has_more, next_cursor + + async def _get_owned_comment( + self, + comment_id: uuid.UUID, + mission_id: uuid.UUID, + workspace_id: uuid.UUID, + author_id: str, + ) -> Optional[MissionComment]: + """Return the comment if it exists and belongs to the author, else None. + Raises PermissionError if the comment exists but belongs to another user.""" + mission = await self.mission_repo.get_by_id_and_workspace(mission_id, workspace_id) + if not mission: + return None + comment = await self.repo.get_by_id_and_mission(comment_id, mission_id) + if not comment: + return None + if comment.author_id != author_id: + raise PermissionError("Only the author can modify this comment") + return comment + + async def update_comment( + self, + *, + comment_id: uuid.UUID, + mission_id: uuid.UUID, + workspace_id: uuid.UUID, + author_id: str, + content: str, + ) -> Optional[MissionComment]: + comment = await self._get_owned_comment(comment_id, mission_id, workspace_id, author_id) + if not comment: + return None + comment.content = content + await self.db.commit() + await self.db.refresh(comment) + return comment + + async def delete_comment( + self, + *, + comment_id: uuid.UUID, + mission_id: uuid.UUID, + workspace_id: uuid.UUID, + author_id: str, + ) -> bool: + comment = await self._get_owned_comment(comment_id, mission_id, workspace_id, author_id) + if not comment: + return False + await self.db.delete(comment) + await self.db.commit() + return True + + # ------------------------------------------------------------------ + # Enqueue logic + # ------------------------------------------------------------------ + + @staticmethod + def _should_enqueue_on_comment(mission: Mission) -> bool: + if mission.assignee_type != AssigneeType.AGENT or mission.assignee_id is None: + return False + if mission.status in {MissionStatus.DONE, MissionStatus.CANCELLED, MissionStatus.BACKLOG}: + return False + # If there's already a running execution, skip — the dedup index only + # covers queued/dispatched. We avoid creating a second concurrent execution. + if mission.current_execution_id is not None and mission.status == MissionStatus.IN_PROGRESS: + return False + return True + + # ------------------------------------------------------------------ + # Auto-comment on execution completion/failure + # ------------------------------------------------------------------ + + async def post_execution_comment( + self, + *, + execution, + result_status: MissionExecutionStatus, + result_output: str = "", + error_message: str = "", + ) -> Optional[MissionComment]: + """Called by ExecutionRunner after finalization to auto-post agent comments.""" + if not execution.mission_id or not execution.agent_profile_id: + return None + + agent_id = str(execution.agent_profile_id) + + if result_status == MissionExecutionStatus.COMPLETED: + # Skip auto-comment for comment-triggered assignee executions + # (the assignee is continuing conversational work). + # Mention executions (non-assignee agents) still get auto-comments. + if execution.trigger_comment_id: + mission = await self.mission_repo.get_by_id_and_workspace(execution.mission_id, execution.workspace_id) + if mission and str(mission.assignee_id) == agent_id: + return None + if execution.started_at: + already = await self.repo.has_agent_commented_since( + execution.mission_id, agent_id, execution.started_at + ) + if already: + return None + content = result_output.strip() if result_output else "Execution completed." + comment_type = CommentType.PROGRESS_UPDATE + + elif result_status == MissionExecutionStatus.FAILED: + content = error_message.strip() if error_message else "Execution failed." + comment_type = CommentType.SYSTEM + + else: + return None + + comment = MissionComment( + mission_id=execution.mission_id, + workspace_id=execution.workspace_id, + author_type=CommentAuthorType.AGENT, + author_id=agent_id, + content=content[:5000], + type=comment_type, + parent_comment_id=None, + ) + self.db.add(comment) + await self.db.commit() + await self.db.refresh(comment) + logger.info(f"Auto-posted {comment_type.value} comment {comment.id} for execution {execution.id}") + return comment diff --git a/backend/app/services/mission_service.py b/backend/app/services/mission_service.py new file mode 100644 index 000000000..db40ef6d2 --- /dev/null +++ b/backend/app/services/mission_service.py @@ -0,0 +1,182 @@ +""" +Mission service layer — pure CRUD + status machine. + +Execution dispatch logic lives in ExecutionLifecycleService. +""" + +from __future__ import annotations + +import uuid +from typing import Any, Optional + +from loguru import logger +from sqlalchemy.ext.asyncio import AsyncSession + +from app.common.exceptions import BadRequestException, ConflictException, NotFoundException +from app.models.mission import AssigneeType, Mission, MissionPriority, MissionStatus +from app.repositories.agent_profile import AgentProfileRepository +from app.repositories.mission import MissionRepository + + +class MissionService: + """Manages mission CRUD and status transitions.""" + + def __init__(self, db: AsyncSession): + self.db = db + self.repo = MissionRepository(db) + self.agent_repo = AgentProfileRepository(db) + + async def create_mission( + self, + *, + workspace_id: uuid.UUID, + creator_id: str, + title: str, + description: Optional[str] = None, + objective: Optional[str] = None, + priority: MissionPriority = MissionPriority.NONE, + parent_mission_id: Optional[uuid.UUID] = None, + tags: Optional[list] = None, + position: float = 0.0, + auto_approve: bool = False, + ) -> Mission: + mission = Mission( + workspace_id=workspace_id, + creator_id=creator_id, + title=title, + description=description, + objective=objective, + priority=priority, + status=MissionStatus.BACKLOG, + parent_mission_id=parent_mission_id, + tags=tags, + position=position, + auto_approve=auto_approve, + ) + self.db.add(mission) + await self.db.commit() + await self.db.refresh(mission) + logger.info(f"Created mission: {mission.id} ({title})") + return mission + + async def get_mission(self, mission_id: uuid.UUID, workspace_id: uuid.UUID) -> Optional[Mission]: + return await self.repo.get_by_id_and_workspace(mission_id, workspace_id) + + async def list_missions( + self, + *, + workspace_id: uuid.UUID, + status: Optional[str] = None, + creator_id: Optional[str] = None, + assignee_id: Optional[uuid.UUID] = None, + parent_mission_id: Optional[uuid.UUID] = None, + limit: int = 50, + ) -> list[Mission]: + return list( + await self.repo.list_by_workspace( + workspace_id=workspace_id, + status=status, + creator_id=creator_id, + assignee_id=assignee_id, + parent_mission_id=parent_mission_id, + limit=limit, + ) + ) + + MANUAL_TRANSITIONS: dict[MissionStatus, set[MissionStatus]] = { + MissionStatus.BACKLOG: {MissionStatus.TODO, MissionStatus.IN_PROGRESS, MissionStatus.CANCELLED}, + MissionStatus.TODO: {MissionStatus.BACKLOG, MissionStatus.IN_PROGRESS, MissionStatus.CANCELLED}, + MissionStatus.IN_PROGRESS: { + MissionStatus.TODO, + MissionStatus.IN_REVIEW, + MissionStatus.DONE, + MissionStatus.CANCELLED, + }, + MissionStatus.IN_REVIEW: { + MissionStatus.TODO, + MissionStatus.IN_PROGRESS, + MissionStatus.DONE, + MissionStatus.CANCELLED, + }, + MissionStatus.DONE: {MissionStatus.BACKLOG, MissionStatus.TODO}, + MissionStatus.CANCELLED: {MissionStatus.BACKLOG, MissionStatus.TODO}, + } + + @classmethod + def get_transitions(cls) -> dict[str, list[str]]: + return {status.value: sorted(t.value for t in targets) for status, targets in cls.MANUAL_TRANSITIONS.items()} + + async def update_mission( + self, + mission_id: uuid.UUID, + workspace_id: uuid.UUID, + **kwargs: Any, + ) -> Optional[Mission]: + mission = await self.repo.get_by_id_and_workspace(mission_id, workspace_id) + if not mission: + return None + + new_status = kwargs.get("status") + if new_status is not None: + try: + new_status = MissionStatus(new_status) + except ValueError: + raise BadRequestException(f"Invalid status: {new_status}") + + if new_status != mission.status: + allowed_targets = self.MANUAL_TRANSITIONS.get(mission.status, set()) + if new_status not in allowed_targets: + raise BadRequestException(f"Cannot transition from {mission.status.value} to {new_status.value}") + if mission.current_execution_id and new_status in { + MissionStatus.DONE, + MissionStatus.CANCELLED, + }: + raise ConflictException( + f"Cannot move to {new_status.value} while an execution is active — cancel the execution first" + ) + + allowed = { + "title", + "description", + "objective", + "priority", + "status", + "assignee_type", + "assignee_id", + "parent_mission_id", + "due_date", + "position", + "tags", + "auto_approve", + } + for key, value in kwargs.items(): + if key in allowed: + setattr(mission, key, value) + await self.db.commit() + await self.db.refresh(mission) + return mission + + async def assign_to_agent( + self, + *, + mission_id: uuid.UUID, + workspace_id: uuid.UUID, + agent_profile_id: uuid.UUID, + ) -> Mission: + """Assign a mission to an agent profile and move it to TODO status.""" + mission = await self.repo.get_for_update(mission_id, workspace_id) + if not mission: + raise NotFoundException(f"Mission not found: {mission_id}") + + agent = await self.agent_repo.get_by_id_and_workspace(agent_profile_id, workspace_id) + if not agent: + raise NotFoundException(f"Agent profile not found: {agent_profile_id}") + + mission.assignee_type = AssigneeType.AGENT + mission.assignee_id = agent_profile_id + if mission.status == MissionStatus.BACKLOG: + mission.status = MissionStatus.TODO + await self.db.commit() + await self.db.refresh(mission) + logger.info(f"Assigned mission {mission_id} to agent {agent_profile_id}") + return mission diff --git a/backend/app/services/openapi_graph_service.py b/backend/app/services/openapi_graph_service.py index da2d1df39..418f6a1c3 100644 --- a/backend/app/services/openapi_graph_service.py +++ b/backend/app/services/openapi_graph_service.py @@ -25,6 +25,7 @@ from app.repositories.graph import GraphRepository from app.repositories.graph_execution import GraphExecutionRepository from app.services.graph_service import GraphService +from app.utils.safe_task import safe_create_task from app.utils.task_manager import task_manager from .base import BaseService @@ -71,13 +72,14 @@ async def run_graph( logger.info(f"[OpenAPI] Graph execution created | execution_id={execution_id} graph_id={graph_id}") # start background execution task - asyncio.create_task( + safe_create_task( self._execute_graph_background( execution_id=execution_id, graph_id=graph_id, user_id=user_id, variables=variables or {}, - ) + ), + name=f"graph-exec-{execution_id}", ) return { diff --git a/backend/app/services/openclaw_instance_service.py b/backend/app/services/openclaw_instance_service.py index 978d1b16f..9597dbc8b 100644 --- a/backend/app/services/openclaw_instance_service.py +++ b/backend/app/services/openclaw_instance_service.py @@ -220,17 +220,9 @@ async def _create_container(self, instance: OpenClawInstance, recreate: bool = F } # Pass through AI provider keys from host environment - for key in ( - "ANTHROPIC_API_KEY", - "OPENAI_API_KEY", - "AI_GATEWAY_BASE_URL", - "AI_GATEWAY_API_KEY", - "AI_GATEWAY_PROVIDER", - "AI_GATEWAY_MODEL", - "ANTHROPIC_BASE_URL", - "ANTHROPIC_AUTH_TOKEN", - "ANTHROPIC_MODEL", - ): + from app.utils.credentials import PASSTHROUGH_ENV_KEYS + + for key in PASSTHROUGH_ENV_KEYS: val = os.environ.get(key) if val: env_vars[key] = val diff --git a/backend/app/services/run_service.py b/backend/app/services/run_service.py index f32b6532a..0d07124f5 100644 --- a/backend/app/services/run_service.py +++ b/backend/app/services/run_service.py @@ -263,26 +263,6 @@ async def list_events_after( return [] return list(await self.repo.list_events_after(run_id, after_seq=after_seq, limit=limit)) - async def find_latest_active_skill_creator_run( - self, *, user_id: str, graph_id: uuid.UUID, thread_id: Optional[str] = None - ) -> Optional[AgentRun]: - """Find the most recent active skill_creator run for a user and graph. - - Args: - user_id: Owner user ID. - graph_id: Graph the run belongs to. - thread_id: Optional thread ID to narrow the search. - - Returns: - The latest active skill_creator run, or None. - """ - return await self.find_latest_active_run( - user_id=user_id, - agent_name="skill_creator", - graph_id=graph_id, - thread_id=thread_id, - ) - async def find_latest_active_run( self, *, diff --git a/backend/app/services/session_service.py b/backend/app/services/session_service.py index 3a6094cb5..50488748c 100644 --- a/backend/app/services/session_service.py +++ b/backend/app/services/session_service.py @@ -37,7 +37,7 @@ async def create_session(self, session_data: SessionCreate, user_id) -> SessionR session_id = str(uuid.uuid4()) # Create workspace directory - workspace_root = Path(settings.WORKSPACE_ROOT) + workspace_root = Path(settings.workspace_root) workspace_path = session_data.workspace_path or str(workspace_root / session_id) workspace = Path(workspace_path) workspace.mkdir(parents=True, exist_ok=True) @@ -117,7 +117,7 @@ async def delete_session(self, session_id: str, user_id=None) -> bool: if workspace_path: workspace = Path(workspace_path) else: - workspace = Path(settings.WORKSPACE_ROOT) / session_id + workspace = Path(settings.workspace_root) / session_id if workspace.exists() and workspace.is_dir(): import shutil @@ -173,7 +173,7 @@ async def get_ai_adapter(self, session_id: str, user_id=None) -> Optional[AgentB return None workspace_path = (conversation.meta_data or {}).get("workspace_path") if not workspace_path: - workspace_path = str(Path(settings.WORKSPACE_ROOT) / session_id) + workspace_path = str(Path(settings.workspace_root) / session_id) # Construct adapter using the decoupled AgentBridge (engine may be injected elsewhere) return AgentBridge(session_id, workspace_path) @@ -184,7 +184,7 @@ async def _to_response(self, conversation: Conversation) -> SessionResponse: ) message_count = count_result.scalar() or 0 workspace_path = (conversation.meta_data or {}).get("workspace_path") or str( - Path(settings.WORKSPACE_ROOT) / conversation.thread_id + Path(settings.workspace_root) / conversation.thread_id ) return SessionResponse( diff --git a/backend/app/services/workspace_file_service.py b/backend/app/services/workspace_file_service.py index 8178ae82c..bab0ce294 100644 --- a/backend/app/services/workspace_file_service.py +++ b/backend/app/services/workspace_file_service.py @@ -45,7 +45,7 @@ def __init__(self, db): # ------------------------------------------------------------------ # def _storage_root(self) -> Path: """Unified file storage root directory.""" - return Path(settings.WORKSPACE_ROOT) / "workspace_files" + return Path(settings.workspace_root) / "workspace_files" def _sanitize_filename(self, filename: str) -> str: """Sanitize filename to prevent path traversal. diff --git a/backend/app/utils/credentials.py b/backend/app/utils/credentials.py new file mode 100644 index 000000000..f41a53e25 --- /dev/null +++ b/backend/app/utils/credentials.py @@ -0,0 +1,43 @@ +""" +Shared credential helpers for CLI agent containers. +""" + +from __future__ import annotations + +import os + +# Host env keys that should be passed through to CLI agent containers +PASSTHROUGH_ENV_KEYS = ( + "ANTHROPIC_API_KEY", + "OPENAI_API_KEY", + "AI_GATEWAY_BASE_URL", + "AI_GATEWAY_API_KEY", + "AI_GATEWAY_PROVIDER", + "AI_GATEWAY_MODEL", + "ANTHROPIC_BASE_URL", + "ANTHROPIC_AUTH_TOKEN", + "ANTHROPIC_MODEL", +) + + +def build_credentials(custom_env: dict[str, str] | None) -> dict[str, str]: + """Merge agent custom_env with host AI provider keys (agent overrides host). + + Raises ValueError if no Anthropic API key is found from any source. + """ + env: dict[str, str] = {} + for key in PASSTHROUGH_ENV_KEYS: + val = os.environ.get(key) + if val: + env[key] = val + if custom_env: + env.update(custom_env) + + has_key = env.get("ANTHROPIC_API_KEY") or env.get("ANTHROPIC_AUTH_TOKEN") + if not has_key: + raise ValueError( + "CLI agent requires an Anthropic API key. " + "Set ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN in " + "the backend environment (.env) or in the agent profile's custom_env." + ) + return env diff --git a/backend/app/utils/mentions.py b/backend/app/utils/mentions.py new file mode 100644 index 000000000..eabfdb579 --- /dev/null +++ b/backend/app/utils/mentions.py @@ -0,0 +1,33 @@ +""" +Mention parsing for comments. + +Format: [@DisplayName](mention://agent/) or [@DisplayName](mention://member/) +""" + +from __future__ import annotations + +import re +import uuid +from dataclasses import dataclass + +_MENTION_RE = re.compile( + r"\[@([^\]]*)\]\(mention://(agent|member)/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\)" +) + + +@dataclass(frozen=True) +class Mention: + display_name: str + type: str # "agent" | "member" + id: uuid.UUID + + +def parse_mentions(content: str) -> list[Mention]: + return [ + Mention(display_name=m.group(1), type=m.group(2), id=uuid.UUID(m.group(3))) + for m in _MENTION_RE.finditer(content) + ] + + +def agent_mentions(content: str) -> list[Mention]: + return [m for m in parse_mentions(content) if m.type == "agent"] diff --git a/backend/app/utils/safe_task.py b/backend/app/utils/safe_task.py new file mode 100644 index 000000000..95e3cd97d --- /dev/null +++ b/backend/app/utils/safe_task.py @@ -0,0 +1,30 @@ +""" +safe_create_task — drop-in replacement for asyncio.create_task with error logging. + +Usage: + from app.utils.safe_task import safe_create_task + + safe_create_task(some_coroutine(), name="my-task") +""" + +import asyncio + +from loguru import logger + + +def safe_create_task(coro, *, name: str | None = None) -> asyncio.Task: + """Create an asyncio task with automatic exception logging via done-callback.""" + task = asyncio.create_task(coro, name=name) + task.add_done_callback(_log_task_exception) + return task + + +def _log_task_exception(task: asyncio.Task) -> None: + if task.cancelled(): + return + exc = task.exception() + if exc: + logger.error( + f"Background task '{task.get_name()}' failed: {exc}", + exc_info=exc, + ) diff --git a/backend/app/utils/string.py b/backend/app/utils/string.py index 31bac13bf..78328c8b3 100644 --- a/backend/app/utils/string.py +++ b/backend/app/utils/string.py @@ -1,9 +1,7 @@ import hashlib import json import re -import uuid from typing import Optional, Tuple, Type -from uuid import uuid4 from loguru import logger from pydantic import BaseModel, ValidationError @@ -199,19 +197,3 @@ def parse_response_model_str(content: str, output_schema: Type[BaseModel]) -> Op logger.warning("All parsing attempts failed.") return structured_output - - -def generate_id(seed: Optional[str] = None) -> str: - """ - Generate a deterministic UUID5 based on a seed string. - If no seed is provided, generate a random UUID4. - - Args: - seed (str): The seed string to generate the UUID from. - - Returns: - str: A deterministic UUID5 string. - """ - if seed is None: - return str(uuid4()) - return str(uuid.uuid5(uuid.NAMESPACE_DNS, seed)) diff --git a/backend/app/utils/token_usage.py b/backend/app/utils/token_usage.py index 0ae18c3aa..648c78565 100644 --- a/backend/app/utils/token_usage.py +++ b/backend/app/utils/token_usage.py @@ -140,9 +140,6 @@ def extract_usage_from_output(output: Any) -> Optional[dict[str, int]]: # 4. amazon-bedrock-invocationMetrics (Bedrock-Titan) if raw_usage is None: raw_usage = rm.get("amazon-bedrock-invocationMetrics") - # 5. usage_metadata (legacy fallback) - if raw_usage is None: - raw_usage = rm.get("usage_metadata") if raw_usage is None: return None diff --git a/backend/app/websocket/chat_ws_handler.py b/backend/app/websocket/chat_ws_handler.py index 29a9deb1e..a53bd5865 100644 --- a/backend/app/websocket/chat_ws_handler.py +++ b/backend/app/websocket/chat_ws_handler.py @@ -48,6 +48,7 @@ from app.services.graph_service import GraphService as GraphService from app.services.run_service import RunService from app.utils.file_event_emitter import FileEventEmitter as FileEventEmitter +from app.utils.safe_task import safe_create_task from app.utils.stream_event_handler import StreamEventHandler as StreamEventHandler from app.utils.stream_event_handler import StreamState from app.utils.task_manager import task_manager @@ -404,7 +405,7 @@ async def _emit_event( if request_id is not None: outbound["request_id"] = request_id if agent_run_id is not None: - asyncio.create_task( + safe_create_task( self._mirror_run_stream_event( run_id=agent_run_id, event=outbound, diff --git a/backend/app/websocket/execution_subscription_handler.py b/backend/app/websocket/execution_subscription_handler.py new file mode 100644 index 000000000..c08868240 --- /dev/null +++ b/backend/app/websocket/execution_subscription_handler.py @@ -0,0 +1,123 @@ +"""WebSocket handler for execution event subscriptions.""" + +from __future__ import annotations + +import json +import uuid + +from fastapi import WebSocket, WebSocketDisconnect + +from app.core.database import AsyncSessionLocal +from app.services.execution_service import ExecutionService +from app.websocket.execution_subscription_manager import execution_subscription_manager + + +class ExecutionSubscriptionHandler: + """Handles subscribe/unsubscribe frames for execution event streams.""" + + async def handle_connection(self, websocket: WebSocket, user_id: str) -> None: + await websocket.accept() + try: + while True: + raw = await websocket.receive_text() + await self._handle_frame(websocket, user_id, raw) + except WebSocketDisconnect: + pass + finally: + execution_subscription_manager.disconnect(websocket) + + async def _handle_frame(self, websocket: WebSocket, user_id: str, raw: str) -> None: + try: + frame = json.loads(raw) + except json.JSONDecodeError: + await websocket.send_text(json.dumps({"type": "ws_error", "message": "invalid json frame"})) + return + + frame_type = frame.get("type") + if frame_type == "ping": + await websocket.send_text(json.dumps({"type": "pong"})) + return + + if frame_type == "unsubscribe": + execution_id = frame.get("execution_id") + if execution_id: + execution_subscription_manager.remove_subscription(websocket, str(execution_id)) + return + + if frame_type != "subscribe": + await websocket.send_text(json.dumps({"type": "ws_error", "message": f"unknown frame type: {frame_type}"})) + return + + execution_id_raw = frame.get("execution_id") + if not execution_id_raw: + await websocket.send_text(json.dumps({"type": "ws_error", "message": "execution_id is required"})) + return + + try: + execution_id = uuid.UUID(str(execution_id_raw)) + except ValueError: + await websocket.send_text(json.dumps({"type": "ws_error", "message": "invalid execution_id"})) + return + + try: + after_seq = int(frame.get("after_seq") or 0) + except (ValueError, TypeError): + await websocket.send_text(json.dumps({"type": "ws_error", "message": "invalid after_seq"})) + return + + async with AsyncSessionLocal() as db: + service = ExecutionService(db) + execution = await service.get_execution(execution_id, user_id) + if execution is None: + await websocket.send_text(json.dumps({"type": "ws_error", "message": "execution not found"})) + return + + snapshot = await service.get_snapshot(execution_id, user_id) + if snapshot is None: + await websocket.send_text(json.dumps({"type": "ws_error", "message": "snapshot not found"})) + return + + snapshot_last_seq = int(snapshot.last_seq or 0) + await websocket.send_text( + json.dumps( + { + "type": "snapshot", + "execution_id": str(execution_id), + "last_seq": snapshot_last_seq, + "data": snapshot.projection, + } + ) + ) + + await execution_subscription_manager.add_subscription(websocket, str(execution_id)) + + catchup_after_seq = max(after_seq, snapshot_last_seq) + events = await service.list_events_after(execution_id, user_id, after_seq=catchup_after_seq, limit=1000) + replay_last_seq = snapshot_last_seq + for event in events: + replay_last_seq = max(replay_last_seq, int(event.seq)) + await websocket.send_text( + json.dumps( + { + "type": "event", + "execution_id": str(execution_id), + "seq": event.seq, + "event_type": event.event_type, + "data": event.payload, + "created_at": event.created_at.isoformat() if event.created_at else None, + } + ) + ) + + await websocket.send_text( + json.dumps( + { + "type": "replay_done", + "execution_id": str(execution_id), + "last_seq": replay_last_seq, + } + ) + ) + + +execution_subscription_handler = ExecutionSubscriptionHandler() diff --git a/backend/app/websocket/execution_subscription_manager.py b/backend/app/websocket/execution_subscription_manager.py new file mode 100644 index 000000000..8a34e0cb5 --- /dev/null +++ b/backend/app/websocket/execution_subscription_manager.py @@ -0,0 +1,61 @@ +"""In-memory execution subscription manager.""" + +from __future__ import annotations + +import json +from collections import defaultdict +from typing import Any + +from fastapi import WebSocket + + +class ExecutionSubscriptionManager: + """Tracks which WebSocket connections are subscribed to which execution IDs. + + Mirrors RunSubscriptionManager but scoped to CLI agent executions. + """ + + def __init__(self) -> None: + self._exec_connections: dict[str, set[WebSocket]] = defaultdict(set) + self._connection_execs: dict[WebSocket, set[str]] = defaultdict(set) + + async def add_subscription(self, websocket: WebSocket, execution_id: str) -> None: + self._exec_connections[execution_id].add(websocket) + self._connection_execs[websocket].add(execution_id) + + def remove_subscription(self, websocket: WebSocket, execution_id: str) -> None: + execs = self._connection_execs.get(websocket) + if execs: + execs.discard(execution_id) + if not execs: + self._connection_execs.pop(websocket, None) + + connections = self._exec_connections.get(execution_id) + if connections: + connections.discard(websocket) + if not connections: + self._exec_connections.pop(execution_id, None) + + def disconnect(self, websocket: WebSocket) -> None: + exec_ids = list(self._connection_execs.get(websocket, set())) + for exec_id in exec_ids: + self.remove_subscription(websocket, exec_id) + + async def broadcast_event(self, execution_id: str, message: dict[str, Any]) -> int: + connections = list(self._exec_connections.get(execution_id, set())) + success_count = 0 + disconnected: list[WebSocket] = [] + for connection in connections: + try: + await connection.send_text(json.dumps(message, default=str)) + success_count += 1 + except Exception: + disconnected.append(connection) + + for connection in disconnected: + self.disconnect(connection) + + return success_count + + +execution_subscription_manager = ExecutionSubscriptionManager() diff --git a/backend/app/websocket/notification_manager.py b/backend/app/websocket/notification_manager.py index 108040d3e..0493e6f63 100644 --- a/backend/app/websocket/notification_manager.py +++ b/backend/app/websocket/notification_manager.py @@ -16,6 +16,9 @@ class NotificationType(str, Enum): INVITATION_ACCEPTED = "invitation_accepted" INVITATION_REJECTED = "invitation_rejected" INVITATION_CANCELLED = "invitation_cancelled" + MISSION_COMMENT_ADDED = "mission_comment_added" + MISSION_UPDATED = "mission_updated" + EXECUTION_STATUS_CHANGED = "execution_status_changed" PING = "ping" PONG = "pong" CONNECTED = "connected" diff --git a/backend/tests/test_core/__init__.py b/backend/tests/test_core/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/backend/tests/test_core/conftest.py b/backend/tests/test_core/conftest.py new file mode 100644 index 000000000..3f9c2c8fe --- /dev/null +++ b/backend/tests/test_core/conftest.py @@ -0,0 +1,3 @@ +import os + +os.environ.setdefault("SECRET_KEY", "test-secret-key-for-unit-tests") diff --git a/backend/tests/test_core/test_cli_backends.py b/backend/tests/test_core/test_cli_backends.py new file mode 100644 index 000000000..d980a7220 --- /dev/null +++ b/backend/tests/test_core/test_cli_backends.py @@ -0,0 +1,383 @@ +from __future__ import annotations + +import asyncio + +import pytest + +from app.core.agent.cli_backends.base import CLIMessage, CLIResult, RuntimeSession +from app.core.agent.cli_backends.claude_code import ClaudeCodeProvider +from app.core.agent.cli_backends.codex import CodexProvider +from app.core.agent.cli_backends.openclaw import OpenClawProvider +from app.core.agent.cli_backends.registry import RuntimeProviderRegistry + + +def test_cli_message_defaults(): + msg = CLIMessage(type="text", content="hello") + assert msg.type == "text" + assert msg.content == "hello" + assert msg.tool == "" + assert msg.input is None + + +def test_cli_result_defaults(): + result = CLIResult(status="completed", output="done") + assert result.status == "completed" + assert result.session_id == "" + + +def test_registry_register_and_get(): + reg = RuntimeProviderRegistry() + provider = ClaudeCodeProvider() + reg.register(provider) + assert reg.get("claude_code") is provider + assert "claude_code" in reg.list_providers() + + +def test_registry_unknown_provider(): + reg = RuntimeProviderRegistry() + with pytest.raises(ValueError, match="Unknown runtime provider"): + reg.get("nonexistent") + + +def test_claude_parse_text_event(): + provider = ClaudeCodeProvider() + event = { + "type": "assistant", + "message": { + "content": [ + {"type": "text", "text": "Hello world"}, + ] + }, + } + messages = provider._parse_event(event) + assert len(messages) == 1 + assert messages[0].type == "text" + assert messages[0].content == "Hello world" + + +def test_claude_parse_tool_use_event(): + provider = ClaudeCodeProvider() + event = { + "type": "assistant", + "message": { + "content": [ + { + "type": "tool_use", + "name": "Bash", + "id": "call-123", + "input": {"command": "ls"}, + }, + ] + }, + } + messages = provider._parse_event(event) + assert len(messages) == 1 + assert messages[0].type == "tool_use" + assert messages[0].tool == "Bash" + assert messages[0].call_id == "call-123" + assert messages[0].input == {"command": "ls"} + + +def test_claude_parse_thinking_event(): + provider = ClaudeCodeProvider() + event = { + "type": "assistant", + "message": { + "content": [ + {"type": "thinking", "thinking": "Let me analyze..."}, + ] + }, + } + messages = provider._parse_event(event) + assert len(messages) == 1 + assert messages[0].type == "thinking" + assert messages[0].content == "Let me analyze..." + + +def test_claude_parse_mixed_content(): + provider = ClaudeCodeProvider() + event = { + "type": "assistant", + "message": { + "content": [ + {"type": "thinking", "thinking": "hmm"}, + {"type": "text", "text": "I'll run a scan"}, + {"type": "tool_use", "name": "Bash", "id": "c1", "input": {"command": "nmap"}}, + ] + }, + } + messages = provider._parse_event(event) + assert len(messages) == 3 + assert messages[0].type == "thinking" + assert messages[1].type == "text" + assert messages[2].type == "tool_use" + + +def test_claude_parse_tool_result_event(): + provider = ClaudeCodeProvider() + event = { + "type": "tool_result", + "tool": "Bash", + "call_id": "c1", + "output": "scan complete", + } + messages = provider._parse_event(event) + assert len(messages) == 1 + assert messages[0].type == "tool_result" + assert messages[0].tool == "Bash" + assert messages[0].output == "scan complete" + + +def test_claude_parse_unknown_event(): + provider = ClaudeCodeProvider() + event = {"type": "unknown_event"} + messages = provider._parse_event(event) + assert len(messages) == 0 + + +@pytest.mark.asyncio +async def test_runtime_session_iter_messages(): + queue: asyncio.Queue[CLIMessage | None] = asyncio.Queue() + loop = asyncio.get_event_loop() + future: asyncio.Future[CLIResult] = loop.create_future() + + session = RuntimeSession(messages=queue, result=future) + + await queue.put(CLIMessage(type="text", content="hello")) + await queue.put(CLIMessage(type="text", content="world")) + await queue.put(None) + + collected = [] + async for msg in session.iter_messages(): + collected.append(msg.content) + + assert collected == ["hello", "world"] + + +@pytest.mark.asyncio +async def test_runtime_session_cancel(): + queue: asyncio.Queue[CLIMessage | None] = asyncio.Queue() + loop = asyncio.get_event_loop() + future: asyncio.Future[CLIResult] = loop.create_future() + + cancelled = False + + async def mock_cancel(): + nonlocal cancelled + cancelled = True + + session = RuntimeSession( + messages=queue, + result=future, + _cancel_fn=mock_cancel, + ) + await session.cancel() + assert cancelled + + +@pytest.mark.asyncio +async def test_runtime_session_inject(): + queue: asyncio.Queue[CLIMessage | None] = asyncio.Queue() + loop = asyncio.get_event_loop() + future: asyncio.Future[CLIResult] = loop.create_future() + + injected = [] + + async def mock_inject(msg: str): + injected.append(msg) + + session = RuntimeSession( + messages=queue, + result=future, + _inject_fn=mock_inject, + ) + await session.inject_message("hello agent") + assert injected == ["hello agent"] + + +# ── Codex provider tests ──────────────────────────────────────────── + + +def test_codex_parse_notification_text(): + provider = CodexProvider() + raw = { + "jsonrpc": "2.0", + "method": "codex/event", + "params": { + "msg": {"type": "agent_message", "message": "Hello from Codex"}, + }, + } + messages = provider._parse_notification(raw) + assert len(messages) == 1 + assert messages[0].type == "text" + assert messages[0].content == "Hello from Codex" + + +def test_codex_parse_notification_tool_use(): + provider = CodexProvider() + # Legacy codex/event format + raw = { + "jsonrpc": "2.0", + "method": "codex/event", + "params": { + "msg": { + "type": "exec_command_begin", + "call_id": "cmd-1", + "command": "ls -la", + }, + }, + } + messages = provider._parse_notification(raw) + assert len(messages) == 1 + assert messages[0].type == "tool_use" + assert messages[0].tool == "exec_command" + assert messages[0].call_id == "cmd-1" + assert messages[0].input == {"command": "ls -la"} + + +def test_codex_parse_notification_tool_use_v2(): + """Raw v2 item/started notification for commandExecution.""" + provider = CodexProvider() + raw = { + "jsonrpc": "2.0", + "method": "item/started", + "params": { + "item": { + "type": "commandExecution", + "id": "item-42", + "command": "git status", + }, + }, + } + messages = provider._parse_notification(raw) + assert len(messages) == 1 + assert messages[0].type == "tool_use" + assert messages[0].tool == "exec_command" + assert messages[0].call_id == "item-42" + assert messages[0].input == {"command": "git status"} + + +def test_codex_parse_response_result(): + """item/completed with agentMessage yields a text CLIMessage.""" + provider = CodexProvider() + raw = { + "jsonrpc": "2.0", + "method": "item/completed", + "params": { + "item": { + "type": "agentMessage", + "id": "msg-99", + "text": "All done!", + }, + }, + } + messages = provider._parse_notification(raw) + assert len(messages) == 1 + assert messages[0].type == "text" + assert messages[0].content == "All done!" + + +def test_codex_parse_unknown_event(): + provider = CodexProvider() + raw = { + "jsonrpc": "2.0", + "method": "some/unknown/method", + "params": {}, + } + messages = provider._parse_notification(raw) + assert len(messages) == 0 + + +# ── OpenClaw provider tests ───────────────────────────────────────── + + +def test_openclaw_parse_message_event(): + provider = OpenClawProvider() + line = '{"type": "text", "text": "Analyzing your code..."}' + messages = provider._parse_line(line) + assert len(messages) == 1 + assert messages[0].type == "text" + assert messages[0].content == "Analyzing your code..." + + +def test_openclaw_parse_tool_call_event(): + provider = OpenClawProvider() + line = '{"type": "tool_use", "tool": "Bash", "callId": "tc-1", "input": {"command": "pwd"}}' + messages = provider._parse_line(line) + assert len(messages) == 1 + assert messages[0].type == "tool_use" + assert messages[0].tool == "Bash" + assert messages[0].call_id == "tc-1" + assert messages[0].input == {"command": "pwd"} + + +def test_openclaw_parse_tool_result_event(): + provider = OpenClawProvider() + line = '{"type": "tool_result", "tool": "Bash", "callId": "tc-1", "text": "/workspace"}' + messages = provider._parse_line(line) + assert len(messages) == 1 + assert messages[0].type == "tool_result" + assert messages[0].tool == "Bash" + assert messages[0].call_id == "tc-1" + assert messages[0].output == "/workspace" + + +def test_openclaw_parse_error_event(): + provider = OpenClawProvider() + line = '{"type": "error", "text": "Rate limit exceeded"}' + messages = provider._parse_line(line) + assert len(messages) == 1 + assert messages[0].type == "error" + assert messages[0].content == "Rate limit exceeded" + + +def test_openclaw_parse_error_event_structured(): + """Error with structured error object (PaperClip format).""" + provider = OpenClawProvider() + line = '{"type": "error", "error": {"name": "RateLimitError", "data": {"message": "Too many requests"}}}' + messages = provider._parse_line(line) + assert len(messages) == 1 + assert messages[0].type == "error" + assert messages[0].content == "Too many requests" + + +def test_openclaw_parse_done_event(): + """step_finish events produce a text marker.""" + provider = OpenClawProvider() + line = '{"type": "step_finish", "usage": {"input_tokens": 100, "output_tokens": 50}}' + messages = provider._parse_line(line) + assert len(messages) == 1 + assert messages[0].type == "text" + assert messages[0].content == "[step finished]" + + +def test_openclaw_parse_unknown_event(): + provider = OpenClawProvider() + line = '{"type": "some_future_event", "data": "whatever"}' + messages = provider._parse_line(line) + assert len(messages) == 0 + + +def test_openclaw_parse_non_json_line(): + provider = OpenClawProvider() + messages = provider._parse_line("INFO: starting agent...") + assert len(messages) == 0 + + +# ── Registry integration ──────────────────────────────────────────── + + +def test_registry_all_providers(): + reg = RuntimeProviderRegistry() + reg.register(ClaudeCodeProvider()) + reg.register(CodexProvider()) + reg.register(OpenClawProvider()) + + providers = reg.list_providers() + assert "claude_code" in providers + assert "codex" in providers + assert "openclaw" in providers + assert len(providers) == 3 + + assert reg.get("codex").provider_type == "codex" + assert reg.get("openclaw").provider_type == "openclaw" diff --git a/backend/tests/test_core/test_container_injectors.py b/backend/tests/test_core/test_container_injectors.py new file mode 100644 index 000000000..faff986a5 --- /dev/null +++ b/backend/tests/test_core/test_container_injectors.py @@ -0,0 +1,162 @@ +from __future__ import annotations + +import pytest + +from app.core.agent.cli_backends.container_service import ContainerConfig, ContainerInfo +from app.core.agent.cli_backends.injectors import ( + CLISkillInjector, + CredentialInjector, + RuntimeConfigInjector, +) + +# --------------------------------------------------------------------------- +# ContainerConfig / ContainerInfo data classes +# --------------------------------------------------------------------------- + + +def test_container_config_defaults(): + cfg = ContainerConfig() + assert cfg.image == "joysafeter/cli-agent:latest" + assert cfg.memory_limit == "2g" + assert cfg.network_mode == "bridge" + assert cfg.labels == {} + + +def test_container_config_custom(): + cfg = ContainerConfig(image="my-image:v1", memory_limit="4g", labels={"env": "test"}) + assert cfg.image == "my-image:v1" + assert cfg.memory_limit == "4g" + assert cfg.labels == {"env": "test"} + + +def test_container_info(): + info = ContainerInfo( + container_id="abc123", + name="cli-agent-test", + status="running", + working_dir="/workspace", + ) + assert info.container_id == "abc123" + assert info.name == "cli-agent-test" + + +# --------------------------------------------------------------------------- +# RuntimeConfigInjector._build_claude_md (pure logic, no Docker needed) +# --------------------------------------------------------------------------- + + +class _FakeContainerService: + """Stub that records exec calls without touching Docker.""" + + def __init__(self): + self.calls: list[tuple[str, list[str]]] = [] + + async def exec_in_container(self, container_id, cmd, workdir=None): + self.calls.append((container_id, cmd)) + return "" + + +def test_build_claude_md_minimal(): + injector = RuntimeConfigInjector(_FakeContainerService()) + md = injector._build_claude_md() + assert "# Agent Configuration" in md + assert "autonomous coding agent" in md + assert "## Instructions" not in md + assert "## Available Skills" not in md + assert "## Project Context" not in md + + +def test_build_claude_md_with_instructions(): + injector = RuntimeConfigInjector(_FakeContainerService()) + md = injector._build_claude_md(instructions="Always write tests first.") + assert "## Instructions" in md + assert "Always write tests first." in md + + +def test_build_claude_md_with_skills(): + injector = RuntimeConfigInjector(_FakeContainerService()) + md = injector._build_claude_md(skill_names=["code_review", "deploy"]) + assert "## Available Skills" in md + assert "- code_review" in md + assert "- deploy" in md + + +def test_build_claude_md_with_project_context(): + injector = RuntimeConfigInjector(_FakeContainerService()) + md = injector._build_claude_md(project_context="Python 3.12, FastAPI backend") + assert "## Project Context" in md + assert "Python 3.12, FastAPI backend" in md + + +def test_build_claude_md_full(): + injector = RuntimeConfigInjector(_FakeContainerService()) + md = injector._build_claude_md( + instructions="Be thorough.", + skill_names=["lint", "test"], + project_context="Monorepo with backend/ and frontend/", + ) + assert "## Instructions" in md + assert "Be thorough." in md + assert "## Available Skills" in md + assert "- lint" in md + assert "- test" in md + assert "## Project Context" in md + assert "Monorepo" in md + + +# --------------------------------------------------------------------------- +# Async injector tests (using fake container service) +# --------------------------------------------------------------------------- + + +@pytest.mark.asyncio +async def test_credential_injector_build_env(): + injector = CredentialInjector() + env = injector.build_env({"ANTHROPIC_API_KEY": "sk-test", "GITHUB_TOKEN": "ghp-abc"}) + assert env == {"ANTHROPIC_API_KEY": "sk-test", "GITHUB_TOKEN": "ghp-abc"} + + +@pytest.mark.asyncio +async def test_credential_injector_empty(): + injector = CredentialInjector() + env = injector.build_env({}) + assert env == {} + + +@pytest.mark.asyncio +async def test_skill_injector_inject(): + svc = _FakeContainerService() + injector = CLISkillInjector(svc) + skills = [ + {"name": "lint", "command": "ruff check ."}, + {"name": "test", "command": "pytest"}, + ] + await injector.inject("ctr-2", skills) + # 1 mkdir + 2 skill writes + assert len(svc.calls) == 3 + assert svc.calls[0][1] == ["mkdir", "-p", "/workspace/.skills"] + + +@pytest.mark.asyncio +async def test_skill_injector_empty(): + svc = _FakeContainerService() + injector = CLISkillInjector(svc) + await injector.inject("ctr-2", []) + assert len(svc.calls) == 0 + + +@pytest.mark.asyncio +async def test_runtime_config_injector_inject(): + svc = _FakeContainerService() + injector = RuntimeConfigInjector(svc) + await injector.inject( + "ctr-3", + instructions="Write clean code.", + skill_names=["lint"], + working_dir="/project", + ) + assert len(svc.calls) == 1 + container_id, cmd = svc.calls[0] + assert container_id == "ctr-3" + cmd_str = " ".join(cmd) + assert "/project/CLAUDE.md" in cmd_str diff --git a/backend/tests/test_core/test_execution_reducer.py b/backend/tests/test_core/test_execution_reducer.py new file mode 100644 index 000000000..2124d6620 --- /dev/null +++ b/backend/tests/test_core/test_execution_reducer.py @@ -0,0 +1,311 @@ +from __future__ import annotations + +from app.services.execution_reducer import apply_execution_event, make_initial_projection + + +def test_make_initial_projection(): + proj = make_initial_projection( + {"source": "mission", "mission_id": "m1", "agent_profile_id": "a1"}, + "queued", + ) + assert proj["status"] == "queued" + assert proj["source"] == "mission" + assert proj["mission_id"] == "m1" + assert proj["agent_profile_id"] == "a1" + assert proj["messages"] == [] + assert proj["tool_calls"] == [] + assert proj["artifacts"] == [] + + +def test_execution_started(): + proj = make_initial_projection({"source": "chat"}, "running") + proj = apply_execution_event( + proj, + event_type="execution_started", + payload={"container_id": "ctr-1", "session_id": "sess-1"}, + status="running", + ) + assert proj["container_id"] == "ctr-1" + assert proj["session_id"] == "sess-1" + assert proj["status"] == "running" + + +def test_prompt_sent(): + proj = make_initial_projection({}, "running") + msg = {"role": "user", "content": "Fix the bug"} + proj = apply_execution_event( + proj, + event_type="prompt_sent", + payload={"message": msg}, + status="running", + ) + assert len(proj["messages"]) == 1 + assert proj["messages"][0]["content"] == "Fix the bug" + + +def test_assistant_text_with_message_dict(): + proj = make_initial_projection({}, "running") + msg = {"role": "assistant", "content": "On it"} + proj = apply_execution_event( + proj, + event_type="assistant_text", + payload={"message": msg}, + status="running", + ) + assert len(proj["messages"]) == 1 + assert proj["messages"][0]["content"] == "On it" + + +def test_assistant_text_with_content_string(): + proj = make_initial_projection({}, "running") + proj = apply_execution_event( + proj, + event_type="assistant_text", + payload={"content": "Hello"}, + status="running", + ) + assert len(proj["messages"]) == 1 + assert proj["messages"][0]["role"] == "assistant" + assert proj["messages"][0]["content"] == "Hello" + + +def test_content_delta_appends(): + proj = make_initial_projection({}, "running") + proj["messages"].append({"role": "assistant", "content": "Hel", "id": "m1"}) + proj = apply_execution_event( + proj, + event_type="content_delta", + payload={"delta": "lo", "message_id": "m1"}, + status="running", + ) + assert proj["messages"][-1]["content"] == "Hello" + + +def test_content_delta_no_messages_is_noop(): + proj = make_initial_projection({}, "running") + proj = apply_execution_event( + proj, + event_type="content_delta", + payload={"delta": "x"}, + status="running", + ) + assert proj["messages"] == [] + + +def test_tool_use_start_with_dict(): + proj = make_initial_projection({}, "running") + tool = {"name": "Bash", "call_id": "c1", "input": {"command": "ls"}, "status": "running"} + proj = apply_execution_event( + proj, + event_type="tool_use_start", + payload={"tool": tool}, + status="running", + ) + assert len(proj["tool_calls"]) == 1 + assert proj["tool_calls"][0]["name"] == "Bash" + + +def test_tool_use_start_with_flat_fields(): + proj = make_initial_projection({}, "running") + proj = apply_execution_event( + proj, + event_type="tool_use_start", + payload={"tool_name": "Read", "call_id": "c2", "input": {"path": "/tmp"}}, + status="running", + ) + assert len(proj["tool_calls"]) == 1 + assert proj["tool_calls"][0]["name"] == "Read" + assert proj["tool_calls"][0]["status"] == "running" + + +def test_tool_use_end(): + proj = make_initial_projection({}, "running") + proj["tool_calls"].append({"name": "Bash", "call_id": "c1", "status": "running"}) + proj = apply_execution_event( + proj, + event_type="tool_use_end", + payload={"call_id": "c1", "output": "file.txt"}, + status="running", + ) + assert proj["tool_calls"][0]["status"] == "completed" + assert proj["tool_calls"][0]["output"] == "file.txt" + + +def test_tool_use_end_no_match(): + proj = make_initial_projection({}, "running") + proj["tool_calls"].append({"name": "Bash", "call_id": "c1", "status": "completed"}) + proj = apply_execution_event( + proj, + event_type="tool_use_end", + payload={"call_id": "c99", "output": "nope"}, + status="running", + ) + # No match — original stays unchanged + assert proj["tool_calls"][0]["status"] == "completed" + assert "output" not in proj["tool_calls"][0] or proj["tool_calls"][0].get("output") != "nope" + + +def test_thinking(): + proj = make_initial_projection({}, "running") + proj = apply_execution_event( + proj, + event_type="thinking", + payload={"content": "analyzing..."}, + status="running", + ) + assert proj["meta"]["last_thinking"] == "analyzing..." + + +def test_artifact_created(): + proj = make_initial_projection({}, "running") + artifact = {"type": "file", "path": "/app/main.py"} + proj = apply_execution_event( + proj, + event_type="artifact_created", + payload={"artifact": artifact}, + status="running", + ) + assert len(proj["artifacts"]) == 1 + assert proj["artifacts"][0]["path"] == "/app/main.py" + + +def test_approval_requested_and_resolved(): + proj = make_initial_projection({}, "approval_wait") + proj = apply_execution_event( + proj, + event_type="approval_requested", + payload={"tool": "Bash", "command": "rm -rf /"}, + status="approval_wait", + ) + assert proj["meta"]["pending_approval"]["tool"] == "Bash" + + proj = apply_execution_event( + proj, + event_type="approval_resolved", + payload={"approved": True}, + status="running", + ) + assert "pending_approval" not in proj["meta"] + + +def test_error_event(): + proj = make_initial_projection({}, "failed") + proj = apply_execution_event( + proj, + event_type="error", + payload={"message": "OOM"}, + status="failed", + ) + assert proj["meta"]["error"] == "OOM" + assert proj["status"] == "failed" + + +def test_execution_completed(): + proj = make_initial_projection({}, "completed") + proj = apply_execution_event( + proj, + event_type="execution_completed", + payload={"result_summary": {"files_changed": 3}}, + status="completed", + ) + assert proj["meta"]["completed"] is True + assert proj["meta"]["result_summary"]["files_changed"] == 3 + + +def test_heartbeat_is_noop(): + proj = make_initial_projection({}, "running") + original_messages = list(proj["messages"]) + proj = apply_execution_event( + proj, + event_type="heartbeat", + payload={}, + status="running", + ) + assert proj["messages"] == original_messages + + +def test_unknown_event_preserves_projection(): + proj = make_initial_projection({}, "running") + proj["messages"].append({"role": "user", "content": "hi"}) + proj = apply_execution_event( + proj, + event_type="some_future_event", + payload={"data": 1}, + status="running", + ) + assert len(proj["messages"]) == 1 + assert proj["status"] == "running" + + +def test_immutability(): + """Verify that apply_execution_event does not mutate the input projection.""" + proj = make_initial_projection({}, "running") + proj["messages"].append({"role": "assistant", "content": "hi", "id": "m1"}) + original_content = proj["messages"][0]["content"] + + _ = apply_execution_event( + proj, + event_type="content_delta", + payload={"delta": " world", "message_id": "m1"}, + status="running", + ) + # Original should be untouched + assert proj["messages"][0]["content"] == original_content + + +def test_full_lifecycle(): + """Walk through a realistic sequence of events.""" + proj = make_initial_projection( + {"source": "mission", "mission_id": "m1"}, + "queued", + ) + assert proj["status"] == "queued" + + proj = apply_execution_event( + proj, + event_type="execution_started", + payload={"container_id": "ctr-abc", "session_id": "s1"}, + status="running", + ) + assert proj["container_id"] == "ctr-abc" + + proj = apply_execution_event( + proj, + event_type="prompt_sent", + payload={"message": {"role": "user", "content": "Fix login bug"}}, + status="running", + ) + + proj = apply_execution_event( + proj, + event_type="assistant_text", + payload={"message": {"role": "assistant", "content": "Looking into it", "id": "a1"}}, + status="running", + ) + + proj = apply_execution_event( + proj, + event_type="tool_use_start", + payload={"tool": {"name": "Bash", "call_id": "t1", "input": {"command": "grep"}, "status": "running"}}, + status="running", + ) + + proj = apply_execution_event( + proj, + event_type="tool_use_end", + payload={"call_id": "t1", "output": "found match"}, + status="running", + ) + + proj = apply_execution_event( + proj, + event_type="execution_completed", + payload={"result_summary": {"fixed": True}}, + status="completed", + ) + + assert proj["status"] == "completed" + assert len(proj["messages"]) == 2 + assert len(proj["tool_calls"]) == 1 + assert proj["tool_calls"][0]["status"] == "completed" + assert proj["meta"]["completed"] is True diff --git a/backend/tests/test_core/test_execution_runner.py b/backend/tests/test_core/test_execution_runner.py new file mode 100644 index 000000000..62c10bd3e --- /dev/null +++ b/backend/tests/test_core/test_execution_runner.py @@ -0,0 +1,109 @@ +from __future__ import annotations + +from app.core.agent.cli_backends.base import CLIMessage +from app.core.agent.cli_backends.execution_runner import ExecutionRunner + + +def test_msg_to_event_type_text(): + msg = CLIMessage(type="text", content="hello") + assert ExecutionRunner._msg_to_event_type(msg) == "assistant_text" + + +def test_msg_to_event_type_thinking(): + msg = CLIMessage(type="thinking", content="hmm") + assert ExecutionRunner._msg_to_event_type(msg) == "thinking" + + +def test_msg_to_event_type_tool_use(): + msg = CLIMessage(type="tool_use", tool="Bash", call_id="c1") + assert ExecutionRunner._msg_to_event_type(msg) == "tool_use_start" + + +def test_msg_to_event_type_tool_result(): + msg = CLIMessage(type="tool_result", tool="Bash", call_id="c1", output="ok") + assert ExecutionRunner._msg_to_event_type(msg) == "tool_use_end" + + +def test_msg_to_event_type_error(): + msg = CLIMessage(type="error", content="boom") + assert ExecutionRunner._msg_to_event_type(msg) == "error" + + +def test_msg_to_event_type_artifact(): + msg = CLIMessage(type="artifact", content="file data") + assert ExecutionRunner._msg_to_event_type(msg) == "artifact_created" + + +def test_msg_to_event_type_unknown(): + msg = CLIMessage(type="custom_type", content="data") + assert ExecutionRunner._msg_to_event_type(msg) == "custom_type" + + +def test_msg_to_payload_text(): + msg = CLIMessage(type="text", content="hello world") + payload = ExecutionRunner._msg_to_payload(msg) + assert payload == {"content": "hello world"} + + +def test_msg_to_payload_thinking(): + msg = CLIMessage(type="thinking", content="analyzing") + payload = ExecutionRunner._msg_to_payload(msg) + assert payload == {"content": "analyzing"} + + +def test_msg_to_payload_tool_use(): + msg = CLIMessage(type="tool_use", tool="Bash", call_id="c1", input={"command": "ls"}) + payload = ExecutionRunner._msg_to_payload(msg) + assert payload["tool"]["name"] == "Bash" + assert payload["tool"]["call_id"] == "c1" + assert payload["tool"]["input"] == {"command": "ls"} + assert payload["tool"]["status"] == "running" + + +def test_msg_to_payload_tool_result(): + msg = CLIMessage(type="tool_result", tool="Bash", call_id="c1", output="file.txt") + payload = ExecutionRunner._msg_to_payload(msg) + assert payload["call_id"] == "c1" + assert payload["tool_name"] == "Bash" + assert payload["output"] == "file.txt" + + +def test_msg_to_payload_error(): + msg = CLIMessage(type="error", content="OOM killed") + payload = ExecutionRunner._msg_to_payload(msg) + assert payload == {"message": "OOM killed"} + + +def test_msg_to_payload_artifact(): + msg = CLIMessage(type="artifact", content="binary data") + payload = ExecutionRunner._msg_to_payload(msg) + assert payload == {"artifact": {"content": "binary data"}} + + +def test_msg_to_payload_unknown(): + msg = CLIMessage(type="custom", content="stuff") + payload = ExecutionRunner._msg_to_payload(msg) + assert payload == {"content": "stuff"} + + +def test_runner_accepts_none_callbacks(): + """Standalone executions pass callbacks=None.""" + from unittest.mock import MagicMock + + db = MagicMock() + runner = ExecutionRunner(db, callbacks=None) + assert runner.callbacks is None + + +def test_runner_accepts_callbacks(): + """Mission executions pass a callbacks implementation.""" + from unittest.mock import MagicMock + + db = MagicMock() + + class StubCallbacks: + async def on_execution_finalized(self, execution_id, status, result): ... + async def on_execution_failed(self, execution_id, error): ... + + runner = ExecutionRunner(db, callbacks=StubCallbacks()) + assert runner.callbacks is not None diff --git a/backend/tests/test_core/test_execution_subscription.py b/backend/tests/test_core/test_execution_subscription.py new file mode 100644 index 000000000..6bd2847ce --- /dev/null +++ b/backend/tests/test_core/test_execution_subscription.py @@ -0,0 +1,113 @@ +from __future__ import annotations + +import asyncio +import json +from unittest.mock import AsyncMock, MagicMock + +import pytest + +from app.websocket.execution_subscription_manager import ExecutionSubscriptionManager + + +def _make_ws() -> MagicMock: + ws = MagicMock() + ws.send_text = AsyncMock() + return ws + + +def test_add_and_remove_subscription(): + mgr = ExecutionSubscriptionManager() + ws = _make_ws() + + asyncio.get_event_loop().run_until_complete(mgr.add_subscription(ws, "exec-1")) + assert ws in mgr._exec_connections["exec-1"] + assert "exec-1" in mgr._connection_execs[ws] + + mgr.remove_subscription(ws, "exec-1") + assert ws not in mgr._exec_connections.get("exec-1", set()) + assert ws not in mgr._connection_execs + + +def test_disconnect_removes_all(): + mgr = ExecutionSubscriptionManager() + ws = _make_ws() + + asyncio.get_event_loop().run_until_complete(mgr.add_subscription(ws, "exec-1")) + asyncio.get_event_loop().run_until_complete(mgr.add_subscription(ws, "exec-2")) + + mgr.disconnect(ws) + assert ws not in mgr._connection_execs + assert ws not in mgr._exec_connections.get("exec-1", set()) + assert ws not in mgr._exec_connections.get("exec-2", set()) + + +@pytest.mark.asyncio +async def test_broadcast_event(): + mgr = ExecutionSubscriptionManager() + ws1 = _make_ws() + ws2 = _make_ws() + + await mgr.add_subscription(ws1, "exec-1") + await mgr.add_subscription(ws2, "exec-1") + + count = await mgr.broadcast_event("exec-1", {"type": "event", "seq": 1}) + assert count == 2 + assert ws1.send_text.call_count == 1 + assert ws2.send_text.call_count == 1 + + sent = json.loads(ws1.send_text.call_args[0][0]) + assert sent["type"] == "event" + assert sent["seq"] == 1 + + +@pytest.mark.asyncio +async def test_broadcast_to_empty(): + mgr = ExecutionSubscriptionManager() + count = await mgr.broadcast_event("nonexistent", {"type": "event"}) + assert count == 0 + + +@pytest.mark.asyncio +async def test_broadcast_disconnects_failed(): + mgr = ExecutionSubscriptionManager() + ws_good = _make_ws() + ws_bad = _make_ws() + ws_bad.send_text.side_effect = Exception("connection closed") + + await mgr.add_subscription(ws_good, "exec-1") + await mgr.add_subscription(ws_bad, "exec-1") + + count = await mgr.broadcast_event("exec-1", {"type": "event"}) + assert count == 1 + # ws_bad should have been disconnected + assert ws_bad not in mgr._exec_connections.get("exec-1", set()) + + +@pytest.mark.asyncio +async def test_multiple_executions_per_connection(): + mgr = ExecutionSubscriptionManager() + ws = _make_ws() + + await mgr.add_subscription(ws, "exec-1") + await mgr.add_subscription(ws, "exec-2") + + assert "exec-1" in mgr._connection_execs[ws] + assert "exec-2" in mgr._connection_execs[ws] + + mgr.remove_subscription(ws, "exec-1") + assert "exec-1" not in mgr._connection_execs[ws] + assert "exec-2" in mgr._connection_execs[ws] + + +def test_remove_nonexistent_subscription(): + mgr = ExecutionSubscriptionManager() + ws = _make_ws() + # Should not raise + mgr.remove_subscription(ws, "nonexistent") + + +def test_disconnect_unsubscribed(): + mgr = ExecutionSubscriptionManager() + ws = _make_ws() + # Should not raise + mgr.disconnect(ws) diff --git a/backend/tests/test_core/test_integration.py b/backend/tests/test_core/test_integration.py new file mode 100644 index 000000000..9decc9dcc --- /dev/null +++ b/backend/tests/test_core/test_integration.py @@ -0,0 +1,542 @@ +""" +Integration test: validates the full mission-to-execution pipeline. + +Exercises the complete flow without a live database or Docker daemon: + AgentProfile creation → Mission creation → assign to agent → + dispatch (creates execution) → verify event sourcing → verify reducer → + verify subscription manager → verify cleanup lifecycle. +""" + +from __future__ import annotations + +import uuid +from unittest.mock import AsyncMock, MagicMock + +import pytest + +from app.core.agent.cli_backends.base import CLIMessage +from app.core.agent.cli_backends.claude_code import ClaudeCodeProvider +from app.core.agent.cli_backends.container_service import ContainerInfo +from app.core.agent.cli_backends.execution_runner import ExecutionRunner +from app.core.agent.cli_backends.injectors import ( + CLISkillInjector, + CredentialInjector, + RuntimeConfigInjector, +) +from app.core.agent.cli_backends.registry import RuntimeProviderRegistry +from app.schemas.execution import ( + AgentProfileSummary, + ExecutionSummary, + MissionSummary, +) +from app.services.execution_lifecycle_service import build_execution_prompt +from app.services.execution_reducer import apply_execution_event, make_initial_projection +from app.websocket.execution_subscription_manager import ExecutionSubscriptionManager + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def _make_ws(): + ws = MagicMock() + ws.send_text = AsyncMock() + return ws + + +class FakeContainerService: + """Records calls without touching Docker.""" + + def __init__(self): + self.calls: list[tuple[str, list]] = [] + self.created: list[str] = [] + self.removed: list[str] = [] + + async def create_container(self, *, execution_id, config=None, env=None): + cid = f"fake-ctr-{execution_id!s:.8}" + self.created.append(cid) + return ContainerInfo( + container_id=cid, + name=f"cli-agent-{execution_id!s:.12}", + status="running", + working_dir="/workspace", + ) + + async def exec_in_container(self, container_id, cmd, workdir=None): + self.calls.append((container_id, cmd)) + return "" + + async def remove_container(self, container_id, force=True): + self.removed.append(container_id) + + async def stop_container(self, container_id, timeout=10): + pass + + async def copy_to_container(self, container_id, src, dest): + pass + + +# --------------------------------------------------------------------------- +# 1. Schema validation +# --------------------------------------------------------------------------- + + +def test_schemas_round_trip(): + """Verify Pydantic schemas serialize/deserialize correctly.""" + profile = AgentProfileSummary( + id=uuid.uuid4(), + workspace_id=uuid.uuid4(), + name="test-agent", + runtime_type="claude_code", + status="idle", + max_concurrent_tasks=1, + created_at="2025-01-01T00:00:00Z", + updated_at="2025-01-01T00:00:00Z", + ) + data = profile.model_dump() + assert data["name"] == "test-agent" + assert data["runtime_type"] == "claude_code" + + mission = MissionSummary( + id=uuid.uuid4(), + workspace_id=uuid.uuid4(), + title="Fix bug", + status="todo", + priority="high", + creator_id="user-1", + position=0.0, + created_at="2025-01-01T00:00:00Z", + updated_at="2025-01-01T00:00:00Z", + ) + data = mission.model_dump() + assert data["title"] == "Fix bug" + + execution = ExecutionSummary( + id=uuid.uuid4(), + workspace_id=uuid.uuid4(), + user_id="user-1", + source="mission", + status="running", + runtime_type="claude_code", + last_seq=5, + created_at="2025-01-01T00:00:00Z", + updated_at="2025-01-01T00:00:00Z", + ) + data = execution.model_dump() + assert data["source"] == "mission" + assert data["last_seq"] == 5 + + +# --------------------------------------------------------------------------- +# 2. Prompt building from mission +# --------------------------------------------------------------------------- + + +def test_prompt_building_integration(): + """Verify prompt building produces valid agent instructions.""" + mission = MagicMock() + mission.title = "Implement OAuth2 login" + mission.description = "Add Google OAuth2 provider to the auth module." + mission.objective = "Users can log in with Google accounts." + mission.tags = ["auth", "oauth", "backend"] + + prompt = build_execution_prompt(mission) + + assert "# Mission: Implement OAuth2 login" in prompt + assert "Google OAuth2" in prompt + assert "Users can log in" in prompt + assert "auth" in prompt + assert "oauth" in prompt + + +# --------------------------------------------------------------------------- +# 3. Registry + provider lookup +# --------------------------------------------------------------------------- + + +def test_registry_lifecycle(): + """Register a provider, look it up, list it.""" + reg = RuntimeProviderRegistry() + provider = ClaudeCodeProvider(executable_path="/usr/bin/claude") + reg.register(provider) + + assert reg.get("claude_code") is provider + assert "claude_code" in reg.list_providers() + + with pytest.raises(ValueError): + reg.get("nonexistent_provider") + + +# --------------------------------------------------------------------------- +# 4. Container + injection pipeline +# --------------------------------------------------------------------------- + + +@pytest.mark.asyncio +async def test_container_injection_pipeline(): + """Create container → inject credentials → inject skills → inject config.""" + svc = FakeContainerService() + exec_id = uuid.uuid4() + + container = await svc.create_container(execution_id=exec_id) + assert container.status == "running" + assert container.container_id.startswith("fake-ctr-") + + # Build credentials env (no longer writes to container filesystem) + cred_injector = CredentialInjector() + env = cred_injector.build_env( + { + "ANTHROPIC_API_KEY": "sk-test-key", + "GITHUB_TOKEN": "ghp-test", + } + ) + assert env == {"ANTHROPIC_API_KEY": "sk-test-key", "GITHUB_TOKEN": "ghp-test"} + + # Inject skills + skill_injector = CLISkillInjector(svc) + await skill_injector.inject( + container.container_id, + [ + {"name": "lint", "command": "ruff check ."}, + {"name": "test", "command": "pytest -x"}, + ], + ) + assert len(svc.calls) == 3 # 1 mkdir + 2 skills + + # Inject CLAUDE.md config + config_injector = RuntimeConfigInjector(svc) + await config_injector.inject( + container.container_id, + instructions="Always write tests.", + skill_names=["lint", "test"], + working_dir="/workspace", + ) + assert len(svc.calls) == 4 # + 1 config write + + +# --------------------------------------------------------------------------- +# 5. Event sourcing + reducer pipeline +# --------------------------------------------------------------------------- + + +def test_event_sourcing_full_lifecycle(): + """Walk through a complete execution event sequence and verify projection.""" + proj = make_initial_projection( + {"source": "mission", "mission_id": "m-1", "agent_profile_id": "a-1"}, + "queued", + ) + assert proj["status"] == "queued" + assert proj["messages"] == [] + + # Execution starts + proj = apply_execution_event( + proj, + event_type="execution_started", + payload={"container_id": "ctr-abc", "session_id": "s-1"}, + status="running", + ) + assert proj["container_id"] == "ctr-abc" + + # User prompt sent + proj = apply_execution_event( + proj, + event_type="prompt_sent", + payload={"message": {"role": "user", "content": "Fix the login bug"}}, + status="running", + ) + assert len(proj["messages"]) == 1 + + # Agent thinks + proj = apply_execution_event( + proj, + event_type="thinking", + payload={"content": "Let me analyze the auth module..."}, + status="running", + ) + assert proj["meta"]["last_thinking"] == "Let me analyze the auth module..." + + # Agent responds + proj = apply_execution_event( + proj, + event_type="assistant_text", + payload={"message": {"role": "assistant", "content": "Found the issue", "id": "a1"}}, + status="running", + ) + assert len(proj["messages"]) == 2 + + # Content delta + proj = apply_execution_event( + proj, + event_type="content_delta", + payload={"delta": " in auth.py", "message_id": "a1"}, + status="running", + ) + assert proj["messages"][-1]["content"] == "Found the issue in auth.py" + + # Tool use + proj = apply_execution_event( + proj, + event_type="tool_use_start", + payload={"tool": {"name": "Edit", "call_id": "t1", "input": {"file": "auth.py"}, "status": "running"}}, + status="running", + ) + assert len(proj["tool_calls"]) == 1 + assert proj["tool_calls"][0]["status"] == "running" + + proj = apply_execution_event( + proj, + event_type="tool_use_end", + payload={"call_id": "t1", "output": "File edited successfully"}, + status="running", + ) + assert proj["tool_calls"][0]["status"] == "completed" + + # Approval flow + proj = apply_execution_event( + proj, + event_type="approval_requested", + payload={"tool": "Bash", "command": "git push"}, + status="approval_wait", + ) + assert "pending_approval" in proj["meta"] + + proj = apply_execution_event( + proj, + event_type="approval_resolved", + payload={"approved": True}, + status="running", + ) + assert "pending_approval" not in proj["meta"] + + # Artifact + proj = apply_execution_event( + proj, + event_type="artifact_created", + payload={"artifact": {"type": "file", "path": "/workspace/auth.py"}}, + status="running", + ) + assert len(proj["artifacts"]) == 1 + + # Completion + proj = apply_execution_event( + proj, + event_type="execution_completed", + payload={"result_summary": {"files_changed": 2, "tests_passed": True}}, + status="completed", + ) + assert proj["status"] == "completed" + assert proj["meta"]["completed"] is True + assert proj["meta"]["result_summary"]["files_changed"] == 2 + + +# --------------------------------------------------------------------------- +# 6. WebSocket subscription manager +# --------------------------------------------------------------------------- + + +@pytest.mark.asyncio +async def test_subscription_manager_full_flow(): + """Subscribe, broadcast, unsubscribe, disconnect.""" + mgr = ExecutionSubscriptionManager() + ws1 = _make_ws() + ws2 = _make_ws() + exec_id = str(uuid.uuid4()) + + # Subscribe both + await mgr.add_subscription(ws1, exec_id) + await mgr.add_subscription(ws2, exec_id) + + # Broadcast event + count = await mgr.broadcast_event( + exec_id, + { + "type": "event", + "execution_id": exec_id, + "seq": 1, + "event_type": "assistant_text", + "data": {"content": "hello"}, + }, + ) + assert count == 2 + + # Verify both received + assert ws1.send_text.call_count == 1 + assert ws2.send_text.call_count == 1 + + # Unsubscribe ws1 + mgr.remove_subscription(ws1, exec_id) + count = await mgr.broadcast_event(exec_id, {"type": "event", "seq": 2}) + assert count == 1 + assert ws2.send_text.call_count == 2 + + # Disconnect ws2 + mgr.disconnect(ws2) + count = await mgr.broadcast_event(exec_id, {"type": "event", "seq": 3}) + assert count == 0 + + +# --------------------------------------------------------------------------- +# 7. ExecutionRunner message mapping +# --------------------------------------------------------------------------- + + +def test_runner_message_mapping_pipeline(): + """Verify CLIMessage → event_type + payload mapping for all message types.""" + test_cases = [ + (CLIMessage(type="text", content="hello"), "assistant_text", {"content": "hello"}), + (CLIMessage(type="thinking", content="hmm"), "thinking", {"content": "hmm"}), + ( + CLIMessage(type="tool_use", tool="Bash", call_id="c1", input={"command": "ls"}), + "tool_use_start", + {"tool": {"name": "Bash", "call_id": "c1", "input": {"command": "ls"}, "status": "running"}}, + ), + ( + CLIMessage(type="tool_result", tool="Bash", call_id="c1", output="file.txt"), + "tool_use_end", + {"call_id": "c1", "tool_name": "Bash", "output": "file.txt"}, + ), + (CLIMessage(type="error", content="OOM"), "error", {"message": "OOM"}), + (CLIMessage(type="artifact", content="data"), "artifact_created", {"artifact": {"content": "data"}}), + ] + + for msg, expected_type, expected_payload in test_cases: + assert ExecutionRunner._msg_to_event_type(msg) == expected_type + assert ExecutionRunner._msg_to_payload(msg) == expected_payload + + +# --------------------------------------------------------------------------- +# 8. Claude Code NDJSON parsing +# --------------------------------------------------------------------------- + + +def test_claude_code_ndjson_parsing(): + """Verify ClaudeCodeProvider parses a realistic NDJSON event stream.""" + provider = ClaudeCodeProvider() + + events = [ + { + "type": "assistant", + "message": { + "content": [ + {"type": "thinking", "thinking": "Let me look at the code"}, + {"type": "text", "text": "I'll fix the bug now"}, + {"type": "tool_use", "name": "Bash", "id": "t1", "input": {"command": "grep -r 'login' ."}}, + ] + }, + }, + { + "type": "tool_result", + "tool": "Bash", + "call_id": "t1", + "output": "auth/login.py:42: def login():", + }, + { + "type": "assistant", + "message": { + "content": [ + {"type": "text", "text": "Found it. Applying fix..."}, + ] + }, + }, + ] + + all_messages = [] + for event in events: + all_messages.extend(provider._parse_event(event)) + + assert len(all_messages) == 5 + assert all_messages[0].type == "thinking" + assert all_messages[1].type == "text" + assert all_messages[1].content == "I'll fix the bug now" + assert all_messages[2].type == "tool_use" + assert all_messages[2].tool == "Bash" + assert all_messages[3].type == "tool_result" + assert "auth/login.py" in all_messages[3].output + assert all_messages[4].type == "text" + + +# --------------------------------------------------------------------------- +# 9. Container lifecycle tracking +# --------------------------------------------------------------------------- + + +@pytest.mark.asyncio +async def test_container_lifecycle(): + """Create → use → remove container, verify tracking.""" + svc = FakeContainerService() + exec_id = uuid.uuid4() + + # Create + container = await svc.create_container(execution_id=exec_id) + assert len(svc.created) == 1 + + # Use (exec commands) + await svc.exec_in_container(container.container_id, ["echo", "hello"]) + assert len(svc.calls) == 1 + + # Remove + await svc.remove_container(container.container_id) + assert len(svc.removed) == 1 + assert svc.removed[0] == container.container_id + + +# --------------------------------------------------------------------------- +# 10. End-to-end data flow validation +# --------------------------------------------------------------------------- + + +def test_end_to_end_data_flow(): + """Validate the complete data flow from mission to execution result. + + This test verifies that data flows correctly through all layers: + Mission → prompt → execution events → reducer → final projection. + """ + # 1. Build prompt from mission + mission = MagicMock() + mission.title = "Add rate limiting" + mission.description = "Implement token bucket rate limiter for API endpoints." + mission.objective = "Prevent API abuse." + mission.tags = ["security", "api"] + + prompt = build_execution_prompt(mission) + assert "rate limiting" in prompt.lower() + + # 2. Initialize projection + proj = make_initial_projection( + {"source": "mission", "mission_id": "m-1"}, + "queued", + ) + + # 3. Simulate execution events + events = [ + ("execution_started", {"container_id": "ctr-1", "session_id": "s-1"}, "running"), + ("prompt_sent", {"message": {"role": "user", "content": prompt}}, "running"), + ( + "assistant_text", + {"message": {"role": "assistant", "content": "Implementing rate limiter", "id": "a1"}}, + "running", + ), + ( + "tool_use_start", + {"tool": {"name": "Write", "call_id": "t1", "input": {"file": "rate_limiter.py"}, "status": "running"}}, + "running", + ), + ("tool_use_end", {"call_id": "t1", "output": "File written"}, "running"), + ("execution_completed", {"result_summary": {"files_created": 1}}, "completed"), + ] + + for event_type, payload, status in events: + proj = apply_execution_event(proj, event_type=event_type, payload=payload, status=status) + + # 4. Verify final state + assert proj["status"] == "completed" + assert proj["container_id"] == "ctr-1" + assert proj["session_id"] == "s-1" + assert len(proj["messages"]) == 2 # user prompt + assistant text + assert len(proj["tool_calls"]) == 1 + assert proj["tool_calls"][0]["status"] == "completed" + assert proj["meta"]["completed"] is True + assert proj["meta"]["result_summary"]["files_created"] == 1 + + # 5. Verify immutability — original events didn't mutate + assert events[0][1]["container_id"] == "ctr-1" # unchanged diff --git a/backend/tests/test_core/test_mission_service.py b/backend/tests/test_core/test_mission_service.py new file mode 100644 index 000000000..29eeead82 --- /dev/null +++ b/backend/tests/test_core/test_mission_service.py @@ -0,0 +1,103 @@ +from __future__ import annotations + +import uuid +from unittest.mock import MagicMock + +from app.models.mission import Mission, MissionPriority, MissionStatus +from app.services.execution_lifecycle_service import build_execution_prompt + + +def _make_mission(**overrides) -> Mission: + """Create a Mission-like object for testing prompt building.""" + defaults = { + "id": uuid.uuid4(), + "workspace_id": uuid.uuid4(), + "creator_id": "user-1", + "title": "Fix login bug", + "description": None, + "objective": None, + "status": MissionStatus.TODO, + "priority": MissionPriority.MEDIUM, + "assignee_type": "agent", + "assignee_id": uuid.uuid4(), + "parent_mission_id": None, + "current_execution_id": None, + "due_date": None, + "position": 0.0, + "tags": None, + } + defaults.update(overrides) + mission = MagicMock(spec=Mission) + for k, v in defaults.items(): + setattr(mission, k, v) + return mission + + +def test_build_prompt_title_only(): + mission = _make_mission(title="Fix login bug") + prompt = build_execution_prompt(mission) + assert "# Mission: Fix login bug" in prompt + assert "## Description" not in prompt + assert "## Objective" not in prompt + + +def test_build_prompt_with_description(): + mission = _make_mission( + title="Add caching", + description="Implement Redis caching for the API layer.", + ) + prompt = build_execution_prompt(mission) + assert "# Mission: Add caching" in prompt + assert "## Description" in prompt + assert "Implement Redis caching" in prompt + + +def test_build_prompt_with_objective(): + mission = _make_mission( + title="Refactor auth", + objective="Reduce auth latency by 50%.", + ) + prompt = build_execution_prompt(mission) + assert "## Objective" in prompt + assert "Reduce auth latency" in prompt + + +def test_build_prompt_with_tags(): + mission = _make_mission( + title="Deploy v2", + tags=["backend", "infra", "urgent"], + ) + prompt = build_execution_prompt(mission) + assert "## Tags" in prompt + assert "backend" in prompt + assert "infra" in prompt + assert "urgent" in prompt + + +def test_build_prompt_full(): + mission = _make_mission( + title="Full mission", + description="Do everything.", + objective="Ship it.", + tags=["release"], + ) + prompt = build_execution_prompt(mission) + assert "# Mission: Full mission" in prompt + assert "## Description" in prompt + assert "Do everything." in prompt + assert "## Objective" in prompt + assert "Ship it." in prompt + assert "## Tags" in prompt + assert "release" in prompt + + +def test_build_prompt_empty_tags_not_shown(): + mission = _make_mission(title="No tags", tags=None) + prompt = build_execution_prompt(mission) + assert "## Tags" not in prompt + + +def test_build_prompt_empty_tags_list_not_shown(): + mission = _make_mission(title="Empty tags", tags=[]) + prompt = build_execution_prompt(mission) + assert "## Tags" not in prompt diff --git a/backend/tests/test_core/test_runner_callbacks.py b/backend/tests/test_core/test_runner_callbacks.py new file mode 100644 index 000000000..8d6bc91c4 --- /dev/null +++ b/backend/tests/test_core/test_runner_callbacks.py @@ -0,0 +1,53 @@ +from __future__ import annotations + +import uuid + +import pytest + +from app.core.agent.cli_backends.base import CLIResult +from app.core.agent.cli_backends.runner_callbacks import RunnerCallbacks +from app.models.execution import MissionExecutionStatus + + +class FakeCallbacks: + """Minimal implementation for testing the Protocol contract.""" + + def __init__(self): + self.finalized: list[tuple] = [] + self.failed: list[tuple] = [] + + async def on_execution_finalized(self, execution_id, status, result): + self.finalized.append((execution_id, status, result)) + + async def on_execution_failed(self, execution_id, error): + self.failed.append((execution_id, error)) + + +def test_fake_callbacks_satisfies_protocol(): + cb = FakeCallbacks() + assert isinstance(cb, RunnerCallbacks) + + +@pytest.mark.asyncio +async def test_on_execution_finalized_records_call(): + cb = FakeCallbacks() + eid = uuid.uuid4() + result = CLIResult(status="completed", output="done", error=None, session_id="s1") + await cb.on_execution_finalized(eid, MissionExecutionStatus.COMPLETED, result) + assert len(cb.finalized) == 1 + assert cb.finalized[0][0] == eid + + +@pytest.mark.asyncio +async def test_on_execution_failed_records_call(): + cb = FakeCallbacks() + eid = uuid.uuid4() + await cb.on_execution_failed(eid, "OOM killed") + assert len(cb.failed) == 1 + assert cb.failed[0] == (eid, "OOM killed") + + +def test_none_satisfies_optional_pattern(): + """Runner accepts callbacks=None for standalone executions.""" + cb = None + assert cb is None or isinstance(cb, RunnerCallbacks) diff --git a/backend/tests/test_core/test_session_registry.py b/backend/tests/test_core/test_session_registry.py new file mode 100644 index 000000000..a59fe7a26 --- /dev/null +++ b/backend/tests/test_core/test_session_registry.py @@ -0,0 +1,51 @@ +"""Tests for SessionRegistry.""" + +from __future__ import annotations + +import uuid +from unittest.mock import MagicMock + +from app.core.agent.cli_backends.session_registry import SessionRegistry + + +def _make_session() -> MagicMock: + """Return a lightweight stand-in for RuntimeSession (registry only checks identity).""" + return MagicMock() + + +def test_register_and_get(): + registry = SessionRegistry() + eid = uuid.uuid4() + session = _make_session() + registry.register(eid, session) + assert registry.get(eid) is session + + +def test_unregister(): + registry = SessionRegistry() + eid = uuid.uuid4() + session = _make_session() + registry.register(eid, session) + registry.unregister(eid) + assert registry.get(eid) is None + + +def test_get_nonexistent(): + registry = SessionRegistry() + assert registry.get(uuid.uuid4()) is None + + +def test_unregister_nonexistent_is_noop(): + registry = SessionRegistry() + # Should not raise + registry.unregister(uuid.uuid4()) + + +def test_register_overwrites(): + registry = SessionRegistry() + eid = uuid.uuid4() + session1 = _make_session() + session2 = _make_session() + registry.register(eid, session1) + registry.register(eid, session2) + assert registry.get(eid) is session2 diff --git a/backend/tests/test_models/__init__.py b/backend/tests/test_models/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/backend/tests/test_models/conftest.py b/backend/tests/test_models/conftest.py new file mode 100644 index 000000000..3f9c2c8fe --- /dev/null +++ b/backend/tests/test_models/conftest.py @@ -0,0 +1,3 @@ +import os + +os.environ.setdefault("SECRET_KEY", "test-secret-key-for-unit-tests") diff --git a/backend/tests/test_models/test_execution.py b/backend/tests/test_models/test_execution.py new file mode 100644 index 000000000..3e9902215 --- /dev/null +++ b/backend/tests/test_models/test_execution.py @@ -0,0 +1,29 @@ +import os +import uuid + +os.environ.setdefault("SECRET_KEY", "test-secret-key-for-unit-tests") + +from app.models.execution import Execution, ExecutionSource, MissionExecutionStatus + + +def test_execution_column_defaults(): + """Verify column default callables are wired to the expected enum values.""" + status_col = Execution.__table__.c.status + last_seq_col = Execution.__table__.c.last_seq + + assert status_col.default.arg == MissionExecutionStatus.QUEUED + assert last_seq_col.default.arg == 0 + + +def test_execution_explicit_values(): + e = Execution( + workspace_id=uuid.uuid4(), + user_id="user-1", + source=ExecutionSource.MISSION, + runtime_type="claude_code", + status=MissionExecutionStatus.RUNNING, + last_seq=42, + ) + assert e.status == MissionExecutionStatus.RUNNING + assert e.last_seq == 42 + assert e.source == ExecutionSource.MISSION diff --git a/backend/tests/test_models/test_mission.py b/backend/tests/test_models/test_mission.py new file mode 100644 index 000000000..b41e8f8f5 --- /dev/null +++ b/backend/tests/test_models/test_mission.py @@ -0,0 +1,32 @@ +import os +import uuid + +os.environ.setdefault("SECRET_KEY", "test-secret-key-for-unit-tests") + +from app.models.mission import Mission, MissionPriority, MissionStatus + + +def test_mission_column_defaults(): + """Verify column default callables are wired to the expected enum values.""" + status_col = Mission.__table__.c.status + priority_col = Mission.__table__.c.priority + position_col = Mission.__table__.c.position + + assert status_col.default.arg == MissionStatus.BACKLOG + assert priority_col.default.arg == MissionPriority.NONE + assert position_col.default.arg == 0.0 + + +def test_mission_explicit_values(): + m = Mission( + workspace_id=uuid.uuid4(), + title="Test APK audit", + creator_id="user-1", + status=MissionStatus.IN_PROGRESS, + priority=MissionPriority.HIGH, + position=1.5, + ) + assert m.status == MissionStatus.IN_PROGRESS + assert m.priority == MissionPriority.HIGH + assert m.position == 1.5 + assert m.title == "Test APK audit" diff --git a/backend/tests/test_services/test_execution_lifecycle_service.py b/backend/tests/test_services/test_execution_lifecycle_service.py new file mode 100644 index 000000000..f41627801 --- /dev/null +++ b/backend/tests/test_services/test_execution_lifecycle_service.py @@ -0,0 +1,14 @@ +# backend/tests/test_services/test_execution_lifecycle_service.py +from __future__ import annotations + +from app.core.agent.cli_backends.runner_callbacks import RunnerCallbacks +from app.services.execution_lifecycle_service import ExecutionLifecycleService + + +def test_lifecycle_service_satisfies_runner_callbacks_protocol(): + """ExecutionLifecycleService must implement RunnerCallbacks.""" + from unittest.mock import MagicMock + + db = MagicMock() + svc = ExecutionLifecycleService(db) + assert isinstance(svc, RunnerCallbacks) diff --git a/backend/uv.lock b/backend/uv.lock index 32f34e043..adac55613 100644 --- a/backend/uv.lock +++ b/backend/uv.lock @@ -1,29 +1,29 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.12, <3.14" [[package]] name = "aiofiles" version = "25.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/41/c3/534eac40372d8ee36ef40df62ec129bee4fdb5ad9706e58a29be53b2c970/aiofiles-25.1.0.tar.gz", hash = "sha256:a8d728f0a29de45dc521f18f07297428d56992a742f0cd2701ba86e44d23d5b2", size = 46354, upload-time = "2025-10-09T20:51:04.358Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/c3/534eac40372d8ee36ef40df62ec129bee4fdb5ad9706e58a29be53b2c970/aiofiles-25.1.0.tar.gz", hash = "sha256:a8d728f0a29de45dc521f18f07297428d56992a742f0cd2701ba86e44d23d5b2", size = 46354, upload-time = "2025-10-09T20:51:04.358Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bc/8a/340a1555ae33d7354dbca4faa54948d76d89a27ceef032c8c3bc661d003e/aiofiles-25.1.0-py3-none-any.whl", hash = "sha256:abe311e527c862958650f9438e859c1fa7568a141b22abcd015e120e86a85695", size = 14668, upload-time = "2025-10-09T20:51:03.174Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bc/8a/340a1555ae33d7354dbca4faa54948d76d89a27ceef032c8c3bc661d003e/aiofiles-25.1.0-py3-none-any.whl", hash = "sha256:abe311e527c862958650f9438e859c1fa7568a141b22abcd015e120e86a85695", size = 14668, upload-time = "2025-10-09T20:51:03.174Z" }, ] [[package]] name = "aiohappyeyeballs" version = "2.6.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, ] [[package]] name = "aiohttp" version = "3.13.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "aiohappyeyeballs" }, { name = "aiosignal" }, @@ -33,48 +33,48 @@ dependencies = [ { name = "propcache" }, { name = "yarl" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/ce/3b83ebba6b3207a7135e5fcaba49706f8a4b6008153b4e30540c982fae26/aiohttp-3.13.2.tar.gz", hash = "sha256:40176a52c186aefef6eb3cad2cdd30cd06e3afbe88fe8ab2af9c0b90f228daca", size = 7837994, upload-time = "2025-10-28T20:59:39.937Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/29/9b/01f00e9856d0a73260e86dd8ed0c2234a466c5c1712ce1c281548df39777/aiohttp-3.13.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b1e56bab2e12b2b9ed300218c351ee2a3d8c8fdab5b1ec6193e11a817767e47b", size = 737623, upload-time = "2025-10-28T20:56:30.797Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/1b/4be39c445e2b2bd0aab4ba736deb649fabf14f6757f405f0c9685019b9e9/aiohttp-3.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:364e25edaabd3d37b1db1f0cbcee8c73c9a3727bfa262b83e5e4cf3489a2a9dc", size = 492664, upload-time = "2025-10-28T20:56:32.708Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/28/66/d35dcfea8050e131cdd731dff36434390479b4045a8d0b9d7111b0a968f1/aiohttp-3.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c5c94825f744694c4b8db20b71dba9a257cd2ba8e010a803042123f3a25d50d7", size = 491808, upload-time = "2025-10-28T20:56:34.57Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/00/29/8e4609b93e10a853b65f8291e64985de66d4f5848c5637cddc70e98f01f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba2715d842ffa787be87cbfce150d5e88c87a98e0b62e0f5aa489169a393dbbb", size = 1738863, upload-time = "2025-10-28T20:56:36.377Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9d/fa/4ebdf4adcc0def75ced1a0d2d227577cd7b1b85beb7edad85fcc87693c75/aiohttp-3.13.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:585542825c4bc662221fb257889e011a5aa00f1ae4d75d1d246a5225289183e3", size = 1700586, upload-time = "2025-10-28T20:56:38.034Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/04/73f5f02ff348a3558763ff6abe99c223381b0bace05cd4530a0258e52597/aiohttp-3.13.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39d02cb6025fe1aabca329c5632f48c9532a3dabccd859e7e2f110668972331f", size = 1768625, upload-time = "2025-10-28T20:56:39.75Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f8/49/a825b79ffec124317265ca7d2344a86bcffeb960743487cb11988ffb3494/aiohttp-3.13.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e67446b19e014d37342f7195f592a2a948141d15a312fe0e700c2fd2f03124f6", size = 1867281, upload-time = "2025-10-28T20:56:41.471Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b9/48/adf56e05f81eac31edcfae45c90928f4ad50ef2e3ea72cb8376162a368f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4356474ad6333e41ccefd39eae869ba15a6c5299c9c01dfdcfdd5c107be4363e", size = 1752431, upload-time = "2025-10-28T20:56:43.162Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/30/ab/593855356eead019a74e862f21523db09c27f12fd24af72dbc3555b9bfd9/aiohttp-3.13.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeacf451c99b4525f700f078becff32c32ec327b10dcf31306a8a52d78166de7", size = 1562846, upload-time = "2025-10-28T20:56:44.85Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/39/0f/9f3d32271aa8dc35036e9668e31870a9d3b9542dd6b3e2c8a30931cb27ae/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8a9b889aeabd7a4e9af0b7f4ab5ad94d42e7ff679aaec6d0db21e3b639ad58d", size = 1699606, upload-time = "2025-10-28T20:56:46.519Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/3c/52d2658c5699b6ef7692a3f7128b2d2d4d9775f2a68093f74bca06cf01e1/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fa89cb11bc71a63b69568d5b8a25c3ca25b6d54c15f907ca1c130d72f320b76b", size = 1720663, upload-time = "2025-10-28T20:56:48.528Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9b/d4/8f8f3ff1fb7fb9e3f04fcad4e89d8a1cd8fc7d05de67e3de5b15b33008ff/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8aa7c807df234f693fed0ecd507192fc97692e61fee5702cdc11155d2e5cadc8", size = 1737939, upload-time = "2025-10-28T20:56:50.77Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/03/d3/ddd348f8a27a634daae39a1b8e291ff19c77867af438af844bf8b7e3231b/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9eb3e33fdbe43f88c3c75fa608c25e7c47bbd80f48d012763cb67c47f39a7e16", size = 1555132, upload-time = "2025-10-28T20:56:52.568Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/39/b8/46790692dc46218406f94374903ba47552f2f9f90dad554eed61bfb7b64c/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9434bc0d80076138ea986833156c5a48c9c7a8abb0c96039ddbb4afc93184169", size = 1764802, upload-time = "2025-10-28T20:56:54.292Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/e4/19ce547b58ab2a385e5f0b8aa3db38674785085abcf79b6e0edd1632b12f/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ff15c147b2ad66da1f2cbb0622313f2242d8e6e8f9b79b5206c84523a4473248", size = 1719512, upload-time = "2025-10-28T20:56:56.428Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/70/30/6355a737fed29dcb6dfdd48682d5790cb5eab050f7b4e01f49b121d3acad/aiohttp-3.13.2-cp312-cp312-win32.whl", hash = "sha256:27e569eb9d9e95dbd55c0fc3ec3a9335defbf1d8bc1d20171a49f3c4c607b93e", size = 426690, upload-time = "2025-10-28T20:56:58.736Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/0d/b10ac09069973d112de6ef980c1f6bb31cb7dcd0bc363acbdad58f927873/aiohttp-3.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:8709a0f05d59a71f33fd05c17fc11fcb8c30140506e13c2f5e8ee1b8964e1b45", size = 453465, upload-time = "2025-10-28T20:57:00.795Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bf/78/7e90ca79e5aa39f9694dcfd74f4720782d3c6828113bb1f3197f7e7c4a56/aiohttp-3.13.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7519bdc7dfc1940d201651b52bf5e03f5503bda45ad6eacf64dda98be5b2b6be", size = 732139, upload-time = "2025-10-28T20:57:02.455Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/db/ed/1f59215ab6853fbaa5c8495fa6cbc39edfc93553426152b75d82a5f32b76/aiohttp-3.13.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:088912a78b4d4f547a1f19c099d5a506df17eacec3c6f4375e2831ec1d995742", size = 490082, upload-time = "2025-10-28T20:57:04.784Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/68/7b/fe0fe0f5e05e13629d893c760465173a15ad0039c0a5b0d0040995c8075e/aiohttp-3.13.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5276807b9de9092af38ed23ce120539ab0ac955547b38563a9ba4f5b07b95293", size = 489035, upload-time = "2025-10-28T20:57:06.894Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/04/db5279e38471b7ac801d7d36a57d1230feeee130bbe2a74f72731b23c2b1/aiohttp-3.13.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1237c1375eaef0db4dcd7c2559f42e8af7b87ea7d295b118c60c36a6e61cb811", size = 1720387, upload-time = "2025-10-28T20:57:08.685Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/07/8ea4326bd7dae2bd59828f69d7fdc6e04523caa55e4a70f4a8725a7e4ed2/aiohttp-3.13.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:96581619c57419c3d7d78703d5b78c1e5e5fc0172d60f555bdebaced82ded19a", size = 1688314, upload-time = "2025-10-28T20:57:10.693Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/48/ab/3d98007b5b87ffd519d065225438cc3b668b2f245572a8cb53da5dd2b1bc/aiohttp-3.13.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2713a95b47374169409d18103366de1050fe0ea73db358fc7a7acb2880422d4", size = 1756317, upload-time = "2025-10-28T20:57:12.563Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/97/3d/801ca172b3d857fafb7b50c7c03f91b72b867a13abca982ed6b3081774ef/aiohttp-3.13.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:228a1cd556b3caca590e9511a89444925da87d35219a49ab5da0c36d2d943a6a", size = 1858539, upload-time = "2025-10-28T20:57:14.623Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f7/0d/4764669bdf47bd472899b3d3db91fffbe925c8e3038ec591a2fd2ad6a14d/aiohttp-3.13.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac6cde5fba8d7d8c6ac963dbb0256a9854e9fafff52fbcc58fdf819357892c3e", size = 1739597, upload-time = "2025-10-28T20:57:16.399Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/52/7bd3c6693da58ba16e657eb904a5b6decfc48ecd06e9ac098591653b1566/aiohttp-3.13.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2bef8237544f4e42878c61cef4e2839fee6346dc60f5739f876a9c50be7fcdb", size = 1555006, upload-time = "2025-10-28T20:57:18.288Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/48/30/9586667acec5993b6f41d2ebcf96e97a1255a85f62f3c653110a5de4d346/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:16f15a4eac3bc2d76c45f7ebdd48a65d41b242eb6c31c2245463b40b34584ded", size = 1683220, upload-time = "2025-10-28T20:57:20.241Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/01/3afe4c96854cfd7b30d78333852e8e851dceaec1c40fd00fec90c6402dd2/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:bb7fb776645af5cc58ab804c58d7eba545a97e047254a52ce89c157b5af6cd0b", size = 1712570, upload-time = "2025-10-28T20:57:22.253Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/11/2c/22799d8e720f4697a9e66fd9c02479e40a49de3de2f0bbe7f9f78a987808/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e1b4951125ec10c70802f2cb09736c895861cd39fd9dcb35107b4dc8ae6220b8", size = 1733407, upload-time = "2025-10-28T20:57:24.37Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/34/cb/90f15dd029f07cebbd91f8238a8b363978b530cd128488085b5703683594/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:550bf765101ae721ee1d37d8095f47b1f220650f85fe1af37a90ce75bab89d04", size = 1550093, upload-time = "2025-10-28T20:57:26.257Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/46/12dce9be9d3303ecbf4d30ad45a7683dc63d90733c2d9fe512be6716cd40/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fe91b87fc295973096251e2d25a811388e7d8adf3bd2b97ef6ae78bc4ac6c476", size = 1758084, upload-time = "2025-10-28T20:57:28.349Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/c8/0932b558da0c302ffd639fc6362a313b98fdf235dc417bc2493da8394df7/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0c8e31cfcc4592cb200160344b2fb6ae0f9e4effe06c644b5a125d4ae5ebe23", size = 1716987, upload-time = "2025-10-28T20:57:30.233Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5d/8b/f5bd1a75003daed099baec373aed678f2e9b34f2ad40d85baa1368556396/aiohttp-3.13.2-cp313-cp313-win32.whl", hash = "sha256:0740f31a60848d6edb296a0df827473eede90c689b8f9f2a4cdde74889eb2254", size = 425859, upload-time = "2025-10-28T20:57:32.105Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5d/28/a8a9fc6957b2cee8902414e41816b5ab5536ecf43c3b1843c10e82c559b2/aiohttp-3.13.2-cp313-cp313-win_amd64.whl", hash = "sha256:a88d13e7ca367394908f8a276b89d04a3652044612b9a408a0bb22a5ed976a1a", size = 452192, upload-time = "2025-10-28T20:57:34.166Z" }, +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/ce/3b83ebba6b3207a7135e5fcaba49706f8a4b6008153b4e30540c982fae26/aiohttp-3.13.2.tar.gz", hash = "sha256:40176a52c186aefef6eb3cad2cdd30cd06e3afbe88fe8ab2af9c0b90f228daca", size = 7837994, upload-time = "2025-10-28T20:59:39.937Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/29/9b/01f00e9856d0a73260e86dd8ed0c2234a466c5c1712ce1c281548df39777/aiohttp-3.13.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b1e56bab2e12b2b9ed300218c351ee2a3d8c8fdab5b1ec6193e11a817767e47b", size = 737623, upload-time = "2025-10-28T20:56:30.797Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/1b/4be39c445e2b2bd0aab4ba736deb649fabf14f6757f405f0c9685019b9e9/aiohttp-3.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:364e25edaabd3d37b1db1f0cbcee8c73c9a3727bfa262b83e5e4cf3489a2a9dc", size = 492664, upload-time = "2025-10-28T20:56:32.708Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/28/66/d35dcfea8050e131cdd731dff36434390479b4045a8d0b9d7111b0a968f1/aiohttp-3.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c5c94825f744694c4b8db20b71dba9a257cd2ba8e010a803042123f3a25d50d7", size = 491808, upload-time = "2025-10-28T20:56:34.57Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/00/29/8e4609b93e10a853b65f8291e64985de66d4f5848c5637cddc70e98f01f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba2715d842ffa787be87cbfce150d5e88c87a98e0b62e0f5aa489169a393dbbb", size = 1738863, upload-time = "2025-10-28T20:56:36.377Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/fa/4ebdf4adcc0def75ced1a0d2d227577cd7b1b85beb7edad85fcc87693c75/aiohttp-3.13.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:585542825c4bc662221fb257889e011a5aa00f1ae4d75d1d246a5225289183e3", size = 1700586, upload-time = "2025-10-28T20:56:38.034Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/04/73f5f02ff348a3558763ff6abe99c223381b0bace05cd4530a0258e52597/aiohttp-3.13.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39d02cb6025fe1aabca329c5632f48c9532a3dabccd859e7e2f110668972331f", size = 1768625, upload-time = "2025-10-28T20:56:39.75Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f8/49/a825b79ffec124317265ca7d2344a86bcffeb960743487cb11988ffb3494/aiohttp-3.13.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e67446b19e014d37342f7195f592a2a948141d15a312fe0e700c2fd2f03124f6", size = 1867281, upload-time = "2025-10-28T20:56:41.471Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/48/adf56e05f81eac31edcfae45c90928f4ad50ef2e3ea72cb8376162a368f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4356474ad6333e41ccefd39eae869ba15a6c5299c9c01dfdcfdd5c107be4363e", size = 1752431, upload-time = "2025-10-28T20:56:43.162Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/30/ab/593855356eead019a74e862f21523db09c27f12fd24af72dbc3555b9bfd9/aiohttp-3.13.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeacf451c99b4525f700f078becff32c32ec327b10dcf31306a8a52d78166de7", size = 1562846, upload-time = "2025-10-28T20:56:44.85Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/0f/9f3d32271aa8dc35036e9668e31870a9d3b9542dd6b3e2c8a30931cb27ae/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8a9b889aeabd7a4e9af0b7f4ab5ad94d42e7ff679aaec6d0db21e3b639ad58d", size = 1699606, upload-time = "2025-10-28T20:56:46.519Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/3c/52d2658c5699b6ef7692a3f7128b2d2d4d9775f2a68093f74bca06cf01e1/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fa89cb11bc71a63b69568d5b8a25c3ca25b6d54c15f907ca1c130d72f320b76b", size = 1720663, upload-time = "2025-10-28T20:56:48.528Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9b/d4/8f8f3ff1fb7fb9e3f04fcad4e89d8a1cd8fc7d05de67e3de5b15b33008ff/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8aa7c807df234f693fed0ecd507192fc97692e61fee5702cdc11155d2e5cadc8", size = 1737939, upload-time = "2025-10-28T20:56:50.77Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/03/d3/ddd348f8a27a634daae39a1b8e291ff19c77867af438af844bf8b7e3231b/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9eb3e33fdbe43f88c3c75fa608c25e7c47bbd80f48d012763cb67c47f39a7e16", size = 1555132, upload-time = "2025-10-28T20:56:52.568Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/b8/46790692dc46218406f94374903ba47552f2f9f90dad554eed61bfb7b64c/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9434bc0d80076138ea986833156c5a48c9c7a8abb0c96039ddbb4afc93184169", size = 1764802, upload-time = "2025-10-28T20:56:54.292Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/e4/19ce547b58ab2a385e5f0b8aa3db38674785085abcf79b6e0edd1632b12f/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ff15c147b2ad66da1f2cbb0622313f2242d8e6e8f9b79b5206c84523a4473248", size = 1719512, upload-time = "2025-10-28T20:56:56.428Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/70/30/6355a737fed29dcb6dfdd48682d5790cb5eab050f7b4e01f49b121d3acad/aiohttp-3.13.2-cp312-cp312-win32.whl", hash = "sha256:27e569eb9d9e95dbd55c0fc3ec3a9335defbf1d8bc1d20171a49f3c4c607b93e", size = 426690, upload-time = "2025-10-28T20:56:58.736Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/0d/b10ac09069973d112de6ef980c1f6bb31cb7dcd0bc363acbdad58f927873/aiohttp-3.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:8709a0f05d59a71f33fd05c17fc11fcb8c30140506e13c2f5e8ee1b8964e1b45", size = 453465, upload-time = "2025-10-28T20:57:00.795Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/78/7e90ca79e5aa39f9694dcfd74f4720782d3c6828113bb1f3197f7e7c4a56/aiohttp-3.13.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7519bdc7dfc1940d201651b52bf5e03f5503bda45ad6eacf64dda98be5b2b6be", size = 732139, upload-time = "2025-10-28T20:57:02.455Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/db/ed/1f59215ab6853fbaa5c8495fa6cbc39edfc93553426152b75d82a5f32b76/aiohttp-3.13.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:088912a78b4d4f547a1f19c099d5a506df17eacec3c6f4375e2831ec1d995742", size = 490082, upload-time = "2025-10-28T20:57:04.784Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/68/7b/fe0fe0f5e05e13629d893c760465173a15ad0039c0a5b0d0040995c8075e/aiohttp-3.13.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5276807b9de9092af38ed23ce120539ab0ac955547b38563a9ba4f5b07b95293", size = 489035, upload-time = "2025-10-28T20:57:06.894Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/04/db5279e38471b7ac801d7d36a57d1230feeee130bbe2a74f72731b23c2b1/aiohttp-3.13.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1237c1375eaef0db4dcd7c2559f42e8af7b87ea7d295b118c60c36a6e61cb811", size = 1720387, upload-time = "2025-10-28T20:57:08.685Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/07/8ea4326bd7dae2bd59828f69d7fdc6e04523caa55e4a70f4a8725a7e4ed2/aiohttp-3.13.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:96581619c57419c3d7d78703d5b78c1e5e5fc0172d60f555bdebaced82ded19a", size = 1688314, upload-time = "2025-10-28T20:57:10.693Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/48/ab/3d98007b5b87ffd519d065225438cc3b668b2f245572a8cb53da5dd2b1bc/aiohttp-3.13.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2713a95b47374169409d18103366de1050fe0ea73db358fc7a7acb2880422d4", size = 1756317, upload-time = "2025-10-28T20:57:12.563Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/3d/801ca172b3d857fafb7b50c7c03f91b72b867a13abca982ed6b3081774ef/aiohttp-3.13.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:228a1cd556b3caca590e9511a89444925da87d35219a49ab5da0c36d2d943a6a", size = 1858539, upload-time = "2025-10-28T20:57:14.623Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f7/0d/4764669bdf47bd472899b3d3db91fffbe925c8e3038ec591a2fd2ad6a14d/aiohttp-3.13.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac6cde5fba8d7d8c6ac963dbb0256a9854e9fafff52fbcc58fdf819357892c3e", size = 1739597, upload-time = "2025-10-28T20:57:16.399Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/52/7bd3c6693da58ba16e657eb904a5b6decfc48ecd06e9ac098591653b1566/aiohttp-3.13.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2bef8237544f4e42878c61cef4e2839fee6346dc60f5739f876a9c50be7fcdb", size = 1555006, upload-time = "2025-10-28T20:57:18.288Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/48/30/9586667acec5993b6f41d2ebcf96e97a1255a85f62f3c653110a5de4d346/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:16f15a4eac3bc2d76c45f7ebdd48a65d41b242eb6c31c2245463b40b34584ded", size = 1683220, upload-time = "2025-10-28T20:57:20.241Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/01/3afe4c96854cfd7b30d78333852e8e851dceaec1c40fd00fec90c6402dd2/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:bb7fb776645af5cc58ab804c58d7eba545a97e047254a52ce89c157b5af6cd0b", size = 1712570, upload-time = "2025-10-28T20:57:22.253Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/11/2c/22799d8e720f4697a9e66fd9c02479e40a49de3de2f0bbe7f9f78a987808/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e1b4951125ec10c70802f2cb09736c895861cd39fd9dcb35107b4dc8ae6220b8", size = 1733407, upload-time = "2025-10-28T20:57:24.37Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/34/cb/90f15dd029f07cebbd91f8238a8b363978b530cd128488085b5703683594/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:550bf765101ae721ee1d37d8095f47b1f220650f85fe1af37a90ce75bab89d04", size = 1550093, upload-time = "2025-10-28T20:57:26.257Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/46/12dce9be9d3303ecbf4d30ad45a7683dc63d90733c2d9fe512be6716cd40/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fe91b87fc295973096251e2d25a811388e7d8adf3bd2b97ef6ae78bc4ac6c476", size = 1758084, upload-time = "2025-10-28T20:57:28.349Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/c8/0932b558da0c302ffd639fc6362a313b98fdf235dc417bc2493da8394df7/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0c8e31cfcc4592cb200160344b2fb6ae0f9e4effe06c644b5a125d4ae5ebe23", size = 1716987, upload-time = "2025-10-28T20:57:30.233Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/8b/f5bd1a75003daed099baec373aed678f2e9b34f2ad40d85baa1368556396/aiohttp-3.13.2-cp313-cp313-win32.whl", hash = "sha256:0740f31a60848d6edb296a0df827473eede90c689b8f9f2a4cdde74889eb2254", size = 425859, upload-time = "2025-10-28T20:57:32.105Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/28/a8a9fc6957b2cee8902414e41816b5ab5536ecf43c3b1843c10e82c559b2/aiohttp-3.13.2-cp313-cp313-win_amd64.whl", hash = "sha256:a88d13e7ca367394908f8a276b89d04a3652044612b9a408a0bb22a5ed976a1a", size = 452192, upload-time = "2025-10-28T20:57:34.166Z" }, ] [[package]] name = "aioquic" version = "1.2.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "certifi" }, { name = "cryptography" }, @@ -82,57 +82,57 @@ dependencies = [ { name = "pyopenssl" }, { name = "service-identity" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4b/1a/bf10b2c57c06c7452b685368cb1ac90565a6e686e84ec6f84465fb8f78f4/aioquic-1.2.0.tar.gz", hash = "sha256:f91263bb3f71948c5c8915b4d50ee370004f20a416f67fab3dcc90556c7e7199", size = 179891, upload-time = "2024-07-06T23:27:09.301Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4b/1a/bf10b2c57c06c7452b685368cb1ac90565a6e686e84ec6f84465fb8f78f4/aioquic-1.2.0.tar.gz", hash = "sha256:f91263bb3f71948c5c8915b4d50ee370004f20a416f67fab3dcc90556c7e7199", size = 179891, upload-time = "2024-07-06T23:27:09.301Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/19/03/1c385739e504c70ab2a66a4bc0e7cd95cee084b374dcd4dc97896378400b/aioquic-1.2.0-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3e23964dfb04526ade6e66f5b7cd0c830421b8138303ab60ba6e204015e7cb0b", size = 1753473, upload-time = "2024-07-06T23:26:20.809Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/1f/4d1c40714db65be828e1a1e2cce7f8f4b252be67d89f2942f86a1951826c/aioquic-1.2.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:84d733332927b76218a3b246216104116f766f5a9b2308ec306cd017b3049660", size = 2083563, upload-time = "2024-07-06T23:26:24.254Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/15/48/56a8c9083d1deea4ccaf1cbf5a91a396b838b4a0f8650f4e9f45c7879a38/aioquic-1.2.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2466499759b31ea4f1d17f4aeb1f8d4297169e05e3c1216d618c9757f4dd740d", size = 2555697, upload-time = "2024-07-06T23:26:26.16Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/93/fa4c981a8a8a903648d4cd6e12c0fca7f44e3ef4ba15a8b99a26af05b868/aioquic-1.2.0-cp38-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd75015462ca5070a888110dc201f35a9f4c7459f9201b77adc3c06013611bb8", size = 2149089, upload-time = "2024-07-06T23:26:28.277Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b0/0f/4a280923313b831892caaa45348abea89e7dd2e4422a86699bb0e506b1dd/aioquic-1.2.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43ae3b11d43400a620ca0b4b4885d12b76a599c2cbddba755f74bebfa65fe587", size = 2205221, upload-time = "2024-07-06T23:26:30.682Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/6b/a6a1d1762ce06f13b68f524bb9c5f4d6ca7cda9b072d7e744626b89b77be/aioquic-1.2.0-cp38-abi3-win32.whl", hash = "sha256:910d8c91da86bba003d491d15deaeac3087d1b9d690b9edc1375905d8867b742", size = 1214037, upload-time = "2024-07-06T23:26:32.651Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dd/aa/e8a8a75c93dee0ab229df3c2d17f63cd44d0ad5ee8540e2ec42779ce3a39/aioquic-1.2.0-cp38-abi3-win_amd64.whl", hash = "sha256:e3dcfb941004333d477225a6689b55fc7f905af5ee6a556eb5083be0354e653a", size = 1530339, upload-time = "2024-07-06T23:26:34.753Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/03/1c385739e504c70ab2a66a4bc0e7cd95cee084b374dcd4dc97896378400b/aioquic-1.2.0-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3e23964dfb04526ade6e66f5b7cd0c830421b8138303ab60ba6e204015e7cb0b", size = 1753473, upload-time = "2024-07-06T23:26:20.809Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/1f/4d1c40714db65be828e1a1e2cce7f8f4b252be67d89f2942f86a1951826c/aioquic-1.2.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:84d733332927b76218a3b246216104116f766f5a9b2308ec306cd017b3049660", size = 2083563, upload-time = "2024-07-06T23:26:24.254Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/15/48/56a8c9083d1deea4ccaf1cbf5a91a396b838b4a0f8650f4e9f45c7879a38/aioquic-1.2.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2466499759b31ea4f1d17f4aeb1f8d4297169e05e3c1216d618c9757f4dd740d", size = 2555697, upload-time = "2024-07-06T23:26:26.16Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0f/93/fa4c981a8a8a903648d4cd6e12c0fca7f44e3ef4ba15a8b99a26af05b868/aioquic-1.2.0-cp38-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd75015462ca5070a888110dc201f35a9f4c7459f9201b77adc3c06013611bb8", size = 2149089, upload-time = "2024-07-06T23:26:28.277Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b0/0f/4a280923313b831892caaa45348abea89e7dd2e4422a86699bb0e506b1dd/aioquic-1.2.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43ae3b11d43400a620ca0b4b4885d12b76a599c2cbddba755f74bebfa65fe587", size = 2205221, upload-time = "2024-07-06T23:26:30.682Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/6b/a6a1d1762ce06f13b68f524bb9c5f4d6ca7cda9b072d7e744626b89b77be/aioquic-1.2.0-cp38-abi3-win32.whl", hash = "sha256:910d8c91da86bba003d491d15deaeac3087d1b9d690b9edc1375905d8867b742", size = 1214037, upload-time = "2024-07-06T23:26:32.651Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dd/aa/e8a8a75c93dee0ab229df3c2d17f63cd44d0ad5ee8540e2ec42779ce3a39/aioquic-1.2.0-cp38-abi3-win_amd64.whl", hash = "sha256:e3dcfb941004333d477225a6689b55fc7f905af5ee6a556eb5083be0354e653a", size = 1530339, upload-time = "2024-07-06T23:26:34.753Z" }, ] [[package]] name = "aiosignal" version = "1.4.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "frozenlist" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, ] [[package]] name = "aiosmtplib" version = "5.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a2/15/c2dc93a58d716bce64b53918d3cf667d86c96a56a9f3a239a9f104643637/aiosmtplib-5.0.0.tar.gz", hash = "sha256:514ac11c31cb767c764077eb3c2eb2ae48df6f63f1e847aeb36119c4fc42b52d", size = 61057, upload-time = "2025-10-19T19:12:31.426Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/15/c2dc93a58d716bce64b53918d3cf667d86c96a56a9f3a239a9f104643637/aiosmtplib-5.0.0.tar.gz", hash = "sha256:514ac11c31cb767c764077eb3c2eb2ae48df6f63f1e847aeb36119c4fc42b52d", size = 61057, upload-time = "2025-10-19T19:12:31.426Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/99/42/b997c306dc54e6ac62a251787f6b5ec730797eea08e0336d8f0d7b899d5f/aiosmtplib-5.0.0-py3-none-any.whl", hash = "sha256:95eb0f81189780845363ab0627e7f130bca2d0060d46cd3eeb459f066eb7df32", size = 27048, upload-time = "2025-10-19T19:12:30.124Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/42/b997c306dc54e6ac62a251787f6b5ec730797eea08e0336d8f0d7b899d5f/aiosmtplib-5.0.0-py3-none-any.whl", hash = "sha256:95eb0f81189780845363ab0627e7f130bca2d0060d46cd3eeb459f066eb7df32", size = 27048, upload-time = "2025-10-19T19:12:30.124Z" }, ] [[package]] name = "alembic" version = "1.17.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "mako" }, { name = "sqlalchemy" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/a6/74c8cadc2882977d80ad756a13857857dbcf9bd405bc80b662eb10651282/alembic-1.17.2.tar.gz", hash = "sha256:bbe9751705c5e0f14877f02d46c53d10885e377e3d90eda810a016f9baa19e8e", size = 1988064, upload-time = "2025-11-14T20:35:04.057Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/a6/74c8cadc2882977d80ad756a13857857dbcf9bd405bc80b662eb10651282/alembic-1.17.2.tar.gz", hash = "sha256:bbe9751705c5e0f14877f02d46c53d10885e377e3d90eda810a016f9baa19e8e", size = 1988064, upload-time = "2025-11-14T20:35:04.057Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl", hash = "sha256:f483dd1fe93f6c5d49217055e4d15b905b425b6af906746abb35b69c1996c4e6", size = 248554, upload-time = "2025-11-14T20:35:05.699Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/88/6237e97e3385b57b5f1528647addea5cc03d4d65d5979ab24327d41fb00d/alembic-1.17.2-py3-none-any.whl", hash = "sha256:f483dd1fe93f6c5d49217055e4d15b905b425b6af906746abb35b69c1996c4e6", size = 248554, upload-time = "2025-11-14T20:35:05.699Z" }, ] [[package]] name = "angr" version = "9.2.191" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "archinfo" }, { name = "cachetools" }, @@ -159,46 +159,37 @@ dependencies = [ { name = "typing-extensions" }, { name = "unique-log-filter" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/72/bd/9ed2df50022dd815386d150b1ae2a35279bd445aa56c79768fc1c0f84872/angr-9.2.191.tar.gz", hash = "sha256:64105292abbfe39bec53f3165231e955d84e19fad48d1aec45c0d0194786469a", size = 3353580, upload-time = "2025-12-30T17:44:24.144Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/bd/9ed2df50022dd815386d150b1ae2a35279bd445aa56c79768fc1c0f84872/angr-9.2.191.tar.gz", hash = "sha256:64105292abbfe39bec53f3165231e955d84e19fad48d1aec45c0d0194786469a", size = 3353580, upload-time = "2025-12-30T17:44:24.144Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ab/70/a06ce0887923c1bc2461f6840bbb4a571ac3f9297d45f622a0cf45d39a4c/angr-9.2.191-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e4df766688bbdacdd053ccae6faf577033af750e4b5b5027f8a90bb08310a084", size = 5989071, upload-time = "2025-12-30T17:42:57.589Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6b/56/17cd22f6bc110b125c0e4bbc7cd04b0bafa607de2a49883bf34233814d51/angr-9.2.191-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:362b8f76c3f7bcd09b0359132065f469af78123c8c92b5866a3db3446dabc707", size = 5819341, upload-time = "2025-12-30T17:42:59.391Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/66/b3/7c5f2cc85eb05b862035d8edb6426acd1fb8426f0b4c7e5793c924e0e669/angr-9.2.191-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03d21f0e5f25629eae63910a62029d9075165f3b4ae46cda459d245aa12e6e30", size = 6185672, upload-time = "2025-12-30T17:43:01.386Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/23/bf/0a2fffced77260ca321af7509fc8379c239c8a621c1bcd21a26a67cdf183/angr-9.2.191-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3ff7b42213650cc4d81a15c435279bfbf7276ada401c1c1056e3fe602d629f27", size = 6011388, upload-time = "2025-12-30T17:43:03.27Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/44/e0/8af0259222bd4d545867991be8ba4a3d4f00ab942bb5687494b29e4db247/angr-9.2.191-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:dee437c32cdd8bac3f34f71afa97c5b7b36d92dd4757a342b6569fa0555bbe6b", size = 6992468, upload-time = "2025-12-30T17:43:05.146Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/17/ba/7be963318e037f32572fcd33ed9b1cbe504c6bdb0b10e7e8ae983f2b4ec2/angr-9.2.191-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ec21fe4de896cca191e083b40c442ebe96075b24e0eaf58a1d53d8b1a5e8021f", size = 7177599, upload-time = "2025-12-30T17:43:07.11Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5f/79/324dc9e2d27b37c54cbff7fd671d33e1b0803fbe78ae1907849bd05a8aa7/angr-9.2.191-cp312-cp312-win_amd64.whl", hash = "sha256:81aa44fd30ccc8f00a20c1f8d695236372ac8c5a1dd5b745653f0909f8a345bc", size = 5789378, upload-time = "2025-12-30T17:43:08.57Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/74/fa/baabac8ada517e16fa70e7384e6d99cbfb5919cf3dca7c109d98d0a4f090/angr-9.2.191-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3c2ccc3ea148851c18eda4546dada965abea40bd703a9a68fae4002808d81f0a", size = 5989143, upload-time = "2025-12-30T17:43:10.235Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6b/1f/00ec8f2ebb6b2134ef697bf63c5488657922a395e0dff49553d530dbce3b/angr-9.2.191-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:07d01dff30f0f9bd7cfc55e8460ec7936e977b7f01e567aae69f3c82842074ec", size = 5819108, upload-time = "2025-12-30T17:43:11.707Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/63/49/f5ad08fb8b203f9185c5b65572510aacb133ae38f4ff56cfa45f43ada3b1/angr-9.2.191-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d91335e18c9d873a7334195b32cfd08cbc3a089d1f5b38ee3ba0f19bf3c29f11", size = 6185183, upload-time = "2025-12-30T17:43:13.24Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/84/cb/eb474e665a74a38c0769cd5028ec6ce555655fdbd239f67e12ed6cf5f61d/angr-9.2.191-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c27e349e6f2cb521264f5e7bc9e01ac7a2e313b2ee0174c5fc8f0af3ffd88e70", size = 6011554, upload-time = "2025-12-30T17:43:15.085Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/39/da/a5102669a633ded0951ef38a9571e4758c468d36d615fbb8566327d29e65/angr-9.2.191-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:322732ede7c289f656fb5d69282b37f3aead8e91b326e9aabe0f1f7acddf1e15", size = 6991995, upload-time = "2025-12-30T17:43:17.013Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/4f/9ff9737f70cb386acfd3a7876c3b3b9c7a74bbe581dfc9e301fb5070f06c/angr-9.2.191-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26c4c8af3ee5a9bf59a8e498891c234b04e0627b7723be39c8e3dcf6d829adb4", size = 7177527, upload-time = "2025-12-30T17:43:18.966Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/55/de/2b8e0ad0511eaae3dfcd16bcdff7a644f41a3fbdf3ce913ec2193cc691b3/angr-9.2.191-cp313-cp313-win_amd64.whl", hash = "sha256:e590eace461015f01c063dbaa3d780e979a3c47ca1077d7b8b5fd57802466ec6", size = 5789129, upload-time = "2025-12-30T17:43:20.766Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6b/56/17cd22f6bc110b125c0e4bbc7cd04b0bafa607de2a49883bf34233814d51/angr-9.2.191-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:362b8f76c3f7bcd09b0359132065f469af78123c8c92b5866a3db3446dabc707", size = 5819341, upload-time = "2025-12-30T17:42:59.391Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/b3/7c5f2cc85eb05b862035d8edb6426acd1fb8426f0b4c7e5793c924e0e669/angr-9.2.191-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03d21f0e5f25629eae63910a62029d9075165f3b4ae46cda459d245aa12e6e30", size = 6185672, upload-time = "2025-12-30T17:43:01.386Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/23/bf/0a2fffced77260ca321af7509fc8379c239c8a621c1bcd21a26a67cdf183/angr-9.2.191-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3ff7b42213650cc4d81a15c435279bfbf7276ada401c1c1056e3fe602d629f27", size = 6011388, upload-time = "2025-12-30T17:43:03.27Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/44/e0/8af0259222bd4d545867991be8ba4a3d4f00ab942bb5687494b29e4db247/angr-9.2.191-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:dee437c32cdd8bac3f34f71afa97c5b7b36d92dd4757a342b6569fa0555bbe6b", size = 6992468, upload-time = "2025-12-30T17:43:05.146Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/79/324dc9e2d27b37c54cbff7fd671d33e1b0803fbe78ae1907849bd05a8aa7/angr-9.2.191-cp312-cp312-win_amd64.whl", hash = "sha256:81aa44fd30ccc8f00a20c1f8d695236372ac8c5a1dd5b745653f0909f8a345bc", size = 5789378, upload-time = "2025-12-30T17:43:08.57Z" }, ] [[package]] name = "annotated-doc" version = "0.0.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, ] [[package]] name = "annotated-types" version = "0.7.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/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" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/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 = "anthropic" version = "0.79.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -209,471 +200,471 @@ dependencies = [ { name = "sniffio" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/15/b1/91aea3f8fd180d01d133d931a167a78a3737b3fd39ccef2ae8d6619c24fd/anthropic-0.79.0.tar.gz", hash = "sha256:8707aafb3b1176ed6c13e2b1c9fb3efddce90d17aee5d8b83a86c70dcdcca871", size = 509825, upload-time = "2026-02-07T18:06:18.388Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/15/b1/91aea3f8fd180d01d133d931a167a78a3737b3fd39ccef2ae8d6619c24fd/anthropic-0.79.0.tar.gz", hash = "sha256:8707aafb3b1176ed6c13e2b1c9fb3efddce90d17aee5d8b83a86c70dcdcca871", size = 509825, upload-time = "2026-02-07T18:06:18.388Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/b2/cc0b8e874a18d7da50b0fda8c99e4ac123f23bf47b471827c5f6f3e4a767/anthropic-0.79.0-py3-none-any.whl", hash = "sha256:04cbd473b6bbda4ca2e41dd670fe2f829a911530f01697d0a1e37321eb75f3cf", size = 405918, upload-time = "2026-02-07T18:06:20.246Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/b2/cc0b8e874a18d7da50b0fda8c99e4ac123f23bf47b471827c5f6f3e4a767/anthropic-0.79.0-py3-none-any.whl", hash = "sha256:04cbd473b6bbda4ca2e41dd670fe2f829a911530f01697d0a1e37321eb75f3cf", size = 405918, upload-time = "2026-02-07T18:06:20.246Z" }, ] [[package]] name = "anyio" version = "4.12.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "idna" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/16/ce/8a777047513153587e5434fd752e89334ac33e379aa3497db860eeb60377/anyio-4.12.0.tar.gz", hash = "sha256:73c693b567b0c55130c104d0b43a9baf3aa6a31fc6110116509f27bf75e21ec0", size = 228266, upload-time = "2025-11-28T23:37:38.911Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/16/ce/8a777047513153587e5434fd752e89334ac33e379aa3497db860eeb60377/anyio-4.12.0.tar.gz", hash = "sha256:73c693b567b0c55130c104d0b43a9baf3aa6a31fc6110116509f27bf75e21ec0", size = 228266, upload-time = "2025-11-28T23:37:38.911Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/9c/36c5c37947ebfb8c7f22e0eb6e4d188ee2d53aa3880f3f2744fb894f0cb1/anyio-4.12.0-py3-none-any.whl", hash = "sha256:dad2376a628f98eeca4881fc56cd06affd18f659b17a747d3ff0307ced94b1bb", size = 113362, upload-time = "2025-11-28T23:36:57.897Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/9c/36c5c37947ebfb8c7f22e0eb6e4d188ee2d53aa3880f3f2744fb894f0cb1/anyio-4.12.0-py3-none-any.whl", hash = "sha256:dad2376a628f98eeca4881fc56cd06affd18f659b17a747d3ff0307ced94b1bb", size = 113362, upload-time = "2025-11-28T23:36:57.897Z" }, ] [[package]] name = "archinfo" version = "9.2.191" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/a4/51fa73732b12b5ca88876fd5eeb9bdad95b1bc6d6047f45c2b2a22c46acd/archinfo-9.2.191.tar.gz", hash = "sha256:926d7cd036deb7630250fdaa6ba1b151b9ca18b08ac15b35e9429b7fe13b9eee", size = 39899, upload-time = "2025-12-30T17:44:27.16Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/a4/51fa73732b12b5ca88876fd5eeb9bdad95b1bc6d6047f45c2b2a22c46acd/archinfo-9.2.191.tar.gz", hash = "sha256:926d7cd036deb7630250fdaa6ba1b151b9ca18b08ac15b35e9429b7fe13b9eee", size = 39899, upload-time = "2025-12-30T17:44:27.16Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/70/0a/03817b0729c458986fd92566fa9200a8376e4c6e460845652f8f1e1cc312/archinfo-9.2.191-py3-none-any.whl", hash = "sha256:7e11a73f0f39b94db4e6ad35dedfc4e7c1b51f12accc88cd82b9acf1f0c05044", size = 48977, upload-time = "2025-12-30T17:43:29.367Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/70/0a/03817b0729c458986fd92566fa9200a8376e4c6e460845652f8f1e1cc312/archinfo-9.2.191-py3-none-any.whl", hash = "sha256:7e11a73f0f39b94db4e6ad35dedfc4e7c1b51f12accc88cd82b9acf1f0c05044", size = 48977, upload-time = "2025-12-30T17:43:29.367Z" }, ] [[package]] name = "argon2-cffi" version = "23.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "argon2-cffi-bindings" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/fa/57ec2c6d16ecd2ba0cf15f3c7d1c3c2e7b5fcb83555ff56d7ab10888ec8f/argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08", size = 42798, upload-time = "2023-08-15T14:13:12.711Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/fa/57ec2c6d16ecd2ba0cf15f3c7d1c3c2e7b5fcb83555ff56d7ab10888ec8f/argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08", size = 42798, upload-time = "2023-08-15T14:13:12.711Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a4/6a/e8a041599e78b6b3752da48000b14c8d1e8a04ded09c88c714ba047f34f5/argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea", size = 15124, upload-time = "2023-08-15T14:13:10.752Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a4/6a/e8a041599e78b6b3752da48000b14c8d1e8a04ded09c88c714ba047f34f5/argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea", size = 15124, upload-time = "2023-08-15T14:13:10.752Z" }, ] [[package]] name = "argon2-cffi-bindings" version = "25.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cffi" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, ] [[package]] name = "arpy" version = "1.1.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/15/09fbfc0d43b66a3845098377249539aa44edcd541e17eabe2e11b4e3855e/arpy-1.1.1.tar.gz", hash = "sha256:3ec36309d2234648ef8dcd2118fe7d81c30195087e0353473546583f3434e776", size = 6774, upload-time = "2013-06-30T21:31:27.411Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/15/09fbfc0d43b66a3845098377249539aa44edcd541e17eabe2e11b4e3855e/arpy-1.1.1.tar.gz", hash = "sha256:3ec36309d2234648ef8dcd2118fe7d81c30195087e0353473546583f3434e776", size = 6774, upload-time = "2013-06-30T21:31:27.411Z" } [[package]] name = "asgiref" version = "3.8.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/29/38/b3395cc9ad1b56d2ddac9970bc8f4141312dbaec28bc7c218b0dfafd0f42/asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590", size = 35186, upload-time = "2024-03-22T14:39:36.863Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/29/38/b3395cc9ad1b56d2ddac9970bc8f4141312dbaec28bc7c218b0dfafd0f42/asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590", size = 35186, upload-time = "2024-03-22T14:39:36.863Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828, upload-time = "2024-03-22T14:39:34.521Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828, upload-time = "2024-03-22T14:39:34.521Z" }, ] [[package]] name = "asyncpg" version = "0.31.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fe/cc/d18065ce2380d80b1bcce927c24a2642efd38918e33fd724bc4bca904877/asyncpg-0.31.0.tar.gz", hash = "sha256:c989386c83940bfbd787180f2b1519415e2d3d6277a70d9d0f0145ac73500735", size = 993667, upload-time = "2025-11-24T23:27:00.812Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2a/a6/59d0a146e61d20e18db7396583242e32e0f120693b67a8de43f1557033e2/asyncpg-0.31.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b44c31e1efc1c15188ef183f287c728e2046abb1d26af4d20858215d50d91fad", size = 662042, upload-time = "2025-11-24T23:25:49.578Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/36/01/ffaa189dcb63a2471720615e60185c3f6327716fdc0fc04334436fbb7c65/asyncpg-0.31.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0c89ccf741c067614c9b5fc7f1fc6f3b61ab05ae4aaa966e6fd6b93097c7d20d", size = 638504, upload-time = "2025-11-24T23:25:51.501Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/62/3f699ba45d8bd24c5d65392190d19656d74ff0185f42e19d0bbd973bb371/asyncpg-0.31.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:12b3b2e39dc5470abd5e98c8d3373e4b1d1234d9fbdedf538798b2c13c64460a", size = 3426241, upload-time = "2025-11-24T23:25:53.278Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8c/d1/a867c2150f9c6e7af6462637f613ba67f78a314b00db220cd26ff559d532/asyncpg-0.31.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:aad7a33913fb8bcb5454313377cc330fbb19a0cd5faa7272407d8a0c4257b671", size = 3520321, upload-time = "2025-11-24T23:25:54.982Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7a/1a/cce4c3f246805ecd285a3591222a2611141f1669d002163abef999b60f98/asyncpg-0.31.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3df118d94f46d85b2e434fd62c84cb66d5834d5a890725fe625f498e72e4d5ec", size = 3316685, upload-time = "2025-11-24T23:25:57.43Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/40/ae/0fc961179e78cc579e138fad6eb580448ecae64908f95b8cb8ee2f241f67/asyncpg-0.31.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd5b6efff3c17c3202d4b37189969acf8927438a238c6257f66be3c426beba20", size = 3471858, upload-time = "2025-11-24T23:25:59.636Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/52/b2/b20e09670be031afa4cbfabd645caece7f85ec62d69c312239de568e058e/asyncpg-0.31.0-cp312-cp312-win32.whl", hash = "sha256:027eaa61361ec735926566f995d959ade4796f6a49d3bde17e5134b9964f9ba8", size = 527852, upload-time = "2025-11-24T23:26:01.084Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b5/f0/f2ed1de154e15b107dc692262395b3c17fc34eafe2a78fc2115931561730/asyncpg-0.31.0-cp312-cp312-win_amd64.whl", hash = "sha256:72d6bdcbc93d608a1158f17932de2321f68b1a967a13e014998db87a72ed3186", size = 597175, upload-time = "2025-11-24T23:26:02.564Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/11/97b5c2af72a5d0b9bc3fa30cd4b9ce22284a9a943a150fdc768763caf035/asyncpg-0.31.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c204fab1b91e08b0f47e90a75d1b3c62174dab21f670ad6c5d0f243a228f015b", size = 661111, upload-time = "2025-11-24T23:26:04.467Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1b/71/157d611c791a5e2d0423f09f027bd499935f0906e0c2a416ce712ba51ef3/asyncpg-0.31.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:54a64f91839ba59008eccf7aad2e93d6e3de688d796f35803235ea1c4898ae1e", size = 636928, upload-time = "2025-11-24T23:26:05.944Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2e/fc/9e3486fb2bbe69d4a867c0b76d68542650a7ff1574ca40e84c3111bb0c6e/asyncpg-0.31.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0e0822b1038dc7253b337b0f3f676cadc4ac31b126c5d42691c39691962e403", size = 3424067, upload-time = "2025-11-24T23:26:07.957Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/12/c6/8c9d076f73f07f995013c791e018a1cd5f31823c2a3187fc8581706aa00f/asyncpg-0.31.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bef056aa502ee34204c161c72ca1f3c274917596877f825968368b2c33f585f4", size = 3518156, upload-time = "2025-11-24T23:26:09.591Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ae/3b/60683a0baf50fbc546499cfb53132cb6835b92b529a05f6a81471ab60d0c/asyncpg-0.31.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0bfbcc5b7ffcd9b75ab1558f00db2ae07db9c80637ad1b2469c43df79d7a5ae2", size = 3319636, upload-time = "2025-11-24T23:26:11.168Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/dc/8487df0f69bd398a61e1792b3cba0e47477f214eff085ba0efa7eac9ce87/asyncpg-0.31.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:22bc525ebbdc24d1261ecbf6f504998244d4e3be1721784b5f64664d61fbe602", size = 3472079, upload-time = "2025-11-24T23:26:13.164Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/13/a1/c5bbeeb8531c05c89135cb8b28575ac2fac618bcb60119ee9696c3faf71c/asyncpg-0.31.0-cp313-cp313-win32.whl", hash = "sha256:f890de5e1e4f7e14023619399a471ce4b71f5418cd67a51853b9910fdfa73696", size = 527606, upload-time = "2025-11-24T23:26:14.78Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/91/66/b25ccb84a246b470eb943b0107c07edcae51804912b824054b3413995a10/asyncpg-0.31.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc5f2fa9916f292e5c5c8b2ac2813763bcd7f58e130055b4ad8a0531314201ab", size = 596569, upload-time = "2025-11-24T23:26:16.189Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fe/cc/d18065ce2380d80b1bcce927c24a2642efd38918e33fd724bc4bca904877/asyncpg-0.31.0.tar.gz", hash = "sha256:c989386c83940bfbd787180f2b1519415e2d3d6277a70d9d0f0145ac73500735", size = 993667, upload-time = "2025-11-24T23:27:00.812Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/a6/59d0a146e61d20e18db7396583242e32e0f120693b67a8de43f1557033e2/asyncpg-0.31.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b44c31e1efc1c15188ef183f287c728e2046abb1d26af4d20858215d50d91fad", size = 662042, upload-time = "2025-11-24T23:25:49.578Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/36/01/ffaa189dcb63a2471720615e60185c3f6327716fdc0fc04334436fbb7c65/asyncpg-0.31.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0c89ccf741c067614c9b5fc7f1fc6f3b61ab05ae4aaa966e6fd6b93097c7d20d", size = 638504, upload-time = "2025-11-24T23:25:51.501Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/62/3f699ba45d8bd24c5d65392190d19656d74ff0185f42e19d0bbd973bb371/asyncpg-0.31.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:12b3b2e39dc5470abd5e98c8d3373e4b1d1234d9fbdedf538798b2c13c64460a", size = 3426241, upload-time = "2025-11-24T23:25:53.278Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8c/d1/a867c2150f9c6e7af6462637f613ba67f78a314b00db220cd26ff559d532/asyncpg-0.31.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:aad7a33913fb8bcb5454313377cc330fbb19a0cd5faa7272407d8a0c4257b671", size = 3520321, upload-time = "2025-11-24T23:25:54.982Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7a/1a/cce4c3f246805ecd285a3591222a2611141f1669d002163abef999b60f98/asyncpg-0.31.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3df118d94f46d85b2e434fd62c84cb66d5834d5a890725fe625f498e72e4d5ec", size = 3316685, upload-time = "2025-11-24T23:25:57.43Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/40/ae/0fc961179e78cc579e138fad6eb580448ecae64908f95b8cb8ee2f241f67/asyncpg-0.31.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd5b6efff3c17c3202d4b37189969acf8927438a238c6257f66be3c426beba20", size = 3471858, upload-time = "2025-11-24T23:25:59.636Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/52/b2/b20e09670be031afa4cbfabd645caece7f85ec62d69c312239de568e058e/asyncpg-0.31.0-cp312-cp312-win32.whl", hash = "sha256:027eaa61361ec735926566f995d959ade4796f6a49d3bde17e5134b9964f9ba8", size = 527852, upload-time = "2025-11-24T23:26:01.084Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b5/f0/f2ed1de154e15b107dc692262395b3c17fc34eafe2a78fc2115931561730/asyncpg-0.31.0-cp312-cp312-win_amd64.whl", hash = "sha256:72d6bdcbc93d608a1158f17932de2321f68b1a967a13e014998db87a72ed3186", size = 597175, upload-time = "2025-11-24T23:26:02.564Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/11/97b5c2af72a5d0b9bc3fa30cd4b9ce22284a9a943a150fdc768763caf035/asyncpg-0.31.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c204fab1b91e08b0f47e90a75d1b3c62174dab21f670ad6c5d0f243a228f015b", size = 661111, upload-time = "2025-11-24T23:26:04.467Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1b/71/157d611c791a5e2d0423f09f027bd499935f0906e0c2a416ce712ba51ef3/asyncpg-0.31.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:54a64f91839ba59008eccf7aad2e93d6e3de688d796f35803235ea1c4898ae1e", size = 636928, upload-time = "2025-11-24T23:26:05.944Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2e/fc/9e3486fb2bbe69d4a867c0b76d68542650a7ff1574ca40e84c3111bb0c6e/asyncpg-0.31.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0e0822b1038dc7253b337b0f3f676cadc4ac31b126c5d42691c39691962e403", size = 3424067, upload-time = "2025-11-24T23:26:07.957Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/12/c6/8c9d076f73f07f995013c791e018a1cd5f31823c2a3187fc8581706aa00f/asyncpg-0.31.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bef056aa502ee34204c161c72ca1f3c274917596877f825968368b2c33f585f4", size = 3518156, upload-time = "2025-11-24T23:26:09.591Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ae/3b/60683a0baf50fbc546499cfb53132cb6835b92b529a05f6a81471ab60d0c/asyncpg-0.31.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0bfbcc5b7ffcd9b75ab1558f00db2ae07db9c80637ad1b2469c43df79d7a5ae2", size = 3319636, upload-time = "2025-11-24T23:26:11.168Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/dc/8487df0f69bd398a61e1792b3cba0e47477f214eff085ba0efa7eac9ce87/asyncpg-0.31.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:22bc525ebbdc24d1261ecbf6f504998244d4e3be1721784b5f64664d61fbe602", size = 3472079, upload-time = "2025-11-24T23:26:13.164Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/13/a1/c5bbeeb8531c05c89135cb8b28575ac2fac618bcb60119ee9696c3faf71c/asyncpg-0.31.0-cp313-cp313-win32.whl", hash = "sha256:f890de5e1e4f7e14023619399a471ce4b71f5418cd67a51853b9910fdfa73696", size = 527606, upload-time = "2025-11-24T23:26:14.78Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/91/66/b25ccb84a246b470eb943b0107c07edcae51804912b824054b3413995a10/asyncpg-0.31.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc5f2fa9916f292e5c5c8b2ac2813763bcd7f58e130055b4ad8a0531314201ab", size = 596569, upload-time = "2025-11-24T23:26:16.189Z" }, ] [[package]] name = "attrs" version = "25.4.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, ] [[package]] name = "authlib" version = "1.6.6" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cryptography" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bb/9b/b1661026ff24bc641b76b78c5222d614776b0c085bcfdac9bd15a1cb4b35/authlib-1.6.6.tar.gz", hash = "sha256:45770e8e056d0f283451d9996fbb59b70d45722b45d854d58f32878d0a40c38e", size = 164894, upload-time = "2025-12-12T08:01:41.464Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bb/9b/b1661026ff24bc641b76b78c5222d614776b0c085bcfdac9bd15a1cb4b35/authlib-1.6.6.tar.gz", hash = "sha256:45770e8e056d0f283451d9996fbb59b70d45722b45d854d58f32878d0a40c38e", size = 164894, upload-time = "2025-12-12T08:01:41.464Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/51/321e821856452f7386c4e9df866f196720b1ad0c5ea1623ea7399969ae3b/authlib-1.6.6-py2.py3-none-any.whl", hash = "sha256:7d9e9bc535c13974313a87f53e8430eb6ea3d1cf6ae4f6efcd793f2e949143fd", size = 244005, upload-time = "2025-12-12T08:01:40.209Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/51/321e821856452f7386c4e9df866f196720b1ad0c5ea1623ea7399969ae3b/authlib-1.6.6-py2.py3-none-any.whl", hash = "sha256:7d9e9bc535c13974313a87f53e8430eb6ea3d1cf6ae4f6efcd793f2e949143fd", size = 244005, upload-time = "2025-12-12T08:01:40.209Z" }, ] [[package]] name = "backoff" version = "2.2.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/47/d7/5bbeb12c44d7c4f2fb5b56abce497eb5ed9f34d85701de869acedd602619/backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba", size = 17001, upload-time = "2022-10-05T19:19:32.061Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/47/d7/5bbeb12c44d7c4f2fb5b56abce497eb5ed9f34d85701de869acedd602619/backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba", size = 17001, upload-time = "2022-10-05T19:19:32.061Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/df/73/b6e24bd22e6720ca8ee9a85a0c4a2971af8497d8f3193fa05390cbd46e09/backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8", size = 15148, upload-time = "2022-10-05T19:19:30.546Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/73/b6e24bd22e6720ca8ee9a85a0c4a2971af8497d8f3193fa05390cbd46e09/backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8", size = 15148, upload-time = "2022-10-05T19:19:30.546Z" }, ] [[package]] name = "bcrypt" version = "5.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d4/36/3329e2518d70ad8e2e5817d5a4cac6bba05a47767ec416c7d020a965f408/bcrypt-5.0.0.tar.gz", hash = "sha256:f748f7c2d6fd375cc93d3fba7ef4a9e3a092421b8dbf34d8d4dc06be9492dfdd", size = 25386, upload-time = "2025-09-25T19:50:47.829Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/13/85/3e65e01985fddf25b64ca67275bb5bdb4040bd1a53b66d355c6c37c8a680/bcrypt-5.0.0-cp313-cp313t-macosx_10_12_universal2.whl", hash = "sha256:f3c08197f3039bec79cee59a606d62b96b16669cff3949f21e74796b6e3cd2be", size = 481806, upload-time = "2025-09-25T19:49:05.102Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/44/dc/01eb79f12b177017a726cbf78330eb0eb442fae0e7b3dfd84ea2849552f3/bcrypt-5.0.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:200af71bc25f22006f4069060c88ed36f8aa4ff7f53e67ff04d2ab3f1e79a5b2", size = 268626, upload-time = "2025-09-25T19:49:06.723Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8c/cf/e82388ad5959c40d6afd94fb4743cc077129d45b952d46bdc3180310e2df/bcrypt-5.0.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:baade0a5657654c2984468efb7d6c110db87ea63ef5a4b54732e7e337253e44f", size = 271853, upload-time = "2025-09-25T19:49:08.028Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ec/86/7134b9dae7cf0efa85671651341f6afa695857fae172615e960fb6a466fa/bcrypt-5.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:c58b56cdfb03202b3bcc9fd8daee8e8e9b6d7e3163aa97c631dfcfcc24d36c86", size = 269793, upload-time = "2025-09-25T19:49:09.727Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cc/82/6296688ac1b9e503d034e7d0614d56e80c5d1a08402ff856a4549cb59207/bcrypt-5.0.0-cp313-cp313t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4bfd2a34de661f34d0bda43c3e4e79df586e4716ef401fe31ea39d69d581ef23", size = 289930, upload-time = "2025-09-25T19:49:11.204Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/18/884a44aa47f2a3b88dd09bc05a1e40b57878ecd111d17e5bba6f09f8bb77/bcrypt-5.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ed2e1365e31fc73f1825fa830f1c8f8917ca1b3ca6185773b349c20fd606cec2", size = 272194, upload-time = "2025-09-25T19:49:12.524Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/8f/371a3ab33c6982070b674f1788e05b656cfbf5685894acbfef0c65483a59/bcrypt-5.0.0-cp313-cp313t-manylinux_2_34_aarch64.whl", hash = "sha256:83e787d7a84dbbfba6f250dd7a5efd689e935f03dd83b0f919d39349e1f23f83", size = 269381, upload-time = "2025-09-25T19:49:14.308Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b1/34/7e4e6abb7a8778db6422e88b1f06eb07c47682313997ee8a8f9352e5a6f1/bcrypt-5.0.0-cp313-cp313t-manylinux_2_34_x86_64.whl", hash = "sha256:137c5156524328a24b9fac1cb5db0ba618bc97d11970b39184c1d87dc4bf1746", size = 271750, upload-time = "2025-09-25T19:49:15.584Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c0/1b/54f416be2499bd72123c70d98d36c6cd61a4e33d9b89562c22481c81bb30/bcrypt-5.0.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:38cac74101777a6a7d3b3e3cfefa57089b5ada650dce2baf0cbdd9d65db22a9e", size = 303757, upload-time = "2025-09-25T19:49:17.244Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/13/62/062c24c7bcf9d2826a1a843d0d605c65a755bc98002923d01fd61270705a/bcrypt-5.0.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:d8d65b564ec849643d9f7ea05c6d9f0cd7ca23bdd4ac0c2dbef1104ab504543d", size = 306740, upload-time = "2025-09-25T19:49:18.693Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d5/c8/1fdbfc8c0f20875b6b4020f3c7dc447b8de60aa0be5faaf009d24242aec9/bcrypt-5.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:741449132f64b3524e95cd30e5cd3343006ce146088f074f31ab26b94e6c75ba", size = 334197, upload-time = "2025-09-25T19:49:20.523Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a6/c1/8b84545382d75bef226fbc6588af0f7b7d095f7cd6a670b42a86243183cd/bcrypt-5.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:212139484ab3207b1f0c00633d3be92fef3c5f0af17cad155679d03ff2ee1e41", size = 352974, upload-time = "2025-09-25T19:49:22.254Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/10/a6/ffb49d4254ed085e62e3e5dd05982b4393e32fe1e49bb1130186617c29cd/bcrypt-5.0.0-cp313-cp313t-win32.whl", hash = "sha256:9d52ed507c2488eddd6a95bccee4e808d3234fa78dd370e24bac65a21212b861", size = 148498, upload-time = "2025-09-25T19:49:24.134Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/48/a9/259559edc85258b6d5fc5471a62a3299a6aa37a6611a169756bf4689323c/bcrypt-5.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f6984a24db30548fd39a44360532898c33528b74aedf81c26cf29c51ee47057e", size = 145853, upload-time = "2025-09-25T19:49:25.702Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2d/df/9714173403c7e8b245acf8e4be8876aac64a209d1b392af457c79e60492e/bcrypt-5.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9fffdb387abe6aa775af36ef16f55e318dcda4194ddbf82007a6f21da29de8f5", size = 139626, upload-time = "2025-09-25T19:49:26.928Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/84/29/6237f151fbfe295fe3e074ecc6d44228faa1e842a81f6d34a02937ee1736/bcrypt-5.0.0-cp38-abi3-macosx_10_12_universal2.whl", hash = "sha256:fc746432b951e92b58317af8e0ca746efe93e66555f1b40888865ef5bf56446b", size = 494553, upload-time = "2025-09-25T19:49:49.006Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/45/b6/4c1205dde5e464ea3bd88e8742e19f899c16fa8916fb8510a851fae985b5/bcrypt-5.0.0-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c2388ca94ffee269b6038d48747f4ce8df0ffbea43f31abfa18ac72f0218effb", size = 275009, upload-time = "2025-09-25T19:49:50.581Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3b/71/427945e6ead72ccffe77894b2655b695ccf14ae1866cd977e185d606dd2f/bcrypt-5.0.0-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:560ddb6ec730386e7b3b26b8b4c88197aaed924430e7b74666a586ac997249ef", size = 278029, upload-time = "2025-09-25T19:49:52.533Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/17/72/c344825e3b83c5389a369c8a8e58ffe1480b8a699f46c127c34580c4666b/bcrypt-5.0.0-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d79e5c65dcc9af213594d6f7f1fa2c98ad3fc10431e7aa53c176b441943efbdd", size = 275907, upload-time = "2025-09-25T19:49:54.709Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0b/7e/d4e47d2df1641a36d1212e5c0514f5291e1a956a7749f1e595c07a972038/bcrypt-5.0.0-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2b732e7d388fa22d48920baa267ba5d97cca38070b69c0e2d37087b381c681fd", size = 296500, upload-time = "2025-09-25T19:49:56.013Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/c3/0ae57a68be2039287ec28bc463b82e4b8dc23f9d12c0be331f4782e19108/bcrypt-5.0.0-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:0c8e093ea2532601a6f686edbc2c6b2ec24131ff5c52f7610dd64fa4553b5464", size = 278412, upload-time = "2025-09-25T19:49:57.356Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/45/2b/77424511adb11e6a99e3a00dcc7745034bee89036ad7d7e255a7e47be7d8/bcrypt-5.0.0-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:5b1589f4839a0899c146e8892efe320c0fa096568abd9b95593efac50a87cb75", size = 275486, upload-time = "2025-09-25T19:49:59.116Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/0a/405c753f6158e0f3f14b00b462d8bca31296f7ecfc8fc8bc7919c0c7d73a/bcrypt-5.0.0-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:89042e61b5e808b67daf24a434d89bab164d4de1746b37a8d173b6b14f3db9ff", size = 277940, upload-time = "2025-09-25T19:50:00.869Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/62/83/b3efc285d4aadc1fa83db385ec64dcfa1707e890eb42f03b127d66ac1b7b/bcrypt-5.0.0-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:e3cf5b2560c7b5a142286f69bde914494b6d8f901aaa71e453078388a50881c4", size = 310776, upload-time = "2025-09-25T19:50:02.393Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/7d/47ee337dacecde6d234890fe929936cb03ebc4c3a7460854bbd9c97780b8/bcrypt-5.0.0-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f632fd56fc4e61564f78b46a2269153122db34988e78b6be8b32d28507b7eaeb", size = 312922, upload-time = "2025-09-25T19:50:04.232Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d6/3a/43d494dfb728f55f4e1cf8fd435d50c16a2d75493225b54c8d06122523c6/bcrypt-5.0.0-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:801cad5ccb6b87d1b430f183269b94c24f248dddbbc5c1f78b6ed231743e001c", size = 341367, upload-time = "2025-09-25T19:50:05.559Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/55/ab/a0727a4547e383e2e22a630e0f908113db37904f58719dc48d4622139b5c/bcrypt-5.0.0-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3cf67a804fc66fc217e6914a5635000259fbbbb12e78a99488e4d5ba445a71eb", size = 359187, upload-time = "2025-09-25T19:50:06.916Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1b/bb/461f352fdca663524b4643d8b09e8435b4990f17fbf4fea6bc2a90aa0cc7/bcrypt-5.0.0-cp38-abi3-win32.whl", hash = "sha256:3abeb543874b2c0524ff40c57a4e14e5d3a66ff33fb423529c88f180fd756538", size = 153752, upload-time = "2025-09-25T19:50:08.515Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/41/aa/4190e60921927b7056820291f56fc57d00d04757c8b316b2d3c0d1d6da2c/bcrypt-5.0.0-cp38-abi3-win_amd64.whl", hash = "sha256:35a77ec55b541e5e583eb3436ffbbf53b0ffa1fa16ca6782279daf95d146dcd9", size = 150881, upload-time = "2025-09-25T19:50:09.742Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/12/cd77221719d0b39ac0b55dbd39358db1cd1246e0282e104366ebbfb8266a/bcrypt-5.0.0-cp38-abi3-win_arm64.whl", hash = "sha256:cde08734f12c6a4e28dc6755cd11d3bdfea608d93d958fffbe95a7026ebe4980", size = 144931, upload-time = "2025-09-25T19:50:11.016Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5d/ba/2af136406e1c3839aea9ecadc2f6be2bcd1eff255bd451dd39bcf302c47a/bcrypt-5.0.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0c418ca99fd47e9c59a301744d63328f17798b5947b0f791e9af3c1c499c2d0a", size = 495313, upload-time = "2025-09-25T19:50:12.309Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ac/ee/2f4985dbad090ace5ad1f7dd8ff94477fe089b5fab2040bd784a3d5f187b/bcrypt-5.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddb4e1500f6efdd402218ffe34d040a1196c072e07929b9820f363a1fd1f4191", size = 275290, upload-time = "2025-09-25T19:50:13.673Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e4/6e/b77ade812672d15cf50842e167eead80ac3514f3beacac8902915417f8b7/bcrypt-5.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7aeef54b60ceddb6f30ee3db090351ecf0d40ec6e2abf41430997407a46d2254", size = 278253, upload-time = "2025-09-25T19:50:15.089Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/36/c4/ed00ed32f1040f7990dac7115f82273e3c03da1e1a1587a778d8cea496d8/bcrypt-5.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f0ce778135f60799d89c9693b9b398819d15f1921ba15fe719acb3178215a7db", size = 276084, upload-time = "2025-09-25T19:50:16.699Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/c4/fa6e16145e145e87f1fa351bbd54b429354fd72145cd3d4e0c5157cf4c70/bcrypt-5.0.0-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a71f70ee269671460b37a449f5ff26982a6f2ba493b3eabdd687b4bf35f875ac", size = 297185, upload-time = "2025-09-25T19:50:18.525Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/24/b4/11f8a31d8b67cca3371e046db49baa7c0594d71eb40ac8121e2fc0888db0/bcrypt-5.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f8429e1c410b4073944f03bd778a9e066e7fad723564a52ff91841d278dfc822", size = 278656, upload-time = "2025-09-25T19:50:19.809Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ac/31/79f11865f8078e192847d2cb526e3fa27c200933c982c5b2869720fa5fce/bcrypt-5.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:edfcdcedd0d0f05850c52ba3127b1fce70b9f89e0fe5ff16517df7e81fa3cbb8", size = 275662, upload-time = "2025-09-25T19:50:21.567Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d4/8d/5e43d9584b3b3591a6f9b68f755a4da879a59712981ef5ad2a0ac1379f7a/bcrypt-5.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:611f0a17aa4a25a69362dcc299fda5c8a3d4f160e2abb3831041feb77393a14a", size = 278240, upload-time = "2025-09-25T19:50:23.305Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/48/44590e3fc158620f680a978aafe8f87a4c4320da81ed11552f0323aa9a57/bcrypt-5.0.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:db99dca3b1fdc3db87d7c57eac0c82281242d1eabf19dcb8a6b10eb29a2e72d1", size = 311152, upload-time = "2025-09-25T19:50:24.597Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5f/85/e4fbfc46f14f47b0d20493669a625da5827d07e8a88ee460af6cd9768b44/bcrypt-5.0.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:5feebf85a9cefda32966d8171f5db7e3ba964b77fdfe31919622256f80f9cf42", size = 313284, upload-time = "2025-09-25T19:50:26.268Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/ae/479f81d3f4594456a01ea2f05b132a519eff9ab5768a70430fa1132384b1/bcrypt-5.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3ca8a166b1140436e058298a34d88032ab62f15aae1c598580333dc21d27ef10", size = 341643, upload-time = "2025-09-25T19:50:28.02Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/df/d2/36a086dee1473b14276cd6ea7f61aef3b2648710b5d7f1c9e032c29b859f/bcrypt-5.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:61afc381250c3182d9078551e3ac3a41da14154fbff647ddf52a769f588c4172", size = 359698, upload-time = "2025-09-25T19:50:31.347Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c0/f6/688d2cd64bfd0b14d805ddb8a565e11ca1fb0fd6817175d58b10052b6d88/bcrypt-5.0.0-cp39-abi3-win32.whl", hash = "sha256:64d7ce196203e468c457c37ec22390f1a61c85c6f0b8160fd752940ccfb3a683", size = 153725, upload-time = "2025-09-25T19:50:34.384Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/b9/9d9a641194a730bda138b3dfe53f584d61c58cd5230e37566e83ec2ffa0d/bcrypt-5.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:64ee8434b0da054d830fa8e89e1c8bf30061d539044a39524ff7dec90481e5c2", size = 150912, upload-time = "2025-09-25T19:50:35.69Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/27/44/d2ef5e87509158ad2187f4dd0852df80695bb1ee0cfe0a684727b01a69e0/bcrypt-5.0.0-cp39-abi3-win_arm64.whl", hash = "sha256:f2347d3534e76bf50bca5500989d6c1d05ed64b440408057a37673282c654927", size = 144953, upload-time = "2025-09-25T19:50:37.32Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/36/3329e2518d70ad8e2e5817d5a4cac6bba05a47767ec416c7d020a965f408/bcrypt-5.0.0.tar.gz", hash = "sha256:f748f7c2d6fd375cc93d3fba7ef4a9e3a092421b8dbf34d8d4dc06be9492dfdd", size = 25386, upload-time = "2025-09-25T19:50:47.829Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/13/85/3e65e01985fddf25b64ca67275bb5bdb4040bd1a53b66d355c6c37c8a680/bcrypt-5.0.0-cp313-cp313t-macosx_10_12_universal2.whl", hash = "sha256:f3c08197f3039bec79cee59a606d62b96b16669cff3949f21e74796b6e3cd2be", size = 481806, upload-time = "2025-09-25T19:49:05.102Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/44/dc/01eb79f12b177017a726cbf78330eb0eb442fae0e7b3dfd84ea2849552f3/bcrypt-5.0.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:200af71bc25f22006f4069060c88ed36f8aa4ff7f53e67ff04d2ab3f1e79a5b2", size = 268626, upload-time = "2025-09-25T19:49:06.723Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8c/cf/e82388ad5959c40d6afd94fb4743cc077129d45b952d46bdc3180310e2df/bcrypt-5.0.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:baade0a5657654c2984468efb7d6c110db87ea63ef5a4b54732e7e337253e44f", size = 271853, upload-time = "2025-09-25T19:49:08.028Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ec/86/7134b9dae7cf0efa85671651341f6afa695857fae172615e960fb6a466fa/bcrypt-5.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:c58b56cdfb03202b3bcc9fd8daee8e8e9b6d7e3163aa97c631dfcfcc24d36c86", size = 269793, upload-time = "2025-09-25T19:49:09.727Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/82/6296688ac1b9e503d034e7d0614d56e80c5d1a08402ff856a4549cb59207/bcrypt-5.0.0-cp313-cp313t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4bfd2a34de661f34d0bda43c3e4e79df586e4716ef401fe31ea39d69d581ef23", size = 289930, upload-time = "2025-09-25T19:49:11.204Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/18/884a44aa47f2a3b88dd09bc05a1e40b57878ecd111d17e5bba6f09f8bb77/bcrypt-5.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ed2e1365e31fc73f1825fa830f1c8f8917ca1b3ca6185773b349c20fd606cec2", size = 272194, upload-time = "2025-09-25T19:49:12.524Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/8f/371a3ab33c6982070b674f1788e05b656cfbf5685894acbfef0c65483a59/bcrypt-5.0.0-cp313-cp313t-manylinux_2_34_aarch64.whl", hash = "sha256:83e787d7a84dbbfba6f250dd7a5efd689e935f03dd83b0f919d39349e1f23f83", size = 269381, upload-time = "2025-09-25T19:49:14.308Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/34/7e4e6abb7a8778db6422e88b1f06eb07c47682313997ee8a8f9352e5a6f1/bcrypt-5.0.0-cp313-cp313t-manylinux_2_34_x86_64.whl", hash = "sha256:137c5156524328a24b9fac1cb5db0ba618bc97d11970b39184c1d87dc4bf1746", size = 271750, upload-time = "2025-09-25T19:49:15.584Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/1b/54f416be2499bd72123c70d98d36c6cd61a4e33d9b89562c22481c81bb30/bcrypt-5.0.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:38cac74101777a6a7d3b3e3cfefa57089b5ada650dce2baf0cbdd9d65db22a9e", size = 303757, upload-time = "2025-09-25T19:49:17.244Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/13/62/062c24c7bcf9d2826a1a843d0d605c65a755bc98002923d01fd61270705a/bcrypt-5.0.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:d8d65b564ec849643d9f7ea05c6d9f0cd7ca23bdd4ac0c2dbef1104ab504543d", size = 306740, upload-time = "2025-09-25T19:49:18.693Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d5/c8/1fdbfc8c0f20875b6b4020f3c7dc447b8de60aa0be5faaf009d24242aec9/bcrypt-5.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:741449132f64b3524e95cd30e5cd3343006ce146088f074f31ab26b94e6c75ba", size = 334197, upload-time = "2025-09-25T19:49:20.523Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a6/c1/8b84545382d75bef226fbc6588af0f7b7d095f7cd6a670b42a86243183cd/bcrypt-5.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:212139484ab3207b1f0c00633d3be92fef3c5f0af17cad155679d03ff2ee1e41", size = 352974, upload-time = "2025-09-25T19:49:22.254Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/a6/ffb49d4254ed085e62e3e5dd05982b4393e32fe1e49bb1130186617c29cd/bcrypt-5.0.0-cp313-cp313t-win32.whl", hash = "sha256:9d52ed507c2488eddd6a95bccee4e808d3234fa78dd370e24bac65a21212b861", size = 148498, upload-time = "2025-09-25T19:49:24.134Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/48/a9/259559edc85258b6d5fc5471a62a3299a6aa37a6611a169756bf4689323c/bcrypt-5.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f6984a24db30548fd39a44360532898c33528b74aedf81c26cf29c51ee47057e", size = 145853, upload-time = "2025-09-25T19:49:25.702Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/df/9714173403c7e8b245acf8e4be8876aac64a209d1b392af457c79e60492e/bcrypt-5.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9fffdb387abe6aa775af36ef16f55e318dcda4194ddbf82007a6f21da29de8f5", size = 139626, upload-time = "2025-09-25T19:49:26.928Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/84/29/6237f151fbfe295fe3e074ecc6d44228faa1e842a81f6d34a02937ee1736/bcrypt-5.0.0-cp38-abi3-macosx_10_12_universal2.whl", hash = "sha256:fc746432b951e92b58317af8e0ca746efe93e66555f1b40888865ef5bf56446b", size = 494553, upload-time = "2025-09-25T19:49:49.006Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/45/b6/4c1205dde5e464ea3bd88e8742e19f899c16fa8916fb8510a851fae985b5/bcrypt-5.0.0-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c2388ca94ffee269b6038d48747f4ce8df0ffbea43f31abfa18ac72f0218effb", size = 275009, upload-time = "2025-09-25T19:49:50.581Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3b/71/427945e6ead72ccffe77894b2655b695ccf14ae1866cd977e185d606dd2f/bcrypt-5.0.0-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:560ddb6ec730386e7b3b26b8b4c88197aaed924430e7b74666a586ac997249ef", size = 278029, upload-time = "2025-09-25T19:49:52.533Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/17/72/c344825e3b83c5389a369c8a8e58ffe1480b8a699f46c127c34580c4666b/bcrypt-5.0.0-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d79e5c65dcc9af213594d6f7f1fa2c98ad3fc10431e7aa53c176b441943efbdd", size = 275907, upload-time = "2025-09-25T19:49:54.709Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0b/7e/d4e47d2df1641a36d1212e5c0514f5291e1a956a7749f1e595c07a972038/bcrypt-5.0.0-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2b732e7d388fa22d48920baa267ba5d97cca38070b69c0e2d37087b381c681fd", size = 296500, upload-time = "2025-09-25T19:49:56.013Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0f/c3/0ae57a68be2039287ec28bc463b82e4b8dc23f9d12c0be331f4782e19108/bcrypt-5.0.0-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:0c8e093ea2532601a6f686edbc2c6b2ec24131ff5c52f7610dd64fa4553b5464", size = 278412, upload-time = "2025-09-25T19:49:57.356Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/45/2b/77424511adb11e6a99e3a00dcc7745034bee89036ad7d7e255a7e47be7d8/bcrypt-5.0.0-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:5b1589f4839a0899c146e8892efe320c0fa096568abd9b95593efac50a87cb75", size = 275486, upload-time = "2025-09-25T19:49:59.116Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/0a/405c753f6158e0f3f14b00b462d8bca31296f7ecfc8fc8bc7919c0c7d73a/bcrypt-5.0.0-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:89042e61b5e808b67daf24a434d89bab164d4de1746b37a8d173b6b14f3db9ff", size = 277940, upload-time = "2025-09-25T19:50:00.869Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/83/b3efc285d4aadc1fa83db385ec64dcfa1707e890eb42f03b127d66ac1b7b/bcrypt-5.0.0-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:e3cf5b2560c7b5a142286f69bde914494b6d8f901aaa71e453078388a50881c4", size = 310776, upload-time = "2025-09-25T19:50:02.393Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/7d/47ee337dacecde6d234890fe929936cb03ebc4c3a7460854bbd9c97780b8/bcrypt-5.0.0-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f632fd56fc4e61564f78b46a2269153122db34988e78b6be8b32d28507b7eaeb", size = 312922, upload-time = "2025-09-25T19:50:04.232Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/3a/43d494dfb728f55f4e1cf8fd435d50c16a2d75493225b54c8d06122523c6/bcrypt-5.0.0-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:801cad5ccb6b87d1b430f183269b94c24f248dddbbc5c1f78b6ed231743e001c", size = 341367, upload-time = "2025-09-25T19:50:05.559Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/55/ab/a0727a4547e383e2e22a630e0f908113db37904f58719dc48d4622139b5c/bcrypt-5.0.0-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3cf67a804fc66fc217e6914a5635000259fbbbb12e78a99488e4d5ba445a71eb", size = 359187, upload-time = "2025-09-25T19:50:06.916Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1b/bb/461f352fdca663524b4643d8b09e8435b4990f17fbf4fea6bc2a90aa0cc7/bcrypt-5.0.0-cp38-abi3-win32.whl", hash = "sha256:3abeb543874b2c0524ff40c57a4e14e5d3a66ff33fb423529c88f180fd756538", size = 153752, upload-time = "2025-09-25T19:50:08.515Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/aa/4190e60921927b7056820291f56fc57d00d04757c8b316b2d3c0d1d6da2c/bcrypt-5.0.0-cp38-abi3-win_amd64.whl", hash = "sha256:35a77ec55b541e5e583eb3436ffbbf53b0ffa1fa16ca6782279daf95d146dcd9", size = 150881, upload-time = "2025-09-25T19:50:09.742Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/12/cd77221719d0b39ac0b55dbd39358db1cd1246e0282e104366ebbfb8266a/bcrypt-5.0.0-cp38-abi3-win_arm64.whl", hash = "sha256:cde08734f12c6a4e28dc6755cd11d3bdfea608d93d958fffbe95a7026ebe4980", size = 144931, upload-time = "2025-09-25T19:50:11.016Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/ba/2af136406e1c3839aea9ecadc2f6be2bcd1eff255bd451dd39bcf302c47a/bcrypt-5.0.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0c418ca99fd47e9c59a301744d63328f17798b5947b0f791e9af3c1c499c2d0a", size = 495313, upload-time = "2025-09-25T19:50:12.309Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/ee/2f4985dbad090ace5ad1f7dd8ff94477fe089b5fab2040bd784a3d5f187b/bcrypt-5.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddb4e1500f6efdd402218ffe34d040a1196c072e07929b9820f363a1fd1f4191", size = 275290, upload-time = "2025-09-25T19:50:13.673Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e4/6e/b77ade812672d15cf50842e167eead80ac3514f3beacac8902915417f8b7/bcrypt-5.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7aeef54b60ceddb6f30ee3db090351ecf0d40ec6e2abf41430997407a46d2254", size = 278253, upload-time = "2025-09-25T19:50:15.089Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/36/c4/ed00ed32f1040f7990dac7115f82273e3c03da1e1a1587a778d8cea496d8/bcrypt-5.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f0ce778135f60799d89c9693b9b398819d15f1921ba15fe719acb3178215a7db", size = 276084, upload-time = "2025-09-25T19:50:16.699Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/c4/fa6e16145e145e87f1fa351bbd54b429354fd72145cd3d4e0c5157cf4c70/bcrypt-5.0.0-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a71f70ee269671460b37a449f5ff26982a6f2ba493b3eabdd687b4bf35f875ac", size = 297185, upload-time = "2025-09-25T19:50:18.525Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/24/b4/11f8a31d8b67cca3371e046db49baa7c0594d71eb40ac8121e2fc0888db0/bcrypt-5.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f8429e1c410b4073944f03bd778a9e066e7fad723564a52ff91841d278dfc822", size = 278656, upload-time = "2025-09-25T19:50:19.809Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/31/79f11865f8078e192847d2cb526e3fa27c200933c982c5b2869720fa5fce/bcrypt-5.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:edfcdcedd0d0f05850c52ba3127b1fce70b9f89e0fe5ff16517df7e81fa3cbb8", size = 275662, upload-time = "2025-09-25T19:50:21.567Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/8d/5e43d9584b3b3591a6f9b68f755a4da879a59712981ef5ad2a0ac1379f7a/bcrypt-5.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:611f0a17aa4a25a69362dcc299fda5c8a3d4f160e2abb3831041feb77393a14a", size = 278240, upload-time = "2025-09-25T19:50:23.305Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/48/44590e3fc158620f680a978aafe8f87a4c4320da81ed11552f0323aa9a57/bcrypt-5.0.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:db99dca3b1fdc3db87d7c57eac0c82281242d1eabf19dcb8a6b10eb29a2e72d1", size = 311152, upload-time = "2025-09-25T19:50:24.597Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/85/e4fbfc46f14f47b0d20493669a625da5827d07e8a88ee460af6cd9768b44/bcrypt-5.0.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:5feebf85a9cefda32966d8171f5db7e3ba964b77fdfe31919622256f80f9cf42", size = 313284, upload-time = "2025-09-25T19:50:26.268Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/ae/479f81d3f4594456a01ea2f05b132a519eff9ab5768a70430fa1132384b1/bcrypt-5.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3ca8a166b1140436e058298a34d88032ab62f15aae1c598580333dc21d27ef10", size = 341643, upload-time = "2025-09-25T19:50:28.02Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/d2/36a086dee1473b14276cd6ea7f61aef3b2648710b5d7f1c9e032c29b859f/bcrypt-5.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:61afc381250c3182d9078551e3ac3a41da14154fbff647ddf52a769f588c4172", size = 359698, upload-time = "2025-09-25T19:50:31.347Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/f6/688d2cd64bfd0b14d805ddb8a565e11ca1fb0fd6817175d58b10052b6d88/bcrypt-5.0.0-cp39-abi3-win32.whl", hash = "sha256:64d7ce196203e468c457c37ec22390f1a61c85c6f0b8160fd752940ccfb3a683", size = 153725, upload-time = "2025-09-25T19:50:34.384Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/b9/9d9a641194a730bda138b3dfe53f584d61c58cd5230e37566e83ec2ffa0d/bcrypt-5.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:64ee8434b0da054d830fa8e89e1c8bf30061d539044a39524ff7dec90481e5c2", size = 150912, upload-time = "2025-09-25T19:50:35.69Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/27/44/d2ef5e87509158ad2187f4dd0852df80695bb1ee0cfe0a684727b01a69e0/bcrypt-5.0.0-cp39-abi3-win_arm64.whl", hash = "sha256:f2347d3534e76bf50bca5500989d6c1d05ed64b440408057a37673282c654927", size = 144953, upload-time = "2025-09-25T19:50:37.32Z" }, ] [[package]] name = "beartype" version = "0.22.9" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/94/1009e248bbfbab11397abca7193bea6626806be9a327d399810d523a07cb/beartype-0.22.9.tar.gz", hash = "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f", size = 1608866, upload-time = "2025-12-13T06:50:30.72Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/94/1009e248bbfbab11397abca7193bea6626806be9a327d399810d523a07cb/beartype-0.22.9.tar.gz", hash = "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f", size = 1608866, upload-time = "2025-12-13T06:50:30.72Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" }, ] [[package]] name = "beautifulsoup4" version = "4.14.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "soupsieve" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, ] [[package]] name = "bitarray" version = "3.8.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/06/92fdc84448d324ab8434b78e65caf4fb4c6c90b4f8ad9bdd4c8021bfaf1e/bitarray-3.8.0.tar.gz", hash = "sha256:3eae38daffd77c9621ae80c16932eea3fb3a4af141fb7cc724d4ad93eff9210d", size = 151991, upload-time = "2025-11-02T21:41:15.117Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/82/a0/0c41d893eda756315491adfdbf9bc928aee3d377a7f97a8834d453aa5de1/bitarray-3.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2fcbe9b3a5996b417e030aa33a562e7e20dfc86271e53d7e841fc5df16268b8", size = 148575, upload-time = "2025-11-02T21:39:25.718Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/30/12ab2f4a4429bd844b419c37877caba93d676d18be71354fbbeb21d9f4cc/bitarray-3.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cd761d158f67e288fd0ebe00c3b158095ce80a4bc7c32b60c7121224003ba70d", size = 145454, upload-time = "2025-11-02T21:39:26.695Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/58/314b3e3f219533464e120f0c51ac5123e7b1c1b91f725a4073fb70c5a858/bitarray-3.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c394a3f055b49f92626f83c1a0b6d6cd2c628f1ccd72481c3e3c6aa4695f3b20", size = 332949, upload-time = "2025-11-02T21:39:27.801Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/ce/ca8c706bd8341c7a22dd92d2a528af71f7e5f4726085d93f81fd768cb03b/bitarray-3.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:969fd67de8c42affdb47b38b80f1eaa79ac0ef17d65407cdd931db1675315af1", size = 360599, upload-time = "2025-11-02T21:39:28.964Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ef/dc/aa181df85f933052d962804906b282acb433cb9318b08ec2aceb4ee34faf/bitarray-3.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:99d25aff3745c54e61ab340b98400c52ebec04290a62078155e0d7eb30380220", size = 371972, upload-time = "2025-11-02T21:39:30.228Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/d9/b805bfa158c7bcf4df0ac19b1be581b47e1ddb792c11023aed80a7058e78/bitarray-3.8.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e645b4c365d6f1f9e0799380ad6395268f3c3b898244a650aaeb8d9d27b74c35", size = 340303, upload-time = "2025-11-02T21:39:31.342Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1f/42/5308cc97ea929e30727292617a3a88293470166851e13c9e3f16f395da55/bitarray-3.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2fa23fdb3beab313950bbb49674e8a161e61449332d3997089fe3944953f1b77", size = 330494, upload-time = "2025-11-02T21:39:32.769Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4c/89/64f1596cb80433323efdbc8dcd0d6e57c40dfbe6ea3341623f34ec397edd/bitarray-3.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:165052a0e61c880f7093808a0c524ce1b3555bfa114c0dfb5c809cd07918a60d", size = 358123, upload-time = "2025-11-02T21:39:34.331Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/27/fd/f3d49c5443b57087f888b5e118c8dd78bb7c8e8cfeeed250f8e92128a05f/bitarray-3.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:337c8cd46a4c6568d367ed676cbf2d7de16f890bb31dbb54c44c1d6bb6d4a1de", size = 356046, upload-time = "2025-11-02T21:39:35.449Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/db/1fd0b402bd2b47142e958b6930dbb9445235d03fa703c9a24caa6e576ae2/bitarray-3.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:21ca6a47bf20db9e7ad74ca04b3d479e4d76109b68333eb23535553d2705339e", size = 336872, upload-time = "2025-11-02T21:39:36.891Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/73/680b47718f1313b4538af479c4732eaca0aeda34d93fc5b869f87932d57d/bitarray-3.8.0-cp312-cp312-win32.whl", hash = "sha256:178c5a4c7fdfb5cd79e372ae7f675390e670f3732e5bc68d327e01a5b3ff8d55", size = 143025, upload-time = "2025-11-02T21:39:38.303Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f8/11/7792587c19c79a8283e8838f44709fa4338a8f7d2a3091dfd81c07ae89c7/bitarray-3.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:75a3b6e9c695a6570ea488db75b84bb592ff70a944957efa1c655867c575018b", size = 149969, upload-time = "2025-11-02T21:39:39.715Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/00/9df64b5d8a84e8e9ec392f6f9ce93f50626a5b301cb6c6b3fe3406454d66/bitarray-3.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:5591daf81313096909d973fb2612fccd87528fdfdd39f6478bdce54543178954", size = 146907, upload-time = "2025-11-02T21:39:40.815Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3e/35/480364d4baf1e34c79076750914664373f561c58abb5c31c35b3fae613ff/bitarray-3.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:18214bac86341f1cc413772e66447d6cca10981e2880b70ecaf4e826c04f95e9", size = 148582, upload-time = "2025-11-02T21:39:42.268Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5e/a8/718b95524c803937f4edbaaf6480f39c80f6ed189d61357b345e8361ffb6/bitarray-3.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:01c5f0dc080b0ebb432f7a68ee1e88a76bd34f6d89c9568fcec65fb16ed71f0e", size = 145433, upload-time = "2025-11-02T21:39:43.552Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/03/66/4a10f30dc9e2e01e3b4ecd44a511219f98e63c86b0e0f704c90fac24059b/bitarray-3.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86685fa04067f7175f9718489ae755f6acde03593a1a9ca89305554af40e14fd", size = 332986, upload-time = "2025-11-02T21:39:44.656Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/53/25/4c08774d847f80a1166e4c704b4e0f1c417c0afe6306eae0bc5e70d35faa/bitarray-3.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56896ceeffe25946c4010320629e2d858ca763cd8ded273c81672a5edbcb1e0a", size = 360634, upload-time = "2025-11-02T21:39:45.798Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a5/8f/bf8ad26169ebd0b2746d5c7564db734453ca467f8aab87e9d43b0a794383/bitarray-3.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9858dcbc23ba7eaadcd319786b982278a1a2b2020720b19db43e309579ff76fb", size = 371992, upload-time = "2025-11-02T21:39:46.968Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a9/16/ce166754e7c9d10650e02914552fa637cf3b2591f7ed16632bbf6b783312/bitarray-3.8.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa7dec53c25f1949513457ef8b0ea1fb40e76c672cc4d2daa8ad3c8d6b73491a", size = 340315, upload-time = "2025-11-02T21:39:48.182Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/de/2a/fbba3a106ddd260e84b9a624f730257c32ba51a8a029565248dfedfdf6f2/bitarray-3.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:15a2eff91f54d2b1f573cca8ca6fb58763ce8fea80e7899ab028f3987ef71cd5", size = 330473, upload-time = "2025-11-02T21:39:49.705Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/68/97/56cf3c70196e7307ad32318a9d6ed969dbdc6a4534bbe429112fa7dfe42e/bitarray-3.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b1572ee0eb1967e71787af636bb7d1eb9c6735d5337762c450650e7f51844594", size = 358129, upload-time = "2025-11-02T21:39:51.189Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/be/afd391a5c0896d3339613321b2f94af853f29afc8bd3fbc327431244c642/bitarray-3.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5bfac7f236ba1a4d402644bdce47fb9db02a7cf3214a1f637d3a88390f9e5428", size = 356005, upload-time = "2025-11-02T21:39:52.355Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ae/08/a8e1a371babba29bad3378bb3a2cdca2b012170711e7fe1f22031a6b7b95/bitarray-3.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f0a55cf02d2cdd739b40ce10c09bbdd520e141217696add7a48b56e67bdfdfe6", size = 336862, upload-time = "2025-11-02T21:39:54.345Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ee/8a/6dc1d0fdc06991c8dc3b1fcfe1ae49fbaced42064cd1b5f24278e73fe05f/bitarray-3.8.0-cp313-cp313-win32.whl", hash = "sha256:a2ba92f59e30ce915e9e79af37649432e3a212ddddf416d4d686b1b4825bcdb2", size = 143018, upload-time = "2025-11-02T21:39:56.361Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2e/72/76e13f5cd23b8b9071747909663ce3b02da24a5e7e22c35146338625db35/bitarray-3.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c8f2a5d8006db5a555e06f9437e76bf52537d3dfd130cb8ae2b30866aca32c9", size = 149977, upload-time = "2025-11-02T21:39:57.718Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/01/37/60f336c32336cc3ec03b0c61076f16ea2f05d5371c8a56e802161d218b77/bitarray-3.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:50ddbe3a7b4b6ab96812f5a4d570f401a2cdb95642fd04c062f98939610bbeee", size = 146930, upload-time = "2025-11-02T21:39:59.308Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/06/92fdc84448d324ab8434b78e65caf4fb4c6c90b4f8ad9bdd4c8021bfaf1e/bitarray-3.8.0.tar.gz", hash = "sha256:3eae38daffd77c9621ae80c16932eea3fb3a4af141fb7cc724d4ad93eff9210d", size = 151991, upload-time = "2025-11-02T21:41:15.117Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/82/a0/0c41d893eda756315491adfdbf9bc928aee3d377a7f97a8834d453aa5de1/bitarray-3.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2fcbe9b3a5996b417e030aa33a562e7e20dfc86271e53d7e841fc5df16268b8", size = 148575, upload-time = "2025-11-02T21:39:25.718Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/30/12ab2f4a4429bd844b419c37877caba93d676d18be71354fbbeb21d9f4cc/bitarray-3.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cd761d158f67e288fd0ebe00c3b158095ce80a4bc7c32b60c7121224003ba70d", size = 145454, upload-time = "2025-11-02T21:39:26.695Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/58/314b3e3f219533464e120f0c51ac5123e7b1c1b91f725a4073fb70c5a858/bitarray-3.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c394a3f055b49f92626f83c1a0b6d6cd2c628f1ccd72481c3e3c6aa4695f3b20", size = 332949, upload-time = "2025-11-02T21:39:27.801Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/ce/ca8c706bd8341c7a22dd92d2a528af71f7e5f4726085d93f81fd768cb03b/bitarray-3.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:969fd67de8c42affdb47b38b80f1eaa79ac0ef17d65407cdd931db1675315af1", size = 360599, upload-time = "2025-11-02T21:39:28.964Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ef/dc/aa181df85f933052d962804906b282acb433cb9318b08ec2aceb4ee34faf/bitarray-3.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:99d25aff3745c54e61ab340b98400c52ebec04290a62078155e0d7eb30380220", size = 371972, upload-time = "2025-11-02T21:39:30.228Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/d9/b805bfa158c7bcf4df0ac19b1be581b47e1ddb792c11023aed80a7058e78/bitarray-3.8.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e645b4c365d6f1f9e0799380ad6395268f3c3b898244a650aaeb8d9d27b74c35", size = 340303, upload-time = "2025-11-02T21:39:31.342Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1f/42/5308cc97ea929e30727292617a3a88293470166851e13c9e3f16f395da55/bitarray-3.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2fa23fdb3beab313950bbb49674e8a161e61449332d3997089fe3944953f1b77", size = 330494, upload-time = "2025-11-02T21:39:32.769Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4c/89/64f1596cb80433323efdbc8dcd0d6e57c40dfbe6ea3341623f34ec397edd/bitarray-3.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:165052a0e61c880f7093808a0c524ce1b3555bfa114c0dfb5c809cd07918a60d", size = 358123, upload-time = "2025-11-02T21:39:34.331Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/27/fd/f3d49c5443b57087f888b5e118c8dd78bb7c8e8cfeeed250f8e92128a05f/bitarray-3.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:337c8cd46a4c6568d367ed676cbf2d7de16f890bb31dbb54c44c1d6bb6d4a1de", size = 356046, upload-time = "2025-11-02T21:39:35.449Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/db/1fd0b402bd2b47142e958b6930dbb9445235d03fa703c9a24caa6e576ae2/bitarray-3.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:21ca6a47bf20db9e7ad74ca04b3d479e4d76109b68333eb23535553d2705339e", size = 336872, upload-time = "2025-11-02T21:39:36.891Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/73/680b47718f1313b4538af479c4732eaca0aeda34d93fc5b869f87932d57d/bitarray-3.8.0-cp312-cp312-win32.whl", hash = "sha256:178c5a4c7fdfb5cd79e372ae7f675390e670f3732e5bc68d327e01a5b3ff8d55", size = 143025, upload-time = "2025-11-02T21:39:38.303Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f8/11/7792587c19c79a8283e8838f44709fa4338a8f7d2a3091dfd81c07ae89c7/bitarray-3.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:75a3b6e9c695a6570ea488db75b84bb592ff70a944957efa1c655867c575018b", size = 149969, upload-time = "2025-11-02T21:39:39.715Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/00/9df64b5d8a84e8e9ec392f6f9ce93f50626a5b301cb6c6b3fe3406454d66/bitarray-3.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:5591daf81313096909d973fb2612fccd87528fdfdd39f6478bdce54543178954", size = 146907, upload-time = "2025-11-02T21:39:40.815Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3e/35/480364d4baf1e34c79076750914664373f561c58abb5c31c35b3fae613ff/bitarray-3.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:18214bac86341f1cc413772e66447d6cca10981e2880b70ecaf4e826c04f95e9", size = 148582, upload-time = "2025-11-02T21:39:42.268Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5e/a8/718b95524c803937f4edbaaf6480f39c80f6ed189d61357b345e8361ffb6/bitarray-3.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:01c5f0dc080b0ebb432f7a68ee1e88a76bd34f6d89c9568fcec65fb16ed71f0e", size = 145433, upload-time = "2025-11-02T21:39:43.552Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/03/66/4a10f30dc9e2e01e3b4ecd44a511219f98e63c86b0e0f704c90fac24059b/bitarray-3.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86685fa04067f7175f9718489ae755f6acde03593a1a9ca89305554af40e14fd", size = 332986, upload-time = "2025-11-02T21:39:44.656Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/53/25/4c08774d847f80a1166e4c704b4e0f1c417c0afe6306eae0bc5e70d35faa/bitarray-3.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56896ceeffe25946c4010320629e2d858ca763cd8ded273c81672a5edbcb1e0a", size = 360634, upload-time = "2025-11-02T21:39:45.798Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a5/8f/bf8ad26169ebd0b2746d5c7564db734453ca467f8aab87e9d43b0a794383/bitarray-3.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9858dcbc23ba7eaadcd319786b982278a1a2b2020720b19db43e309579ff76fb", size = 371992, upload-time = "2025-11-02T21:39:46.968Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a9/16/ce166754e7c9d10650e02914552fa637cf3b2591f7ed16632bbf6b783312/bitarray-3.8.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa7dec53c25f1949513457ef8b0ea1fb40e76c672cc4d2daa8ad3c8d6b73491a", size = 340315, upload-time = "2025-11-02T21:39:48.182Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/de/2a/fbba3a106ddd260e84b9a624f730257c32ba51a8a029565248dfedfdf6f2/bitarray-3.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:15a2eff91f54d2b1f573cca8ca6fb58763ce8fea80e7899ab028f3987ef71cd5", size = 330473, upload-time = "2025-11-02T21:39:49.705Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/68/97/56cf3c70196e7307ad32318a9d6ed969dbdc6a4534bbe429112fa7dfe42e/bitarray-3.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b1572ee0eb1967e71787af636bb7d1eb9c6735d5337762c450650e7f51844594", size = 358129, upload-time = "2025-11-02T21:39:51.189Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/be/afd391a5c0896d3339613321b2f94af853f29afc8bd3fbc327431244c642/bitarray-3.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5bfac7f236ba1a4d402644bdce47fb9db02a7cf3214a1f637d3a88390f9e5428", size = 356005, upload-time = "2025-11-02T21:39:52.355Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ae/08/a8e1a371babba29bad3378bb3a2cdca2b012170711e7fe1f22031a6b7b95/bitarray-3.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f0a55cf02d2cdd739b40ce10c09bbdd520e141217696add7a48b56e67bdfdfe6", size = 336862, upload-time = "2025-11-02T21:39:54.345Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ee/8a/6dc1d0fdc06991c8dc3b1fcfe1ae49fbaced42064cd1b5f24278e73fe05f/bitarray-3.8.0-cp313-cp313-win32.whl", hash = "sha256:a2ba92f59e30ce915e9e79af37649432e3a212ddddf416d4d686b1b4825bcdb2", size = 143018, upload-time = "2025-11-02T21:39:56.361Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2e/72/76e13f5cd23b8b9071747909663ce3b02da24a5e7e22c35146338625db35/bitarray-3.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c8f2a5d8006db5a555e06f9437e76bf52537d3dfd130cb8ae2b30866aca32c9", size = 149977, upload-time = "2025-11-02T21:39:57.718Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/01/37/60f336c32336cc3ec03b0c61076f16ea2f05d5371c8a56e802161d218b77/bitarray-3.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:50ddbe3a7b4b6ab96812f5a4d570f401a2cdb95642fd04c062f98939610bbeee", size = 146930, upload-time = "2025-11-02T21:39:59.308Z" }, ] [[package]] name = "bitstring" version = "4.3.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "bitarray" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/15/a8/a80c890db75d5bdd5314b5de02c4144c7de94fd0cefcae51acaeb14c6a3f/bitstring-4.3.1.tar.gz", hash = "sha256:a08bc09d3857216d4c0f412a1611056f1cc2b64fd254fb1e8a0afba7cfa1a95a", size = 251426, upload-time = "2025-03-22T09:39:06.978Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/15/a8/a80c890db75d5bdd5314b5de02c4144c7de94fd0cefcae51acaeb14c6a3f/bitstring-4.3.1.tar.gz", hash = "sha256:a08bc09d3857216d4c0f412a1611056f1cc2b64fd254fb1e8a0afba7cfa1a95a", size = 251426, upload-time = "2025-03-22T09:39:06.978Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/2d/174566b533755ddf8efb32a5503af61c756a983de379f8ad3aed6a982d38/bitstring-4.3.1-py3-none-any.whl", hash = "sha256:69d1587f0ac18dc7d93fc7e80d5f447161a33e57027e726dc18a0a8bacf1711a", size = 71930, upload-time = "2025-03-22T09:39:05.163Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/2d/174566b533755ddf8efb32a5503af61c756a983de379f8ad3aed6a982d38/bitstring-4.3.1-py3-none-any.whl", hash = "sha256:69d1587f0ac18dc7d93fc7e80d5f447161a33e57027e726dc18a0a8bacf1711a", size = 71930, upload-time = "2025-03-22T09:39:05.163Z" }, ] [[package]] name = "blinker" version = "1.9.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" }, ] [[package]] name = "bracex" version = "2.6" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/63/9a/fec38644694abfaaeca2798b58e276a8e61de49e2e37494ace423395febc/bracex-2.6.tar.gz", hash = "sha256:98f1347cd77e22ee8d967a30ad4e310b233f7754dbf31ff3fceb76145ba47dc7", size = 26642, upload-time = "2025-06-22T19:12:31.254Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/63/9a/fec38644694abfaaeca2798b58e276a8e61de49e2e37494ace423395febc/bracex-2.6.tar.gz", hash = "sha256:98f1347cd77e22ee8d967a30ad4e310b233f7754dbf31ff3fceb76145ba47dc7", size = 26642, upload-time = "2025-06-22T19:12:31.254Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl", hash = "sha256:0b0049264e7340b3ec782b5cb99beb325f36c3782a32e36e876452fd49a09952", size = 11508, upload-time = "2025-06-22T19:12:29.781Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl", hash = "sha256:0b0049264e7340b3ec782b5cb99beb325f36c3782a32e36e876452fd49a09952", size = 11508, upload-time = "2025-06-22T19:12:29.781Z" }, ] [[package]] name = "brotli" version = "1.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2f/c2/f9e977608bdf958650638c3f1e28f85a1b075f075ebbe77db8555463787b/Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724", size = 7372270, upload-time = "2023-09-07T14:05:41.643Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5c/d0/5373ae13b93fe00095a58efcbce837fd470ca39f703a235d2a999baadfbc/Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28", size = 815693, upload-time = "2024-10-18T12:32:23.824Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8e/48/f6e1cdf86751300c288c1459724bfa6917a80e30dbfc326f92cea5d3683a/Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f", size = 422489, upload-time = "2024-10-18T12:32:25.641Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/88/564958cedce636d0f1bed313381dfc4b4e3d3f6015a63dae6146e1b8c65c/Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", size = 873081, upload-time = "2023-09-07T14:03:57.967Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/79/b7026a8bb65da9a6bb7d14329fd2bd48d2b7f86d7329d5cc8ddc6a90526f/Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", size = 446244, upload-time = "2023-09-07T14:03:59.319Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/18/c18c32ecea41b6c0004e15606e274006366fe19436b6adccc1ae7b2e50c2/Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", size = 2906505, upload-time = "2023-09-07T14:04:01.327Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/08/c8/69ec0496b1ada7569b62d85893d928e865df29b90736558d6c98c2031208/Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91", size = 2944152, upload-time = "2023-09-07T14:04:03.033Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ab/fb/0517cea182219d6768113a38167ef6d4eb157a033178cc938033a552ed6d/Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408", size = 2919252, upload-time = "2023-09-07T14:04:04.675Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/53/73a3431662e33ae61a5c80b1b9d2d18f58dfa910ae8dd696e57d39f1a2f5/Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0", size = 2845955, upload-time = "2023-09-07T14:04:06.585Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/55/ac/bd280708d9c5ebdbf9de01459e625a3e3803cce0784f47d633562cf40e83/Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc", size = 2914304, upload-time = "2023-09-07T14:04:08.668Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/76/58/5c391b41ecfc4527d2cc3350719b02e87cb424ef8ba2023fb662f9bf743c/Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", size = 2814452, upload-time = "2023-09-07T14:04:10.736Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/4e/91b8256dfe99c407f174924b65a01f5305e303f486cc7a2e8a5d43c8bec3/Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", size = 2938751, upload-time = "2023-09-07T14:04:12.875Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/a6/e2a39a5d3b412938362bbbeba5af904092bf3f95b867b4a3eb856104074e/Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", size = 2933757, upload-time = "2023-09-07T14:04:14.551Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/13/f0/358354786280a509482e0e77c1a5459e439766597d280f28cb097642fc26/Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9", size = 2936146, upload-time = "2024-10-18T12:32:27.257Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/80/f7/daf538c1060d3a88266b80ecc1d1c98b79553b3f117a485653f17070ea2a/Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb", size = 2848055, upload-time = "2024-10-18T12:32:29.376Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ad/cf/0eaa0585c4077d3c2d1edf322d8e97aabf317941d3a72d7b3ad8bce004b0/Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111", size = 3035102, upload-time = "2024-10-18T12:32:31.371Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/63/1c1585b2aa554fe6dbce30f0c18bdbc877fa9a1bf5ff17677d9cca0ac122/Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839", size = 2930029, upload-time = "2024-10-18T12:32:33.293Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5f/3b/4e3fd1893eb3bbfef8e5a80d4508bec17a57bb92d586c85c12d28666bb13/Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", size = 333276, upload-time = "2023-09-07T14:04:16.49Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/d5/942051b45a9e883b5b6e98c041698b1eb2012d25e5948c58d6bf85b1bb43/Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", size = 357255, upload-time = "2023-09-07T14:04:17.83Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/9f/fb37bb8ffc52a8da37b1c03c459a8cd55df7a57bdccd8831d500e994a0ca/Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5", size = 815681, upload-time = "2024-10-18T12:32:34.942Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/b3/dbd332a988586fefb0aa49c779f59f47cae76855c2d00f450364bb574cac/Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8", size = 422475, upload-time = "2024-10-18T12:32:36.485Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bb/80/6aaddc2f63dbcf2d93c2d204e49c11a9ec93a8c7c63261e2b4bd35198283/Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f", size = 2906173, upload-time = "2024-10-18T12:32:37.978Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/1d/e6ca79c96ff5b641df6097d299347507d39a9604bde8915e76bf026d6c77/Brotli-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648", size = 2943803, upload-time = "2024-10-18T12:32:39.606Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ac/a3/d98d2472e0130b7dd3acdbb7f390d478123dbf62b7d32bda5c830a96116d/Brotli-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0", size = 2918946, upload-time = "2024-10-18T12:32:41.679Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/a5/c69e6d272aee3e1423ed005d8915a7eaa0384c7de503da987f2d224d0721/Brotli-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089", size = 2845707, upload-time = "2024-10-18T12:32:43.478Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/9f/4149d38b52725afa39067350696c09526de0125ebfbaab5acc5af28b42ea/Brotli-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368", size = 2936231, upload-time = "2024-10-18T12:32:45.224Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/5a/145de884285611838a16bebfdb060c231c52b8f84dfbe52b852a15780386/Brotli-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c", size = 2848157, upload-time = "2024-10-18T12:32:46.894Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/ae/408b6bfb8525dadebd3b3dd5b19d631da4f7d46420321db44cd99dcf2f2c/Brotli-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284", size = 3035122, upload-time = "2024-10-18T12:32:48.844Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/af/85/a94e5cfaa0ca449d8f91c3d6f78313ebf919a0dbd55a100c711c6e9655bc/Brotli-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7", size = 2930206, upload-time = "2024-10-18T12:32:51.198Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c2/f0/a61d9262cd01351df22e57ad7c34f66794709acab13f34be2675f45bf89d/Brotli-1.1.0-cp313-cp313-win32.whl", hash = "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0", size = 333804, upload-time = "2024-10-18T12:32:52.661Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7e/c1/ec214e9c94000d1c1974ec67ced1c970c148aa6b8d8373066123fc3dbf06/Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b", size = 358517, upload-time = "2024-10-18T12:32:54.066Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2f/c2/f9e977608bdf958650638c3f1e28f85a1b075f075ebbe77db8555463787b/Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724", size = 7372270, upload-time = "2023-09-07T14:05:41.643Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/d0/5373ae13b93fe00095a58efcbce837fd470ca39f703a235d2a999baadfbc/Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28", size = 815693, upload-time = "2024-10-18T12:32:23.824Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8e/48/f6e1cdf86751300c288c1459724bfa6917a80e30dbfc326f92cea5d3683a/Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f", size = 422489, upload-time = "2024-10-18T12:32:25.641Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/88/564958cedce636d0f1bed313381dfc4b4e3d3f6015a63dae6146e1b8c65c/Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", size = 873081, upload-time = "2023-09-07T14:03:57.967Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/79/b7026a8bb65da9a6bb7d14329fd2bd48d2b7f86d7329d5cc8ddc6a90526f/Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", size = 446244, upload-time = "2023-09-07T14:03:59.319Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/18/c18c32ecea41b6c0004e15606e274006366fe19436b6adccc1ae7b2e50c2/Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", size = 2906505, upload-time = "2023-09-07T14:04:01.327Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/08/c8/69ec0496b1ada7569b62d85893d928e865df29b90736558d6c98c2031208/Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91", size = 2944152, upload-time = "2023-09-07T14:04:03.033Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ab/fb/0517cea182219d6768113a38167ef6d4eb157a033178cc938033a552ed6d/Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408", size = 2919252, upload-time = "2023-09-07T14:04:04.675Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/53/73a3431662e33ae61a5c80b1b9d2d18f58dfa910ae8dd696e57d39f1a2f5/Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0", size = 2845955, upload-time = "2023-09-07T14:04:06.585Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/55/ac/bd280708d9c5ebdbf9de01459e625a3e3803cce0784f47d633562cf40e83/Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc", size = 2914304, upload-time = "2023-09-07T14:04:08.668Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/76/58/5c391b41ecfc4527d2cc3350719b02e87cb424ef8ba2023fb662f9bf743c/Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", size = 2814452, upload-time = "2023-09-07T14:04:10.736Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/4e/91b8256dfe99c407f174924b65a01f5305e303f486cc7a2e8a5d43c8bec3/Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", size = 2938751, upload-time = "2023-09-07T14:04:12.875Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/a6/e2a39a5d3b412938362bbbeba5af904092bf3f95b867b4a3eb856104074e/Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", size = 2933757, upload-time = "2023-09-07T14:04:14.551Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/13/f0/358354786280a509482e0e77c1a5459e439766597d280f28cb097642fc26/Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9", size = 2936146, upload-time = "2024-10-18T12:32:27.257Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/80/f7/daf538c1060d3a88266b80ecc1d1c98b79553b3f117a485653f17070ea2a/Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb", size = 2848055, upload-time = "2024-10-18T12:32:29.376Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ad/cf/0eaa0585c4077d3c2d1edf322d8e97aabf317941d3a72d7b3ad8bce004b0/Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111", size = 3035102, upload-time = "2024-10-18T12:32:31.371Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/63/1c1585b2aa554fe6dbce30f0c18bdbc877fa9a1bf5ff17677d9cca0ac122/Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839", size = 2930029, upload-time = "2024-10-18T12:32:33.293Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/3b/4e3fd1893eb3bbfef8e5a80d4508bec17a57bb92d586c85c12d28666bb13/Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", size = 333276, upload-time = "2023-09-07T14:04:16.49Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/d5/942051b45a9e883b5b6e98c041698b1eb2012d25e5948c58d6bf85b1bb43/Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", size = 357255, upload-time = "2023-09-07T14:04:17.83Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/9f/fb37bb8ffc52a8da37b1c03c459a8cd55df7a57bdccd8831d500e994a0ca/Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5", size = 815681, upload-time = "2024-10-18T12:32:34.942Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/b3/dbd332a988586fefb0aa49c779f59f47cae76855c2d00f450364bb574cac/Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8", size = 422475, upload-time = "2024-10-18T12:32:36.485Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bb/80/6aaddc2f63dbcf2d93c2d204e49c11a9ec93a8c7c63261e2b4bd35198283/Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f", size = 2906173, upload-time = "2024-10-18T12:32:37.978Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/1d/e6ca79c96ff5b641df6097d299347507d39a9604bde8915e76bf026d6c77/Brotli-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648", size = 2943803, upload-time = "2024-10-18T12:32:39.606Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/a3/d98d2472e0130b7dd3acdbb7f390d478123dbf62b7d32bda5c830a96116d/Brotli-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0", size = 2918946, upload-time = "2024-10-18T12:32:41.679Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/a5/c69e6d272aee3e1423ed005d8915a7eaa0384c7de503da987f2d224d0721/Brotli-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089", size = 2845707, upload-time = "2024-10-18T12:32:43.478Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/9f/4149d38b52725afa39067350696c09526de0125ebfbaab5acc5af28b42ea/Brotli-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368", size = 2936231, upload-time = "2024-10-18T12:32:45.224Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/5a/145de884285611838a16bebfdb060c231c52b8f84dfbe52b852a15780386/Brotli-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c", size = 2848157, upload-time = "2024-10-18T12:32:46.894Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/ae/408b6bfb8525dadebd3b3dd5b19d631da4f7d46420321db44cd99dcf2f2c/Brotli-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284", size = 3035122, upload-time = "2024-10-18T12:32:48.844Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/af/85/a94e5cfaa0ca449d8f91c3d6f78313ebf919a0dbd55a100c711c6e9655bc/Brotli-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7", size = 2930206, upload-time = "2024-10-18T12:32:51.198Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/f0/a61d9262cd01351df22e57ad7c34f66794709acab13f34be2675f45bf89d/Brotli-1.1.0-cp313-cp313-win32.whl", hash = "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0", size = 333804, upload-time = "2024-10-18T12:32:52.661Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/c1/ec214e9c94000d1c1974ec67ced1c970c148aa6b8d8373066123fc3dbf06/Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b", size = 358517, upload-time = "2024-10-18T12:32:54.066Z" }, ] [[package]] name = "cachetools" version = "6.2.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bc/1d/ede8680603f6016887c062a2cf4fc8fdba905866a3ab8831aa8aa651320c/cachetools-6.2.4.tar.gz", hash = "sha256:82c5c05585e70b6ba2d3ae09ea60b79548872185d2f24ae1f2709d37299fd607", size = 31731, upload-time = "2025-12-15T18:24:53.744Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bc/1d/ede8680603f6016887c062a2cf4fc8fdba905866a3ab8831aa8aa651320c/cachetools-6.2.4.tar.gz", hash = "sha256:82c5c05585e70b6ba2d3ae09ea60b79548872185d2f24ae1f2709d37299fd607", size = 31731, upload-time = "2025-12-15T18:24:53.744Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/fc/1d7b80d0eb7b714984ce40efc78859c022cd930e402f599d8ca9e39c78a4/cachetools-6.2.4-py3-none-any.whl", hash = "sha256:69a7a52634fed8b8bf6e24a050fb60bff1c9bd8f6d24572b99c32d4e71e62a51", size = 11551, upload-time = "2025-12-15T18:24:52.332Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/fc/1d7b80d0eb7b714984ce40efc78859c022cd930e402f599d8ca9e39c78a4/cachetools-6.2.4-py3-none-any.whl", hash = "sha256:69a7a52634fed8b8bf6e24a050fb60bff1c9bd8f6d24572b99c32d4e71e62a51", size = 11551, upload-time = "2025-12-15T18:24:52.332Z" }, ] [[package]] name = "capstone" version = "5.0.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/27/45/d811f0f3b345c8882b9179f7e310f222ba6af45f0cc729028cbf35c6ce03/capstone-5.0.3.tar.gz", hash = "sha256:1f15616c0528f5268f2dc0a81708483e605ce71961b02a01a791230b51fe862d", size = 2943858, upload-time = "2024-08-20T15:20:08.044Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/27/45/d811f0f3b345c8882b9179f7e310f222ba6af45f0cc729028cbf35c6ce03/capstone-5.0.3.tar.gz", hash = "sha256:1f15616c0528f5268f2dc0a81708483e605ce71961b02a01a791230b51fe862d", size = 2943858, upload-time = "2024-08-20T15:20:08.044Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cc/40/503cdbc0b38c5b8b5bcad47ae507b70cecbb18365a82470a46f425788061/capstone-5.0.3-py3-none-macosx_10_9_universal2.whl", hash = "sha256:5dc6b5f4d85a2ba2330473529d7b4faccd71470b489fd19a539c20b74f3c9924", size = 2176874, upload-time = "2024-08-20T15:19:44.511Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/60/3f/89f13db42cd24af1c80831b6ac978a8a42ad860a35cc461ec009c281e8f3/capstone-5.0.3-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:5917b00ddb0b3a665bcb7a623ee08bcaf4ddec783c5d2ca69f72278d6de38d2c", size = 1180331, upload-time = "2024-08-20T15:19:46.149Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/36/79/ddc8a36238791e58ec31a13c10887447b56819d934ab00d6e1371a2e94f1/capstone-5.0.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:76658b66a5f0275c942cd4daf35dca7520387689f588f127020c9130d76c4ddf", size = 1192365, upload-time = "2024-08-20T15:19:47.535Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/22/bc/39d69c65b7d58157d0c3acad9b929a3f0852c84e44b0e25b6fb89a9e1a7d/capstone-5.0.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:237fef7e20906bad09286554c7f8a5a744adeec4d658c5e33938bf9241b5f076", size = 2829855, upload-time = "2024-08-20T15:19:49.353Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/24/f4/ae2d072d39664b7c32da9c8877f7d204692565f7c844da10e70c47730191/capstone-5.0.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b7f3ec2346a60475d9d043b437ace5e6688fc9c4d45387476104bd2c231040", size = 2921407, upload-time = "2024-08-20T15:19:51.186Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/1b/1b200d7a32de3b2bf61ee0316385aa566d698d20af99d8e2e00e5ec4b144/capstone-5.0.3-py3-none-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f25e23052d5fa5b6709f7111d7f1250131fb5dac878b8249a4637e6ab953129", size = 2941774, upload-time = "2024-08-20T15:19:53.736Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/82/dd45915b0de636ef949b9d56bd529ae52987d74db1c2d2b7feb4dee322f6/capstone-5.0.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:aebb35f0cfb808aac24d2e3c745be43bcedbb863ecb0192d720faa8002983544", size = 2840714, upload-time = "2024-08-20T15:19:59.593Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6b/e0/d3b617dd552a802760d63e29392c217266505f531c799f4b4cf3e9906eef/capstone-5.0.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8d45fdf4ae11197234eedbd81742bd4650924f9bb3abee0b238ea63dad8001cc", size = 2937106, upload-time = "2024-08-20T15:20:02.066Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/00/88/3459e1124a7c1bdc02fa2870ffeecdd0fa2be2b4b3382732cd3e3b2e92f2/capstone-5.0.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:63e8544d7500b889a5feb6f7c9a939723663107dd3360ad18f36a3f6985cfd26", size = 2895850, upload-time = "2024-08-20T15:20:04.166Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/35/29/f751bb52b73b0a2e6414ad4e9271fa0cba966e747c1f3351a9c46e9f1ca7/capstone-5.0.3-py3-none-win_amd64.whl", hash = "sha256:21d00dce9dc204a22126fe6f45a8894d03a6607182bc86f14fc9bd1d1d3897ed", size = 1270430, upload-time = "2024-08-20T15:20:06.092Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/40/503cdbc0b38c5b8b5bcad47ae507b70cecbb18365a82470a46f425788061/capstone-5.0.3-py3-none-macosx_10_9_universal2.whl", hash = "sha256:5dc6b5f4d85a2ba2330473529d7b4faccd71470b489fd19a539c20b74f3c9924", size = 2176874, upload-time = "2024-08-20T15:19:44.511Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/60/3f/89f13db42cd24af1c80831b6ac978a8a42ad860a35cc461ec009c281e8f3/capstone-5.0.3-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:5917b00ddb0b3a665bcb7a623ee08bcaf4ddec783c5d2ca69f72278d6de38d2c", size = 1180331, upload-time = "2024-08-20T15:19:46.149Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/36/79/ddc8a36238791e58ec31a13c10887447b56819d934ab00d6e1371a2e94f1/capstone-5.0.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:76658b66a5f0275c942cd4daf35dca7520387689f588f127020c9130d76c4ddf", size = 1192365, upload-time = "2024-08-20T15:19:47.535Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/bc/39d69c65b7d58157d0c3acad9b929a3f0852c84e44b0e25b6fb89a9e1a7d/capstone-5.0.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:237fef7e20906bad09286554c7f8a5a744adeec4d658c5e33938bf9241b5f076", size = 2829855, upload-time = "2024-08-20T15:19:49.353Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/24/f4/ae2d072d39664b7c32da9c8877f7d204692565f7c844da10e70c47730191/capstone-5.0.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b7f3ec2346a60475d9d043b437ace5e6688fc9c4d45387476104bd2c231040", size = 2921407, upload-time = "2024-08-20T15:19:51.186Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/1b/1b200d7a32de3b2bf61ee0316385aa566d698d20af99d8e2e00e5ec4b144/capstone-5.0.3-py3-none-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f25e23052d5fa5b6709f7111d7f1250131fb5dac878b8249a4637e6ab953129", size = 2941774, upload-time = "2024-08-20T15:19:53.736Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/82/dd45915b0de636ef949b9d56bd529ae52987d74db1c2d2b7feb4dee322f6/capstone-5.0.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:aebb35f0cfb808aac24d2e3c745be43bcedbb863ecb0192d720faa8002983544", size = 2840714, upload-time = "2024-08-20T15:19:59.593Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6b/e0/d3b617dd552a802760d63e29392c217266505f531c799f4b4cf3e9906eef/capstone-5.0.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8d45fdf4ae11197234eedbd81742bd4650924f9bb3abee0b238ea63dad8001cc", size = 2937106, upload-time = "2024-08-20T15:20:02.066Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/00/88/3459e1124a7c1bdc02fa2870ffeecdd0fa2be2b4b3382732cd3e3b2e92f2/capstone-5.0.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:63e8544d7500b889a5feb6f7c9a939723663107dd3360ad18f36a3f6985cfd26", size = 2895850, upload-time = "2024-08-20T15:20:04.166Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/35/29/f751bb52b73b0a2e6414ad4e9271fa0cba966e747c1f3351a9c46e9f1ca7/capstone-5.0.3-py3-none-win_amd64.whl", hash = "sha256:21d00dce9dc204a22126fe6f45a8894d03a6607182bc86f14fc9bd1d1d3897ed", size = 1270430, upload-time = "2024-08-20T15:20:06.092Z" }, ] [[package]] name = "cart" version = "1.2.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pycryptodome" }, ] wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/de/38/9180e61177d57840a6431784f26a291dc01d8fa32f3a58087919e27c95cd/cart-1.2.3-py2.py3-none-any.whl", hash = "sha256:32a1f16a5b521e077a540b98942e74d3ae04fba58be3c658f7b7c14dcef1a53f", size = 10449, upload-time = "2025-02-10T17:14:42.402Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/de/38/9180e61177d57840a6431784f26a291dc01d8fa32f3a58087919e27c95cd/cart-1.2.3-py2.py3-none-any.whl", hash = "sha256:32a1f16a5b521e077a540b98942e74d3ae04fba58be3c658f7b7c14dcef1a53f", size = 10449, upload-time = "2025-02-10T17:14:42.402Z" }, ] [[package]] name = "certifi" version = "2025.11.12" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a2/8c/58f469717fa48465e4a50c014a0400602d3c437d7c0c468e17ada824da3a/certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316", size = 160538, upload-time = "2025-11-12T02:54:51.517Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/8c/58f469717fa48465e4a50c014a0400602d3c437d7c0c468e17ada824da3a/certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316", size = 160538, upload-time = "2025-11-12T02:54:51.517Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, ] [[package]] name = "cffi" version = "2.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pycparser", marker = "implementation_name != 'PyPy'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, ] [[package]] name = "cfgv" version = "3.5.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, ] [[package]] name = "chardet" version = "5.2.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618, upload-time = "2023-08-01T19:23:02.662Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618, upload-time = "2023-08-01T19:23:02.662Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385, upload-time = "2023-08-01T19:23:00.661Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385, upload-time = "2023-08-01T19:23:00.661Z" }, ] [[package]] name = "charset-normalizer" version = "3.4.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, ] [[package]] name = "claripy" version = "9.2.191" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cachetools" }, { name = "typing-extensions" }, { name = "z3-solver" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/e3/0eb13ac36149adf962a8e87f96a2e6aaa73a26486375c84d0755361adf4e/claripy-9.2.191.tar.gz", hash = "sha256:34151964784e884f6f1474be62e7e263f9952bb5b55fc53c6174cd1a0d551252", size = 147144, upload-time = "2025-12-30T17:44:28.253Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/e3/0eb13ac36149adf962a8e87f96a2e6aaa73a26486375c84d0755361adf4e/claripy-9.2.191.tar.gz", hash = "sha256:34151964784e884f6f1474be62e7e263f9952bb5b55fc53c6174cd1a0d551252", size = 147144, upload-time = "2025-12-30T17:44:28.253Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6c/00/d8e47b281dc75c0ac6e1cfbe32913e4d3bbd617f494dd080be2502a5bbbf/claripy-9.2.191-py3-none-any.whl", hash = "sha256:159d98d761c900f605e4491ac92681161347fe7b2c901d75da7db9d5d2246d63", size = 141513, upload-time = "2025-12-30T17:43:30.493Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6c/00/d8e47b281dc75c0ac6e1cfbe32913e4d3bbd617f494dd080be2502a5bbbf/claripy-9.2.191-py3-none-any.whl", hash = "sha256:159d98d761c900f605e4491ac92681161347fe7b2c901d75da7db9d5d2246d63", size = 141513, upload-time = "2025-12-30T17:43:30.493Z" }, ] [[package]] name = "cle" version = "9.2.191" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "archinfo" }, { name = "arpy" }, @@ -687,152 +678,152 @@ dependencies = [ { name = "sortedcontainers" }, { name = "uefi-firmware" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b9/08/114d1375d30da242fb37d07cd9bbd7845219ce68f68f9bd9045122981bed/cle-9.2.191.tar.gz", hash = "sha256:f0cf9b46b663292c944f8a0bc9d61cc88b0c31a52381d839f11ea16dec0195ee", size = 199791, upload-time = "2025-12-30T17:44:29.553Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/08/114d1375d30da242fb37d07cd9bbd7845219ce68f68f9bd9045122981bed/cle-9.2.191.tar.gz", hash = "sha256:f0cf9b46b663292c944f8a0bc9d61cc88b0c31a52381d839f11ea16dec0195ee", size = 199791, upload-time = "2025-12-30T17:44:29.553Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1f/b2/0469ca9b121f71d64e43b1dcb348099dcc71f6061ab87f22314f02b00cf2/cle-9.2.191-py3-none-any.whl", hash = "sha256:d82a46a102b162b803e0a07fd00ea725335f03c2773b4b4ba6c6f5c8f4832751", size = 204019, upload-time = "2025-12-30T17:43:31.745Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1f/b2/0469ca9b121f71d64e43b1dcb348099dcc71f6061ab87f22314f02b00cf2/cle-9.2.191-py3-none-any.whl", hash = "sha256:d82a46a102b162b803e0a07fd00ea725335f03c2773b4b4ba6c6f5c8f4832751", size = 204019, upload-time = "2025-12-30T17:43:31.745Z" }, ] [[package]] name = "click" version = "8.3.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, ] [[package]] name = "cloudpickle" version = "3.1.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/27/fb/576f067976d320f5f0114a8d9fa1215425441bb35627b1993e5afd8111e5/cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414", size = 22330, upload-time = "2025-11-03T09:25:26.604Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/27/fb/576f067976d320f5f0114a8d9fa1215425441bb35627b1993e5afd8111e5/cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414", size = 22330, upload-time = "2025-11-03T09:25:26.604Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a", size = 22228, upload-time = "2025-11-03T09:25:25.534Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a", size = 22228, upload-time = "2025-11-03T09:25:25.534Z" }, ] [[package]] name = "colorama" version = "0.4.6" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/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://mirrors.tuna.tsinghua.edu.cn/pypi/web/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" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/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]] name = "coverage" version = "7.13.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/23/f9/e92df5e07f3fc8d4c7f9a0f146ef75446bf870351cd37b788cf5897f8079/coverage-7.13.1.tar.gz", hash = "sha256:b7593fe7eb5feaa3fbb461ac79aac9f9fc0387a5ca8080b0c6fe2ca27b091afd", size = 825862, upload-time = "2025-12-28T15:42:56.969Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/8a/87af46cccdfa78f53db747b09f5f9a21d5fc38d796834adac09b30a8ce74/coverage-7.13.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6f34591000f06e62085b1865c9bc5f7858df748834662a51edadfd2c3bfe0dd3", size = 218927, upload-time = "2025-12-28T15:40:52.814Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/82/a8/6e22fdc67242a4a5a153f9438d05944553121c8f4ba70cb072af4c41362e/coverage-7.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b67e47c5595b9224599016e333f5ec25392597a89d5744658f837d204e16c63e", size = 219288, upload-time = "2025-12-28T15:40:54.262Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d0/0a/853a76e03b0f7c4375e2ca025df45c918beb367f3e20a0a8e91967f6e96c/coverage-7.13.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e7b8bd70c48ffb28461ebe092c2345536fb18bbbf19d287c8913699735f505c", size = 250786, upload-time = "2025-12-28T15:40:56.059Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/b4/694159c15c52b9f7ec7adf49d50e5f8ee71d3e9ef38adb4445d13dd56c20/coverage-7.13.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c223d078112e90dc0e5c4e35b98b9584164bea9fbbd221c0b21c5241f6d51b62", size = 253543, upload-time = "2025-12-28T15:40:57.585Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/96/b2/7f1f0437a5c855f87e17cf5d0dc35920b6440ff2b58b1ba9788c059c26c8/coverage-7.13.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:794f7c05af0763b1bbd1b9e6eff0e52ad068be3b12cd96c87de037b01390c968", size = 254635, upload-time = "2025-12-28T15:40:59.443Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/d1/73c3fdb8d7d3bddd9473c9c6a2e0682f09fc3dfbcb9c3f36412a7368bcab/coverage-7.13.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0642eae483cc8c2902e4af7298bf886d605e80f26382124cddc3967c2a3df09e", size = 251202, upload-time = "2025-12-28T15:41:01.328Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/66/3c/f0edf75dcc152f145d5598329e864bbbe04ab78660fe3e8e395f9fff010f/coverage-7.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9f5e772ed5fef25b3de9f2008fe67b92d46831bd2bc5bdc5dd6bfd06b83b316f", size = 252566, upload-time = "2025-12-28T15:41:03.319Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/17/b3/e64206d3c5f7dcbceafd14941345a754d3dbc78a823a6ed526e23b9cdaab/coverage-7.13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:45980ea19277dc0a579e432aef6a504fe098ef3a9032ead15e446eb0f1191aee", size = 250711, upload-time = "2025-12-28T15:41:06.411Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/ad/28a3eb970a8ef5b479ee7f0c484a19c34e277479a5b70269dc652b730733/coverage-7.13.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f18eca6028ffa62adbd185a8f1e1dd242f2e68164dba5c2b74a5204850b4cf", size = 250278, upload-time = "2025-12-28T15:41:08.285Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/e3/c8f0f1a93133e3e1291ca76cbb63565bd4b5c5df63b141f539d747fff348/coverage-7.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8dca5590fec7a89ed6826fce625595279e586ead52e9e958d3237821fbc750c", size = 252154, upload-time = "2025-12-28T15:41:09.969Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d0/bf/9939c5d6859c380e405b19e736321f1c7d402728792f4c752ad1adcce005/coverage-7.13.1-cp312-cp312-win32.whl", hash = "sha256:ff86d4e85188bba72cfb876df3e11fa243439882c55957184af44a35bd5880b7", size = 221487, upload-time = "2025-12-28T15:41:11.468Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fa/dc/7282856a407c621c2aad74021680a01b23010bb8ebf427cf5eacda2e876f/coverage-7.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:16cc1da46c04fb0fb128b4dc430b78fa2aba8a6c0c9f8eb391fd5103409a6ac6", size = 222299, upload-time = "2025-12-28T15:41:13.386Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/10/79/176a11203412c350b3e9578620013af35bcdb79b651eb976f4a4b32044fa/coverage-7.13.1-cp312-cp312-win_arm64.whl", hash = "sha256:8d9bc218650022a768f3775dd7fdac1886437325d8d295d923ebcfef4892ad5c", size = 220941, upload-time = "2025-12-28T15:41:14.975Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a3/a4/e98e689347a1ff1a7f67932ab535cef82eb5e78f32a9e4132e114bbb3a0a/coverage-7.13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb237bfd0ef4d5eb6a19e29f9e528ac67ac3be932ea6b44fb6cc09b9f3ecff78", size = 218951, upload-time = "2025-12-28T15:41:16.653Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/32/33/7cbfe2bdc6e2f03d6b240d23dc45fdaf3fd270aaf2d640be77b7f16989ab/coverage-7.13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1dcb645d7e34dcbcc96cd7c132b1fc55c39263ca62eb961c064eb3928997363b", size = 219325, upload-time = "2025-12-28T15:41:18.609Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/f6/efdabdb4929487baeb7cb2a9f7dac457d9356f6ad1b255be283d58b16316/coverage-7.13.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3d42df8201e00384736f0df9be2ced39324c3907607d17d50d50116c989d84cd", size = 250309, upload-time = "2025-12-28T15:41:20.629Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/12/da/91a52516e9d5aea87d32d1523f9cdcf7a35a3b298e6be05d6509ba3cfab2/coverage-7.13.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa3edde1aa8807de1d05934982416cb3ec46d1d4d91e280bcce7cca01c507992", size = 252907, upload-time = "2025-12-28T15:41:22.257Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/38/f1ea837e3dc1231e086db1638947e00d264e7e8c41aa8ecacf6e1e0c05f4/coverage-7.13.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9edd0e01a343766add6817bc448408858ba6b489039eaaa2018474e4001651a4", size = 254148, upload-time = "2025-12-28T15:41:23.87Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/43/f4f16b881aaa34954ba446318dea6b9ed5405dd725dd8daac2358eda869a/coverage-7.13.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:985b7836931d033570b94c94713c6dba5f9d3ff26045f72c3e5dbc5fe3361e5a", size = 250515, upload-time = "2025-12-28T15:41:25.437Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/84/34/8cba7f00078bd468ea914134e0144263194ce849ec3baad187ffb6203d1c/coverage-7.13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ffed1e4980889765c84a5d1a566159e363b71d6b6fbaf0bebc9d3c30bc016766", size = 252292, upload-time = "2025-12-28T15:41:28.459Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8c/a4/cffac66c7652d84ee4ac52d3ccb94c015687d3b513f9db04bfcac2ac800d/coverage-7.13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8842af7f175078456b8b17f1b73a0d16a65dcbdc653ecefeb00a56b3c8c298c4", size = 250242, upload-time = "2025-12-28T15:41:30.02Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f4/78/9a64d462263dde416f3c0067efade7b52b52796f489b1037a95b0dc389c9/coverage-7.13.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ccd7a6fca48ca9c131d9b0a2972a581e28b13416fc313fb98b6d24a03ce9a398", size = 250068, upload-time = "2025-12-28T15:41:32.007Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/c8/a8994f5fece06db7c4a97c8fc1973684e178599b42e66280dded0524ef00/coverage-7.13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0403f647055de2609be776965108447deb8e384fe4a553c119e3ff6bfbab4784", size = 251846, upload-time = "2025-12-28T15:41:33.946Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cc/f7/91fa73c4b80305c86598a2d4e54ba22df6bf7d0d97500944af7ef155d9f7/coverage-7.13.1-cp313-cp313-win32.whl", hash = "sha256:549d195116a1ba1e1ae2f5ca143f9777800f6636eab917d4f02b5310d6d73461", size = 221512, upload-time = "2025-12-28T15:41:35.519Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/45/0b/0768b4231d5a044da8f75e097a8714ae1041246bb765d6b5563bab456735/coverage-7.13.1-cp313-cp313-win_amd64.whl", hash = "sha256:5899d28b5276f536fcf840b18b61a9fce23cc3aec1d114c44c07fe94ebeaa500", size = 222321, upload-time = "2025-12-28T15:41:37.371Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9b/b8/bdcb7253b7e85157282450262008f1366aa04663f3e3e4c30436f596c3e2/coverage-7.13.1-cp313-cp313-win_arm64.whl", hash = "sha256:868a2fae76dfb06e87291bcbd4dcbcc778a8500510b618d50496e520bd94d9b9", size = 220949, upload-time = "2025-12-28T15:41:39.553Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/70/52/f2be52cc445ff75ea8397948c96c1b4ee14f7f9086ea62fc929c5ae7b717/coverage-7.13.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:67170979de0dacac3f3097d02b0ad188d8edcea44ccc44aaa0550af49150c7dc", size = 219643, upload-time = "2025-12-28T15:41:41.567Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/47/79/c85e378eaa239e2edec0c5523f71542c7793fe3340954eafb0bc3904d32d/coverage-7.13.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f80e2bb21bfab56ed7405c2d79d34b5dc0bc96c2c1d2a067b643a09fb756c43a", size = 219997, upload-time = "2025-12-28T15:41:43.418Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fe/9b/b1ade8bfb653c0bbce2d6d6e90cc6c254cbb99b7248531cc76253cb4da6d/coverage-7.13.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f83351e0f7dcdb14d7326c3d8d8c4e915fa685cbfdc6281f9470d97a04e9dfe4", size = 261296, upload-time = "2025-12-28T15:41:45.207Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1f/af/ebf91e3e1a2473d523e87e87fd8581e0aa08741b96265730e2d79ce78d8d/coverage-7.13.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb3f6562e89bad0110afbe64e485aac2462efdce6232cdec7862a095dc3412f6", size = 263363, upload-time = "2025-12-28T15:41:47.163Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/8b/fb2423526d446596624ac7fde12ea4262e66f86f5120114c3cfd0bb2befa/coverage-7.13.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77545b5dcda13b70f872c3b5974ac64c21d05e65b1590b441c8560115dc3a0d1", size = 265783, upload-time = "2025-12-28T15:41:49.03Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9b/26/ef2adb1e22674913b89f0fe7490ecadcef4a71fa96f5ced90c60ec358789/coverage-7.13.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4d240d260a1aed814790bbe1f10a5ff31ce6c21bc78f0da4a1e8268d6c80dbd", size = 260508, upload-time = "2025-12-28T15:41:51.035Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/7d/f0f59b3404caf662e7b5346247883887687c074ce67ba453ea08c612b1d5/coverage-7.13.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d2287ac9360dec3837bfdad969963a5d073a09a85d898bd86bea82aa8876ef3c", size = 263357, upload-time = "2025-12-28T15:41:52.631Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1a/b1/29896492b0b1a047604d35d6fa804f12818fa30cdad660763a5f3159e158/coverage-7.13.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0d2c11f3ea4db66b5cbded23b20185c35066892c67d80ec4be4bab257b9ad1e0", size = 260978, upload-time = "2025-12-28T15:41:54.589Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/48/f2/971de1238a62e6f0a4128d37adadc8bb882ee96afbe03ff1570291754629/coverage-7.13.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:3fc6a169517ca0d7ca6846c3c5392ef2b9e38896f61d615cb75b9e7134d4ee1e", size = 259877, upload-time = "2025-12-28T15:41:56.263Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/fc/0474efcbb590ff8628830e9aaec5f1831594874360e3251f1fdec31d07a3/coverage-7.13.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d10a2ed46386e850bb3de503a54f9fe8192e5917fcbb143bfef653a9355e9a53", size = 262069, upload-time = "2025-12-28T15:41:58.093Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/88/4f/3c159b7953db37a7b44c0eab8a95c37d1aa4257c47b4602c04022d5cb975/coverage-7.13.1-cp313-cp313t-win32.whl", hash = "sha256:75a6f4aa904301dab8022397a22c0039edc1f51e90b83dbd4464b8a38dc87842", size = 222184, upload-time = "2025-12-28T15:41:59.763Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/a5/6b57d28f81417f9335774f20679d9d13b9a8fb90cd6160957aa3b54a2379/coverage-7.13.1-cp313-cp313t-win_amd64.whl", hash = "sha256:309ef5706e95e62578cda256b97f5e097916a2c26247c287bbe74794e7150df2", size = 223250, upload-time = "2025-12-28T15:42:01.52Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/81/7c/160796f3b035acfbb58be80e02e484548595aa67e16a6345e7910ace0a38/coverage-7.13.1-cp313-cp313t-win_arm64.whl", hash = "sha256:92f980729e79b5d16d221038dbf2e8f9a9136afa072f9d5d6ed4cb984b126a09", size = 221521, upload-time = "2025-12-28T15:42:03.275Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cc/48/d9f421cb8da5afaa1a64570d9989e00fb7955e6acddc5a12979f7666ef60/coverage-7.13.1-py3-none-any.whl", hash = "sha256:2016745cb3ba554469d02819d78958b571792bb68e31302610e898f80dd3a573", size = 210722, upload-time = "2025-12-28T15:42:54.901Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/23/f9/e92df5e07f3fc8d4c7f9a0f146ef75446bf870351cd37b788cf5897f8079/coverage-7.13.1.tar.gz", hash = "sha256:b7593fe7eb5feaa3fbb461ac79aac9f9fc0387a5ca8080b0c6fe2ca27b091afd", size = 825862, upload-time = "2025-12-28T15:42:56.969Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/8a/87af46cccdfa78f53db747b09f5f9a21d5fc38d796834adac09b30a8ce74/coverage-7.13.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6f34591000f06e62085b1865c9bc5f7858df748834662a51edadfd2c3bfe0dd3", size = 218927, upload-time = "2025-12-28T15:40:52.814Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/82/a8/6e22fdc67242a4a5a153f9438d05944553121c8f4ba70cb072af4c41362e/coverage-7.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b67e47c5595b9224599016e333f5ec25392597a89d5744658f837d204e16c63e", size = 219288, upload-time = "2025-12-28T15:40:54.262Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d0/0a/853a76e03b0f7c4375e2ca025df45c918beb367f3e20a0a8e91967f6e96c/coverage-7.13.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e7b8bd70c48ffb28461ebe092c2345536fb18bbbf19d287c8913699735f505c", size = 250786, upload-time = "2025-12-28T15:40:56.059Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/b4/694159c15c52b9f7ec7adf49d50e5f8ee71d3e9ef38adb4445d13dd56c20/coverage-7.13.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c223d078112e90dc0e5c4e35b98b9584164bea9fbbd221c0b21c5241f6d51b62", size = 253543, upload-time = "2025-12-28T15:40:57.585Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/96/b2/7f1f0437a5c855f87e17cf5d0dc35920b6440ff2b58b1ba9788c059c26c8/coverage-7.13.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:794f7c05af0763b1bbd1b9e6eff0e52ad068be3b12cd96c87de037b01390c968", size = 254635, upload-time = "2025-12-28T15:40:59.443Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/d1/73c3fdb8d7d3bddd9473c9c6a2e0682f09fc3dfbcb9c3f36412a7368bcab/coverage-7.13.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0642eae483cc8c2902e4af7298bf886d605e80f26382124cddc3967c2a3df09e", size = 251202, upload-time = "2025-12-28T15:41:01.328Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/3c/f0edf75dcc152f145d5598329e864bbbe04ab78660fe3e8e395f9fff010f/coverage-7.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9f5e772ed5fef25b3de9f2008fe67b92d46831bd2bc5bdc5dd6bfd06b83b316f", size = 252566, upload-time = "2025-12-28T15:41:03.319Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/17/b3/e64206d3c5f7dcbceafd14941345a754d3dbc78a823a6ed526e23b9cdaab/coverage-7.13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:45980ea19277dc0a579e432aef6a504fe098ef3a9032ead15e446eb0f1191aee", size = 250711, upload-time = "2025-12-28T15:41:06.411Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/ad/28a3eb970a8ef5b479ee7f0c484a19c34e277479a5b70269dc652b730733/coverage-7.13.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f18eca6028ffa62adbd185a8f1e1dd242f2e68164dba5c2b74a5204850b4cf", size = 250278, upload-time = "2025-12-28T15:41:08.285Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/e3/c8f0f1a93133e3e1291ca76cbb63565bd4b5c5df63b141f539d747fff348/coverage-7.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8dca5590fec7a89ed6826fce625595279e586ead52e9e958d3237821fbc750c", size = 252154, upload-time = "2025-12-28T15:41:09.969Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d0/bf/9939c5d6859c380e405b19e736321f1c7d402728792f4c752ad1adcce005/coverage-7.13.1-cp312-cp312-win32.whl", hash = "sha256:ff86d4e85188bba72cfb876df3e11fa243439882c55957184af44a35bd5880b7", size = 221487, upload-time = "2025-12-28T15:41:11.468Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fa/dc/7282856a407c621c2aad74021680a01b23010bb8ebf427cf5eacda2e876f/coverage-7.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:16cc1da46c04fb0fb128b4dc430b78fa2aba8a6c0c9f8eb391fd5103409a6ac6", size = 222299, upload-time = "2025-12-28T15:41:13.386Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/79/176a11203412c350b3e9578620013af35bcdb79b651eb976f4a4b32044fa/coverage-7.13.1-cp312-cp312-win_arm64.whl", hash = "sha256:8d9bc218650022a768f3775dd7fdac1886437325d8d295d923ebcfef4892ad5c", size = 220941, upload-time = "2025-12-28T15:41:14.975Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a3/a4/e98e689347a1ff1a7f67932ab535cef82eb5e78f32a9e4132e114bbb3a0a/coverage-7.13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb237bfd0ef4d5eb6a19e29f9e528ac67ac3be932ea6b44fb6cc09b9f3ecff78", size = 218951, upload-time = "2025-12-28T15:41:16.653Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/32/33/7cbfe2bdc6e2f03d6b240d23dc45fdaf3fd270aaf2d640be77b7f16989ab/coverage-7.13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1dcb645d7e34dcbcc96cd7c132b1fc55c39263ca62eb961c064eb3928997363b", size = 219325, upload-time = "2025-12-28T15:41:18.609Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/f6/efdabdb4929487baeb7cb2a9f7dac457d9356f6ad1b255be283d58b16316/coverage-7.13.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3d42df8201e00384736f0df9be2ced39324c3907607d17d50d50116c989d84cd", size = 250309, upload-time = "2025-12-28T15:41:20.629Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/12/da/91a52516e9d5aea87d32d1523f9cdcf7a35a3b298e6be05d6509ba3cfab2/coverage-7.13.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa3edde1aa8807de1d05934982416cb3ec46d1d4d91e280bcce7cca01c507992", size = 252907, upload-time = "2025-12-28T15:41:22.257Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/38/f1ea837e3dc1231e086db1638947e00d264e7e8c41aa8ecacf6e1e0c05f4/coverage-7.13.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9edd0e01a343766add6817bc448408858ba6b489039eaaa2018474e4001651a4", size = 254148, upload-time = "2025-12-28T15:41:23.87Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/43/f4f16b881aaa34954ba446318dea6b9ed5405dd725dd8daac2358eda869a/coverage-7.13.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:985b7836931d033570b94c94713c6dba5f9d3ff26045f72c3e5dbc5fe3361e5a", size = 250515, upload-time = "2025-12-28T15:41:25.437Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/84/34/8cba7f00078bd468ea914134e0144263194ce849ec3baad187ffb6203d1c/coverage-7.13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ffed1e4980889765c84a5d1a566159e363b71d6b6fbaf0bebc9d3c30bc016766", size = 252292, upload-time = "2025-12-28T15:41:28.459Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8c/a4/cffac66c7652d84ee4ac52d3ccb94c015687d3b513f9db04bfcac2ac800d/coverage-7.13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8842af7f175078456b8b17f1b73a0d16a65dcbdc653ecefeb00a56b3c8c298c4", size = 250242, upload-time = "2025-12-28T15:41:30.02Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f4/78/9a64d462263dde416f3c0067efade7b52b52796f489b1037a95b0dc389c9/coverage-7.13.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ccd7a6fca48ca9c131d9b0a2972a581e28b13416fc313fb98b6d24a03ce9a398", size = 250068, upload-time = "2025-12-28T15:41:32.007Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/c8/a8994f5fece06db7c4a97c8fc1973684e178599b42e66280dded0524ef00/coverage-7.13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0403f647055de2609be776965108447deb8e384fe4a553c119e3ff6bfbab4784", size = 251846, upload-time = "2025-12-28T15:41:33.946Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/f7/91fa73c4b80305c86598a2d4e54ba22df6bf7d0d97500944af7ef155d9f7/coverage-7.13.1-cp313-cp313-win32.whl", hash = "sha256:549d195116a1ba1e1ae2f5ca143f9777800f6636eab917d4f02b5310d6d73461", size = 221512, upload-time = "2025-12-28T15:41:35.519Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/45/0b/0768b4231d5a044da8f75e097a8714ae1041246bb765d6b5563bab456735/coverage-7.13.1-cp313-cp313-win_amd64.whl", hash = "sha256:5899d28b5276f536fcf840b18b61a9fce23cc3aec1d114c44c07fe94ebeaa500", size = 222321, upload-time = "2025-12-28T15:41:37.371Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9b/b8/bdcb7253b7e85157282450262008f1366aa04663f3e3e4c30436f596c3e2/coverage-7.13.1-cp313-cp313-win_arm64.whl", hash = "sha256:868a2fae76dfb06e87291bcbd4dcbcc778a8500510b618d50496e520bd94d9b9", size = 220949, upload-time = "2025-12-28T15:41:39.553Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/70/52/f2be52cc445ff75ea8397948c96c1b4ee14f7f9086ea62fc929c5ae7b717/coverage-7.13.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:67170979de0dacac3f3097d02b0ad188d8edcea44ccc44aaa0550af49150c7dc", size = 219643, upload-time = "2025-12-28T15:41:41.567Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/47/79/c85e378eaa239e2edec0c5523f71542c7793fe3340954eafb0bc3904d32d/coverage-7.13.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f80e2bb21bfab56ed7405c2d79d34b5dc0bc96c2c1d2a067b643a09fb756c43a", size = 219997, upload-time = "2025-12-28T15:41:43.418Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fe/9b/b1ade8bfb653c0bbce2d6d6e90cc6c254cbb99b7248531cc76253cb4da6d/coverage-7.13.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f83351e0f7dcdb14d7326c3d8d8c4e915fa685cbfdc6281f9470d97a04e9dfe4", size = 261296, upload-time = "2025-12-28T15:41:45.207Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1f/af/ebf91e3e1a2473d523e87e87fd8581e0aa08741b96265730e2d79ce78d8d/coverage-7.13.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb3f6562e89bad0110afbe64e485aac2462efdce6232cdec7862a095dc3412f6", size = 263363, upload-time = "2025-12-28T15:41:47.163Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/8b/fb2423526d446596624ac7fde12ea4262e66f86f5120114c3cfd0bb2befa/coverage-7.13.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77545b5dcda13b70f872c3b5974ac64c21d05e65b1590b441c8560115dc3a0d1", size = 265783, upload-time = "2025-12-28T15:41:49.03Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9b/26/ef2adb1e22674913b89f0fe7490ecadcef4a71fa96f5ced90c60ec358789/coverage-7.13.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4d240d260a1aed814790bbe1f10a5ff31ce6c21bc78f0da4a1e8268d6c80dbd", size = 260508, upload-time = "2025-12-28T15:41:51.035Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/7d/f0f59b3404caf662e7b5346247883887687c074ce67ba453ea08c612b1d5/coverage-7.13.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d2287ac9360dec3837bfdad969963a5d073a09a85d898bd86bea82aa8876ef3c", size = 263357, upload-time = "2025-12-28T15:41:52.631Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1a/b1/29896492b0b1a047604d35d6fa804f12818fa30cdad660763a5f3159e158/coverage-7.13.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0d2c11f3ea4db66b5cbded23b20185c35066892c67d80ec4be4bab257b9ad1e0", size = 260978, upload-time = "2025-12-28T15:41:54.589Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/48/f2/971de1238a62e6f0a4128d37adadc8bb882ee96afbe03ff1570291754629/coverage-7.13.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:3fc6a169517ca0d7ca6846c3c5392ef2b9e38896f61d615cb75b9e7134d4ee1e", size = 259877, upload-time = "2025-12-28T15:41:56.263Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/fc/0474efcbb590ff8628830e9aaec5f1831594874360e3251f1fdec31d07a3/coverage-7.13.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d10a2ed46386e850bb3de503a54f9fe8192e5917fcbb143bfef653a9355e9a53", size = 262069, upload-time = "2025-12-28T15:41:58.093Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/88/4f/3c159b7953db37a7b44c0eab8a95c37d1aa4257c47b4602c04022d5cb975/coverage-7.13.1-cp313-cp313t-win32.whl", hash = "sha256:75a6f4aa904301dab8022397a22c0039edc1f51e90b83dbd4464b8a38dc87842", size = 222184, upload-time = "2025-12-28T15:41:59.763Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/a5/6b57d28f81417f9335774f20679d9d13b9a8fb90cd6160957aa3b54a2379/coverage-7.13.1-cp313-cp313t-win_amd64.whl", hash = "sha256:309ef5706e95e62578cda256b97f5e097916a2c26247c287bbe74794e7150df2", size = 223250, upload-time = "2025-12-28T15:42:01.52Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/81/7c/160796f3b035acfbb58be80e02e484548595aa67e16a6345e7910ace0a38/coverage-7.13.1-cp313-cp313t-win_arm64.whl", hash = "sha256:92f980729e79b5d16d221038dbf2e8f9a9136afa072f9d5d6ed4cb984b126a09", size = 221521, upload-time = "2025-12-28T15:42:03.275Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/48/d9f421cb8da5afaa1a64570d9989e00fb7955e6acddc5a12979f7666ef60/coverage-7.13.1-py3-none-any.whl", hash = "sha256:2016745cb3ba554469d02819d78958b571792bb68e31302610e898f80dd3a573", size = 210722, upload-time = "2025-12-28T15:42:54.901Z" }, ] [[package]] name = "cryptography" version = "44.0.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/53/d6/1411ab4d6108ab167d06254c5be517681f1e331f90edf1379895bcb87020/cryptography-44.0.3.tar.gz", hash = "sha256:fe19d8bc5536a91a24a8133328880a41831b6c5df54599a8417b62fe015d3053", size = 711096, upload-time = "2025-05-02T19:36:04.667Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/08/53/c776d80e9d26441bb3868457909b4e74dd9ccabd182e10b2b0ae7a07e265/cryptography-44.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:962bc30480a08d133e631e8dfd4783ab71cc9e33d5d7c1e192f0b7c06397bb88", size = 6670281, upload-time = "2025-05-02T19:34:50.665Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/06/af2cf8d56ef87c77319e9086601bef621bedf40f6f59069e1b6d1ec498c5/cryptography-44.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc61e8f3bf5b60346d89cd3d37231019c17a081208dfbbd6e1605ba03fa137", size = 3959305, upload-time = "2025-05-02T19:34:53.042Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ae/01/80de3bec64627207d030f47bf3536889efee8913cd363e78ca9a09b13c8e/cryptography-44.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58968d331425a6f9eedcee087f77fd3c927c88f55368f43ff7e0a19891f2642c", size = 4171040, upload-time = "2025-05-02T19:34:54.675Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bd/48/bb16b7541d207a19d9ae8b541c70037a05e473ddc72ccb1386524d4f023c/cryptography-44.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e28d62e59a4dbd1d22e747f57d4f00c459af22181f0b2f787ea83f5a876d7c76", size = 3963411, upload-time = "2025-05-02T19:34:56.61Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/42/b2/7d31f2af5591d217d71d37d044ef5412945a8a8e98d5a2a8ae4fd9cd4489/cryptography-44.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af653022a0c25ef2e3ffb2c673a50e5a0d02fecc41608f4954176f1933b12359", size = 3689263, upload-time = "2025-05-02T19:34:58.591Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/50/c0dfb9d87ae88ccc01aad8eb93e23cfbcea6a6a106a9b63a7b14c1f93c75/cryptography-44.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:157f1f3b8d941c2bd8f3ffee0af9b049c9665c39d3da9db2dc338feca5e98a43", size = 4196198, upload-time = "2025-05-02T19:35:00.988Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/66/c9/55c6b8794a74da652690c898cb43906310a3e4e4f6ee0b5f8b3b3e70c441/cryptography-44.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:c6cd67722619e4d55fdb42ead64ed8843d64638e9c07f4011163e46bc512cf01", size = 3966502, upload-time = "2025-05-02T19:35:03.091Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b6/f7/7cb5488c682ca59a02a32ec5f975074084db4c983f849d47b7b67cc8697a/cryptography-44.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b424563394c369a804ecbee9b06dfb34997f19d00b3518e39f83a5642618397d", size = 4196173, upload-time = "2025-05-02T19:35:05.018Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/0b/2f789a8403ae089b0b121f8f54f4a3e5228df756e2146efdf4a09a3d5083/cryptography-44.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c91fc8e8fd78af553f98bc7f2a1d8db977334e4eea302a4bfd75b9461c2d8904", size = 4087713, upload-time = "2025-05-02T19:35:07.187Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1d/aa/330c13655f1af398fc154089295cf259252f0ba5df93b4bc9d9c7d7f843e/cryptography-44.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:25cd194c39fa5a0aa4169125ee27d1172097857b27109a45fadc59653ec06f44", size = 4299064, upload-time = "2025-05-02T19:35:08.879Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/10/a8/8c540a421b44fd267a7d58a1fd5f072a552d72204a3f08194f98889de76d/cryptography-44.0.3-cp37-abi3-win32.whl", hash = "sha256:3be3f649d91cb182c3a6bd336de8b61a0a71965bd13d1a04a0e15b39c3d5809d", size = 2773887, upload-time = "2025-05-02T19:35:10.41Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b9/0d/c4b1657c39ead18d76bbd122da86bd95bdc4095413460d09544000a17d56/cryptography-44.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:3883076d5c4cc56dbef0b898a74eb6992fdac29a7b9013870b34efe4ddb39a0d", size = 3209737, upload-time = "2025-05-02T19:35:12.12Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/34/a3/ad08e0bcc34ad436013458d7528e83ac29910943cea42ad7dd4141a27bbb/cryptography-44.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:5639c2b16764c6f76eedf722dbad9a0914960d3489c0cc38694ddf9464f1bb2f", size = 6673501, upload-time = "2025-05-02T19:35:13.775Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b1/f0/7491d44bba8d28b464a5bc8cc709f25a51e3eac54c0a4444cf2473a57c37/cryptography-44.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ffef566ac88f75967d7abd852ed5f182da252d23fac11b4766da3957766759", size = 3960307, upload-time = "2025-05-02T19:35:15.917Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f7/c8/e5c5d0e1364d3346a5747cdcd7ecbb23ca87e6dea4f942a44e88be349f06/cryptography-44.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:192ed30fac1728f7587c6f4613c29c584abdc565d7417c13904708db10206645", size = 4170876, upload-time = "2025-05-02T19:35:18.138Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/73/96/025cb26fc351d8c7d3a1c44e20cf9a01e9f7cf740353c9c7a17072e4b264/cryptography-44.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7d5fe7195c27c32a64955740b949070f21cba664604291c298518d2e255931d2", size = 3964127, upload-time = "2025-05-02T19:35:19.864Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/01/44/eb6522db7d9f84e8833ba3bf63313f8e257729cf3a8917379473fcfd6601/cryptography-44.0.3-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3f07943aa4d7dad689e3bb1638ddc4944cc5e0921e3c227486daae0e31a05e54", size = 3689164, upload-time = "2025-05-02T19:35:21.449Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/68/fb/d61a4defd0d6cee20b1b8a1ea8f5e25007e26aeb413ca53835f0cae2bcd1/cryptography-44.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb90f60e03d563ca2445099edf605c16ed1d5b15182d21831f58460c48bffb93", size = 4198081, upload-time = "2025-05-02T19:35:23.187Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1b/50/457f6911d36432a8811c3ab8bd5a6090e8d18ce655c22820994913dd06ea/cryptography-44.0.3-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ab0b005721cc0039e885ac3503825661bd9810b15d4f374e473f8c89b7d5460c", size = 3967716, upload-time = "2025-05-02T19:35:25.426Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/35/6e/dca39d553075980ccb631955c47b93d87d27f3596da8d48b1ae81463d915/cryptography-44.0.3-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:3bb0847e6363c037df8f6ede57d88eaf3410ca2267fb12275370a76f85786a6f", size = 4197398, upload-time = "2025-05-02T19:35:27.678Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9b/9d/d1f2fe681eabc682067c66a74addd46c887ebacf39038ba01f8860338d3d/cryptography-44.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b0cc66c74c797e1db750aaa842ad5b8b78e14805a9b5d1348dc603612d3e3ff5", size = 4087900, upload-time = "2025-05-02T19:35:29.312Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/f5/3599e48c5464580b73b236aafb20973b953cd2e7b44c7c2533de1d888446/cryptography-44.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6866df152b581f9429020320e5eb9794c8780e90f7ccb021940d7f50ee00ae0b", size = 4301067, upload-time = "2025-05-02T19:35:31.547Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/6c/d2c48c8137eb39d0c193274db5c04a75dab20d2f7c3f81a7dcc3a8897701/cryptography-44.0.3-cp39-abi3-win32.whl", hash = "sha256:c138abae3a12a94c75c10499f1cbae81294a6f983b3af066390adee73f433028", size = 2775467, upload-time = "2025-05-02T19:35:33.805Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c9/ad/51f212198681ea7b0deaaf8846ee10af99fba4e894f67b353524eab2bbe5/cryptography-44.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:5d186f32e52e66994dce4f766884bcb9c68b8da62d61d9d215bfe5fb56d21334", size = 3210375, upload-time = "2025-05-02T19:35:35.369Z" }, +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/53/d6/1411ab4d6108ab167d06254c5be517681f1e331f90edf1379895bcb87020/cryptography-44.0.3.tar.gz", hash = "sha256:fe19d8bc5536a91a24a8133328880a41831b6c5df54599a8417b62fe015d3053", size = 711096, upload-time = "2025-05-02T19:36:04.667Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/08/53/c776d80e9d26441bb3868457909b4e74dd9ccabd182e10b2b0ae7a07e265/cryptography-44.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:962bc30480a08d133e631e8dfd4783ab71cc9e33d5d7c1e192f0b7c06397bb88", size = 6670281, upload-time = "2025-05-02T19:34:50.665Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/06/af2cf8d56ef87c77319e9086601bef621bedf40f6f59069e1b6d1ec498c5/cryptography-44.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc61e8f3bf5b60346d89cd3d37231019c17a081208dfbbd6e1605ba03fa137", size = 3959305, upload-time = "2025-05-02T19:34:53.042Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ae/01/80de3bec64627207d030f47bf3536889efee8913cd363e78ca9a09b13c8e/cryptography-44.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58968d331425a6f9eedcee087f77fd3c927c88f55368f43ff7e0a19891f2642c", size = 4171040, upload-time = "2025-05-02T19:34:54.675Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bd/48/bb16b7541d207a19d9ae8b541c70037a05e473ddc72ccb1386524d4f023c/cryptography-44.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e28d62e59a4dbd1d22e747f57d4f00c459af22181f0b2f787ea83f5a876d7c76", size = 3963411, upload-time = "2025-05-02T19:34:56.61Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/42/b2/7d31f2af5591d217d71d37d044ef5412945a8a8e98d5a2a8ae4fd9cd4489/cryptography-44.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af653022a0c25ef2e3ffb2c673a50e5a0d02fecc41608f4954176f1933b12359", size = 3689263, upload-time = "2025-05-02T19:34:58.591Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/50/c0dfb9d87ae88ccc01aad8eb93e23cfbcea6a6a106a9b63a7b14c1f93c75/cryptography-44.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:157f1f3b8d941c2bd8f3ffee0af9b049c9665c39d3da9db2dc338feca5e98a43", size = 4196198, upload-time = "2025-05-02T19:35:00.988Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/c9/55c6b8794a74da652690c898cb43906310a3e4e4f6ee0b5f8b3b3e70c441/cryptography-44.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:c6cd67722619e4d55fdb42ead64ed8843d64638e9c07f4011163e46bc512cf01", size = 3966502, upload-time = "2025-05-02T19:35:03.091Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b6/f7/7cb5488c682ca59a02a32ec5f975074084db4c983f849d47b7b67cc8697a/cryptography-44.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b424563394c369a804ecbee9b06dfb34997f19d00b3518e39f83a5642618397d", size = 4196173, upload-time = "2025-05-02T19:35:05.018Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/0b/2f789a8403ae089b0b121f8f54f4a3e5228df756e2146efdf4a09a3d5083/cryptography-44.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c91fc8e8fd78af553f98bc7f2a1d8db977334e4eea302a4bfd75b9461c2d8904", size = 4087713, upload-time = "2025-05-02T19:35:07.187Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1d/aa/330c13655f1af398fc154089295cf259252f0ba5df93b4bc9d9c7d7f843e/cryptography-44.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:25cd194c39fa5a0aa4169125ee27d1172097857b27109a45fadc59653ec06f44", size = 4299064, upload-time = "2025-05-02T19:35:08.879Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/a8/8c540a421b44fd267a7d58a1fd5f072a552d72204a3f08194f98889de76d/cryptography-44.0.3-cp37-abi3-win32.whl", hash = "sha256:3be3f649d91cb182c3a6bd336de8b61a0a71965bd13d1a04a0e15b39c3d5809d", size = 2773887, upload-time = "2025-05-02T19:35:10.41Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/0d/c4b1657c39ead18d76bbd122da86bd95bdc4095413460d09544000a17d56/cryptography-44.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:3883076d5c4cc56dbef0b898a74eb6992fdac29a7b9013870b34efe4ddb39a0d", size = 3209737, upload-time = "2025-05-02T19:35:12.12Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/34/a3/ad08e0bcc34ad436013458d7528e83ac29910943cea42ad7dd4141a27bbb/cryptography-44.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:5639c2b16764c6f76eedf722dbad9a0914960d3489c0cc38694ddf9464f1bb2f", size = 6673501, upload-time = "2025-05-02T19:35:13.775Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/f0/7491d44bba8d28b464a5bc8cc709f25a51e3eac54c0a4444cf2473a57c37/cryptography-44.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ffef566ac88f75967d7abd852ed5f182da252d23fac11b4766da3957766759", size = 3960307, upload-time = "2025-05-02T19:35:15.917Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f7/c8/e5c5d0e1364d3346a5747cdcd7ecbb23ca87e6dea4f942a44e88be349f06/cryptography-44.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:192ed30fac1728f7587c6f4613c29c584abdc565d7417c13904708db10206645", size = 4170876, upload-time = "2025-05-02T19:35:18.138Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/73/96/025cb26fc351d8c7d3a1c44e20cf9a01e9f7cf740353c9c7a17072e4b264/cryptography-44.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7d5fe7195c27c32a64955740b949070f21cba664604291c298518d2e255931d2", size = 3964127, upload-time = "2025-05-02T19:35:19.864Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/01/44/eb6522db7d9f84e8833ba3bf63313f8e257729cf3a8917379473fcfd6601/cryptography-44.0.3-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3f07943aa4d7dad689e3bb1638ddc4944cc5e0921e3c227486daae0e31a05e54", size = 3689164, upload-time = "2025-05-02T19:35:21.449Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/68/fb/d61a4defd0d6cee20b1b8a1ea8f5e25007e26aeb413ca53835f0cae2bcd1/cryptography-44.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb90f60e03d563ca2445099edf605c16ed1d5b15182d21831f58460c48bffb93", size = 4198081, upload-time = "2025-05-02T19:35:23.187Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1b/50/457f6911d36432a8811c3ab8bd5a6090e8d18ce655c22820994913dd06ea/cryptography-44.0.3-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ab0b005721cc0039e885ac3503825661bd9810b15d4f374e473f8c89b7d5460c", size = 3967716, upload-time = "2025-05-02T19:35:25.426Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/35/6e/dca39d553075980ccb631955c47b93d87d27f3596da8d48b1ae81463d915/cryptography-44.0.3-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:3bb0847e6363c037df8f6ede57d88eaf3410ca2267fb12275370a76f85786a6f", size = 4197398, upload-time = "2025-05-02T19:35:27.678Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9b/9d/d1f2fe681eabc682067c66a74addd46c887ebacf39038ba01f8860338d3d/cryptography-44.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b0cc66c74c797e1db750aaa842ad5b8b78e14805a9b5d1348dc603612d3e3ff5", size = 4087900, upload-time = "2025-05-02T19:35:29.312Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/f5/3599e48c5464580b73b236aafb20973b953cd2e7b44c7c2533de1d888446/cryptography-44.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6866df152b581f9429020320e5eb9794c8780e90f7ccb021940d7f50ee00ae0b", size = 4301067, upload-time = "2025-05-02T19:35:31.547Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/6c/d2c48c8137eb39d0c193274db5c04a75dab20d2f7c3f81a7dcc3a8897701/cryptography-44.0.3-cp39-abi3-win32.whl", hash = "sha256:c138abae3a12a94c75c10499f1cbae81294a6f983b3af066390adee73f433028", size = 2775467, upload-time = "2025-05-02T19:35:33.805Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c9/ad/51f212198681ea7b0deaaf8846ee10af99fba4e894f67b353524eab2bbe5/cryptography-44.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:5d186f32e52e66994dce4f766884bcb9c68b8da62d61d9d215bfe5fb56d21334", size = 3210375, upload-time = "2025-05-02T19:35:35.369Z" }, ] [[package]] name = "cxxheaderparser" version = "1.6.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/88/bcb6400315da0df5f18197a285863d7da99bfec02a46c91df95a225df18f/cxxheaderparser-1.6.2.tar.gz", hash = "sha256:4574f09908609a7bf5d93841fae6e677b803e9708f564ae599382c1f0e18c7ed", size = 52562, upload-time = "2025-12-16T05:02:14.048Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/88/bcb6400315da0df5f18197a285863d7da99bfec02a46c91df95a225df18f/cxxheaderparser-1.6.2.tar.gz", hash = "sha256:4574f09908609a7bf5d93841fae6e677b803e9708f564ae599382c1f0e18c7ed", size = 52562, upload-time = "2025-12-16T05:02:14.048Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/3b/ef8c9839b958b853f9a081de7a2a8c48c4f73b00269cf1048e009727c032/cxxheaderparser-1.6.2-py3-none-any.whl", hash = "sha256:92aae2b45cb96e4bb5b4be392cca73afef439f06d612c5da3a9cab6d7a13e4ae", size = 58935, upload-time = "2025-12-16T05:02:12.433Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/3b/ef8c9839b958b853f9a081de7a2a8c48c4f73b00269cf1048e009727c032/cxxheaderparser-1.6.2-py3-none-any.whl", hash = "sha256:92aae2b45cb96e4bb5b4be392cca73afef439f06d612c5da3a9cab6d7a13e4ae", size = 58935, upload-time = "2025-12-16T05:02:12.433Z" }, ] [[package]] name = "cyclopts" version = "4.4.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "attrs" }, { name = "docstring-parser" }, { name = "rich" }, { name = "rich-rst" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8f/21/732453ae69d65d72fe37a34f8b1a455c72313b8b0a905b876da20ff7e81a/cyclopts-4.4.3.tar.gz", hash = "sha256:03797c71b49a39dcad8324d6655363056fb998e2ba0240940050331a7f63fe65", size = 159360, upload-time = "2025-12-28T18:57:03.831Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8f/21/732453ae69d65d72fe37a34f8b1a455c72313b8b0a905b876da20ff7e81a/cyclopts-4.4.3.tar.gz", hash = "sha256:03797c71b49a39dcad8324d6655363056fb998e2ba0240940050331a7f63fe65", size = 159360, upload-time = "2025-12-28T18:57:03.831Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8b/28/03f9b8fbf396b3f2eaf65a7ff441ba2fb7dd397109d563a4e556dc5b3efb/cyclopts-4.4.3-py3-none-any.whl", hash = "sha256:951611a9d4d88d9916716ae281faca9af1cb79b88bb4f22bd0192cff54e7dec6", size = 196707, upload-time = "2025-12-28T18:57:04.884Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8b/28/03f9b8fbf396b3f2eaf65a7ff441ba2fb7dd397109d563a4e556dc5b3efb/cyclopts-4.4.3-py3-none-any.whl", hash = "sha256:951611a9d4d88d9916716ae281faca9af1cb79b88bb4f22bd0192cff54e7dec6", size = 196707, upload-time = "2025-12-28T18:57:04.884Z" }, ] [[package]] name = "deepagents" version = "0.4.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "langchain" }, { name = "langchain-anthropic" }, @@ -840,127 +831,127 @@ dependencies = [ { name = "langchain-google-genai" }, { name = "wcmatch" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b2/ac/895c5efe77ee64f38af64146509b97220867fc149a9a376b2c74f266fd45/deepagents-0.4.0.tar.gz", hash = "sha256:ccfbb2394d2c50a3cf6f61457c5c1d3868354beee2177a57b8497c72c38f8e9b", size = 77614, upload-time = "2026-02-10T16:31:16.99Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/ac/895c5efe77ee64f38af64146509b97220867fc149a9a376b2c74f266fd45/deepagents-0.4.0.tar.gz", hash = "sha256:ccfbb2394d2c50a3cf6f61457c5c1d3868354beee2177a57b8497c72c38f8e9b", size = 77614, upload-time = "2026-02-10T16:31:16.99Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/c8/cbedac42e011889f151047cf22dbecef9a38330c2e90e517c2bd1b1e636d/deepagents-0.4.0-py3-none-any.whl", hash = "sha256:475af99429c7b6abe4c53d476d6b48f01960dc1bcaec7fa21093189acdfc2864", size = 87831, upload-time = "2026-02-10T16:31:15.596Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/c8/cbedac42e011889f151047cf22dbecef9a38330c2e90e517c2bd1b1e636d/deepagents-0.4.0-py3-none-any.whl", hash = "sha256:475af99429c7b6abe4c53d476d6b48f01960dc1bcaec7fa21093189acdfc2864", size = 87831, upload-time = "2026-02-10T16:31:15.596Z" }, ] [[package]] name = "diskcache" version = "5.6.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3f/21/1c1ffc1a039ddcc459db43cc108658f32c57d271d7289a2794e401d0fdb6/diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3f/21/1c1ffc1a039ddcc459db43cc108658f32c57d271d7289a2794e401d0fdb6/diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3f/27/4570e78fc0bf5ea0ca45eb1de3818a23787af9b390c0b0a0033a1b8236f9/diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3f/27/4570e78fc0bf5ea0ca45eb1de3818a23787af9b390c0b0a0033a1b8236f9/diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19" }, ] [[package]] name = "distlib" version = "0.4.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, ] [[package]] name = "distro" version = "1.9.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, ] [[package]] name = "dnspython" version = "2.8.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, ] [[package]] name = "docker" version = "7.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pywin32", marker = "sys_platform == 'win32'" }, { name = "requests" }, { name = "urllib3" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" }, ] [[package]] name = "docstring-parser" version = "0.17.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b2/9d/c3b43da9515bd270df0f80548d9944e389870713cc1fe2b8fb35fe2bcefd/docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", size = 27442, upload-time = "2025-07-21T07:35:01.868Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/9d/c3b43da9515bd270df0f80548d9944e389870713cc1fe2b8fb35fe2bcefd/docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", size = 27442, upload-time = "2025-07-21T07:35:01.868Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload-time = "2025-07-21T07:35:00.684Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size = 36896, upload-time = "2025-07-21T07:35:00.684Z" }, ] [[package]] name = "docutils" version = "0.22.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, ] [[package]] name = "ecdsa" version = "0.19.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "six" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c0/1f/924e3caae75f471eae4b26bd13b698f6af2c44279f67af317439c2f4c46a/ecdsa-0.19.1.tar.gz", hash = "sha256:478cba7b62555866fcb3bb3fe985e06decbdb68ef55713c4e5ab98c57d508e61", size = 201793, upload-time = "2025-03-13T11:52:43.25Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/1f/924e3caae75f471eae4b26bd13b698f6af2c44279f67af317439c2f4c46a/ecdsa-0.19.1.tar.gz", hash = "sha256:478cba7b62555866fcb3bb3fe985e06decbdb68ef55713c4e5ab98c57d508e61", size = 201793, upload-time = "2025-03-13T11:52:43.25Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/a3/460c57f094a4a165c84a1341c373b0a4f5ec6ac244b998d5021aade89b77/ecdsa-0.19.1-py2.py3-none-any.whl", hash = "sha256:30638e27cf77b7e15c4c4cc1973720149e1033827cfd00661ca5c8cc0cdb24c3", size = 150607, upload-time = "2025-03-13T11:52:41.757Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/a3/460c57f094a4a165c84a1341c373b0a4f5ec6ac244b998d5021aade89b77/ecdsa-0.19.1-py2.py3-none-any.whl", hash = "sha256:30638e27cf77b7e15c4c4cc1973720149e1033827cfd00661ca5c8cc0cdb24c3", size = 150607, upload-time = "2025-03-13T11:52:41.757Z" }, ] [[package]] name = "email-validator" version = "2.3.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "dnspython" }, { name = "idna" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" }, ] [[package]] name = "exceptiongroup" version = "1.3.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] [[package]] name = "fakeredis" version = "2.33.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "redis" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5f/f9/57464119936414d60697fcbd32f38909bb5688b616ae13de6e98384433e0/fakeredis-2.33.0.tar.gz", hash = "sha256:d7bc9a69d21df108a6451bbffee23b3eba432c21a654afc7ff2d295428ec5770", size = 175187, upload-time = "2025-12-16T19:45:52.269Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/f9/57464119936414d60697fcbd32f38909bb5688b616ae13de6e98384433e0/fakeredis-2.33.0.tar.gz", hash = "sha256:d7bc9a69d21df108a6451bbffee23b3eba432c21a654afc7ff2d295428ec5770", size = 175187, upload-time = "2025-12-16T19:45:52.269Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/78/a850fed8aeef96d4a99043c90b818b2ed5419cd5b24a4049fd7cfb9f1471/fakeredis-2.33.0-py3-none-any.whl", hash = "sha256:de535f3f9ccde1c56672ab2fdd6a8efbc4f2619fc2f1acc87b8737177d71c965", size = 119605, upload-time = "2025-12-16T19:45:51.08Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/78/a850fed8aeef96d4a99043c90b818b2ed5419cd5b24a4049fd7cfb9f1471/fakeredis-2.33.0-py3-none-any.whl", hash = "sha256:de535f3f9ccde1c56672ab2fdd6a8efbc4f2619fc2f1acc87b8737177d71c965", size = 119605, upload-time = "2025-12-16T19:45:51.08Z" }, ] [package.optional-dependencies] @@ -971,16 +962,16 @@ lua = [ [[package]] name = "fastapi" version = "0.128.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "annotated-doc" }, { name = "pydantic" }, { name = "starlette" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/52/08/8c8508db6c7b9aae8f7175046af41baad690771c9bcde676419965e338c7/fastapi-0.128.0.tar.gz", hash = "sha256:1cc179e1cef10a6be60ffe429f79b829dce99d8de32d7acb7e6c8dfdf7f2645a", size = 365682, upload-time = "2025-12-27T15:21:13.714Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/52/08/8c8508db6c7b9aae8f7175046af41baad690771c9bcde676419965e338c7/fastapi-0.128.0.tar.gz", hash = "sha256:1cc179e1cef10a6be60ffe429f79b829dce99d8de32d7acb7e6c8dfdf7f2645a", size = 365682, upload-time = "2025-12-27T15:21:13.714Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5c/05/5cbb59154b093548acd0f4c7c474a118eda06da25aa75c616b72d8fcd92a/fastapi-0.128.0-py3-none-any.whl", hash = "sha256:aebd93f9716ee3b4f4fcfe13ffb7cf308d99c9f3ab5622d8877441072561582d", size = 103094, upload-time = "2025-12-27T15:21:12.154Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/05/5cbb59154b093548acd0f4c7c474a118eda06da25aa75c616b72d8fcd92a/fastapi-0.128.0-py3-none-any.whl", hash = "sha256:aebd93f9716ee3b4f4fcfe13ffb7cf308d99c9f3ab5622d8877441072561582d", size = 103094, upload-time = "2025-12-27T15:21:12.154Z" }, ] [package.optional-dependencies] @@ -998,15 +989,15 @@ standard = [ [[package]] name = "fastapi-cli" version = "0.0.20" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "rich-toolkit" }, { name = "typer" }, { name = "uvicorn", extra = ["standard"] }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d3/ca/d90fb3bfbcbd6e56c77afd9d114dd6ce8955d8bb90094399d1c70e659e40/fastapi_cli-0.0.20.tar.gz", hash = "sha256:d17c2634f7b96b6b560bc16b0035ed047d523c912011395f49f00a421692bc3a", size = 19786, upload-time = "2025-12-22T17:13:33.794Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d3/ca/d90fb3bfbcbd6e56c77afd9d114dd6ce8955d8bb90094399d1c70e659e40/fastapi_cli-0.0.20.tar.gz", hash = "sha256:d17c2634f7b96b6b560bc16b0035ed047d523c912011395f49f00a421692bc3a", size = 19786, upload-time = "2025-12-22T17:13:33.794Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/08/89/5c4eef60524d0fd704eb0706885b82cd5623a43396b94e4a5b17d3a3f516/fastapi_cli-0.0.20-py3-none-any.whl", hash = "sha256:e58b6a0038c0b1532b7a0af690656093dee666201b6b19d3c87175b358e9f783", size = 12390, upload-time = "2025-12-22T17:13:31.708Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/08/89/5c4eef60524d0fd704eb0706885b82cd5623a43396b94e4a5b17d3a3f516/fastapi_cli-0.0.20-py3-none-any.whl", hash = "sha256:e58b6a0038c0b1532b7a0af690656093dee666201b6b19d3c87175b358e9f783", size = 12390, upload-time = "2025-12-22T17:13:31.708Z" }, ] [package.optional-dependencies] @@ -1018,7 +1009,7 @@ standard = [ [[package]] name = "fastapi-cloud-cli" version = "0.11.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "fastar" }, { name = "httpx" }, @@ -1029,53 +1020,53 @@ dependencies = [ { name = "typer" }, { name = "uvicorn", extra = ["standard"] }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/11/15/6c3d85d63964340fde6f36cc80f3f365d35f371e6a918d68ff3a3d588ef2/fastapi_cloud_cli-0.11.0.tar.gz", hash = "sha256:ecc83a5db106be35af528eccb01aa9bced1d29783efd48c8c1c831cf111eea99", size = 36170, upload-time = "2026-01-15T09:51:33.681Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/11/15/6c3d85d63964340fde6f36cc80f3f365d35f371e6a918d68ff3a3d588ef2/fastapi_cloud_cli-0.11.0.tar.gz", hash = "sha256:ecc83a5db106be35af528eccb01aa9bced1d29783efd48c8c1c831cf111eea99", size = 36170, upload-time = "2026-01-15T09:51:33.681Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1a/07/60f79270a3320780be7e2ae8a1740cb98a692920b569ba420b97bcc6e175/fastapi_cloud_cli-0.11.0-py3-none-any.whl", hash = "sha256:76857b0f09d918acfcb50ade34682ba3b2079ca0c43fda10215de301f185a7f8", size = 26884, upload-time = "2026-01-15T09:51:34.471Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1a/07/60f79270a3320780be7e2ae8a1740cb98a692920b569ba420b97bcc6e175/fastapi_cloud_cli-0.11.0-py3-none-any.whl", hash = "sha256:76857b0f09d918acfcb50ade34682ba3b2079ca0c43fda10215de301f185a7f8", size = 26884, upload-time = "2026-01-15T09:51:34.471Z" }, ] [[package]] name = "fastar" version = "0.8.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/e7/f89d54fb04104114dd0552836dc2b47914f416cc0e200b409dd04a33de5e/fastar-0.8.0.tar.gz", hash = "sha256:f4d4d68dbf1c4c2808f0e730fac5843493fc849f70fe3ad3af60dfbaf68b9a12", size = 68524, upload-time = "2025-11-26T02:36:00.72Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/f1/5b2ff898abac7f1a418284aad285e3a4f68d189c572ab2db0f6c9079dd16/fastar-0.8.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f10d2adfe40f47ff228f4efaa32d409d732ded98580e03ed37c9535b5fc923d", size = 706369, upload-time = "2025-11-26T02:34:37.783Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/23/60/8046a386dca39154f80c927cbbeeb4b1c1267a3271bffe61552eb9995757/fastar-0.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b930da9d598e3bc69513d131f397e6d6be4643926ef3de5d33d1e826631eb036", size = 629097, upload-time = "2025-11-26T02:34:21.888Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/22/7e/1ae005addc789924a9268da2394d3bb5c6f96836f7e37b7e3d23c2362675/fastar-0.8.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9d210da2de733ca801de83e931012349d209f38b92d9630ccaa94bd445bdc9b8", size = 868938, upload-time = "2025-11-26T02:33:51.119Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a6/77/290a892b073b84bf82e6b2259708dfe79c54f356e252c2dd40180b16fe07/fastar-0.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa02270721517078a5bd61a38719070ac2537a4aa6b6c48cf369cf2abc59174a", size = 765204, upload-time = "2025-11-26T02:32:47.02Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d0/00/c3155171b976003af3281f5258189f1935b15d1221bfc7467b478c631216/fastar-0.8.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:83c391e5b789a720e4d0029b9559f5d6dee3226693c5b39c0eab8eaece997e0f", size = 764717, upload-time = "2025-11-26T02:33:02.453Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b7/43/405b7ad76207b2c11b7b59335b70eac19e4a2653977f5588a1ac8fed54f4/fastar-0.8.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3258d7a78a72793cdd081545da61cabe85b1f37634a1d0b97ffee0ff11d105ef", size = 931502, upload-time = "2025-11-26T02:33:18.619Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/8a/a3dde6d37cc3da4453f2845cdf16675b5686b73b164f37e2cc579b057c2c/fastar-0.8.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6eab95dd985cdb6a50666cbeb9e4814676e59cfe52039c880b69d67cfd44767", size = 821454, upload-time = "2025-11-26T02:33:33.427Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/c1/904fe2468609c8990dce9fe654df3fbc7324a8d8e80d8240ae2c89757064/fastar-0.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:829b1854166141860887273c116c94e31357213fa8e9fe8baeb18bd6c38aa8d9", size = 821647, upload-time = "2025-11-26T02:34:07Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c8/73/a0642ab7a400bc07528091785e868ace598fde06fcd139b8f865ec1b6f3c/fastar-0.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b1667eae13f9457a3c737f4376d68e8c3e548353538b28f7e4273a30cb3965cd", size = 986342, upload-time = "2025-11-26T02:34:53.371Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/af/af/60c1bfa6edab72366461a95f053d0f5f7ab1825fe65ca2ca367432cd8629/fastar-0.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b864a95229a7db0814cd9ef7987cb713fd43dce1b0d809dd17d9cd6f02fdde3e", size = 1040207, upload-time = "2025-11-26T02:35:10.65Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f6/a0/0d624290dec622e7fa084b6881f456809f68777d54a314f5dde932714506/fastar-0.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c05fbc5618ce17675a42576fa49858d79734627f0a0c74c0875ab45ee8de340c", size = 1045031, upload-time = "2025-11-26T02:35:28.108Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/74/cf663af53c4706ba88e6b4af44a6b0c3bd7d7ca09f079dc40647a8f06585/fastar-0.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7f41c51ee96f338662ee3c3df4840511ba3f9969606840f1b10b7cb633a3c716", size = 994877, upload-time = "2025-11-26T02:35:45.797Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/52/17/444c8be6e77206050e350da7c338102b6cab384be937fa0b1d6d1f9ede73/fastar-0.8.0-cp312-cp312-win32.whl", hash = "sha256:d949a1a2ea7968b734632c009df0571c94636a5e1622c87a6e2bf712a7334f47", size = 455996, upload-time = "2025-11-26T02:36:26.938Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/34/fc3b5e56d71a17b1904800003d9251716e8fd65f662e1b10a26881698a74/fastar-0.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:fc645994d5b927d769121094e8a649b09923b3c13a8b0b98696d8f853f23c532", size = 490429, upload-time = "2025-11-26T02:36:12.707Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/35/a8/5608cc837417107c594e2e7be850b9365bcb05e99645966a5d6a156285fe/fastar-0.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:d81ee82e8dc78a0adb81728383bd39611177d642a8fa2d601d4ad5ad59e5f3bd", size = 461297, upload-time = "2025-11-26T02:36:03.546Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/a5/79ecba3646e22d03eef1a66fb7fc156567213e2e4ab9faab3bbd4489e483/fastar-0.8.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:a3253a06845462ca2196024c7a18f5c0ba4de1532ab1c4bad23a40b332a06a6a", size = 706112, upload-time = "2025-11-26T02:34:39.237Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/03/4f883bce878218a8676c2d7ca09b50c856a5470bb3b7f63baf9521ea6995/fastar-0.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5cbeb3ebfa0980c68ff8b126295cc6b208ccd81b638aebc5a723d810a7a0e5d2", size = 628954, upload-time = "2025-11-26T02:34:23.705Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4f/f1/892e471f156b03d10ba48ace9384f5a896702a54506137462545f38e40b8/fastar-0.8.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1c0d5956b917daac77d333d48b3f0f3ff927b8039d5b32d8125462782369f761", size = 868685, upload-time = "2025-11-26T02:33:53.077Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/39/ba/e24915045852e30014ec6840446975c03f4234d1c9270394b51d3ad18394/fastar-0.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27b404db2b786b65912927ce7f3790964a4bcbde42cdd13091b82a89cd655e1c", size = 765044, upload-time = "2025-11-26T02:32:48.187Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/14/2c/1aa11ac21a99984864c2fca4994e094319ff3a2046e7a0343c39317bd5b9/fastar-0.8.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0902fc89dcf1e7f07b8563032a4159fe2b835e4c16942c76fd63451d0e5f76a3", size = 764322, upload-time = "2025-11-26T02:33:03.859Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/f0/4b91902af39fe2d3bae7c85c6d789586b9fbcf618d7fdb3d37323915906d/fastar-0.8.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:069347e2f0f7a8b99bbac8cd1bc0e06c7b4a31dc964fc60d84b95eab3d869dc1", size = 931016, upload-time = "2025-11-26T02:33:19.902Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c9/97/8fc43a5a9c0a2dc195730f6f7a0f367d171282cd8be2511d0e87c6d2dad0/fastar-0.8.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd135306f6bfe9a835918280e0eb440b70ab303e0187d90ab51ca86e143f70d", size = 821308, upload-time = "2025-11-26T02:33:34.664Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0c/e9/058615b63a7fd27965e8c5966f393ed0c169f7ff5012e1674f21684de3ba/fastar-0.8.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d06d6897f43c27154b5f2d0eb930a43a81b7eec73f6f0b0114814d4a10ab38", size = 821171, upload-time = "2025-11-26T02:34:08.498Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ca/cf/69e16a17961570a755c37ffb5b5aa7610d2e77807625f537989da66f2a9d/fastar-0.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a922f8439231fa0c32b15e8d70ff6d415619b9d40492029dabbc14a0c53b5f18", size = 986227, upload-time = "2025-11-26T02:34:55.06Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fb/83/2100192372e59b56f4ace37d7d9cabda511afd71b5febad1643d1c334271/fastar-0.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a739abd51eb766384b4caff83050888e80cd75bbcfec61e6d1e64875f94e4a40", size = 1039395, upload-time = "2025-11-26T02:35:12.166Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/15/cdd03aca972f55872efbb7cf7540c3fa7b97a75d626303a3ea46932163dc/fastar-0.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5a65f419d808b23ac89d5cd1b13a2f340f15bc5d1d9af79f39fdb77bba48ff1b", size = 1044766, upload-time = "2025-11-26T02:35:29.62Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/29/945e69e4e2652329ace545999334ec31f1431fbae3abb0105587e11af2ae/fastar-0.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7bb2ae6c0cce58f0db1c9f20495e7557cca2c1ee9c69bbd90eafd54f139171c5", size = 994740, upload-time = "2025-11-26T02:35:47.887Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4b/5d/dbfe28f8cd1eb484bba0c62e5259b2cf6fea229d6ef43e05c06b5a78c034/fastar-0.8.0-cp313-cp313-win32.whl", hash = "sha256:b28753e0d18a643272597cb16d39f1053842aa43131ad3e260c03a2417d38401", size = 455990, upload-time = "2025-11-26T02:36:28.502Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e1/01/e965740bd36e60ef4c5aa2cbe42b6c4eb1dc3551009238a97c2e5e96bd23/fastar-0.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:620e5d737dce8321d49a5ebb7997f1fd0047cde3512082c27dc66d6ac8c1927a", size = 490227, upload-time = "2025-11-26T02:36:14.363Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dd/10/c99202719b83e5249f26902ae53a05aea67d840eeb242019322f20fc171c/fastar-0.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:c4c4bd08df563120cd33e854fe0a93b81579e8571b11f9b7da9e84c37da2d6b6", size = 461078, upload-time = "2025-11-26T02:36:04.94Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/e7/f89d54fb04104114dd0552836dc2b47914f416cc0e200b409dd04a33de5e/fastar-0.8.0.tar.gz", hash = "sha256:f4d4d68dbf1c4c2808f0e730fac5843493fc849f70fe3ad3af60dfbaf68b9a12", size = 68524, upload-time = "2025-11-26T02:36:00.72Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/f1/5b2ff898abac7f1a418284aad285e3a4f68d189c572ab2db0f6c9079dd16/fastar-0.8.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f10d2adfe40f47ff228f4efaa32d409d732ded98580e03ed37c9535b5fc923d", size = 706369, upload-time = "2025-11-26T02:34:37.783Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/23/60/8046a386dca39154f80c927cbbeeb4b1c1267a3271bffe61552eb9995757/fastar-0.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b930da9d598e3bc69513d131f397e6d6be4643926ef3de5d33d1e826631eb036", size = 629097, upload-time = "2025-11-26T02:34:21.888Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/7e/1ae005addc789924a9268da2394d3bb5c6f96836f7e37b7e3d23c2362675/fastar-0.8.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9d210da2de733ca801de83e931012349d209f38b92d9630ccaa94bd445bdc9b8", size = 868938, upload-time = "2025-11-26T02:33:51.119Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a6/77/290a892b073b84bf82e6b2259708dfe79c54f356e252c2dd40180b16fe07/fastar-0.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa02270721517078a5bd61a38719070ac2537a4aa6b6c48cf369cf2abc59174a", size = 765204, upload-time = "2025-11-26T02:32:47.02Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d0/00/c3155171b976003af3281f5258189f1935b15d1221bfc7467b478c631216/fastar-0.8.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:83c391e5b789a720e4d0029b9559f5d6dee3226693c5b39c0eab8eaece997e0f", size = 764717, upload-time = "2025-11-26T02:33:02.453Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/43/405b7ad76207b2c11b7b59335b70eac19e4a2653977f5588a1ac8fed54f4/fastar-0.8.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3258d7a78a72793cdd081545da61cabe85b1f37634a1d0b97ffee0ff11d105ef", size = 931502, upload-time = "2025-11-26T02:33:18.619Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/8a/a3dde6d37cc3da4453f2845cdf16675b5686b73b164f37e2cc579b057c2c/fastar-0.8.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6eab95dd985cdb6a50666cbeb9e4814676e59cfe52039c880b69d67cfd44767", size = 821454, upload-time = "2025-11-26T02:33:33.427Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/c1/904fe2468609c8990dce9fe654df3fbc7324a8d8e80d8240ae2c89757064/fastar-0.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:829b1854166141860887273c116c94e31357213fa8e9fe8baeb18bd6c38aa8d9", size = 821647, upload-time = "2025-11-26T02:34:07Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c8/73/a0642ab7a400bc07528091785e868ace598fde06fcd139b8f865ec1b6f3c/fastar-0.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b1667eae13f9457a3c737f4376d68e8c3e548353538b28f7e4273a30cb3965cd", size = 986342, upload-time = "2025-11-26T02:34:53.371Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/af/af/60c1bfa6edab72366461a95f053d0f5f7ab1825fe65ca2ca367432cd8629/fastar-0.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b864a95229a7db0814cd9ef7987cb713fd43dce1b0d809dd17d9cd6f02fdde3e", size = 1040207, upload-time = "2025-11-26T02:35:10.65Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f6/a0/0d624290dec622e7fa084b6881f456809f68777d54a314f5dde932714506/fastar-0.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c05fbc5618ce17675a42576fa49858d79734627f0a0c74c0875ab45ee8de340c", size = 1045031, upload-time = "2025-11-26T02:35:28.108Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/74/cf663af53c4706ba88e6b4af44a6b0c3bd7d7ca09f079dc40647a8f06585/fastar-0.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7f41c51ee96f338662ee3c3df4840511ba3f9969606840f1b10b7cb633a3c716", size = 994877, upload-time = "2025-11-26T02:35:45.797Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/52/17/444c8be6e77206050e350da7c338102b6cab384be937fa0b1d6d1f9ede73/fastar-0.8.0-cp312-cp312-win32.whl", hash = "sha256:d949a1a2ea7968b734632c009df0571c94636a5e1622c87a6e2bf712a7334f47", size = 455996, upload-time = "2025-11-26T02:36:26.938Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/34/fc3b5e56d71a17b1904800003d9251716e8fd65f662e1b10a26881698a74/fastar-0.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:fc645994d5b927d769121094e8a649b09923b3c13a8b0b98696d8f853f23c532", size = 490429, upload-time = "2025-11-26T02:36:12.707Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/35/a8/5608cc837417107c594e2e7be850b9365bcb05e99645966a5d6a156285fe/fastar-0.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:d81ee82e8dc78a0adb81728383bd39611177d642a8fa2d601d4ad5ad59e5f3bd", size = 461297, upload-time = "2025-11-26T02:36:03.546Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/a5/79ecba3646e22d03eef1a66fb7fc156567213e2e4ab9faab3bbd4489e483/fastar-0.8.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:a3253a06845462ca2196024c7a18f5c0ba4de1532ab1c4bad23a40b332a06a6a", size = 706112, upload-time = "2025-11-26T02:34:39.237Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/03/4f883bce878218a8676c2d7ca09b50c856a5470bb3b7f63baf9521ea6995/fastar-0.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5cbeb3ebfa0980c68ff8b126295cc6b208ccd81b638aebc5a723d810a7a0e5d2", size = 628954, upload-time = "2025-11-26T02:34:23.705Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4f/f1/892e471f156b03d10ba48ace9384f5a896702a54506137462545f38e40b8/fastar-0.8.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1c0d5956b917daac77d333d48b3f0f3ff927b8039d5b32d8125462782369f761", size = 868685, upload-time = "2025-11-26T02:33:53.077Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/ba/e24915045852e30014ec6840446975c03f4234d1c9270394b51d3ad18394/fastar-0.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27b404db2b786b65912927ce7f3790964a4bcbde42cdd13091b82a89cd655e1c", size = 765044, upload-time = "2025-11-26T02:32:48.187Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/2c/1aa11ac21a99984864c2fca4994e094319ff3a2046e7a0343c39317bd5b9/fastar-0.8.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0902fc89dcf1e7f07b8563032a4159fe2b835e4c16942c76fd63451d0e5f76a3", size = 764322, upload-time = "2025-11-26T02:33:03.859Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/f0/4b91902af39fe2d3bae7c85c6d789586b9fbcf618d7fdb3d37323915906d/fastar-0.8.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:069347e2f0f7a8b99bbac8cd1bc0e06c7b4a31dc964fc60d84b95eab3d869dc1", size = 931016, upload-time = "2025-11-26T02:33:19.902Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c9/97/8fc43a5a9c0a2dc195730f6f7a0f367d171282cd8be2511d0e87c6d2dad0/fastar-0.8.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd135306f6bfe9a835918280e0eb440b70ab303e0187d90ab51ca86e143f70d", size = 821308, upload-time = "2025-11-26T02:33:34.664Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0c/e9/058615b63a7fd27965e8c5966f393ed0c169f7ff5012e1674f21684de3ba/fastar-0.8.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d06d6897f43c27154b5f2d0eb930a43a81b7eec73f6f0b0114814d4a10ab38", size = 821171, upload-time = "2025-11-26T02:34:08.498Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/cf/69e16a17961570a755c37ffb5b5aa7610d2e77807625f537989da66f2a9d/fastar-0.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a922f8439231fa0c32b15e8d70ff6d415619b9d40492029dabbc14a0c53b5f18", size = 986227, upload-time = "2025-11-26T02:34:55.06Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fb/83/2100192372e59b56f4ace37d7d9cabda511afd71b5febad1643d1c334271/fastar-0.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a739abd51eb766384b4caff83050888e80cd75bbcfec61e6d1e64875f94e4a40", size = 1039395, upload-time = "2025-11-26T02:35:12.166Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/15/cdd03aca972f55872efbb7cf7540c3fa7b97a75d626303a3ea46932163dc/fastar-0.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5a65f419d808b23ac89d5cd1b13a2f340f15bc5d1d9af79f39fdb77bba48ff1b", size = 1044766, upload-time = "2025-11-26T02:35:29.62Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/29/945e69e4e2652329ace545999334ec31f1431fbae3abb0105587e11af2ae/fastar-0.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7bb2ae6c0cce58f0db1c9f20495e7557cca2c1ee9c69bbd90eafd54f139171c5", size = 994740, upload-time = "2025-11-26T02:35:47.887Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4b/5d/dbfe28f8cd1eb484bba0c62e5259b2cf6fea229d6ef43e05c06b5a78c034/fastar-0.8.0-cp313-cp313-win32.whl", hash = "sha256:b28753e0d18a643272597cb16d39f1053842aa43131ad3e260c03a2417d38401", size = 455990, upload-time = "2025-11-26T02:36:28.502Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e1/01/e965740bd36e60ef4c5aa2cbe42b6c4eb1dc3551009238a97c2e5e96bd23/fastar-0.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:620e5d737dce8321d49a5ebb7997f1fd0047cde3512082c27dc66d6ac8c1927a", size = 490227, upload-time = "2025-11-26T02:36:14.363Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dd/10/c99202719b83e5249f26902ae53a05aea67d840eeb242019322f20fc171c/fastar-0.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:c4c4bd08df563120cd33e854fe0a93b81579e8571b11f9b7da9e84c37da2d6b6", size = 461078, upload-time = "2025-11-26T02:36:04.94Z" }, ] [[package]] name = "fastmcp" version = "2.14.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "authlib" }, { name = "cyclopts" }, @@ -1094,33 +1085,33 @@ dependencies = [ { name = "uvicorn" }, { name = "websockets" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9e/50/d38e4371bdc34e709f4731b1e882cb7bc50e51c1a224859d4cd381b3a79b/fastmcp-2.14.1.tar.gz", hash = "sha256:132725cbf77b68fa3c3d165eff0cfa47e40c1479457419e6a2cfda65bd84c8d6", size = 8263331, upload-time = "2025-12-15T02:26:27.102Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9e/50/d38e4371bdc34e709f4731b1e882cb7bc50e51c1a224859d4cd381b3a79b/fastmcp-2.14.1.tar.gz", hash = "sha256:132725cbf77b68fa3c3d165eff0cfa47e40c1479457419e6a2cfda65bd84c8d6", size = 8263331, upload-time = "2025-12-15T02:26:27.102Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1d/82/72401d09dc27c27fdf72ad6c2fe331e553e3c3646e01b5ff16473191033d/fastmcp-2.14.1-py3-none-any.whl", hash = "sha256:fb3e365cc1d52573ab89caeba9944dd4b056149097be169bce428e011f0a57e5", size = 412176, upload-time = "2025-12-15T02:26:25.356Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1d/82/72401d09dc27c27fdf72ad6c2fe331e553e3c3646e01b5ff16473191033d/fastmcp-2.14.1-py3-none-any.whl", hash = "sha256:fb3e365cc1d52573ab89caeba9944dd4b056149097be169bce428e011f0a57e5", size = 412176, upload-time = "2025-12-15T02:26:25.356Z" }, ] [[package]] name = "filelock" version = "3.20.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/23/ce7a1126827cedeb958fc043d61745754464eb56c5937c35bbf2b8e26f34/filelock-3.20.1.tar.gz", hash = "sha256:b8360948b351b80f420878d8516519a2204b07aefcdcfd24912a5d33127f188c", size = 19476, upload-time = "2025-12-15T23:54:28.027Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/23/ce7a1126827cedeb958fc043d61745754464eb56c5937c35bbf2b8e26f34/filelock-3.20.1.tar.gz", hash = "sha256:b8360948b351b80f420878d8516519a2204b07aefcdcfd24912a5d33127f188c", size = 19476, upload-time = "2025-12-15T23:54:28.027Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e3/7f/a1a97644e39e7316d850784c642093c99df1290a460df4ede27659056834/filelock-3.20.1-py3-none-any.whl", hash = "sha256:15d9e9a67306188a44baa72f569d2bfd803076269365fdea0934385da4dc361a", size = 16666, upload-time = "2025-12-15T23:54:26.874Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/7f/a1a97644e39e7316d850784c642093c99df1290a460df4ede27659056834/filelock-3.20.1-py3-none-any.whl", hash = "sha256:15d9e9a67306188a44baa72f569d2bfd803076269365fdea0934385da4dc361a", size = 16666, upload-time = "2025-12-15T23:54:26.874Z" }, ] [[package]] name = "filetype" version = "1.2.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bb/29/745f7d30d47fe0f251d3ad3dc2978a23141917661998763bebb6da007eb1/filetype-1.2.0.tar.gz", hash = "sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb", size = 998020, upload-time = "2022-11-02T17:34:04.141Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bb/29/745f7d30d47fe0f251d3ad3dc2978a23141917661998763bebb6da007eb1/filetype-1.2.0.tar.gz", hash = "sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb", size = 998020, upload-time = "2022-11-02T17:34:04.141Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/18/79/1b8fa1bb3568781e84c9200f951c735f3f157429f44be0495da55894d620/filetype-1.2.0-py2.py3-none-any.whl", hash = "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25", size = 19970, upload-time = "2022-11-02T17:34:01.425Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/79/1b8fa1bb3568781e84c9200f951c735f3f157429f44be0495da55894d620/filetype-1.2.0-py2.py3-none-any.whl", hash = "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25", size = 19970, upload-time = "2022-11-02T17:34:01.425Z" }, ] [[package]] name = "flask" version = "3.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "blinker" }, { name = "click" }, @@ -1128,113 +1119,113 @@ dependencies = [ { name = "jinja2" }, { name = "werkzeug" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/50/dff6380f1c7f84135484e176e0cac8690af72fa90e932ad2a0a60e28c69b/flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac", size = 680824, upload-time = "2024-11-13T18:24:38.127Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/50/dff6380f1c7f84135484e176e0cac8690af72fa90e932ad2a0a60e28c69b/flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac", size = 680824, upload-time = "2024-11-13T18:24:38.127Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/af/47/93213ee66ef8fae3b93b3e29206f6b251e65c97bd91d8e1c5596ef15af0a/flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136", size = 102979, upload-time = "2024-11-13T18:24:36.135Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/af/47/93213ee66ef8fae3b93b3e29206f6b251e65c97bd91d8e1c5596ef15af0a/flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136", size = 102979, upload-time = "2024-11-13T18:24:36.135Z" }, ] [[package]] name = "frozenlist" version = "1.8.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, ] [[package]] name = "future" version = "1.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/b2/4140c69c6a66432916b26158687e821ba631a4c9273c474343badf84d3ba/future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05", size = 1228490, upload-time = "2024-02-21T11:52:38.461Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/b2/4140c69c6a66432916b26158687e821ba631a4c9273c474343badf84d3ba/future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05", size = 1228490, upload-time = "2024-02-21T11:52:38.461Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216", size = 491326, upload-time = "2024-02-21T11:52:35.956Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216", size = 491326, upload-time = "2024-02-21T11:52:35.956Z" }, ] [[package]] name = "gitdb" version = "4.0.12" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "smmap" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/72/94/63b0fc47eb32792c7ba1fe1b694daec9a63620db1e313033d18140c2320a/gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571", size = 394684, upload-time = "2025-01-02T07:20:46.413Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/94/63b0fc47eb32792c7ba1fe1b694daec9a63620db1e313033d18140c2320a/gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571", size = 394684, upload-time = "2025-01-02T07:20:46.413Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf", size = 62794, upload-time = "2025-01-02T07:20:43.624Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf", size = 62794, upload-time = "2025-01-02T07:20:43.624Z" }, ] [[package]] name = "gitpython" version = "3.1.45" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "gitdb" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/c8/dd58967d119baab745caec2f9d853297cec1989ec1d63f677d3880632b88/gitpython-3.1.45.tar.gz", hash = "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c", size = 215076, upload-time = "2025-07-24T03:45:54.871Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/c8/dd58967d119baab745caec2f9d853297cec1989ec1d63f677d3880632b88/gitpython-3.1.45.tar.gz", hash = "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c", size = 215076, upload-time = "2025-07-24T03:45:54.871Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/01/61/d4b89fec821f72385526e1b9d9a3a0385dda4a72b206d28049e2c7cd39b8/gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77", size = 208168, upload-time = "2025-07-24T03:45:52.517Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/01/61/d4b89fec821f72385526e1b9d9a3a0385dda4a72b206d28049e2c7cd39b8/gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77", size = 208168, upload-time = "2025-07-24T03:45:52.517Z" }, ] [[package]] name = "google-auth" version = "2.45.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cachetools" }, { name = "pyasn1-modules" }, { name = "rsa" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/00/3c794502a8b892c404b2dea5b3650eb21bfc7069612fbfd15c7f17c1cb0d/google_auth-2.45.0.tar.gz", hash = "sha256:90d3f41b6b72ea72dd9811e765699ee491ab24139f34ebf1ca2b9cc0c38708f3", size = 320708, upload-time = "2025-12-15T22:58:42.889Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/00/3c794502a8b892c404b2dea5b3650eb21bfc7069612fbfd15c7f17c1cb0d/google_auth-2.45.0.tar.gz", hash = "sha256:90d3f41b6b72ea72dd9811e765699ee491ab24139f34ebf1ca2b9cc0c38708f3", size = 320708, upload-time = "2025-12-15T22:58:42.889Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c6/97/451d55e05487a5cd6279a01a7e34921858b16f7dc8aa38a2c684743cd2b3/google_auth-2.45.0-py2.py3-none-any.whl", hash = "sha256:82344e86dc00410ef5382d99be677c6043d72e502b625aa4f4afa0bdacca0f36", size = 233312, upload-time = "2025-12-15T22:58:40.777Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c6/97/451d55e05487a5cd6279a01a7e34921858b16f7dc8aa38a2c684743cd2b3/google_auth-2.45.0-py2.py3-none-any.whl", hash = "sha256:82344e86dc00410ef5382d99be677c6043d72e502b625aa4f4afa0bdacca0f36", size = 233312, upload-time = "2025-12-15T22:58:40.777Z" }, ] [package.optional-dependencies] @@ -1245,7 +1236,7 @@ requests = [ [[package]] name = "google-genai" version = "1.56.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -1258,316 +1249,316 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/70/ad/d3ac5a102135bd3f1e4b1475ca65d2bd4bcc22eb2e9348ac40fe3fadb1d6/google_genai-1.56.0.tar.gz", hash = "sha256:0491af33c375f099777ae207d9621f044e27091fafad4c50e617eba32165e82f", size = 340451, upload-time = "2025-12-17T12:35:05.412Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/70/ad/d3ac5a102135bd3f1e4b1475ca65d2bd4bcc22eb2e9348ac40fe3fadb1d6/google_genai-1.56.0.tar.gz", hash = "sha256:0491af33c375f099777ae207d9621f044e27091fafad4c50e617eba32165e82f", size = 340451, upload-time = "2025-12-17T12:35:05.412Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/84/93/94bc7a89ef4e7ed3666add55cd859d1483a22737251df659bf1aa46e9405/google_genai-1.56.0-py3-none-any.whl", hash = "sha256:9e6b11e0c105ead229368cb5849a480e4d0185519f8d9f538d61ecfcf193b052", size = 426563, upload-time = "2025-12-17T12:35:03.717Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/84/93/94bc7a89ef4e7ed3666add55cd859d1483a22737251df659bf1aa46e9405/google_genai-1.56.0-py3-none-any.whl", hash = "sha256:9e6b11e0c105ead229368cb5849a480e4d0185519f8d9f538d61ecfcf193b052", size = 426563, upload-time = "2025-12-17T12:35:03.717Z" }, ] [[package]] name = "googleapis-common-protos" version = "1.72.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/7b/adfd75544c415c487b33061fe7ae526165241c1ea133f9a9125a56b39fd8/googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5", size = 147433, upload-time = "2025-11-06T18:29:24.087Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/7b/adfd75544c415c487b33061fe7ae526165241c1ea133f9a9125a56b39fd8/googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5", size = 147433, upload-time = "2025-11-06T18:29:24.087Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/ab/09169d5a4612a5f92490806649ac8d41e3ec9129c636754575b3553f4ea4/googleapis_common_protos-1.72.0-py3-none-any.whl", hash = "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", size = 297515, upload-time = "2025-11-06T18:29:13.14Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/ab/09169d5a4612a5f92490806649ac8d41e3ec9129c636754575b3553f4ea4/googleapis_common_protos-1.72.0-py3-none-any.whl", hash = "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", size = 297515, upload-time = "2025-11-06T18:29:13.14Z" }, ] [[package]] name = "greenlet" version = "3.3.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/e5/40dbda2736893e3e53d25838e0f19a2b417dfc122b9989c91918db30b5d3/greenlet-3.3.0.tar.gz", hash = "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb", size = 190651, upload-time = "2025-12-04T14:49:44.05Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f8/0a/a3871375c7b9727edaeeea994bfff7c63ff7804c9829c19309ba2e058807/greenlet-3.3.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb", size = 276379, upload-time = "2025-12-04T14:23:30.498Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/ab/7ebfe34dce8b87be0d11dae91acbf76f7b8246bf9d6b319c741f99fa59c6/greenlet-3.3.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3", size = 597294, upload-time = "2025-12-04T14:50:06.847Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a4/39/f1c8da50024feecd0793dbd5e08f526809b8ab5609224a2da40aad3a7641/greenlet-3.3.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655", size = 607742, upload-time = "2025-12-04T14:57:42.349Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/77/cb/43692bcd5f7a0da6ec0ec6d58ee7cddb606d055ce94a62ac9b1aa481e969/greenlet-3.3.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7", size = 622297, upload-time = "2025-12-04T15:07:13.552Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/b0/6bde0b1011a60782108c01de5913c588cf51a839174538d266de15e4bf4d/greenlet-3.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b", size = 609885, upload-time = "2025-12-04T14:26:02.368Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/49/0e/49b46ac39f931f59f987b7cd9f34bfec8ef81d2a1e6e00682f55be5de9f4/greenlet-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53", size = 1567424, upload-time = "2025-12-04T15:04:23.757Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/f5/49a9ac2dff7f10091935def9165c90236d8f175afb27cbed38fb1d61ab6b/greenlet-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614", size = 1636017, upload-time = "2025-12-04T14:27:29.688Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6c/79/3912a94cf27ec503e51ba493692d6db1e3cd8ac7ac52b0b47c8e33d7f4f9/greenlet-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7a34b13d43a6b78abf828a6d0e87d3385680eaf830cd60d20d52f249faabf39", size = 301964, upload-time = "2025-12-04T14:36:58.316Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/2f/28592176381b9ab2cafa12829ba7b472d177f3acc35d8fbcf3673d966fff/greenlet-3.3.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739", size = 275140, upload-time = "2025-12-04T14:23:01.282Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808", size = 599219, upload-time = "2025-12-04T14:50:08.309Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c2/ff/7c985128f0514271b8268476af89aee6866df5eec04ac17dcfbc676213df/greenlet-3.3.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54", size = 610211, upload-time = "2025-12-04T14:57:43.968Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/79/07/c47a82d881319ec18a4510bb30463ed6891f2ad2c1901ed5ec23d3de351f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30a6e28487a790417d036088b3bcb3f3ac7d8babaa7d0139edbaddebf3af9492", size = 624311, upload-time = "2025-12-04T15:07:14.697Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527", size = 612833, upload-time = "2025-12-04T14:26:03.669Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b5/ba/56699ff9b7c76ca12f1cdc27a886d0f81f2189c3455ff9f65246780f713d/greenlet-3.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab97cf74045343f6c60a39913fa59710e4bd26a536ce7ab2397adf8b27e67c39", size = 1567256, upload-time = "2025-12-04T15:04:25.276Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1e/37/f31136132967982d698c71a281a8901daf1a8fbab935dce7c0cf15f942cc/greenlet-3.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5375d2e23184629112ca1ea89a53389dddbffcf417dad40125713d88eb5f96e8", size = 1636483, upload-time = "2025-12-04T14:27:30.804Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7e/71/ba21c3fb8c5dce83b8c01f458a42e99ffdb1963aeec08fff5a18588d8fd7/greenlet-3.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:9ee1942ea19550094033c35d25d20726e4f1c40d59545815e1128ac58d416d38", size = 301833, upload-time = "2025-12-04T14:32:23.929Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/e5/40dbda2736893e3e53d25838e0f19a2b417dfc122b9989c91918db30b5d3/greenlet-3.3.0.tar.gz", hash = "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb", size = 190651, upload-time = "2025-12-04T14:49:44.05Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f8/0a/a3871375c7b9727edaeeea994bfff7c63ff7804c9829c19309ba2e058807/greenlet-3.3.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb", size = 276379, upload-time = "2025-12-04T14:23:30.498Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/ab/7ebfe34dce8b87be0d11dae91acbf76f7b8246bf9d6b319c741f99fa59c6/greenlet-3.3.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3", size = 597294, upload-time = "2025-12-04T14:50:06.847Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a4/39/f1c8da50024feecd0793dbd5e08f526809b8ab5609224a2da40aad3a7641/greenlet-3.3.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655", size = 607742, upload-time = "2025-12-04T14:57:42.349Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/77/cb/43692bcd5f7a0da6ec0ec6d58ee7cddb606d055ce94a62ac9b1aa481e969/greenlet-3.3.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7", size = 622297, upload-time = "2025-12-04T15:07:13.552Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/b0/6bde0b1011a60782108c01de5913c588cf51a839174538d266de15e4bf4d/greenlet-3.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b", size = 609885, upload-time = "2025-12-04T14:26:02.368Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/49/0e/49b46ac39f931f59f987b7cd9f34bfec8ef81d2a1e6e00682f55be5de9f4/greenlet-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53", size = 1567424, upload-time = "2025-12-04T15:04:23.757Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/f5/49a9ac2dff7f10091935def9165c90236d8f175afb27cbed38fb1d61ab6b/greenlet-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614", size = 1636017, upload-time = "2025-12-04T14:27:29.688Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6c/79/3912a94cf27ec503e51ba493692d6db1e3cd8ac7ac52b0b47c8e33d7f4f9/greenlet-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7a34b13d43a6b78abf828a6d0e87d3385680eaf830cd60d20d52f249faabf39", size = 301964, upload-time = "2025-12-04T14:36:58.316Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/2f/28592176381b9ab2cafa12829ba7b472d177f3acc35d8fbcf3673d966fff/greenlet-3.3.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739", size = 275140, upload-time = "2025-12-04T14:23:01.282Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808", size = 599219, upload-time = "2025-12-04T14:50:08.309Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/ff/7c985128f0514271b8268476af89aee6866df5eec04ac17dcfbc676213df/greenlet-3.3.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54", size = 610211, upload-time = "2025-12-04T14:57:43.968Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/07/c47a82d881319ec18a4510bb30463ed6891f2ad2c1901ed5ec23d3de351f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30a6e28487a790417d036088b3bcb3f3ac7d8babaa7d0139edbaddebf3af9492", size = 624311, upload-time = "2025-12-04T15:07:14.697Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527", size = 612833, upload-time = "2025-12-04T14:26:03.669Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b5/ba/56699ff9b7c76ca12f1cdc27a886d0f81f2189c3455ff9f65246780f713d/greenlet-3.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab97cf74045343f6c60a39913fa59710e4bd26a536ce7ab2397adf8b27e67c39", size = 1567256, upload-time = "2025-12-04T15:04:25.276Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1e/37/f31136132967982d698c71a281a8901daf1a8fbab935dce7c0cf15f942cc/greenlet-3.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5375d2e23184629112ca1ea89a53389dddbffcf417dad40125713d88eb5f96e8", size = 1636483, upload-time = "2025-12-04T14:27:30.804Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/71/ba21c3fb8c5dce83b8c01f458a42e99ffdb1963aeec08fff5a18588d8fd7/greenlet-3.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:9ee1942ea19550094033c35d25d20726e4f1c40d59545815e1128ac58d416d38", size = 301833, upload-time = "2025-12-04T14:32:23.929Z" }, ] [[package]] name = "gunicorn" version = "25.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "packaging" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/66/13/ef67f59f6a7896fdc2c1d62b5665c5219d6b0a9a1784938eb9a28e55e128/gunicorn-25.1.0.tar.gz", hash = "sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616", size = 594377, upload-time = "2026-02-13T11:09:58.989Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/13/ef67f59f6a7896fdc2c1d62b5665c5219d6b0a9a1784938eb9a28e55e128/gunicorn-25.1.0.tar.gz", hash = "sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616", size = 594377, upload-time = "2026-02-13T11:09:58.989Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/73/4ad5b1f6a2e21cf1e85afdaad2b7b1a933985e2f5d679147a1953aaa192c/gunicorn-25.1.0-py3-none-any.whl", hash = "sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b", size = 197067, upload-time = "2026-02-13T11:09:57.146Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/73/4ad5b1f6a2e21cf1e85afdaad2b7b1a933985e2f5d679147a1953aaa192c/gunicorn-25.1.0-py3-none-any.whl", hash = "sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b", size = 197067, upload-time = "2026-02-13T11:09:57.146Z" }, ] [[package]] name = "h11" version = "0.14.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418, upload-time = "2022-09-25T15:40:01.519Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418, upload-time = "2022-09-25T15:40:01.519Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259, upload-time = "2022-09-25T15:39:59.68Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259, upload-time = "2022-09-25T15:39:59.68Z" }, ] [[package]] name = "h2" version = "4.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "hpack" }, { name = "hyperframe" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2a/32/fec683ddd10629ea4ea46d206752a95a2d8a48c22521edd70b142488efe1/h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb", size = 2145593, upload-time = "2021-10-05T18:27:47.18Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/32/fec683ddd10629ea4ea46d206752a95a2d8a48c22521edd70b142488efe1/h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb", size = 2145593, upload-time = "2021-10-05T18:27:47.18Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2a/e5/db6d438da759efbb488c4f3fbdab7764492ff3c3f953132efa6b9f0e9e53/h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d", size = 57488, upload-time = "2021-10-05T18:27:39.977Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/e5/db6d438da759efbb488c4f3fbdab7764492ff3c3f953132efa6b9f0e9e53/h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d", size = 57488, upload-time = "2021-10-05T18:27:39.977Z" }, ] [[package]] name = "hpack" version = "4.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/48/71de9ed269fdae9c8057e5a4c0aa7402e8bb16f2c6e90b3aa53327b113f8/hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca", size = 51276, upload-time = "2025-01-22T21:44:58.347Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/48/71de9ed269fdae9c8057e5a4c0aa7402e8bb16f2c6e90b3aa53327b113f8/hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca", size = 51276, upload-time = "2025-01-22T21:44:58.347Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/07/c6/80c95b1b2b94682a72cbdbfb85b81ae2daffa4291fbfa1b1464502ede10d/hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496", size = 34357, upload-time = "2025-01-22T21:44:56.92Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/07/c6/80c95b1b2b94682a72cbdbfb85b81ae2daffa4291fbfa1b1464502ede10d/hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496", size = 34357, upload-time = "2025-01-22T21:44:56.92Z" }, ] [[package]] name = "httpcore" version = "1.0.8" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "certifi" }, { name = "h11" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/45/ad3e1b4d448f22c0cff4f5692f5ed0666658578e358b8d58a19846048059/httpcore-1.0.8.tar.gz", hash = "sha256:86e94505ed24ea06514883fd44d2bc02d90e77e7979c8eb71b90f41d364a1bad", size = 85385, upload-time = "2025-04-11T14:42:46.661Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/45/ad3e1b4d448f22c0cff4f5692f5ed0666658578e358b8d58a19846048059/httpcore-1.0.8.tar.gz", hash = "sha256:86e94505ed24ea06514883fd44d2bc02d90e77e7979c8eb71b90f41d364a1bad", size = 85385, upload-time = "2025-04-11T14:42:46.661Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/18/8d/f052b1e336bb2c1fc7ed1aaed898aa570c0b61a09707b108979d9fc6e308/httpcore-1.0.8-py3-none-any.whl", hash = "sha256:5254cf149bcb5f75e9d1b2b9f729ea4a4b883d1ad7379fc632b727cec23674be", size = 78732, upload-time = "2025-04-11T14:42:44.896Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/8d/f052b1e336bb2c1fc7ed1aaed898aa570c0b61a09707b108979d9fc6e308/httpcore-1.0.8-py3-none-any.whl", hash = "sha256:5254cf149bcb5f75e9d1b2b9f729ea4a4b883d1ad7379fc632b727cec23674be", size = 78732, upload-time = "2025-04-11T14:42:44.896Z" }, ] [[package]] name = "httptools" version = "0.7.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b5/46/120a669232c7bdedb9d52d4aeae7e6c7dfe151e99dc70802e2fc7a5e1993/httptools-0.7.1.tar.gz", hash = "sha256:abd72556974f8e7c74a259655924a717a2365b236c882c3f6f8a45fe94703ac9", size = 258961, upload-time = "2025-10-10T03:55:08.559Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/53/7f/403e5d787dc4942316e515e949b0c8a013d84078a915910e9f391ba9b3ed/httptools-0.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:38e0c83a2ea9746ebbd643bdfb521b9aa4a91703e2cd705c20443405d2fd16a5", size = 206280, upload-time = "2025-10-10T03:54:39.274Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2a/0d/7f3fd28e2ce311ccc998c388dd1c53b18120fda3b70ebb022b135dc9839b/httptools-0.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f25bbaf1235e27704f1a7b86cd3304eabc04f569c828101d94a0e605ef7205a5", size = 110004, upload-time = "2025-10-10T03:54:40.403Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/84/a6/b3965e1e146ef5762870bbe76117876ceba51a201e18cc31f5703e454596/httptools-0.7.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2c15f37ef679ab9ecc06bfc4e6e8628c32a8e4b305459de7cf6785acd57e4d03", size = 517655, upload-time = "2025-10-10T03:54:41.347Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/11/7d/71fee6f1844e6fa378f2eddde6c3e41ce3a1fb4b2d81118dd544e3441ec0/httptools-0.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7fe6e96090df46b36ccfaf746f03034e5ab723162bc51b0a4cf58305324036f2", size = 511440, upload-time = "2025-10-10T03:54:42.452Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/22/a5/079d216712a4f3ffa24af4a0381b108aa9c45b7a5cc6eb141f81726b1823/httptools-0.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f72fdbae2dbc6e68b8239defb48e6a5937b12218e6ffc2c7846cc37befa84362", size = 495186, upload-time = "2025-10-10T03:54:43.937Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/9e/025ad7b65278745dee3bd0ebf9314934c4592560878308a6121f7f812084/httptools-0.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e99c7b90a29fd82fea9ef57943d501a16f3404d7b9ee81799d41639bdaae412c", size = 499192, upload-time = "2025-10-10T03:54:45.003Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6d/de/40a8f202b987d43afc4d54689600ff03ce65680ede2f31df348d7f368b8f/httptools-0.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:3e14f530fefa7499334a79b0cf7e7cd2992870eb893526fb097d51b4f2d0f321", size = 86694, upload-time = "2025-10-10T03:54:45.923Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/09/8f/c77b1fcbfd262d422f12da02feb0d218fa228d52485b77b953832105bb90/httptools-0.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6babce6cfa2a99545c60bfef8bee0cc0545413cb0018f617c8059a30ad985de3", size = 202889, upload-time = "2025-10-10T03:54:47.089Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/1a/22887f53602feaa066354867bc49a68fc295c2293433177ee90870a7d517/httptools-0.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:601b7628de7504077dd3dcb3791c6b8694bbd967148a6d1f01806509254fb1ca", size = 108180, upload-time = "2025-10-10T03:54:48.052Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/32/6a/6aaa91937f0010d288d3d124ca2946d48d60c3a5ee7ca62afe870e3ea011/httptools-0.7.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:04c6c0e6c5fb0739c5b8a9eb046d298650a0ff38cf42537fc372b28dc7e4472c", size = 478596, upload-time = "2025-10-10T03:54:48.919Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6d/70/023d7ce117993107be88d2cbca566a7c1323ccbaf0af7eabf2064fe356f6/httptools-0.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:69d4f9705c405ae3ee83d6a12283dc9feba8cc6aaec671b412917e644ab4fa66", size = 473268, upload-time = "2025-10-10T03:54:49.993Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/32/4d/9dd616c38da088e3f436e9a616e1d0cc66544b8cdac405cc4e81c8679fc7/httptools-0.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:44c8f4347d4b31269c8a9205d8a5ee2df5322b09bbbd30f8f862185bb6b05346", size = 455517, upload-time = "2025-10-10T03:54:51.066Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1d/3a/a6c595c310b7df958e739aae88724e24f9246a514d909547778d776799be/httptools-0.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:465275d76db4d554918aba40bf1cbebe324670f3dfc979eaffaa5d108e2ed650", size = 458337, upload-time = "2025-10-10T03:54:52.196Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/82/88e8d6d2c51edc1cc391b6e044c6c435b6aebe97b1abc33db1b0b24cd582/httptools-0.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:322d00c2068d125bd570f7bf78b2d367dad02b919d8581d7476d8b75b294e3e6", size = 85743, upload-time = "2025-10-10T03:54:53.448Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b5/46/120a669232c7bdedb9d52d4aeae7e6c7dfe151e99dc70802e2fc7a5e1993/httptools-0.7.1.tar.gz", hash = "sha256:abd72556974f8e7c74a259655924a717a2365b236c882c3f6f8a45fe94703ac9", size = 258961, upload-time = "2025-10-10T03:55:08.559Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/53/7f/403e5d787dc4942316e515e949b0c8a013d84078a915910e9f391ba9b3ed/httptools-0.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:38e0c83a2ea9746ebbd643bdfb521b9aa4a91703e2cd705c20443405d2fd16a5", size = 206280, upload-time = "2025-10-10T03:54:39.274Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/0d/7f3fd28e2ce311ccc998c388dd1c53b18120fda3b70ebb022b135dc9839b/httptools-0.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f25bbaf1235e27704f1a7b86cd3304eabc04f569c828101d94a0e605ef7205a5", size = 110004, upload-time = "2025-10-10T03:54:40.403Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/84/a6/b3965e1e146ef5762870bbe76117876ceba51a201e18cc31f5703e454596/httptools-0.7.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2c15f37ef679ab9ecc06bfc4e6e8628c32a8e4b305459de7cf6785acd57e4d03", size = 517655, upload-time = "2025-10-10T03:54:41.347Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/11/7d/71fee6f1844e6fa378f2eddde6c3e41ce3a1fb4b2d81118dd544e3441ec0/httptools-0.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7fe6e96090df46b36ccfaf746f03034e5ab723162bc51b0a4cf58305324036f2", size = 511440, upload-time = "2025-10-10T03:54:42.452Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/a5/079d216712a4f3ffa24af4a0381b108aa9c45b7a5cc6eb141f81726b1823/httptools-0.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f72fdbae2dbc6e68b8239defb48e6a5937b12218e6ffc2c7846cc37befa84362", size = 495186, upload-time = "2025-10-10T03:54:43.937Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/9e/025ad7b65278745dee3bd0ebf9314934c4592560878308a6121f7f812084/httptools-0.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e99c7b90a29fd82fea9ef57943d501a16f3404d7b9ee81799d41639bdaae412c", size = 499192, upload-time = "2025-10-10T03:54:45.003Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6d/de/40a8f202b987d43afc4d54689600ff03ce65680ede2f31df348d7f368b8f/httptools-0.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:3e14f530fefa7499334a79b0cf7e7cd2992870eb893526fb097d51b4f2d0f321", size = 86694, upload-time = "2025-10-10T03:54:45.923Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/09/8f/c77b1fcbfd262d422f12da02feb0d218fa228d52485b77b953832105bb90/httptools-0.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6babce6cfa2a99545c60bfef8bee0cc0545413cb0018f617c8059a30ad985de3", size = 202889, upload-time = "2025-10-10T03:54:47.089Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/1a/22887f53602feaa066354867bc49a68fc295c2293433177ee90870a7d517/httptools-0.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:601b7628de7504077dd3dcb3791c6b8694bbd967148a6d1f01806509254fb1ca", size = 108180, upload-time = "2025-10-10T03:54:48.052Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/32/6a/6aaa91937f0010d288d3d124ca2946d48d60c3a5ee7ca62afe870e3ea011/httptools-0.7.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:04c6c0e6c5fb0739c5b8a9eb046d298650a0ff38cf42537fc372b28dc7e4472c", size = 478596, upload-time = "2025-10-10T03:54:48.919Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6d/70/023d7ce117993107be88d2cbca566a7c1323ccbaf0af7eabf2064fe356f6/httptools-0.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:69d4f9705c405ae3ee83d6a12283dc9feba8cc6aaec671b412917e644ab4fa66", size = 473268, upload-time = "2025-10-10T03:54:49.993Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/32/4d/9dd616c38da088e3f436e9a616e1d0cc66544b8cdac405cc4e81c8679fc7/httptools-0.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:44c8f4347d4b31269c8a9205d8a5ee2df5322b09bbbd30f8f862185bb6b05346", size = 455517, upload-time = "2025-10-10T03:54:51.066Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1d/3a/a6c595c310b7df958e739aae88724e24f9246a514d909547778d776799be/httptools-0.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:465275d76db4d554918aba40bf1cbebe324670f3dfc979eaffaa5d108e2ed650", size = 458337, upload-time = "2025-10-10T03:54:52.196Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/82/88e8d6d2c51edc1cc391b6e044c6c435b6aebe97b1abc33db1b0b24cd582/httptools-0.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:322d00c2068d125bd570f7bf78b2d367dad02b919d8581d7476d8b75b294e3e6", size = 85743, upload-time = "2025-10-10T03:54:53.448Z" }, ] [[package]] name = "httpx" version = "0.28.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "anyio" }, { name = "certifi" }, { name = "httpcore" }, { name = "idna" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/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://mirrors.tuna.tsinghua.edu.cn/pypi/web/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" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/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 = "httpx-sse" version = "0.4.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, ] [[package]] name = "hypercorn" version = "0.17.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "h11" }, { name = "h2" }, { name = "priority" }, { name = "wsproto" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7e/3a/df6c27642e0dcb7aff688ca4be982f0fb5d89f2afd3096dc75347c16140f/hypercorn-0.17.3.tar.gz", hash = "sha256:1b37802ee3ac52d2d85270700d565787ab16cf19e1462ccfa9f089ca17574165", size = 44409, upload-time = "2024-05-28T20:55:53.06Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/3a/df6c27642e0dcb7aff688ca4be982f0fb5d89f2afd3096dc75347c16140f/hypercorn-0.17.3.tar.gz", hash = "sha256:1b37802ee3ac52d2d85270700d565787ab16cf19e1462ccfa9f089ca17574165", size = 44409, upload-time = "2024-05-28T20:55:53.06Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/3b/dfa13a8d96aa24e40ea74a975a9906cfdc2ab2f4e3b498862a57052f04eb/hypercorn-0.17.3-py3-none-any.whl", hash = "sha256:059215dec34537f9d40a69258d323f56344805efb462959e727152b0aa504547", size = 61742, upload-time = "2024-05-28T20:55:48.829Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/3b/dfa13a8d96aa24e40ea74a975a9906cfdc2ab2f4e3b498862a57052f04eb/hypercorn-0.17.3-py3-none-any.whl", hash = "sha256:059215dec34537f9d40a69258d323f56344805efb462959e727152b0aa504547", size = 61742, upload-time = "2024-05-28T20:55:48.829Z" }, ] [[package]] name = "hyperframe" version = "6.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/e7/94f8232d4a74cc99514c13a9f995811485a6903d48e5d952771ef6322e30/hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08", size = 26566, upload-time = "2025-01-22T21:41:49.302Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/e7/94f8232d4a74cc99514c13a9f995811485a6903d48e5d952771ef6322e30/hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08", size = 26566, upload-time = "2025-01-22T21:41:49.302Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/48/30/47d0bf6072f7252e6521f3447ccfa40b421b6824517f82854703d0f5a98b/hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5", size = 13007, upload-time = "2025-01-22T21:41:47.295Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/48/30/47d0bf6072f7252e6521f3447ccfa40b421b6824517f82854703d0f5a98b/hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5", size = 13007, upload-time = "2025-01-22T21:41:47.295Z" }, ] [[package]] name = "identify" version = "2.6.15" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/e7/685de97986c916a6d93b3876139e00eef26ad5bbbd61925d670ae8013449/identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf", size = 99311, upload-time = "2025-10-02T17:43:40.631Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/e7/685de97986c916a6d93b3876139e00eef26ad5bbbd61925d670ae8013449/identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf", size = 99311, upload-time = "2025-10-02T17:43:40.631Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/1c/e5fd8f973d4f375adb21565739498e2e9a1e54c858a97b9a8ccfdc81da9b/identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757", size = 99183, upload-time = "2025-10-02T17:43:39.137Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0f/1c/e5fd8f973d4f375adb21565739498e2e9a1e54c858a97b9a8ccfdc81da9b/identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757", size = 99183, upload-time = "2025-10-02T17:43:39.137Z" }, ] [[package]] name = "idna" version = "3.11" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, ] [[package]] name = "importlib-metadata" version = "8.7.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "zipp" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, ] [[package]] name = "iniconfig" version = "2.3.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] [[package]] name = "itsdangerous" version = "2.2.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" }, ] [[package]] name = "jaraco-classes" version = "3.4.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "more-itertools" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" }, ] [[package]] name = "jaraco-context" version = "6.0.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8d/7d/41acf8e22d791bde812cb6c2c36128bb932ed8ae066bcb5e39cb198e8253/jaraco_context-6.0.2.tar.gz", hash = "sha256:953ae8dddb57b1d791bf72ea1009b32088840a7dd19b9ba16443f62be919ee57", size = 14994, upload-time = "2025-12-24T19:21:35.784Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8d/7d/41acf8e22d791bde812cb6c2c36128bb932ed8ae066bcb5e39cb198e8253/jaraco_context-6.0.2.tar.gz", hash = "sha256:953ae8dddb57b1d791bf72ea1009b32088840a7dd19b9ba16443f62be919ee57", size = 14994, upload-time = "2025-12-24T19:21:35.784Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/0c/1e0096ced9c55f9c6c6655446798df74165780375d3f5ab5f33751e087ae/jaraco_context-6.0.2-py3-none-any.whl", hash = "sha256:55fc21af4b4f9ca94aa643b6ee7fe13b1e4c01abf3aeb98ca4ad9c80b741c786", size = 6988, upload-time = "2025-12-24T19:21:34.557Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/0c/1e0096ced9c55f9c6c6655446798df74165780375d3f5ab5f33751e087ae/jaraco_context-6.0.2-py3-none-any.whl", hash = "sha256:55fc21af4b4f9ca94aa643b6ee7fe13b1e4c01abf3aeb98ca4ad9c80b741c786", size = 6988, upload-time = "2025-12-24T19:21:34.557Z" }, ] [[package]] name = "jaraco-functools" version = "4.4.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "more-itertools" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/27/056e0638a86749374d6f57d0b0db39f29509cce9313cf91bdc0ac4d91084/jaraco_functools-4.4.0.tar.gz", hash = "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb", size = 19943, upload-time = "2025-12-21T09:29:43.6Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0f/27/056e0638a86749374d6f57d0b0db39f29509cce9313cf91bdc0ac4d91084/jaraco_functools-4.4.0.tar.gz", hash = "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb", size = 19943, upload-time = "2025-12-21T09:29:43.6Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl", hash = "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", size = 10481, upload-time = "2025-12-21T09:29:42.27Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl", hash = "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", size = 10481, upload-time = "2025-12-21T09:29:42.27Z" }, ] [[package]] name = "jeepney" version = "0.9.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, ] [[package]] name = "jinja2" version = "3.1.6" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] [[package]] name = "jiter" version = "0.12.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/45/9d/e0660989c1370e25848bb4c52d061c71837239738ad937e83edca174c273/jiter-0.12.0.tar.gz", hash = "sha256:64dfcd7d5c168b38d3f9f8bba7fc639edb3418abcc74f22fdbe6b8938293f30b", size = 168294, upload-time = "2025-11-09T20:49:23.302Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/92/c9/5b9f7b4983f1b542c64e84165075335e8a236fa9e2ea03a0c79780062be8/jiter-0.12.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:305e061fa82f4680607a775b2e8e0bcb071cd2205ac38e6ef48c8dd5ebe1cf37", size = 314449, upload-time = "2025-11-09T20:47:22.999Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/6e/e8efa0e78de00db0aee82c0cf9e8b3f2027efd7f8a71f859d8f4be8e98ef/jiter-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5c1860627048e302a528333c9307c818c547f214d8659b0705d2195e1a94b274", size = 319855, upload-time = "2025-11-09T20:47:24.779Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/20/26/894cd88e60b5d58af53bec5c6759d1292bd0b37a8b5f60f07abf7a63ae5f/jiter-0.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df37577a4f8408f7e0ec3205d2a8f87672af8f17008358063a4d6425b6081ce3", size = 350171, upload-time = "2025-11-09T20:47:26.469Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/27/a7b818b9979ac31b3763d25f3653ec3a954044d5e9f5d87f2f247d679fd1/jiter-0.12.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75fdd787356c1c13a4f40b43c2156276ef7a71eb487d98472476476d803fb2cf", size = 365590, upload-time = "2025-11-09T20:47:27.918Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/7e/e46195801a97673a83746170b17984aa8ac4a455746354516d02ca5541b4/jiter-0.12.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1eb5db8d9c65b112aacf14fcd0faae9913d07a8afea5ed06ccdd12b724e966a1", size = 479462, upload-time = "2025-11-09T20:47:29.654Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ca/75/f833bfb009ab4bd11b1c9406d333e3b4357709ed0570bb48c7c06d78c7dd/jiter-0.12.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73c568cc27c473f82480abc15d1301adf333a7ea4f2e813d6a2c7d8b6ba8d0df", size = 378983, upload-time = "2025-11-09T20:47:31.026Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/b3/7a69d77943cc837d30165643db753471aff5df39692d598da880a6e51c24/jiter-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4321e8a3d868919bcb1abb1db550d41f2b5b326f72df29e53b2df8b006eb9403", size = 361328, upload-time = "2025-11-09T20:47:33.286Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b0/ac/a78f90caf48d65ba70d8c6efc6f23150bc39dc3389d65bbec2a95c7bc628/jiter-0.12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a51bad79f8cc9cac2b4b705039f814049142e0050f30d91695a2d9a6611f126", size = 386740, upload-time = "2025-11-09T20:47:34.703Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/39/b6/5d31c2cc8e1b6a6bcf3c5721e4ca0a3633d1ab4754b09bc7084f6c4f5327/jiter-0.12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2a67b678f6a5f1dd6c36d642d7db83e456bc8b104788262aaefc11a22339f5a9", size = 520875, upload-time = "2025-11-09T20:47:36.058Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/30/b5/4df540fae4e9f68c54b8dab004bd8c943a752f0b00efd6e7d64aa3850339/jiter-0.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efe1a211fe1fd14762adea941e3cfd6c611a136e28da6c39272dbb7a1bbe6a86", size = 511457, upload-time = "2025-11-09T20:47:37.932Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/07/65/86b74010e450a1a77b2c1aabb91d4a91dd3cd5afce99f34d75fd1ac64b19/jiter-0.12.0-cp312-cp312-win32.whl", hash = "sha256:d779d97c834b4278276ec703dc3fc1735fca50af63eb7262f05bdb4e62203d44", size = 204546, upload-time = "2025-11-09T20:47:40.47Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/c7/6659f537f9562d963488e3e55573498a442503ced01f7e169e96a6110383/jiter-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e8269062060212b373316fe69236096aaf4c49022d267c6736eebd66bbbc60bb", size = 205196, upload-time = "2025-11-09T20:47:41.794Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/21/f4/935304f5169edadfec7f9c01eacbce4c90bb9a82035ac1de1f3bd2d40be6/jiter-0.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:06cb970936c65de926d648af0ed3d21857f026b1cf5525cb2947aa5e01e05789", size = 186100, upload-time = "2025-11-09T20:47:43.007Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/a6/97209693b177716e22576ee1161674d1d58029eb178e01866a0422b69224/jiter-0.12.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6cc49d5130a14b732e0612bc76ae8db3b49898732223ef8b7599aa8d9810683e", size = 313658, upload-time = "2025-11-09T20:47:44.424Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/4d/125c5c1537c7d8ee73ad3d530a442d6c619714b95027143f1b61c0b4dfe0/jiter-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:37f27a32ce36364d2fa4f7fdc507279db604d27d239ea2e044c8f148410defe1", size = 318605, upload-time = "2025-11-09T20:47:45.973Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/99/bf/a840b89847885064c41a5f52de6e312e91fa84a520848ee56c97e4fa0205/jiter-0.12.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbc0944aa3d4b4773e348cda635252824a78f4ba44328e042ef1ff3f6080d1cf", size = 349803, upload-time = "2025-11-09T20:47:47.535Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8a/88/e63441c28e0db50e305ae23e19c1d8fae012d78ed55365da392c1f34b09c/jiter-0.12.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da25c62d4ee1ffbacb97fac6dfe4dcd6759ebdc9015991e92a6eae5816287f44", size = 365120, upload-time = "2025-11-09T20:47:49.284Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/7c/49b02714af4343970eb8aca63396bc1c82fa01197dbb1e9b0d274b550d4e/jiter-0.12.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:048485c654b838140b007390b8182ba9774621103bd4d77c9c3f6f117474ba45", size = 479918, upload-time = "2025-11-09T20:47:50.807Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/ba/0a809817fdd5a1db80490b9150645f3aae16afad166960bcd562be194f3b/jiter-0.12.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:635e737fbb7315bef0037c19b88b799143d2d7d3507e61a76751025226b3ac87", size = 379008, upload-time = "2025-11-09T20:47:52.211Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5f/c3/c9fc0232e736c8877d9e6d83d6eeb0ba4e90c6c073835cc2e8f73fdeef51/jiter-0.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e017c417b1ebda911bd13b1e40612704b1f5420e30695112efdbed8a4b389ed", size = 361785, upload-time = "2025-11-09T20:47:53.512Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/96/61/61f69b7e442e97ca6cd53086ddc1cf59fb830549bc72c0a293713a60c525/jiter-0.12.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:89b0bfb8b2bf2351fba36bb211ef8bfceba73ef58e7f0c68fb67b5a2795ca2f9", size = 386108, upload-time = "2025-11-09T20:47:54.893Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/2e/76bb3332f28550c8f1eba3bf6e5efe211efda0ddbbaf24976bc7078d42a5/jiter-0.12.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:f5aa5427a629a824a543672778c9ce0c5e556550d1569bb6ea28a85015287626", size = 519937, upload-time = "2025-11-09T20:47:56.253Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/84/d6/fa96efa87dc8bff2094fb947f51f66368fa56d8d4fc9e77b25d7fbb23375/jiter-0.12.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed53b3d6acbcb0fd0b90f20c7cb3b24c357fe82a3518934d4edfa8c6898e498c", size = 510853, upload-time = "2025-11-09T20:47:58.32Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8a/28/93f67fdb4d5904a708119a6ab58a8f1ec226ff10a94a282e0215402a8462/jiter-0.12.0-cp313-cp313-win32.whl", hash = "sha256:4747de73d6b8c78f2e253a2787930f4fffc68da7fa319739f57437f95963c4de", size = 204699, upload-time = "2025-11-09T20:47:59.686Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/1f/30b0eb087045a0abe2a5c9c0c0c8da110875a1d3be83afd4a9a4e548be3c/jiter-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:e25012eb0c456fcc13354255d0338cd5397cce26c77b2832b3c4e2e255ea5d9a", size = 204258, upload-time = "2025-11-09T20:48:01.01Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/f4/2b4daf99b96bce6fc47971890b14b2a36aef88d7beb9f057fafa032c6141/jiter-0.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:c97b92c54fe6110138c872add030a1f99aea2401ddcdaa21edf74705a646dd60", size = 185503, upload-time = "2025-11-09T20:48:02.35Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/39/ca/67bb15a7061d6fe20b9b2a2fd783e296a1e0f93468252c093481a2f00efa/jiter-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:53839b35a38f56b8be26a7851a48b89bc47e5d88e900929df10ed93b95fea3d6", size = 317965, upload-time = "2025-11-09T20:48:03.783Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/18/af/1788031cd22e29c3b14bc6ca80b16a39a0b10e611367ffd480c06a259831/jiter-0.12.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94f669548e55c91ab47fef8bddd9c954dab1938644e715ea49d7e117015110a4", size = 345831, upload-time = "2025-11-09T20:48:05.55Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/17/710bf8472d1dff0d3caf4ced6031060091c1320f84ee7d5dcbed1f352417/jiter-0.12.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:351d54f2b09a41600ffea43d081522d792e81dcfb915f6d2d242744c1cc48beb", size = 361272, upload-time = "2025-11-09T20:48:06.951Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fb/f1/1dcc4618b59761fef92d10bcbb0b038b5160be653b003651566a185f1a5c/jiter-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2a5e90604620f94bf62264e7c2c038704d38217b7465b863896c6d7c902b06c7", size = 204604, upload-time = "2025-11-09T20:48:08.328Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d9/32/63cb1d9f1c5c6632a783c0052cde9ef7ba82688f7065e2f0d5f10a7e3edb/jiter-0.12.0-cp313-cp313t-win_arm64.whl", hash = "sha256:88ef757017e78d2860f96250f9393b7b577b06a956ad102c29c8237554380db3", size = 185628, upload-time = "2025-11-09T20:48:09.572Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/f5/12efb8ada5f5c9edc1d4555fe383c1fb2eac05ac5859258a72d61981d999/jiter-0.12.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:e8547883d7b96ef2e5fe22b88f8a4c8725a56e7f4abafff20fd5272d634c7ecb", size = 309974, upload-time = "2025-11-09T20:49:17.187Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/85/15/d6eb3b770f6a0d332675141ab3962fd4a7c270ede3515d9f3583e1d28276/jiter-0.12.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:89163163c0934854a668ed783a2546a0617f71706a2551a4a0666d91ab365d6b", size = 304233, upload-time = "2025-11-09T20:49:18.734Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8c/3e/e7e06743294eea2cf02ced6aa0ff2ad237367394e37a0e2b4a1108c67a36/jiter-0.12.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d96b264ab7d34bbb2312dedc47ce07cd53f06835eacbc16dde3761f47c3a9e7f", size = 338537, upload-time = "2025-11-09T20:49:20.317Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2f/9c/6753e6522b8d0ef07d3a3d239426669e984fb0eba15a315cdbc1253904e4/jiter-0.12.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c24e864cb30ab82311c6425655b0cdab0a98c5d973b065c66a3f020740c2324c", size = 346110, upload-time = "2025-11-09T20:49:21.817Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/45/9d/e0660989c1370e25848bb4c52d061c71837239738ad937e83edca174c273/jiter-0.12.0.tar.gz", hash = "sha256:64dfcd7d5c168b38d3f9f8bba7fc639edb3418abcc74f22fdbe6b8938293f30b", size = 168294, upload-time = "2025-11-09T20:49:23.302Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/92/c9/5b9f7b4983f1b542c64e84165075335e8a236fa9e2ea03a0c79780062be8/jiter-0.12.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:305e061fa82f4680607a775b2e8e0bcb071cd2205ac38e6ef48c8dd5ebe1cf37", size = 314449, upload-time = "2025-11-09T20:47:22.999Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/6e/e8efa0e78de00db0aee82c0cf9e8b3f2027efd7f8a71f859d8f4be8e98ef/jiter-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5c1860627048e302a528333c9307c818c547f214d8659b0705d2195e1a94b274", size = 319855, upload-time = "2025-11-09T20:47:24.779Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/26/894cd88e60b5d58af53bec5c6759d1292bd0b37a8b5f60f07abf7a63ae5f/jiter-0.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df37577a4f8408f7e0ec3205d2a8f87672af8f17008358063a4d6425b6081ce3", size = 350171, upload-time = "2025-11-09T20:47:26.469Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/27/a7b818b9979ac31b3763d25f3653ec3a954044d5e9f5d87f2f247d679fd1/jiter-0.12.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75fdd787356c1c13a4f40b43c2156276ef7a71eb487d98472476476d803fb2cf", size = 365590, upload-time = "2025-11-09T20:47:27.918Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/7e/e46195801a97673a83746170b17984aa8ac4a455746354516d02ca5541b4/jiter-0.12.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1eb5db8d9c65b112aacf14fcd0faae9913d07a8afea5ed06ccdd12b724e966a1", size = 479462, upload-time = "2025-11-09T20:47:29.654Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/75/f833bfb009ab4bd11b1c9406d333e3b4357709ed0570bb48c7c06d78c7dd/jiter-0.12.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73c568cc27c473f82480abc15d1301adf333a7ea4f2e813d6a2c7d8b6ba8d0df", size = 378983, upload-time = "2025-11-09T20:47:31.026Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/b3/7a69d77943cc837d30165643db753471aff5df39692d598da880a6e51c24/jiter-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4321e8a3d868919bcb1abb1db550d41f2b5b326f72df29e53b2df8b006eb9403", size = 361328, upload-time = "2025-11-09T20:47:33.286Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b0/ac/a78f90caf48d65ba70d8c6efc6f23150bc39dc3389d65bbec2a95c7bc628/jiter-0.12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a51bad79f8cc9cac2b4b705039f814049142e0050f30d91695a2d9a6611f126", size = 386740, upload-time = "2025-11-09T20:47:34.703Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/b6/5d31c2cc8e1b6a6bcf3c5721e4ca0a3633d1ab4754b09bc7084f6c4f5327/jiter-0.12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2a67b678f6a5f1dd6c36d642d7db83e456bc8b104788262aaefc11a22339f5a9", size = 520875, upload-time = "2025-11-09T20:47:36.058Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/30/b5/4df540fae4e9f68c54b8dab004bd8c943a752f0b00efd6e7d64aa3850339/jiter-0.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efe1a211fe1fd14762adea941e3cfd6c611a136e28da6c39272dbb7a1bbe6a86", size = 511457, upload-time = "2025-11-09T20:47:37.932Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/07/65/86b74010e450a1a77b2c1aabb91d4a91dd3cd5afce99f34d75fd1ac64b19/jiter-0.12.0-cp312-cp312-win32.whl", hash = "sha256:d779d97c834b4278276ec703dc3fc1735fca50af63eb7262f05bdb4e62203d44", size = 204546, upload-time = "2025-11-09T20:47:40.47Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/c7/6659f537f9562d963488e3e55573498a442503ced01f7e169e96a6110383/jiter-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e8269062060212b373316fe69236096aaf4c49022d267c6736eebd66bbbc60bb", size = 205196, upload-time = "2025-11-09T20:47:41.794Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/21/f4/935304f5169edadfec7f9c01eacbce4c90bb9a82035ac1de1f3bd2d40be6/jiter-0.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:06cb970936c65de926d648af0ed3d21857f026b1cf5525cb2947aa5e01e05789", size = 186100, upload-time = "2025-11-09T20:47:43.007Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/a6/97209693b177716e22576ee1161674d1d58029eb178e01866a0422b69224/jiter-0.12.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6cc49d5130a14b732e0612bc76ae8db3b49898732223ef8b7599aa8d9810683e", size = 313658, upload-time = "2025-11-09T20:47:44.424Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/4d/125c5c1537c7d8ee73ad3d530a442d6c619714b95027143f1b61c0b4dfe0/jiter-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:37f27a32ce36364d2fa4f7fdc507279db604d27d239ea2e044c8f148410defe1", size = 318605, upload-time = "2025-11-09T20:47:45.973Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/bf/a840b89847885064c41a5f52de6e312e91fa84a520848ee56c97e4fa0205/jiter-0.12.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbc0944aa3d4b4773e348cda635252824a78f4ba44328e042ef1ff3f6080d1cf", size = 349803, upload-time = "2025-11-09T20:47:47.535Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/88/e63441c28e0db50e305ae23e19c1d8fae012d78ed55365da392c1f34b09c/jiter-0.12.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da25c62d4ee1ffbacb97fac6dfe4dcd6759ebdc9015991e92a6eae5816287f44", size = 365120, upload-time = "2025-11-09T20:47:49.284Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/7c/49b02714af4343970eb8aca63396bc1c82fa01197dbb1e9b0d274b550d4e/jiter-0.12.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:048485c654b838140b007390b8182ba9774621103bd4d77c9c3f6f117474ba45", size = 479918, upload-time = "2025-11-09T20:47:50.807Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/ba/0a809817fdd5a1db80490b9150645f3aae16afad166960bcd562be194f3b/jiter-0.12.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:635e737fbb7315bef0037c19b88b799143d2d7d3507e61a76751025226b3ac87", size = 379008, upload-time = "2025-11-09T20:47:52.211Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/c3/c9fc0232e736c8877d9e6d83d6eeb0ba4e90c6c073835cc2e8f73fdeef51/jiter-0.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e017c417b1ebda911bd13b1e40612704b1f5420e30695112efdbed8a4b389ed", size = 361785, upload-time = "2025-11-09T20:47:53.512Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/96/61/61f69b7e442e97ca6cd53086ddc1cf59fb830549bc72c0a293713a60c525/jiter-0.12.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:89b0bfb8b2bf2351fba36bb211ef8bfceba73ef58e7f0c68fb67b5a2795ca2f9", size = 386108, upload-time = "2025-11-09T20:47:54.893Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/2e/76bb3332f28550c8f1eba3bf6e5efe211efda0ddbbaf24976bc7078d42a5/jiter-0.12.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:f5aa5427a629a824a543672778c9ce0c5e556550d1569bb6ea28a85015287626", size = 519937, upload-time = "2025-11-09T20:47:56.253Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/84/d6/fa96efa87dc8bff2094fb947f51f66368fa56d8d4fc9e77b25d7fbb23375/jiter-0.12.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed53b3d6acbcb0fd0b90f20c7cb3b24c357fe82a3518934d4edfa8c6898e498c", size = 510853, upload-time = "2025-11-09T20:47:58.32Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/28/93f67fdb4d5904a708119a6ab58a8f1ec226ff10a94a282e0215402a8462/jiter-0.12.0-cp313-cp313-win32.whl", hash = "sha256:4747de73d6b8c78f2e253a2787930f4fffc68da7fa319739f57437f95963c4de", size = 204699, upload-time = "2025-11-09T20:47:59.686Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/1f/30b0eb087045a0abe2a5c9c0c0c8da110875a1d3be83afd4a9a4e548be3c/jiter-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:e25012eb0c456fcc13354255d0338cd5397cce26c77b2832b3c4e2e255ea5d9a", size = 204258, upload-time = "2025-11-09T20:48:01.01Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/f4/2b4daf99b96bce6fc47971890b14b2a36aef88d7beb9f057fafa032c6141/jiter-0.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:c97b92c54fe6110138c872add030a1f99aea2401ddcdaa21edf74705a646dd60", size = 185503, upload-time = "2025-11-09T20:48:02.35Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/ca/67bb15a7061d6fe20b9b2a2fd783e296a1e0f93468252c093481a2f00efa/jiter-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:53839b35a38f56b8be26a7851a48b89bc47e5d88e900929df10ed93b95fea3d6", size = 317965, upload-time = "2025-11-09T20:48:03.783Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/af/1788031cd22e29c3b14bc6ca80b16a39a0b10e611367ffd480c06a259831/jiter-0.12.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94f669548e55c91ab47fef8bddd9c954dab1938644e715ea49d7e117015110a4", size = 345831, upload-time = "2025-11-09T20:48:05.55Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/17/710bf8472d1dff0d3caf4ced6031060091c1320f84ee7d5dcbed1f352417/jiter-0.12.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:351d54f2b09a41600ffea43d081522d792e81dcfb915f6d2d242744c1cc48beb", size = 361272, upload-time = "2025-11-09T20:48:06.951Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fb/f1/1dcc4618b59761fef92d10bcbb0b038b5160be653b003651566a185f1a5c/jiter-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2a5e90604620f94bf62264e7c2c038704d38217b7465b863896c6d7c902b06c7", size = 204604, upload-time = "2025-11-09T20:48:08.328Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/32/63cb1d9f1c5c6632a783c0052cde9ef7ba82688f7065e2f0d5f10a7e3edb/jiter-0.12.0-cp313-cp313t-win_arm64.whl", hash = "sha256:88ef757017e78d2860f96250f9393b7b577b06a956ad102c29c8237554380db3", size = 185628, upload-time = "2025-11-09T20:48:09.572Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/f5/12efb8ada5f5c9edc1d4555fe383c1fb2eac05ac5859258a72d61981d999/jiter-0.12.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:e8547883d7b96ef2e5fe22b88f8a4c8725a56e7f4abafff20fd5272d634c7ecb", size = 309974, upload-time = "2025-11-09T20:49:17.187Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/85/15/d6eb3b770f6a0d332675141ab3962fd4a7c270ede3515d9f3583e1d28276/jiter-0.12.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:89163163c0934854a668ed783a2546a0617f71706a2551a4a0666d91ab365d6b", size = 304233, upload-time = "2025-11-09T20:49:18.734Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8c/3e/e7e06743294eea2cf02ced6aa0ff2ad237367394e37a0e2b4a1108c67a36/jiter-0.12.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d96b264ab7d34bbb2312dedc47ce07cd53f06835eacbc16dde3761f47c3a9e7f", size = 338537, upload-time = "2025-11-09T20:49:20.317Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2f/9c/6753e6522b8d0ef07d3a3d239426669e984fb0eba15a315cdbc1253904e4/jiter-0.12.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c24e864cb30ab82311c6425655b0cdab0a98c5d973b065c66a3f020740c2324c", size = 346110, upload-time = "2025-11-09T20:49:21.817Z" }, ] [[package]] @@ -1731,79 +1722,79 @@ dev = [ [[package]] name = "jsonpatch" version = "1.33" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "jsonpointer" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/42/78/18813351fe5d63acad16aec57f94ec2b70a09e53ca98145589e185423873/jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/42/78/18813351fe5d63acad16aec57f94ec2b70a09e53ca98145589e185423873/jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/73/07/02e16ed01e04a374e644b575638ec7987ae846d25ad97bcc9945a3ee4b0e/jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/73/07/02e16ed01e04a374e644b575638ec7987ae846d25ad97bcc9945a3ee4b0e/jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade" }, ] [[package]] name = "jsonpointer" version = "3.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, ] [[package]] name = "jsonschema" version = "4.25.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "attrs" }, { name = "jsonschema-specifications" }, { name = "referencing" }, { name = "rpds-py" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" }, ] [[package]] name = "jsonschema-path" version = "0.3.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pathable" }, { name = "pyyaml" }, { name = "referencing" }, { name = "requests" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/45/41ebc679c2a4fced6a722f624c18d658dee42612b83ea24c1caf7c0eb3a8/jsonschema_path-0.3.4.tar.gz", hash = "sha256:8365356039f16cc65fddffafda5f58766e34bebab7d6d105616ab52bc4297001", size = 11159, upload-time = "2025-01-24T14:33:16.547Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/45/41ebc679c2a4fced6a722f624c18d658dee42612b83ea24c1caf7c0eb3a8/jsonschema_path-0.3.4.tar.gz", hash = "sha256:8365356039f16cc65fddffafda5f58766e34bebab7d6d105616ab52bc4297001", size = 11159, upload-time = "2025-01-24T14:33:16.547Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/58/3485da8cb93d2f393bce453adeef16896751f14ba3e2024bc21dc9597646/jsonschema_path-0.3.4-py3-none-any.whl", hash = "sha256:f502191fdc2b22050f9a81c9237be9d27145b9001c55842bece5e94e382e52f8", size = 14810, upload-time = "2025-01-24T14:33:14.652Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/58/3485da8cb93d2f393bce453adeef16896751f14ba3e2024bc21dc9597646/jsonschema_path-0.3.4-py3-none-any.whl", hash = "sha256:f502191fdc2b22050f9a81c9237be9d27145b9001c55842bece5e94e382e52f8", size = 14810, upload-time = "2025-01-24T14:33:14.652Z" }, ] [[package]] name = "jsonschema-specifications" version = "2025.9.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "referencing" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, ] [[package]] name = "kaitaistruct" version = "0.10" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/04/dd60b9cb65d580ef6cb6eaee975ad1bdd22d46a3f51b07a1e0606710ea88/kaitaistruct-0.10.tar.gz", hash = "sha256:a044dee29173d6afbacf27bcac39daf89b654dd418cfa009ab82d9178a9ae52a", size = 7061, upload-time = "2022-07-09T00:34:06.729Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/04/dd60b9cb65d580ef6cb6eaee975ad1bdd22d46a3f51b07a1e0606710ea88/kaitaistruct-0.10.tar.gz", hash = "sha256:a044dee29173d6afbacf27bcac39daf89b654dd418cfa009ab82d9178a9ae52a", size = 7061, upload-time = "2022-07-09T00:34:06.729Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4e/bf/88ad23efc08708bda9a2647169828e3553bb2093a473801db61f75356395/kaitaistruct-0.10-py2.py3-none-any.whl", hash = "sha256:a97350919adbf37fda881f75e9365e2fb88d04832b7a4e57106ec70119efb235", size = 7013, upload-time = "2022-07-09T00:34:03.905Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4e/bf/88ad23efc08708bda9a2647169828e3553bb2093a473801db61f75356395/kaitaistruct-0.10-py2.py3-none-any.whl", hash = "sha256:a97350919adbf37fda881f75e9365e2fb88d04832b7a4e57106ec70119efb235", size = 7013, upload-time = "2022-07-09T00:34:03.905Z" }, ] [[package]] name = "keyring" version = "25.7.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "jaraco-classes" }, { name = "jaraco-context" }, @@ -1812,43 +1803,43 @@ dependencies = [ { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, { name = "secretstorage", marker = "sys_platform == 'linux'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, ] [[package]] name = "langchain" version = "1.2.10" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph" }, { name = "pydantic" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/16/22/a4d4ac98fc2e393537130bbfba0d71a8113e6f884d96f935923e247397fe/langchain-1.2.10.tar.gz", hash = "sha256:bdcd7218d9c79a413cf15e106e4eb94408ac0963df9333ccd095b9ed43bf3be7", size = 570071, upload-time = "2026-02-10T14:56:49.74Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/16/22/a4d4ac98fc2e393537130bbfba0d71a8113e6f884d96f935923e247397fe/langchain-1.2.10.tar.gz", hash = "sha256:bdcd7218d9c79a413cf15e106e4eb94408ac0963df9333ccd095b9ed43bf3be7", size = 570071, upload-time = "2026-02-10T14:56:49.74Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7c/06/c3394327f815fade875724c0f6cff529777c96a1e17fea066deb997f8cf5/langchain-1.2.10-py3-none-any.whl", hash = "sha256:e07a377204451fffaed88276b8193e894893b1003e25c5bca6539288ccca3698", size = 111738, upload-time = "2026-02-10T14:56:47.985Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7c/06/c3394327f815fade875724c0f6cff529777c96a1e17fea066deb997f8cf5/langchain-1.2.10-py3-none-any.whl", hash = "sha256:e07a377204451fffaed88276b8193e894893b1003e25c5bca6539288ccca3698", size = 111738, upload-time = "2026-02-10T14:56:47.985Z" }, ] [[package]] name = "langchain-anthropic" version = "1.3.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "anthropic" }, { name = "langchain-core" }, { name = "pydantic" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/48/cf217b3836099220737ff1f8fd07a554993080dfc9c0b4dd4af16ccb0604/langchain_anthropic-1.3.3.tar.gz", hash = "sha256:37198413c9bde5a9e9829f13c7b9ed4870d7085e7fba9fd803ef4d98ef8ea220", size = 686916, upload-time = "2026-02-10T21:02:28.924Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/48/cf217b3836099220737ff1f8fd07a554993080dfc9c0b4dd4af16ccb0604/langchain_anthropic-1.3.3.tar.gz", hash = "sha256:37198413c9bde5a9e9829f13c7b9ed4870d7085e7fba9fd803ef4d98ef8ea220", size = 686916, upload-time = "2026-02-10T21:02:28.924Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8c/f1/cf56d47964b6fe080cdc54c3e32bc05e560927d549b2634b39d14aaf6e05/langchain_anthropic-1.3.3-py3-none-any.whl", hash = "sha256:8008ce5fb680268681673e09f93a9ac08eba9e304477101e5e138f06b5cd8710", size = 46831, upload-time = "2026-02-10T21:02:27.386Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8c/f1/cf56d47964b6fe080cdc54c3e32bc05e560927d549b2634b39d14aaf6e05/langchain_anthropic-1.3.3-py3-none-any.whl", hash = "sha256:8008ce5fb680268681673e09f93a9ac08eba9e304477101e5e138f06b5cd8710", size = 46831, upload-time = "2026-02-10T21:02:27.386Z" }, ] [[package]] name = "langchain-core" version = "1.2.11" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "jsonpatch" }, { name = "langsmith" }, @@ -1859,58 +1850,58 @@ dependencies = [ { name = "typing-extensions" }, { name = "uuid-utils" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/12/17/1943cedfc118e04b8128e4c3e1dbf0fa0ea58eefddbb6198cfd699d19f01/langchain_core-1.2.11.tar.gz", hash = "sha256:f164bb36602dd74a3a50c1334fca75309ad5ed95767acdfdbb9fa95ce28a1e01", size = 831211, upload-time = "2026-02-10T20:35:28.35Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/12/17/1943cedfc118e04b8128e4c3e1dbf0fa0ea58eefddbb6198cfd699d19f01/langchain_core-1.2.11.tar.gz", hash = "sha256:f164bb36602dd74a3a50c1334fca75309ad5ed95767acdfdbb9fa95ce28a1e01", size = 831211, upload-time = "2026-02-10T20:35:28.35Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/10/30/1f80e3fc674353cad975ed5294353d42512535d2094ef032c06454c2c873/langchain_core-1.2.11-py3-none-any.whl", hash = "sha256:ae11ceb8dda60d0b9d09e763116e592f1683327c17be5b715f350fd29aee65d3", size = 500062, upload-time = "2026-02-10T20:35:26.698Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/30/1f80e3fc674353cad975ed5294353d42512535d2094ef032c06454c2c873/langchain_core-1.2.11-py3-none-any.whl", hash = "sha256:ae11ceb8dda60d0b9d09e763116e592f1683327c17be5b715f350fd29aee65d3", size = 500062, upload-time = "2026-02-10T20:35:26.698Z" }, ] [[package]] name = "langchain-google-genai" version = "4.2.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "filetype" }, { name = "google-genai" }, { name = "langchain-core" }, { name = "pydantic" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/0b/eae2305e207574dc633983a8a82a745e0ede1bce1f3a9daff24d2341fadc/langchain_google_genai-4.2.0.tar.gz", hash = "sha256:9a8d9bfc35354983ed29079cefff53c3e7c9c2a44b6ba75cc8f13a0cf8b55c33", size = 277361, upload-time = "2026-01-13T20:41:17.63Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/0b/eae2305e207574dc633983a8a82a745e0ede1bce1f3a9daff24d2341fadc/langchain_google_genai-4.2.0.tar.gz", hash = "sha256:9a8d9bfc35354983ed29079cefff53c3e7c9c2a44b6ba75cc8f13a0cf8b55c33", size = 277361, upload-time = "2026-01-13T20:41:17.63Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/22/51/39942c0083139652494bb354dddf0ed397703a4882302f7b48aeca531c96/langchain_google_genai-4.2.0-py3-none-any.whl", hash = "sha256:856041aaafceff65a4ef0d5acf5731f2db95229ff041132af011aec51e8279d9", size = 66452, upload-time = "2026-01-13T20:41:16.296Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/51/39942c0083139652494bb354dddf0ed397703a4882302f7b48aeca531c96/langchain_google_genai-4.2.0-py3-none-any.whl", hash = "sha256:856041aaafceff65a4ef0d5acf5731f2db95229ff041132af011aec51e8279d9", size = 66452, upload-time = "2026-01-13T20:41:16.296Z" }, ] [[package]] name = "langchain-mcp-adapters" version = "0.2.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "langchain-core" }, { name = "mcp" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d9/52/cebf0ef5b1acef6cbc63d671171d43af70f12d19f55577909c7afa79fb6e/langchain_mcp_adapters-0.2.1.tar.gz", hash = "sha256:58e64c44e8df29ca7eb3b656cf8c9931ef64386534d7ca261982e3bdc63f3176", size = 36394, upload-time = "2025-12-09T16:28:38.98Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/52/cebf0ef5b1acef6cbc63d671171d43af70f12d19f55577909c7afa79fb6e/langchain_mcp_adapters-0.2.1.tar.gz", hash = "sha256:58e64c44e8df29ca7eb3b656cf8c9931ef64386534d7ca261982e3bdc63f3176", size = 36394, upload-time = "2025-12-09T16:28:38.98Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/03/81/b2479eb26861ab36be851026d004b2d391d789b7856e44c272b12828ece0/langchain_mcp_adapters-0.2.1-py3-none-any.whl", hash = "sha256:9f96ad4c64230f6757297fec06fde19d772c99dbdfbca987f7b7cfd51ff77240", size = 22708, upload-time = "2025-12-09T16:28:37.877Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/03/81/b2479eb26861ab36be851026d004b2d391d789b7856e44c272b12828ece0/langchain_mcp_adapters-0.2.1-py3-none-any.whl", hash = "sha256:9f96ad4c64230f6757297fec06fde19d772c99dbdfbca987f7b7cfd51ff77240", size = 22708, upload-time = "2025-12-09T16:28:37.877Z" }, ] [[package]] name = "langchain-openai" version = "1.1.6" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "langchain-core" }, { name = "openai" }, { name = "tiktoken" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ae/67/228dc28b4498ea16422577013b5bb4ba35a1b99f8be975d6747c7a9f7e6a/langchain_openai-1.1.6.tar.gz", hash = "sha256:e306612654330ae36fb6bbe36db91c98534312afade19e140c3061fe4208dac8", size = 1038310, upload-time = "2025-12-18T17:58:52.84Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ae/67/228dc28b4498ea16422577013b5bb4ba35a1b99f8be975d6747c7a9f7e6a/langchain_openai-1.1.6.tar.gz", hash = "sha256:e306612654330ae36fb6bbe36db91c98534312afade19e140c3061fe4208dac8", size = 1038310, upload-time = "2025-12-18T17:58:52.84Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/db/5b/1f6521df83c1a8e8d3f52351883b59683e179c0aa1bec75d0a77a394c9e7/langchain_openai-1.1.6-py3-none-any.whl", hash = "sha256:c42d04a67a85cee1d994afe400800d2b09ebf714721345f0b651eb06a02c3948", size = 84701, upload-time = "2025-12-18T17:58:51.527Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/db/5b/1f6521df83c1a8e8d3f52351883b59683e179c0aa1bec75d0a77a394c9e7/langchain_openai-1.1.6-py3-none-any.whl", hash = "sha256:c42d04a67a85cee1d994afe400800d2b09ebf714721345f0b651eb06a02c3948", size = 84701, upload-time = "2025-12-18T17:58:51.527Z" }, ] [[package]] name = "langfuse" version = "3.11.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "backoff" }, { name = "httpx" }, @@ -1923,15 +1914,15 @@ dependencies = [ { name = "requests" }, { name = "wrapt" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/10/6b28f3b2c008b1f48478c4f45ceb956dfcc951910f5896b3fe44c20174db/langfuse-3.11.2.tar.gz", hash = "sha256:ab5f296a8056815b7288c7f25bc308a5e79f82a8634467b25daffdde99276e09", size = 230795, upload-time = "2025-12-23T20:42:57.177Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/10/6b28f3b2c008b1f48478c4f45ceb956dfcc951910f5896b3fe44c20174db/langfuse-3.11.2.tar.gz", hash = "sha256:ab5f296a8056815b7288c7f25bc308a5e79f82a8634467b25daffdde99276e09", size = 230795, upload-time = "2025-12-23T20:42:57.177Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/04/95407023b786ed2eef1e2cd220f5baf7b1dd70d88645af129cc1fd1da867/langfuse-3.11.2-py3-none-any.whl", hash = "sha256:84faea9f909694023cc7f0eb45696be190248c8790424f22af57ca4cd7a29f2d", size = 413786, upload-time = "2025-12-23T20:42:55.48Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/04/95407023b786ed2eef1e2cd220f5baf7b1dd70d88645af129cc1fd1da867/langfuse-3.11.2-py3-none-any.whl", hash = "sha256:84faea9f909694023cc7f0eb45696be190248c8790424f22af57ca4cd7a29f2d", size = 413786, upload-time = "2025-12-23T20:42:55.48Z" }, ] [[package]] name = "langgraph" version = "1.0.8" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, @@ -1940,69 +1931,69 @@ dependencies = [ { name = "pydantic" }, { name = "xxhash" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ca/49/e9551965d8a44dd9afdc55cbcdc5a9bd18bee6918cc2395b225d40adb77c/langgraph-1.0.8.tar.gz", hash = "sha256:2630fc578846995114fd659f8b14df9eff5a4e78c49413f67718725e88ceb544", size = 498708, upload-time = "2026-02-06T12:31:13.776Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/49/e9551965d8a44dd9afdc55cbcdc5a9bd18bee6918cc2395b225d40adb77c/langgraph-1.0.8.tar.gz", hash = "sha256:2630fc578846995114fd659f8b14df9eff5a4e78c49413f67718725e88ceb544", size = 498708, upload-time = "2026-02-06T12:31:13.776Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/72/b0d7fc1007821a08dfc03ce232f39f209aa4aa46414ea3d125b24e35093a/langgraph-1.0.8-py3-none-any.whl", hash = "sha256:da737177c024caad7e5262642bece4f54edf4cba2c905a1d1338963f41cf0904", size = 158144, upload-time = "2026-02-06T12:31:12.489Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/72/b0d7fc1007821a08dfc03ce232f39f209aa4aa46414ea3d125b24e35093a/langgraph-1.0.8-py3-none-any.whl", hash = "sha256:da737177c024caad7e5262642bece4f54edf4cba2c905a1d1338963f41cf0904", size = 158144, upload-time = "2026-02-06T12:31:12.489Z" }, ] [[package]] name = "langgraph-checkpoint" version = "3.0.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "langchain-core" }, { name = "ormsgpack" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/07/2b1c042fa87d40cf2db5ca27dc4e8dd86f9a0436a10aa4361a8982718ae7/langgraph_checkpoint-3.0.1.tar.gz", hash = "sha256:59222f875f85186a22c494aedc65c4e985a3df27e696e5016ba0b98a5ed2cee0", size = 137785, upload-time = "2025-11-04T21:55:47.774Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0f/07/2b1c042fa87d40cf2db5ca27dc4e8dd86f9a0436a10aa4361a8982718ae7/langgraph_checkpoint-3.0.1.tar.gz", hash = "sha256:59222f875f85186a22c494aedc65c4e985a3df27e696e5016ba0b98a5ed2cee0", size = 137785, upload-time = "2025-11-04T21:55:47.774Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/48/e3/616e3a7ff737d98c1bbb5700dd62278914e2a9ded09a79a1fa93cf24ce12/langgraph_checkpoint-3.0.1-py3-none-any.whl", hash = "sha256:9b04a8d0edc0474ce4eaf30c5d731cee38f11ddff50a6177eead95b5c4e4220b", size = 46249, upload-time = "2025-11-04T21:55:46.472Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/48/e3/616e3a7ff737d98c1bbb5700dd62278914e2a9ded09a79a1fa93cf24ce12/langgraph_checkpoint-3.0.1-py3-none-any.whl", hash = "sha256:9b04a8d0edc0474ce4eaf30c5d731cee38f11ddff50a6177eead95b5c4e4220b", size = 46249, upload-time = "2025-11-04T21:55:46.472Z" }, ] [[package]] name = "langgraph-checkpoint-postgres" version = "3.0.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "langgraph-checkpoint" }, { name = "orjson" }, { name = "psycopg" }, { name = "psycopg-pool" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/68/4e/ffea5b0d667e10d408b3b2d6dd967ea79e208eef73fe6ee5622625496238/langgraph_checkpoint_postgres-3.0.2.tar.gz", hash = "sha256:448cb8ec245b6fe10171a0f90e9aa047e24a9d3febba6a914644b0c1323da158", size = 127766, upload-time = "2025-12-09T23:15:31.223Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/68/4e/ffea5b0d667e10d408b3b2d6dd967ea79e208eef73fe6ee5622625496238/langgraph_checkpoint_postgres-3.0.2.tar.gz", hash = "sha256:448cb8ec245b6fe10171a0f90e9aa047e24a9d3febba6a914644b0c1323da158", size = 127766, upload-time = "2025-12-09T23:15:31.223Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ac/e4/b4248e10289b6e2c2d33586c87c5eb421e566ef5f336ee45269223cc3b92/langgraph_checkpoint_postgres-3.0.2-py3-none-any.whl", hash = "sha256:15c0fb638edfbc54d496f1758d0327d1a081e0ef94dda8f0c91d4b307d6d8545", size = 42710, upload-time = "2025-12-09T23:15:29.895Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/e4/b4248e10289b6e2c2d33586c87c5eb421e566ef5f336ee45269223cc3b92/langgraph_checkpoint_postgres-3.0.2-py3-none-any.whl", hash = "sha256:15c0fb638edfbc54d496f1758d0327d1a081e0ef94dda8f0c91d4b307d6d8545", size = 42710, upload-time = "2025-12-09T23:15:29.895Z" }, ] [[package]] name = "langgraph-prebuilt" version = "1.0.7" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/59/711aecd1a50999456850dc328f3cad72b4372d8218838d8d5326f80cb76f/langgraph_prebuilt-1.0.7.tar.gz", hash = "sha256:38e097e06de810de4d0e028ffc0e432bb56d1fb417620fb1dfdc76c5e03e4bf9", size = 163692, upload-time = "2026-01-22T16:45:22.801Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/59/711aecd1a50999456850dc328f3cad72b4372d8218838d8d5326f80cb76f/langgraph_prebuilt-1.0.7.tar.gz", hash = "sha256:38e097e06de810de4d0e028ffc0e432bb56d1fb417620fb1dfdc76c5e03e4bf9", size = 163692, upload-time = "2026-01-22T16:45:22.801Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/47/49/5e37abb3f38a17a3487634abc2a5da87c208cc1d14577eb8d7184b25c886/langgraph_prebuilt-1.0.7-py3-none-any.whl", hash = "sha256:e14923516504405bb5edc3977085bc9622c35476b50c1808544490e13871fe7c", size = 35324, upload-time = "2026-01-22T16:45:21.784Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/47/49/5e37abb3f38a17a3487634abc2a5da87c208cc1d14577eb8d7184b25c886/langgraph_prebuilt-1.0.7-py3-none-any.whl", hash = "sha256:e14923516504405bb5edc3977085bc9622c35476b50c1808544490e13871fe7c", size = 35324, upload-time = "2026-01-22T16:45:21.784Z" }, ] [[package]] name = "langgraph-sdk" version = "0.3.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "httpx" }, { name = "orjson" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a9/d3/b6be0b0aba2a53a8920a2b0b4328a83121ec03eea9952e576d06a4182f6f/langgraph_sdk-0.3.1.tar.gz", hash = "sha256:f6dadfd2444eeff3e01405a9005c95fb3a028d4bd954ebec80ea6150084f92bb", size = 130312, upload-time = "2025-12-18T22:11:47.42Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a9/d3/b6be0b0aba2a53a8920a2b0b4328a83121ec03eea9952e576d06a4182f6f/langgraph_sdk-0.3.1.tar.gz", hash = "sha256:f6dadfd2444eeff3e01405a9005c95fb3a028d4bd954ebec80ea6150084f92bb", size = 130312, upload-time = "2025-12-18T22:11:47.42Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ab/fe/0c1c9c01a154eba62b20b02fabe811fd94a2b810061ae9e4d8462b8cf85a/langgraph_sdk-0.3.1-py3-none-any.whl", hash = "sha256:0b856923bfd20bf3441ce9d03bef488aa333fb610e972618799a9d584436acad", size = 66517, upload-time = "2025-12-18T22:11:46.625Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ab/fe/0c1c9c01a154eba62b20b02fabe811fd94a2b810061ae9e4d8462b8cf85a/langgraph_sdk-0.3.1-py3-none-any.whl", hash = "sha256:0b856923bfd20bf3441ce9d03bef488aa333fb610e972618799a9d584436acad", size = 66517, upload-time = "2025-12-18T22:11:46.625Z" }, ] [[package]] name = "langsmith" version = "0.5.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "httpx" }, { name = "orjson", marker = "platform_python_implementation != 'PyPy'" }, @@ -2013,178 +2004,178 @@ dependencies = [ { name = "uuid-utils" }, { name = "zstandard" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/7e/e38706c85dde3865c4eeadb044a19e6c7de4f40e2be0cc9100d2ff6e82aa/langsmith-0.5.2.tar.gz", hash = "sha256:a6186d555ba59732b1b10e2ba6fe34ee0b3c1bf3a7fb8d7be0dec367ac3b75f1", size = 883096, upload-time = "2025-12-30T13:41:36.132Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/7e/e38706c85dde3865c4eeadb044a19e6c7de4f40e2be0cc9100d2ff6e82aa/langsmith-0.5.2.tar.gz", hash = "sha256:a6186d555ba59732b1b10e2ba6fe34ee0b3c1bf3a7fb8d7be0dec367ac3b75f1", size = 883096, upload-time = "2025-12-30T13:41:36.132Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ed/d8/91a8b483b30e0708a8911df10b4ce04ebf2b4b8dde8d020c124aec77380a/langsmith-0.5.2-py3-none-any.whl", hash = "sha256:42f8b853a18dd4d5f7fa38c8ff29e38da065a727022da410d91b3e13819aacc1", size = 283311, upload-time = "2025-12-30T13:41:33.915Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/d8/91a8b483b30e0708a8911df10b4ce04ebf2b4b8dde8d020c124aec77380a/langsmith-0.5.2-py3-none-any.whl", hash = "sha256:42f8b853a18dd4d5f7fa38c8ff29e38da065a727022da410d91b3e13819aacc1", size = 283311, upload-time = "2025-12-30T13:41:33.915Z" }, ] [[package]] name = "ldap3" version = "2.9.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pyasn1" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/ac/96bd5464e3edbc61595d0d69989f5d9969ae411866427b2500a8e5b812c0/ldap3-2.9.1.tar.gz", hash = "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f", size = 398830, upload-time = "2021-07-18T06:34:21.786Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/ac/96bd5464e3edbc61595d0d69989f5d9969ae411866427b2500a8e5b812c0/ldap3-2.9.1.tar.gz", hash = "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f", size = 398830, upload-time = "2021-07-18T06:34:21.786Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4e/f6/71d6ec9f18da0b2201287ce9db6afb1a1f637dedb3f0703409558981c723/ldap3-2.9.1-py2.py3-none-any.whl", hash = "sha256:5869596fc4948797020d3f03b7939da938778a0f9e2009f7a072ccf92b8e8d70", size = 432192, upload-time = "2021-07-18T06:34:12.905Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4e/f6/71d6ec9f18da0b2201287ce9db6afb1a1f637dedb3f0703409558981c723/ldap3-2.9.1-py2.py3-none-any.whl", hash = "sha256:5869596fc4948797020d3f03b7939da938778a0f9e2009f7a072ccf92b8e8d70", size = 432192, upload-time = "2021-07-18T06:34:12.905Z" }, ] [[package]] name = "librt" version = "0.7.5" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b5/8a/071f6628363d83e803d4783e0cd24fb9c5b798164300fcfaaa47c30659c0/librt-0.7.5.tar.gz", hash = "sha256:de4221a1181fa9c8c4b5f35506ed6f298948f44003d84d2a8b9885d7e01e6cfa", size = 145868, upload-time = "2025-12-25T03:53:16.039Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/33/9d/cb0a296cee177c0fee7999ada1c1af7eee0e2191372058814a4ca6d2baf0/librt-0.7.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba1077c562a046208a2dc6366227b3eeae8f2c2ab4b41eaf4fd2fa28cece4203", size = 55689, upload-time = "2025-12-25T03:52:14.041Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/79/5c/d7de4d4228b74c5b81a3fbada157754bb29f0e1f8c38229c669a7f90422a/librt-0.7.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:654fdc971c76348a73af5240d8e2529265b9a7ba6321e38dd5bae7b0d4ab3abe", size = 57142, upload-time = "2025-12-25T03:52:15.336Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/b2/5da779184aae369b69f4ae84225f63741662a0fe422e91616c533895d7a4/librt-0.7.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6b7b58913d475911f6f33e8082f19dd9b120c4f4a5c911d07e395d67b81c6982", size = 165323, upload-time = "2025-12-25T03:52:16.384Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/40/6d5abc15ab6cc70e04c4d201bb28baffff4cfb46ab950b8e90935b162d58/librt-0.7.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8e0fd344bad57026a8f4ccfaf406486c2fc991838050c2fef156170edc3b775", size = 174218, upload-time = "2025-12-25T03:52:17.518Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0d/d0/5239a8507e6117a3cb59ce0095bdd258bd2a93d8d4b819a506da06d8d645/librt-0.7.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:46aa91813c267c3f60db75d56419b42c0c0b9748ec2c568a0e3588e543fb4233", size = 189007, upload-time = "2025-12-25T03:52:18.585Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1f/a4/8eed1166ffddbb01c25363e4c4e655f4bac298debe9e5a2dcfaf942438a1/librt-0.7.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ddc0ab9dbc5f9ceaf2bf7a367bf01f2697660e908f6534800e88f43590b271db", size = 183962, upload-time = "2025-12-25T03:52:19.723Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a1/83/260e60aab2f5ccba04579c5c46eb3b855e51196fde6e2bcf6742d89140a8/librt-0.7.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7a488908a470451338607650f1c064175094aedebf4a4fa37890682e30ce0b57", size = 177611, upload-time = "2025-12-25T03:52:21.18Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/36/6dcfed0df41e9695665462bab59af15b7ed2b9c668d85c7ebadd022cbb76/librt-0.7.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e47fc52602ffc374e69bf1b76536dc99f7f6dd876bd786c8213eaa3598be030a", size = 199273, upload-time = "2025-12-25T03:52:22.25Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a6/b7/157149c8cffae6bc4293a52e0267860cee2398cb270798d94f1c8a69b9ae/librt-0.7.5-cp312-cp312-win32.whl", hash = "sha256:cda8b025875946ffff5a9a7590bf9acde3eb02cb6200f06a2d3e691ef3d9955b", size = 43191, upload-time = "2025-12-25T03:52:23.643Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f8/91/197dfeb8d3bdeb0a5344d0d8b3077f183ba5e76c03f158126f6072730998/librt-0.7.5-cp312-cp312-win_amd64.whl", hash = "sha256:b591c094afd0ffda820e931148c9e48dc31a556dc5b2b9b3cc552fa710d858e4", size = 49462, upload-time = "2025-12-25T03:52:24.637Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/03/ea/052a79454cc52081dfaa9a1c4c10a529f7a6a6805b2fac5805fea5b25975/librt-0.7.5-cp312-cp312-win_arm64.whl", hash = "sha256:532ddc6a8a6ca341b1cd7f4d999043e4c71a212b26fe9fd2e7f1e8bb4e873544", size = 42830, upload-time = "2025-12-25T03:52:25.944Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/9a/8f61e16de0ff76590af893cfb5b1aa5fa8b13e5e54433d0809c7033f59ed/librt-0.7.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b1795c4b2789b458fa290059062c2f5a297ddb28c31e704d27e161386469691a", size = 55750, upload-time = "2025-12-25T03:52:26.975Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/7c/a8a883804851a066f301e0bad22b462260b965d5c9e7fe3c5de04e6f91f8/librt-0.7.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2fcbf2e135c11f721193aa5f42ba112bb1046afafbffd407cbc81d8d735c74d0", size = 57170, upload-time = "2025-12-25T03:52:27.948Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d6/5d/b3b47facf5945be294cf8a835b03589f70ee0e791522f99ec6782ed738b3/librt-0.7.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c039bbf79a9a2498404d1ae7e29a6c175e63678d7a54013a97397c40aee026c5", size = 165834, upload-time = "2025-12-25T03:52:29.09Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b4/b6/b26910cd0a4e43e5d02aacaaea0db0d2a52e87660dca08293067ee05601a/librt-0.7.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3919c9407faeeee35430ae135e3a78acd4ecaaaa73767529e2c15ca1d73ba325", size = 174820, upload-time = "2025-12-25T03:52:30.463Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a5/a3/81feddd345d4c869b7a693135a462ae275f964fcbbe793d01ea56a84c2ee/librt-0.7.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:26b46620e1e0e45af510d9848ea0915e7040605dd2ae94ebefb6c962cbb6f7ec", size = 189609, upload-time = "2025-12-25T03:52:31.492Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/a9/31310796ef4157d1d37648bf4a3b84555319f14cee3e9bad7bdd7bfd9a35/librt-0.7.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9bbb8facc5375476d392990dd6a71f97e4cb42e2ac66f32e860f6e47299d5e89", size = 184589, upload-time = "2025-12-25T03:52:32.59Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/32/22/da3900544cb0ac6ab7a2857850158a0a093b86f92b264aa6c4a4f2355ff3/librt-0.7.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e9e9c988b5ffde7be02180f864cbd17c0b0c1231c235748912ab2afa05789c25", size = 178251, upload-time = "2025-12-25T03:52:33.745Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/db/77/78e02609846e78b9b8c8e361753b3dbac9a07e6d5b567fe518de9e074ab0/librt-0.7.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:edf6b465306215b19dbe6c3fb63cf374a8f3e1ad77f3b4c16544b83033bbb67b", size = 199852, upload-time = "2025-12-25T03:52:34.826Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2a/25/05706f6b346429c951582f1b3561f4d5e1418d0d7ba1a0c181237cd77b3b/librt-0.7.5-cp313-cp313-win32.whl", hash = "sha256:060bde69c3604f694bd8ae21a780fe8be46bb3dbb863642e8dfc75c931ca8eee", size = 43250, upload-time = "2025-12-25T03:52:35.905Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d9/59/c38677278ac0b9ae1afc611382ef6c9ea87f52ad257bd3d8d65f0eacdc6a/librt-0.7.5-cp313-cp313-win_amd64.whl", hash = "sha256:a82d5a0ee43aeae2116d7292c77cc8038f4841830ade8aa922e098933b468b9e", size = 49421, upload-time = "2025-12-25T03:52:36.895Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c0/47/1d71113df4a81de5fdfbd3d7244e05d3d67e89f25455c3380ca50b92741e/librt-0.7.5-cp313-cp313-win_arm64.whl", hash = "sha256:3c98a8d0ac9e2a7cb8ff8c53e5d6e8d82bfb2839abf144fdeaaa832f2a12aa45", size = 42827, upload-time = "2025-12-25T03:52:37.856Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b5/8a/071f6628363d83e803d4783e0cd24fb9c5b798164300fcfaaa47c30659c0/librt-0.7.5.tar.gz", hash = "sha256:de4221a1181fa9c8c4b5f35506ed6f298948f44003d84d2a8b9885d7e01e6cfa", size = 145868, upload-time = "2025-12-25T03:53:16.039Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/33/9d/cb0a296cee177c0fee7999ada1c1af7eee0e2191372058814a4ca6d2baf0/librt-0.7.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba1077c562a046208a2dc6366227b3eeae8f2c2ab4b41eaf4fd2fa28cece4203", size = 55689, upload-time = "2025-12-25T03:52:14.041Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/5c/d7de4d4228b74c5b81a3fbada157754bb29f0e1f8c38229c669a7f90422a/librt-0.7.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:654fdc971c76348a73af5240d8e2529265b9a7ba6321e38dd5bae7b0d4ab3abe", size = 57142, upload-time = "2025-12-25T03:52:15.336Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/b2/5da779184aae369b69f4ae84225f63741662a0fe422e91616c533895d7a4/librt-0.7.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6b7b58913d475911f6f33e8082f19dd9b120c4f4a5c911d07e395d67b81c6982", size = 165323, upload-time = "2025-12-25T03:52:16.384Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/40/6d5abc15ab6cc70e04c4d201bb28baffff4cfb46ab950b8e90935b162d58/librt-0.7.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8e0fd344bad57026a8f4ccfaf406486c2fc991838050c2fef156170edc3b775", size = 174218, upload-time = "2025-12-25T03:52:17.518Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0d/d0/5239a8507e6117a3cb59ce0095bdd258bd2a93d8d4b819a506da06d8d645/librt-0.7.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:46aa91813c267c3f60db75d56419b42c0c0b9748ec2c568a0e3588e543fb4233", size = 189007, upload-time = "2025-12-25T03:52:18.585Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1f/a4/8eed1166ffddbb01c25363e4c4e655f4bac298debe9e5a2dcfaf942438a1/librt-0.7.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ddc0ab9dbc5f9ceaf2bf7a367bf01f2697660e908f6534800e88f43590b271db", size = 183962, upload-time = "2025-12-25T03:52:19.723Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a1/83/260e60aab2f5ccba04579c5c46eb3b855e51196fde6e2bcf6742d89140a8/librt-0.7.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7a488908a470451338607650f1c064175094aedebf4a4fa37890682e30ce0b57", size = 177611, upload-time = "2025-12-25T03:52:21.18Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/36/6dcfed0df41e9695665462bab59af15b7ed2b9c668d85c7ebadd022cbb76/librt-0.7.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e47fc52602ffc374e69bf1b76536dc99f7f6dd876bd786c8213eaa3598be030a", size = 199273, upload-time = "2025-12-25T03:52:22.25Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a6/b7/157149c8cffae6bc4293a52e0267860cee2398cb270798d94f1c8a69b9ae/librt-0.7.5-cp312-cp312-win32.whl", hash = "sha256:cda8b025875946ffff5a9a7590bf9acde3eb02cb6200f06a2d3e691ef3d9955b", size = 43191, upload-time = "2025-12-25T03:52:23.643Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f8/91/197dfeb8d3bdeb0a5344d0d8b3077f183ba5e76c03f158126f6072730998/librt-0.7.5-cp312-cp312-win_amd64.whl", hash = "sha256:b591c094afd0ffda820e931148c9e48dc31a556dc5b2b9b3cc552fa710d858e4", size = 49462, upload-time = "2025-12-25T03:52:24.637Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/03/ea/052a79454cc52081dfaa9a1c4c10a529f7a6a6805b2fac5805fea5b25975/librt-0.7.5-cp312-cp312-win_arm64.whl", hash = "sha256:532ddc6a8a6ca341b1cd7f4d999043e4c71a212b26fe9fd2e7f1e8bb4e873544", size = 42830, upload-time = "2025-12-25T03:52:25.944Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/9a/8f61e16de0ff76590af893cfb5b1aa5fa8b13e5e54433d0809c7033f59ed/librt-0.7.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b1795c4b2789b458fa290059062c2f5a297ddb28c31e704d27e161386469691a", size = 55750, upload-time = "2025-12-25T03:52:26.975Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/7c/a8a883804851a066f301e0bad22b462260b965d5c9e7fe3c5de04e6f91f8/librt-0.7.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2fcbf2e135c11f721193aa5f42ba112bb1046afafbffd407cbc81d8d735c74d0", size = 57170, upload-time = "2025-12-25T03:52:27.948Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/5d/b3b47facf5945be294cf8a835b03589f70ee0e791522f99ec6782ed738b3/librt-0.7.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c039bbf79a9a2498404d1ae7e29a6c175e63678d7a54013a97397c40aee026c5", size = 165834, upload-time = "2025-12-25T03:52:29.09Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b4/b6/b26910cd0a4e43e5d02aacaaea0db0d2a52e87660dca08293067ee05601a/librt-0.7.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3919c9407faeeee35430ae135e3a78acd4ecaaaa73767529e2c15ca1d73ba325", size = 174820, upload-time = "2025-12-25T03:52:30.463Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a5/a3/81feddd345d4c869b7a693135a462ae275f964fcbbe793d01ea56a84c2ee/librt-0.7.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:26b46620e1e0e45af510d9848ea0915e7040605dd2ae94ebefb6c962cbb6f7ec", size = 189609, upload-time = "2025-12-25T03:52:31.492Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/a9/31310796ef4157d1d37648bf4a3b84555319f14cee3e9bad7bdd7bfd9a35/librt-0.7.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9bbb8facc5375476d392990dd6a71f97e4cb42e2ac66f32e860f6e47299d5e89", size = 184589, upload-time = "2025-12-25T03:52:32.59Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/32/22/da3900544cb0ac6ab7a2857850158a0a093b86f92b264aa6c4a4f2355ff3/librt-0.7.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e9e9c988b5ffde7be02180f864cbd17c0b0c1231c235748912ab2afa05789c25", size = 178251, upload-time = "2025-12-25T03:52:33.745Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/db/77/78e02609846e78b9b8c8e361753b3dbac9a07e6d5b567fe518de9e074ab0/librt-0.7.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:edf6b465306215b19dbe6c3fb63cf374a8f3e1ad77f3b4c16544b83033bbb67b", size = 199852, upload-time = "2025-12-25T03:52:34.826Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/25/05706f6b346429c951582f1b3561f4d5e1418d0d7ba1a0c181237cd77b3b/librt-0.7.5-cp313-cp313-win32.whl", hash = "sha256:060bde69c3604f694bd8ae21a780fe8be46bb3dbb863642e8dfc75c931ca8eee", size = 43250, upload-time = "2025-12-25T03:52:35.905Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/59/c38677278ac0b9ae1afc611382ef6c9ea87f52ad257bd3d8d65f0eacdc6a/librt-0.7.5-cp313-cp313-win_amd64.whl", hash = "sha256:a82d5a0ee43aeae2116d7292c77cc8038f4841830ade8aa922e098933b468b9e", size = 49421, upload-time = "2025-12-25T03:52:36.895Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/47/1d71113df4a81de5fdfbd3d7244e05d3d67e89f25455c3380ca50b92741e/librt-0.7.5-cp313-cp313-win_arm64.whl", hash = "sha256:3c98a8d0ac9e2a7cb8ff8c53e5d6e8d82bfb2839abf144fdeaaa832f2a12aa45", size = 42827, upload-time = "2025-12-25T03:52:37.856Z" }, ] [[package]] name = "loguru" version = "0.7.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "win32-setctime", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3a/05/a1dae3dffd1116099471c643b8924f5aa6524411dc6c63fdae648c4f1aca/loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6", size = 63559, upload-time = "2024-12-06T11:20:56.608Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/05/a1dae3dffd1116099471c643b8924f5aa6524411dc6c63fdae648c4f1aca/loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6", size = 63559, upload-time = "2024-12-06T11:20:56.608Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0c/29/0348de65b8cc732daa3e33e67806420b2ae89bdce2b04af740289c5c6c8c/loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c", size = 61595, upload-time = "2024-12-06T11:20:54.538Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0c/29/0348de65b8cc732daa3e33e67806420b2ae89bdce2b04af740289c5c6c8c/loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c", size = 61595, upload-time = "2024-12-06T11:20:54.538Z" }, ] [[package]] name = "lupa" version = "2.6" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b8/1c/191c3e6ec6502e3dbe25a53e27f69a5daeac3e56de1f73c0138224171ead/lupa-2.6.tar.gz", hash = "sha256:9a770a6e89576be3447668d7ced312cd6fd41d3c13c2462c9dc2c2ab570e45d9", size = 7240282, upload-time = "2025-10-24T07:20:29.738Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/94/86/ce243390535c39d53ea17ccf0240815e6e457e413e40428a658ea4ee4b8d/lupa-2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47ce718817ef1cc0c40d87c3d5ae56a800d61af00fbc0fad1ca9be12df2f3b56", size = 951707, upload-time = "2025-10-24T07:18:03.884Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/86/85/cedea5e6cbeb54396fdcc55f6b741696f3f036d23cfaf986d50d680446da/lupa-2.6-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7aba985b15b101495aa4b07112cdc08baa0c545390d560ad5cfde2e9e34f4d58", size = 1916703, upload-time = "2025-10-24T07:18:05.6Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/24/be/3d6b5f9a8588c01a4d88129284c726017b2089f3a3fd3ba8bd977292fea0/lupa-2.6-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:b766f62f95b2739f2248977d29b0722e589dcf4f0ccfa827ccbd29f0148bd2e5", size = 985152, upload-time = "2025-10-24T07:18:08.561Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/eb/23/9f9a05beee5d5dce9deca4cb07c91c40a90541fc0a8e09db4ee670da550f/lupa-2.6-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:00a934c23331f94cb51760097ebfab14b005d55a6b30a2b480e3c53dd2fa290d", size = 1159599, upload-time = "2025-10-24T07:18:10.346Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/40/4e/e7c0583083db9d7f1fd023800a9767d8e4391e8330d56c2373d890ac971b/lupa-2.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21de9f38bd475303e34a042b7081aabdf50bd9bafd36ce4faea2f90fd9f15c31", size = 1038686, upload-time = "2025-10-24T07:18:12.112Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/9f/5a4f7d959d4feba5e203ff0c31889e74d1ca3153122be4a46dca7d92bf7c/lupa-2.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf3bda96d3fc41237e964a69c23647d50d4e28421111360274d4799832c560e9", size = 2071956, upload-time = "2025-10-24T07:18:14.572Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/92/34/2f4f13ca65d01169b1720176aedc4af17bc19ee834598c7292db232cb6dc/lupa-2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a76ead245da54801a81053794aa3975f213221f6542d14ec4b859ee2e7e0323", size = 1057199, upload-time = "2025-10-24T07:18:16.379Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/35/2a/5f7d2eebec6993b0dcd428e0184ad71afb06a45ba13e717f6501bfed1da3/lupa-2.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8dd0861741caa20886ddbda0a121d8e52fb9b5bb153d82fa9bba796962bf30e8", size = 1173693, upload-time = "2025-10-24T07:18:18.153Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e4/29/089b4d2f8e34417349af3904bb40bec40b65c8731f45e3fd8d497ca573e5/lupa-2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:239e63948b0b23023f81d9a19a395e768ed3da6a299f84e7963b8f813f6e3f9c", size = 2164394, upload-time = "2025-10-24T07:18:20.403Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f3/1b/79c17b23c921f81468a111cad843b076a17ef4b684c4a8dff32a7969c3f0/lupa-2.6-cp312-cp312-win32.whl", hash = "sha256:325894e1099499e7a6f9c351147661a2011887603c71086d36fe0f964d52d1ce", size = 1420647, upload-time = "2025-10-24T07:18:23.368Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b8/15/5121e68aad3584e26e1425a5c9a79cd898f8a152292059e128c206ee817c/lupa-2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c735a1ce8ee60edb0fe71d665f1e6b7c55c6021f1d340eb8c865952c602cd36f", size = 1688529, upload-time = "2025-10-24T07:18:25.523Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/28/1d/21176b682ca5469001199d8b95fa1737e29957a3d185186e7a8b55345f2e/lupa-2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:663a6e58a0f60e7d212017d6678639ac8df0119bc13c2145029dcba084391310", size = 947232, upload-time = "2025-10-24T07:18:27.878Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/4c/d327befb684660ca13cf79cd1f1d604331808f9f1b6fb6bf57832f8edf80/lupa-2.6-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:d1f5afda5c20b1f3217a80e9bc1b77037f8a6eb11612fd3ada19065303c8f380", size = 1908625, upload-time = "2025-10-24T07:18:29.944Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/66/8e/ad22b0a19454dfd08662237a84c792d6d420d36b061f239e084f29d1a4f3/lupa-2.6-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:26f2b3c085fe76e9119e48c1013c1cccdc1f51585d456858290475aa38e7089e", size = 981057, upload-time = "2025-10-24T07:18:31.553Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5c/48/74859073ab276bd0566c719f9ca0108b0cfc1956ca0d68678d117d47d155/lupa-2.6-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:60d2f902c7b96fb8ab98493dcff315e7bb4d0b44dc9dd76eb37de575025d5685", size = 1156227, upload-time = "2025-10-24T07:18:33.981Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/09/6c/0e9ded061916877253c2266074060eb71ed99fb21d73c8c114a76725bce2/lupa-2.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a02d25dee3a3250967c36590128d9220ae02f2eda166a24279da0b481519cbff", size = 1035752, upload-time = "2025-10-24T07:18:36.32Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dd/ef/f8c32e454ef9f3fe909f6c7d57a39f950996c37a3deb7b391fec7903dab7/lupa-2.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6eae1ee16b886b8914ff292dbefbf2f48abfbdee94b33a88d1d5475e02423203", size = 2069009, upload-time = "2025-10-24T07:18:38.072Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/53/dc/15b80c226a5225815a890ee1c11f07968e0aba7a852df41e8ae6fe285063/lupa-2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0edd5073a4ee74ab36f74fe61450148e6044f3952b8d21248581f3c5d1a58be", size = 1056301, upload-time = "2025-10-24T07:18:40.165Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/14/2086c1425c985acfb30997a67e90c39457122df41324d3c179d6ee2292c6/lupa-2.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c53ee9f22a8a17e7d4266ad48e86f43771951797042dd51d1494aaa4f5f3f0a", size = 1170673, upload-time = "2025-10-24T07:18:42.426Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/10/e5/b216c054cf86576c0191bf9a9f05de6f7e8e07164897d95eea0078dca9b2/lupa-2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:de7c0f157a9064a400d828789191a96da7f4ce889969a588b87ec80de9b14772", size = 2162227, upload-time = "2025-10-24T07:18:46.112Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/2f/33ecb5bedf4f3bc297ceacb7f016ff951331d352f58e7e791589609ea306/lupa-2.6-cp313-cp313-win32.whl", hash = "sha256:ee9523941ae0a87b5b703417720c5d78f72d2f5bc23883a2ea80a949a3ed9e75", size = 1419558, upload-time = "2025-10-24T07:18:48.371Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/b4/55e885834c847ea610e111d87b9ed4768f0afdaeebc00cd46810f25029f6/lupa-2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b1335a5835b0a25ebdbc75cf0bda195e54d133e4d994877ef025e218c2e59db9", size = 1683424, upload-time = "2025-10-24T07:18:50.976Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b8/1c/191c3e6ec6502e3dbe25a53e27f69a5daeac3e56de1f73c0138224171ead/lupa-2.6.tar.gz", hash = "sha256:9a770a6e89576be3447668d7ced312cd6fd41d3c13c2462c9dc2c2ab570e45d9", size = 7240282, upload-time = "2025-10-24T07:20:29.738Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/94/86/ce243390535c39d53ea17ccf0240815e6e457e413e40428a658ea4ee4b8d/lupa-2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47ce718817ef1cc0c40d87c3d5ae56a800d61af00fbc0fad1ca9be12df2f3b56", size = 951707, upload-time = "2025-10-24T07:18:03.884Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/86/85/cedea5e6cbeb54396fdcc55f6b741696f3f036d23cfaf986d50d680446da/lupa-2.6-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7aba985b15b101495aa4b07112cdc08baa0c545390d560ad5cfde2e9e34f4d58", size = 1916703, upload-time = "2025-10-24T07:18:05.6Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/24/be/3d6b5f9a8588c01a4d88129284c726017b2089f3a3fd3ba8bd977292fea0/lupa-2.6-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:b766f62f95b2739f2248977d29b0722e589dcf4f0ccfa827ccbd29f0148bd2e5", size = 985152, upload-time = "2025-10-24T07:18:08.561Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/eb/23/9f9a05beee5d5dce9deca4cb07c91c40a90541fc0a8e09db4ee670da550f/lupa-2.6-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:00a934c23331f94cb51760097ebfab14b005d55a6b30a2b480e3c53dd2fa290d", size = 1159599, upload-time = "2025-10-24T07:18:10.346Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/40/4e/e7c0583083db9d7f1fd023800a9767d8e4391e8330d56c2373d890ac971b/lupa-2.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21de9f38bd475303e34a042b7081aabdf50bd9bafd36ce4faea2f90fd9f15c31", size = 1038686, upload-time = "2025-10-24T07:18:12.112Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/9f/5a4f7d959d4feba5e203ff0c31889e74d1ca3153122be4a46dca7d92bf7c/lupa-2.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf3bda96d3fc41237e964a69c23647d50d4e28421111360274d4799832c560e9", size = 2071956, upload-time = "2025-10-24T07:18:14.572Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/92/34/2f4f13ca65d01169b1720176aedc4af17bc19ee834598c7292db232cb6dc/lupa-2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a76ead245da54801a81053794aa3975f213221f6542d14ec4b859ee2e7e0323", size = 1057199, upload-time = "2025-10-24T07:18:16.379Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/35/2a/5f7d2eebec6993b0dcd428e0184ad71afb06a45ba13e717f6501bfed1da3/lupa-2.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8dd0861741caa20886ddbda0a121d8e52fb9b5bb153d82fa9bba796962bf30e8", size = 1173693, upload-time = "2025-10-24T07:18:18.153Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e4/29/089b4d2f8e34417349af3904bb40bec40b65c8731f45e3fd8d497ca573e5/lupa-2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:239e63948b0b23023f81d9a19a395e768ed3da6a299f84e7963b8f813f6e3f9c", size = 2164394, upload-time = "2025-10-24T07:18:20.403Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/1b/79c17b23c921f81468a111cad843b076a17ef4b684c4a8dff32a7969c3f0/lupa-2.6-cp312-cp312-win32.whl", hash = "sha256:325894e1099499e7a6f9c351147661a2011887603c71086d36fe0f964d52d1ce", size = 1420647, upload-time = "2025-10-24T07:18:23.368Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b8/15/5121e68aad3584e26e1425a5c9a79cd898f8a152292059e128c206ee817c/lupa-2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c735a1ce8ee60edb0fe71d665f1e6b7c55c6021f1d340eb8c865952c602cd36f", size = 1688529, upload-time = "2025-10-24T07:18:25.523Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/28/1d/21176b682ca5469001199d8b95fa1737e29957a3d185186e7a8b55345f2e/lupa-2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:663a6e58a0f60e7d212017d6678639ac8df0119bc13c2145029dcba084391310", size = 947232, upload-time = "2025-10-24T07:18:27.878Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/4c/d327befb684660ca13cf79cd1f1d604331808f9f1b6fb6bf57832f8edf80/lupa-2.6-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:d1f5afda5c20b1f3217a80e9bc1b77037f8a6eb11612fd3ada19065303c8f380", size = 1908625, upload-time = "2025-10-24T07:18:29.944Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/8e/ad22b0a19454dfd08662237a84c792d6d420d36b061f239e084f29d1a4f3/lupa-2.6-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:26f2b3c085fe76e9119e48c1013c1cccdc1f51585d456858290475aa38e7089e", size = 981057, upload-time = "2025-10-24T07:18:31.553Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/48/74859073ab276bd0566c719f9ca0108b0cfc1956ca0d68678d117d47d155/lupa-2.6-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:60d2f902c7b96fb8ab98493dcff315e7bb4d0b44dc9dd76eb37de575025d5685", size = 1156227, upload-time = "2025-10-24T07:18:33.981Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/09/6c/0e9ded061916877253c2266074060eb71ed99fb21d73c8c114a76725bce2/lupa-2.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a02d25dee3a3250967c36590128d9220ae02f2eda166a24279da0b481519cbff", size = 1035752, upload-time = "2025-10-24T07:18:36.32Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dd/ef/f8c32e454ef9f3fe909f6c7d57a39f950996c37a3deb7b391fec7903dab7/lupa-2.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6eae1ee16b886b8914ff292dbefbf2f48abfbdee94b33a88d1d5475e02423203", size = 2069009, upload-time = "2025-10-24T07:18:38.072Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/53/dc/15b80c226a5225815a890ee1c11f07968e0aba7a852df41e8ae6fe285063/lupa-2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0edd5073a4ee74ab36f74fe61450148e6044f3952b8d21248581f3c5d1a58be", size = 1056301, upload-time = "2025-10-24T07:18:40.165Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/14/2086c1425c985acfb30997a67e90c39457122df41324d3c179d6ee2292c6/lupa-2.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c53ee9f22a8a17e7d4266ad48e86f43771951797042dd51d1494aaa4f5f3f0a", size = 1170673, upload-time = "2025-10-24T07:18:42.426Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/e5/b216c054cf86576c0191bf9a9f05de6f7e8e07164897d95eea0078dca9b2/lupa-2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:de7c0f157a9064a400d828789191a96da7f4ce889969a588b87ec80de9b14772", size = 2162227, upload-time = "2025-10-24T07:18:46.112Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/2f/33ecb5bedf4f3bc297ceacb7f016ff951331d352f58e7e791589609ea306/lupa-2.6-cp313-cp313-win32.whl", hash = "sha256:ee9523941ae0a87b5b703417720c5d78f72d2f5bc23883a2ea80a949a3ed9e75", size = 1419558, upload-time = "2025-10-24T07:18:48.371Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/b4/55e885834c847ea610e111d87b9ed4768f0afdaeebc00cd46810f25029f6/lupa-2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b1335a5835b0a25ebdbc75cf0bda195e54d133e4d994877ef025e218c2e59db9", size = 1683424, upload-time = "2025-10-24T07:18:50.976Z" }, ] [[package]] name = "mako" version = "1.3.10" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9e/38/bd5b78a920a64d708fe6bc8e0a2c075e1389d53bef8413725c63ba041535/mako-1.3.10.tar.gz", hash = "sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28", size = 392474, upload-time = "2025-04-10T12:44:31.16Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9e/38/bd5b78a920a64d708fe6bc8e0a2c075e1389d53bef8413725c63ba041535/mako-1.3.10.tar.gz", hash = "sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28", size = 392474, upload-time = "2025-04-10T12:44:31.16Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl", hash = "sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59", size = 78509, upload-time = "2025-04-10T12:50:53.297Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/87/fb/99f81ac72ae23375f22b7afdb7642aba97c00a713c217124420147681a2f/mako-1.3.10-py3-none-any.whl", hash = "sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59", size = 78509, upload-time = "2025-04-10T12:50:53.297Z" }, ] [[package]] name = "markdown-it-py" version = "4.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "mdurl" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, ] [[package]] name = "markdownify" version = "1.2.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "beautifulsoup4" }, { name = "six" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3f/bc/c8c8eea5335341306b0fa7e1cb33c5e1c8d24ef70ddd684da65f41c49c92/markdownify-1.2.2.tar.gz", hash = "sha256:b274f1b5943180b031b699b199cbaeb1e2ac938b75851849a31fd0c3d6603d09", size = 18816, upload-time = "2025-11-16T19:21:18.565Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3f/bc/c8c8eea5335341306b0fa7e1cb33c5e1c8d24ef70ddd684da65f41c49c92/markdownify-1.2.2.tar.gz", hash = "sha256:b274f1b5943180b031b699b199cbaeb1e2ac938b75851849a31fd0c3d6603d09", size = 18816, upload-time = "2025-11-16T19:21:18.565Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/ce/f1e3e9d959db134cedf06825fae8d5b294bd368aacdd0831a3975b7c4d55/markdownify-1.2.2-py3-none-any.whl", hash = "sha256:3f02d3cc52714084d6e589f70397b6fc9f2f3a8531481bf35e8cc39f975e186a", size = 15724, upload-time = "2025-11-16T19:21:17.622Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/ce/f1e3e9d959db134cedf06825fae8d5b294bd368aacdd0831a3975b7c4d55/markdownify-1.2.2-py3-none-any.whl", hash = "sha256:3f02d3cc52714084d6e589f70397b6fc9f2f3a8531481bf35e8cc39f975e186a", size = 15724, upload-time = "2025-11-16T19:21:17.622Z" }, ] [[package]] name = "markupsafe" version = "3.0.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, ] [[package]] name = "mcp" version = "1.25.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "anyio" }, { name = "httpx" }, @@ -2201,33 +2192,33 @@ dependencies = [ { name = "typing-inspection" }, { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d5/2d/649d80a0ecf6a1f82632ca44bec21c0461a9d9fc8934d38cb5b319f2db5e/mcp-1.25.0.tar.gz", hash = "sha256:56310361ebf0364e2d438e5b45f7668cbb124e158bb358333cd06e49e83a6802", size = 605387, upload-time = "2025-12-19T10:19:56.985Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d5/2d/649d80a0ecf6a1f82632ca44bec21c0461a9d9fc8934d38cb5b319f2db5e/mcp-1.25.0.tar.gz", hash = "sha256:56310361ebf0364e2d438e5b45f7668cbb124e158bb358333cd06e49e83a6802", size = 605387, upload-time = "2025-12-19T10:19:56.985Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e2/fc/6dc7659c2ae5ddf280477011f4213a74f806862856b796ef08f028e664bf/mcp-1.25.0-py3-none-any.whl", hash = "sha256:b37c38144a666add0862614cc79ec276e97d72aa8ca26d622818d4e278b9721a", size = 233076, upload-time = "2025-12-19T10:19:55.416Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e2/fc/6dc7659c2ae5ddf280477011f4213a74f806862856b796ef08f028e664bf/mcp-1.25.0-py3-none-any.whl", hash = "sha256:b37c38144a666add0862614cc79ec276e97d72aa8ca26d622818d4e278b9721a", size = 233076, upload-time = "2025-12-19T10:19:55.416Z" }, ] [[package]] name = "mdurl" version = "0.1.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/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://pypi.tuna.tsinghua.edu.cn/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 = "minidump" version = "0.0.24" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/4b/bc695b99dc7d77d28223765c3ee5a31d34fd2850c52eb683ccdd1206067d/minidump-0.0.24.tar.gz", hash = "sha256:f7ae09b944f3b17ccf5cecc66f9ff5a7a45b053474a13aeb012f4c9204470437", size = 60709, upload-time = "2024-08-15T14:54:22.728Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/4b/bc695b99dc7d77d28223765c3ee5a31d34fd2850c52eb683ccdd1206067d/minidump-0.0.24.tar.gz", hash = "sha256:f7ae09b944f3b17ccf5cecc66f9ff5a7a45b053474a13aeb012f4c9204470437", size = 60709, upload-time = "2024-08-15T14:54:22.728Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/8b/3a148750e6d65f4fe6e249f6d0d6c497eeadd867a63ed69cee3fa17e7c83/minidump-0.0.24-py3-none-any.whl", hash = "sha256:9c016e35c8fe37c82a01b0a266f5416a0b0138934d92affb436ac2e72372bec6", size = 78365, upload-time = "2024-08-15T14:54:21.124Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/8b/3a148750e6d65f4fe6e249f6d0d6c497eeadd867a63ed69cee3fa17e7c83/minidump-0.0.24-py3-none-any.whl", hash = "sha256:9c016e35c8fe37c82a01b0a266f5416a0b0138934d92affb436ac2e72372bec6", size = 78365, upload-time = "2024-08-15T14:54:21.124Z" }, ] [[package]] name = "mitmproxy" version = "11.1.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "aioquic" }, { name = "argon2-cffi" }, @@ -2257,293 +2248,293 @@ dependencies = [ { name = "zstandard" }, ] wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/14/07/0a8528ea8d4e08a7cf19bf41158d3fcd0baad3686059ae54ee2d647d81db/mitmproxy-11.1.3-py3-none-any.whl", hash = "sha256:2305880b46465d1a9bdcdac369655826f588d05f382b082249a3e532a0e52952", size = 1662554, upload-time = "2025-02-17T12:10:28.138Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/07/0a8528ea8d4e08a7cf19bf41158d3fcd0baad3686059ae54ee2d647d81db/mitmproxy-11.1.3-py3-none-any.whl", hash = "sha256:2305880b46465d1a9bdcdac369655826f588d05f382b082249a3e532a0e52952", size = 1662554, upload-time = "2025-02-17T12:10:28.138Z" }, ] [[package]] name = "mitmproxy-linux" version = "0.11.5" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c1/81/aebf603418ad01c70d2944e45f646889693cedd89c2993a2c4e3dc975b07/mitmproxy_linux-0.11.5.tar.gz", hash = "sha256:ee3782fe4e7ccc6a899fa0ef5ad3e35a3ec358587304bd4d212188d2462c8f82", size = 1285776, upload-time = "2025-02-17T11:54:42.132Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/81/aebf603418ad01c70d2944e45f646889693cedd89c2993a2c4e3dc975b07/mitmproxy_linux-0.11.5.tar.gz", hash = "sha256:ee3782fe4e7ccc6a899fa0ef5ad3e35a3ec358587304bd4d212188d2462c8f82", size = 1285776, upload-time = "2025-02-17T11:54:42.132Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/81/ed/f864f39e733f6ecaaddf894c0f295983a6b5b09055d00a659eb08001b0d1/mitmproxy_linux-0.11.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7ce0b91d7a510009d532e6abbebe59f027a011fa745b13faa5b4d9ebe92abf5", size = 962015, upload-time = "2025-02-17T11:54:24.592Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/0c/5cc04ac3b7bb21b464d1109745ddfbdefc478ca0501b6cb5f7a91edd8516/mitmproxy_linux-0.11.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6a31faf244a9e3d44db02e3e3301aa2e699da67188820982a93028884f4cba8", size = 1040306, upload-time = "2025-02-17T11:54:26.199Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/f8/25d0483cd26fd6488c7fc16f0f8797ec19104863bff6bb3ee7dc56995b69/mitmproxy_linux-0.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544be1db84575fc8ecc71fb566032cabe4a65a4891d5bd0dc688e3023b49a18a", size = 962015, upload-time = "2025-02-17T11:54:28.547Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/80/12/6a9f189f7aa0b8dfb1c2017b41f2fdb43d64b32e30d1f5fa7e6aeb69c218/mitmproxy_linux-0.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00a40d08a1522d5718e9ff87458a950f06f62e5374d154d851122c0eb41c5dc0", size = 1040306, upload-time = "2025-02-17T11:54:30.611Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/81/ed/f864f39e733f6ecaaddf894c0f295983a6b5b09055d00a659eb08001b0d1/mitmproxy_linux-0.11.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7ce0b91d7a510009d532e6abbebe59f027a011fa745b13faa5b4d9ebe92abf5", size = 962015, upload-time = "2025-02-17T11:54:24.592Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/0c/5cc04ac3b7bb21b464d1109745ddfbdefc478ca0501b6cb5f7a91edd8516/mitmproxy_linux-0.11.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6a31faf244a9e3d44db02e3e3301aa2e699da67188820982a93028884f4cba8", size = 1040306, upload-time = "2025-02-17T11:54:26.199Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/f8/25d0483cd26fd6488c7fc16f0f8797ec19104863bff6bb3ee7dc56995b69/mitmproxy_linux-0.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544be1db84575fc8ecc71fb566032cabe4a65a4891d5bd0dc688e3023b49a18a", size = 962015, upload-time = "2025-02-17T11:54:28.547Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/80/12/6a9f189f7aa0b8dfb1c2017b41f2fdb43d64b32e30d1f5fa7e6aeb69c218/mitmproxy_linux-0.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00a40d08a1522d5718e9ff87458a950f06f62e5374d154d851122c0eb41c5dc0", size = 1040306, upload-time = "2025-02-17T11:54:30.611Z" }, ] [[package]] name = "mitmproxy-macos" version = "0.11.5" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9d/e5/060bb75c98120f5a2fc0cde20f376cc947e5b8474cb2d8ebabade69fbf8f/mitmproxy_macos-0.11.5-py3-none-any.whl", hash = "sha256:8f7aaa646acc64ba4790a7f4d46cb9fbfd7cb0411b9b7a567db0404864bff28d", size = 2658276, upload-time = "2025-02-17T11:54:31.833Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/e5/060bb75c98120f5a2fc0cde20f376cc947e5b8474cb2d8ebabade69fbf8f/mitmproxy_macos-0.11.5-py3-none-any.whl", hash = "sha256:8f7aaa646acc64ba4790a7f4d46cb9fbfd7cb0411b9b7a567db0404864bff28d", size = 2658276, upload-time = "2025-02-17T11:54:31.833Z" }, ] [[package]] name = "mitmproxy-rs" version = "0.11.5" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "mitmproxy-linux", marker = "sys_platform == 'linux'" }, { name = "mitmproxy-macos", marker = "sys_platform == 'darwin'" }, { name = "mitmproxy-windows", marker = "os_name == 'nt'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/fc/a944a0efa89606efde1f8d8acfd763b69b8d13d5d84d8f8ea79939682204/mitmproxy_rs-0.11.5.tar.gz", hash = "sha256:05f0da03165c2ee2803f91e6648bc9409692f42d796cbaf3fec5a20754ca8c39", size = 1296760, upload-time = "2025-02-17T11:54:43.933Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/fc/a944a0efa89606efde1f8d8acfd763b69b8d13d5d84d8f8ea79939682204/mitmproxy_rs-0.11.5.tar.gz", hash = "sha256:05f0da03165c2ee2803f91e6648bc9409692f42d796cbaf3fec5a20754ca8c39", size = 1296760, upload-time = "2025-02-17T11:54:43.933Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/63/18/91a37552505b5e1baea555425f8ab30694cf6e16a34e2a528e0ae70ca6b1/mitmproxy_rs-0.11.5-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:2f668dc92573cc3c3ba8c75b166276d846ce7321daf37f4a68bd837538298c5c", size = 3811905, upload-time = "2025-02-17T11:54:34.21Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/97/a2/aa81e54a27572b4d9503e79e9999019fdf4c1e1f2a7b8a083a7fa01f7bd6/mitmproxy_rs-0.11.5-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971241cb70bad87b55f12bc6e8d7dd3efd02a1acbe1730703e2cfeeb6edd3908", size = 1512445, upload-time = "2025-02-17T11:54:35.766Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/29/34/430966c7a5dc998dec4e9f73d5628b2ccadaf73c26697020ad87e5183e16/mitmproxy_rs-0.11.5-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a4ffe6d20b3a0edb47b40cd60e7b62709c29e8adf2573514cc0abd1442acf63", size = 1605733, upload-time = "2025-02-17T11:54:37Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/13/a7/43999d162b44b5848c0d663790027711927bded4b506a01f3f36d386d57f/mitmproxy_rs-0.11.5-cp310-abi3-win_amd64.whl", hash = "sha256:5353ad0c828aaa37ac53511f3960e39c0888848565f5faa3ea09e205ed8a7350", size = 1539652, upload-time = "2025-02-17T11:54:38.531Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/63/18/91a37552505b5e1baea555425f8ab30694cf6e16a34e2a528e0ae70ca6b1/mitmproxy_rs-0.11.5-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:2f668dc92573cc3c3ba8c75b166276d846ce7321daf37f4a68bd837538298c5c", size = 3811905, upload-time = "2025-02-17T11:54:34.21Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/a2/aa81e54a27572b4d9503e79e9999019fdf4c1e1f2a7b8a083a7fa01f7bd6/mitmproxy_rs-0.11.5-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971241cb70bad87b55f12bc6e8d7dd3efd02a1acbe1730703e2cfeeb6edd3908", size = 1512445, upload-time = "2025-02-17T11:54:35.766Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/29/34/430966c7a5dc998dec4e9f73d5628b2ccadaf73c26697020ad87e5183e16/mitmproxy_rs-0.11.5-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a4ffe6d20b3a0edb47b40cd60e7b62709c29e8adf2573514cc0abd1442acf63", size = 1605733, upload-time = "2025-02-17T11:54:37Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/13/a7/43999d162b44b5848c0d663790027711927bded4b506a01f3f36d386d57f/mitmproxy_rs-0.11.5-cp310-abi3-win_amd64.whl", hash = "sha256:5353ad0c828aaa37ac53511f3960e39c0888848565f5faa3ea09e205ed8a7350", size = 1539652, upload-time = "2025-02-17T11:54:38.531Z" }, ] [[package]] name = "mitmproxy-windows" version = "0.11.5" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/4e/65804c55c0457e87c33e94b3c92421e4519337dd17a747795ef9c507da95/mitmproxy_windows-0.11.5-py3-none-any.whl", hash = "sha256:76035ddf3067b07a2200e286a9fdb3d447cd4a9755dca1d5cb06935947b52592", size = 480403, upload-time = "2025-02-17T11:54:40.204Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/4e/65804c55c0457e87c33e94b3c92421e4519337dd17a747795ef9c507da95/mitmproxy_windows-0.11.5-py3-none-any.whl", hash = "sha256:76035ddf3067b07a2200e286a9fdb3d447cd4a9755dca1d5cb06935947b52592", size = 480403, upload-time = "2025-02-17T11:54:40.204Z" }, ] [[package]] name = "more-itertools" version = "10.8.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/5d/38b681d3fce7a266dd9ab73c66959406d565b3e85f21d5e66e1181d93721/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd", size = 137431, upload-time = "2025-09-02T15:23:11.018Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/5d/38b681d3fce7a266dd9ab73c66959406d565b3e85f21d5e66e1181d93721/more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd", size = 137431, upload-time = "2025-09-02T15:23:11.018Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" }, ] [[package]] name = "mpmath" version = "1.3.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" }, ] [[package]] name = "msgpack" version = "1.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/d0/7555686ae7ff5731205df1012ede15dd9d927f6227ea151e901c7406af4f/msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", size = 167260, upload-time = "2024-09-10T04:25:52.197Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e1/d6/716b7ca1dbde63290d2973d22bbef1b5032ca634c3ff4384a958ec3f093a/msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d", size = 152421, upload-time = "2024-09-10T04:25:49.63Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/70/da/5312b067f6773429cec2f8f08b021c06af416bba340c912c2ec778539ed6/msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2", size = 85277, upload-time = "2024-09-10T04:24:48.562Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/28/51/da7f3ae4462e8bb98af0d5bdf2707f1b8c65a0d4f496e46b6afb06cbc286/msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420", size = 82222, upload-time = "2024-09-10T04:25:36.49Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/33/af/dc95c4b2a49cff17ce47611ca9ba218198806cad7796c0b01d1e332c86bb/msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2", size = 392971, upload-time = "2024-09-10T04:24:58.129Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f1/54/65af8de681fa8255402c80eda2a501ba467921d5a7a028c9c22a2c2eedb5/msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39", size = 401403, upload-time = "2024-09-10T04:25:40.428Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/97/8c/e333690777bd33919ab7024269dc3c41c76ef5137b211d776fbb404bfead/msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f", size = 385356, upload-time = "2024-09-10T04:25:31.406Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/57/52/406795ba478dc1c890559dd4e89280fa86506608a28ccf3a72fbf45df9f5/msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247", size = 383028, upload-time = "2024-09-10T04:25:17.08Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/69/053b6549bf90a3acadcd8232eae03e2fefc87f066a5b9fbb37e2e608859f/msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c", size = 391100, upload-time = "2024-09-10T04:25:08.993Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/23/f0/d4101d4da054f04274995ddc4086c2715d9b93111eb9ed49686c0f7ccc8a/msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b", size = 394254, upload-time = "2024-09-10T04:25:06.048Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/12/cf07458f35d0d775ff3a2dc5559fa2e1fcd06c46f1ef510e594ebefdca01/msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b", size = 69085, upload-time = "2024-09-10T04:25:01.494Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/73/80/2708a4641f7d553a63bc934a3eb7214806b5b39d200133ca7f7afb0a53e8/msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f", size = 75347, upload-time = "2024-09-10T04:25:33.106Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c8/b0/380f5f639543a4ac413e969109978feb1f3c66e931068f91ab6ab0f8be00/msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf", size = 151142, upload-time = "2024-09-10T04:24:59.656Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c8/ee/be57e9702400a6cb2606883d55b05784fada898dfc7fd12608ab1fdb054e/msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330", size = 84523, upload-time = "2024-09-10T04:25:37.924Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7e/3a/2919f63acca3c119565449681ad08a2f84b2171ddfcff1dba6959db2cceb/msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734", size = 81556, upload-time = "2024-09-10T04:24:28.296Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7c/43/a11113d9e5c1498c145a8925768ea2d5fce7cbab15c99cda655aa09947ed/msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e", size = 392105, upload-time = "2024-09-10T04:25:20.153Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2d/7b/2c1d74ca6c94f70a1add74a8393a0138172207dc5de6fc6269483519d048/msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca", size = 399979, upload-time = "2024-09-10T04:25:41.75Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/82/8c/cf64ae518c7b8efc763ca1f1348a96f0e37150061e777a8ea5430b413a74/msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915", size = 383816, upload-time = "2024-09-10T04:24:45.826Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/86/a847ef7a0f5ef3fa94ae20f52a4cacf596a4e4a010197fbcc27744eb9a83/msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d", size = 380973, upload-time = "2024-09-10T04:25:04.689Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/90/c74cf6e1126faa93185d3b830ee97246ecc4fe12cf9d2d31318ee4246994/msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434", size = 387435, upload-time = "2024-09-10T04:24:17.879Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7a/40/631c238f1f338eb09f4acb0f34ab5862c4e9d7eda11c1b685471a4c5ea37/msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c", size = 399082, upload-time = "2024-09-10T04:25:18.398Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/1b/fa8a952be252a1555ed39f97c06778e3aeb9123aa4cccc0fd2acd0b4e315/msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc", size = 69037, upload-time = "2024-09-10T04:24:52.798Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b6/bc/8bd826dd03e022153bfa1766dcdec4976d6c818865ed54223d71f07862b3/msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f", size = 75140, upload-time = "2024-09-10T04:24:31.288Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/d0/7555686ae7ff5731205df1012ede15dd9d927f6227ea151e901c7406af4f/msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", size = 167260, upload-time = "2024-09-10T04:25:52.197Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e1/d6/716b7ca1dbde63290d2973d22bbef1b5032ca634c3ff4384a958ec3f093a/msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d", size = 152421, upload-time = "2024-09-10T04:25:49.63Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/70/da/5312b067f6773429cec2f8f08b021c06af416bba340c912c2ec778539ed6/msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2", size = 85277, upload-time = "2024-09-10T04:24:48.562Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/28/51/da7f3ae4462e8bb98af0d5bdf2707f1b8c65a0d4f496e46b6afb06cbc286/msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420", size = 82222, upload-time = "2024-09-10T04:25:36.49Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/33/af/dc95c4b2a49cff17ce47611ca9ba218198806cad7796c0b01d1e332c86bb/msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2", size = 392971, upload-time = "2024-09-10T04:24:58.129Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f1/54/65af8de681fa8255402c80eda2a501ba467921d5a7a028c9c22a2c2eedb5/msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39", size = 401403, upload-time = "2024-09-10T04:25:40.428Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/8c/e333690777bd33919ab7024269dc3c41c76ef5137b211d776fbb404bfead/msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f", size = 385356, upload-time = "2024-09-10T04:25:31.406Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/57/52/406795ba478dc1c890559dd4e89280fa86506608a28ccf3a72fbf45df9f5/msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247", size = 383028, upload-time = "2024-09-10T04:25:17.08Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/69/053b6549bf90a3acadcd8232eae03e2fefc87f066a5b9fbb37e2e608859f/msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c", size = 391100, upload-time = "2024-09-10T04:25:08.993Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/23/f0/d4101d4da054f04274995ddc4086c2715d9b93111eb9ed49686c0f7ccc8a/msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b", size = 394254, upload-time = "2024-09-10T04:25:06.048Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/12/cf07458f35d0d775ff3a2dc5559fa2e1fcd06c46f1ef510e594ebefdca01/msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b", size = 69085, upload-time = "2024-09-10T04:25:01.494Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/73/80/2708a4641f7d553a63bc934a3eb7214806b5b39d200133ca7f7afb0a53e8/msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f", size = 75347, upload-time = "2024-09-10T04:25:33.106Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c8/b0/380f5f639543a4ac413e969109978feb1f3c66e931068f91ab6ab0f8be00/msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf", size = 151142, upload-time = "2024-09-10T04:24:59.656Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c8/ee/be57e9702400a6cb2606883d55b05784fada898dfc7fd12608ab1fdb054e/msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330", size = 84523, upload-time = "2024-09-10T04:25:37.924Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/3a/2919f63acca3c119565449681ad08a2f84b2171ddfcff1dba6959db2cceb/msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734", size = 81556, upload-time = "2024-09-10T04:24:28.296Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7c/43/a11113d9e5c1498c145a8925768ea2d5fce7cbab15c99cda655aa09947ed/msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e", size = 392105, upload-time = "2024-09-10T04:25:20.153Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/7b/2c1d74ca6c94f70a1add74a8393a0138172207dc5de6fc6269483519d048/msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca", size = 399979, upload-time = "2024-09-10T04:25:41.75Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/82/8c/cf64ae518c7b8efc763ca1f1348a96f0e37150061e777a8ea5430b413a74/msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915", size = 383816, upload-time = "2024-09-10T04:24:45.826Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/86/a847ef7a0f5ef3fa94ae20f52a4cacf596a4e4a010197fbcc27744eb9a83/msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d", size = 380973, upload-time = "2024-09-10T04:25:04.689Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/90/c74cf6e1126faa93185d3b830ee97246ecc4fe12cf9d2d31318ee4246994/msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434", size = 387435, upload-time = "2024-09-10T04:24:17.879Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7a/40/631c238f1f338eb09f4acb0f34ab5862c4e9d7eda11c1b685471a4c5ea37/msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c", size = 399082, upload-time = "2024-09-10T04:25:18.398Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/1b/fa8a952be252a1555ed39f97c06778e3aeb9123aa4cccc0fd2acd0b4e315/msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc", size = 69037, upload-time = "2024-09-10T04:24:52.798Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b6/bc/8bd826dd03e022153bfa1766dcdec4976d6c818865ed54223d71f07862b3/msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f", size = 75140, upload-time = "2024-09-10T04:24:31.288Z" }, ] [[package]] name = "msgspec" version = "0.20.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/9c/bfbd12955a49180cbd234c5d29ec6f74fe641698f0cd9df154a854fc8a15/msgspec-0.20.0.tar.gz", hash = "sha256:692349e588fde322875f8d3025ac01689fead5901e7fb18d6870a44519d62a29", size = 317862, upload-time = "2025-11-24T03:56:28.934Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d9/6f/1e25eee957e58e3afb2a44b94fa95e06cebc4c236193ed0de3012fff1e19/msgspec-0.20.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2aba22e2e302e9231e85edc24f27ba1f524d43c223ef5765bd8624c7df9ec0a5", size = 196391, upload-time = "2025-11-24T03:55:32.677Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/ee/af51d090ada641d4b264992a486435ba3ef5b5634bc27e6eb002f71cef7d/msgspec-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:716284f898ab2547fedd72a93bb940375de9fbfe77538f05779632dc34afdfde", size = 188644, upload-time = "2025-11-24T03:55:33.934Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/49/d6/9709ee093b7742362c2934bfb1bbe791a1e09bed3ea5d8a18ce552fbfd73/msgspec-0.20.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:558ed73315efa51b1538fa8f1d3b22c8c5ff6d9a2a62eff87d25829b94fc5054", size = 218852, upload-time = "2025-11-24T03:55:35.575Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5c/a2/488517a43ccf5a4b6b6eca6dd4ede0bd82b043d1539dd6bb908a19f8efd3/msgspec-0.20.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:509ac1362a1d53aa66798c9b9fd76872d7faa30fcf89b2fba3bcbfd559d56eb0", size = 224937, upload-time = "2025-11-24T03:55:36.859Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d5/e8/49b832808aa23b85d4f090d1d2e48a4e3834871415031ed7c5fe48723156/msgspec-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1353c2c93423602e7dea1aa4c92f3391fdfc25ff40e0bacf81d34dbc68adb870", size = 222858, upload-time = "2025-11-24T03:55:38.187Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/56/1dc2fa53685dca9c3f243a6cbecd34e856858354e455b77f47ebd76cf5bf/msgspec-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cb33b5eb5adb3c33d749684471c6a165468395d7aa02d8867c15103b81e1da3e", size = 227248, upload-time = "2025-11-24T03:55:39.496Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/51/aba940212c23b32eedce752896205912c2668472ed5b205fc33da28a6509/msgspec-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:fb1d934e435dd3a2b8cf4bbf47a8757100b4a1cfdc2afdf227541199885cdacb", size = 190024, upload-time = "2025-11-24T03:55:40.829Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/41/ad/3b9f259d94f183daa9764fef33fdc7010f7ecffc29af977044fa47440a83/msgspec-0.20.0-cp312-cp312-win_arm64.whl", hash = "sha256:00648b1e19cf01b2be45444ba9dc961bd4c056ffb15706651e64e5d6ec6197b7", size = 175390, upload-time = "2025-11-24T03:55:42.05Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8a/d1/b902d38b6e5ba3bdddbec469bba388d647f960aeed7b5b3623a8debe8a76/msgspec-0.20.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9c1ff8db03be7598b50dd4b4a478d6fe93faae3bd54f4f17aa004d0e46c14c46", size = 196463, upload-time = "2025-11-24T03:55:43.405Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/57/b6/eff0305961a1d9447ec2b02f8c73c8946f22564d302a504185b730c9a761/msgspec-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f6532369ece217fd37c5ebcfd7e981f2615628c21121b7b2df9d3adcf2fd69b8", size = 188650, upload-time = "2025-11-24T03:55:44.761Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/99/93/f2ec1ae1de51d3fdee998a1ede6b2c089453a2ee82b5c1b361ed9095064a/msgspec-0.20.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f9a1697da2f85a751ac3cc6a97fceb8e937fc670947183fb2268edaf4016d1ee", size = 218834, upload-time = "2025-11-24T03:55:46.441Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/28/83/36557b04cfdc317ed8a525c4993b23e43a8fbcddaddd78619112ca07138c/msgspec-0.20.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7fac7e9c92eddcd24c19d9e5f6249760941485dff97802461ae7c995a2450111", size = 224917, upload-time = "2025-11-24T03:55:48.06Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8f/56/362037a1ed5be0b88aced59272442c4b40065c659700f4b195a7f4d0ac88/msgspec-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f953a66f2a3eb8d5ea64768445e2bb301d97609db052628c3e1bcb7d87192a9f", size = 222821, upload-time = "2025-11-24T03:55:49.388Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/92/75/fa2370ec341cedf663731ab7042e177b3742645c5dd4f64dc96bd9f18a6b/msgspec-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:247af0313ae64a066d3aea7ba98840f6681ccbf5c90ba9c7d17f3e39dbba679c", size = 227227, upload-time = "2025-11-24T03:55:51.125Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f1/25/5e8080fe0117f799b1b68008dc29a65862077296b92550632de015128579/msgspec-0.20.0-cp313-cp313-win_amd64.whl", hash = "sha256:67d5e4dfad52832017018d30a462604c80561aa62a9d548fc2bd4e430b66a352", size = 189966, upload-time = "2025-11-24T03:55:52.458Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/79/b6/63363422153937d40e1cb349c5081338401f8529a5a4e216865decd981bf/msgspec-0.20.0-cp313-cp313-win_arm64.whl", hash = "sha256:91a52578226708b63a9a13de287b1ec3ed1123e4a088b198143860c087770458", size = 175378, upload-time = "2025-11-24T03:55:53.721Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/9c/bfbd12955a49180cbd234c5d29ec6f74fe641698f0cd9df154a854fc8a15/msgspec-0.20.0.tar.gz", hash = "sha256:692349e588fde322875f8d3025ac01689fead5901e7fb18d6870a44519d62a29", size = 317862, upload-time = "2025-11-24T03:56:28.934Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/6f/1e25eee957e58e3afb2a44b94fa95e06cebc4c236193ed0de3012fff1e19/msgspec-0.20.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2aba22e2e302e9231e85edc24f27ba1f524d43c223ef5765bd8624c7df9ec0a5", size = 196391, upload-time = "2025-11-24T03:55:32.677Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/ee/af51d090ada641d4b264992a486435ba3ef5b5634bc27e6eb002f71cef7d/msgspec-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:716284f898ab2547fedd72a93bb940375de9fbfe77538f05779632dc34afdfde", size = 188644, upload-time = "2025-11-24T03:55:33.934Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/49/d6/9709ee093b7742362c2934bfb1bbe791a1e09bed3ea5d8a18ce552fbfd73/msgspec-0.20.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:558ed73315efa51b1538fa8f1d3b22c8c5ff6d9a2a62eff87d25829b94fc5054", size = 218852, upload-time = "2025-11-24T03:55:35.575Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/a2/488517a43ccf5a4b6b6eca6dd4ede0bd82b043d1539dd6bb908a19f8efd3/msgspec-0.20.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:509ac1362a1d53aa66798c9b9fd76872d7faa30fcf89b2fba3bcbfd559d56eb0", size = 224937, upload-time = "2025-11-24T03:55:36.859Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d5/e8/49b832808aa23b85d4f090d1d2e48a4e3834871415031ed7c5fe48723156/msgspec-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1353c2c93423602e7dea1aa4c92f3391fdfc25ff40e0bacf81d34dbc68adb870", size = 222858, upload-time = "2025-11-24T03:55:38.187Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/56/1dc2fa53685dca9c3f243a6cbecd34e856858354e455b77f47ebd76cf5bf/msgspec-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cb33b5eb5adb3c33d749684471c6a165468395d7aa02d8867c15103b81e1da3e", size = 227248, upload-time = "2025-11-24T03:55:39.496Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/51/aba940212c23b32eedce752896205912c2668472ed5b205fc33da28a6509/msgspec-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:fb1d934e435dd3a2b8cf4bbf47a8757100b4a1cfdc2afdf227541199885cdacb", size = 190024, upload-time = "2025-11-24T03:55:40.829Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/ad/3b9f259d94f183daa9764fef33fdc7010f7ecffc29af977044fa47440a83/msgspec-0.20.0-cp312-cp312-win_arm64.whl", hash = "sha256:00648b1e19cf01b2be45444ba9dc961bd4c056ffb15706651e64e5d6ec6197b7", size = 175390, upload-time = "2025-11-24T03:55:42.05Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/d1/b902d38b6e5ba3bdddbec469bba388d647f960aeed7b5b3623a8debe8a76/msgspec-0.20.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9c1ff8db03be7598b50dd4b4a478d6fe93faae3bd54f4f17aa004d0e46c14c46", size = 196463, upload-time = "2025-11-24T03:55:43.405Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/57/b6/eff0305961a1d9447ec2b02f8c73c8946f22564d302a504185b730c9a761/msgspec-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f6532369ece217fd37c5ebcfd7e981f2615628c21121b7b2df9d3adcf2fd69b8", size = 188650, upload-time = "2025-11-24T03:55:44.761Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/93/f2ec1ae1de51d3fdee998a1ede6b2c089453a2ee82b5c1b361ed9095064a/msgspec-0.20.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f9a1697da2f85a751ac3cc6a97fceb8e937fc670947183fb2268edaf4016d1ee", size = 218834, upload-time = "2025-11-24T03:55:46.441Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/28/83/36557b04cfdc317ed8a525c4993b23e43a8fbcddaddd78619112ca07138c/msgspec-0.20.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7fac7e9c92eddcd24c19d9e5f6249760941485dff97802461ae7c995a2450111", size = 224917, upload-time = "2025-11-24T03:55:48.06Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8f/56/362037a1ed5be0b88aced59272442c4b40065c659700f4b195a7f4d0ac88/msgspec-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f953a66f2a3eb8d5ea64768445e2bb301d97609db052628c3e1bcb7d87192a9f", size = 222821, upload-time = "2025-11-24T03:55:49.388Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/92/75/fa2370ec341cedf663731ab7042e177b3742645c5dd4f64dc96bd9f18a6b/msgspec-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:247af0313ae64a066d3aea7ba98840f6681ccbf5c90ba9c7d17f3e39dbba679c", size = 227227, upload-time = "2025-11-24T03:55:51.125Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f1/25/5e8080fe0117f799b1b68008dc29a65862077296b92550632de015128579/msgspec-0.20.0-cp313-cp313-win_amd64.whl", hash = "sha256:67d5e4dfad52832017018d30a462604c80561aa62a9d548fc2bd4e430b66a352", size = 189966, upload-time = "2025-11-24T03:55:52.458Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/b6/63363422153937d40e1cb349c5081338401f8529a5a4e216865decd981bf/msgspec-0.20.0-cp313-cp313-win_arm64.whl", hash = "sha256:91a52578226708b63a9a13de287b1ec3ed1123e4a088b198143860c087770458", size = 175378, upload-time = "2025-11-24T03:55:53.721Z" }, ] [[package]] name = "mulpyplexer" version = "0.9" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d7/6f/f036d4fb9f5a511262345bb18215c70fa69a250aca2e5ffe1a9c7e4cb85c/mulpyplexer-0.09.tar.gz", hash = "sha256:144e9e9bf66d3988f60542c9d3d4c94857438f7908f60e53f4c1cb1622fbbd30", size = 2846, upload-time = "2021-01-11T21:10:21.68Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d7/6f/f036d4fb9f5a511262345bb18215c70fa69a250aca2e5ffe1a9c7e4cb85c/mulpyplexer-0.09.tar.gz", hash = "sha256:144e9e9bf66d3988f60542c9d3d4c94857438f7908f60e53f4c1cb1622fbbd30", size = 2846, upload-time = "2021-01-11T21:10:21.68Z" } [[package]] name = "multidict" version = "6.7.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c2/9e/9f61ac18d9c8b475889f32ccfa91c9f59363480613fc807b6e3023d6f60b/multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", size = 76877, upload-time = "2025-10-06T14:49:20.884Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/38/6f/614f09a04e6184f8824268fce4bc925e9849edfa654ddd59f0b64508c595/multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", size = 45467, upload-time = "2025-10-06T14:49:22.054Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b3/93/c4f67a436dd026f2e780c433277fff72be79152894d9fc36f44569cab1a6/multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", size = 43834, upload-time = "2025-10-06T14:49:23.566Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/f5/013798161ca665e4a422afbc5e2d9e4070142a9ff8905e482139cd09e4d0/multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", size = 250545, upload-time = "2025-10-06T14:49:24.882Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/2f/91dbac13e0ba94669ea5119ba267c9a832f0cb65419aca75549fcf09a3dc/multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", size = 258305, upload-time = "2025-10-06T14:49:26.778Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ef/b0/754038b26f6e04488b48ac621f779c341338d78503fb45403755af2df477/multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", size = 242363, upload-time = "2025-10-06T14:49:28.562Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/87/15/9da40b9336a7c9fa606c4cf2ed80a649dffeb42b905d4f63a1d7eb17d746/multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", size = 268375, upload-time = "2025-10-06T14:49:29.96Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/82/72/c53fcade0cc94dfaad583105fd92b3a783af2091eddcb41a6d5a52474000/multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", size = 269346, upload-time = "2025-10-06T14:49:31.404Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0d/e2/9baffdae21a76f77ef8447f1a05a96ec4bc0a24dae08767abc0a2fe680b8/multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", size = 256107, upload-time = "2025-10-06T14:49:32.974Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3c/06/3f06f611087dc60d65ef775f1fb5aca7c6d61c6db4990e7cda0cef9b1651/multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", size = 253592, upload-time = "2025-10-06T14:49:34.52Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/20/24/54e804ec7945b6023b340c412ce9c3f81e91b3bf5fa5ce65558740141bee/multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", size = 251024, upload-time = "2025-10-06T14:49:35.956Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/14/48/011cba467ea0b17ceb938315d219391d3e421dfd35928e5dbdc3f4ae76ef/multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", size = 251484, upload-time = "2025-10-06T14:49:37.631Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0d/2f/919258b43bb35b99fa127435cfb2d91798eb3a943396631ef43e3720dcf4/multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", size = 263579, upload-time = "2025-10-06T14:49:39.502Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/22/a0e884d86b5242b5a74cf08e876bdf299e413016b66e55511f7a804a366e/multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", size = 259654, upload-time = "2025-10-06T14:49:41.32Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b2/e5/17e10e1b5c5f5a40f2fcbb45953c9b215f8a4098003915e46a93f5fcaa8f/multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", size = 251511, upload-time = "2025-10-06T14:49:46.021Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e3/9a/201bb1e17e7af53139597069c375e7b0dcbd47594604f65c2d5359508566/multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", size = 41895, upload-time = "2025-10-06T14:49:48.718Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/46/e2/348cd32faad84eaf1d20cce80e2bb0ef8d312c55bca1f7fa9865e7770aaf/multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", size = 46073, upload-time = "2025-10-06T14:49:50.28Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/ec/aad2613c1910dce907480e0c3aa306905830f25df2e54ccc9dea450cb5aa/multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", size = 43226, upload-time = "2025-10-06T14:49:52.304Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/86/33272a544eeb36d66e4d9a920602d1a2f57d4ebea4ef3cdfe5a912574c95/multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", size = 76135, upload-time = "2025-10-06T14:49:54.26Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", size = 45117, upload-time = "2025-10-06T14:49:55.82Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", size = 43472, upload-time = "2025-10-06T14:49:57.048Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/3f/e2639e80325af0b6c6febdf8e57cc07043ff15f57fa1ef808f4ccb5ac4cd/multidict-6.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8", size = 249342, upload-time = "2025-10-06T14:49:58.368Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5d/cc/84e0585f805cbeaa9cbdaa95f9a3d6aed745b9d25700623ac89a6ecff400/multidict-6.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60", size = 257082, upload-time = "2025-10-06T14:49:59.89Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b0/9c/ac851c107c92289acbbf5cfb485694084690c1b17e555f44952c26ddc5bd/multidict-6.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4", size = 240704, upload-time = "2025-10-06T14:50:01.485Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/cc/5f93e99427248c09da95b62d64b25748a5f5c98c7c2ab09825a1d6af0e15/multidict-6.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f", size = 266355, upload-time = "2025-10-06T14:50:02.955Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ec/0c/2ec1d883ceb79c6f7f6d7ad90c919c898f5d1c6ea96d322751420211e072/multidict-6.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf", size = 267259, upload-time = "2025-10-06T14:50:04.446Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c6/2d/f0b184fa88d6630aa267680bdb8623fb69cb0d024b8c6f0d23f9a0f406d3/multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32", size = 254903, upload-time = "2025-10-06T14:50:05.98Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/c9/11ea263ad0df7dfabcad404feb3c0dd40b131bc7f232d5537f2fb1356951/multidict-6.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036", size = 252365, upload-time = "2025-10-06T14:50:07.511Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/41/88/d714b86ee2c17d6e09850c70c9d310abac3d808ab49dfa16b43aba9d53fd/multidict-6.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec", size = 250062, upload-time = "2025-10-06T14:50:09.074Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/15/fe/ad407bb9e818c2b31383f6131ca19ea7e35ce93cf1310fce69f12e89de75/multidict-6.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e", size = 249683, upload-time = "2025-10-06T14:50:10.714Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8c/a4/a89abdb0229e533fb925e7c6e5c40201c2873efebc9abaf14046a4536ee6/multidict-6.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64", size = 261254, upload-time = "2025-10-06T14:50:12.28Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8d/aa/0e2b27bd88b40a4fb8dc53dd74eecac70edaa4c1dd0707eb2164da3675b3/multidict-6.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd", size = 257967, upload-time = "2025-10-06T14:50:14.16Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d0/8e/0c67b7120d5d5f6d874ed85a085f9dc770a7f9d8813e80f44a9fec820bb7/multidict-6.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288", size = 250085, upload-time = "2025-10-06T14:50:15.639Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/55/b73e1d624ea4b8fd4dd07a3bb70f6e4c7c6c5d9d640a41c6ffe5cdbd2a55/multidict-6.7.0-cp313-cp313-win32.whl", hash = "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17", size = 41713, upload-time = "2025-10-06T14:50:17.066Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/32/31/75c59e7d3b4205075b4c183fa4ca398a2daf2303ddf616b04ae6ef55cffe/multidict-6.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390", size = 45915, upload-time = "2025-10-06T14:50:18.264Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/2a/8987831e811f1184c22bc2e45844934385363ee61c0a2dcfa8f71b87e608/multidict-6.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e", size = 43077, upload-time = "2025-10-06T14:50:19.853Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e8/68/7b3a5170a382a340147337b300b9eb25a9ddb573bcdfff19c0fa3f31ffba/multidict-6.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00", size = 83114, upload-time = "2025-10-06T14:50:21.223Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/55/5c/3fa2d07c84df4e302060f555bbf539310980362236ad49f50eeb0a1c1eb9/multidict-6.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb", size = 48442, upload-time = "2025-10-06T14:50:22.871Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fc/56/67212d33239797f9bd91962bb899d72bb0f4c35a8652dcdb8ed049bef878/multidict-6.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b", size = 46885, upload-time = "2025-10-06T14:50:24.258Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/46/d1/908f896224290350721597a61a69cd19b89ad8ee0ae1f38b3f5cd12ea2ac/multidict-6.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c", size = 242588, upload-time = "2025-10-06T14:50:25.716Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ab/67/8604288bbd68680eee0ab568fdcb56171d8b23a01bcd5cb0c8fedf6e5d99/multidict-6.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1", size = 249966, upload-time = "2025-10-06T14:50:28.192Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/20/33/9228d76339f1ba51e3efef7da3ebd91964d3006217aae13211653193c3ff/multidict-6.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b", size = 228618, upload-time = "2025-10-06T14:50:29.82Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f8/2d/25d9b566d10cab1c42b3b9e5b11ef79c9111eaf4463b8c257a3bd89e0ead/multidict-6.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5", size = 257539, upload-time = "2025-10-06T14:50:31.731Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b6/b1/8d1a965e6637fc33de3c0d8f414485c2b7e4af00f42cab3d84e7b955c222/multidict-6.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad", size = 256345, upload-time = "2025-10-06T14:50:33.26Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/0c/06b5a8adbdeedada6f4fb8d8f193d44a347223b11939b42953eeb6530b6b/multidict-6.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c", size = 247934, upload-time = "2025-10-06T14:50:34.808Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8f/31/b2491b5fe167ca044c6eb4b8f2c9f3b8a00b24c432c365358eadac5d7625/multidict-6.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5", size = 245243, upload-time = "2025-10-06T14:50:36.436Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/1a/982913957cb90406c8c94f53001abd9eafc271cb3e70ff6371590bec478e/multidict-6.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10", size = 235878, upload-time = "2025-10-06T14:50:37.953Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/be/c0/21435d804c1a1cf7a2608593f4d19bca5bcbd7a81a70b253fdd1c12af9c0/multidict-6.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754", size = 243452, upload-time = "2025-10-06T14:50:39.574Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/0a/4349d540d4a883863191be6eb9a928846d4ec0ea007d3dcd36323bb058ac/multidict-6.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c", size = 252312, upload-time = "2025-10-06T14:50:41.612Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/64/d5416038dbda1488daf16b676e4dbfd9674dde10a0cc8f4fc2b502d8125d/multidict-6.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762", size = 246935, upload-time = "2025-10-06T14:50:43.972Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/8c/8290c50d14e49f35e0bd4abc25e1bc7711149ca9588ab7d04f886cdf03d9/multidict-6.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6", size = 243385, upload-time = "2025-10-06T14:50:45.648Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ef/a0/f83ae75e42d694b3fbad3e047670e511c138be747bc713cf1b10d5096416/multidict-6.7.0-cp313-cp313t-win32.whl", hash = "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d", size = 47777, upload-time = "2025-10-06T14:50:47.154Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/80/9b174a92814a3830b7357307a792300f42c9e94664b01dee8e457551fa66/multidict-6.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6", size = 53104, upload-time = "2025-10-06T14:50:48.851Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cc/28/04baeaf0428d95bb7a7bea0e691ba2f31394338ba424fb0679a9ed0f4c09/multidict-6.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792", size = 45503, upload-time = "2025-10-06T14:50:50.16Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b7/da/7d22601b625e241d4f23ef1ebff8acfc60da633c9e7e7922e24d10f592b3/multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3", size = 12317, upload-time = "2025-10-06T14:52:29.272Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/9e/9f61ac18d9c8b475889f32ccfa91c9f59363480613fc807b6e3023d6f60b/multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", size = 76877, upload-time = "2025-10-06T14:49:20.884Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/6f/614f09a04e6184f8824268fce4bc925e9849edfa654ddd59f0b64508c595/multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", size = 45467, upload-time = "2025-10-06T14:49:22.054Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b3/93/c4f67a436dd026f2e780c433277fff72be79152894d9fc36f44569cab1a6/multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", size = 43834, upload-time = "2025-10-06T14:49:23.566Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/f5/013798161ca665e4a422afbc5e2d9e4070142a9ff8905e482139cd09e4d0/multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", size = 250545, upload-time = "2025-10-06T14:49:24.882Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/2f/91dbac13e0ba94669ea5119ba267c9a832f0cb65419aca75549fcf09a3dc/multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", size = 258305, upload-time = "2025-10-06T14:49:26.778Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ef/b0/754038b26f6e04488b48ac621f779c341338d78503fb45403755af2df477/multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", size = 242363, upload-time = "2025-10-06T14:49:28.562Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/87/15/9da40b9336a7c9fa606c4cf2ed80a649dffeb42b905d4f63a1d7eb17d746/multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", size = 268375, upload-time = "2025-10-06T14:49:29.96Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/82/72/c53fcade0cc94dfaad583105fd92b3a783af2091eddcb41a6d5a52474000/multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", size = 269346, upload-time = "2025-10-06T14:49:31.404Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0d/e2/9baffdae21a76f77ef8447f1a05a96ec4bc0a24dae08767abc0a2fe680b8/multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", size = 256107, upload-time = "2025-10-06T14:49:32.974Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3c/06/3f06f611087dc60d65ef775f1fb5aca7c6d61c6db4990e7cda0cef9b1651/multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", size = 253592, upload-time = "2025-10-06T14:49:34.52Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/24/54e804ec7945b6023b340c412ce9c3f81e91b3bf5fa5ce65558740141bee/multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", size = 251024, upload-time = "2025-10-06T14:49:35.956Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/48/011cba467ea0b17ceb938315d219391d3e421dfd35928e5dbdc3f4ae76ef/multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", size = 251484, upload-time = "2025-10-06T14:49:37.631Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0d/2f/919258b43bb35b99fa127435cfb2d91798eb3a943396631ef43e3720dcf4/multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", size = 263579, upload-time = "2025-10-06T14:49:39.502Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/22/a0e884d86b5242b5a74cf08e876bdf299e413016b66e55511f7a804a366e/multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", size = 259654, upload-time = "2025-10-06T14:49:41.32Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/e5/17e10e1b5c5f5a40f2fcbb45953c9b215f8a4098003915e46a93f5fcaa8f/multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", size = 251511, upload-time = "2025-10-06T14:49:46.021Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/9a/201bb1e17e7af53139597069c375e7b0dcbd47594604f65c2d5359508566/multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", size = 41895, upload-time = "2025-10-06T14:49:48.718Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/46/e2/348cd32faad84eaf1d20cce80e2bb0ef8d312c55bca1f7fa9865e7770aaf/multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", size = 46073, upload-time = "2025-10-06T14:49:50.28Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/ec/aad2613c1910dce907480e0c3aa306905830f25df2e54ccc9dea450cb5aa/multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", size = 43226, upload-time = "2025-10-06T14:49:52.304Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/86/33272a544eeb36d66e4d9a920602d1a2f57d4ebea4ef3cdfe5a912574c95/multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", size = 76135, upload-time = "2025-10-06T14:49:54.26Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", size = 45117, upload-time = "2025-10-06T14:49:55.82Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", size = 43472, upload-time = "2025-10-06T14:49:57.048Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/3f/e2639e80325af0b6c6febdf8e57cc07043ff15f57fa1ef808f4ccb5ac4cd/multidict-6.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8", size = 249342, upload-time = "2025-10-06T14:49:58.368Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/cc/84e0585f805cbeaa9cbdaa95f9a3d6aed745b9d25700623ac89a6ecff400/multidict-6.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60", size = 257082, upload-time = "2025-10-06T14:49:59.89Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b0/9c/ac851c107c92289acbbf5cfb485694084690c1b17e555f44952c26ddc5bd/multidict-6.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4", size = 240704, upload-time = "2025-10-06T14:50:01.485Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/cc/5f93e99427248c09da95b62d64b25748a5f5c98c7c2ab09825a1d6af0e15/multidict-6.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f", size = 266355, upload-time = "2025-10-06T14:50:02.955Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ec/0c/2ec1d883ceb79c6f7f6d7ad90c919c898f5d1c6ea96d322751420211e072/multidict-6.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf", size = 267259, upload-time = "2025-10-06T14:50:04.446Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c6/2d/f0b184fa88d6630aa267680bdb8623fb69cb0d024b8c6f0d23f9a0f406d3/multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32", size = 254903, upload-time = "2025-10-06T14:50:05.98Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/c9/11ea263ad0df7dfabcad404feb3c0dd40b131bc7f232d5537f2fb1356951/multidict-6.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036", size = 252365, upload-time = "2025-10-06T14:50:07.511Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/88/d714b86ee2c17d6e09850c70c9d310abac3d808ab49dfa16b43aba9d53fd/multidict-6.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec", size = 250062, upload-time = "2025-10-06T14:50:09.074Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/15/fe/ad407bb9e818c2b31383f6131ca19ea7e35ce93cf1310fce69f12e89de75/multidict-6.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e", size = 249683, upload-time = "2025-10-06T14:50:10.714Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8c/a4/a89abdb0229e533fb925e7c6e5c40201c2873efebc9abaf14046a4536ee6/multidict-6.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64", size = 261254, upload-time = "2025-10-06T14:50:12.28Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8d/aa/0e2b27bd88b40a4fb8dc53dd74eecac70edaa4c1dd0707eb2164da3675b3/multidict-6.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd", size = 257967, upload-time = "2025-10-06T14:50:14.16Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d0/8e/0c67b7120d5d5f6d874ed85a085f9dc770a7f9d8813e80f44a9fec820bb7/multidict-6.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288", size = 250085, upload-time = "2025-10-06T14:50:15.639Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/55/b73e1d624ea4b8fd4dd07a3bb70f6e4c7c6c5d9d640a41c6ffe5cdbd2a55/multidict-6.7.0-cp313-cp313-win32.whl", hash = "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17", size = 41713, upload-time = "2025-10-06T14:50:17.066Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/32/31/75c59e7d3b4205075b4c183fa4ca398a2daf2303ddf616b04ae6ef55cffe/multidict-6.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390", size = 45915, upload-time = "2025-10-06T14:50:18.264Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/2a/8987831e811f1184c22bc2e45844934385363ee61c0a2dcfa8f71b87e608/multidict-6.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e", size = 43077, upload-time = "2025-10-06T14:50:19.853Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e8/68/7b3a5170a382a340147337b300b9eb25a9ddb573bcdfff19c0fa3f31ffba/multidict-6.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00", size = 83114, upload-time = "2025-10-06T14:50:21.223Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/55/5c/3fa2d07c84df4e302060f555bbf539310980362236ad49f50eeb0a1c1eb9/multidict-6.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb", size = 48442, upload-time = "2025-10-06T14:50:22.871Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fc/56/67212d33239797f9bd91962bb899d72bb0f4c35a8652dcdb8ed049bef878/multidict-6.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b", size = 46885, upload-time = "2025-10-06T14:50:24.258Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/46/d1/908f896224290350721597a61a69cd19b89ad8ee0ae1f38b3f5cd12ea2ac/multidict-6.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c", size = 242588, upload-time = "2025-10-06T14:50:25.716Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ab/67/8604288bbd68680eee0ab568fdcb56171d8b23a01bcd5cb0c8fedf6e5d99/multidict-6.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1", size = 249966, upload-time = "2025-10-06T14:50:28.192Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/33/9228d76339f1ba51e3efef7da3ebd91964d3006217aae13211653193c3ff/multidict-6.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b", size = 228618, upload-time = "2025-10-06T14:50:29.82Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f8/2d/25d9b566d10cab1c42b3b9e5b11ef79c9111eaf4463b8c257a3bd89e0ead/multidict-6.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5", size = 257539, upload-time = "2025-10-06T14:50:31.731Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b6/b1/8d1a965e6637fc33de3c0d8f414485c2b7e4af00f42cab3d84e7b955c222/multidict-6.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad", size = 256345, upload-time = "2025-10-06T14:50:33.26Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/0c/06b5a8adbdeedada6f4fb8d8f193d44a347223b11939b42953eeb6530b6b/multidict-6.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c", size = 247934, upload-time = "2025-10-06T14:50:34.808Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8f/31/b2491b5fe167ca044c6eb4b8f2c9f3b8a00b24c432c365358eadac5d7625/multidict-6.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5", size = 245243, upload-time = "2025-10-06T14:50:36.436Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/1a/982913957cb90406c8c94f53001abd9eafc271cb3e70ff6371590bec478e/multidict-6.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10", size = 235878, upload-time = "2025-10-06T14:50:37.953Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/be/c0/21435d804c1a1cf7a2608593f4d19bca5bcbd7a81a70b253fdd1c12af9c0/multidict-6.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754", size = 243452, upload-time = "2025-10-06T14:50:39.574Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/0a/4349d540d4a883863191be6eb9a928846d4ec0ea007d3dcd36323bb058ac/multidict-6.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c", size = 252312, upload-time = "2025-10-06T14:50:41.612Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/64/d5416038dbda1488daf16b676e4dbfd9674dde10a0cc8f4fc2b502d8125d/multidict-6.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762", size = 246935, upload-time = "2025-10-06T14:50:43.972Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/8c/8290c50d14e49f35e0bd4abc25e1bc7711149ca9588ab7d04f886cdf03d9/multidict-6.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6", size = 243385, upload-time = "2025-10-06T14:50:45.648Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ef/a0/f83ae75e42d694b3fbad3e047670e511c138be747bc713cf1b10d5096416/multidict-6.7.0-cp313-cp313t-win32.whl", hash = "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d", size = 47777, upload-time = "2025-10-06T14:50:47.154Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/80/9b174a92814a3830b7357307a792300f42c9e94664b01dee8e457551fa66/multidict-6.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6", size = 53104, upload-time = "2025-10-06T14:50:48.851Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/28/04baeaf0428d95bb7a7bea0e691ba2f31394338ba424fb0679a9ed0f4c09/multidict-6.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792", size = 45503, upload-time = "2025-10-06T14:50:50.16Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/da/7d22601b625e241d4f23ef1ebff8acfc60da633c9e7e7922e24d10f592b3/multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3", size = 12317, upload-time = "2025-10-06T14:52:29.272Z" }, ] [[package]] name = "mypy" version = "1.19.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, { name = "mypy-extensions" }, { name = "pathspec" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/8a/19bfae96f6615aa8a0604915512e0289b1fad33d5909bf7244f02935d33a/mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1", size = 13206053, upload-time = "2025-12-15T05:03:46.622Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a5/34/3e63879ab041602154ba2a9f99817bb0c85c4df19a23a1443c8986e4d565/mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e", size = 12219134, upload-time = "2025-12-15T05:03:24.367Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/cc/2db6f0e95366b630364e09845672dbee0cbf0bbe753a204b29a944967cd9/mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2", size = 12731616, upload-time = "2025-12-15T05:02:44.725Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/00/be/dd56c1fd4807bc1eba1cf18b2a850d0de7bacb55e158755eb79f77c41f8e/mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8", size = 13620847, upload-time = "2025-12-15T05:03:39.633Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6d/42/332951aae42b79329f743bf1da088cd75d8d4d9acc18fbcbd84f26c1af4e/mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a", size = 13834976, upload-time = "2025-12-15T05:03:08.786Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6f/63/e7493e5f90e1e085c562bb06e2eb32cae27c5057b9653348d38b47daaecc/mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13", size = 10118104, upload-time = "2025-12-15T05:03:10.834Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/de/9f/a6abae693f7a0c697dbb435aac52e958dc8da44e92e08ba88d2e42326176/mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250", size = 13201927, upload-time = "2025-12-15T05:02:29.138Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/a4/45c35ccf6e1c65afc23a069f50e2c66f46bd3798cbe0d680c12d12935caa/mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b", size = 12206730, upload-time = "2025-12-15T05:03:01.325Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/bb/cdcf89678e26b187650512620eec8368fded4cfd99cfcb431e4cdfd19dec/mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e", size = 12724581, upload-time = "2025-12-15T05:03:20.087Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/32/dd260d52babf67bad8e6770f8e1102021877ce0edea106e72df5626bb0ec/mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef", size = 13616252, upload-time = "2025-12-15T05:02:49.036Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/d0/5e60a9d2e3bd48432ae2b454b7ef2b62a960ab51292b1eda2a95edd78198/mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75", size = 13840848, upload-time = "2025-12-15T05:02:55.95Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/76/d32051fa65ecf6cc8c6610956473abdc9b4c43301107476ac03559507843/mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd", size = 10135510, upload-time = "2025-12-15T05:02:58.438Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/8a/19bfae96f6615aa8a0604915512e0289b1fad33d5909bf7244f02935d33a/mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1", size = 13206053, upload-time = "2025-12-15T05:03:46.622Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a5/34/3e63879ab041602154ba2a9f99817bb0c85c4df19a23a1443c8986e4d565/mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e", size = 12219134, upload-time = "2025-12-15T05:03:24.367Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/cc/2db6f0e95366b630364e09845672dbee0cbf0bbe753a204b29a944967cd9/mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2", size = 12731616, upload-time = "2025-12-15T05:02:44.725Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/00/be/dd56c1fd4807bc1eba1cf18b2a850d0de7bacb55e158755eb79f77c41f8e/mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8", size = 13620847, upload-time = "2025-12-15T05:03:39.633Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6d/42/332951aae42b79329f743bf1da088cd75d8d4d9acc18fbcbd84f26c1af4e/mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a", size = 13834976, upload-time = "2025-12-15T05:03:08.786Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6f/63/e7493e5f90e1e085c562bb06e2eb32cae27c5057b9653348d38b47daaecc/mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13", size = 10118104, upload-time = "2025-12-15T05:03:10.834Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/de/9f/a6abae693f7a0c697dbb435aac52e958dc8da44e92e08ba88d2e42326176/mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250", size = 13201927, upload-time = "2025-12-15T05:02:29.138Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/a4/45c35ccf6e1c65afc23a069f50e2c66f46bd3798cbe0d680c12d12935caa/mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b", size = 12206730, upload-time = "2025-12-15T05:03:01.325Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/bb/cdcf89678e26b187650512620eec8368fded4cfd99cfcb431e4cdfd19dec/mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e", size = 12724581, upload-time = "2025-12-15T05:03:20.087Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/32/dd260d52babf67bad8e6770f8e1102021877ce0edea106e72df5626bb0ec/mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef", size = 13616252, upload-time = "2025-12-15T05:02:49.036Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/d0/5e60a9d2e3bd48432ae2b454b7ef2b62a960ab51292b1eda2a95edd78198/mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75", size = 13840848, upload-time = "2025-12-15T05:02:55.95Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/76/d32051fa65ecf6cc8c6610956473abdc9b4c43301107476ac03559507843/mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd", size = 10135510, upload-time = "2025-12-15T05:02:58.438Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, ] [[package]] name = "mypy-extensions" version = "1.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] [[package]] name = "networkx" version = "3.6.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762", size = 2068504, upload-time = "2025-12-08T17:02:38.159Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762", size = 2068504, upload-time = "2025-12-08T17:02:38.159Z" }, ] [[package]] name = "nodeenv" version = "1.10.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, ] [[package]] name = "numpy" version = "2.4.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a4/7a/6a3d14e205d292b738db449d0de649b373a59edb0d0b4493821d0a3e8718/numpy-2.4.0.tar.gz", hash = "sha256:6e504f7b16118198f138ef31ba24d985b124c2c469fe8467007cf30fd992f934", size = 20685720, upload-time = "2025-12-20T16:18:19.023Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8b/ff/f6400ffec95de41c74b8e73df32e3fff1830633193a7b1e409be7fb1bb8c/numpy-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2a8b6bb8369abefb8bd1801b054ad50e02b3275c8614dc6e5b0373c305291037", size = 16653117, upload-time = "2025-12-20T16:16:06.709Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/28/6c23e97450035072e8d830a3c411bf1abd1f42c611ff9d29e3d8f55c6252/numpy-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e284ca13d5a8367e43734148622caf0b261b275673823593e3e3634a6490f83", size = 12369711, upload-time = "2025-12-20T16:16:08.758Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bc/af/acbef97b630ab1bb45e6a7d01d1452e4251aa88ce680ac36e56c272120ec/numpy-2.4.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:49ff32b09f5aa0cd30a20c2b39db3e669c845589f2b7fc910365210887e39344", size = 5198355, upload-time = "2025-12-20T16:16:10.902Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c1/c8/4e0d436b66b826f2e53330adaa6311f5cac9871a5b5c31ad773b27f25a74/numpy-2.4.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:36cbfb13c152b1c7c184ddac43765db8ad672567e7bafff2cc755a09917ed2e6", size = 6545298, upload-time = "2025-12-20T16:16:12.607Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ef/27/e1f5d144ab54eac34875e79037011d511ac57b21b220063310cb96c80fbc/numpy-2.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35ddc8f4914466e6fc954c76527aa91aa763682a4f6d73249ef20b418fe6effb", size = 14398387, upload-time = "2025-12-20T16:16:14.257Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/67/64/4cb909dd5ab09a9a5d086eff9586e69e827b88a5585517386879474f4cf7/numpy-2.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc578891de1db95b2a35001b695451767b580bb45753717498213c5ff3c41d63", size = 16363091, upload-time = "2025-12-20T16:16:17.32Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9d/9c/8efe24577523ec6809261859737cf117b0eb6fdb655abdfdc81b2e468ce4/numpy-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98e81648e0b36e325ab67e46b5400a7a6d4a22b8a7c8e8bbfe20e7db7906bf95", size = 16176394, upload-time = "2025-12-20T16:16:19.524Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/f0/1687441ece7b47a62e45a1f82015352c240765c707928edd8aef875d5951/numpy-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d57b5046c120561ba8fa8e4030fbb8b822f3063910fa901ffadf16e2b7128ad6", size = 18287378, upload-time = "2025-12-20T16:16:22.866Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d3/6f/f868765d44e6fc466467ed810ba9d8d6db1add7d4a748abfa2a4c99a3194/numpy-2.4.0-cp312-cp312-win32.whl", hash = "sha256:92190db305a6f48734d3982f2c60fa30d6b5ee9bff10f2887b930d7b40119f4c", size = 5955432, upload-time = "2025-12-20T16:16:25.06Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d4/b5/94c1e79fcbab38d1ca15e13777477b2914dd2d559b410f96949d6637b085/numpy-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:680060061adb2d74ce352628cb798cfdec399068aa7f07ba9fb818b2b3305f98", size = 12306201, upload-time = "2025-12-20T16:16:26.979Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/70/09/c39dadf0b13bb0768cd29d6a3aaff1fb7c6905ac40e9aaeca26b1c086e06/numpy-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:39699233bc72dd482da1415dcb06076e32f60eddc796a796c5fb6c5efce94667", size = 10308234, upload-time = "2025-12-20T16:16:29.417Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/0d/853fd96372eda07c824d24adf02e8bc92bb3731b43a9b2a39161c3667cc4/numpy-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a152d86a3ae00ba5f47b3acf3b827509fd0b6cb7d3259665e63dafbad22a75ea", size = 16649088, upload-time = "2025-12-20T16:16:31.421Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39b19251dec4de8ff8496cd0806cbe27bf0684f765abb1f4809554de93785f2d", size = 12364065, upload-time = "2025-12-20T16:16:33.491Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ed/69/0b78f37ca3690969beee54103ce5f6021709134e8020767e93ba691a72f1/numpy-2.4.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:009bd0ea12d3c784b6639a8457537016ce5172109e585338e11334f6a7bb88ee", size = 5192640, upload-time = "2025-12-20T16:16:35.636Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1d/2a/08569f8252abf590294dbb09a430543ec8f8cc710383abfb3e75cc73aeda/numpy-2.4.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5fe44e277225fd3dff6882d86d3d447205d43532c3627313d17e754fb3905a0e", size = 6541556, upload-time = "2025-12-20T16:16:37.276Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f935c4493eda9069851058fa0d9e39dbf6286be690066509305e52912714dbb2", size = 14396562, upload-time = "2025-12-20T16:16:38.953Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cfa5f29a695cb7438965e6c3e8d06e0416060cf0d709c1b1c1653a939bf5c2a", size = 16351719, upload-time = "2025-12-20T16:16:41.503Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/28/de/5f3711a38341d6e8dd619f6353251a0cdd07f3d6d101a8fd46f4ef87f895/numpy-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba0cb30acd3ef11c94dc27fbfba68940652492bc107075e7ffe23057f9425681", size = 16176053, upload-time = "2025-12-20T16:16:44.552Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2a/5b/2a3753dc43916501b4183532e7ace862e13211042bceafa253afb5c71272/numpy-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60e8c196cd82cbbd4f130b5290007e13e6de3eca79f0d4d38014769d96a7c475", size = 18277859, upload-time = "2025-12-20T16:16:47.174Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/c5/a18bcdd07a941db3076ef489d036ab16d2bfc2eae0cf27e5a26e29189434/numpy-2.4.0-cp313-cp313-win32.whl", hash = "sha256:5f48cb3e88fbc294dc90e215d86fbaf1c852c63dbdb6c3a3e63f45c4b57f7344", size = 5953849, upload-time = "2025-12-20T16:16:49.554Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4f/f1/719010ff8061da6e8a26e1980cf090412d4f5f8060b31f0c45d77dd67a01/numpy-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:a899699294f28f7be8992853c0c60741f16ff199205e2e6cdca155762cbaa59d", size = 12302840, upload-time = "2025-12-20T16:16:51.227Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/5a/b3d259083ed8b4d335270c76966cb6cf14a5d1b69e1a608994ac57a659e6/numpy-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:9198f447e1dc5647d07c9a6bbe2063cc0132728cc7175b39dbc796da5b54920d", size = 10308509, upload-time = "2025-12-20T16:16:53.313Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/01/95edcffd1bb6c0633df4e808130545c4f07383ab629ac7e316fb44fff677/numpy-2.4.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74623f2ab5cc3f7c886add4f735d1031a1d2be4a4ae63c0546cfd74e7a31ddf6", size = 12491815, upload-time = "2025-12-20T16:16:55.496Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/ea/5644b8baa92cc1c7163b4b4458c8679852733fa74ca49c942cfa82ded4e0/numpy-2.4.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:0804a8e4ab070d1d35496e65ffd3cf8114c136a2b81f61dfab0de4b218aacfd5", size = 5320321, upload-time = "2025-12-20T16:16:57.468Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/4e/e10938106d70bc21319bd6a86ae726da37edc802ce35a3a71ecdf1fdfe7f/numpy-2.4.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:02a2038eb27f9443a8b266a66911e926566b5a6ffd1a689b588f7f35b81e7dc3", size = 6641635, upload-time = "2025-12-20T16:16:59.379Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b3/8d/a8828e3eaf5c0b4ab116924df82f24ce3416fa38d0674d8f708ddc6c8aac/numpy-2.4.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1889b3a3f47a7b5bee16bc25a2145bd7cb91897f815ce3499db64c7458b6d91d", size = 14456053, upload-time = "2025-12-20T16:17:01.768Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/68/a1/17d97609d87d4520aa5ae2dcfb32305654550ac6a35effb946d303e594ce/numpy-2.4.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85eef4cb5625c47ee6425c58a3502555e10f45ee973da878ac8248ad58c136f3", size = 16401702, upload-time = "2025-12-20T16:17:04.235Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/18/32/0f13c1b2d22bea1118356b8b963195446f3af124ed7a5adfa8fdecb1b6ca/numpy-2.4.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6dc8b7e2f4eb184b37655195f421836cfae6f58197b67e3ffc501f1333d993fa", size = 16242493, upload-time = "2025-12-20T16:17:06.856Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ae/23/48f21e3d309fbc137c068a1475358cbd3a901b3987dcfc97a029ab3068e2/numpy-2.4.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:44aba2f0cafd287871a495fb3163408b0bd25bbce135c6f621534a07f4f7875c", size = 18324222, upload-time = "2025-12-20T16:17:09.392Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ac/52/41f3d71296a3dcaa4f456aaa3c6fc8e745b43d0552b6bde56571bb4b4a0f/numpy-2.4.0-cp313-cp313t-win32.whl", hash = "sha256:20c115517513831860c573996e395707aa9fb691eb179200125c250e895fcd93", size = 6076216, upload-time = "2025-12-20T16:17:11.437Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/35/ff/46fbfe60ab0710d2a2b16995f708750307d30eccbb4c38371ea9e986866e/numpy-2.4.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b48e35f4ab6f6a7597c46e301126ceba4c44cd3280e3750f85db48b082624fa4", size = 12444263, upload-time = "2025-12-20T16:17:13.182Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a3/e3/9189ab319c01d2ed556c932ccf55064c5d75bb5850d1df7a482ce0badead/numpy-2.4.0-cp313-cp313t-win_arm64.whl", hash = "sha256:4d1cfce39e511069b11e67cd0bd78ceff31443b7c9e5c04db73c7a19f572967c", size = 10378265, upload-time = "2025-12-20T16:17:15.211Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a4/7a/6a3d14e205d292b738db449d0de649b373a59edb0d0b4493821d0a3e8718/numpy-2.4.0.tar.gz", hash = "sha256:6e504f7b16118198f138ef31ba24d985b124c2c469fe8467007cf30fd992f934", size = 20685720, upload-time = "2025-12-20T16:18:19.023Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8b/ff/f6400ffec95de41c74b8e73df32e3fff1830633193a7b1e409be7fb1bb8c/numpy-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2a8b6bb8369abefb8bd1801b054ad50e02b3275c8614dc6e5b0373c305291037", size = 16653117, upload-time = "2025-12-20T16:16:06.709Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/28/6c23e97450035072e8d830a3c411bf1abd1f42c611ff9d29e3d8f55c6252/numpy-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e284ca13d5a8367e43734148622caf0b261b275673823593e3e3634a6490f83", size = 12369711, upload-time = "2025-12-20T16:16:08.758Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bc/af/acbef97b630ab1bb45e6a7d01d1452e4251aa88ce680ac36e56c272120ec/numpy-2.4.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:49ff32b09f5aa0cd30a20c2b39db3e669c845589f2b7fc910365210887e39344", size = 5198355, upload-time = "2025-12-20T16:16:10.902Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/c8/4e0d436b66b826f2e53330adaa6311f5cac9871a5b5c31ad773b27f25a74/numpy-2.4.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:36cbfb13c152b1c7c184ddac43765db8ad672567e7bafff2cc755a09917ed2e6", size = 6545298, upload-time = "2025-12-20T16:16:12.607Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ef/27/e1f5d144ab54eac34875e79037011d511ac57b21b220063310cb96c80fbc/numpy-2.4.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35ddc8f4914466e6fc954c76527aa91aa763682a4f6d73249ef20b418fe6effb", size = 14398387, upload-time = "2025-12-20T16:16:14.257Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/67/64/4cb909dd5ab09a9a5d086eff9586e69e827b88a5585517386879474f4cf7/numpy-2.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc578891de1db95b2a35001b695451767b580bb45753717498213c5ff3c41d63", size = 16363091, upload-time = "2025-12-20T16:16:17.32Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/9c/8efe24577523ec6809261859737cf117b0eb6fdb655abdfdc81b2e468ce4/numpy-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98e81648e0b36e325ab67e46b5400a7a6d4a22b8a7c8e8bbfe20e7db7906bf95", size = 16176394, upload-time = "2025-12-20T16:16:19.524Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/f0/1687441ece7b47a62e45a1f82015352c240765c707928edd8aef875d5951/numpy-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d57b5046c120561ba8fa8e4030fbb8b822f3063910fa901ffadf16e2b7128ad6", size = 18287378, upload-time = "2025-12-20T16:16:22.866Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d3/6f/f868765d44e6fc466467ed810ba9d8d6db1add7d4a748abfa2a4c99a3194/numpy-2.4.0-cp312-cp312-win32.whl", hash = "sha256:92190db305a6f48734d3982f2c60fa30d6b5ee9bff10f2887b930d7b40119f4c", size = 5955432, upload-time = "2025-12-20T16:16:25.06Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/b5/94c1e79fcbab38d1ca15e13777477b2914dd2d559b410f96949d6637b085/numpy-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:680060061adb2d74ce352628cb798cfdec399068aa7f07ba9fb818b2b3305f98", size = 12306201, upload-time = "2025-12-20T16:16:26.979Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/70/09/c39dadf0b13bb0768cd29d6a3aaff1fb7c6905ac40e9aaeca26b1c086e06/numpy-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:39699233bc72dd482da1415dcb06076e32f60eddc796a796c5fb6c5efce94667", size = 10308234, upload-time = "2025-12-20T16:16:29.417Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/0d/853fd96372eda07c824d24adf02e8bc92bb3731b43a9b2a39161c3667cc4/numpy-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a152d86a3ae00ba5f47b3acf3b827509fd0b6cb7d3259665e63dafbad22a75ea", size = 16649088, upload-time = "2025-12-20T16:16:31.421Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39b19251dec4de8ff8496cd0806cbe27bf0684f765abb1f4809554de93785f2d", size = 12364065, upload-time = "2025-12-20T16:16:33.491Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/69/0b78f37ca3690969beee54103ce5f6021709134e8020767e93ba691a72f1/numpy-2.4.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:009bd0ea12d3c784b6639a8457537016ce5172109e585338e11334f6a7bb88ee", size = 5192640, upload-time = "2025-12-20T16:16:35.636Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1d/2a/08569f8252abf590294dbb09a430543ec8f8cc710383abfb3e75cc73aeda/numpy-2.4.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5fe44e277225fd3dff6882d86d3d447205d43532c3627313d17e754fb3905a0e", size = 6541556, upload-time = "2025-12-20T16:16:37.276Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f935c4493eda9069851058fa0d9e39dbf6286be690066509305e52912714dbb2", size = 14396562, upload-time = "2025-12-20T16:16:38.953Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cfa5f29a695cb7438965e6c3e8d06e0416060cf0d709c1b1c1653a939bf5c2a", size = 16351719, upload-time = "2025-12-20T16:16:41.503Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/28/de/5f3711a38341d6e8dd619f6353251a0cdd07f3d6d101a8fd46f4ef87f895/numpy-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba0cb30acd3ef11c94dc27fbfba68940652492bc107075e7ffe23057f9425681", size = 16176053, upload-time = "2025-12-20T16:16:44.552Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/5b/2a3753dc43916501b4183532e7ace862e13211042bceafa253afb5c71272/numpy-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60e8c196cd82cbbd4f130b5290007e13e6de3eca79f0d4d38014769d96a7c475", size = 18277859, upload-time = "2025-12-20T16:16:47.174Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/c5/a18bcdd07a941db3076ef489d036ab16d2bfc2eae0cf27e5a26e29189434/numpy-2.4.0-cp313-cp313-win32.whl", hash = "sha256:5f48cb3e88fbc294dc90e215d86fbaf1c852c63dbdb6c3a3e63f45c4b57f7344", size = 5953849, upload-time = "2025-12-20T16:16:49.554Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4f/f1/719010ff8061da6e8a26e1980cf090412d4f5f8060b31f0c45d77dd67a01/numpy-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:a899699294f28f7be8992853c0c60741f16ff199205e2e6cdca155762cbaa59d", size = 12302840, upload-time = "2025-12-20T16:16:51.227Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/5a/b3d259083ed8b4d335270c76966cb6cf14a5d1b69e1a608994ac57a659e6/numpy-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:9198f447e1dc5647d07c9a6bbe2063cc0132728cc7175b39dbc796da5b54920d", size = 10308509, upload-time = "2025-12-20T16:16:53.313Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/01/95edcffd1bb6c0633df4e808130545c4f07383ab629ac7e316fb44fff677/numpy-2.4.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74623f2ab5cc3f7c886add4f735d1031a1d2be4a4ae63c0546cfd74e7a31ddf6", size = 12491815, upload-time = "2025-12-20T16:16:55.496Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/ea/5644b8baa92cc1c7163b4b4458c8679852733fa74ca49c942cfa82ded4e0/numpy-2.4.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:0804a8e4ab070d1d35496e65ffd3cf8114c136a2b81f61dfab0de4b218aacfd5", size = 5320321, upload-time = "2025-12-20T16:16:57.468Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/4e/e10938106d70bc21319bd6a86ae726da37edc802ce35a3a71ecdf1fdfe7f/numpy-2.4.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:02a2038eb27f9443a8b266a66911e926566b5a6ffd1a689b588f7f35b81e7dc3", size = 6641635, upload-time = "2025-12-20T16:16:59.379Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b3/8d/a8828e3eaf5c0b4ab116924df82f24ce3416fa38d0674d8f708ddc6c8aac/numpy-2.4.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1889b3a3f47a7b5bee16bc25a2145bd7cb91897f815ce3499db64c7458b6d91d", size = 14456053, upload-time = "2025-12-20T16:17:01.768Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/68/a1/17d97609d87d4520aa5ae2dcfb32305654550ac6a35effb946d303e594ce/numpy-2.4.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85eef4cb5625c47ee6425c58a3502555e10f45ee973da878ac8248ad58c136f3", size = 16401702, upload-time = "2025-12-20T16:17:04.235Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/32/0f13c1b2d22bea1118356b8b963195446f3af124ed7a5adfa8fdecb1b6ca/numpy-2.4.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6dc8b7e2f4eb184b37655195f421836cfae6f58197b67e3ffc501f1333d993fa", size = 16242493, upload-time = "2025-12-20T16:17:06.856Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ae/23/48f21e3d309fbc137c068a1475358cbd3a901b3987dcfc97a029ab3068e2/numpy-2.4.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:44aba2f0cafd287871a495fb3163408b0bd25bbce135c6f621534a07f4f7875c", size = 18324222, upload-time = "2025-12-20T16:17:09.392Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/52/41f3d71296a3dcaa4f456aaa3c6fc8e745b43d0552b6bde56571bb4b4a0f/numpy-2.4.0-cp313-cp313t-win32.whl", hash = "sha256:20c115517513831860c573996e395707aa9fb691eb179200125c250e895fcd93", size = 6076216, upload-time = "2025-12-20T16:17:11.437Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/35/ff/46fbfe60ab0710d2a2b16995f708750307d30eccbb4c38371ea9e986866e/numpy-2.4.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b48e35f4ab6f6a7597c46e301126ceba4c44cd3280e3750f85db48b082624fa4", size = 12444263, upload-time = "2025-12-20T16:17:13.182Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a3/e3/9189ab319c01d2ed556c932ccf55064c5d75bb5850d1df7a482ce0badead/numpy-2.4.0-cp313-cp313t-win_arm64.whl", hash = "sha256:4d1cfce39e511069b11e67cd0bd78ceff31443b7c9e5c04db73c7a19f572967c", size = 10378265, upload-time = "2025-12-20T16:17:15.211Z" }, ] [[package]] name = "openai" version = "2.14.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "anyio" }, { name = "distro" }, @@ -2554,52 +2545,52 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/b1/12fe1c196bea326261718eb037307c1c1fe1dedc2d2d4de777df822e6238/openai-2.14.0.tar.gz", hash = "sha256:419357bedde9402d23bf8f2ee372fca1985a73348debba94bddff06f19459952", size = 626938, upload-time = "2025-12-19T03:28:45.742Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/b1/12fe1c196bea326261718eb037307c1c1fe1dedc2d2d4de777df822e6238/openai-2.14.0.tar.gz", hash = "sha256:419357bedde9402d23bf8f2ee372fca1985a73348debba94bddff06f19459952", size = 626938, upload-time = "2025-12-19T03:28:45.742Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/27/4b/7c1a00c2c3fbd004253937f7520f692a9650767aa73894d7a34f0d65d3f4/openai-2.14.0-py3-none-any.whl", hash = "sha256:7ea40aca4ffc4c4a776e77679021b47eec1160e341f42ae086ba949c9dcc9183", size = 1067558, upload-time = "2025-12-19T03:28:43.727Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/27/4b/7c1a00c2c3fbd004253937f7520f692a9650767aa73894d7a34f0d65d3f4/openai-2.14.0-py3-none-any.whl", hash = "sha256:7ea40aca4ffc4c4a776e77679021b47eec1160e341f42ae086ba949c9dcc9183", size = 1067558, upload-time = "2025-12-19T03:28:43.727Z" }, ] [[package]] name = "openapi-pydantic" version = "0.5.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pydantic" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/2e/58d83848dd1a79cb92ed8e63f6ba901ca282c5f09d04af9423ec26c56fd7/openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d", size = 60892, upload-time = "2025-01-08T19:29:27.083Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/2e/58d83848dd1a79cb92ed8e63f6ba901ca282c5f09d04af9423ec26c56fd7/openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d", size = 60892, upload-time = "2025-01-08T19:29:27.083Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381, upload-time = "2025-01-08T19:29:25.275Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381, upload-time = "2025-01-08T19:29:25.275Z" }, ] [[package]] name = "opentelemetry-api" version = "1.39.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "importlib-metadata" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/97/b9/3161be15bb8e3ad01be8be5a968a9237c3027c5be504362ff800fca3e442/opentelemetry_api-1.39.1.tar.gz", hash = "sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c", size = 65767, upload-time = "2025-12-11T13:32:39.182Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/b9/3161be15bb8e3ad01be8be5a968a9237c3027c5be504362ff800fca3e442/opentelemetry_api-1.39.1.tar.gz", hash = "sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c", size = 65767, upload-time = "2025-12-11T13:32:39.182Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cf/df/d3f1ddf4bb4cb50ed9b1139cc7b1c54c34a1e7ce8fd1b9a37c0d1551a6bd/opentelemetry_api-1.39.1-py3-none-any.whl", hash = "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950", size = 66356, upload-time = "2025-12-11T13:32:17.304Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cf/df/d3f1ddf4bb4cb50ed9b1139cc7b1c54c34a1e7ce8fd1b9a37c0d1551a6bd/opentelemetry_api-1.39.1-py3-none-any.whl", hash = "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950", size = 66356, upload-time = "2025-12-11T13:32:17.304Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-common" version = "1.39.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "opentelemetry-proto" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/9d/22d241b66f7bbde88a3bfa6847a351d2c46b84de23e71222c6aae25c7050/opentelemetry_exporter_otlp_proto_common-1.39.1.tar.gz", hash = "sha256:763370d4737a59741c89a67b50f9e39271639ee4afc999dadfe768541c027464", size = 20409, upload-time = "2025-12-11T13:32:40.885Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/9d/22d241b66f7bbde88a3bfa6847a351d2c46b84de23e71222c6aae25c7050/opentelemetry_exporter_otlp_proto_common-1.39.1.tar.gz", hash = "sha256:763370d4737a59741c89a67b50f9e39271639ee4afc999dadfe768541c027464", size = 20409, upload-time = "2025-12-11T13:32:40.885Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8c/02/ffc3e143d89a27ac21fd557365b98bd0653b98de8a101151d5805b5d4c33/opentelemetry_exporter_otlp_proto_common-1.39.1-py3-none-any.whl", hash = "sha256:08f8a5862d64cc3435105686d0216c1365dc5701f86844a8cd56597d0c764fde", size = 18366, upload-time = "2025-12-11T13:32:20.2Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8c/02/ffc3e143d89a27ac21fd557365b98bd0653b98de8a101151d5805b5d4c33/opentelemetry_exporter_otlp_proto_common-1.39.1-py3-none-any.whl", hash = "sha256:08f8a5862d64cc3435105686d0216c1365dc5701f86844a8cd56597d0c764fde", size = 18366, upload-time = "2025-12-11T13:32:20.2Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-http" version = "1.39.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "googleapis-common-protos" }, { name = "opentelemetry-api" }, @@ -2609,171 +2600,171 @@ dependencies = [ { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/80/04/2a08fa9c0214ae38880df01e8bfae12b067ec0793446578575e5080d6545/opentelemetry_exporter_otlp_proto_http-1.39.1.tar.gz", hash = "sha256:31bdab9745c709ce90a49a0624c2bd445d31a28ba34275951a6a362d16a0b9cb", size = 17288, upload-time = "2025-12-11T13:32:42.029Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/80/04/2a08fa9c0214ae38880df01e8bfae12b067ec0793446578575e5080d6545/opentelemetry_exporter_otlp_proto_http-1.39.1.tar.gz", hash = "sha256:31bdab9745c709ce90a49a0624c2bd445d31a28ba34275951a6a362d16a0b9cb", size = 17288, upload-time = "2025-12-11T13:32:42.029Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/f1/b27d3e2e003cd9a3592c43d099d2ed8d0a947c15281bf8463a256db0b46c/opentelemetry_exporter_otlp_proto_http-1.39.1-py3-none-any.whl", hash = "sha256:d9f5207183dd752a412c4cd564ca8875ececba13be6e9c6c370ffb752fd59985", size = 19641, upload-time = "2025-12-11T13:32:22.248Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/f1/b27d3e2e003cd9a3592c43d099d2ed8d0a947c15281bf8463a256db0b46c/opentelemetry_exporter_otlp_proto_http-1.39.1-py3-none-any.whl", hash = "sha256:d9f5207183dd752a412c4cd564ca8875ececba13be6e9c6c370ffb752fd59985", size = 19641, upload-time = "2025-12-11T13:32:22.248Z" }, ] [[package]] name = "opentelemetry-exporter-prometheus" version = "0.60b1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, { name = "prometheus-client" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/14/39/7dafa6fff210737267bed35a8855b6ac7399b9e582b8cf1f25f842517012/opentelemetry_exporter_prometheus-0.60b1.tar.gz", hash = "sha256:a4011b46906323f71724649d301b4dc188aaa068852e814f4df38cc76eac616b", size = 14976, upload-time = "2025-12-11T13:32:42.944Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/39/7dafa6fff210737267bed35a8855b6ac7399b9e582b8cf1f25f842517012/opentelemetry_exporter_prometheus-0.60b1.tar.gz", hash = "sha256:a4011b46906323f71724649d301b4dc188aaa068852e814f4df38cc76eac616b", size = 14976, upload-time = "2025-12-11T13:32:42.944Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9b/0d/4be6bf5477a3eb3d917d2f17d3c0b6720cd6cb97898444a61d43cc983f5c/opentelemetry_exporter_prometheus-0.60b1-py3-none-any.whl", hash = "sha256:49f59178de4f4590e3cef0b8b95cf6e071aae70e1f060566df5546fad773b8fd", size = 13019, upload-time = "2025-12-11T13:32:23.974Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9b/0d/4be6bf5477a3eb3d917d2f17d3c0b6720cd6cb97898444a61d43cc983f5c/opentelemetry_exporter_prometheus-0.60b1-py3-none-any.whl", hash = "sha256:49f59178de4f4590e3cef0b8b95cf6e071aae70e1f060566df5546fad773b8fd", size = 13019, upload-time = "2025-12-11T13:32:23.974Z" }, ] [[package]] name = "opentelemetry-instrumentation" version = "0.60b1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "packaging" }, { name = "wrapt" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/41/0f/7e6b713ac117c1f5e4e3300748af699b9902a2e5e34c9cf443dde25a01fa/opentelemetry_instrumentation-0.60b1.tar.gz", hash = "sha256:57ddc7974c6eb35865af0426d1a17132b88b2ed8586897fee187fd5b8944bd6a", size = 31706, upload-time = "2025-12-11T13:36:42.515Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/0f/7e6b713ac117c1f5e4e3300748af699b9902a2e5e34c9cf443dde25a01fa/opentelemetry_instrumentation-0.60b1.tar.gz", hash = "sha256:57ddc7974c6eb35865af0426d1a17132b88b2ed8586897fee187fd5b8944bd6a", size = 31706, upload-time = "2025-12-11T13:36:42.515Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/77/d2/6788e83c5c86a2690101681aeef27eeb2a6bf22df52d3f263a22cee20915/opentelemetry_instrumentation-0.60b1-py3-none-any.whl", hash = "sha256:04480db952b48fb1ed0073f822f0ee26012b7be7c3eac1a3793122737c78632d", size = 33096, upload-time = "2025-12-11T13:35:33.067Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/77/d2/6788e83c5c86a2690101681aeef27eeb2a6bf22df52d3f263a22cee20915/opentelemetry_instrumentation-0.60b1-py3-none-any.whl", hash = "sha256:04480db952b48fb1ed0073f822f0ee26012b7be7c3eac1a3793122737c78632d", size = 33096, upload-time = "2025-12-11T13:35:33.067Z" }, ] [[package]] name = "opentelemetry-proto" version = "1.39.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/49/1d/f25d76d8260c156c40c97c9ed4511ec0f9ce353f8108ca6e7561f82a06b2/opentelemetry_proto-1.39.1.tar.gz", hash = "sha256:6c8e05144fc0d3ed4d22c2289c6b126e03bcd0e6a7da0f16cedd2e1c2772e2c8", size = 46152, upload-time = "2025-12-11T13:32:48.681Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/49/1d/f25d76d8260c156c40c97c9ed4511ec0f9ce353f8108ca6e7561f82a06b2/opentelemetry_proto-1.39.1.tar.gz", hash = "sha256:6c8e05144fc0d3ed4d22c2289c6b126e03bcd0e6a7da0f16cedd2e1c2772e2c8", size = 46152, upload-time = "2025-12-11T13:32:48.681Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/51/95/b40c96a7b5203005a0b03d8ce8cd212ff23f1793d5ba289c87a097571b18/opentelemetry_proto-1.39.1-py3-none-any.whl", hash = "sha256:22cdc78efd3b3765d09e68bfbd010d4fc254c9818afd0b6b423387d9dee46007", size = 72535, upload-time = "2025-12-11T13:32:33.866Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/51/95/b40c96a7b5203005a0b03d8ce8cd212ff23f1793d5ba289c87a097571b18/opentelemetry_proto-1.39.1-py3-none-any.whl", hash = "sha256:22cdc78efd3b3765d09e68bfbd010d4fc254c9818afd0b6b423387d9dee46007", size = 72535, upload-time = "2025-12-11T13:32:33.866Z" }, ] [[package]] name = "opentelemetry-sdk" version = "1.39.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/eb/fb/c76080c9ba07e1e8235d24cdcc4d125ef7aa3edf23eb4e497c2e50889adc/opentelemetry_sdk-1.39.1.tar.gz", hash = "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6", size = 171460, upload-time = "2025-12-11T13:32:49.369Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/eb/fb/c76080c9ba07e1e8235d24cdcc4d125ef7aa3edf23eb4e497c2e50889adc/opentelemetry_sdk-1.39.1.tar.gz", hash = "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6", size = 171460, upload-time = "2025-12-11T13:32:49.369Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7c/98/e91cf858f203d86f4eccdf763dcf01cf03f1dae80c3750f7e635bfa206b6/opentelemetry_sdk-1.39.1-py3-none-any.whl", hash = "sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c", size = 132565, upload-time = "2025-12-11T13:32:35.069Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7c/98/e91cf858f203d86f4eccdf763dcf01cf03f1dae80c3750f7e635bfa206b6/opentelemetry_sdk-1.39.1-py3-none-any.whl", hash = "sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c", size = 132565, upload-time = "2025-12-11T13:32:35.069Z" }, ] [[package]] name = "opentelemetry-semantic-conventions" version = "0.60b1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/91/df/553f93ed38bf22f4b999d9be9c185adb558982214f33eae539d3b5cd0858/opentelemetry_semantic_conventions-0.60b1.tar.gz", hash = "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953", size = 137935, upload-time = "2025-12-11T13:32:50.487Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/91/df/553f93ed38bf22f4b999d9be9c185adb558982214f33eae539d3b5cd0858/opentelemetry_semantic_conventions-0.60b1.tar.gz", hash = "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953", size = 137935, upload-time = "2025-12-11T13:32:50.487Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7a/5e/5958555e09635d09b75de3c4f8b9cae7335ca545d77392ffe7331534c402/opentelemetry_semantic_conventions-0.60b1-py3-none-any.whl", hash = "sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb", size = 219982, upload-time = "2025-12-11T13:32:36.955Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7a/5e/5958555e09635d09b75de3c4f8b9cae7335ca545d77392ffe7331534c402/opentelemetry_semantic_conventions-0.60b1-py3-none-any.whl", hash = "sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb", size = 219982, upload-time = "2025-12-11T13:32:36.955Z" }, ] [[package]] name = "orjson" version = "3.11.5" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/04/b8/333fdb27840f3bf04022d21b654a35f58e15407183aeb16f3b41aa053446/orjson-3.11.5.tar.gz", hash = "sha256:82393ab47b4fe44ffd0a7659fa9cfaacc717eb617c93cde83795f14af5c2e9d5", size = 5972347, upload-time = "2025-12-06T15:55:39.458Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ef/a4/8052a029029b096a78955eadd68ab594ce2197e24ec50e6b6d2ab3f4e33b/orjson-3.11.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:334e5b4bff9ad101237c2d799d9fd45737752929753bf4faf4b207335a416b7d", size = 245347, upload-time = "2025-12-06T15:54:22.061Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/64/67/574a7732bd9d9d79ac620c8790b4cfe0717a3d5a6eb2b539e6e8995e24a0/orjson-3.11.5-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:ff770589960a86eae279f5d8aa536196ebda8273a2a07db2a54e82b93bc86626", size = 129435, upload-time = "2025-12-06T15:54:23.615Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/52/8d/544e77d7a29d90cf4d9eecd0ae801c688e7f3d1adfa2ebae5e1e94d38ab9/orjson-3.11.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed24250e55efbcb0b35bed7caaec8cedf858ab2f9f2201f17b8938c618c8ca6f", size = 132074, upload-time = "2025-12-06T15:54:24.694Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/57/b9f5b5b6fbff9c26f77e785baf56ae8460ef74acdb3eae4931c25b8f5ba9/orjson-3.11.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a66d7769e98a08a12a139049aac2f0ca3adae989817f8c43337455fbc7669b85", size = 130520, upload-time = "2025-12-06T15:54:26.185Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f6/6d/d34970bf9eb33f9ec7c979a262cad86076814859e54eb9a059a52f6dc13d/orjson-3.11.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86cfc555bfd5794d24c6a1903e558b50644e5e68e6471d66502ce5cb5fdef3f9", size = 136209, upload-time = "2025-12-06T15:54:27.264Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/39/bc373b63cc0e117a105ea12e57280f83ae52fdee426890d57412432d63b3/orjson-3.11.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a230065027bc2a025e944f9d4714976a81e7ecfa940923283bca7bbc1f10f626", size = 139837, upload-time = "2025-12-06T15:54:28.75Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/aa/7c4818c8d7d324da220f4f1af55c343956003aa4d1ce1857bdc1d396ba69/orjson-3.11.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b29d36b60e606df01959c4b982729c8845c69d1963f88686608be9ced96dbfaa", size = 137307, upload-time = "2025-12-06T15:54:29.856Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/46/bf/0993b5a056759ba65145effe3a79dd5a939d4a070eaa5da2ee3180fbb13f/orjson-3.11.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c74099c6b230d4261fdc3169d50efc09abf38ace1a42ea2f9994b1d79153d477", size = 139020, upload-time = "2025-12-06T15:54:31.024Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/65/e8/83a6c95db3039e504eda60fc388f9faedbb4f6472f5aba7084e06552d9aa/orjson-3.11.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e697d06ad57dd0c7a737771d470eedc18e68dfdefcdd3b7de7f33dfda5b6212e", size = 141099, upload-time = "2025-12-06T15:54:32.196Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b9/b4/24fdc024abfce31c2f6812973b0a693688037ece5dc64b7a60c1ce69e2f2/orjson-3.11.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e08ca8a6c851e95aaecc32bc44a5aa75d0ad26af8cdac7c77e4ed93acf3d5b69", size = 413540, upload-time = "2025-12-06T15:54:33.361Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d9/37/01c0ec95d55ed0c11e4cae3e10427e479bba40c77312b63e1f9665e0737d/orjson-3.11.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e8b5f96c05fce7d0218df3fdfeb962d6b8cfff7e3e20264306b46dd8b217c0f3", size = 151530, upload-time = "2025-12-06T15:54:34.6Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/d4/f9ebc57182705bb4bbe63f5bbe14af43722a2533135e1d2fb7affa0c355d/orjson-3.11.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ddbfdb5099b3e6ba6d6ea818f61997bb66de14b411357d24c4612cf1ebad08ca", size = 141863, upload-time = "2025-12-06T15:54:35.801Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0d/04/02102b8d19fdcb009d72d622bb5781e8f3fae1646bf3e18c53d1bc8115b5/orjson-3.11.5-cp312-cp312-win32.whl", hash = "sha256:9172578c4eb09dbfcf1657d43198de59b6cef4054de385365060ed50c458ac98", size = 135255, upload-time = "2025-12-06T15:54:37.209Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d4/fb/f05646c43d5450492cb387de5549f6de90a71001682c17882d9f66476af5/orjson-3.11.5-cp312-cp312-win_amd64.whl", hash = "sha256:2b91126e7b470ff2e75746f6f6ee32b9ab67b7a93c8ba1d15d3a0caaf16ec875", size = 133252, upload-time = "2025-12-06T15:54:38.401Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/a6/7b8c0b26ba18c793533ac1cd145e131e46fcf43952aa94c109b5b913c1f0/orjson-3.11.5-cp312-cp312-win_arm64.whl", hash = "sha256:acbc5fac7e06777555b0722b8ad5f574739e99ffe99467ed63da98f97f9ca0fe", size = 126777, upload-time = "2025-12-06T15:54:39.515Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/10/43/61a77040ce59f1569edf38f0b9faadc90c8cf7e9bec2e0df51d0132c6bb7/orjson-3.11.5-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3b01799262081a4c47c035dd77c1301d40f568f77cc7ec1bb7db5d63b0a01629", size = 245271, upload-time = "2025-12-06T15:54:40.878Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/55/f9/0f79be617388227866d50edd2fd320cb8fb94dc1501184bb1620981a0aba/orjson-3.11.5-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:61de247948108484779f57a9f406e4c84d636fa5a59e411e6352484985e8a7c3", size = 129422, upload-time = "2025-12-06T15:54:42.403Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/77/42/f1bf1549b432d4a78bfa95735b79b5dac75b65b5bb815bba86ad406ead0a/orjson-3.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:894aea2e63d4f24a7f04a1908307c738d0dce992e9249e744b8f4e8dd9197f39", size = 132060, upload-time = "2025-12-06T15:54:43.531Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/49/825aa6b929f1a6ed244c78acd7b22c1481fd7e5fda047dc8bf4c1a807eb6/orjson-3.11.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ddc21521598dbe369d83d4d40338e23d4101dad21dae0e79fa20465dbace019f", size = 130391, upload-time = "2025-12-06T15:54:45.059Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/42/ec/de55391858b49e16e1aa8f0bbbb7e5997b7345d8e984a2dec3746d13065b/orjson-3.11.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7cce16ae2f5fb2c53c3eafdd1706cb7b6530a67cc1c17abe8ec747f5cd7c0c51", size = 135964, upload-time = "2025-12-06T15:54:46.576Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/40/820bc63121d2d28818556a2d0a09384a9f0262407cf9fa305e091a8048df/orjson-3.11.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e46c762d9f0e1cfb4ccc8515de7f349abbc95b59cb5a2bd68df5973fdef913f8", size = 139817, upload-time = "2025-12-06T15:54:48.084Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/09/c7/3a445ca9a84a0d59d26365fd8898ff52bdfcdcb825bcc6519830371d2364/orjson-3.11.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7345c759276b798ccd6d77a87136029e71e66a8bbf2d2755cbdde1d82e78706", size = 137336, upload-time = "2025-12-06T15:54:49.426Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/b3/dc0d3771f2e5d1f13368f56b339c6782f955c6a20b50465a91acb79fe961/orjson-3.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75bc2e59e6a2ac1dd28901d07115abdebc4563b5b07dd612bf64260a201b1c7f", size = 138993, upload-time = "2025-12-06T15:54:50.939Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/a2/65267e959de6abe23444659b6e19c888f242bf7725ff927e2292776f6b89/orjson-3.11.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:54aae9b654554c3b4edd61896b978568c6daa16af96fa4681c9b5babd469f863", size = 141070, upload-time = "2025-12-06T15:54:52.414Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/63/c9/da44a321b288727a322c6ab17e1754195708786a04f4f9d2220a5076a649/orjson-3.11.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4bdd8d164a871c4ec773f9de0f6fe8769c2d6727879c37a9666ba4183b7f8228", size = 413505, upload-time = "2025-12-06T15:54:53.67Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/17/68dc14fa7000eefb3d4d6d7326a190c99bb65e319f02747ef3ebf2452f12/orjson-3.11.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a261fef929bcf98a60713bf5e95ad067cea16ae345d9a35034e73c3990e927d2", size = 151342, upload-time = "2025-12-06T15:54:55.113Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/c5/ccee774b67225bed630a57478529fc026eda33d94fe4c0eac8fe58d4aa52/orjson-3.11.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c028a394c766693c5c9909dec76b24f37e6a1b91999e8d0c0d5feecbe93c3e05", size = 141823, upload-time = "2025-12-06T15:54:56.331Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/67/80/5d00e4155d0cd7390ae2087130637671da713959bb558db9bac5e6f6b042/orjson-3.11.5-cp313-cp313-win32.whl", hash = "sha256:2cc79aaad1dfabe1bd2d50ee09814a1253164b3da4c00a78c458d82d04b3bdef", size = 135236, upload-time = "2025-12-06T15:54:57.507Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/fe/792cc06a84808dbdc20ac6eab6811c53091b42f8e51ecebf14b540e9cfe4/orjson-3.11.5-cp313-cp313-win_amd64.whl", hash = "sha256:ff7877d376add4e16b274e35a3f58b7f37b362abf4aa31863dadacdd20e3a583", size = 133167, upload-time = "2025-12-06T15:54:58.71Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/46/2c/d158bd8b50e3b1cfdcf406a7e463f6ffe3f0d167b99634717acdaf5e299f/orjson-3.11.5-cp313-cp313-win_arm64.whl", hash = "sha256:59ac72ea775c88b163ba8d21b0177628bd015c5dd060647bbab6e22da3aad287", size = 126712, upload-time = "2025-12-06T15:54:59.892Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/b8/333fdb27840f3bf04022d21b654a35f58e15407183aeb16f3b41aa053446/orjson-3.11.5.tar.gz", hash = "sha256:82393ab47b4fe44ffd0a7659fa9cfaacc717eb617c93cde83795f14af5c2e9d5", size = 5972347, upload-time = "2025-12-06T15:55:39.458Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ef/a4/8052a029029b096a78955eadd68ab594ce2197e24ec50e6b6d2ab3f4e33b/orjson-3.11.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:334e5b4bff9ad101237c2d799d9fd45737752929753bf4faf4b207335a416b7d", size = 245347, upload-time = "2025-12-06T15:54:22.061Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/64/67/574a7732bd9d9d79ac620c8790b4cfe0717a3d5a6eb2b539e6e8995e24a0/orjson-3.11.5-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:ff770589960a86eae279f5d8aa536196ebda8273a2a07db2a54e82b93bc86626", size = 129435, upload-time = "2025-12-06T15:54:23.615Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/52/8d/544e77d7a29d90cf4d9eecd0ae801c688e7f3d1adfa2ebae5e1e94d38ab9/orjson-3.11.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed24250e55efbcb0b35bed7caaec8cedf858ab2f9f2201f17b8938c618c8ca6f", size = 132074, upload-time = "2025-12-06T15:54:24.694Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/57/b9f5b5b6fbff9c26f77e785baf56ae8460ef74acdb3eae4931c25b8f5ba9/orjson-3.11.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a66d7769e98a08a12a139049aac2f0ca3adae989817f8c43337455fbc7669b85", size = 130520, upload-time = "2025-12-06T15:54:26.185Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f6/6d/d34970bf9eb33f9ec7c979a262cad86076814859e54eb9a059a52f6dc13d/orjson-3.11.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86cfc555bfd5794d24c6a1903e558b50644e5e68e6471d66502ce5cb5fdef3f9", size = 136209, upload-time = "2025-12-06T15:54:27.264Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/39/bc373b63cc0e117a105ea12e57280f83ae52fdee426890d57412432d63b3/orjson-3.11.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a230065027bc2a025e944f9d4714976a81e7ecfa940923283bca7bbc1f10f626", size = 139837, upload-time = "2025-12-06T15:54:28.75Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/aa/7c4818c8d7d324da220f4f1af55c343956003aa4d1ce1857bdc1d396ba69/orjson-3.11.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b29d36b60e606df01959c4b982729c8845c69d1963f88686608be9ced96dbfaa", size = 137307, upload-time = "2025-12-06T15:54:29.856Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/46/bf/0993b5a056759ba65145effe3a79dd5a939d4a070eaa5da2ee3180fbb13f/orjson-3.11.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c74099c6b230d4261fdc3169d50efc09abf38ace1a42ea2f9994b1d79153d477", size = 139020, upload-time = "2025-12-06T15:54:31.024Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/65/e8/83a6c95db3039e504eda60fc388f9faedbb4f6472f5aba7084e06552d9aa/orjson-3.11.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e697d06ad57dd0c7a737771d470eedc18e68dfdefcdd3b7de7f33dfda5b6212e", size = 141099, upload-time = "2025-12-06T15:54:32.196Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/b4/24fdc024abfce31c2f6812973b0a693688037ece5dc64b7a60c1ce69e2f2/orjson-3.11.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e08ca8a6c851e95aaecc32bc44a5aa75d0ad26af8cdac7c77e4ed93acf3d5b69", size = 413540, upload-time = "2025-12-06T15:54:33.361Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/37/01c0ec95d55ed0c11e4cae3e10427e479bba40c77312b63e1f9665e0737d/orjson-3.11.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e8b5f96c05fce7d0218df3fdfeb962d6b8cfff7e3e20264306b46dd8b217c0f3", size = 151530, upload-time = "2025-12-06T15:54:34.6Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/d4/f9ebc57182705bb4bbe63f5bbe14af43722a2533135e1d2fb7affa0c355d/orjson-3.11.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ddbfdb5099b3e6ba6d6ea818f61997bb66de14b411357d24c4612cf1ebad08ca", size = 141863, upload-time = "2025-12-06T15:54:35.801Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0d/04/02102b8d19fdcb009d72d622bb5781e8f3fae1646bf3e18c53d1bc8115b5/orjson-3.11.5-cp312-cp312-win32.whl", hash = "sha256:9172578c4eb09dbfcf1657d43198de59b6cef4054de385365060ed50c458ac98", size = 135255, upload-time = "2025-12-06T15:54:37.209Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/fb/f05646c43d5450492cb387de5549f6de90a71001682c17882d9f66476af5/orjson-3.11.5-cp312-cp312-win_amd64.whl", hash = "sha256:2b91126e7b470ff2e75746f6f6ee32b9ab67b7a93c8ba1d15d3a0caaf16ec875", size = 133252, upload-time = "2025-12-06T15:54:38.401Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/a6/7b8c0b26ba18c793533ac1cd145e131e46fcf43952aa94c109b5b913c1f0/orjson-3.11.5-cp312-cp312-win_arm64.whl", hash = "sha256:acbc5fac7e06777555b0722b8ad5f574739e99ffe99467ed63da98f97f9ca0fe", size = 126777, upload-time = "2025-12-06T15:54:39.515Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/43/61a77040ce59f1569edf38f0b9faadc90c8cf7e9bec2e0df51d0132c6bb7/orjson-3.11.5-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3b01799262081a4c47c035dd77c1301d40f568f77cc7ec1bb7db5d63b0a01629", size = 245271, upload-time = "2025-12-06T15:54:40.878Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/55/f9/0f79be617388227866d50edd2fd320cb8fb94dc1501184bb1620981a0aba/orjson-3.11.5-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:61de247948108484779f57a9f406e4c84d636fa5a59e411e6352484985e8a7c3", size = 129422, upload-time = "2025-12-06T15:54:42.403Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/77/42/f1bf1549b432d4a78bfa95735b79b5dac75b65b5bb815bba86ad406ead0a/orjson-3.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:894aea2e63d4f24a7f04a1908307c738d0dce992e9249e744b8f4e8dd9197f39", size = 132060, upload-time = "2025-12-06T15:54:43.531Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/49/825aa6b929f1a6ed244c78acd7b22c1481fd7e5fda047dc8bf4c1a807eb6/orjson-3.11.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ddc21521598dbe369d83d4d40338e23d4101dad21dae0e79fa20465dbace019f", size = 130391, upload-time = "2025-12-06T15:54:45.059Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/42/ec/de55391858b49e16e1aa8f0bbbb7e5997b7345d8e984a2dec3746d13065b/orjson-3.11.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7cce16ae2f5fb2c53c3eafdd1706cb7b6530a67cc1c17abe8ec747f5cd7c0c51", size = 135964, upload-time = "2025-12-06T15:54:46.576Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/40/820bc63121d2d28818556a2d0a09384a9f0262407cf9fa305e091a8048df/orjson-3.11.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e46c762d9f0e1cfb4ccc8515de7f349abbc95b59cb5a2bd68df5973fdef913f8", size = 139817, upload-time = "2025-12-06T15:54:48.084Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/09/c7/3a445ca9a84a0d59d26365fd8898ff52bdfcdcb825bcc6519830371d2364/orjson-3.11.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7345c759276b798ccd6d77a87136029e71e66a8bbf2d2755cbdde1d82e78706", size = 137336, upload-time = "2025-12-06T15:54:49.426Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/b3/dc0d3771f2e5d1f13368f56b339c6782f955c6a20b50465a91acb79fe961/orjson-3.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75bc2e59e6a2ac1dd28901d07115abdebc4563b5b07dd612bf64260a201b1c7f", size = 138993, upload-time = "2025-12-06T15:54:50.939Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/a2/65267e959de6abe23444659b6e19c888f242bf7725ff927e2292776f6b89/orjson-3.11.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:54aae9b654554c3b4edd61896b978568c6daa16af96fa4681c9b5babd469f863", size = 141070, upload-time = "2025-12-06T15:54:52.414Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/63/c9/da44a321b288727a322c6ab17e1754195708786a04f4f9d2220a5076a649/orjson-3.11.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4bdd8d164a871c4ec773f9de0f6fe8769c2d6727879c37a9666ba4183b7f8228", size = 413505, upload-time = "2025-12-06T15:54:53.67Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/17/68dc14fa7000eefb3d4d6d7326a190c99bb65e319f02747ef3ebf2452f12/orjson-3.11.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a261fef929bcf98a60713bf5e95ad067cea16ae345d9a35034e73c3990e927d2", size = 151342, upload-time = "2025-12-06T15:54:55.113Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/c5/ccee774b67225bed630a57478529fc026eda33d94fe4c0eac8fe58d4aa52/orjson-3.11.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c028a394c766693c5c9909dec76b24f37e6a1b91999e8d0c0d5feecbe93c3e05", size = 141823, upload-time = "2025-12-06T15:54:56.331Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/67/80/5d00e4155d0cd7390ae2087130637671da713959bb558db9bac5e6f6b042/orjson-3.11.5-cp313-cp313-win32.whl", hash = "sha256:2cc79aaad1dfabe1bd2d50ee09814a1253164b3da4c00a78c458d82d04b3bdef", size = 135236, upload-time = "2025-12-06T15:54:57.507Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/fe/792cc06a84808dbdc20ac6eab6811c53091b42f8e51ecebf14b540e9cfe4/orjson-3.11.5-cp313-cp313-win_amd64.whl", hash = "sha256:ff7877d376add4e16b274e35a3f58b7f37b362abf4aa31863dadacdd20e3a583", size = 133167, upload-time = "2025-12-06T15:54:58.71Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/46/2c/d158bd8b50e3b1cfdcf406a7e463f6ffe3f0d167b99634717acdaf5e299f/orjson-3.11.5-cp313-cp313-win_arm64.whl", hash = "sha256:59ac72ea775c88b163ba8d21b0177628bd015c5dd060647bbab6e22da3aad287", size = 126712, upload-time = "2025-12-06T15:54:59.892Z" }, ] [[package]] name = "ormsgpack" version = "1.12.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fe/96/34c40d621996c2f377a18decbd3c59f031dde73c3ba47d1e1e8f29a05aaa/ormsgpack-1.12.1.tar.gz", hash = "sha256:a3877fde1e4f27a39f92681a0aab6385af3a41d0c25375d33590ae20410ea2ac", size = 39476, upload-time = "2025-12-14T07:57:43.248Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/17/fe/ab9167ca037406b5703add24049cf3e18021a3b16133ea20615b1f160ea4/ormsgpack-1.12.1-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4d7fb0e1b6fbc701d75269f7405a4f79230a6ce0063fb1092e4f6577e312f86d", size = 376725, upload-time = "2025-12-14T07:57:07.894Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/ea/2820e65f506894c459b840d1091ae6e327fde3d5a3f3b002a11a1b9bdf7d/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43a9353e2db5b024c91a47d864ef15eaa62d81824cfc7740fed4cef7db738694", size = 202466, upload-time = "2025-12-14T07:57:09.049Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/45/8b/def01c13339c5bbec2ee1469ef53e7fadd66c8d775df974ee4def1572515/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc8fe866b7706fc25af0adf1f600bc06ece5b15ca44e34641327198b821e5c3c", size = 210748, upload-time = "2025-12-14T07:57:10.074Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5d/d2/bf350c92f7f067dd9484499705f2d8366d8d9008a670e3d1d0add1908f85/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:813755b5f598a78242042e05dfd1ada4e769e94b98c9ab82554550f97ff4d641", size = 211510, upload-time = "2025-12-14T07:57:11.165Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/74/92/9d689bcb95304a6da26c4d59439c350940c25d1b35f146d402ccc6344c51/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8eea2a13536fae45d78f93f2cc846c9765c7160c85f19cfefecc20873c137cdd", size = 386237, upload-time = "2025-12-14T07:57:12.306Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/17/fe/bd3107547f8b6129265dd957f40b9cd547d2445db2292aacb13335a7ea89/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7a02ebda1a863cbc604740e76faca8eee1add322db2dcbe6cf32669fffdff65c", size = 479589, upload-time = "2025-12-14T07:57:13.475Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c1/7c/e8e5cc9edb967d44f6f85e9ebdad440b59af3fae00b137a4327dc5aed9bb/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3c0bd63897c439931cdf29348e5e6e8c330d529830e848d10767615c0f3d1b82", size = 388077, upload-time = "2025-12-14T07:57:14.551Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/35/6b/5031797e43b58506f28a8760b26dc23f2620fb4f2200c4c1b3045603e67e/ormsgpack-1.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:362f2e812f8d7035dc25a009171e09d7cc97cb30d3c9e75a16aeae00ca3c1dcf", size = 116190, upload-time = "2025-12-14T07:57:15.575Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1e/fd/9f43ea6425e383a6b2dbfafebb06fd60e8d68c700ef715adfbcdb499f75d/ormsgpack-1.12.1-cp312-cp312-win_arm64.whl", hash = "sha256:6190281e381db2ed0045052208f47a995ccf61eed48f1215ae3cce3fbccd59c5", size = 109990, upload-time = "2025-12-14T07:57:16.419Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/11/42/f110dfe7cf23a52a82e23eb23d9a6a76ae495447d474686dfa758f3d71d6/ormsgpack-1.12.1-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:9663d6b3ecc917c063d61a99169ce196a80f3852e541ae404206836749459279", size = 376746, upload-time = "2025-12-14T07:57:17.699Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/11/76/b386e508a8ae207daec240201a81adb26467bf99b163560724e86bd9ff33/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32e85cfbaf01a94a92520e7fe7851cfcfe21a5698299c28ab86194895f9b9233", size = 202489, upload-time = "2025-12-14T07:57:18.807Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/0e/5db7a63f387149024572daa3d9512fe8fb14bf4efa0722d6d491bed280e7/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dabfd2c24b59c7c69870a5ecee480dfae914a42a0c2e7c9d971cf531e2ba471a", size = 210757, upload-time = "2025-12-14T07:57:19.893Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/64/79/3a9899e57cb57430bd766fc1b4c9ad410cb2ba6070bc8cf6301e7d385768/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51bbf2b64afeded34ccd8e25402e4bca038757913931fa0d693078d75563f6f9", size = 211518, upload-time = "2025-12-14T07:57:20.972Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d7/cd/4f41710ae9fe50d7fcbe476793b3c487746d0e1cc194cc0fee42ff6d989b/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9959a71dde1bd0ced84af17facc06a8afada495a34e9cb1bad8e9b20d4c59cef", size = 386251, upload-time = "2025-12-14T07:57:22.099Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bf/54/ba0c97d6231b1f01daafaa520c8cce1e1b7fceaae6fdc1c763925874a7de/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:e9be0e3b62d758f21f5b20e0e06b3a240ec546c4a327bf771f5825462aa74714", size = 479607, upload-time = "2025-12-14T07:57:23.525Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/18/75/19a9a97a462776d525baf41cfb7072734528775f0a3d5fbfab3aa7756b9b/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a29d49ab7fdd77ea787818e60cb4ef491708105b9c4c9b0f919201625eb036b5", size = 388062, upload-time = "2025-12-14T07:57:24.616Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a8/6a/ec26e3f44e9632ecd2f43638b7b37b500eaea5d79cab984ad0b94be14f82/ormsgpack-1.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:c418390b47a1d367e803f6c187f77e4d67c7ae07ba962e3a4a019001f4b0291a", size = 116195, upload-time = "2025-12-14T07:57:25.626Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7d/64/bfa5f4a34d0f15c6aba1b73e73f7441a66d635bd03249d334a4796b7a924/ormsgpack-1.12.1-cp313-cp313-win_arm64.whl", hash = "sha256:cfa22c91cffc10a7fbd43729baff2de7d9c28cef2509085a704168ae31f02568", size = 109986, upload-time = "2025-12-14T07:57:26.569Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fe/96/34c40d621996c2f377a18decbd3c59f031dde73c3ba47d1e1e8f29a05aaa/ormsgpack-1.12.1.tar.gz", hash = "sha256:a3877fde1e4f27a39f92681a0aab6385af3a41d0c25375d33590ae20410ea2ac", size = 39476, upload-time = "2025-12-14T07:57:43.248Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/17/fe/ab9167ca037406b5703add24049cf3e18021a3b16133ea20615b1f160ea4/ormsgpack-1.12.1-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4d7fb0e1b6fbc701d75269f7405a4f79230a6ce0063fb1092e4f6577e312f86d", size = 376725, upload-time = "2025-12-14T07:57:07.894Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/ea/2820e65f506894c459b840d1091ae6e327fde3d5a3f3b002a11a1b9bdf7d/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43a9353e2db5b024c91a47d864ef15eaa62d81824cfc7740fed4cef7db738694", size = 202466, upload-time = "2025-12-14T07:57:09.049Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/45/8b/def01c13339c5bbec2ee1469ef53e7fadd66c8d775df974ee4def1572515/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc8fe866b7706fc25af0adf1f600bc06ece5b15ca44e34641327198b821e5c3c", size = 210748, upload-time = "2025-12-14T07:57:10.074Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/d2/bf350c92f7f067dd9484499705f2d8366d8d9008a670e3d1d0add1908f85/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:813755b5f598a78242042e05dfd1ada4e769e94b98c9ab82554550f97ff4d641", size = 211510, upload-time = "2025-12-14T07:57:11.165Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/74/92/9d689bcb95304a6da26c4d59439c350940c25d1b35f146d402ccc6344c51/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8eea2a13536fae45d78f93f2cc846c9765c7160c85f19cfefecc20873c137cdd", size = 386237, upload-time = "2025-12-14T07:57:12.306Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/17/fe/bd3107547f8b6129265dd957f40b9cd547d2445db2292aacb13335a7ea89/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7a02ebda1a863cbc604740e76faca8eee1add322db2dcbe6cf32669fffdff65c", size = 479589, upload-time = "2025-12-14T07:57:13.475Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/7c/e8e5cc9edb967d44f6f85e9ebdad440b59af3fae00b137a4327dc5aed9bb/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3c0bd63897c439931cdf29348e5e6e8c330d529830e848d10767615c0f3d1b82", size = 388077, upload-time = "2025-12-14T07:57:14.551Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/35/6b/5031797e43b58506f28a8760b26dc23f2620fb4f2200c4c1b3045603e67e/ormsgpack-1.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:362f2e812f8d7035dc25a009171e09d7cc97cb30d3c9e75a16aeae00ca3c1dcf", size = 116190, upload-time = "2025-12-14T07:57:15.575Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1e/fd/9f43ea6425e383a6b2dbfafebb06fd60e8d68c700ef715adfbcdb499f75d/ormsgpack-1.12.1-cp312-cp312-win_arm64.whl", hash = "sha256:6190281e381db2ed0045052208f47a995ccf61eed48f1215ae3cce3fbccd59c5", size = 109990, upload-time = "2025-12-14T07:57:16.419Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/11/42/f110dfe7cf23a52a82e23eb23d9a6a76ae495447d474686dfa758f3d71d6/ormsgpack-1.12.1-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:9663d6b3ecc917c063d61a99169ce196a80f3852e541ae404206836749459279", size = 376746, upload-time = "2025-12-14T07:57:17.699Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/11/76/b386e508a8ae207daec240201a81adb26467bf99b163560724e86bd9ff33/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32e85cfbaf01a94a92520e7fe7851cfcfe21a5698299c28ab86194895f9b9233", size = 202489, upload-time = "2025-12-14T07:57:18.807Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/0e/5db7a63f387149024572daa3d9512fe8fb14bf4efa0722d6d491bed280e7/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dabfd2c24b59c7c69870a5ecee480dfae914a42a0c2e7c9d971cf531e2ba471a", size = 210757, upload-time = "2025-12-14T07:57:19.893Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/64/79/3a9899e57cb57430bd766fc1b4c9ad410cb2ba6070bc8cf6301e7d385768/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51bbf2b64afeded34ccd8e25402e4bca038757913931fa0d693078d75563f6f9", size = 211518, upload-time = "2025-12-14T07:57:20.972Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d7/cd/4f41710ae9fe50d7fcbe476793b3c487746d0e1cc194cc0fee42ff6d989b/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9959a71dde1bd0ced84af17facc06a8afada495a34e9cb1bad8e9b20d4c59cef", size = 386251, upload-time = "2025-12-14T07:57:22.099Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/54/ba0c97d6231b1f01daafaa520c8cce1e1b7fceaae6fdc1c763925874a7de/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:e9be0e3b62d758f21f5b20e0e06b3a240ec546c4a327bf771f5825462aa74714", size = 479607, upload-time = "2025-12-14T07:57:23.525Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/75/19a9a97a462776d525baf41cfb7072734528775f0a3d5fbfab3aa7756b9b/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a29d49ab7fdd77ea787818e60cb4ef491708105b9c4c9b0f919201625eb036b5", size = 388062, upload-time = "2025-12-14T07:57:24.616Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a8/6a/ec26e3f44e9632ecd2f43638b7b37b500eaea5d79cab984ad0b94be14f82/ormsgpack-1.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:c418390b47a1d367e803f6c187f77e4d67c7ae07ba962e3a4a019001f4b0291a", size = 116195, upload-time = "2025-12-14T07:57:25.626Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7d/64/bfa5f4a34d0f15c6aba1b73e73f7441a66d635bd03249d334a4796b7a924/ormsgpack-1.12.1-cp313-cp313-win_arm64.whl", hash = "sha256:cfa22c91cffc10a7fbd43729baff2de7d9c28cef2509085a704168ae31f02568", size = 109986, upload-time = "2025-12-14T07:57:26.569Z" }, ] [[package]] name = "outcome" version = "1.3.0.post0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "attrs" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/df/77698abfac98571e65ffeb0c1fba8ffd692ab8458d617a0eed7d9a8d38f2/outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/df/77698abfac98571e65ffeb0c1fba8ffd692ab8458d617a0eed7d9a8d38f2/outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b" }, ] [[package]] name = "packaging" version = "25.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/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://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/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 = "passlib" version = "1.7.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b6/06/9da9ee59a67fae7761aab3ccc84fa4f3f33f125b370f1ccdb915bf967c11/passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04", size = 689844, upload-time = "2020-10-08T19:00:52.121Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b6/06/9da9ee59a67fae7761aab3ccc84fa4f3f33f125b370f1ccdb915bf967c11/passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04", size = 689844, upload-time = "2020-10-08T19:00:52.121Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3b/a4/ab6b7589382ca3df236e03faa71deac88cae040af60c071a78d254a62172/passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1", size = 525554, upload-time = "2020-10-08T19:00:49.856Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3b/a4/ab6b7589382ca3df236e03faa71deac88cae040af60c071a78d254a62172/passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1", size = 525554, upload-time = "2020-10-08T19:00:49.856Z" }, ] [package.optional-dependencies] @@ -2784,61 +2775,61 @@ bcrypt = [ [[package]] name = "pathable" version = "0.4.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/67/93/8f2c2075b180c12c1e9f6a09d1a985bc2036906b13dff1d8917e395f2048/pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2", size = 8124, upload-time = "2025-01-10T18:43:13.247Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/67/93/8f2c2075b180c12c1e9f6a09d1a985bc2036906b13dff1d8917e395f2048/pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2", size = 8124, upload-time = "2025-01-10T18:43:13.247Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7d/eb/b6260b31b1a96386c0a880edebe26f89669098acea8e0318bff6adb378fd/pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2", size = 9592, upload-time = "2025-01-10T18:43:11.88Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7d/eb/b6260b31b1a96386c0a880edebe26f89669098acea8e0318bff6adb378fd/pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2", size = 9592, upload-time = "2025-01-10T18:43:11.88Z" }, ] [[package]] name = "pathspec" version = "0.12.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, ] [[package]] name = "pathvalidate" version = "3.3.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fa/2a/52a8da6fe965dea6192eb716b357558e103aea0a1e9a8352ad575a8406ca/pathvalidate-3.3.1.tar.gz", hash = "sha256:b18c07212bfead624345bb8e1d6141cdcf15a39736994ea0b94035ad2b1ba177", size = 63262, upload-time = "2025-06-15T09:07:20.736Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fa/2a/52a8da6fe965dea6192eb716b357558e103aea0a1e9a8352ad575a8406ca/pathvalidate-3.3.1.tar.gz", hash = "sha256:b18c07212bfead624345bb8e1d6141cdcf15a39736994ea0b94035ad2b1ba177", size = 63262, upload-time = "2025-06-15T09:07:20.736Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/70/875f4a23bfc4731703a5835487d0d2fb999031bd415e7d17c0ae615c18b7/pathvalidate-3.3.1-py3-none-any.whl", hash = "sha256:5263baab691f8e1af96092fa5137ee17df5bdfbd6cff1fcac4d6ef4bc2e1735f", size = 24305, upload-time = "2025-06-15T09:07:19.117Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/70/875f4a23bfc4731703a5835487d0d2fb999031bd415e7d17c0ae615c18b7/pathvalidate-3.3.1-py3-none-any.whl", hash = "sha256:5263baab691f8e1af96092fa5137ee17df5bdfbd6cff1fcac4d6ef4bc2e1735f", size = 24305, upload-time = "2025-06-15T09:07:19.117Z" }, ] [[package]] name = "pefile" version = "2024.8.26" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/03/4f/2750f7f6f025a1507cd3b7218691671eecfd0bbebebe8b39aa0fe1d360b8/pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632", size = 76008, upload-time = "2024-08-26T20:58:38.155Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/03/4f/2750f7f6f025a1507cd3b7218691671eecfd0bbebebe8b39aa0fe1d360b8/pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632", size = 76008, upload-time = "2024-08-26T20:58:38.155Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/16/12b82f791c7f50ddec566873d5bdd245baa1491bac11d15ffb98aecc8f8b/pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f", size = 74766, upload-time = "2024-08-26T21:01:02.632Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/16/12b82f791c7f50ddec566873d5bdd245baa1491bac11d15ffb98aecc8f8b/pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f", size = 74766, upload-time = "2024-08-26T21:01:02.632Z" }, ] [[package]] name = "platformdirs" version = "4.5.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, ] [[package]] name = "pluggy" version = "1.6.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/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://mirrors.tuna.tsinghua.edu.cn/pypi/web/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" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/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]] name = "pre-commit" version = "4.5.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cfgv" }, { name = "identify" }, @@ -2846,131 +2837,131 @@ dependencies = [ { name = "pyyaml" }, { name = "virtualenv" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61", size = 198232, upload-time = "2025-12-16T21:14:33.552Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61", size = 198232, upload-time = "2025-12-16T21:14:33.552Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" }, ] [[package]] name = "priority" version = "2.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/3c/eb7c35f4dcede96fca1842dac5f4f5d15511aa4b52f3a961219e68ae9204/priority-2.0.0.tar.gz", hash = "sha256:c965d54f1b8d0d0b19479db3924c7c36cf672dbf2aec92d43fbdaf4492ba18c0", size = 24792, upload-time = "2021-06-27T10:15:05.487Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/3c/eb7c35f4dcede96fca1842dac5f4f5d15511aa4b52f3a961219e68ae9204/priority-2.0.0.tar.gz", hash = "sha256:c965d54f1b8d0d0b19479db3924c7c36cf672dbf2aec92d43fbdaf4492ba18c0", size = 24792, upload-time = "2021-06-27T10:15:05.487Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5e/5f/82c8074f7e84978129347c2c6ec8b6c59f3584ff1a20bc3c940a3e061790/priority-2.0.0-py3-none-any.whl", hash = "sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa", size = 8946, upload-time = "2021-06-27T10:15:03.856Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5e/5f/82c8074f7e84978129347c2c6ec8b6c59f3584ff1a20bc3c940a3e061790/priority-2.0.0-py3-none-any.whl", hash = "sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa", size = 8946, upload-time = "2021-06-27T10:15:03.856Z" }, ] [[package]] name = "prometheus-client" version = "0.23.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/23/53/3edb5d68ecf6b38fcbcc1ad28391117d2a322d9a1a3eff04bfdb184d8c3b/prometheus_client-0.23.1.tar.gz", hash = "sha256:6ae8f9081eaaaf153a2e959d2e6c4f4fb57b12ef76c8c7980202f1e57b48b2ce", size = 80481, upload-time = "2025-09-18T20:47:25.043Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/23/53/3edb5d68ecf6b38fcbcc1ad28391117d2a322d9a1a3eff04bfdb184d8c3b/prometheus_client-0.23.1.tar.gz", hash = "sha256:6ae8f9081eaaaf153a2e959d2e6c4f4fb57b12ef76c8c7980202f1e57b48b2ce", size = 80481, upload-time = "2025-09-18T20:47:25.043Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b8/db/14bafcb4af2139e046d03fd00dea7873e48eafe18b7d2797e73d6681f210/prometheus_client-0.23.1-py3-none-any.whl", hash = "sha256:dd1913e6e76b59cfe44e7a4b83e01afc9873c1bdfd2ed8739f1e76aeca115f99", size = 61145, upload-time = "2025-09-18T20:47:23.875Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b8/db/14bafcb4af2139e046d03fd00dea7873e48eafe18b7d2797e73d6681f210/prometheus_client-0.23.1-py3-none-any.whl", hash = "sha256:dd1913e6e76b59cfe44e7a4b83e01afc9873c1bdfd2ed8739f1e76aeca115f99", size = 61145, upload-time = "2025-09-18T20:47:23.875Z" }, ] [[package]] name = "propcache" version = "0.4.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, ] [[package]] name = "protobuf" version = "6.33.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/34/44/e49ecff446afeec9d1a66d6bbf9adc21e3c7cea7803a920ca3773379d4f6/protobuf-6.33.2.tar.gz", hash = "sha256:56dc370c91fbb8ac85bc13582c9e373569668a290aa2e66a590c2a0d35ddb9e4", size = 444296, upload-time = "2025-12-06T00:17:53.311Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/34/44/e49ecff446afeec9d1a66d6bbf9adc21e3c7cea7803a920ca3773379d4f6/protobuf-6.33.2.tar.gz", hash = "sha256:56dc370c91fbb8ac85bc13582c9e373569668a290aa2e66a590c2a0d35ddb9e4", size = 444296, upload-time = "2025-12-06T00:17:53.311Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bc/91/1e3a34881a88697a7354ffd177e8746e97a722e5e8db101544b47e84afb1/protobuf-6.33.2-cp310-abi3-win32.whl", hash = "sha256:87eb388bd2d0f78febd8f4c8779c79247b26a5befad525008e49a6955787ff3d", size = 425603, upload-time = "2025-12-06T00:17:41.114Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/64/20/4d50191997e917ae13ad0a235c8b42d8c1ab9c3e6fd455ca16d416944355/protobuf-6.33.2-cp310-abi3-win_amd64.whl", hash = "sha256:fc2a0e8b05b180e5fc0dd1559fe8ebdae21a27e81ac77728fb6c42b12c7419b4", size = 436930, upload-time = "2025-12-06T00:17:43.278Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43", size = 427621, upload-time = "2025-12-06T00:17:44.445Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:b5d3b5625192214066d99b2b605f5783483575656784de223f00a8d00754fc0e", size = 324460, upload-time = "2025-12-06T00:17:45.678Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b1/fa/26468d00a92824020f6f2090d827078c09c9c587e34cbfd2d0c7911221f8/protobuf-6.33.2-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8cd7640aee0b7828b6d03ae518b5b4806fdfc1afe8de82f79c3454f8aef29872", size = 339168, upload-time = "2025-12-06T00:17:46.813Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:1f8017c48c07ec5859106533b682260ba3d7c5567b1ca1f24297ce03384d1b4f", size = 323270, upload-time = "2025-12-06T00:17:48.253Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/15/4f02896cc3df04fc465010a4c6a0cd89810f54617a32a70ef531ed75d61c/protobuf-6.33.2-py3-none-any.whl", hash = "sha256:7636aad9bb01768870266de5dc009de2d1b936771b38a793f73cbbf279c91c5c", size = 170501, upload-time = "2025-12-06T00:17:52.211Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bc/91/1e3a34881a88697a7354ffd177e8746e97a722e5e8db101544b47e84afb1/protobuf-6.33.2-cp310-abi3-win32.whl", hash = "sha256:87eb388bd2d0f78febd8f4c8779c79247b26a5befad525008e49a6955787ff3d", size = 425603, upload-time = "2025-12-06T00:17:41.114Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/64/20/4d50191997e917ae13ad0a235c8b42d8c1ab9c3e6fd455ca16d416944355/protobuf-6.33.2-cp310-abi3-win_amd64.whl", hash = "sha256:fc2a0e8b05b180e5fc0dd1559fe8ebdae21a27e81ac77728fb6c42b12c7419b4", size = 436930, upload-time = "2025-12-06T00:17:43.278Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/ca/7e485da88ba45c920fb3f50ae78de29ab925d9e54ef0de678306abfbb497/protobuf-6.33.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d9b19771ca75935b3a4422957bc518b0cecb978b31d1dd12037b088f6bcc0e43", size = 427621, upload-time = "2025-12-06T00:17:44.445Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7d/4f/f743761e41d3b2b2566748eb76bbff2b43e14d5fcab694f494a16458b05f/protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:b5d3b5625192214066d99b2b605f5783483575656784de223f00a8d00754fc0e", size = 324460, upload-time = "2025-12-06T00:17:45.678Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/fa/26468d00a92824020f6f2090d827078c09c9c587e34cbfd2d0c7911221f8/protobuf-6.33.2-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8cd7640aee0b7828b6d03ae518b5b4806fdfc1afe8de82f79c3454f8aef29872", size = 339168, upload-time = "2025-12-06T00:17:46.813Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/56/13/333b8f421738f149d4fe5e49553bc2a2ab75235486259f689b4b91f96cec/protobuf-6.33.2-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:1f8017c48c07ec5859106533b682260ba3d7c5567b1ca1f24297ce03384d1b4f", size = 323270, upload-time = "2025-12-06T00:17:48.253Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/15/4f02896cc3df04fc465010a4c6a0cd89810f54617a32a70ef531ed75d61c/protobuf-6.33.2-py3-none-any.whl", hash = "sha256:7636aad9bb01768870266de5dc009de2d1b936771b38a793f73cbbf279c91c5c", size = 170501, upload-time = "2025-12-06T00:17:52.211Z" }, ] [[package]] name = "psutil" version = "7.2.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/73/cb/09e5184fb5fc0358d110fc3ca7f6b1d033800734d34cac10f4136cfac10e/psutil-7.2.1.tar.gz", hash = "sha256:f7583aec590485b43ca601dd9cea0dcd65bd7bb21d30ef4ddbf4ea6b5ed1bdd3", size = 490253, upload-time = "2025-12-29T08:26:00.169Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/77/8e/f0c242053a368c2aa89584ecd1b054a18683f13d6e5a318fc9ec36582c94/psutil-7.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ba9f33bb525b14c3ea563b2fd521a84d2fa214ec59e3e6a2858f78d0844dd60d", size = 129624, upload-time = "2025-12-29T08:26:04.255Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/97/a58a4968f8990617decee234258a2b4fc7cd9e35668387646c1963e69f26/psutil-7.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:81442dac7abfc2f4f4385ea9e12ddf5a796721c0f6133260687fec5c3780fa49", size = 130132, upload-time = "2025-12-29T08:26:06.228Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/db/6d/ed44901e830739af5f72a85fa7ec5ff1edea7f81bfbf4875e409007149bd/psutil-7.2.1-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea46c0d060491051d39f0d2cff4f98d5c72b288289f57a21556cc7d504db37fc", size = 180612, upload-time = "2025-12-29T08:26:08.276Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/65/b628f8459bca4efbfae50d4bf3feaab803de9a160b9d5f3bd9295a33f0c2/psutil-7.2.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35630d5af80d5d0d49cfc4d64c1c13838baf6717a13effb35869a5919b854cdf", size = 183201, upload-time = "2025-12-29T08:26:10.622Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fb/23/851cadc9764edcc18f0effe7d0bf69f727d4cf2442deb4a9f78d4e4f30f2/psutil-7.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:923f8653416604e356073e6e0bccbe7c09990acef442def2f5640dd0faa9689f", size = 139081, upload-time = "2025-12-29T08:26:12.483Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/82/d63e8494ec5758029f31c6cb06d7d161175d8281e91d011a4a441c8a43b5/psutil-7.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cfbe6b40ca48019a51827f20d830887b3107a74a79b01ceb8cc8de4ccb17b672", size = 134767, upload-time = "2025-12-29T08:26:14.528Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c5/cf/5180eb8c8bdf6a503c6919f1da28328bd1e6b3b1b5b9d5b01ae64f019616/psutil-7.2.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b2e953fcfaedcfbc952b44744f22d16575d3aa78eb4f51ae74165b4e96e55f42", size = 128137, upload-time = "2025-12-29T08:26:27.759Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c5/2c/78e4a789306a92ade5000da4f5de3255202c534acdadc3aac7b5458fadef/psutil-7.2.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:05cc68dbb8c174828624062e73078e7e35406f4ca2d0866c272c2410d8ef06d1", size = 128947, upload-time = "2025-12-29T08:26:29.548Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/29/f8/40e01c350ad9a2b3cb4e6adbcc8a83b17ee50dd5792102b6142385937db5/psutil-7.2.1-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e38404ca2bb30ed7267a46c02f06ff842e92da3bb8c5bfdadbd35a5722314d8", size = 154694, upload-time = "2025-12-29T08:26:32.147Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/e4/b751cdf839c011a9714a783f120e6a86b7494eb70044d7d81a25a5cd295f/psutil-7.2.1-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab2b98c9fc19f13f59628d94df5cc4cc4844bc572467d113a8b517d634e362c6", size = 156136, upload-time = "2025-12-29T08:26:34.079Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/44/ad/bbf6595a8134ee1e94a4487af3f132cef7fce43aef4a93b49912a48c3af7/psutil-7.2.1-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f78baafb38436d5a128f837fab2d92c276dfb48af01a240b861ae02b2413ada8", size = 148108, upload-time = "2025-12-29T08:26:36.225Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/15/dd6fd869753ce82ff64dcbc18356093471a5a5adf4f77ed1f805d473d859/psutil-7.2.1-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:99a4cd17a5fdd1f3d014396502daa70b5ec21bf4ffe38393e152f8e449757d67", size = 147402, upload-time = "2025-12-29T08:26:39.21Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/34/68/d9317542e3f2b180c4306e3f45d3c922d7e86d8ce39f941bb9e2e9d8599e/psutil-7.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:b1b0671619343aa71c20ff9767eced0483e4fc9e1f489d50923738caf6a03c17", size = 136938, upload-time = "2025-12-29T08:26:41.036Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3e/73/2ce007f4198c80fcf2cb24c169884f833fe93fbc03d55d302627b094ee91/psutil-7.2.1-cp37-abi3-win_arm64.whl", hash = "sha256:0d67c1822c355aa6f7314d92018fb4268a76668a536f133599b91edd48759442", size = 133836, upload-time = "2025-12-29T08:26:43.086Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/73/cb/09e5184fb5fc0358d110fc3ca7f6b1d033800734d34cac10f4136cfac10e/psutil-7.2.1.tar.gz", hash = "sha256:f7583aec590485b43ca601dd9cea0dcd65bd7bb21d30ef4ddbf4ea6b5ed1bdd3", size = 490253, upload-time = "2025-12-29T08:26:00.169Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/77/8e/f0c242053a368c2aa89584ecd1b054a18683f13d6e5a318fc9ec36582c94/psutil-7.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ba9f33bb525b14c3ea563b2fd521a84d2fa214ec59e3e6a2858f78d0844dd60d", size = 129624, upload-time = "2025-12-29T08:26:04.255Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/97/a58a4968f8990617decee234258a2b4fc7cd9e35668387646c1963e69f26/psutil-7.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:81442dac7abfc2f4f4385ea9e12ddf5a796721c0f6133260687fec5c3780fa49", size = 130132, upload-time = "2025-12-29T08:26:06.228Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/db/6d/ed44901e830739af5f72a85fa7ec5ff1edea7f81bfbf4875e409007149bd/psutil-7.2.1-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea46c0d060491051d39f0d2cff4f98d5c72b288289f57a21556cc7d504db37fc", size = 180612, upload-time = "2025-12-29T08:26:08.276Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/65/b628f8459bca4efbfae50d4bf3feaab803de9a160b9d5f3bd9295a33f0c2/psutil-7.2.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35630d5af80d5d0d49cfc4d64c1c13838baf6717a13effb35869a5919b854cdf", size = 183201, upload-time = "2025-12-29T08:26:10.622Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fb/23/851cadc9764edcc18f0effe7d0bf69f727d4cf2442deb4a9f78d4e4f30f2/psutil-7.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:923f8653416604e356073e6e0bccbe7c09990acef442def2f5640dd0faa9689f", size = 139081, upload-time = "2025-12-29T08:26:12.483Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/82/d63e8494ec5758029f31c6cb06d7d161175d8281e91d011a4a441c8a43b5/psutil-7.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cfbe6b40ca48019a51827f20d830887b3107a74a79b01ceb8cc8de4ccb17b672", size = 134767, upload-time = "2025-12-29T08:26:14.528Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c5/cf/5180eb8c8bdf6a503c6919f1da28328bd1e6b3b1b5b9d5b01ae64f019616/psutil-7.2.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b2e953fcfaedcfbc952b44744f22d16575d3aa78eb4f51ae74165b4e96e55f42", size = 128137, upload-time = "2025-12-29T08:26:27.759Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c5/2c/78e4a789306a92ade5000da4f5de3255202c534acdadc3aac7b5458fadef/psutil-7.2.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:05cc68dbb8c174828624062e73078e7e35406f4ca2d0866c272c2410d8ef06d1", size = 128947, upload-time = "2025-12-29T08:26:29.548Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/29/f8/40e01c350ad9a2b3cb4e6adbcc8a83b17ee50dd5792102b6142385937db5/psutil-7.2.1-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e38404ca2bb30ed7267a46c02f06ff842e92da3bb8c5bfdadbd35a5722314d8", size = 154694, upload-time = "2025-12-29T08:26:32.147Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/e4/b751cdf839c011a9714a783f120e6a86b7494eb70044d7d81a25a5cd295f/psutil-7.2.1-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab2b98c9fc19f13f59628d94df5cc4cc4844bc572467d113a8b517d634e362c6", size = 156136, upload-time = "2025-12-29T08:26:34.079Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/44/ad/bbf6595a8134ee1e94a4487af3f132cef7fce43aef4a93b49912a48c3af7/psutil-7.2.1-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f78baafb38436d5a128f837fab2d92c276dfb48af01a240b861ae02b2413ada8", size = 148108, upload-time = "2025-12-29T08:26:36.225Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/15/dd6fd869753ce82ff64dcbc18356093471a5a5adf4f77ed1f805d473d859/psutil-7.2.1-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:99a4cd17a5fdd1f3d014396502daa70b5ec21bf4ffe38393e152f8e449757d67", size = 147402, upload-time = "2025-12-29T08:26:39.21Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/34/68/d9317542e3f2b180c4306e3f45d3c922d7e86d8ce39f941bb9e2e9d8599e/psutil-7.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:b1b0671619343aa71c20ff9767eced0483e4fc9e1f489d50923738caf6a03c17", size = 136938, upload-time = "2025-12-29T08:26:41.036Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3e/73/2ce007f4198c80fcf2cb24c169884f833fe93fbc03d55d302627b094ee91/psutil-7.2.1-cp37-abi3-win_arm64.whl", hash = "sha256:0d67c1822c355aa6f7314d92018fb4268a76668a536f133599b91edd48759442", size = 133836, upload-time = "2025-12-29T08:26:43.086Z" }, ] [[package]] name = "psycopg" version = "3.3.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e0/1a/7d9ef4fdc13ef7f15b934c393edc97a35c281bb7d3c3329fbfcbe915a7c2/psycopg-3.3.2.tar.gz", hash = "sha256:707a67975ee214d200511177a6a80e56e654754c9afca06a7194ea6bbfde9ca7", size = 165630, upload-time = "2025-12-06T17:34:53.899Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/1a/7d9ef4fdc13ef7f15b934c393edc97a35c281bb7d3c3329fbfcbe915a7c2/psycopg-3.3.2.tar.gz", hash = "sha256:707a67975ee214d200511177a6a80e56e654754c9afca06a7194ea6bbfde9ca7", size = 165630, upload-time = "2025-12-06T17:34:53.899Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8c/51/2779ccdf9305981a06b21a6b27e8547c948d85c41c76ff434192784a4c93/psycopg-3.3.2-py3-none-any.whl", hash = "sha256:3e94bc5f4690247d734599af56e51bae8e0db8e4311ea413f801fef82b14a99b", size = 212774, upload-time = "2025-12-06T17:31:41.414Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8c/51/2779ccdf9305981a06b21a6b27e8547c948d85c41c76ff434192784a4c93/psycopg-3.3.2-py3-none-any.whl", hash = "sha256:3e94bc5f4690247d734599af56e51bae8e0db8e4311ea413f801fef82b14a99b", size = 212774, upload-time = "2025-12-06T17:31:41.414Z" }, ] [package.optional-dependencies] @@ -2984,94 +2975,94 @@ pool = [ [[package]] name = "psycopg-binary" version = "3.3.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4e/1e/8614b01c549dd7e385dacdcd83fe194f6b3acb255a53cc67154ee6bf00e7/psycopg_binary-3.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a9387ab615f929e71ef0f4a8a51e986fa06236ccfa9f3ec98a88f60fbf230634", size = 4579832, upload-time = "2025-12-06T17:33:01.388Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/97/0bb093570fae2f4454d42c1ae6000f15934391867402f680254e4a7def54/psycopg_binary-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3ff7489df5e06c12d1829544eaec64970fe27fe300f7cf04c8495fe682064688", size = 4658786, upload-time = "2025-12-06T17:33:05.022Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/20/1d9383e3f2038826900a14137b0647d755f67551aab316e1021443105ed5/psycopg_binary-3.3.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:9742580ecc8e1ac45164e98d32ca6df90da509c2d3ff26be245d94c430f92db4", size = 5454896, upload-time = "2025-12-06T17:33:09.023Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a6/62/513c80ad8bbb545e364f7737bf2492d34a4c05eef4f7b5c16428dc42260d/psycopg_binary-3.3.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d45acedcaa58619355f18e0f42af542fcad3fd84ace4b8355d3a5dea23318578", size = 5132731, upload-time = "2025-12-06T17:33:12.519Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f3/28/ddf5f5905f088024bccb19857949467407c693389a14feb527d6171d8215/psycopg_binary-3.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d88f32ff8c47cb7f4e7e7a9d1747dcee6f3baa19ed9afa9e5694fd2fb32b61ed", size = 6724495, upload-time = "2025-12-06T17:33:16.624Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/93/a1157ebcc650960b264542b547f7914d87a42ff0cc15a7584b29d5807e6b/psycopg_binary-3.3.2-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:59d0163c4617a2c577cb34afbed93d7a45b8c8364e54b2bd2020ff25d5f5f860", size = 4964979, upload-time = "2025-12-06T17:33:20.179Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/27/65939ba6798f9c5be4a5d9cd2061ebaf0851798525c6811d347821c8132d/psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e750afe74e6c17b2c7046d2c3e3173b5a3f6080084671c8aa327215323df155b", size = 4493648, upload-time = "2025-12-06T17:33:23.464Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8a/c4/5e9e4b9b1c1e27026e43387b0ba4aaf3537c7806465dd3f1d5bde631752a/psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f26f113013c4dcfbfe9ced57b5bad2035dda1a7349f64bf726021968f9bccad3", size = 4173392, upload-time = "2025-12-06T17:33:26.88Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c6/81/cf43fb76993190cee9af1cbcfe28afb47b1928bdf45a252001017e5af26e/psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8309ee4569dced5e81df5aa2dcd48c7340c8dee603a66430f042dfbd2878edca", size = 3909241, upload-time = "2025-12-06T17:33:30.092Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9d/20/c6377a0d17434674351627489deca493ea0b137c522b99c81d3a106372c8/psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c6464150e25b68ae3cb04c4e57496ea11ebfaae4d98126aea2f4702dd43e3c12", size = 4219746, upload-time = "2025-12-06T17:33:33.097Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/32/716c57b28eefe02a57a4c9d5bf956849597f5ea476c7010397199e56cfde/psycopg_binary-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:716a586f99bbe4f710dc58b40069fcb33c7627e95cc6fc936f73c9235e07f9cf", size = 3537494, upload-time = "2025-12-06T17:33:35.82Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/14/73/7ca7cb22b9ac7393fb5de7d28ca97e8347c375c8498b3bff2c99c1f38038/psycopg_binary-3.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fc5a189e89cbfff174588665bb18d28d2d0428366cc9dae5864afcaa2e57380b", size = 4579068, upload-time = "2025-12-06T17:33:39.303Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/42/0cf38ff6c62c792fc5b55398a853a77663210ebd51ed6f0c4a05b06f95a6/psycopg_binary-3.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:083c2e182be433f290dc2c516fd72b9b47054fcd305cce791e0a50d9e93e06f2", size = 4657520, upload-time = "2025-12-06T17:33:42.536Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3b/60/df846bc84cbf2231e01b0fff48b09841fe486fa177665e50f4995b1bfa44/psycopg_binary-3.3.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:ac230e3643d1c436a2dfb59ca84357dfc6862c9f372fc5dbd96bafecae581f9f", size = 5452086, upload-time = "2025-12-06T17:33:46.54Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ab/85/30c846a00db86b1b53fd5bfd4b4edfbd0c00de8f2c75dd105610bd7568fc/psycopg_binary-3.3.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d8c899a540f6c7585cee53cddc929dd4d2db90fd828e37f5d4017b63acbc1a5d", size = 5131125, upload-time = "2025-12-06T17:33:50.413Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6d/15/9968732013373f36f8a2a3fb76104dffc8efd9db78709caa5ae1a87b1f80/psycopg_binary-3.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50ff10ab8c0abdb5a5451b9315538865b50ba64c907742a1385fdf5f5772b73e", size = 6722914, upload-time = "2025-12-06T17:33:54.544Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b2/ba/29e361fe02143ac5ff5a1ca3e45697344cfbebe2eaf8c4e7eec164bff9a0/psycopg_binary-3.3.2-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:23d2594af848c1fd3d874a9364bef50730124e72df7bb145a20cb45e728c50ed", size = 4966081, upload-time = "2025-12-06T17:33:58.477Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/99/45/1be90c8f1a1a237046903e91202fb06708745c179f220b361d6333ed7641/psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ea4fe6b4ead3bbbe27244ea224fcd1f53cb119afc38b71a2f3ce570149a03e30", size = 4493332, upload-time = "2025-12-06T17:34:02.011Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2e/b5/bbdc07d5f0a5e90c617abd624368182aa131485e18038b2c6c85fc054aed/psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:742ce48cde825b8e52fb1a658253d6d1ff66d152081cbc76aa45e2986534858d", size = 4170781, upload-time = "2025-12-06T17:34:05.298Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/2a/0d45e4f4da2bd78c3237ffa03475ef3751f69a81919c54a6e610eb1a7c96/psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e22bf6b54df994aff37ab52695d635f1ef73155e781eee1f5fa75bc08b58c8da", size = 3910544, upload-time = "2025-12-06T17:34:08.251Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3a/62/a8e0f092f4dbef9a94b032fb71e214cf0a375010692fbe7493a766339e47/psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8db9034cde3bcdafc66980f0130813f5c5d19e74b3f2a19fb3cfbc25ad113121", size = 4220070, upload-time = "2025-12-06T17:34:11.392Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/09/e6/5fc8d8aff8afa114bb4a94a0341b9309311e8bf3ab32d816032f8b984d4e/psycopg_binary-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:df65174c7cf6b05ea273ce955927d3270b3a6e27b0b12762b009ce6082b8d3fc", size = 3540922, upload-time = "2025-12-06T17:34:14.88Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4e/1e/8614b01c549dd7e385dacdcd83fe194f6b3acb255a53cc67154ee6bf00e7/psycopg_binary-3.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a9387ab615f929e71ef0f4a8a51e986fa06236ccfa9f3ec98a88f60fbf230634", size = 4579832, upload-time = "2025-12-06T17:33:01.388Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/97/0bb093570fae2f4454d42c1ae6000f15934391867402f680254e4a7def54/psycopg_binary-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3ff7489df5e06c12d1829544eaec64970fe27fe300f7cf04c8495fe682064688", size = 4658786, upload-time = "2025-12-06T17:33:05.022Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/20/1d9383e3f2038826900a14137b0647d755f67551aab316e1021443105ed5/psycopg_binary-3.3.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:9742580ecc8e1ac45164e98d32ca6df90da509c2d3ff26be245d94c430f92db4", size = 5454896, upload-time = "2025-12-06T17:33:09.023Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a6/62/513c80ad8bbb545e364f7737bf2492d34a4c05eef4f7b5c16428dc42260d/psycopg_binary-3.3.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d45acedcaa58619355f18e0f42af542fcad3fd84ace4b8355d3a5dea23318578", size = 5132731, upload-time = "2025-12-06T17:33:12.519Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/28/ddf5f5905f088024bccb19857949467407c693389a14feb527d6171d8215/psycopg_binary-3.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d88f32ff8c47cb7f4e7e7a9d1747dcee6f3baa19ed9afa9e5694fd2fb32b61ed", size = 6724495, upload-time = "2025-12-06T17:33:16.624Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/93/a1157ebcc650960b264542b547f7914d87a42ff0cc15a7584b29d5807e6b/psycopg_binary-3.3.2-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:59d0163c4617a2c577cb34afbed93d7a45b8c8364e54b2bd2020ff25d5f5f860", size = 4964979, upload-time = "2025-12-06T17:33:20.179Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/27/65939ba6798f9c5be4a5d9cd2061ebaf0851798525c6811d347821c8132d/psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e750afe74e6c17b2c7046d2c3e3173b5a3f6080084671c8aa327215323df155b", size = 4493648, upload-time = "2025-12-06T17:33:23.464Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/c4/5e9e4b9b1c1e27026e43387b0ba4aaf3537c7806465dd3f1d5bde631752a/psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f26f113013c4dcfbfe9ced57b5bad2035dda1a7349f64bf726021968f9bccad3", size = 4173392, upload-time = "2025-12-06T17:33:26.88Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c6/81/cf43fb76993190cee9af1cbcfe28afb47b1928bdf45a252001017e5af26e/psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8309ee4569dced5e81df5aa2dcd48c7340c8dee603a66430f042dfbd2878edca", size = 3909241, upload-time = "2025-12-06T17:33:30.092Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/20/c6377a0d17434674351627489deca493ea0b137c522b99c81d3a106372c8/psycopg_binary-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c6464150e25b68ae3cb04c4e57496ea11ebfaae4d98126aea2f4702dd43e3c12", size = 4219746, upload-time = "2025-12-06T17:33:33.097Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/32/716c57b28eefe02a57a4c9d5bf956849597f5ea476c7010397199e56cfde/psycopg_binary-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:716a586f99bbe4f710dc58b40069fcb33c7627e95cc6fc936f73c9235e07f9cf", size = 3537494, upload-time = "2025-12-06T17:33:35.82Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/73/7ca7cb22b9ac7393fb5de7d28ca97e8347c375c8498b3bff2c99c1f38038/psycopg_binary-3.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fc5a189e89cbfff174588665bb18d28d2d0428366cc9dae5864afcaa2e57380b", size = 4579068, upload-time = "2025-12-06T17:33:39.303Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/42/0cf38ff6c62c792fc5b55398a853a77663210ebd51ed6f0c4a05b06f95a6/psycopg_binary-3.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:083c2e182be433f290dc2c516fd72b9b47054fcd305cce791e0a50d9e93e06f2", size = 4657520, upload-time = "2025-12-06T17:33:42.536Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3b/60/df846bc84cbf2231e01b0fff48b09841fe486fa177665e50f4995b1bfa44/psycopg_binary-3.3.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:ac230e3643d1c436a2dfb59ca84357dfc6862c9f372fc5dbd96bafecae581f9f", size = 5452086, upload-time = "2025-12-06T17:33:46.54Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ab/85/30c846a00db86b1b53fd5bfd4b4edfbd0c00de8f2c75dd105610bd7568fc/psycopg_binary-3.3.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d8c899a540f6c7585cee53cddc929dd4d2db90fd828e37f5d4017b63acbc1a5d", size = 5131125, upload-time = "2025-12-06T17:33:50.413Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6d/15/9968732013373f36f8a2a3fb76104dffc8efd9db78709caa5ae1a87b1f80/psycopg_binary-3.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50ff10ab8c0abdb5a5451b9315538865b50ba64c907742a1385fdf5f5772b73e", size = 6722914, upload-time = "2025-12-06T17:33:54.544Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/ba/29e361fe02143ac5ff5a1ca3e45697344cfbebe2eaf8c4e7eec164bff9a0/psycopg_binary-3.3.2-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:23d2594af848c1fd3d874a9364bef50730124e72df7bb145a20cb45e728c50ed", size = 4966081, upload-time = "2025-12-06T17:33:58.477Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/45/1be90c8f1a1a237046903e91202fb06708745c179f220b361d6333ed7641/psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ea4fe6b4ead3bbbe27244ea224fcd1f53cb119afc38b71a2f3ce570149a03e30", size = 4493332, upload-time = "2025-12-06T17:34:02.011Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2e/b5/bbdc07d5f0a5e90c617abd624368182aa131485e18038b2c6c85fc054aed/psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:742ce48cde825b8e52fb1a658253d6d1ff66d152081cbc76aa45e2986534858d", size = 4170781, upload-time = "2025-12-06T17:34:05.298Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/2a/0d45e4f4da2bd78c3237ffa03475ef3751f69a81919c54a6e610eb1a7c96/psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e22bf6b54df994aff37ab52695d635f1ef73155e781eee1f5fa75bc08b58c8da", size = 3910544, upload-time = "2025-12-06T17:34:08.251Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/62/a8e0f092f4dbef9a94b032fb71e214cf0a375010692fbe7493a766339e47/psycopg_binary-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8db9034cde3bcdafc66980f0130813f5c5d19e74b3f2a19fb3cfbc25ad113121", size = 4220070, upload-time = "2025-12-06T17:34:11.392Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/09/e6/5fc8d8aff8afa114bb4a94a0341b9309311e8bf3ab32d816032f8b984d4e/psycopg_binary-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:df65174c7cf6b05ea273ce955927d3270b3a6e27b0b12762b009ce6082b8d3fc", size = 3540922, upload-time = "2025-12-06T17:34:14.88Z" }, ] [[package]] name = "psycopg-pool" version = "3.3.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/56/9a/9470d013d0d50af0da9c4251614aeb3c1823635cab3edc211e3839db0bcf/psycopg_pool-3.3.0.tar.gz", hash = "sha256:fa115eb2860bd88fce1717d75611f41490dec6135efb619611142b24da3f6db5", size = 31606, upload-time = "2025-12-01T11:34:33.11Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/56/9a/9470d013d0d50af0da9c4251614aeb3c1823635cab3edc211e3839db0bcf/psycopg_pool-3.3.0.tar.gz", hash = "sha256:fa115eb2860bd88fce1717d75611f41490dec6135efb619611142b24da3f6db5", size = 31606, upload-time = "2025-12-01T11:34:33.11Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/c3/26b8a0908a9db249de3b4169692e1c7c19048a9bc41a4d3209cee7dbb758/psycopg_pool-3.3.0-py3-none-any.whl", hash = "sha256:2e44329155c410b5e8666372db44276a8b1ebd8c90f1c3026ebba40d4bc81063", size = 39995, upload-time = "2025-12-01T11:34:29.761Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/c3/26b8a0908a9db249de3b4169692e1c7c19048a9bc41a4d3209cee7dbb758/psycopg_pool-3.3.0-py3-none-any.whl", hash = "sha256:2e44329155c410b5e8666372db44276a8b1ebd8c90f1c3026ebba40d4bc81063", size = 39995, upload-time = "2025-12-01T11:34:29.761Z" }, ] [[package]] name = "psycopg2-binary" version = "2.9.11" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ac/6c/8767aaa597ba424643dc87348c6f1754dd9f48e80fdc1b9f7ca5c3a7c213/psycopg2-binary-2.9.11.tar.gz", hash = "sha256:b6aed9e096bf63f9e75edf2581aa9a7e7186d97ab5c177aa6c87797cd591236c", size = 379620, upload-time = "2025-10-10T11:14:48.041Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/91/f870a02f51be4a65987b45a7de4c2e1897dd0d01051e2b559a38fa634e3e/psycopg2_binary-2.9.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:be9b840ac0525a283a96b556616f5b4820e0526addb8dcf6525a0fa162730be4", size = 3756603, upload-time = "2025-10-10T11:11:52.213Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/27/fa/cae40e06849b6c9a95eb5c04d419942f00d9eaac8d81626107461e268821/psycopg2_binary-2.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f090b7ddd13ca842ebfe301cd587a76a4cf0913b1e429eb92c1be5dbeb1a19bc", size = 3864509, upload-time = "2025-10-10T11:11:56.452Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2d/75/364847b879eb630b3ac8293798e380e441a957c53657995053c5ec39a316/psycopg2_binary-2.9.11-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ab8905b5dcb05bf3fb22e0cf90e10f469563486ffb6a96569e51f897c750a76a", size = 4411159, upload-time = "2025-10-10T11:12:00.49Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6f/a0/567f7ea38b6e1c62aafd58375665a547c00c608a471620c0edc364733e13/psycopg2_binary-2.9.11-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf940cd7e7fec19181fdbc29d76911741153d51cab52e5c21165f3262125685e", size = 4468234, upload-time = "2025-10-10T11:12:04.892Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/30/da/4e42788fb811bbbfd7b7f045570c062f49e350e1d1f3df056c3fb5763353/psycopg2_binary-2.9.11-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fa0f693d3c68ae925966f0b14b8edda71696608039f4ed61b1fe9ffa468d16db", size = 4166236, upload-time = "2025-10-10T11:12:11.674Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3c/94/c1777c355bc560992af848d98216148be5f1be001af06e06fc49cbded578/psycopg2_binary-2.9.11-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a1cf393f1cdaf6a9b57c0a719a1068ba1069f022a59b8b1fe44b006745b59757", size = 3983083, upload-time = "2025-10-30T02:55:15.73Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bd/42/c9a21edf0e3daa7825ed04a4a8588686c6c14904344344a039556d78aa58/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ef7a6beb4beaa62f88592ccc65df20328029d721db309cb3250b0aae0fa146c3", size = 3652281, upload-time = "2025-10-10T11:12:17.713Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/12/22/dedfbcfa97917982301496b6b5e5e6c5531d1f35dd2b488b08d1ebc52482/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:31b32c457a6025e74d233957cc9736742ac5a6cb196c6b68499f6bb51390bd6a", size = 3298010, upload-time = "2025-10-10T11:12:22.671Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/66/ea/d3390e6696276078bd01b2ece417deac954dfdd552d2edc3d03204416c0c/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:edcb3aeb11cb4bf13a2af3c53a15b3d612edeb6409047ea0b5d6a21a9d744b34", size = 3044641, upload-time = "2025-10-30T02:55:19.929Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/12/9a/0402ded6cbd321da0c0ba7d34dc12b29b14f5764c2fc10750daa38e825fc/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b6d93d7c0b61a1dd6197d208ab613eb7dcfdcca0a49c42ceb082257991de9d", size = 3347940, upload-time = "2025-10-10T11:12:26.529Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b1/d2/99b55e85832ccde77b211738ff3925a5d73ad183c0b37bcbbe5a8ff04978/psycopg2_binary-2.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:b33fabeb1fde21180479b2d4667e994de7bbf0eec22832ba5d9b5e4cf65b6c6d", size = 2714147, upload-time = "2025-10-10T11:12:29.535Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/a8/a2709681b3ac11b0b1786def10006b8995125ba268c9a54bea6f5ae8bd3e/psycopg2_binary-2.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b8fb3db325435d34235b044b199e56cdf9ff41223a4b9752e8576465170bb38c", size = 3756572, upload-time = "2025-10-10T11:12:32.873Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/62/e1/c2b38d256d0dafd32713e9f31982a5b028f4a3651f446be70785f484f472/psycopg2_binary-2.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:366df99e710a2acd90efed3764bb1e28df6c675d33a7fb40df9b7281694432ee", size = 3864529, upload-time = "2025-10-10T11:12:36.791Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/11/32/b2ffe8f3853c181e88f0a157c5fb4e383102238d73c52ac6d93a5c8bffe6/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8c55b385daa2f92cb64b12ec4536c66954ac53654c7f15a203578da4e78105c0", size = 4411242, upload-time = "2025-10-10T11:12:42.388Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/10/04/6ca7477e6160ae258dc96f67c371157776564679aefd247b66f4661501a2/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c0377174bf1dd416993d16edc15357f6eb17ac998244cca19bc67cdc0e2e5766", size = 4468258, upload-time = "2025-10-10T11:12:48.654Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3c/7e/6a1a38f86412df101435809f225d57c1a021307dd0689f7a5e7fe83588b1/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5c6ff3335ce08c75afaed19e08699e8aacf95d4a260b495a4a8545244fe2ceb3", size = 4166295, upload-time = "2025-10-10T11:12:52.525Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f2/7d/c07374c501b45f3579a9eb761cbf2604ddef3d96ad48679112c2c5aa9c25/psycopg2_binary-2.9.11-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84011ba3109e06ac412f95399b704d3d6950e386b7994475b231cf61eec2fc1f", size = 3983133, upload-time = "2025-10-30T02:55:24.329Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/82/56/993b7104cb8345ad7d4516538ccf8f0d0ac640b1ebd8c754a7b024e76878/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba34475ceb08cccbdd98f6b46916917ae6eeb92b5ae111df10b544c3a4621dc4", size = 3652383, upload-time = "2025-10-10T11:12:56.387Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2d/ac/eaeb6029362fd8d454a27374d84c6866c82c33bfc24587b4face5a8e43ef/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b31e90fdd0f968c2de3b26ab014314fe814225b6c324f770952f7d38abf17e3c", size = 3298168, upload-time = "2025-10-10T11:13:00.403Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2b/39/50c3facc66bded9ada5cbc0de867499a703dc6bca6be03070b4e3b65da6c/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:d526864e0f67f74937a8fce859bd56c979f5e2ec57ca7c627f5f1071ef7fee60", size = 3044712, upload-time = "2025-10-30T02:55:27.975Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9c/8e/b7de019a1f562f72ada81081a12823d3c1590bedc48d7d2559410a2763fe/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04195548662fa544626c8ea0f06561eb6203f1984ba5b4562764fbeb4c3d14b1", size = 3347549, upload-time = "2025-10-10T11:13:03.971Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/80/2d/1bb683f64737bbb1f86c82b7359db1eb2be4e2c0c13b947f80efefa7d3e5/psycopg2_binary-2.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:efff12b432179443f54e230fdf60de1f6cc726b6c832db8701227d089310e8aa", size = 2714215, upload-time = "2025-10-10T11:13:07.14Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/6c/8767aaa597ba424643dc87348c6f1754dd9f48e80fdc1b9f7ca5c3a7c213/psycopg2-binary-2.9.11.tar.gz", hash = "sha256:b6aed9e096bf63f9e75edf2581aa9a7e7186d97ab5c177aa6c87797cd591236c", size = 379620, upload-time = "2025-10-10T11:14:48.041Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/91/f870a02f51be4a65987b45a7de4c2e1897dd0d01051e2b559a38fa634e3e/psycopg2_binary-2.9.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:be9b840ac0525a283a96b556616f5b4820e0526addb8dcf6525a0fa162730be4", size = 3756603, upload-time = "2025-10-10T11:11:52.213Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/27/fa/cae40e06849b6c9a95eb5c04d419942f00d9eaac8d81626107461e268821/psycopg2_binary-2.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f090b7ddd13ca842ebfe301cd587a76a4cf0913b1e429eb92c1be5dbeb1a19bc", size = 3864509, upload-time = "2025-10-10T11:11:56.452Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/75/364847b879eb630b3ac8293798e380e441a957c53657995053c5ec39a316/psycopg2_binary-2.9.11-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ab8905b5dcb05bf3fb22e0cf90e10f469563486ffb6a96569e51f897c750a76a", size = 4411159, upload-time = "2025-10-10T11:12:00.49Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6f/a0/567f7ea38b6e1c62aafd58375665a547c00c608a471620c0edc364733e13/psycopg2_binary-2.9.11-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf940cd7e7fec19181fdbc29d76911741153d51cab52e5c21165f3262125685e", size = 4468234, upload-time = "2025-10-10T11:12:04.892Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/30/da/4e42788fb811bbbfd7b7f045570c062f49e350e1d1f3df056c3fb5763353/psycopg2_binary-2.9.11-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fa0f693d3c68ae925966f0b14b8edda71696608039f4ed61b1fe9ffa468d16db", size = 4166236, upload-time = "2025-10-10T11:12:11.674Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3c/94/c1777c355bc560992af848d98216148be5f1be001af06e06fc49cbded578/psycopg2_binary-2.9.11-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a1cf393f1cdaf6a9b57c0a719a1068ba1069f022a59b8b1fe44b006745b59757", size = 3983083, upload-time = "2025-10-30T02:55:15.73Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bd/42/c9a21edf0e3daa7825ed04a4a8588686c6c14904344344a039556d78aa58/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ef7a6beb4beaa62f88592ccc65df20328029d721db309cb3250b0aae0fa146c3", size = 3652281, upload-time = "2025-10-10T11:12:17.713Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/12/22/dedfbcfa97917982301496b6b5e5e6c5531d1f35dd2b488b08d1ebc52482/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:31b32c457a6025e74d233957cc9736742ac5a6cb196c6b68499f6bb51390bd6a", size = 3298010, upload-time = "2025-10-10T11:12:22.671Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/ea/d3390e6696276078bd01b2ece417deac954dfdd552d2edc3d03204416c0c/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:edcb3aeb11cb4bf13a2af3c53a15b3d612edeb6409047ea0b5d6a21a9d744b34", size = 3044641, upload-time = "2025-10-30T02:55:19.929Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/12/9a/0402ded6cbd321da0c0ba7d34dc12b29b14f5764c2fc10750daa38e825fc/psycopg2_binary-2.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b6d93d7c0b61a1dd6197d208ab613eb7dcfdcca0a49c42ceb082257991de9d", size = 3347940, upload-time = "2025-10-10T11:12:26.529Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/d2/99b55e85832ccde77b211738ff3925a5d73ad183c0b37bcbbe5a8ff04978/psycopg2_binary-2.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:b33fabeb1fde21180479b2d4667e994de7bbf0eec22832ba5d9b5e4cf65b6c6d", size = 2714147, upload-time = "2025-10-10T11:12:29.535Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/a8/a2709681b3ac11b0b1786def10006b8995125ba268c9a54bea6f5ae8bd3e/psycopg2_binary-2.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b8fb3db325435d34235b044b199e56cdf9ff41223a4b9752e8576465170bb38c", size = 3756572, upload-time = "2025-10-10T11:12:32.873Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/e1/c2b38d256d0dafd32713e9f31982a5b028f4a3651f446be70785f484f472/psycopg2_binary-2.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:366df99e710a2acd90efed3764bb1e28df6c675d33a7fb40df9b7281694432ee", size = 3864529, upload-time = "2025-10-10T11:12:36.791Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/11/32/b2ffe8f3853c181e88f0a157c5fb4e383102238d73c52ac6d93a5c8bffe6/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8c55b385daa2f92cb64b12ec4536c66954ac53654c7f15a203578da4e78105c0", size = 4411242, upload-time = "2025-10-10T11:12:42.388Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/04/6ca7477e6160ae258dc96f67c371157776564679aefd247b66f4661501a2/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c0377174bf1dd416993d16edc15357f6eb17ac998244cca19bc67cdc0e2e5766", size = 4468258, upload-time = "2025-10-10T11:12:48.654Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3c/7e/6a1a38f86412df101435809f225d57c1a021307dd0689f7a5e7fe83588b1/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5c6ff3335ce08c75afaed19e08699e8aacf95d4a260b495a4a8545244fe2ceb3", size = 4166295, upload-time = "2025-10-10T11:12:52.525Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f2/7d/c07374c501b45f3579a9eb761cbf2604ddef3d96ad48679112c2c5aa9c25/psycopg2_binary-2.9.11-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84011ba3109e06ac412f95399b704d3d6950e386b7994475b231cf61eec2fc1f", size = 3983133, upload-time = "2025-10-30T02:55:24.329Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/82/56/993b7104cb8345ad7d4516538ccf8f0d0ac640b1ebd8c754a7b024e76878/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba34475ceb08cccbdd98f6b46916917ae6eeb92b5ae111df10b544c3a4621dc4", size = 3652383, upload-time = "2025-10-10T11:12:56.387Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/ac/eaeb6029362fd8d454a27374d84c6866c82c33bfc24587b4face5a8e43ef/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b31e90fdd0f968c2de3b26ab014314fe814225b6c324f770952f7d38abf17e3c", size = 3298168, upload-time = "2025-10-10T11:13:00.403Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/39/50c3facc66bded9ada5cbc0de867499a703dc6bca6be03070b4e3b65da6c/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:d526864e0f67f74937a8fce859bd56c979f5e2ec57ca7c627f5f1071ef7fee60", size = 3044712, upload-time = "2025-10-30T02:55:27.975Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9c/8e/b7de019a1f562f72ada81081a12823d3c1590bedc48d7d2559410a2763fe/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04195548662fa544626c8ea0f06561eb6203f1984ba5b4562764fbeb4c3d14b1", size = 3347549, upload-time = "2025-10-10T11:13:03.971Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/80/2d/1bb683f64737bbb1f86c82b7359db1eb2be4e2c0c13b947f80efefa7d3e5/psycopg2_binary-2.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:efff12b432179443f54e230fdf60de1f6cc726b6c832db8701227d089310e8aa", size = 2714215, upload-time = "2025-10-10T11:13:07.14Z" }, ] [[package]] name = "publicsuffix2" version = "2.20191221" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/04/1759906c4c5b67b2903f546de234a824d4028ef24eb0b1122daa43376c20/publicsuffix2-2.20191221.tar.gz", hash = "sha256:00f8cc31aa8d0d5592a5ced19cccba7de428ebca985db26ac852d920ddd6fe7b", size = 99592, upload-time = "2019-12-21T11:30:44.863Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/04/1759906c4c5b67b2903f546de234a824d4028ef24eb0b1122daa43376c20/publicsuffix2-2.20191221.tar.gz", hash = "sha256:00f8cc31aa8d0d5592a5ced19cccba7de428ebca985db26ac852d920ddd6fe7b", size = 99592, upload-time = "2019-12-21T11:30:44.863Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9d/16/053c2945c5e3aebeefb4ccd5c5e7639e38bc30ad1bdc7ce86c6d01707726/publicsuffix2-2.20191221-py2.py3-none-any.whl", hash = "sha256:786b5e36205b88758bd3518725ec8cfe7a8173f5269354641f581c6b80a99893", size = 89033, upload-time = "2019-12-21T11:30:41.744Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9d/16/053c2945c5e3aebeefb4ccd5c5e7639e38bc30ad1bdc7ce86c6d01707726/publicsuffix2-2.20191221-py2.py3-none-any.whl", hash = "sha256:786b5e36205b88758bd3518725ec8cfe7a8173f5269354641f581c6b80a99893", size = 89033, upload-time = "2019-12-21T11:30:41.744Z" }, ] [[package]] name = "py-key-value-aio" version = "0.3.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "beartype" }, { name = "py-key-value-shared" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/93/ce/3136b771dddf5ac905cc193b461eb67967cf3979688c6696e1f2cdcde7ea/py_key_value_aio-0.3.0.tar.gz", hash = "sha256:858e852fcf6d696d231266da66042d3355a7f9871650415feef9fca7a6cd4155", size = 50801, upload-time = "2025-11-17T16:50:04.711Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/93/ce/3136b771dddf5ac905cc193b461eb67967cf3979688c6696e1f2cdcde7ea/py_key_value_aio-0.3.0.tar.gz", hash = "sha256:858e852fcf6d696d231266da66042d3355a7f9871650415feef9fca7a6cd4155", size = 50801, upload-time = "2025-11-17T16:50:04.711Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/99/10/72f6f213b8f0bce36eff21fda0a13271834e9eeff7f9609b01afdc253c79/py_key_value_aio-0.3.0-py3-none-any.whl", hash = "sha256:1c781915766078bfd608daa769fefb97e65d1d73746a3dfb640460e322071b64", size = 96342, upload-time = "2025-11-17T16:50:03.801Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/10/72f6f213b8f0bce36eff21fda0a13271834e9eeff7f9609b01afdc253c79/py_key_value_aio-0.3.0-py3-none-any.whl", hash = "sha256:1c781915766078bfd608daa769fefb97e65d1d73746a3dfb640460e322071b64", size = 96342, upload-time = "2025-11-17T16:50:03.801Z" }, ] [package.optional-dependencies] @@ -3092,89 +3083,89 @@ redis = [ [[package]] name = "py-key-value-shared" version = "0.3.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "beartype" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7b/e4/1971dfc4620a3a15b4579fe99e024f5edd6e0967a71154771a059daff4db/py_key_value_shared-0.3.0.tar.gz", hash = "sha256:8fdd786cf96c3e900102945f92aa1473138ebe960ef49da1c833790160c28a4b", size = 11666, upload-time = "2025-11-17T16:50:06.849Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7b/e4/1971dfc4620a3a15b4579fe99e024f5edd6e0967a71154771a059daff4db/py_key_value_shared-0.3.0.tar.gz", hash = "sha256:8fdd786cf96c3e900102945f92aa1473138ebe960ef49da1c833790160c28a4b", size = 11666, upload-time = "2025-11-17T16:50:06.849Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/51/e4/b8b0a03ece72f47dce2307d36e1c34725b7223d209fc679315ffe6a4e2c3/py_key_value_shared-0.3.0-py3-none-any.whl", hash = "sha256:5b0efba7ebca08bb158b1e93afc2f07d30b8f40c2fc12ce24a4c0d84f42f9298", size = 19560, upload-time = "2025-11-17T16:50:05.954Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/51/e4/b8b0a03ece72f47dce2307d36e1c34725b7223d209fc679315ffe6a4e2c3/py_key_value_shared-0.3.0-py3-none-any.whl", hash = "sha256:5b0efba7ebca08bb158b1e93afc2f07d30b8f40c2fc12ce24a4c0d84f42f9298", size = 19560, upload-time = "2025-11-17T16:50:05.954Z" }, ] [[package]] name = "pyasn1" version = "0.6.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" }, ] [[package]] name = "pyasn1-modules" version = "0.4.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pyasn1" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, ] [[package]] name = "pycparser" version = "2.23" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, ] [[package]] name = "pycryptodome" version = "3.23.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276, upload-time = "2025-05-17T17:21:45.242Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152, upload-time = "2025-05-17T17:20:20.833Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348, upload-time = "2025-05-17T17:20:23.171Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033, upload-time = "2025-05-17T17:20:25.424Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142, upload-time = "2025-05-17T17:20:27.808Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384, upload-time = "2025-05-17T17:20:30.765Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237, upload-time = "2025-05-17T17:20:33.736Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898, upload-time = "2025-05-17T17:20:36.086Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197, upload-time = "2025-05-17T17:20:38.414Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600, upload-time = "2025-05-17T17:20:40.688Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740, upload-time = "2025-05-17T17:20:42.413Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685, upload-time = "2025-05-17T17:20:44.388Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627, upload-time = "2025-05-17T17:20:47.139Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362, upload-time = "2025-05-17T17:20:50.392Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625, upload-time = "2025-05-17T17:20:52.866Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954, upload-time = "2025-05-17T17:20:55.027Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534, upload-time = "2025-05-17T17:20:57.279Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853, upload-time = "2025-05-17T17:20:59.322Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465, upload-time = "2025-05-17T17:21:03.83Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414, upload-time = "2025-05-17T17:21:06.72Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484, upload-time = "2025-05-17T17:21:08.535Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636, upload-time = "2025-05-17T17:21:10.393Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675, upload-time = "2025-05-17T17:21:13.146Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276, upload-time = "2025-05-17T17:21:45.242Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152, upload-time = "2025-05-17T17:20:20.833Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348, upload-time = "2025-05-17T17:20:23.171Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033, upload-time = "2025-05-17T17:20:25.424Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142, upload-time = "2025-05-17T17:20:27.808Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384, upload-time = "2025-05-17T17:20:30.765Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237, upload-time = "2025-05-17T17:20:33.736Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898, upload-time = "2025-05-17T17:20:36.086Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197, upload-time = "2025-05-17T17:20:38.414Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600, upload-time = "2025-05-17T17:20:40.688Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740, upload-time = "2025-05-17T17:20:42.413Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685, upload-time = "2025-05-17T17:20:44.388Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627, upload-time = "2025-05-17T17:20:47.139Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362, upload-time = "2025-05-17T17:20:50.392Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625, upload-time = "2025-05-17T17:20:52.866Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954, upload-time = "2025-05-17T17:20:55.027Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534, upload-time = "2025-05-17T17:20:57.279Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853, upload-time = "2025-05-17T17:20:59.322Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465, upload-time = "2025-05-17T17:21:03.83Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414, upload-time = "2025-05-17T17:21:06.72Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484, upload-time = "2025-05-17T17:21:08.535Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636, upload-time = "2025-05-17T17:21:10.393Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675, upload-time = "2025-05-17T17:21:13.146Z" }, ] [[package]] name = "pydantic" version = "2.12.5" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "annotated-types" }, { name = "pydantic-core" }, { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, ] [package.optional-dependencies] @@ -3185,14 +3176,14 @@ email = [ [[package]] name = "pydantic-ai-backend" version = "0.1.14" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pydantic" }, { name = "wcmatch" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/cc/901bb48e16c676773b0c0c3cf554b5eb841086355d17bea786295ed3c795/pydantic_ai_backend-0.1.14.tar.gz", hash = "sha256:c1213f36c8ca8f2db78f299de177ac0f3cdcb09230d1ba2857e656e334ed1bfd", size = 13766281, upload-time = "2026-03-12T01:42:37.918Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/cc/901bb48e16c676773b0c0c3cf554b5eb841086355d17bea786295ed3c795/pydantic_ai_backend-0.1.14.tar.gz", hash = "sha256:c1213f36c8ca8f2db78f299de177ac0f3cdcb09230d1ba2857e656e334ed1bfd", size = 13766281, upload-time = "2026-03-12T01:42:37.918Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/c6/3af09264faaeea83b98ef4e1aaf199d5ace4edabe1dae1e3430b692ef194/pydantic_ai_backend-0.1.14-py3-none-any.whl", hash = "sha256:8bcc9e05c41c10fbb446ea704de2505548d8bf2c9fc491209305626db2d8bdc2", size = 54991, upload-time = "2026-03-12T01:42:36.459Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/c6/3af09264faaeea83b98ef4e1aaf199d5ace4edabe1dae1e3430b692ef194/pydantic_ai_backend-0.1.14-py3-none-any.whl", hash = "sha256:8bcc9e05c41c10fbb446ea704de2505548d8bf2c9fc491209305626db2d8bdc2", size = 54991, upload-time = "2026-03-12T01:42:36.459Z" }, ] [package.optional-dependencies] @@ -3205,104 +3196,104 @@ docker = [ [[package]] name = "pydantic-core" version = "2.41.5" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, ] [[package]] name = "pydantic-extra-types" version = "2.11.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pydantic" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/35/2fee58b1316a73e025728583d3b1447218a97e621933fc776fb8c0f2ebdd/pydantic_extra_types-2.11.0.tar.gz", hash = "sha256:4e9991959d045b75feb775683437a97991d02c138e00b59176571db9ce634f0e", size = 157226, upload-time = "2025-12-31T16:18:27.944Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/35/2fee58b1316a73e025728583d3b1447218a97e621933fc776fb8c0f2ebdd/pydantic_extra_types-2.11.0.tar.gz", hash = "sha256:4e9991959d045b75feb775683437a97991d02c138e00b59176571db9ce634f0e", size = 157226, upload-time = "2025-12-31T16:18:27.944Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fe/17/fabd56da47096d240dd45ba627bead0333b0cf0ee8ada9bec579287dadf3/pydantic_extra_types-2.11.0-py3-none-any.whl", hash = "sha256:84b864d250a0fc62535b7ec591e36f2c5b4d1325fa0017eb8cda9aeb63b374a6", size = 74296, upload-time = "2025-12-31T16:18:26.38Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fe/17/fabd56da47096d240dd45ba627bead0333b0cf0ee8ada9bec579287dadf3/pydantic_extra_types-2.11.0-py3-none-any.whl", hash = "sha256:84b864d250a0fc62535b7ec591e36f2c5b4d1325fa0017eb8cda9aeb63b374a6", size = 74296, upload-time = "2025-12-31T16:18:26.38Z" }, ] [[package]] name = "pydantic-settings" version = "2.12.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/4b/ac7e0aae12027748076d72a8764ff1c9d82ca75a7a52622e67ed3f765c54/pydantic_settings-2.12.0.tar.gz", hash = "sha256:005538ef951e3c2a68e1c08b292b5f2e71490def8589d4221b95dab00dafcfd0", size = 194184, upload-time = "2025-11-10T14:25:47.013Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/4b/ac7e0aae12027748076d72a8764ff1c9d82ca75a7a52622e67ed3f765c54/pydantic_settings-2.12.0.tar.gz", hash = "sha256:005538ef951e3c2a68e1c08b292b5f2e71490def8589d4221b95dab00dafcfd0", size = 194184, upload-time = "2025-11-10T14:25:47.013Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl", hash = "sha256:fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809", size = 51880, upload-time = "2025-11-10T14:25:45.546Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/60/5d4751ba3f4a40a6891f24eec885f51afd78d208498268c734e256fb13c4/pydantic_settings-2.12.0-py3-none-any.whl", hash = "sha256:fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809", size = 51880, upload-time = "2025-11-10T14:25:45.546Z" }, ] [[package]] name = "pydemumble" version = "0.0.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c6/a9/1a78b7b6ed256c7bfec610e20658a3c8ed726a4c1a4652f2a17059c3563c/pydemumble-0.0.1.tar.gz", hash = "sha256:715f34fa999add1ef9337d1aae32d3b4b2a2a8dea0ddf363fcb1dac10593ca43", size = 1298294, upload-time = "2025-02-15T05:19:10.803Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c6/a9/1a78b7b6ed256c7bfec610e20658a3c8ed726a4c1a4652f2a17059c3563c/pydemumble-0.0.1.tar.gz", hash = "sha256:715f34fa999add1ef9337d1aae32d3b4b2a2a8dea0ddf363fcb1dac10593ca43", size = 1298294, upload-time = "2025-02-15T05:19:10.803Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/62/d479f63a145e50fb42dfa1090d0f5a58b3af94d02990e84c09c7b8cc2e7c/pydemumble-0.0.1-cp312-abi3-macosx_10_14_x86_64.whl", hash = "sha256:2dc4848ad97afb897877ee537820b38f427e30fe0a3b8dac25fe5c7b44d60cf0", size = 150273, upload-time = "2025-02-15T05:18:52.897Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fa/3e/4acec3739eef2b05779d250cbb9420feb61d8a3a1945651826620c03be12/pydemumble-0.0.1-cp312-abi3-macosx_11_0_arm64.whl", hash = "sha256:f5c770fde6b5929b5b386fe99960e6c237d62860c0eea0267f179034716c3ca0", size = 143501, upload-time = "2025-02-15T05:18:53.946Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/97/23/2ca50587a14cff273f3c4bb42dd42c87efd921ed09974bd7c43fcd8e02bc/pydemumble-0.0.1-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94d7348778ed7a483cec06554b6367decb9c16da1a1b251e56faa21f2f34b4cc", size = 175584, upload-time = "2025-02-15T05:18:54.952Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/88/504c1bcd70bf970e387eaf789fd89637d01b333ba2c1b0975977fc7f0d64/pydemumble-0.0.1-cp312-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18c83eeab994eab54640d347564799dd651857d06b1cdaf60fb81d2215c55a20", size = 190161, upload-time = "2025-02-15T05:18:56.077Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/df/5c/c9f981ea7b10817ec3b71a9d1790deb2c90031ec800e974cf432701efe49/pydemumble-0.0.1-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ff7fe892dd90e9a73e8a8e8225247820613b2ac9e6b6d5cf916f3a1d51cc1d", size = 181234, upload-time = "2025-02-15T05:18:57.211Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/ee/e249299975181286cfdbffcd070856e950451d1859aeb564a5ca28ac18a5/pydemumble-0.0.1-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:488c2ee1c743d0989bdc67c802c941900db77cc8150fb100f38eca2e3a462d5b", size = 588544, upload-time = "2025-02-15T05:18:58.351Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/81/bb/06c2a4861a3f7945d2918f6142bf688eaf4fa6424ddd46e792f00399fee6/pydemumble-0.0.1-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:20a3e1e672ab210139640658f4ef3b4e7abe48f4562fc14947b538b95ab3e1c2", size = 653900, upload-time = "2025-02-15T05:18:59.443Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e2/23/7edfc6c6f4fba5fa3f371cdc3ecd774ab98bc4efb8a688a89b802a553f13/pydemumble-0.0.1-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:76f8bd943d8eec3b65beb09e97fd3a5994a519700243e5ecaf6a6a3ebe3e3809", size = 607638, upload-time = "2025-02-15T05:19:00.684Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/28/a2/b4f22086fb6d479cd01410cd0a57c39748736315a7a6a753f2d6ab9e6b22/pydemumble-0.0.1-cp312-abi3-win32.whl", hash = "sha256:63b965b89401ededcf8fc879196586a6427f4d4ba2be32953170b1965f34b51b", size = 143771, upload-time = "2025-02-15T05:19:01.838Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6f/7c/d7dc551b63c79795cad5a3c35b0799437e0d34de8d93a3ffb3539bbc8930/pydemumble-0.0.1-cp312-abi3-win_amd64.whl", hash = "sha256:6dd17d309a9b7bd2eaf697e9b07d35d5c88ce30026d12cf6e58d8a9900a737c4", size = 171611, upload-time = "2025-02-15T05:19:02.881Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/62/d479f63a145e50fb42dfa1090d0f5a58b3af94d02990e84c09c7b8cc2e7c/pydemumble-0.0.1-cp312-abi3-macosx_10_14_x86_64.whl", hash = "sha256:2dc4848ad97afb897877ee537820b38f427e30fe0a3b8dac25fe5c7b44d60cf0", size = 150273, upload-time = "2025-02-15T05:18:52.897Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fa/3e/4acec3739eef2b05779d250cbb9420feb61d8a3a1945651826620c03be12/pydemumble-0.0.1-cp312-abi3-macosx_11_0_arm64.whl", hash = "sha256:f5c770fde6b5929b5b386fe99960e6c237d62860c0eea0267f179034716c3ca0", size = 143501, upload-time = "2025-02-15T05:18:53.946Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/23/2ca50587a14cff273f3c4bb42dd42c87efd921ed09974bd7c43fcd8e02bc/pydemumble-0.0.1-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94d7348778ed7a483cec06554b6367decb9c16da1a1b251e56faa21f2f34b4cc", size = 175584, upload-time = "2025-02-15T05:18:54.952Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/88/504c1bcd70bf970e387eaf789fd89637d01b333ba2c1b0975977fc7f0d64/pydemumble-0.0.1-cp312-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18c83eeab994eab54640d347564799dd651857d06b1cdaf60fb81d2215c55a20", size = 190161, upload-time = "2025-02-15T05:18:56.077Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/5c/c9f981ea7b10817ec3b71a9d1790deb2c90031ec800e974cf432701efe49/pydemumble-0.0.1-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ff7fe892dd90e9a73e8a8e8225247820613b2ac9e6b6d5cf916f3a1d51cc1d", size = 181234, upload-time = "2025-02-15T05:18:57.211Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/ee/e249299975181286cfdbffcd070856e950451d1859aeb564a5ca28ac18a5/pydemumble-0.0.1-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:488c2ee1c743d0989bdc67c802c941900db77cc8150fb100f38eca2e3a462d5b", size = 588544, upload-time = "2025-02-15T05:18:58.351Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/81/bb/06c2a4861a3f7945d2918f6142bf688eaf4fa6424ddd46e792f00399fee6/pydemumble-0.0.1-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:20a3e1e672ab210139640658f4ef3b4e7abe48f4562fc14947b538b95ab3e1c2", size = 653900, upload-time = "2025-02-15T05:18:59.443Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e2/23/7edfc6c6f4fba5fa3f371cdc3ecd774ab98bc4efb8a688a89b802a553f13/pydemumble-0.0.1-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:76f8bd943d8eec3b65beb09e97fd3a5994a519700243e5ecaf6a6a3ebe3e3809", size = 607638, upload-time = "2025-02-15T05:19:00.684Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/28/a2/b4f22086fb6d479cd01410cd0a57c39748736315a7a6a753f2d6ab9e6b22/pydemumble-0.0.1-cp312-abi3-win32.whl", hash = "sha256:63b965b89401ededcf8fc879196586a6427f4d4ba2be32953170b1965f34b51b", size = 143771, upload-time = "2025-02-15T05:19:01.838Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6f/7c/d7dc551b63c79795cad5a3c35b0799437e0d34de8d93a3ffb3539bbc8930/pydemumble-0.0.1-cp312-abi3-win_amd64.whl", hash = "sha256:6dd17d309a9b7bd2eaf697e9b07d35d5c88ce30026d12cf6e58d8a9900a737c4", size = 171611, upload-time = "2025-02-15T05:19:02.881Z" }, ] [[package]] name = "pydivert" version = "2.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cf/71/2da9bcf742df3ab23f75f10fedca074951dd13a84bda8dea3077f68ae9a6/pydivert-2.1.0.tar.gz", hash = "sha256:f0e150f4ff591b78e35f514e319561dadff7f24a82186a171dd4d465483de5b4", size = 91057, upload-time = "2017-10-20T21:36:58.165Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cf/71/2da9bcf742df3ab23f75f10fedca074951dd13a84bda8dea3077f68ae9a6/pydivert-2.1.0.tar.gz", hash = "sha256:f0e150f4ff591b78e35f514e319561dadff7f24a82186a171dd4d465483de5b4", size = 91057, upload-time = "2017-10-20T21:36:58.165Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ca/8f/86d7931c62013a5a7ebf4e1642a87d4a6050c0f570e714f61b0df1984c62/pydivert-2.1.0-py2.py3-none-any.whl", hash = "sha256:382db488e3c37c03ec9ec94e061a0b24334d78dbaeebb7d4e4d32ce4355d9da1", size = 104718, upload-time = "2017-10-20T21:36:56.726Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/8f/86d7931c62013a5a7ebf4e1642a87d4a6050c0f570e714f61b0df1984c62/pydivert-2.1.0-py2.py3-none-any.whl", hash = "sha256:382db488e3c37c03ec9ec94e061a0b24334d78dbaeebb7d4e4d32ce4355d9da1", size = 104718, upload-time = "2017-10-20T21:36:56.726Z" }, ] [[package]] name = "pydocket" version = "0.16.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cloudpickle" }, { name = "fakeredis", extra = ["lua"] }, @@ -3317,62 +3308,62 @@ dependencies = [ { name = "typer" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e0/c5/61dcfce4d50b66a3f09743294d37fab598b81bb0975054b7f732da9243ec/pydocket-0.16.3.tar.gz", hash = "sha256:78e9da576de09e9f3f410d2471ef1c679b7741ddd21b586c97a13872b69bd265", size = 297080, upload-time = "2025-12-23T23:37:33.32Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/c5/61dcfce4d50b66a3f09743294d37fab598b81bb0975054b7f732da9243ec/pydocket-0.16.3.tar.gz", hash = "sha256:78e9da576de09e9f3f410d2471ef1c679b7741ddd21b586c97a13872b69bd265", size = 297080, upload-time = "2025-12-23T23:37:33.32Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/94/93b7f5981aa04f922e0d9ce7326a4587866ec7e39f7c180ffcf408e66ee8/pydocket-0.16.3-py3-none-any.whl", hash = "sha256:e2b50925356e7cd535286255195458ac7bba15f25293356651b36d223db5dd7c", size = 67087, upload-time = "2025-12-23T23:37:31.829Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/94/93b7f5981aa04f922e0d9ce7326a4587866ec7e39f7c180ffcf408e66ee8/pydocket-0.16.3-py3-none-any.whl", hash = "sha256:e2b50925356e7cd535286255195458ac7bba15f25293356651b36d223db5dd7c", size = 67087, upload-time = "2025-12-23T23:37:31.829Z" }, ] [[package]] name = "pydot" version = "4.0.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pyparsing" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/35/b17cb89ff865484c6a20ef46bf9d95a5f07328292578de0b295f4a6beec2/pydot-4.0.1.tar.gz", hash = "sha256:c2148f681c4a33e08bf0e26a9e5f8e4099a82e0e2a068098f32ce86577364ad5", size = 162594, upload-time = "2025-06-17T20:09:56.454Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/35/b17cb89ff865484c6a20ef46bf9d95a5f07328292578de0b295f4a6beec2/pydot-4.0.1.tar.gz", hash = "sha256:c2148f681c4a33e08bf0e26a9e5f8e4099a82e0e2a068098f32ce86577364ad5", size = 162594, upload-time = "2025-06-17T20:09:56.454Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7e/32/a7125fb28c4261a627f999d5fb4afff25b523800faed2c30979949d6facd/pydot-4.0.1-py3-none-any.whl", hash = "sha256:869c0efadd2708c0be1f916eb669f3d664ca684bc57ffb7ecc08e70d5e93fee6", size = 37087, upload-time = "2025-06-17T20:09:55.25Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/32/a7125fb28c4261a627f999d5fb4afff25b523800faed2c30979949d6facd/pydot-4.0.1-py3-none-any.whl", hash = "sha256:869c0efadd2708c0be1f916eb669f3d664ca684bc57ffb7ecc08e70d5e93fee6", size = 37087, upload-time = "2025-06-17T20:09:55.25Z" }, ] [[package]] name = "pyelftools" version = "0.32" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b9/ab/33968940b2deb3d92f5b146bc6d4009a5f95d1d06c148ea2f9ee965071af/pyelftools-0.32.tar.gz", hash = "sha256:6de90ee7b8263e740c8715a925382d4099b354f29ac48ea40d840cf7aa14ace5", size = 15047199, upload-time = "2025-02-19T14:20:05.549Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/ab/33968940b2deb3d92f5b146bc6d4009a5f95d1d06c148ea2f9ee965071af/pyelftools-0.32.tar.gz", hash = "sha256:6de90ee7b8263e740c8715a925382d4099b354f29ac48ea40d840cf7aa14ace5", size = 15047199, upload-time = "2025-02-19T14:20:05.549Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/af/43/700932c4f0638c3421177144a2e86448c0d75dbaee2c7936bda3f9fd0878/pyelftools-0.32-py3-none-any.whl", hash = "sha256:013df952a006db5e138b1edf6d8a68ecc50630adbd0d83a2d41e7f846163d738", size = 188525, upload-time = "2025-02-19T14:19:59.919Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/af/43/700932c4f0638c3421177144a2e86448c0d75dbaee2c7936bda3f9fd0878/pyelftools-0.32-py3-none-any.whl", hash = "sha256:013df952a006db5e138b1edf6d8a68ecc50630adbd0d83a2d41e7f846163d738", size = 188525, upload-time = "2025-02-19T14:19:59.919Z" }, ] [[package]] name = "pyformlang" version = "1.0.11" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "networkx" }, { name = "numpy" }, { name = "pydot" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/70/41/772000760174a909294ad496854b81a882e68458dda22f53b47e1e777f0d/pyformlang-1.0.11.tar.gz", hash = "sha256:e292ec8b9cfa64c26b592faf9b7cfc72c4f4b0eb0d533f045a46061e75c5ce99", size = 97188, upload-time = "2025-03-18T09:59:30.581Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/70/41/772000760174a909294ad496854b81a882e68458dda22f53b47e1e777f0d/pyformlang-1.0.11.tar.gz", hash = "sha256:e292ec8b9cfa64c26b592faf9b7cfc72c4f4b0eb0d533f045a46061e75c5ce99", size = 97188, upload-time = "2025-03-18T09:59:30.581Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/fe/e26ea3b233672c7a89642b0615e2c44905578a4889eb00b06a358d8ab8c5/pyformlang-1.0.11-py3-none-any.whl", hash = "sha256:a8d76481e4d76e4df1c00cd5c5fce61969635900ef521ad182a07a61ca1c070e", size = 128508, upload-time = "2025-03-18T09:59:28.897Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/fe/e26ea3b233672c7a89642b0615e2c44905578a4889eb00b06a358d8ab8c5/pyformlang-1.0.11-py3-none-any.whl", hash = "sha256:a8d76481e4d76e4df1c00cd5c5fce61969635900ef521ad182a07a61ca1c070e", size = 128508, upload-time = "2025-03-18T09:59:28.897Z" }, ] [[package]] name = "pygments" version = "2.19.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/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://pypi.tuna.tsinghua.edu.cn/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 = "pyjwt" version = "2.10.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785, upload-time = "2024-11-28T03:43:29.933Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785, upload-time = "2024-11-28T03:43:29.933Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" }, ] [package.optional-dependencies] @@ -3383,90 +3374,90 @@ crypto = [ [[package]] name = "pylsqpack" version = "0.3.23" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/f3/2681d5d38cd789a62352e105619d353d3c245f463a376c1b9a735e3c47b3/pylsqpack-0.3.23.tar.gz", hash = "sha256:f55b126940d8b3157331f123d4428d703a698a6db65a6a7891f7ec1b90c86c56", size = 676891, upload-time = "2025-10-10T17:12:58.747Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/f3/2681d5d38cd789a62352e105619d353d3c245f463a376c1b9a735e3c47b3/pylsqpack-0.3.23.tar.gz", hash = "sha256:f55b126940d8b3157331f123d4428d703a698a6db65a6a7891f7ec1b90c86c56", size = 676891, upload-time = "2025-10-10T17:12:58.747Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ef/5d/44c5f05d4f72ac427210326a283f74541ad694d517a1c136631fdbcd8e4b/pylsqpack-0.3.23-cp310-abi3-macosx_10_9_x86_64.whl", hash = "sha256:978497811bb58cf7ae11c0e1d4cf9bdf6bccef77556d039ae1836b458cb235fc", size = 162519, upload-time = "2025-10-10T17:12:44.892Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/38/9a/3472903fd88dfa87ac683e7113e0ac9df47b70924db9410b275c6e16b25f/pylsqpack-0.3.23-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:8a9e25c5a98a0959c6511aaf7d1a6ac0d6146be349a8c3c09fec2e5250cb2901", size = 167819, upload-time = "2025-10-10T17:12:46.54Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/cf/43e7b04f6397be691a255589fbed25fb4b8d7b707ad8c118408553ff2a5b/pylsqpack-0.3.23-cp310-abi3-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3f7d78352e764732ac1a9ab109aa84e003996a7d64de7098cb20bdc007cf7613", size = 246484, upload-time = "2025-10-10T17:12:47.588Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ed/38/e44ba48404b61b4dd1e9902bef7e01afac5c31e57c5dceec2f0f4e522fcb/pylsqpack-0.3.23-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ba86c384dcf8952cef190f8cc4d61cb2a8e4eeaf25093c6aa38b9b696ac82dc", size = 248586, upload-time = "2025-10-10T17:12:48.621Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1f/46/1f0eb601215bc7596e3003dde6a4c9ad457a4ab35405cdcc56c0727cdf49/pylsqpack-0.3.23-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:829a2466b80af9766cf0ad795b866796a4000cec441a0eb222357efd01ec6d42", size = 249520, upload-time = "2025-10-10T17:12:49.639Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b9/20/a91d4f90480baaa14aa940512bdfae3774b2524bbf71d3f16391b244b31e/pylsqpack-0.3.23-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b516d56078a16592596ea450ea20e9a54650af759754e2e807b7046be13c83ee", size = 246141, upload-time = "2025-10-10T17:12:51.165Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/28/bb/02c018e0fc174122d5bd0cfcbe858d40a4516d9245fca4a7a2dd5201deea/pylsqpack-0.3.23-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:db03232c85855cb03226447e41539f8631d7d4e5483d48206e30d470a9cb07a1", size = 246064, upload-time = "2025-10-10T17:12:52.243Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/ca/082d31c1180ab856118634a3a26c7739cf38aee656702c1b39dc1acc26a0/pylsqpack-0.3.23-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2d91d87672beb0beff6a866dbf35e8b45791d8dffcd5cfd9d8cc397001101fd5", size = 247847, upload-time = "2025-10-10T17:12:53.364Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/33/58e7ced97a04bfb1807143fc70dc7ff3b8abef4e39c5144235f0985e43cc/pylsqpack-0.3.23-cp310-abi3-win32.whl", hash = "sha256:4e5b0b5ec92be6e5e6eb1c52d45271c5c7f8f2a2cd8c672ab240ac2cd893cd26", size = 153227, upload-time = "2025-10-10T17:12:54.459Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/da/691477b89927643ea30f36511825e9551d7f36c887ce9bb9903fac31390d/pylsqpack-0.3.23-cp310-abi3-win_amd64.whl", hash = "sha256:498b374b16b51532997998c4cf4021161d2a611f5ea6b02ad95ca99815c54abf", size = 155779, upload-time = "2025-10-10T17:12:55.406Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e0/17/a8bc10443fd4261911dbb41331d39ce2ad28ba82a170eddecf23904b321c/pylsqpack-0.3.23-cp310-abi3-win_arm64.whl", hash = "sha256:2f9a2ef59588d32cd02847c6b9d7140440f67a0751da99f96a2ff4edadc85eae", size = 153188, upload-time = "2025-10-10T17:12:56.782Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ef/5d/44c5f05d4f72ac427210326a283f74541ad694d517a1c136631fdbcd8e4b/pylsqpack-0.3.23-cp310-abi3-macosx_10_9_x86_64.whl", hash = "sha256:978497811bb58cf7ae11c0e1d4cf9bdf6bccef77556d039ae1836b458cb235fc", size = 162519, upload-time = "2025-10-10T17:12:44.892Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/9a/3472903fd88dfa87ac683e7113e0ac9df47b70924db9410b275c6e16b25f/pylsqpack-0.3.23-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:8a9e25c5a98a0959c6511aaf7d1a6ac0d6146be349a8c3c09fec2e5250cb2901", size = 167819, upload-time = "2025-10-10T17:12:46.54Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/cf/43e7b04f6397be691a255589fbed25fb4b8d7b707ad8c118408553ff2a5b/pylsqpack-0.3.23-cp310-abi3-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3f7d78352e764732ac1a9ab109aa84e003996a7d64de7098cb20bdc007cf7613", size = 246484, upload-time = "2025-10-10T17:12:47.588Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/38/e44ba48404b61b4dd1e9902bef7e01afac5c31e57c5dceec2f0f4e522fcb/pylsqpack-0.3.23-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ba86c384dcf8952cef190f8cc4d61cb2a8e4eeaf25093c6aa38b9b696ac82dc", size = 248586, upload-time = "2025-10-10T17:12:48.621Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1f/46/1f0eb601215bc7596e3003dde6a4c9ad457a4ab35405cdcc56c0727cdf49/pylsqpack-0.3.23-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:829a2466b80af9766cf0ad795b866796a4000cec441a0eb222357efd01ec6d42", size = 249520, upload-time = "2025-10-10T17:12:49.639Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/20/a91d4f90480baaa14aa940512bdfae3774b2524bbf71d3f16391b244b31e/pylsqpack-0.3.23-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b516d56078a16592596ea450ea20e9a54650af759754e2e807b7046be13c83ee", size = 246141, upload-time = "2025-10-10T17:12:51.165Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/28/bb/02c018e0fc174122d5bd0cfcbe858d40a4516d9245fca4a7a2dd5201deea/pylsqpack-0.3.23-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:db03232c85855cb03226447e41539f8631d7d4e5483d48206e30d470a9cb07a1", size = 246064, upload-time = "2025-10-10T17:12:52.243Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/ca/082d31c1180ab856118634a3a26c7739cf38aee656702c1b39dc1acc26a0/pylsqpack-0.3.23-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2d91d87672beb0beff6a866dbf35e8b45791d8dffcd5cfd9d8cc397001101fd5", size = 247847, upload-time = "2025-10-10T17:12:53.364Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/33/58e7ced97a04bfb1807143fc70dc7ff3b8abef4e39c5144235f0985e43cc/pylsqpack-0.3.23-cp310-abi3-win32.whl", hash = "sha256:4e5b0b5ec92be6e5e6eb1c52d45271c5c7f8f2a2cd8c672ab240ac2cd893cd26", size = 153227, upload-time = "2025-10-10T17:12:54.459Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/da/691477b89927643ea30f36511825e9551d7f36c887ce9bb9903fac31390d/pylsqpack-0.3.23-cp310-abi3-win_amd64.whl", hash = "sha256:498b374b16b51532997998c4cf4021161d2a611f5ea6b02ad95ca99815c54abf", size = 155779, upload-time = "2025-10-10T17:12:55.406Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/17/a8bc10443fd4261911dbb41331d39ce2ad28ba82a170eddecf23904b321c/pylsqpack-0.3.23-cp310-abi3-win_arm64.whl", hash = "sha256:2f9a2ef59588d32cd02847c6b9d7140440f67a0751da99f96a2ff4edadc85eae", size = 153188, upload-time = "2025-10-10T17:12:56.782Z" }, ] [[package]] name = "pyopenssl" version = "25.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cryptography" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/26/e25b4a374b4639e0c235527bbe31c0524f26eda701d79456a7e1877f4cc5/pyopenssl-25.0.0.tar.gz", hash = "sha256:cd2cef799efa3936bb08e8ccb9433a575722b9dd986023f1cabc4ae64e9dac16", size = 179573, upload-time = "2025-01-12T17:22:48.897Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/26/e25b4a374b4639e0c235527bbe31c0524f26eda701d79456a7e1877f4cc5/pyopenssl-25.0.0.tar.gz", hash = "sha256:cd2cef799efa3936bb08e8ccb9433a575722b9dd986023f1cabc4ae64e9dac16", size = 179573, upload-time = "2025-01-12T17:22:48.897Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ca/d7/eb76863d2060dcbe7c7e6cccfd95ac02ea0b9acc37745a0d99ff6457aefb/pyOpenSSL-25.0.0-py3-none-any.whl", hash = "sha256:424c247065e46e76a37411b9ab1782541c23bb658bf003772c3405fbaa128e90", size = 56453, upload-time = "2025-01-12T17:22:43.44Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/d7/eb76863d2060dcbe7c7e6cccfd95ac02ea0b9acc37745a0d99ff6457aefb/pyOpenSSL-25.0.0-py3-none-any.whl", hash = "sha256:424c247065e46e76a37411b9ab1782541c23bb658bf003772c3405fbaa128e90", size = 56453, upload-time = "2025-01-12T17:22:43.44Z" }, ] [[package]] name = "pyparsing" version = "3.2.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8b/1a/3544f4f299a47911c2ab3710f534e52fea62a633c96806995da5d25be4b2/pyparsing-3.2.1.tar.gz", hash = "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a", size = 1067694, upload-time = "2024-12-31T20:59:46.157Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8b/1a/3544f4f299a47911c2ab3710f534e52fea62a633c96806995da5d25be4b2/pyparsing-3.2.1.tar.gz", hash = "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a", size = 1067694, upload-time = "2024-12-31T20:59:46.157Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/a7/c8a2d361bf89c0d9577c934ebb7421b25dc84bf3a8e3ac0a40aed9acc547/pyparsing-3.2.1-py3-none-any.whl", hash = "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1", size = 107716, upload-time = "2024-12-31T20:59:42.738Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/a7/c8a2d361bf89c0d9577c934ebb7421b25dc84bf3a8e3ac0a40aed9acc547/pyparsing-3.2.1-py3-none-any.whl", hash = "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1", size = 107716, upload-time = "2024-12-31T20:59:42.738Z" }, ] [[package]] name = "pypcode" version = "3.3.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/4c/7a57f97f569c24607a0490d9bf5e69ad2a29915ece5cb7f0891d4d6847d5/pypcode-3.3.3.tar.gz", hash = "sha256:378b8d3b1552c3251243b421114dd67ccb49660fe762c60fb19dede1279cf30c", size = 2159423, upload-time = "2025-10-13T21:34:36.64Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/4c/7a57f97f569c24607a0490d9bf5e69ad2a29915ece5cb7f0891d4d6847d5/pypcode-3.3.3.tar.gz", hash = "sha256:378b8d3b1552c3251243b421114dd67ccb49660fe762c60fb19dede1279cf30c", size = 2159423, upload-time = "2025-10-13T21:34:36.64Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/39/92/3272987c85f92f6cd6b77b4b2b663c14bb0006aee04e8d55329d9dafdc09/pypcode-3.3.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:31be0e2524701546106f98a16faad85f85b89fcd98289ff41d9129f4280fe29d", size = 13805188, upload-time = "2025-10-13T21:33:56.879Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/cb/3c3b182808ad1667cdd9d2dd2994f2c662b8cfa68d206bb5218684377414/pypcode-3.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a60bbe863456f42a97b5b33d10ccb97ae2f725542d1fd871b9293000619532af", size = 13756473, upload-time = "2025-10-13T21:33:59.122Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/f6/235a8aeabed2bc8e74f4dd5d052c0548f7e2aabad47ad8916873e717c358/pypcode-3.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5241cd815a89229d6ccc26b3d525e38eb1b17df7f60c35f085428351ad199f8d", size = 13844193, upload-time = "2025-10-13T21:34:01.14Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0c/16/2fd2e676d0de49c9c8afcdcde747019e96cc9a9c50810a93cee69ae1c79a/pypcode-3.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2af24d1741aff3e57821c58c90ffafe2d66d540284f126b5e46cec4826060f0", size = 13878012, upload-time = "2025-10-13T21:34:03.221Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/d9/b5deaab861c384f3b0702aab2c1a952921cf9ab4cbf7be5dab806bb476cd/pypcode-3.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:1346b59345c361f2fe782db8bef7c7478c57261ff760567096507285f7ff22d0", size = 13628994, upload-time = "2025-10-13T21:34:05.571Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5e/45/4c5416a4703b3b56f43cb71a0fdf8216620cd486110f9b1c94a6b419c63a/pypcode-3.3.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:e7ce476461ce9224a3dd77ad05810322c1f161155e2c773207368a6ff4103708", size = 13805118, upload-time = "2025-10-13T21:34:07.69Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/fb/1b6c995783c26b9fb70ad8feb05dcb82aa3f55252c85bb2499d5b3cf25a7/pypcode-3.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:245e36beb6487c9f4aed1fe20b6c40454d93f52d2f9e56ece79c66c569a50020", size = 13756412, upload-time = "2025-10-13T21:34:11.592Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/00/04/69a0557253fc9dcefdb88cb28e254c436dc66e5be0867e8cbf755daa6558/pypcode-3.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d977dcb6519fefe6c198b49a1c3b51ef1aac25c6829c51103104b13bd846f7d7", size = 13844125, upload-time = "2025-10-13T21:34:14.053Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/16/c4f618d51529418a7ceb8fd6f8b4a323cc9889afa5211d2b7177d4560e60/pypcode-3.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cdfd0c89c24c13fe0f04f570adc3369c39a3c3c5696b86178f74f436a3f7500", size = 13877979, upload-time = "2025-10-13T21:34:16.178Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d0/68/3e3b7f076a4c7bf0b114a0393e7ad8d90ddfb4882f790d2009481e4be4e0/pypcode-3.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:ddcb34b31a904241dcafc22c674511b11455f56a05c11ab1ee3a5973ff0cfd77", size = 13628920, upload-time = "2025-10-13T21:34:18.562Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/92/3272987c85f92f6cd6b77b4b2b663c14bb0006aee04e8d55329d9dafdc09/pypcode-3.3.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:31be0e2524701546106f98a16faad85f85b89fcd98289ff41d9129f4280fe29d", size = 13805188, upload-time = "2025-10-13T21:33:56.879Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/cb/3c3b182808ad1667cdd9d2dd2994f2c662b8cfa68d206bb5218684377414/pypcode-3.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a60bbe863456f42a97b5b33d10ccb97ae2f725542d1fd871b9293000619532af", size = 13756473, upload-time = "2025-10-13T21:33:59.122Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/f6/235a8aeabed2bc8e74f4dd5d052c0548f7e2aabad47ad8916873e717c358/pypcode-3.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5241cd815a89229d6ccc26b3d525e38eb1b17df7f60c35f085428351ad199f8d", size = 13844193, upload-time = "2025-10-13T21:34:01.14Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0c/16/2fd2e676d0de49c9c8afcdcde747019e96cc9a9c50810a93cee69ae1c79a/pypcode-3.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2af24d1741aff3e57821c58c90ffafe2d66d540284f126b5e46cec4826060f0", size = 13878012, upload-time = "2025-10-13T21:34:03.221Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/d9/b5deaab861c384f3b0702aab2c1a952921cf9ab4cbf7be5dab806bb476cd/pypcode-3.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:1346b59345c361f2fe782db8bef7c7478c57261ff760567096507285f7ff22d0", size = 13628994, upload-time = "2025-10-13T21:34:05.571Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5e/45/4c5416a4703b3b56f43cb71a0fdf8216620cd486110f9b1c94a6b419c63a/pypcode-3.3.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:e7ce476461ce9224a3dd77ad05810322c1f161155e2c773207368a6ff4103708", size = 13805118, upload-time = "2025-10-13T21:34:07.69Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/fb/1b6c995783c26b9fb70ad8feb05dcb82aa3f55252c85bb2499d5b3cf25a7/pypcode-3.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:245e36beb6487c9f4aed1fe20b6c40454d93f52d2f9e56ece79c66c569a50020", size = 13756412, upload-time = "2025-10-13T21:34:11.592Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/00/04/69a0557253fc9dcefdb88cb28e254c436dc66e5be0867e8cbf755daa6558/pypcode-3.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d977dcb6519fefe6c198b49a1c3b51ef1aac25c6829c51103104b13bd846f7d7", size = 13844125, upload-time = "2025-10-13T21:34:14.053Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/16/c4f618d51529418a7ceb8fd6f8b4a323cc9889afa5211d2b7177d4560e60/pypcode-3.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cdfd0c89c24c13fe0f04f570adc3369c39a3c3c5696b86178f74f436a3f7500", size = 13877979, upload-time = "2025-10-13T21:34:16.178Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d0/68/3e3b7f076a4c7bf0b114a0393e7ad8d90ddfb4882f790d2009481e4be4e0/pypcode-3.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:ddcb34b31a904241dcafc22c674511b11455f56a05c11ab1ee3a5973ff0cfd77", size = 13628920, upload-time = "2025-10-13T21:34:18.562Z" }, ] [[package]] name = "pypdf" version = "6.6.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/f4/801632a8b62a805378b6af2b5a3fcbfd8923abf647e0ed1af846a83433b2/pypdf-6.6.0.tar.gz", hash = "sha256:4c887ef2ea38d86faded61141995a3c7d068c9d6ae8477be7ae5de8a8e16592f", size = 5281063, upload-time = "2026-01-09T11:20:11.786Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/f4/801632a8b62a805378b6af2b5a3fcbfd8923abf647e0ed1af846a83433b2/pypdf-6.6.0.tar.gz", hash = "sha256:4c887ef2ea38d86faded61141995a3c7d068c9d6ae8477be7ae5de8a8e16592f", size = 5281063, upload-time = "2026-01-09T11:20:11.786Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b2/ba/96f99276194f720e74ed99905a080f6e77810558874e8935e580331b46de/pypdf-6.6.0-py3-none-any.whl", hash = "sha256:bca9091ef6de36c7b1a81e09327c554b7ce51e88dad68f5890c2b4a4417f1fd7", size = 328963, upload-time = "2026-01-09T11:20:09.278Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/ba/96f99276194f720e74ed99905a080f6e77810558874e8935e580331b46de/pypdf-6.6.0-py3-none-any.whl", hash = "sha256:bca9091ef6de36c7b1a81e09327c554b7ce51e88dad68f5890c2b4a4417f1fd7", size = 328963, upload-time = "2026-01-09T11:20:09.278Z" }, ] [[package]] name = "pyperclip" version = "1.9.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/30/23/2f0a3efc4d6a32f3b63cdff36cd398d9701d26cda58e3ab97ac79fb5e60d/pyperclip-1.9.0.tar.gz", hash = "sha256:b7de0142ddc81bfc5c7507eea19da920b92252b548b96186caf94a5e2527d310", size = 20961, upload-time = "2024-06-18T20:38:48.401Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/30/23/2f0a3efc4d6a32f3b63cdff36cd398d9701d26cda58e3ab97ac79fb5e60d/pyperclip-1.9.0.tar.gz", hash = "sha256:b7de0142ddc81bfc5c7507eea19da920b92252b548b96186caf94a5e2527d310", size = 20961, upload-time = "2024-06-18T20:38:48.401Z" } [[package]] name = "pysocks" version = "1.7.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bd/11/293dd436aea955d45fc4e8a35b6ae7270f5b8e00b53cf6c024c83b657a11/PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0", size = 284429, upload-time = "2019-09-20T02:07:35.714Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bd/11/293dd436aea955d45fc4e8a35b6ae7270f5b8e00b53cf6c024c83b657a11/PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0", size = 284429, upload-time = "2019-09-20T02:07:35.714Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", size = 16725, upload-time = "2019-09-20T02:06:22.938Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", size = 16725, upload-time = "2019-09-20T02:06:22.938Z" }, ] [[package]] name = "pytest" version = "9.0.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "iniconfig" }, @@ -3474,71 +3465,71 @@ dependencies = [ { name = "pluggy" }, { name = "pygments" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, ] [[package]] name = "pytest-asyncio" version = "1.3.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pytest" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" }, ] [[package]] name = "pytest-cov" version = "7.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "coverage" }, { name = "pluggy" }, { name = "pytest" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, ] [[package]] name = "python-dotenv" version = "1.2.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, ] [[package]] name = "python-frontmatter" version = "1.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pyyaml" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/96/de/910fa208120314a12f9a88ea63e03707261692af782c99283f1a2c8a5e6f/python-frontmatter-1.1.0.tar.gz", hash = "sha256:7118d2bd56af9149625745c58c9b51fb67e8d1294a0c76796dafdc72c36e5f6d", size = 16256, upload-time = "2024-01-16T18:50:04.052Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/96/de/910fa208120314a12f9a88ea63e03707261692af782c99283f1a2c8a5e6f/python-frontmatter-1.1.0.tar.gz", hash = "sha256:7118d2bd56af9149625745c58c9b51fb67e8d1294a0c76796dafdc72c36e5f6d", size = 16256, upload-time = "2024-01-16T18:50:04.052Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/49/87/3c8da047b3ec5f99511d1b4d7a5bc72d4b98751c7e78492d14dc736319c5/python_frontmatter-1.1.0-py3-none-any.whl", hash = "sha256:335465556358d9d0e6c98bbeb69b1c969f2a4a21360587b9873bfc3b213407c1", size = 9834, upload-time = "2024-01-16T18:50:00.911Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/49/87/3c8da047b3ec5f99511d1b4d7a5bc72d4b98751c7e78492d14dc736319c5/python_frontmatter-1.1.0-py3-none-any.whl", hash = "sha256:335465556358d9d0e6c98bbeb69b1c969f2a4a21360587b9873bfc3b213407c1", size = 9834, upload-time = "2024-01-16T18:50:00.911Z" }, ] [[package]] name = "python-jose" version = "3.5.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "ecdsa" }, { name = "pyasn1" }, { name = "rsa" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c6/77/3a1c9039db7124eb039772b935f2244fbb73fc8ee65b9acf2375da1c07bf/python_jose-3.5.0.tar.gz", hash = "sha256:fb4eaa44dbeb1c26dcc69e4bd7ec54a1cb8dd64d3b4d81ef08d90ff453f2b01b", size = 92726, upload-time = "2025-05-28T17:31:54.288Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c6/77/3a1c9039db7124eb039772b935f2244fbb73fc8ee65b9acf2375da1c07bf/python_jose-3.5.0.tar.gz", hash = "sha256:fb4eaa44dbeb1c26dcc69e4bd7ec54a1cb8dd64d3b4d81ef08d90ff453f2b01b", size = 92726, upload-time = "2025-05-28T17:31:54.288Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d9/c3/0bd11992072e6a1c513b16500a5d07f91a24017c5909b02c72c62d7ad024/python_jose-3.5.0-py2.py3-none-any.whl", hash = "sha256:abd1202f23d34dfad2c3d28cb8617b90acf34132c7afd60abd0b0b7d3cb55771", size = 34624, upload-time = "2025-05-28T17:31:52.802Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/c3/0bd11992072e6a1c513b16500a5d07f91a24017c5909b02c72c62d7ad024/python_jose-3.5.0-py2.py3-none-any.whl", hash = "sha256:abd1202f23d34dfad2c3d28cb8617b90acf34132c7afd60abd0b0b7d3cb55771", size = 34624, upload-time = "2025-05-28T17:31:52.802Z" }, ] [package.optional-dependencies] @@ -3549,441 +3540,441 @@ cryptography = [ [[package]] name = "python-json-logger" version = "4.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, ] [[package]] name = "python-multipart" version = "0.0.21" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/78/96/804520d0850c7db98e5ccb70282e29208723f0964e88ffd9d0da2f52ea09/python_multipart-0.0.21.tar.gz", hash = "sha256:7137ebd4d3bbf70ea1622998f902b97a29434a9e8dc40eb203bbcf7c2a2cba92", size = 37196, upload-time = "2025-12-17T09:24:22.446Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/78/96/804520d0850c7db98e5ccb70282e29208723f0964e88ffd9d0da2f52ea09/python_multipart-0.0.21.tar.gz", hash = "sha256:7137ebd4d3bbf70ea1622998f902b97a29434a9e8dc40eb203bbcf7c2a2cba92", size = 37196, upload-time = "2025-12-17T09:24:22.446Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/76/03af049af4dcee5d27442f71b6924f01f3efb5d2bd34f23fcd563f2cc5f5/python_multipart-0.0.21-py3-none-any.whl", hash = "sha256:cf7a6713e01c87aa35387f4774e812c4361150938d20d232800f75ffcf266090", size = 24541, upload-time = "2025-12-17T09:24:21.153Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/76/03af049af4dcee5d27442f71b6924f01f3efb5d2bd34f23fcd563f2cc5f5/python_multipart-0.0.21-py3-none-any.whl", hash = "sha256:cf7a6713e01c87aa35387f4774e812c4361150938d20d232800f75ffcf266090", size = 24541, upload-time = "2025-12-17T09:24:21.153Z" }, ] [[package]] name = "pyvex" version = "9.2.191" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "bitstring" }, { name = "cffi", marker = "implementation_name == 'cpython'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f8/01/de3b1f358184bda64dc5025ca28f5e4be26fa1a88c9fe404ced9e25c8b0d/pyvex-9.2.191.tar.gz", hash = "sha256:b98ddc16db5693f46155f13ba770f272615450b8e3e58ca24b45a5fb5ac4befd", size = 3649102, upload-time = "2025-12-30T17:44:30.636Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f8/01/de3b1f358184bda64dc5025ca28f5e4be26fa1a88c9fe404ced9e25c8b0d/pyvex-9.2.191.tar.gz", hash = "sha256:b98ddc16db5693f46155f13ba770f272615450b8e3e58ca24b45a5fb5ac4befd", size = 3649102, upload-time = "2025-12-30T17:44:30.636Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/ac/ae661cb67c19c462017bcdb355bc0356a2f1cd655586e257f6cdc53963c2/pyvex-9.2.191-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:efc09e4ce15586db59a8604c2c5285094ef8088bc235a731042a66e130503795", size = 1864470, upload-time = "2025-12-30T17:43:55.507Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c4/31/bac6717c87aa58a1b239b37dad27d94ce14df521c3d1497822c96126cb9e/pyvex-9.2.191-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a204ec025f727dff6687740eb542c7391b7d632bd79e98301a4d91a4223ee17a", size = 1587483, upload-time = "2025-12-30T17:43:56.85Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/66/f7d85588918edc13d3c5f07ccade62a2d140c53717d76793b01fbca3e9e9/pyvex-9.2.191-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffd74f6944ed62409afd0ebafafbbda06e352f65175a8b803b49701bb7937815", size = 1783318, upload-time = "2025-12-30T17:43:58.598Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6d/93/b11bc5f61783a6693c4b0df97aee403740b426f17fde42cf264a2d2354a7/pyvex-9.2.191-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3acc386970e655913f469e0883d81efaa2b60d4e042e48102c645d3429918ba", size = 1915136, upload-time = "2025-12-30T17:43:59.95Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/01/ba1651f7d0d9cc9f66bf99507d4b47af49563c1f73bc6de207e7fa71d58c/pyvex-9.2.191-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:46966273c3e808e6c06d78da62f1549c433a6b7c1968bf6a4a85d87052236468", size = 1800213, upload-time = "2025-12-30T17:44:01.367Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/93/a2/73252ea93502c304b2b4335ff9a9c8d98ebd3b8701610f381c35a698aee9/pyvex-9.2.191-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8b02ecd0aae6f93028d877e87fdb82654b549e2942e227db97eaf1f6e1fb00d0", size = 1946647, upload-time = "2025-12-30T17:44:03.006Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/10/c9/a3e0e652a5077fcbcb781362f4f0dc375951edd4483b839b5b6dca024d58/pyvex-9.2.191-cp312-cp312-win_amd64.whl", hash = "sha256:52f3e47be14bec4a15be38d3af8e62898ade7cd392b7f16b78b8018af9b01c41", size = 1363400, upload-time = "2025-12-30T17:44:04.471Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4d/c9/a1ba716ef9f2133fcfe77bd190c13abb8254ab757bdff7198ddc279c12e7/pyvex-9.2.191-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0dec0aa852098dda20dc5888018b619bb55a9b20013ae3e10e8924e4f74503b", size = 1864470, upload-time = "2025-12-30T17:44:06.378Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/04/98/f2fc6834da2c9a2e3e1ab45f7e2ab53c4bb799822aab27c25f2188a0bfbd/pyvex-9.2.191-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b7f1381d2d74c5878364371600d3be900cd852f697a6d4839b5df5de511bc937", size = 1587481, upload-time = "2025-12-30T17:44:07.742Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/04/1d/4f95450cb4ca625103e43db874f5b633816ef811fbe60a0900761dc9a6b2/pyvex-9.2.191-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ef8fc1ec814738d1371ceee5e05eec2e318a2135282b4468ac591b2c6d51412", size = 1783318, upload-time = "2025-12-30T17:44:09.485Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4f/d3/273e64b7db5ed3893502c9f432aaaaeda617930363ce28b7d134017e16a1/pyvex-9.2.191-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f0fbea242f96f0520b4d9b5c2231fd9ccbd90cc69be8ff0efba63c04c6c1c15", size = 1915137, upload-time = "2025-12-30T17:44:10.886Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/77/14110503262d2fcb1f29ce1227782d39fb8308f4ddabbe608444291cec1a/pyvex-9.2.191-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:441b7e329a6e298ac23058cf68c7d87ae698309510abc7d81a1ba98e2d81d9ce", size = 1800213, upload-time = "2025-12-30T17:44:12.661Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a7/af/174010241e939f19d606e4442566effe4655b19622e95fa9fe14b6438708/pyvex-9.2.191-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:32aa150c032f43e3ecdff97ed86e8fe92eaf12f59251d76c85b824c3c85c0a55", size = 1946648, upload-time = "2025-12-30T17:44:14.188Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/3a/6060b8f682da42e4b533876c7679c9d1bf3b40829d1b881c222a589e4da1/pyvex-9.2.191-cp313-cp313-win_amd64.whl", hash = "sha256:25958bdfddda731cefa2387bf4068e34493ca345d29da57ee96d9e4bc0a1954d", size = 1363401, upload-time = "2025-12-30T17:44:15.79Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/ac/ae661cb67c19c462017bcdb355bc0356a2f1cd655586e257f6cdc53963c2/pyvex-9.2.191-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:efc09e4ce15586db59a8604c2c5285094ef8088bc235a731042a66e130503795", size = 1864470, upload-time = "2025-12-30T17:43:55.507Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c4/31/bac6717c87aa58a1b239b37dad27d94ce14df521c3d1497822c96126cb9e/pyvex-9.2.191-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a204ec025f727dff6687740eb542c7391b7d632bd79e98301a4d91a4223ee17a", size = 1587483, upload-time = "2025-12-30T17:43:56.85Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/66/f7d85588918edc13d3c5f07ccade62a2d140c53717d76793b01fbca3e9e9/pyvex-9.2.191-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffd74f6944ed62409afd0ebafafbbda06e352f65175a8b803b49701bb7937815", size = 1783318, upload-time = "2025-12-30T17:43:58.598Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6d/93/b11bc5f61783a6693c4b0df97aee403740b426f17fde42cf264a2d2354a7/pyvex-9.2.191-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3acc386970e655913f469e0883d81efaa2b60d4e042e48102c645d3429918ba", size = 1915136, upload-time = "2025-12-30T17:43:59.95Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/01/ba1651f7d0d9cc9f66bf99507d4b47af49563c1f73bc6de207e7fa71d58c/pyvex-9.2.191-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:46966273c3e808e6c06d78da62f1549c433a6b7c1968bf6a4a85d87052236468", size = 1800213, upload-time = "2025-12-30T17:44:01.367Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/93/a2/73252ea93502c304b2b4335ff9a9c8d98ebd3b8701610f381c35a698aee9/pyvex-9.2.191-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8b02ecd0aae6f93028d877e87fdb82654b549e2942e227db97eaf1f6e1fb00d0", size = 1946647, upload-time = "2025-12-30T17:44:03.006Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/c9/a3e0e652a5077fcbcb781362f4f0dc375951edd4483b839b5b6dca024d58/pyvex-9.2.191-cp312-cp312-win_amd64.whl", hash = "sha256:52f3e47be14bec4a15be38d3af8e62898ade7cd392b7f16b78b8018af9b01c41", size = 1363400, upload-time = "2025-12-30T17:44:04.471Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4d/c9/a1ba716ef9f2133fcfe77bd190c13abb8254ab757bdff7198ddc279c12e7/pyvex-9.2.191-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0dec0aa852098dda20dc5888018b619bb55a9b20013ae3e10e8924e4f74503b", size = 1864470, upload-time = "2025-12-30T17:44:06.378Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/98/f2fc6834da2c9a2e3e1ab45f7e2ab53c4bb799822aab27c25f2188a0bfbd/pyvex-9.2.191-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b7f1381d2d74c5878364371600d3be900cd852f697a6d4839b5df5de511bc937", size = 1587481, upload-time = "2025-12-30T17:44:07.742Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/1d/4f95450cb4ca625103e43db874f5b633816ef811fbe60a0900761dc9a6b2/pyvex-9.2.191-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ef8fc1ec814738d1371ceee5e05eec2e318a2135282b4468ac591b2c6d51412", size = 1783318, upload-time = "2025-12-30T17:44:09.485Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4f/d3/273e64b7db5ed3893502c9f432aaaaeda617930363ce28b7d134017e16a1/pyvex-9.2.191-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f0fbea242f96f0520b4d9b5c2231fd9ccbd90cc69be8ff0efba63c04c6c1c15", size = 1915137, upload-time = "2025-12-30T17:44:10.886Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/77/14110503262d2fcb1f29ce1227782d39fb8308f4ddabbe608444291cec1a/pyvex-9.2.191-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:441b7e329a6e298ac23058cf68c7d87ae698309510abc7d81a1ba98e2d81d9ce", size = 1800213, upload-time = "2025-12-30T17:44:12.661Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a7/af/174010241e939f19d606e4442566effe4655b19622e95fa9fe14b6438708/pyvex-9.2.191-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:32aa150c032f43e3ecdff97ed86e8fe92eaf12f59251d76c85b824c3c85c0a55", size = 1946648, upload-time = "2025-12-30T17:44:14.188Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/3a/6060b8f682da42e4b533876c7679c9d1bf3b40829d1b881c222a589e4da1/pyvex-9.2.191-cp313-cp313-win_amd64.whl", hash = "sha256:25958bdfddda731cefa2387bf4068e34493ca345d29da57ee96d9e4bc0a1954d", size = 1363401, upload-time = "2025-12-30T17:44:15.79Z" }, ] [[package]] name = "pywin32" version = "311" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, ] [[package]] name = "pywin32-ctypes" version = "0.2.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, ] [[package]] name = "pyxbe" version = "1.0.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/df/cb/a090b3a16a6a3d3c0c91f6d9e187df3dae33ce1f5b19b91bbf218dea0a6d/pyxbe-1.0.3.tar.gz", hash = "sha256:ef38c9b07bffd9daecdd32640a3e6c99f62a621a8b8a4d54a0c2ccf9fb1b7cdb" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/cb/a090b3a16a6a3d3c0c91f6d9e187df3dae33ce1f5b19b91bbf218dea0a6d/pyxbe-1.0.3.tar.gz", hash = "sha256:ef38c9b07bffd9daecdd32640a3e6c99f62a621a8b8a4d54a0c2ccf9fb1b7cdb" } [[package]] name = "pyxdia" version = "0.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/17/d8/6e691bfb19edf50a3286349d5fd4200a569dfc2c900a083e3548a6a1c726/pyxdia-0.1.0.tar.gz", hash = "sha256:af95d1ce70407e7a0f72d02ba77d366c0dfb0ed58fb336f8725ac8f3493b7e68", size = 6043, upload-time = "2025-06-13T20:03:44.192Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/17/d8/6e691bfb19edf50a3286349d5fd4200a569dfc2c900a083e3548a6a1c726/pyxdia-0.1.0.tar.gz", hash = "sha256:af95d1ce70407e7a0f72d02ba77d366c0dfb0ed58fb336f8725ac8f3493b7e68", size = 6043, upload-time = "2025-06-13T20:03:44.192Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/21/d8/fceba98b6faa81534faae2b87b52d669d22f61ea7c64968babe01fa839a8/pyxdia-0.1.0-py3-none-macosx_13_0_x86_64.whl", hash = "sha256:c5c2ca7041294a9e1ff81622b0305569b04c3d511992c84640052899fb039b00", size = 1641463, upload-time = "2025-06-13T20:03:35.701Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/2f/f563746306c448248b98303f2a991812d1180766cb220f4e601f0caec771/pyxdia-0.1.0-py3-none-macosx_14_0_arm64.whl", hash = "sha256:b40738dc999e560fa3283aa2aeb819c34cd9084c7b0949bc2e5e136c631cbbc0", size = 1625815, upload-time = "2025-06-13T20:03:37.489Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/d4/46ee9f0c1b0a29160fd7490cb2a5abf32bb64bb5d704404bd937c9498e43/pyxdia-0.1.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3809b60a4b95d2bf5a2babd8b50f67b362b10a371abc92a8cf3a86fc648857d8", size = 1383830, upload-time = "2025-06-13T20:03:39.283Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/84/81/638749bc9bba9b4be8a3c8dd6abba85b1cb527bc6507f591e8d7fd1cfd37/pyxdia-0.1.0-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:28e385eda08eba48883c2c6fc29ea6da8d8536924133468b4b8281a8b24a176a", size = 2706942, upload-time = "2025-06-13T20:03:40.903Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2f/ea/34d31e0e4484d2acdd25a24d56a26be7855f9119244fd9ea16d00095b01e/pyxdia-0.1.0-py3-none-win_amd64.whl", hash = "sha256:5bd17cec300f53d0bb7926f64095e3806674c6a82f8c2a5c6be24aa6fc1384a1", size = 958051, upload-time = "2025-06-13T20:03:42.789Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/21/d8/fceba98b6faa81534faae2b87b52d669d22f61ea7c64968babe01fa839a8/pyxdia-0.1.0-py3-none-macosx_13_0_x86_64.whl", hash = "sha256:c5c2ca7041294a9e1ff81622b0305569b04c3d511992c84640052899fb039b00", size = 1641463, upload-time = "2025-06-13T20:03:35.701Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/2f/f563746306c448248b98303f2a991812d1180766cb220f4e601f0caec771/pyxdia-0.1.0-py3-none-macosx_14_0_arm64.whl", hash = "sha256:b40738dc999e560fa3283aa2aeb819c34cd9084c7b0949bc2e5e136c631cbbc0", size = 1625815, upload-time = "2025-06-13T20:03:37.489Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/d4/46ee9f0c1b0a29160fd7490cb2a5abf32bb64bb5d704404bd937c9498e43/pyxdia-0.1.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3809b60a4b95d2bf5a2babd8b50f67b362b10a371abc92a8cf3a86fc648857d8", size = 1383830, upload-time = "2025-06-13T20:03:39.283Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/84/81/638749bc9bba9b4be8a3c8dd6abba85b1cb527bc6507f591e8d7fd1cfd37/pyxdia-0.1.0-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:28e385eda08eba48883c2c6fc29ea6da8d8536924133468b4b8281a8b24a176a", size = 2706942, upload-time = "2025-06-13T20:03:40.903Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2f/ea/34d31e0e4484d2acdd25a24d56a26be7855f9119244fd9ea16d00095b01e/pyxdia-0.1.0-py3-none-win_amd64.whl", hash = "sha256:5bd17cec300f53d0bb7926f64095e3806674c6a82f8c2a5c6be24aa6fc1384a1", size = 958051, upload-time = "2025-06-13T20:03:42.789Z" }, ] [[package]] name = "pyyaml" version = "6.0.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, ] [[package]] name = "redis" version = "7.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/c8/983d5c6579a411d8a99bc5823cc5712768859b5ce2c8afe1a65b37832c81/redis-7.1.0.tar.gz", hash = "sha256:b1cc3cfa5a2cb9c2ab3ba700864fb0ad75617b41f01352ce5779dabf6d5f9c3c", size = 4796669, upload-time = "2025-11-19T15:54:39.961Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/c8/983d5c6579a411d8a99bc5823cc5712768859b5ce2c8afe1a65b37832c81/redis-7.1.0.tar.gz", hash = "sha256:b1cc3cfa5a2cb9c2ab3ba700864fb0ad75617b41f01352ce5779dabf6d5f9c3c", size = 4796669, upload-time = "2025-11-19T15:54:39.961Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/f0/8956f8a86b20d7bb9d6ac0187cf4cd54d8065bc9a1a09eb8011d4d326596/redis-7.1.0-py3-none-any.whl", hash = "sha256:23c52b208f92b56103e17c5d06bdc1a6c2c0b3106583985a76a18f83b265de2b", size = 354159, upload-time = "2025-11-19T15:54:38.064Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/f0/8956f8a86b20d7bb9d6ac0187cf4cd54d8065bc9a1a09eb8011d4d326596/redis-7.1.0-py3-none-any.whl", hash = "sha256:23c52b208f92b56103e17c5d06bdc1a6c2c0b3106583985a76a18f83b265de2b", size = 354159, upload-time = "2025-11-19T15:54:38.064Z" }, ] [[package]] name = "referencing" version = "0.36.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "attrs" }, { name = "rpds-py" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744, upload-time = "2025-01-25T08:48:16.138Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744, upload-time = "2025-01-25T08:48:16.138Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775, upload-time = "2025-01-25T08:48:14.241Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775, upload-time = "2025-01-25T08:48:14.241Z" }, ] [[package]] name = "regex" version = "2025.11.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cc/a9/546676f25e573a4cf00fe8e119b78a37b6a8fe2dc95cda877b30889c9c45/regex-2025.11.3.tar.gz", hash = "sha256:1fedc720f9bb2494ce31a58a1631f9c82df6a09b49c19517ea5cc280b4541e01", size = 414669, upload-time = "2025-11-03T21:34:22.089Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e8/74/18f04cb53e58e3fb107439699bd8375cf5a835eec81084e0bddbd122e4c2/regex-2025.11.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bc8ab71e2e31b16e40868a40a69007bc305e1109bd4658eb6cad007e0bf67c41", size = 489312, upload-time = "2025-11-03T21:31:34.343Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/78/3f/37fcdd0d2b1e78909108a876580485ea37c91e1acf66d3bb8e736348f441/regex-2025.11.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:22b29dda7e1f7062a52359fca6e58e548e28c6686f205e780b02ad8ef710de36", size = 291256, upload-time = "2025-11-03T21:31:35.675Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bf/26/0a575f58eb23b7ebd67a45fccbc02ac030b737b896b7e7a909ffe43ffd6a/regex-2025.11.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3a91e4a29938bc1a082cc28fdea44be420bf2bebe2665343029723892eb073e1", size = 288921, upload-time = "2025-11-03T21:31:37.07Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/98/6a8dff667d1af907150432cf5abc05a17ccd32c72a3615410d5365ac167a/regex-2025.11.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08b884f4226602ad40c5d55f52bf91a9df30f513864e0054bad40c0e9cf1afb7", size = 798568, upload-time = "2025-11-03T21:31:38.784Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/64/15/92c1db4fa4e12733dd5a526c2dd2b6edcbfe13257e135fc0f6c57f34c173/regex-2025.11.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3e0b11b2b2433d1c39c7c7a30e3f3d0aeeea44c2a8d0bae28f6b95f639927a69", size = 864165, upload-time = "2025-11-03T21:31:40.559Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/e7/3ad7da8cdee1ce66c7cd37ab5ab05c463a86ffeb52b1a25fe7bd9293b36c/regex-2025.11.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:87eb52a81ef58c7ba4d45c3ca74e12aa4b4e77816f72ca25258a85b3ea96cb48", size = 912182, upload-time = "2025-11-03T21:31:42.002Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/84/bd/9ce9f629fcb714ffc2c3faf62b6766ecb7a585e1e885eb699bcf130a5209/regex-2025.11.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a12ab1f5c29b4e93db518f5e3872116b7e9b1646c9f9f426f777b50d44a09e8c", size = 803501, upload-time = "2025-11-03T21:31:43.815Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7c/0f/8dc2e4349d8e877283e6edd6c12bdcebc20f03744e86f197ab6e4492bf08/regex-2025.11.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7521684c8c7c4f6e88e35ec89680ee1aa8358d3f09d27dfbdf62c446f5d4c695", size = 787842, upload-time = "2025-11-03T21:31:45.353Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/73/cff02702960bc185164d5619c0c62a2f598a6abff6695d391b096237d4ab/regex-2025.11.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7fe6e5440584e94cc4b3f5f4d98a25e29ca12dccf8873679a635638349831b98", size = 858519, upload-time = "2025-11-03T21:31:46.814Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/83/0e8d1ae71e15bc1dc36231c90b46ee35f9d52fab2e226b0e039e7ea9c10a/regex-2025.11.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8e026094aa12b43f4fd74576714e987803a315c76edb6b098b9809db5de58f74", size = 850611, upload-time = "2025-11-03T21:31:48.289Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c8/f5/70a5cdd781dcfaa12556f2955bf170cd603cb1c96a1827479f8faea2df97/regex-2025.11.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:435bbad13e57eb5606a68443af62bed3556de2f46deb9f7d4237bc2f1c9fb3a0", size = 789759, upload-time = "2025-11-03T21:31:49.759Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/9b/7c29be7903c318488983e7d97abcf8ebd3830e4c956c4c540005fcfb0462/regex-2025.11.3-cp312-cp312-win32.whl", hash = "sha256:3839967cf4dc4b985e1570fd8d91078f0c519f30491c60f9ac42a8db039be204", size = 266194, upload-time = "2025-11-03T21:31:51.53Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1a/67/3b92df89f179d7c367be654ab5626ae311cb28f7d5c237b6bb976cd5fbbb/regex-2025.11.3-cp312-cp312-win_amd64.whl", hash = "sha256:e721d1b46e25c481dc5ded6f4b3f66c897c58d2e8cfdf77bbced84339108b0b9", size = 277069, upload-time = "2025-11-03T21:31:53.151Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d7/55/85ba4c066fe5094d35b249c3ce8df0ba623cfd35afb22d6764f23a52a1c5/regex-2025.11.3-cp312-cp312-win_arm64.whl", hash = "sha256:64350685ff08b1d3a6fff33f45a9ca183dc1d58bbfe4981604e70ec9801bbc26", size = 270330, upload-time = "2025-11-03T21:31:54.514Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e1/a7/dda24ebd49da46a197436ad96378f17df30ceb40e52e859fc42cac45b850/regex-2025.11.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c1e448051717a334891f2b9a620fe36776ebf3dd8ec46a0b877c8ae69575feb4", size = 489081, upload-time = "2025-11-03T21:31:55.9Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/19/22/af2dc751aacf88089836aa088a1a11c4f21a04707eb1b0478e8e8fb32847/regex-2025.11.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9b5aca4d5dfd7fbfbfbdaf44850fcc7709a01146a797536a8f84952e940cca76", size = 291123, upload-time = "2025-11-03T21:31:57.758Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a3/88/1a3ea5672f4b0a84802ee9891b86743438e7c04eb0b8f8c4e16a42375327/regex-2025.11.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:04d2765516395cf7dda331a244a3282c0f5ae96075f728629287dfa6f76ba70a", size = 288814, upload-time = "2025-11-03T21:32:01.12Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fb/8c/f5987895bf42b8ddeea1b315c9fedcfe07cadee28b9c98cf50d00adcb14d/regex-2025.11.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d9903ca42bfeec4cebedba8022a7c97ad2aab22e09573ce9976ba01b65e4361", size = 798592, upload-time = "2025-11-03T21:32:03.006Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/99/2a/6591ebeede78203fa77ee46a1c36649e02df9eaa77a033d1ccdf2fcd5d4e/regex-2025.11.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:639431bdc89d6429f6721625e8129413980ccd62e9d3f496be618a41d205f160", size = 864122, upload-time = "2025-11-03T21:32:04.553Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/94/d6/be32a87cf28cf8ed064ff281cfbd49aefd90242a83e4b08b5a86b38e8eb4/regex-2025.11.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f117efad42068f9715677c8523ed2be1518116d1c49b1dd17987716695181efe", size = 912272, upload-time = "2025-11-03T21:32:06.148Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/62/11/9bcef2d1445665b180ac7f230406ad80671f0fc2a6ffb93493b5dd8cd64c/regex-2025.11.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4aecb6f461316adf9f1f0f6a4a1a3d79e045f9b71ec76055a791affa3b285850", size = 803497, upload-time = "2025-11-03T21:32:08.162Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/a7/da0dc273d57f560399aa16d8a68ae7f9b57679476fc7ace46501d455fe84/regex-2025.11.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3b3a5f320136873cc5561098dfab677eea139521cb9a9e8db98b7e64aef44cbc", size = 787892, upload-time = "2025-11-03T21:32:09.769Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/4b/732a0c5a9736a0b8d6d720d4945a2f1e6f38f87f48f3173559f53e8d5d82/regex-2025.11.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:75fa6f0056e7efb1f42a1c34e58be24072cb9e61a601340cc1196ae92326a4f9", size = 858462, upload-time = "2025-11-03T21:32:11.769Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0c/f5/a2a03df27dc4c2d0c769220f5110ba8c4084b0bfa9ab0f9b4fcfa3d2b0fc/regex-2025.11.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:dbe6095001465294f13f1adcd3311e50dd84e5a71525f20a10bd16689c61ce0b", size = 850528, upload-time = "2025-11-03T21:32:13.906Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d6/09/e1cd5bee3841c7f6eb37d95ca91cdee7100b8f88b81e41c2ef426910891a/regex-2025.11.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:454d9b4ae7881afbc25015b8627c16d88a597479b9dea82b8c6e7e2e07240dc7", size = 789866, upload-time = "2025-11-03T21:32:15.748Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/eb/51/702f5ea74e2a9c13d855a6a85b7f80c30f9e72a95493260193c07f3f8d74/regex-2025.11.3-cp313-cp313-win32.whl", hash = "sha256:28ba4d69171fc6e9896337d4fc63a43660002b7da53fc15ac992abcf3410917c", size = 266189, upload-time = "2025-11-03T21:32:17.493Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8b/00/6e29bb314e271a743170e53649db0fdb8e8ff0b64b4f425f5602f4eb9014/regex-2025.11.3-cp313-cp313-win_amd64.whl", hash = "sha256:bac4200befe50c670c405dc33af26dad5a3b6b255dd6c000d92fe4629f9ed6a5", size = 277054, upload-time = "2025-11-03T21:32:19.042Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/f1/b156ff9f2ec9ac441710764dda95e4edaf5f36aca48246d1eea3f1fd96ec/regex-2025.11.3-cp313-cp313-win_arm64.whl", hash = "sha256:2292cd5a90dab247f9abe892ac584cb24f0f54680c73fcb4a7493c66c2bf2467", size = 270325, upload-time = "2025-11-03T21:32:21.338Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/20/28/fd0c63357caefe5680b8ea052131acbd7f456893b69cc2a90cc3e0dc90d4/regex-2025.11.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:1eb1ebf6822b756c723e09f5186473d93236c06c579d2cc0671a722d2ab14281", size = 491984, upload-time = "2025-11-03T21:32:23.466Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/df/ec/7014c15626ab46b902b3bcc4b28a7bae46d8f281fc7ea9c95e22fcaaa917/regex-2025.11.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1e00ec2970aab10dc5db34af535f21fcf32b4a31d99e34963419636e2f85ae39", size = 292673, upload-time = "2025-11-03T21:32:25.034Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/23/ab/3b952ff7239f20d05f1f99e9e20188513905f218c81d52fb5e78d2bf7634/regex-2025.11.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a4cb042b615245d5ff9b3794f56be4138b5adc35a4166014d31d1814744148c7", size = 291029, upload-time = "2025-11-03T21:32:26.528Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/21/7e/3dc2749fc684f455f162dcafb8a187b559e2614f3826877d3844a131f37b/regex-2025.11.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44f264d4bf02f3176467d90b294d59bf1db9fe53c141ff772f27a8b456b2a9ed", size = 807437, upload-time = "2025-11-03T21:32:28.363Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1b/0b/d529a85ab349c6a25d1ca783235b6e3eedf187247eab536797021f7126c6/regex-2025.11.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7be0277469bf3bd7a34a9c57c1b6a724532a0d235cd0dc4e7f4316f982c28b19", size = 873368, upload-time = "2025-11-03T21:32:30.4Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7d/18/2d868155f8c9e3e9d8f9e10c64e9a9f496bb8f7e037a88a8bed26b435af6/regex-2025.11.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0d31e08426ff4b5b650f68839f5af51a92a5b51abd8554a60c2fbc7c71f25d0b", size = 914921, upload-time = "2025-11-03T21:32:32.123Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2d/71/9d72ff0f354fa783fe2ba913c8734c3b433b86406117a8db4ea2bf1c7a2f/regex-2025.11.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e43586ce5bd28f9f285a6e729466841368c4a0353f6fd08d4ce4630843d3648a", size = 812708, upload-time = "2025-11-03T21:32:34.305Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/19/ce4bf7f5575c97f82b6e804ffb5c4e940c62609ab2a0d9538d47a7fdf7d4/regex-2025.11.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0f9397d561a4c16829d4e6ff75202c1c08b68a3bdbfe29dbfcdb31c9830907c6", size = 795472, upload-time = "2025-11-03T21:32:36.364Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/03/86/fd1063a176ffb7b2315f9a1b08d17b18118b28d9df163132615b835a26ee/regex-2025.11.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:dd16e78eb18ffdb25ee33a0682d17912e8cc8a770e885aeee95020046128f1ce", size = 868341, upload-time = "2025-11-03T21:32:38.042Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/12/43/103fb2e9811205e7386366501bc866a164a0430c79dd59eac886a2822950/regex-2025.11.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:ffcca5b9efe948ba0661e9df0fa50d2bc4b097c70b9810212d6b62f05d83b2dd", size = 854666, upload-time = "2025-11-03T21:32:40.079Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7d/22/e392e53f3869b75804762c7c848bd2dd2abf2b70fb0e526f58724638bd35/regex-2025.11.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c56b4d162ca2b43318ac671c65bd4d563e841a694ac70e1a976ac38fcf4ca1d2", size = 799473, upload-time = "2025-11-03T21:32:42.148Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4f/f9/8bd6b656592f925b6845fcbb4d57603a3ac2fb2373344ffa1ed70aa6820a/regex-2025.11.3-cp313-cp313t-win32.whl", hash = "sha256:9ddc42e68114e161e51e272f667d640f97e84a2b9ef14b7477c53aac20c2d59a", size = 268792, upload-time = "2025-11-03T21:32:44.13Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/87/0e7d603467775ff65cd2aeabf1b5b50cc1c3708556a8b849a2fa4dd1542b/regex-2025.11.3-cp313-cp313t-win_amd64.whl", hash = "sha256:7a7c7fdf755032ffdd72c77e3d8096bdcb0eb92e89e17571a196f03d88b11b3c", size = 280214, upload-time = "2025-11-03T21:32:45.853Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8d/d0/2afc6f8e94e2b64bfb738a7c2b6387ac1699f09f032d363ed9447fd2bb57/regex-2025.11.3-cp313-cp313t-win_arm64.whl", hash = "sha256:df9eb838c44f570283712e7cff14c16329a9f0fb19ca492d21d4b7528ee6821e", size = 271469, upload-time = "2025-11-03T21:32:48.026Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/a9/546676f25e573a4cf00fe8e119b78a37b6a8fe2dc95cda877b30889c9c45/regex-2025.11.3.tar.gz", hash = "sha256:1fedc720f9bb2494ce31a58a1631f9c82df6a09b49c19517ea5cc280b4541e01", size = 414669, upload-time = "2025-11-03T21:34:22.089Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e8/74/18f04cb53e58e3fb107439699bd8375cf5a835eec81084e0bddbd122e4c2/regex-2025.11.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bc8ab71e2e31b16e40868a40a69007bc305e1109bd4658eb6cad007e0bf67c41", size = 489312, upload-time = "2025-11-03T21:31:34.343Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/78/3f/37fcdd0d2b1e78909108a876580485ea37c91e1acf66d3bb8e736348f441/regex-2025.11.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:22b29dda7e1f7062a52359fca6e58e548e28c6686f205e780b02ad8ef710de36", size = 291256, upload-time = "2025-11-03T21:31:35.675Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/26/0a575f58eb23b7ebd67a45fccbc02ac030b737b896b7e7a909ffe43ffd6a/regex-2025.11.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3a91e4a29938bc1a082cc28fdea44be420bf2bebe2665343029723892eb073e1", size = 288921, upload-time = "2025-11-03T21:31:37.07Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/98/6a8dff667d1af907150432cf5abc05a17ccd32c72a3615410d5365ac167a/regex-2025.11.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08b884f4226602ad40c5d55f52bf91a9df30f513864e0054bad40c0e9cf1afb7", size = 798568, upload-time = "2025-11-03T21:31:38.784Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/64/15/92c1db4fa4e12733dd5a526c2dd2b6edcbfe13257e135fc0f6c57f34c173/regex-2025.11.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3e0b11b2b2433d1c39c7c7a30e3f3d0aeeea44c2a8d0bae28f6b95f639927a69", size = 864165, upload-time = "2025-11-03T21:31:40.559Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/e7/3ad7da8cdee1ce66c7cd37ab5ab05c463a86ffeb52b1a25fe7bd9293b36c/regex-2025.11.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:87eb52a81ef58c7ba4d45c3ca74e12aa4b4e77816f72ca25258a85b3ea96cb48", size = 912182, upload-time = "2025-11-03T21:31:42.002Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/84/bd/9ce9f629fcb714ffc2c3faf62b6766ecb7a585e1e885eb699bcf130a5209/regex-2025.11.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a12ab1f5c29b4e93db518f5e3872116b7e9b1646c9f9f426f777b50d44a09e8c", size = 803501, upload-time = "2025-11-03T21:31:43.815Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7c/0f/8dc2e4349d8e877283e6edd6c12bdcebc20f03744e86f197ab6e4492bf08/regex-2025.11.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7521684c8c7c4f6e88e35ec89680ee1aa8358d3f09d27dfbdf62c446f5d4c695", size = 787842, upload-time = "2025-11-03T21:31:45.353Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/73/cff02702960bc185164d5619c0c62a2f598a6abff6695d391b096237d4ab/regex-2025.11.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7fe6e5440584e94cc4b3f5f4d98a25e29ca12dccf8873679a635638349831b98", size = 858519, upload-time = "2025-11-03T21:31:46.814Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/83/0e8d1ae71e15bc1dc36231c90b46ee35f9d52fab2e226b0e039e7ea9c10a/regex-2025.11.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8e026094aa12b43f4fd74576714e987803a315c76edb6b098b9809db5de58f74", size = 850611, upload-time = "2025-11-03T21:31:48.289Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c8/f5/70a5cdd781dcfaa12556f2955bf170cd603cb1c96a1827479f8faea2df97/regex-2025.11.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:435bbad13e57eb5606a68443af62bed3556de2f46deb9f7d4237bc2f1c9fb3a0", size = 789759, upload-time = "2025-11-03T21:31:49.759Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/9b/7c29be7903c318488983e7d97abcf8ebd3830e4c956c4c540005fcfb0462/regex-2025.11.3-cp312-cp312-win32.whl", hash = "sha256:3839967cf4dc4b985e1570fd8d91078f0c519f30491c60f9ac42a8db039be204", size = 266194, upload-time = "2025-11-03T21:31:51.53Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1a/67/3b92df89f179d7c367be654ab5626ae311cb28f7d5c237b6bb976cd5fbbb/regex-2025.11.3-cp312-cp312-win_amd64.whl", hash = "sha256:e721d1b46e25c481dc5ded6f4b3f66c897c58d2e8cfdf77bbced84339108b0b9", size = 277069, upload-time = "2025-11-03T21:31:53.151Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d7/55/85ba4c066fe5094d35b249c3ce8df0ba623cfd35afb22d6764f23a52a1c5/regex-2025.11.3-cp312-cp312-win_arm64.whl", hash = "sha256:64350685ff08b1d3a6fff33f45a9ca183dc1d58bbfe4981604e70ec9801bbc26", size = 270330, upload-time = "2025-11-03T21:31:54.514Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e1/a7/dda24ebd49da46a197436ad96378f17df30ceb40e52e859fc42cac45b850/regex-2025.11.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c1e448051717a334891f2b9a620fe36776ebf3dd8ec46a0b877c8ae69575feb4", size = 489081, upload-time = "2025-11-03T21:31:55.9Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/22/af2dc751aacf88089836aa088a1a11c4f21a04707eb1b0478e8e8fb32847/regex-2025.11.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9b5aca4d5dfd7fbfbfbdaf44850fcc7709a01146a797536a8f84952e940cca76", size = 291123, upload-time = "2025-11-03T21:31:57.758Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a3/88/1a3ea5672f4b0a84802ee9891b86743438e7c04eb0b8f8c4e16a42375327/regex-2025.11.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:04d2765516395cf7dda331a244a3282c0f5ae96075f728629287dfa6f76ba70a", size = 288814, upload-time = "2025-11-03T21:32:01.12Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fb/8c/f5987895bf42b8ddeea1b315c9fedcfe07cadee28b9c98cf50d00adcb14d/regex-2025.11.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d9903ca42bfeec4cebedba8022a7c97ad2aab22e09573ce9976ba01b65e4361", size = 798592, upload-time = "2025-11-03T21:32:03.006Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/2a/6591ebeede78203fa77ee46a1c36649e02df9eaa77a033d1ccdf2fcd5d4e/regex-2025.11.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:639431bdc89d6429f6721625e8129413980ccd62e9d3f496be618a41d205f160", size = 864122, upload-time = "2025-11-03T21:32:04.553Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/94/d6/be32a87cf28cf8ed064ff281cfbd49aefd90242a83e4b08b5a86b38e8eb4/regex-2025.11.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f117efad42068f9715677c8523ed2be1518116d1c49b1dd17987716695181efe", size = 912272, upload-time = "2025-11-03T21:32:06.148Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/11/9bcef2d1445665b180ac7f230406ad80671f0fc2a6ffb93493b5dd8cd64c/regex-2025.11.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4aecb6f461316adf9f1f0f6a4a1a3d79e045f9b71ec76055a791affa3b285850", size = 803497, upload-time = "2025-11-03T21:32:08.162Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/a7/da0dc273d57f560399aa16d8a68ae7f9b57679476fc7ace46501d455fe84/regex-2025.11.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3b3a5f320136873cc5561098dfab677eea139521cb9a9e8db98b7e64aef44cbc", size = 787892, upload-time = "2025-11-03T21:32:09.769Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/4b/732a0c5a9736a0b8d6d720d4945a2f1e6f38f87f48f3173559f53e8d5d82/regex-2025.11.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:75fa6f0056e7efb1f42a1c34e58be24072cb9e61a601340cc1196ae92326a4f9", size = 858462, upload-time = "2025-11-03T21:32:11.769Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0c/f5/a2a03df27dc4c2d0c769220f5110ba8c4084b0bfa9ab0f9b4fcfa3d2b0fc/regex-2025.11.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:dbe6095001465294f13f1adcd3311e50dd84e5a71525f20a10bd16689c61ce0b", size = 850528, upload-time = "2025-11-03T21:32:13.906Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/09/e1cd5bee3841c7f6eb37d95ca91cdee7100b8f88b81e41c2ef426910891a/regex-2025.11.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:454d9b4ae7881afbc25015b8627c16d88a597479b9dea82b8c6e7e2e07240dc7", size = 789866, upload-time = "2025-11-03T21:32:15.748Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/eb/51/702f5ea74e2a9c13d855a6a85b7f80c30f9e72a95493260193c07f3f8d74/regex-2025.11.3-cp313-cp313-win32.whl", hash = "sha256:28ba4d69171fc6e9896337d4fc63a43660002b7da53fc15ac992abcf3410917c", size = 266189, upload-time = "2025-11-03T21:32:17.493Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8b/00/6e29bb314e271a743170e53649db0fdb8e8ff0b64b4f425f5602f4eb9014/regex-2025.11.3-cp313-cp313-win_amd64.whl", hash = "sha256:bac4200befe50c670c405dc33af26dad5a3b6b255dd6c000d92fe4629f9ed6a5", size = 277054, upload-time = "2025-11-03T21:32:19.042Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/f1/b156ff9f2ec9ac441710764dda95e4edaf5f36aca48246d1eea3f1fd96ec/regex-2025.11.3-cp313-cp313-win_arm64.whl", hash = "sha256:2292cd5a90dab247f9abe892ac584cb24f0f54680c73fcb4a7493c66c2bf2467", size = 270325, upload-time = "2025-11-03T21:32:21.338Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/28/fd0c63357caefe5680b8ea052131acbd7f456893b69cc2a90cc3e0dc90d4/regex-2025.11.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:1eb1ebf6822b756c723e09f5186473d93236c06c579d2cc0671a722d2ab14281", size = 491984, upload-time = "2025-11-03T21:32:23.466Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/ec/7014c15626ab46b902b3bcc4b28a7bae46d8f281fc7ea9c95e22fcaaa917/regex-2025.11.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1e00ec2970aab10dc5db34af535f21fcf32b4a31d99e34963419636e2f85ae39", size = 292673, upload-time = "2025-11-03T21:32:25.034Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/23/ab/3b952ff7239f20d05f1f99e9e20188513905f218c81d52fb5e78d2bf7634/regex-2025.11.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a4cb042b615245d5ff9b3794f56be4138b5adc35a4166014d31d1814744148c7", size = 291029, upload-time = "2025-11-03T21:32:26.528Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/21/7e/3dc2749fc684f455f162dcafb8a187b559e2614f3826877d3844a131f37b/regex-2025.11.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44f264d4bf02f3176467d90b294d59bf1db9fe53c141ff772f27a8b456b2a9ed", size = 807437, upload-time = "2025-11-03T21:32:28.363Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1b/0b/d529a85ab349c6a25d1ca783235b6e3eedf187247eab536797021f7126c6/regex-2025.11.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7be0277469bf3bd7a34a9c57c1b6a724532a0d235cd0dc4e7f4316f982c28b19", size = 873368, upload-time = "2025-11-03T21:32:30.4Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7d/18/2d868155f8c9e3e9d8f9e10c64e9a9f496bb8f7e037a88a8bed26b435af6/regex-2025.11.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0d31e08426ff4b5b650f68839f5af51a92a5b51abd8554a60c2fbc7c71f25d0b", size = 914921, upload-time = "2025-11-03T21:32:32.123Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/71/9d72ff0f354fa783fe2ba913c8734c3b433b86406117a8db4ea2bf1c7a2f/regex-2025.11.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e43586ce5bd28f9f285a6e729466841368c4a0353f6fd08d4ce4630843d3648a", size = 812708, upload-time = "2025-11-03T21:32:34.305Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/19/ce4bf7f5575c97f82b6e804ffb5c4e940c62609ab2a0d9538d47a7fdf7d4/regex-2025.11.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0f9397d561a4c16829d4e6ff75202c1c08b68a3bdbfe29dbfcdb31c9830907c6", size = 795472, upload-time = "2025-11-03T21:32:36.364Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/03/86/fd1063a176ffb7b2315f9a1b08d17b18118b28d9df163132615b835a26ee/regex-2025.11.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:dd16e78eb18ffdb25ee33a0682d17912e8cc8a770e885aeee95020046128f1ce", size = 868341, upload-time = "2025-11-03T21:32:38.042Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/12/43/103fb2e9811205e7386366501bc866a164a0430c79dd59eac886a2822950/regex-2025.11.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:ffcca5b9efe948ba0661e9df0fa50d2bc4b097c70b9810212d6b62f05d83b2dd", size = 854666, upload-time = "2025-11-03T21:32:40.079Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7d/22/e392e53f3869b75804762c7c848bd2dd2abf2b70fb0e526f58724638bd35/regex-2025.11.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c56b4d162ca2b43318ac671c65bd4d563e841a694ac70e1a976ac38fcf4ca1d2", size = 799473, upload-time = "2025-11-03T21:32:42.148Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4f/f9/8bd6b656592f925b6845fcbb4d57603a3ac2fb2373344ffa1ed70aa6820a/regex-2025.11.3-cp313-cp313t-win32.whl", hash = "sha256:9ddc42e68114e161e51e272f667d640f97e84a2b9ef14b7477c53aac20c2d59a", size = 268792, upload-time = "2025-11-03T21:32:44.13Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/87/0e7d603467775ff65cd2aeabf1b5b50cc1c3708556a8b849a2fa4dd1542b/regex-2025.11.3-cp313-cp313t-win_amd64.whl", hash = "sha256:7a7c7fdf755032ffdd72c77e3d8096bdcb0eb92e89e17571a196f03d88b11b3c", size = 280214, upload-time = "2025-11-03T21:32:45.853Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8d/d0/2afc6f8e94e2b64bfb738a7c2b6387ac1699f09f032d363ed9447fd2bb57/regex-2025.11.3-cp313-cp313t-win_arm64.whl", hash = "sha256:df9eb838c44f570283712e7cff14c16329a9f0fb19ca492d21d4b7528ee6821e", size = 271469, upload-time = "2025-11-03T21:32:48.026Z" }, ] [[package]] name = "requests" version = "2.32.5" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "certifi" }, { name = "charset-normalizer" }, { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/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://mirrors.tuna.tsinghua.edu.cn/pypi/web/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" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/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]] name = "requests-toolbelt" version = "1.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "requests" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, ] [[package]] name = "rich" version = "14.2.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, ] [[package]] name = "rich-rst" version = "1.3.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "docutils" }, { name = "rich" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bc/6d/a506aaa4a9eaa945ed8ab2b7347859f53593864289853c5d6d62b77246e0/rich_rst-1.3.2.tar.gz", hash = "sha256:a1196fdddf1e364b02ec68a05e8ff8f6914fee10fbca2e6b6735f166bb0da8d4", size = 14936, upload-time = "2025-10-14T16:49:45.332Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bc/6d/a506aaa4a9eaa945ed8ab2b7347859f53593864289853c5d6d62b77246e0/rich_rst-1.3.2.tar.gz", hash = "sha256:a1196fdddf1e364b02ec68a05e8ff8f6914fee10fbca2e6b6735f166bb0da8d4", size = 14936, upload-time = "2025-10-14T16:49:45.332Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/13/2f/b4530fbf948867702d0a3f27de4a6aab1d156f406d72852ab902c4d04de9/rich_rst-1.3.2-py3-none-any.whl", hash = "sha256:a99b4907cbe118cf9d18b0b44de272efa61f15117c61e39ebdc431baf5df722a", size = 12567, upload-time = "2025-10-14T16:49:42.953Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/13/2f/b4530fbf948867702d0a3f27de4a6aab1d156f406d72852ab902c4d04de9/rich_rst-1.3.2-py3-none-any.whl", hash = "sha256:a99b4907cbe118cf9d18b0b44de272efa61f15117c61e39ebdc431baf5df722a", size = 12567, upload-time = "2025-10-14T16:49:42.953Z" }, ] [[package]] name = "rich-toolkit" version = "0.17.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "click" }, { name = "rich" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/97/09/3f9b8d9daaf235195c626f21e03604c05b987404ee3bcacee0c1f67f2a8e/rich_toolkit-0.17.1.tar.gz", hash = "sha256:5af54df8d1dd9c8530e462e1bdcaed625c9b49f5a55b035aa0ba1c17bdb87c9a", size = 187925, upload-time = "2025-12-17T10:49:22.583Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/97/09/3f9b8d9daaf235195c626f21e03604c05b987404ee3bcacee0c1f67f2a8e/rich_toolkit-0.17.1.tar.gz", hash = "sha256:5af54df8d1dd9c8530e462e1bdcaed625c9b49f5a55b035aa0ba1c17bdb87c9a", size = 187925, upload-time = "2025-12-17T10:49:22.583Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/7b/15e55fa8a76d0d41bf34d965af78acdaf80a315907adb30de8b63c272694/rich_toolkit-0.17.1-py3-none-any.whl", hash = "sha256:96d24bb921ecd225ffce7c526a9149e74006410c05e6d405bd74ffd54d5631ed", size = 31412, upload-time = "2025-12-17T10:49:21.793Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/7b/15e55fa8a76d0d41bf34d965af78acdaf80a315907adb30de8b63c272694/rich_toolkit-0.17.1-py3-none-any.whl", hash = "sha256:96d24bb921ecd225ffce7c526a9149e74006410c05e6d405bd74ffd54d5631ed", size = 31412, upload-time = "2025-12-17T10:49:21.793Z" }, ] [[package]] name = "rignore" version = "0.7.6" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/f5/8bed2310abe4ae04b67a38374a4d311dd85220f5d8da56f47ae9361be0b0/rignore-0.7.6.tar.gz", hash = "sha256:00d3546cd793c30cb17921ce674d2c8f3a4b00501cb0e3dd0e82217dbeba2671", size = 57140, upload-time = "2025-11-05T21:41:21.968Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0b/0e/012556ef3047a2628842b44e753bb15f4dc46806780ff090f1e8fe4bf1eb/rignore-0.7.6-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:03e82348cb7234f8d9b2834f854400ddbbd04c0f8f35495119e66adbd37827a8", size = 883488, upload-time = "2025-11-05T20:42:41.359Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/93/b0/d4f1f3fe9eb3f8e382d45ce5b0547ea01c4b7e0b4b4eb87bcd66a1d2b888/rignore-0.7.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9e624f6be6116ea682e76c5feb71ea91255c67c86cb75befe774365b2931961", size = 820411, upload-time = "2025-11-05T20:42:24.782Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4a/c8/dea564b36dedac8de21c18e1851789545bc52a0c22ece9843444d5608a6a/rignore-0.7.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bda49950d405aa8d0ebe26af807c4e662dd281d926530f03f29690a2e07d649a", size = 897821, upload-time = "2025-11-05T20:40:52.613Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b3/2b/ee96db17ac1835e024c5d0742eefb7e46de60020385ac883dd3d1cde2c1f/rignore-0.7.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5fd5ab3840b8c16851d327ed06e9b8be6459702a53e5ab1fc4073b684b3789e", size = 873963, upload-time = "2025-11-05T20:41:07.49Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a5/8c/ad5a57bbb9d14d5c7e5960f712a8a0b902472ea3f4a2138cbf70d1777b75/rignore-0.7.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ced2a248352636a5c77504cb755dc02c2eef9a820a44d3f33061ce1bb8a7f2d2", size = 1169216, upload-time = "2025-11-05T20:41:23.73Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/80/e6/5b00bc2a6bc1701e6878fca798cf5d9125eb3113193e33078b6fc0d99123/rignore-0.7.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a04a3b73b75ddc12c9c9b21efcdaab33ca3832941d6f1d67bffd860941cd448a", size = 942942, upload-time = "2025-11-05T20:41:39.393Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/85/e5/7f99bd0cc9818a91d0e8b9acc65b792e35750e3bdccd15a7ee75e64efca4/rignore-0.7.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d24321efac92140b7ec910ac7c53ab0f0c86a41133d2bb4b0e6a7c94967f44dd", size = 959787, upload-time = "2025-11-05T20:42:09.765Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/55/54/2ffea79a7c1eabcede1926347ebc2a81bc6b81f447d05b52af9af14948b9/rignore-0.7.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:73c7aa109d41e593785c55fdaa89ad80b10330affa9f9d3e3a51fa695f739b20", size = 984245, upload-time = "2025-11-05T20:41:54.062Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/41/f7/e80f55dfe0f35787fa482aa18689b9c8251e045076c35477deb0007b3277/rignore-0.7.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1734dc49d1e9501b07852ef44421f84d9f378da9fbeda729e77db71f49cac28b", size = 1078647, upload-time = "2025-11-05T21:40:13.463Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d4/cf/2c64f0b6725149f7c6e7e5a909d14354889b4beaadddaa5fff023ec71084/rignore-0.7.6-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5719ea14ea2b652c0c0894be5dfde954e1853a80dea27dd2fbaa749618d837f5", size = 1139186, upload-time = "2025-11-05T21:40:31.27Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/95/a86c84909ccc24af0d094b50d54697951e576c252a4d9f21b47b52af9598/rignore-0.7.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8e23424fc7ce35726854f639cb7968151a792c0c3d9d082f7f67e0c362cfecca", size = 1117604, upload-time = "2025-11-05T21:40:48.07Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7f/5e/13b249613fd5d18d58662490ab910a9f0be758981d1797789913adb4e918/rignore-0.7.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3efdcf1dd84d45f3e2bd2f93303d9be103888f56dfa7c3349b5bf4f0657ec696", size = 1127725, upload-time = "2025-11-05T21:41:05.804Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/28/fa5dcd1e2e16982c359128664e3785f202d3eca9b22dd0b2f91c4b3d242f/rignore-0.7.6-cp312-cp312-win32.whl", hash = "sha256:ccca9d1a8b5234c76b71546fc3c134533b013f40495f394a65614a81f7387046", size = 646145, upload-time = "2025-11-05T21:41:51.096Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/87/69387fb5dd81a0f771936381431780b8cf66fcd2cfe9495e1aaf41548931/rignore-0.7.6-cp312-cp312-win_amd64.whl", hash = "sha256:c96a285e4a8bfec0652e0bfcf42b1aabcdda1e7625f5006d188e3b1c87fdb543", size = 726090, upload-time = "2025-11-05T21:41:36.485Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/24/5f/e8418108dcda8087fb198a6f81caadbcda9fd115d61154bf0df4d6d3619b/rignore-0.7.6-cp312-cp312-win_arm64.whl", hash = "sha256:a64a750e7a8277a323f01ca50b7784a764845f6cce2fe38831cb93f0508d0051", size = 656317, upload-time = "2025-11-05T21:41:25.305Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b7/8a/a4078f6e14932ac7edb171149c481de29969d96ddee3ece5dc4c26f9e0c3/rignore-0.7.6-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:2bdab1d31ec9b4fb1331980ee49ea051c0d7f7bb6baa28b3125ef03cdc48fdaf", size = 883057, upload-time = "2025-11-05T20:42:42.741Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/8f/f8daacd177db4bf7c2223bab41e630c52711f8af9ed279be2058d2fe4982/rignore-0.7.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:90f0a00ce0c866c275bf888271f1dc0d2140f29b82fcf33cdbda1e1a6af01010", size = 820150, upload-time = "2025-11-05T20:42:26.545Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/36/31/b65b837e39c3f7064c426754714ac633b66b8c2290978af9d7f513e14aa9/rignore-0.7.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1ad295537041dc2ed4b540fb1a3906bd9ede6ccdad3fe79770cd89e04e3c73c", size = 897406, upload-time = "2025-11-05T20:40:53.854Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ca/58/1970ce006c427e202ac7c081435719a076c478f07b3a23f469227788dc23/rignore-0.7.6-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f782dbd3a65a5ac85adfff69e5c6b101285ef3f845c3a3cae56a54bebf9fe116", size = 874050, upload-time = "2025-11-05T20:41:08.922Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d4/00/eb45db9f90137329072a732273be0d383cb7d7f50ddc8e0bceea34c1dfdf/rignore-0.7.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65cece3b36e5b0826d946494734c0e6aaf5a0337e18ff55b071438efe13d559e", size = 1167835, upload-time = "2025-11-05T20:41:24.997Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f3/f1/6f1d72ddca41a64eed569680587a1236633587cc9f78136477ae69e2c88a/rignore-0.7.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7e4bb66c13cd7602dc8931822c02dfbbd5252015c750ac5d6152b186f0a8be0", size = 941945, upload-time = "2025-11-05T20:41:40.628Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/48/6f/2f178af1c1a276a065f563ec1e11e7a9e23d4996fd0465516afce4b5c636/rignore-0.7.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:297e500c15766e196f68aaaa70e8b6db85fa23fdc075b880d8231fdfba738cd7", size = 959067, upload-time = "2025-11-05T20:42:11.09Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5b/db/423a81c4c1e173877c7f9b5767dcaf1ab50484a94f60a0b2ed78be3fa765/rignore-0.7.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a07084211a8d35e1a5b1d32b9661a5ed20669970b369df0cf77da3adea3405de", size = 984438, upload-time = "2025-11-05T20:41:55.443Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/eb/c4f92cc3f2825d501d3c46a244a671eb737fc1bcf7b05a3ecd34abb3e0d7/rignore-0.7.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:181eb2a975a22256a1441a9d2f15eb1292839ea3f05606620bd9e1938302cf79", size = 1078365, upload-time = "2025-11-05T21:40:15.148Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/09/99442f02794bd7441bfc8ed1c7319e890449b816a7493b2db0e30af39095/rignore-0.7.6-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:7bbcdc52b5bf9f054b34ce4af5269df5d863d9c2456243338bc193c28022bd7b", size = 1139066, upload-time = "2025-11-05T21:40:32.771Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/88/bcfc21e520bba975410e9419450f4b90a2ac8236b9a80fd8130e87d098af/rignore-0.7.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f2e027a6da21a7c8c0d87553c24ca5cc4364def18d146057862c23a96546238e", size = 1118036, upload-time = "2025-11-05T21:40:49.646Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e2/25/d37215e4562cda5c13312636393aea0bafe38d54d4e0517520a4cc0753ec/rignore-0.7.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee4a18b82cbbc648e4aac1510066682fe62beb5dc88e2c67c53a83954e541360", size = 1127550, upload-time = "2025-11-05T21:41:07.648Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/76/a264ab38bfa1620ec12a8ff1c07778da89e16d8c0f3450b0333020d3d6dc/rignore-0.7.6-cp313-cp313-win32.whl", hash = "sha256:a7d7148b6e5e95035d4390396895adc384d37ff4e06781a36fe573bba7c283e5", size = 646097, upload-time = "2025-11-05T21:41:53.201Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/62/44/3c31b8983c29ea8832b6082ddb1d07b90379c2d993bd20fce4487b71b4f4/rignore-0.7.6-cp313-cp313-win_amd64.whl", hash = "sha256:b037c4b15a64dced08fc12310ee844ec2284c4c5c1ca77bc37d0a04f7bff386e", size = 726170, upload-time = "2025-11-05T21:41:38.131Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/41/e26a075cab83debe41a42661262f606166157df84e0e02e2d904d134c0d8/rignore-0.7.6-cp313-cp313-win_arm64.whl", hash = "sha256:e47443de9b12fe569889bdbe020abe0e0b667516ee2ab435443f6d0869bd2804", size = 656184, upload-time = "2025-11-05T21:41:27.396Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/f5/8bed2310abe4ae04b67a38374a4d311dd85220f5d8da56f47ae9361be0b0/rignore-0.7.6.tar.gz", hash = "sha256:00d3546cd793c30cb17921ce674d2c8f3a4b00501cb0e3dd0e82217dbeba2671", size = 57140, upload-time = "2025-11-05T21:41:21.968Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0b/0e/012556ef3047a2628842b44e753bb15f4dc46806780ff090f1e8fe4bf1eb/rignore-0.7.6-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:03e82348cb7234f8d9b2834f854400ddbbd04c0f8f35495119e66adbd37827a8", size = 883488, upload-time = "2025-11-05T20:42:41.359Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/93/b0/d4f1f3fe9eb3f8e382d45ce5b0547ea01c4b7e0b4b4eb87bcd66a1d2b888/rignore-0.7.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9e624f6be6116ea682e76c5feb71ea91255c67c86cb75befe774365b2931961", size = 820411, upload-time = "2025-11-05T20:42:24.782Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4a/c8/dea564b36dedac8de21c18e1851789545bc52a0c22ece9843444d5608a6a/rignore-0.7.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bda49950d405aa8d0ebe26af807c4e662dd281d926530f03f29690a2e07d649a", size = 897821, upload-time = "2025-11-05T20:40:52.613Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b3/2b/ee96db17ac1835e024c5d0742eefb7e46de60020385ac883dd3d1cde2c1f/rignore-0.7.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5fd5ab3840b8c16851d327ed06e9b8be6459702a53e5ab1fc4073b684b3789e", size = 873963, upload-time = "2025-11-05T20:41:07.49Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a5/8c/ad5a57bbb9d14d5c7e5960f712a8a0b902472ea3f4a2138cbf70d1777b75/rignore-0.7.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ced2a248352636a5c77504cb755dc02c2eef9a820a44d3f33061ce1bb8a7f2d2", size = 1169216, upload-time = "2025-11-05T20:41:23.73Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/80/e6/5b00bc2a6bc1701e6878fca798cf5d9125eb3113193e33078b6fc0d99123/rignore-0.7.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a04a3b73b75ddc12c9c9b21efcdaab33ca3832941d6f1d67bffd860941cd448a", size = 942942, upload-time = "2025-11-05T20:41:39.393Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/85/e5/7f99bd0cc9818a91d0e8b9acc65b792e35750e3bdccd15a7ee75e64efca4/rignore-0.7.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d24321efac92140b7ec910ac7c53ab0f0c86a41133d2bb4b0e6a7c94967f44dd", size = 959787, upload-time = "2025-11-05T20:42:09.765Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/55/54/2ffea79a7c1eabcede1926347ebc2a81bc6b81f447d05b52af9af14948b9/rignore-0.7.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:73c7aa109d41e593785c55fdaa89ad80b10330affa9f9d3e3a51fa695f739b20", size = 984245, upload-time = "2025-11-05T20:41:54.062Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/f7/e80f55dfe0f35787fa482aa18689b9c8251e045076c35477deb0007b3277/rignore-0.7.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1734dc49d1e9501b07852ef44421f84d9f378da9fbeda729e77db71f49cac28b", size = 1078647, upload-time = "2025-11-05T21:40:13.463Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/cf/2c64f0b6725149f7c6e7e5a909d14354889b4beaadddaa5fff023ec71084/rignore-0.7.6-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5719ea14ea2b652c0c0894be5dfde954e1853a80dea27dd2fbaa749618d837f5", size = 1139186, upload-time = "2025-11-05T21:40:31.27Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/95/a86c84909ccc24af0d094b50d54697951e576c252a4d9f21b47b52af9598/rignore-0.7.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8e23424fc7ce35726854f639cb7968151a792c0c3d9d082f7f67e0c362cfecca", size = 1117604, upload-time = "2025-11-05T21:40:48.07Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7f/5e/13b249613fd5d18d58662490ab910a9f0be758981d1797789913adb4e918/rignore-0.7.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3efdcf1dd84d45f3e2bd2f93303d9be103888f56dfa7c3349b5bf4f0657ec696", size = 1127725, upload-time = "2025-11-05T21:41:05.804Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/28/fa5dcd1e2e16982c359128664e3785f202d3eca9b22dd0b2f91c4b3d242f/rignore-0.7.6-cp312-cp312-win32.whl", hash = "sha256:ccca9d1a8b5234c76b71546fc3c134533b013f40495f394a65614a81f7387046", size = 646145, upload-time = "2025-11-05T21:41:51.096Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/87/69387fb5dd81a0f771936381431780b8cf66fcd2cfe9495e1aaf41548931/rignore-0.7.6-cp312-cp312-win_amd64.whl", hash = "sha256:c96a285e4a8bfec0652e0bfcf42b1aabcdda1e7625f5006d188e3b1c87fdb543", size = 726090, upload-time = "2025-11-05T21:41:36.485Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/24/5f/e8418108dcda8087fb198a6f81caadbcda9fd115d61154bf0df4d6d3619b/rignore-0.7.6-cp312-cp312-win_arm64.whl", hash = "sha256:a64a750e7a8277a323f01ca50b7784a764845f6cce2fe38831cb93f0508d0051", size = 656317, upload-time = "2025-11-05T21:41:25.305Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/8a/a4078f6e14932ac7edb171149c481de29969d96ddee3ece5dc4c26f9e0c3/rignore-0.7.6-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:2bdab1d31ec9b4fb1331980ee49ea051c0d7f7bb6baa28b3125ef03cdc48fdaf", size = 883057, upload-time = "2025-11-05T20:42:42.741Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/8f/f8daacd177db4bf7c2223bab41e630c52711f8af9ed279be2058d2fe4982/rignore-0.7.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:90f0a00ce0c866c275bf888271f1dc0d2140f29b82fcf33cdbda1e1a6af01010", size = 820150, upload-time = "2025-11-05T20:42:26.545Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/36/31/b65b837e39c3f7064c426754714ac633b66b8c2290978af9d7f513e14aa9/rignore-0.7.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1ad295537041dc2ed4b540fb1a3906bd9ede6ccdad3fe79770cd89e04e3c73c", size = 897406, upload-time = "2025-11-05T20:40:53.854Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/58/1970ce006c427e202ac7c081435719a076c478f07b3a23f469227788dc23/rignore-0.7.6-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f782dbd3a65a5ac85adfff69e5c6b101285ef3f845c3a3cae56a54bebf9fe116", size = 874050, upload-time = "2025-11-05T20:41:08.922Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/00/eb45db9f90137329072a732273be0d383cb7d7f50ddc8e0bceea34c1dfdf/rignore-0.7.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65cece3b36e5b0826d946494734c0e6aaf5a0337e18ff55b071438efe13d559e", size = 1167835, upload-time = "2025-11-05T20:41:24.997Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/f1/6f1d72ddca41a64eed569680587a1236633587cc9f78136477ae69e2c88a/rignore-0.7.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7e4bb66c13cd7602dc8931822c02dfbbd5252015c750ac5d6152b186f0a8be0", size = 941945, upload-time = "2025-11-05T20:41:40.628Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/48/6f/2f178af1c1a276a065f563ec1e11e7a9e23d4996fd0465516afce4b5c636/rignore-0.7.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:297e500c15766e196f68aaaa70e8b6db85fa23fdc075b880d8231fdfba738cd7", size = 959067, upload-time = "2025-11-05T20:42:11.09Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5b/db/423a81c4c1e173877c7f9b5767dcaf1ab50484a94f60a0b2ed78be3fa765/rignore-0.7.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a07084211a8d35e1a5b1d32b9661a5ed20669970b369df0cf77da3adea3405de", size = 984438, upload-time = "2025-11-05T20:41:55.443Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/eb/c4f92cc3f2825d501d3c46a244a671eb737fc1bcf7b05a3ecd34abb3e0d7/rignore-0.7.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:181eb2a975a22256a1441a9d2f15eb1292839ea3f05606620bd9e1938302cf79", size = 1078365, upload-time = "2025-11-05T21:40:15.148Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/09/99442f02794bd7441bfc8ed1c7319e890449b816a7493b2db0e30af39095/rignore-0.7.6-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:7bbcdc52b5bf9f054b34ce4af5269df5d863d9c2456243338bc193c28022bd7b", size = 1139066, upload-time = "2025-11-05T21:40:32.771Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/88/bcfc21e520bba975410e9419450f4b90a2ac8236b9a80fd8130e87d098af/rignore-0.7.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f2e027a6da21a7c8c0d87553c24ca5cc4364def18d146057862c23a96546238e", size = 1118036, upload-time = "2025-11-05T21:40:49.646Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e2/25/d37215e4562cda5c13312636393aea0bafe38d54d4e0517520a4cc0753ec/rignore-0.7.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee4a18b82cbbc648e4aac1510066682fe62beb5dc88e2c67c53a83954e541360", size = 1127550, upload-time = "2025-11-05T21:41:07.648Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/76/a264ab38bfa1620ec12a8ff1c07778da89e16d8c0f3450b0333020d3d6dc/rignore-0.7.6-cp313-cp313-win32.whl", hash = "sha256:a7d7148b6e5e95035d4390396895adc384d37ff4e06781a36fe573bba7c283e5", size = 646097, upload-time = "2025-11-05T21:41:53.201Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/44/3c31b8983c29ea8832b6082ddb1d07b90379c2d993bd20fce4487b71b4f4/rignore-0.7.6-cp313-cp313-win_amd64.whl", hash = "sha256:b037c4b15a64dced08fc12310ee844ec2284c4c5c1ca77bc37d0a04f7bff386e", size = 726170, upload-time = "2025-11-05T21:41:38.131Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/41/e26a075cab83debe41a42661262f606166157df84e0e02e2d904d134c0d8/rignore-0.7.6-cp313-cp313-win_arm64.whl", hash = "sha256:e47443de9b12fe569889bdbe020abe0e0b667516ee2ab435443f6d0869bd2804", size = 656184, upload-time = "2025-11-05T21:41:27.396Z" }, ] [[package]] name = "rpds-py" version = "0.30.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/03/e7/98a2f4ac921d82f33e03f3835f5bf3a4a40aa1bfdc57975e74a97b2b4bdd/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad", size = 375086, upload-time = "2025-11-30T20:22:17.93Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4d/a1/bca7fd3d452b272e13335db8d6b0b3ecde0f90ad6f16f3328c6fb150c889/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05", size = 359053, upload-time = "2025-11-30T20:22:19.297Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/65/1c/ae157e83a6357eceff62ba7e52113e3ec4834a84cfe07fa4b0757a7d105f/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28", size = 390763, upload-time = "2025-11-30T20:22:21.661Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d4/36/eb2eb8515e2ad24c0bd43c3ee9cd74c33f7ca6430755ccdb240fd3144c44/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd", size = 408951, upload-time = "2025-11-30T20:22:23.408Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d6/65/ad8dc1784a331fabbd740ef6f71ce2198c7ed0890dab595adb9ea2d775a1/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f", size = 514622, upload-time = "2025-11-30T20:22:25.16Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/63/8e/0cfa7ae158e15e143fe03993b5bcd743a59f541f5952e1546b1ac1b5fd45/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1", size = 414492, upload-time = "2025-11-30T20:22:26.505Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/60/1b/6f8f29f3f995c7ffdde46a626ddccd7c63aefc0efae881dc13b6e5d5bb16/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23", size = 394080, upload-time = "2025-11-30T20:22:27.934Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6d/d5/a266341051a7a3ca2f4b750a3aa4abc986378431fc2da508c5034d081b70/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6", size = 408680, upload-time = "2025-11-30T20:22:29.341Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/10/3b/71b725851df9ab7a7a4e33cf36d241933da66040d195a84781f49c50490c/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51", size = 423589, upload-time = "2025-11-30T20:22:31.469Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/00/2b/e59e58c544dc9bd8bd8384ecdb8ea91f6727f0e37a7131baeff8d6f51661/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5", size = 573289, upload-time = "2025-11-30T20:22:32.997Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/3e/a18e6f5b460893172a7d6a680e86d3b6bc87a54c1f0b03446a3c8c7b588f/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e", size = 599737, upload-time = "2025-11-30T20:22:34.419Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5c/e2/714694e4b87b85a18e2c243614974413c60aa107fd815b8cbc42b873d1d7/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394", size = 563120, upload-time = "2025-11-30T20:22:35.903Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6f/ab/d5d5e3bcedb0a77f4f613706b750e50a5a3ba1c15ccd3665ecc636c968fd/rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf", size = 223782, upload-time = "2025-11-30T20:22:37.271Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/39/3b/f786af9957306fdc38a74cef405b7b93180f481fb48453a114bb6465744a/rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b", size = 240463, upload-time = "2025-11-30T20:22:39.021Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f3/d2/b91dc748126c1559042cfe41990deb92c4ee3e2b415f6b5234969ffaf0cc/rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e", size = 230868, upload-time = "2025-11-30T20:22:40.493Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/03/e7/98a2f4ac921d82f33e03f3835f5bf3a4a40aa1bfdc57975e74a97b2b4bdd/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad", size = 375086, upload-time = "2025-11-30T20:22:17.93Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4d/a1/bca7fd3d452b272e13335db8d6b0b3ecde0f90ad6f16f3328c6fb150c889/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05", size = 359053, upload-time = "2025-11-30T20:22:19.297Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/65/1c/ae157e83a6357eceff62ba7e52113e3ec4834a84cfe07fa4b0757a7d105f/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28", size = 390763, upload-time = "2025-11-30T20:22:21.661Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/36/eb2eb8515e2ad24c0bd43c3ee9cd74c33f7ca6430755ccdb240fd3144c44/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd", size = 408951, upload-time = "2025-11-30T20:22:23.408Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/65/ad8dc1784a331fabbd740ef6f71ce2198c7ed0890dab595adb9ea2d775a1/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f", size = 514622, upload-time = "2025-11-30T20:22:25.16Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/63/8e/0cfa7ae158e15e143fe03993b5bcd743a59f541f5952e1546b1ac1b5fd45/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1", size = 414492, upload-time = "2025-11-30T20:22:26.505Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/60/1b/6f8f29f3f995c7ffdde46a626ddccd7c63aefc0efae881dc13b6e5d5bb16/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23", size = 394080, upload-time = "2025-11-30T20:22:27.934Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6d/d5/a266341051a7a3ca2f4b750a3aa4abc986378431fc2da508c5034d081b70/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6", size = 408680, upload-time = "2025-11-30T20:22:29.341Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/10/3b/71b725851df9ab7a7a4e33cf36d241933da66040d195a84781f49c50490c/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51", size = 423589, upload-time = "2025-11-30T20:22:31.469Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/00/2b/e59e58c544dc9bd8bd8384ecdb8ea91f6727f0e37a7131baeff8d6f51661/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5", size = 573289, upload-time = "2025-11-30T20:22:32.997Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/3e/a18e6f5b460893172a7d6a680e86d3b6bc87a54c1f0b03446a3c8c7b588f/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e", size = 599737, upload-time = "2025-11-30T20:22:34.419Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/e2/714694e4b87b85a18e2c243614974413c60aa107fd815b8cbc42b873d1d7/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394", size = 563120, upload-time = "2025-11-30T20:22:35.903Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6f/ab/d5d5e3bcedb0a77f4f613706b750e50a5a3ba1c15ccd3665ecc636c968fd/rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf", size = 223782, upload-time = "2025-11-30T20:22:37.271Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/3b/f786af9957306fdc38a74cef405b7b93180f481fb48453a114bb6465744a/rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b", size = 240463, upload-time = "2025-11-30T20:22:39.021Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/d2/b91dc748126c1559042cfe41990deb92c4ee3e2b415f6b5234969ffaf0cc/rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e", size = 230868, upload-time = "2025-11-30T20:22:40.493Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, ] [[package]] name = "rsa" version = "4.9.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "pyasn1" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, ] [[package]] name = "ruamel-yaml" version = "0.18.10" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "ruamel-yaml-clib", marker = "python_full_version < '3.13' and platform_python_implementation == 'CPython'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/46/f44d8be06b85bc7c4d8c95d658be2b68f27711f279bf9dd0612a5e4794f5/ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58", size = 143447, upload-time = "2025-01-06T14:08:51.334Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/46/f44d8be06b85bc7c4d8c95d658be2b68f27711f279bf9dd0612a5e4794f5/ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58", size = 143447, upload-time = "2025-01-06T14:08:51.334Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c2/36/dfc1ebc0081e6d39924a2cc53654497f967a084a436bb64402dfce4254d9/ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1", size = 117729, upload-time = "2025-01-06T14:08:47.471Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/36/dfc1ebc0081e6d39924a2cc53654497f967a084a436bb64402dfce4254d9/ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1", size = 117729, upload-time = "2025-01-06T14:08:47.471Z" }, ] [[package]] name = "ruamel-yaml-clib" version = "0.2.15" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/97/60fda20e2fb54b83a61ae14648b0817c8f5d84a3821e40bfbdae1437026a/ruamel_yaml_clib-0.2.15.tar.gz", hash = "sha256:46e4cc8c43ef6a94885f72512094e482114a8a706d3c555a34ed4b0d20200600", size = 225794, upload-time = "2025-11-16T16:12:59.761Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/72/4b/5fde11a0722d676e469d3d6f78c6a17591b9c7e0072ca359801c4bd17eee/ruamel_yaml_clib-0.2.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cb15a2e2a90c8475df45c0949793af1ff413acfb0a716b8b94e488ea95ce7cff", size = 149088, upload-time = "2025-11-16T16:13:22.836Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/85/82/4d08ac65ecf0ef3b046421985e66301a242804eb9a62c93ca3437dc94ee0/ruamel_yaml_clib-0.2.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:64da03cbe93c1e91af133f5bec37fd24d0d4ba2418eaf970d7166b0a26a148a2", size = 134553, upload-time = "2025-11-16T16:13:24.151Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b9/cb/22366d68b280e281a932403b76da7a988108287adff2bfa5ce881200107a/ruamel_yaml_clib-0.2.15-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f6d3655e95a80325b84c4e14c080b2470fe4f33b6846f288379ce36154993fb1", size = 737468, upload-time = "2025-11-16T20:22:47.335Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/71/73/81230babf8c9e33770d43ed9056f603f6f5f9665aea4177a2c30ae48e3f3/ruamel_yaml_clib-0.2.15-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:71845d377c7a47afc6592aacfea738cc8a7e876d586dfba814501d8c53c1ba60", size = 753349, upload-time = "2025-11-16T16:13:26.269Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/62/150c841f24cda9e30f588ef396ed83f64cfdc13b92d2f925bb96df337ba9/ruamel_yaml_clib-0.2.15-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11e5499db1ccbc7f4b41f0565e4f799d863ea720e01d3e99fa0b7b5fcd7802c9", size = 788211, upload-time = "2025-11-16T16:13:27.441Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/30/93/e79bd9cbecc3267499d9ead919bd61f7ddf55d793fb5ef2b1d7d92444f35/ruamel_yaml_clib-0.2.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4b293a37dc97e2b1e8a1aec62792d1e52027087c8eea4fc7b5abd2bdafdd6642", size = 743203, upload-time = "2025-11-16T16:13:28.671Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8d/06/1eb640065c3a27ce92d76157f8efddb184bd484ed2639b712396a20d6dce/ruamel_yaml_clib-0.2.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:512571ad41bba04eac7268fe33f7f4742210ca26a81fe0c75357fa682636c690", size = 747292, upload-time = "2025-11-16T20:22:48.584Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a5/21/ee353e882350beab65fcc47a91b6bdc512cace4358ee327af2962892ff16/ruamel_yaml_clib-0.2.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5e9f630c73a490b758bf14d859a39f375e6999aea5ddd2e2e9da89b9953486a", size = 771624, upload-time = "2025-11-16T16:13:29.853Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/57/34/cc1b94057aa867c963ecf9ea92ac59198ec2ee3a8d22a126af0b4d4be712/ruamel_yaml_clib-0.2.15-cp312-cp312-win32.whl", hash = "sha256:f4421ab780c37210a07d138e56dd4b51f8642187cdfb433eb687fe8c11de0144", size = 100342, upload-time = "2025-11-16T16:13:31.067Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b3/e5/8925a4208f131b218f9a7e459c0d6fcac8324ae35da269cb437894576366/ruamel_yaml_clib-0.2.15-cp312-cp312-win_amd64.whl", hash = "sha256:2b216904750889133d9222b7b873c199d48ecbb12912aca78970f84a5aa1a4bc", size = 119013, upload-time = "2025-11-16T16:13:32.164Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/17/5e/2f970ce4c573dc30c2f95825f2691c96d55560268ddc67603dc6ea2dd08e/ruamel_yaml_clib-0.2.15-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4dcec721fddbb62e60c2801ba08c87010bd6b700054a09998c4d09c08147b8fb", size = 147450, upload-time = "2025-11-16T16:13:33.542Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d6/03/a1baa5b94f71383913f21b96172fb3a2eb5576a4637729adbf7cd9f797f8/ruamel_yaml_clib-0.2.15-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:65f48245279f9bb301d1276f9679b82e4c080a1ae25e679f682ac62446fac471", size = 133139, upload-time = "2025-11-16T16:13:34.587Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/19/40d676802390f85784235a05788fd28940923382e3f8b943d25febbb98b7/ruamel_yaml_clib-0.2.15-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:46895c17ead5e22bea5e576f1db7e41cb273e8d062c04a6a49013d9f60996c25", size = 731474, upload-time = "2025-11-16T20:22:49.934Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/bb/6ef5abfa43b48dd55c30d53e997f8f978722f02add61efba31380d73e42e/ruamel_yaml_clib-0.2.15-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3eb199178b08956e5be6288ee0b05b2fb0b5c1f309725ad25d9c6ea7e27f962a", size = 748047, upload-time = "2025-11-16T16:13:35.633Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/5d/e4f84c9c448613e12bd62e90b23aa127ea4c46b697f3d760acc32cb94f25/ruamel_yaml_clib-0.2.15-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d1032919280ebc04a80e4fb1e93f7a738129857eaec9448310e638c8bccefcf", size = 782129, upload-time = "2025-11-16T16:13:36.781Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/de/4b/e98086e88f76c00c88a6bcf15eae27a1454f661a9eb72b111e6bbb69024d/ruamel_yaml_clib-0.2.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab0df0648d86a7ecbd9c632e8f8d6b21bb21b5fc9d9e095c796cacf32a728d2d", size = 736848, upload-time = "2025-11-16T16:13:37.952Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0c/5c/5964fcd1fd9acc53b7a3a5d9a05ea4f95ead9495d980003a557deb9769c7/ruamel_yaml_clib-0.2.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:331fb180858dd8534f0e61aa243b944f25e73a4dae9962bd44c46d1761126bbf", size = 741630, upload-time = "2025-11-16T20:22:51.718Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/07/1e/99660f5a30fceb58494598e7d15df883a07292346ef5696f0c0ae5dee8c6/ruamel_yaml_clib-0.2.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fd4c928ddf6bce586285daa6d90680b9c291cfd045fc40aad34e445d57b1bf51", size = 766619, upload-time = "2025-11-16T16:13:39.178Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/36/2f/fa0344a9327b58b54970e56a27b32416ffbcfe4dcc0700605516708579b2/ruamel_yaml_clib-0.2.15-cp313-cp313-win32.whl", hash = "sha256:bf0846d629e160223805db9fe8cc7aec16aaa11a07310c50c8c7164efa440aec", size = 100171, upload-time = "2025-11-16T16:13:40.456Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/c4/c124fbcef0684fcf3c9b72374c2a8c35c94464d8694c50f37eef27f5a145/ruamel_yaml_clib-0.2.15-cp313-cp313-win_amd64.whl", hash = "sha256:45702dfbea1420ba3450bb3dd9a80b33f0badd57539c6aac09f42584303e0db6", size = 118845, upload-time = "2025-11-16T16:13:41.481Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/97/60fda20e2fb54b83a61ae14648b0817c8f5d84a3821e40bfbdae1437026a/ruamel_yaml_clib-0.2.15.tar.gz", hash = "sha256:46e4cc8c43ef6a94885f72512094e482114a8a706d3c555a34ed4b0d20200600", size = 225794, upload-time = "2025-11-16T16:12:59.761Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/4b/5fde11a0722d676e469d3d6f78c6a17591b9c7e0072ca359801c4bd17eee/ruamel_yaml_clib-0.2.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cb15a2e2a90c8475df45c0949793af1ff413acfb0a716b8b94e488ea95ce7cff", size = 149088, upload-time = "2025-11-16T16:13:22.836Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/85/82/4d08ac65ecf0ef3b046421985e66301a242804eb9a62c93ca3437dc94ee0/ruamel_yaml_clib-0.2.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:64da03cbe93c1e91af133f5bec37fd24d0d4ba2418eaf970d7166b0a26a148a2", size = 134553, upload-time = "2025-11-16T16:13:24.151Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/cb/22366d68b280e281a932403b76da7a988108287adff2bfa5ce881200107a/ruamel_yaml_clib-0.2.15-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f6d3655e95a80325b84c4e14c080b2470fe4f33b6846f288379ce36154993fb1", size = 737468, upload-time = "2025-11-16T20:22:47.335Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/73/81230babf8c9e33770d43ed9056f603f6f5f9665aea4177a2c30ae48e3f3/ruamel_yaml_clib-0.2.15-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:71845d377c7a47afc6592aacfea738cc8a7e876d586dfba814501d8c53c1ba60", size = 753349, upload-time = "2025-11-16T16:13:26.269Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/62/150c841f24cda9e30f588ef396ed83f64cfdc13b92d2f925bb96df337ba9/ruamel_yaml_clib-0.2.15-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11e5499db1ccbc7f4b41f0565e4f799d863ea720e01d3e99fa0b7b5fcd7802c9", size = 788211, upload-time = "2025-11-16T16:13:27.441Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/30/93/e79bd9cbecc3267499d9ead919bd61f7ddf55d793fb5ef2b1d7d92444f35/ruamel_yaml_clib-0.2.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4b293a37dc97e2b1e8a1aec62792d1e52027087c8eea4fc7b5abd2bdafdd6642", size = 743203, upload-time = "2025-11-16T16:13:28.671Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8d/06/1eb640065c3a27ce92d76157f8efddb184bd484ed2639b712396a20d6dce/ruamel_yaml_clib-0.2.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:512571ad41bba04eac7268fe33f7f4742210ca26a81fe0c75357fa682636c690", size = 747292, upload-time = "2025-11-16T20:22:48.584Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a5/21/ee353e882350beab65fcc47a91b6bdc512cace4358ee327af2962892ff16/ruamel_yaml_clib-0.2.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5e9f630c73a490b758bf14d859a39f375e6999aea5ddd2e2e9da89b9953486a", size = 771624, upload-time = "2025-11-16T16:13:29.853Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/57/34/cc1b94057aa867c963ecf9ea92ac59198ec2ee3a8d22a126af0b4d4be712/ruamel_yaml_clib-0.2.15-cp312-cp312-win32.whl", hash = "sha256:f4421ab780c37210a07d138e56dd4b51f8642187cdfb433eb687fe8c11de0144", size = 100342, upload-time = "2025-11-16T16:13:31.067Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b3/e5/8925a4208f131b218f9a7e459c0d6fcac8324ae35da269cb437894576366/ruamel_yaml_clib-0.2.15-cp312-cp312-win_amd64.whl", hash = "sha256:2b216904750889133d9222b7b873c199d48ecbb12912aca78970f84a5aa1a4bc", size = 119013, upload-time = "2025-11-16T16:13:32.164Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/17/5e/2f970ce4c573dc30c2f95825f2691c96d55560268ddc67603dc6ea2dd08e/ruamel_yaml_clib-0.2.15-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4dcec721fddbb62e60c2801ba08c87010bd6b700054a09998c4d09c08147b8fb", size = 147450, upload-time = "2025-11-16T16:13:33.542Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/03/a1baa5b94f71383913f21b96172fb3a2eb5576a4637729adbf7cd9f797f8/ruamel_yaml_clib-0.2.15-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:65f48245279f9bb301d1276f9679b82e4c080a1ae25e679f682ac62446fac471", size = 133139, upload-time = "2025-11-16T16:13:34.587Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/19/40d676802390f85784235a05788fd28940923382e3f8b943d25febbb98b7/ruamel_yaml_clib-0.2.15-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:46895c17ead5e22bea5e576f1db7e41cb273e8d062c04a6a49013d9f60996c25", size = 731474, upload-time = "2025-11-16T20:22:49.934Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/bb/6ef5abfa43b48dd55c30d53e997f8f978722f02add61efba31380d73e42e/ruamel_yaml_clib-0.2.15-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3eb199178b08956e5be6288ee0b05b2fb0b5c1f309725ad25d9c6ea7e27f962a", size = 748047, upload-time = "2025-11-16T16:13:35.633Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/5d/e4f84c9c448613e12bd62e90b23aa127ea4c46b697f3d760acc32cb94f25/ruamel_yaml_clib-0.2.15-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d1032919280ebc04a80e4fb1e93f7a738129857eaec9448310e638c8bccefcf", size = 782129, upload-time = "2025-11-16T16:13:36.781Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/de/4b/e98086e88f76c00c88a6bcf15eae27a1454f661a9eb72b111e6bbb69024d/ruamel_yaml_clib-0.2.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab0df0648d86a7ecbd9c632e8f8d6b21bb21b5fc9d9e095c796cacf32a728d2d", size = 736848, upload-time = "2025-11-16T16:13:37.952Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0c/5c/5964fcd1fd9acc53b7a3a5d9a05ea4f95ead9495d980003a557deb9769c7/ruamel_yaml_clib-0.2.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:331fb180858dd8534f0e61aa243b944f25e73a4dae9962bd44c46d1761126bbf", size = 741630, upload-time = "2025-11-16T20:22:51.718Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/07/1e/99660f5a30fceb58494598e7d15df883a07292346ef5696f0c0ae5dee8c6/ruamel_yaml_clib-0.2.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fd4c928ddf6bce586285daa6d90680b9c291cfd045fc40aad34e445d57b1bf51", size = 766619, upload-time = "2025-11-16T16:13:39.178Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/36/2f/fa0344a9327b58b54970e56a27b32416ffbcfe4dcc0700605516708579b2/ruamel_yaml_clib-0.2.15-cp313-cp313-win32.whl", hash = "sha256:bf0846d629e160223805db9fe8cc7aec16aaa11a07310c50c8c7164efa440aec", size = 100171, upload-time = "2025-11-16T16:13:40.456Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/c4/c124fbcef0684fcf3c9b72374c2a8c35c94464d8694c50f37eef27f5a145/ruamel_yaml_clib-0.2.15-cp313-cp313-win_amd64.whl", hash = "sha256:45702dfbea1420ba3450bb3dd9a80b33f0badd57539c6aac09f42584303e0db6", size = 118845, upload-time = "2025-11-16T16:13:41.481Z" }, ] [[package]] name = "ruff" version = "0.14.10" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/57/08/52232a877978dd8f9cf2aeddce3e611b40a63287dfca29b6b8da791f5e8d/ruff-0.14.10.tar.gz", hash = "sha256:9a2e830f075d1a42cd28420d7809ace390832a490ed0966fe373ba288e77aaf4", size = 5859763, upload-time = "2025-12-18T19:28:57.98Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/60/01/933704d69f3f05ee16ef11406b78881733c186fe14b6a46b05cfcaf6d3b2/ruff-0.14.10-py3-none-linux_armv6l.whl", hash = "sha256:7a3ce585f2ade3e1f29ec1b92df13e3da262178df8c8bdf876f48fa0e8316c49", size = 13527080, upload-time = "2025-12-18T19:29:25.642Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/df/58/a0349197a7dfa603ffb7f5b0470391efa79ddc327c1e29c4851e85b09cc5/ruff-0.14.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:674f9be9372907f7257c51f1d4fc902cb7cf014b9980152b802794317941f08f", size = 13797320, upload-time = "2025-12-18T19:29:02.571Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7b/82/36be59f00a6082e38c23536df4e71cdbc6af8d7c707eade97fcad5c98235/ruff-0.14.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d85713d522348837ef9df8efca33ccb8bd6fcfc86a2cde3ccb4bc9d28a18003d", size = 12918434, upload-time = "2025-12-18T19:28:51.202Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a6/00/45c62a7f7e34da92a25804f813ebe05c88aa9e0c25e5cb5a7d23dd7450e3/ruff-0.14.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6987ebe0501ae4f4308d7d24e2d0fe3d7a98430f5adfd0f1fead050a740a3a77", size = 13371961, upload-time = "2025-12-18T19:29:04.991Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/40/31/a5906d60f0405f7e57045a70f2d57084a93ca7425f22e1d66904769d1628/ruff-0.14.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16a01dfb7b9e4eee556fbfd5392806b1b8550c9b4a9f6acd3dbe6812b193c70a", size = 13275629, upload-time = "2025-12-18T19:29:21.381Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3e/60/61c0087df21894cf9d928dc04bcd4fb10e8b2e8dca7b1a276ba2155b2002/ruff-0.14.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7165d31a925b7a294465fa81be8c12a0e9b60fb02bf177e79067c867e71f8b1f", size = 14029234, upload-time = "2025-12-18T19:29:00.132Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/44/84/77d911bee3b92348b6e5dab5a0c898d87084ea03ac5dc708f46d88407def/ruff-0.14.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c561695675b972effb0c0a45db233f2c816ff3da8dcfbe7dfc7eed625f218935", size = 15449890, upload-time = "2025-12-18T19:28:53.573Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/36/480206eaefa24a7ec321582dda580443a8f0671fdbf6b1c80e9c3e93a16a/ruff-0.14.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bb98fcbbc61725968893682fd4df8966a34611239c9fd07a1f6a07e7103d08e", size = 15123172, upload-time = "2025-12-18T19:29:23.453Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5c/38/68e414156015ba80cef5473d57919d27dfb62ec804b96180bafdeaf0e090/ruff-0.14.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f24b47993a9d8cb858429e97bdf8544c78029f09b520af615c1d261bf827001d", size = 14460260, upload-time = "2025-12-18T19:29:27.808Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b3/19/9e050c0dca8aba824d67cc0db69fb459c28d8cd3f6855b1405b3f29cc91d/ruff-0.14.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59aabd2e2c4fd614d2862e7939c34a532c04f1084476d6833dddef4afab87e9f", size = 14229978, upload-time = "2025-12-18T19:29:11.32Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/51/eb/e8dd1dd6e05b9e695aa9dd420f4577debdd0f87a5ff2fedda33c09e9be8c/ruff-0.14.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:213db2b2e44be8625002dbea33bb9c60c66ea2c07c084a00d55732689d697a7f", size = 14338036, upload-time = "2025-12-18T19:29:09.184Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/12/f3e3a505db7c19303b70af370d137795fcfec136d670d5de5391e295c134/ruff-0.14.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b914c40ab64865a17a9a5b67911d14df72346a634527240039eb3bd650e5979d", size = 13264051, upload-time = "2025-12-18T19:29:13.431Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/08/64/8c3a47eaccfef8ac20e0484e68e0772013eb85802f8a9f7603ca751eb166/ruff-0.14.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1484983559f026788e3a5c07c81ef7d1e97c1c78ed03041a18f75df104c45405", size = 13283998, upload-time = "2025-12-18T19:29:06.994Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/12/84/534a5506f4074e5cc0529e5cd96cfc01bb480e460c7edf5af70d2bcae55e/ruff-0.14.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c70427132db492d25f982fffc8d6c7535cc2fd2c83fc8888f05caaa248521e60", size = 13601891, upload-time = "2025-12-18T19:28:55.811Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0d/1e/14c916087d8598917dbad9b2921d340f7884824ad6e9c55de948a93b106d/ruff-0.14.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5bcf45b681e9f1ee6445d317ce1fa9d6cba9a6049542d1c3d5b5958986be8830", size = 14336660, upload-time = "2025-12-18T19:29:16.531Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f2/1c/d7b67ab43f30013b47c12b42d1acd354c195351a3f7a1d67f59e54227ede/ruff-0.14.10-py3-none-win32.whl", hash = "sha256:104c49fc7ab73f3f3a758039adea978869a918f31b73280db175b43a2d9b51d6", size = 13196187, upload-time = "2025-12-18T19:29:19.006Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fb/9c/896c862e13886fae2af961bef3e6312db9ebc6adc2b156fe95e615dee8c1/ruff-0.14.10-py3-none-win_amd64.whl", hash = "sha256:466297bd73638c6bdf06485683e812db1c00c7ac96d4ddd0294a338c62fdc154", size = 14661283, upload-time = "2025-12-18T19:29:30.16Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/74/31/b0e29d572670dca3674eeee78e418f20bdf97fa8aa9ea71380885e175ca0/ruff-0.14.10-py3-none-win_arm64.whl", hash = "sha256:e51d046cf6dda98a4633b8a8a771451107413b0f07183b2bef03f075599e44e6", size = 13729839, upload-time = "2025-12-18T19:28:48.636Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/57/08/52232a877978dd8f9cf2aeddce3e611b40a63287dfca29b6b8da791f5e8d/ruff-0.14.10.tar.gz", hash = "sha256:9a2e830f075d1a42cd28420d7809ace390832a490ed0966fe373ba288e77aaf4", size = 5859763, upload-time = "2025-12-18T19:28:57.98Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/60/01/933704d69f3f05ee16ef11406b78881733c186fe14b6a46b05cfcaf6d3b2/ruff-0.14.10-py3-none-linux_armv6l.whl", hash = "sha256:7a3ce585f2ade3e1f29ec1b92df13e3da262178df8c8bdf876f48fa0e8316c49", size = 13527080, upload-time = "2025-12-18T19:29:25.642Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/58/a0349197a7dfa603ffb7f5b0470391efa79ddc327c1e29c4851e85b09cc5/ruff-0.14.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:674f9be9372907f7257c51f1d4fc902cb7cf014b9980152b802794317941f08f", size = 13797320, upload-time = "2025-12-18T19:29:02.571Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7b/82/36be59f00a6082e38c23536df4e71cdbc6af8d7c707eade97fcad5c98235/ruff-0.14.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d85713d522348837ef9df8efca33ccb8bd6fcfc86a2cde3ccb4bc9d28a18003d", size = 12918434, upload-time = "2025-12-18T19:28:51.202Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a6/00/45c62a7f7e34da92a25804f813ebe05c88aa9e0c25e5cb5a7d23dd7450e3/ruff-0.14.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6987ebe0501ae4f4308d7d24e2d0fe3d7a98430f5adfd0f1fead050a740a3a77", size = 13371961, upload-time = "2025-12-18T19:29:04.991Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/40/31/a5906d60f0405f7e57045a70f2d57084a93ca7425f22e1d66904769d1628/ruff-0.14.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16a01dfb7b9e4eee556fbfd5392806b1b8550c9b4a9f6acd3dbe6812b193c70a", size = 13275629, upload-time = "2025-12-18T19:29:21.381Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3e/60/61c0087df21894cf9d928dc04bcd4fb10e8b2e8dca7b1a276ba2155b2002/ruff-0.14.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7165d31a925b7a294465fa81be8c12a0e9b60fb02bf177e79067c867e71f8b1f", size = 14029234, upload-time = "2025-12-18T19:29:00.132Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/44/84/77d911bee3b92348b6e5dab5a0c898d87084ea03ac5dc708f46d88407def/ruff-0.14.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c561695675b972effb0c0a45db233f2c816ff3da8dcfbe7dfc7eed625f218935", size = 15449890, upload-time = "2025-12-18T19:28:53.573Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/36/480206eaefa24a7ec321582dda580443a8f0671fdbf6b1c80e9c3e93a16a/ruff-0.14.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bb98fcbbc61725968893682fd4df8966a34611239c9fd07a1f6a07e7103d08e", size = 15123172, upload-time = "2025-12-18T19:29:23.453Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/38/68e414156015ba80cef5473d57919d27dfb62ec804b96180bafdeaf0e090/ruff-0.14.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f24b47993a9d8cb858429e97bdf8544c78029f09b520af615c1d261bf827001d", size = 14460260, upload-time = "2025-12-18T19:29:27.808Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b3/19/9e050c0dca8aba824d67cc0db69fb459c28d8cd3f6855b1405b3f29cc91d/ruff-0.14.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59aabd2e2c4fd614d2862e7939c34a532c04f1084476d6833dddef4afab87e9f", size = 14229978, upload-time = "2025-12-18T19:29:11.32Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/51/eb/e8dd1dd6e05b9e695aa9dd420f4577debdd0f87a5ff2fedda33c09e9be8c/ruff-0.14.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:213db2b2e44be8625002dbea33bb9c60c66ea2c07c084a00d55732689d697a7f", size = 14338036, upload-time = "2025-12-18T19:29:09.184Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/12/f3e3a505db7c19303b70af370d137795fcfec136d670d5de5391e295c134/ruff-0.14.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b914c40ab64865a17a9a5b67911d14df72346a634527240039eb3bd650e5979d", size = 13264051, upload-time = "2025-12-18T19:29:13.431Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/08/64/8c3a47eaccfef8ac20e0484e68e0772013eb85802f8a9f7603ca751eb166/ruff-0.14.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1484983559f026788e3a5c07c81ef7d1e97c1c78ed03041a18f75df104c45405", size = 13283998, upload-time = "2025-12-18T19:29:06.994Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/12/84/534a5506f4074e5cc0529e5cd96cfc01bb480e460c7edf5af70d2bcae55e/ruff-0.14.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c70427132db492d25f982fffc8d6c7535cc2fd2c83fc8888f05caaa248521e60", size = 13601891, upload-time = "2025-12-18T19:28:55.811Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0d/1e/14c916087d8598917dbad9b2921d340f7884824ad6e9c55de948a93b106d/ruff-0.14.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5bcf45b681e9f1ee6445d317ce1fa9d6cba9a6049542d1c3d5b5958986be8830", size = 14336660, upload-time = "2025-12-18T19:29:16.531Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f2/1c/d7b67ab43f30013b47c12b42d1acd354c195351a3f7a1d67f59e54227ede/ruff-0.14.10-py3-none-win32.whl", hash = "sha256:104c49fc7ab73f3f3a758039adea978869a918f31b73280db175b43a2d9b51d6", size = 13196187, upload-time = "2025-12-18T19:29:19.006Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fb/9c/896c862e13886fae2af961bef3e6312db9ebc6adc2b156fe95e615dee8c1/ruff-0.14.10-py3-none-win_amd64.whl", hash = "sha256:466297bd73638c6bdf06485683e812db1c00c7ac96d4ddd0294a338c62fdc154", size = 14661283, upload-time = "2025-12-18T19:29:30.16Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/74/31/b0e29d572670dca3674eeee78e418f20bdf97fa8aa9ea71380885e175ca0/ruff-0.14.10-py3-none-win_arm64.whl", hash = "sha256:e51d046cf6dda98a4633b8a8a771451107413b0f07183b2bef03f075599e44e6", size = 13729839, upload-time = "2025-12-18T19:28:48.636Z" }, ] [[package]] name = "secretstorage" version = "3.5.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cryptography" }, { name = "jeepney" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, ] [[package]] name = "selenium" version = "4.39.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "certifi" }, { name = "trio" }, @@ -3992,257 +3983,257 @@ dependencies = [ { name = "urllib3", extra = ["socks"] }, { name = "websocket-client" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/af/19/27c1bf9eb1f7025632d35a956b50746efb4b10aa87f961b263fa7081f4c5/selenium-4.39.0.tar.gz", hash = "sha256:12f3325f02d43b6c24030fc9602b34a3c6865abbb1db9406641d13d108aa1889", size = 928575, upload-time = "2025-12-06T23:12:34.896Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/af/19/27c1bf9eb1f7025632d35a956b50746efb4b10aa87f961b263fa7081f4c5/selenium-4.39.0.tar.gz", hash = "sha256:12f3325f02d43b6c24030fc9602b34a3c6865abbb1db9406641d13d108aa1889", size = 928575, upload-time = "2025-12-06T23:12:34.896Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/d0/55a6b7c6f35aad4c8a54be0eb7a52c1ff29a59542fc3e655f0ecbb14456d/selenium-4.39.0-py3-none-any.whl", hash = "sha256:c85f65d5610642ca0f47dae9d5cc117cd9e831f74038bc09fe1af126288200f9", size = 9655249, upload-time = "2025-12-06T23:12:33.085Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/d0/55a6b7c6f35aad4c8a54be0eb7a52c1ff29a59542fc3e655f0ecbb14456d/selenium-4.39.0-py3-none-any.whl", hash = "sha256:c85f65d5610642ca0f47dae9d5cc117cd9e831f74038bc09fe1af126288200f9", size = 9655249, upload-time = "2025-12-06T23:12:33.085Z" }, ] [[package]] name = "semver" version = "3.0.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/72/d1/d3159231aec234a59dd7d601e9dd9fe96f3afff15efd33c1070019b26132/semver-3.0.4.tar.gz", hash = "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602", size = 269730, upload-time = "2025-01-24T13:19:27.617Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/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://mirrors.tuna.tsinghua.edu.cn/pypi/web/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" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/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" }, ] [[package]] name = "sentry-sdk" version = "2.49.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "certifi" }, { name = "urllib3" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/94/23ac26616a883f492428d9ee9ad6eee391612125326b784dbfc30e1e7bab/sentry_sdk-2.49.0.tar.gz", hash = "sha256:c1878599cde410d481c04ef50ee3aedd4f600e4d0d253f4763041e468b332c30", size = 387228, upload-time = "2026-01-08T09:56:25.642Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/94/23ac26616a883f492428d9ee9ad6eee391612125326b784dbfc30e1e7bab/sentry_sdk-2.49.0.tar.gz", hash = "sha256:c1878599cde410d481c04ef50ee3aedd4f600e4d0d253f4763041e468b332c30", size = 387228, upload-time = "2026-01-08T09:56:25.642Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/88/43/1c586f9f413765201234541857cb82fda076f4b0f7bad4a0ec248da39cf3/sentry_sdk-2.49.0-py2.py3-none-any.whl", hash = "sha256:6ea78499133874445a20fe9c826c9e960070abeb7ae0cdf930314ab16bb97aa0", size = 415693, upload-time = "2026-01-08T09:56:21.872Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/88/43/1c586f9f413765201234541857cb82fda076f4b0f7bad4a0ec248da39cf3/sentry_sdk-2.49.0-py2.py3-none-any.whl", hash = "sha256:6ea78499133874445a20fe9c826c9e960070abeb7ae0cdf930314ab16bb97aa0", size = 415693, upload-time = "2026-01-08T09:56:21.872Z" }, ] [[package]] name = "service-identity" version = "24.2.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "attrs" }, { name = "cryptography" }, { name = "pyasn1" }, { name = "pyasn1-modules" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/07/a5/dfc752b979067947261dbbf2543470c58efe735c3c1301dd870ef27830ee/service_identity-24.2.0.tar.gz", hash = "sha256:b8683ba13f0d39c6cd5d625d2c5f65421d6d707b013b375c355751557cbe8e09", size = 39245, upload-time = "2024-10-26T07:21:57.736Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/07/a5/dfc752b979067947261dbbf2543470c58efe735c3c1301dd870ef27830ee/service_identity-24.2.0.tar.gz", hash = "sha256:b8683ba13f0d39c6cd5d625d2c5f65421d6d707b013b375c355751557cbe8e09", size = 39245, upload-time = "2024-10-26T07:21:57.736Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/08/2c/ca6dd598b384bc1ce581e24aaae0f2bed4ccac57749d5c3befbb5e742081/service_identity-24.2.0-py3-none-any.whl", hash = "sha256:6b047fbd8a84fd0bb0d55ebce4031e400562b9196e1e0d3e0fe2b8a59f6d4a85", size = 11364, upload-time = "2024-10-26T07:21:56.302Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/08/2c/ca6dd598b384bc1ce581e24aaae0f2bed4ccac57749d5c3befbb5e742081/service_identity-24.2.0-py3-none-any.whl", hash = "sha256:6b047fbd8a84fd0bb0d55ebce4031e400562b9196e1e0d3e0fe2b8a59f6d4a85", size = 11364, upload-time = "2024-10-26T07:21:56.302Z" }, ] [[package]] name = "shellingham" version = "1.5.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, ] [[package]] name = "six" version = "1.17.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] [[package]] name = "smmap" version = "5.0.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/44/cd/a040c4b3119bbe532e5b0732286f805445375489fceaec1f48306068ee3b/smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5", size = 22329, upload-time = "2025-01-02T07:14:40.909Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/44/cd/a040c4b3119bbe532e5b0732286f805445375489fceaec1f48306068ee3b/smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5", size = 22329, upload-time = "2025-01-02T07:14:40.909Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/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" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/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://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/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://mirrors.tuna.tsinghua.edu.cn/pypi/web/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" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/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 = "sortedcontainers" version = "2.4.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, ] [[package]] name = "soupsieve" version = "2.8.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/23/adf3796d740536d63a6fbda113d07e60c734b6ed5d3058d1e47fc0495e47/soupsieve-2.8.1.tar.gz", hash = "sha256:4cf733bc50fa805f5df4b8ef4740fc0e0fa6218cf3006269afd3f9d6d80fd350", size = 117856, upload-time = "2025-12-18T13:50:34.655Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/23/adf3796d740536d63a6fbda113d07e60c734b6ed5d3058d1e47fc0495e47/soupsieve-2.8.1.tar.gz", hash = "sha256:4cf733bc50fa805f5df4b8ef4740fc0e0fa6218cf3006269afd3f9d6d80fd350", size = 117856, upload-time = "2025-12-18T13:50:34.655Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/48/f3/b67d6ea49ca9154453b6d70b34ea22f3996b9fa55da105a79d8732227adc/soupsieve-2.8.1-py3-none-any.whl", hash = "sha256:a11fe2a6f3d76ab3cf2de04eb339c1be5b506a8a47f2ceb6d139803177f85434", size = 36710, upload-time = "2025-12-18T13:50:33.267Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/48/f3/b67d6ea49ca9154453b6d70b34ea22f3996b9fa55da105a79d8732227adc/soupsieve-2.8.1-py3-none-any.whl", hash = "sha256:a11fe2a6f3d76ab3cf2de04eb339c1be5b506a8a47f2ceb6d139803177f85434", size = 36710, upload-time = "2025-12-18T13:50:33.267Z" }, ] [[package]] name = "sqlalchemy" version = "2.0.45" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/be/f9/5e4491e5ccf42f5d9cfc663741d261b3e6e1683ae7812114e7636409fcc6/sqlalchemy-2.0.45.tar.gz", hash = "sha256:1632a4bda8d2d25703fdad6363058d882541bdaaee0e5e3ddfa0cd3229efce88", size = 9869912, upload-time = "2025-12-09T21:05:16.737Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/be/f9/5e4491e5ccf42f5d9cfc663741d261b3e6e1683ae7812114e7636409fcc6/sqlalchemy-2.0.45.tar.gz", hash = "sha256:1632a4bda8d2d25703fdad6363058d882541bdaaee0e5e3ddfa0cd3229efce88", size = 9869912, upload-time = "2025-12-09T21:05:16.737Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2d/c7/1900b56ce19bff1c26f39a4ce427faec7716c81ac792bfac8b6a9f3dca93/sqlalchemy-2.0.45-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3ee2aac15169fb0d45822983631466d60b762085bc4535cd39e66bea362df5f", size = 3333760, upload-time = "2025-12-09T22:11:02.66Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/93/3be94d96bb442d0d9a60e55a6bb6e0958dd3457751c6f8502e56ef95fed0/sqlalchemy-2.0.45-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba547ac0b361ab4f1608afbc8432db669bd0819b3e12e29fb5fa9529a8bba81d", size = 3348268, upload-time = "2025-12-09T22:13:49.054Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/48/4b/f88ded696e61513595e4a9778f9d3f2bf7332cce4eb0c7cedaabddd6687b/sqlalchemy-2.0.45-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:215f0528b914e5c75ef2559f69dca86878a3beeb0c1be7279d77f18e8d180ed4", size = 3278144, upload-time = "2025-12-09T22:11:04.14Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ed/6a/310ecb5657221f3e1bd5288ed83aa554923fb5da48d760a9f7622afeb065/sqlalchemy-2.0.45-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:107029bf4f43d076d4011f1afb74f7c3e2ea029ec82eb23d8527d5e909e97aa6", size = 3313907, upload-time = "2025-12-09T22:13:50.598Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5c/39/69c0b4051079addd57c84a5bfb34920d87456dd4c90cf7ee0df6efafc8ff/sqlalchemy-2.0.45-cp312-cp312-win32.whl", hash = "sha256:0c9f6ada57b58420a2c0277ff853abe40b9e9449f8d7d231763c6bc30f5c4953", size = 2112182, upload-time = "2025-12-09T21:39:30.824Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f7/4e/510db49dd89fc3a6e994bee51848c94c48c4a00dc905e8d0133c251f41a7/sqlalchemy-2.0.45-cp312-cp312-win_amd64.whl", hash = "sha256:8defe5737c6d2179c7997242d6473587c3beb52e557f5ef0187277009f73e5e1", size = 2139200, upload-time = "2025-12-09T21:39:32.321Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe187fc31a54d7fd90352f34e8c008cf3ad5d064d08fedd3de2e8df83eb4a1cf", size = 3277082, upload-time = "2025-12-09T22:11:06.167Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:672c45cae53ba88e0dad74b9027dddd09ef6f441e927786b05bec75d949fbb2e", size = 3293131, upload-time = "2025-12-09T22:13:52.626Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/da/4c/13dab31266fc9904f7609a5dc308a2432a066141d65b857760c3bef97e69/sqlalchemy-2.0.45-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:470daea2c1ce73910f08caf10575676a37159a6d16c4da33d0033546bddebc9b", size = 3225389, upload-time = "2025-12-09T22:11:08.093Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/74/04/891b5c2e9f83589de202e7abaf24cd4e4fa59e1837d64d528829ad6cc107/sqlalchemy-2.0.45-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9c6378449e0940476577047150fd09e242529b761dc887c9808a9a937fe990c8", size = 3266054, upload-time = "2025-12-09T22:13:54.262Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f1/24/fc59e7f71b0948cdd4cff7a286210e86b0443ef1d18a23b0d83b87e4b1f7/sqlalchemy-2.0.45-cp313-cp313-win32.whl", hash = "sha256:4b6bec67ca45bc166c8729910bd2a87f1c0407ee955df110d78948f5b5827e8a", size = 2110299, upload-time = "2025-12-09T21:39:33.486Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c0/c5/d17113020b2d43073412aeca09b60d2009442420372123b8d49cc253f8b8/sqlalchemy-2.0.45-cp313-cp313-win_amd64.whl", hash = "sha256:afbf47dc4de31fa38fd491f3705cac5307d21d4bb828a4f020ee59af412744ee", size = 2136264, upload-time = "2025-12-09T21:39:36.801Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/8d/bb40a5d10e7a5f2195f235c0b2f2c79b0bf6e8f00c0c223130a4fbd2db09/sqlalchemy-2.0.45-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:83d7009f40ce619d483d26ac1b757dfe3167b39921379a8bd1b596cf02dab4a6", size = 3521998, upload-time = "2025-12-09T22:13:28.622Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/a5/346128b0464886f036c039ea287b7332a410aa2d3fb0bb5d404cb8861635/sqlalchemy-2.0.45-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d8a2ca754e5415cde2b656c27900b19d50ba076aa05ce66e2207623d3fe41f5a", size = 3473434, upload-time = "2025-12-09T22:13:30.188Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl", hash = "sha256:5225a288e4c8cc2308dbdd874edad6e7d0fd38eac1e9e5f23503425c8eee20d0", size = 1936672, upload-time = "2025-12-09T21:54:52.608Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2d/c7/1900b56ce19bff1c26f39a4ce427faec7716c81ac792bfac8b6a9f3dca93/sqlalchemy-2.0.45-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3ee2aac15169fb0d45822983631466d60b762085bc4535cd39e66bea362df5f", size = 3333760, upload-time = "2025-12-09T22:11:02.66Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/93/3be94d96bb442d0d9a60e55a6bb6e0958dd3457751c6f8502e56ef95fed0/sqlalchemy-2.0.45-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba547ac0b361ab4f1608afbc8432db669bd0819b3e12e29fb5fa9529a8bba81d", size = 3348268, upload-time = "2025-12-09T22:13:49.054Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/48/4b/f88ded696e61513595e4a9778f9d3f2bf7332cce4eb0c7cedaabddd6687b/sqlalchemy-2.0.45-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:215f0528b914e5c75ef2559f69dca86878a3beeb0c1be7279d77f18e8d180ed4", size = 3278144, upload-time = "2025-12-09T22:11:04.14Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/6a/310ecb5657221f3e1bd5288ed83aa554923fb5da48d760a9f7622afeb065/sqlalchemy-2.0.45-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:107029bf4f43d076d4011f1afb74f7c3e2ea029ec82eb23d8527d5e909e97aa6", size = 3313907, upload-time = "2025-12-09T22:13:50.598Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/39/69c0b4051079addd57c84a5bfb34920d87456dd4c90cf7ee0df6efafc8ff/sqlalchemy-2.0.45-cp312-cp312-win32.whl", hash = "sha256:0c9f6ada57b58420a2c0277ff853abe40b9e9449f8d7d231763c6bc30f5c4953", size = 2112182, upload-time = "2025-12-09T21:39:30.824Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f7/4e/510db49dd89fc3a6e994bee51848c94c48c4a00dc905e8d0133c251f41a7/sqlalchemy-2.0.45-cp312-cp312-win_amd64.whl", hash = "sha256:8defe5737c6d2179c7997242d6473587c3beb52e557f5ef0187277009f73e5e1", size = 2139200, upload-time = "2025-12-09T21:39:32.321Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/c8/7cc5221b47a54edc72a0140a1efa56e0a2730eefa4058d7ed0b4c4357ff8/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe187fc31a54d7fd90352f34e8c008cf3ad5d064d08fedd3de2e8df83eb4a1cf", size = 3277082, upload-time = "2025-12-09T22:11:06.167Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/50/80a8d080ac7d3d321e5e5d420c9a522b0aa770ec7013ea91f9a8b7d36e4a/sqlalchemy-2.0.45-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:672c45cae53ba88e0dad74b9027dddd09ef6f441e927786b05bec75d949fbb2e", size = 3293131, upload-time = "2025-12-09T22:13:52.626Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/da/4c/13dab31266fc9904f7609a5dc308a2432a066141d65b857760c3bef97e69/sqlalchemy-2.0.45-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:470daea2c1ce73910f08caf10575676a37159a6d16c4da33d0033546bddebc9b", size = 3225389, upload-time = "2025-12-09T22:11:08.093Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/74/04/891b5c2e9f83589de202e7abaf24cd4e4fa59e1837d64d528829ad6cc107/sqlalchemy-2.0.45-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9c6378449e0940476577047150fd09e242529b761dc887c9808a9a937fe990c8", size = 3266054, upload-time = "2025-12-09T22:13:54.262Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f1/24/fc59e7f71b0948cdd4cff7a286210e86b0443ef1d18a23b0d83b87e4b1f7/sqlalchemy-2.0.45-cp313-cp313-win32.whl", hash = "sha256:4b6bec67ca45bc166c8729910bd2a87f1c0407ee955df110d78948f5b5827e8a", size = 2110299, upload-time = "2025-12-09T21:39:33.486Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c0/c5/d17113020b2d43073412aeca09b60d2009442420372123b8d49cc253f8b8/sqlalchemy-2.0.45-cp313-cp313-win_amd64.whl", hash = "sha256:afbf47dc4de31fa38fd491f3705cac5307d21d4bb828a4f020ee59af412744ee", size = 2136264, upload-time = "2025-12-09T21:39:36.801Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/8d/bb40a5d10e7a5f2195f235c0b2f2c79b0bf6e8f00c0c223130a4fbd2db09/sqlalchemy-2.0.45-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:83d7009f40ce619d483d26ac1b757dfe3167b39921379a8bd1b596cf02dab4a6", size = 3521998, upload-time = "2025-12-09T22:13:28.622Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/a5/346128b0464886f036c039ea287b7332a410aa2d3fb0bb5d404cb8861635/sqlalchemy-2.0.45-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d8a2ca754e5415cde2b656c27900b19d50ba076aa05ce66e2207623d3fe41f5a", size = 3473434, upload-time = "2025-12-09T22:13:30.188Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/e1/3ccb13c643399d22289c6a9786c1a91e3dcbb68bce4beb44926ac2c557bf/sqlalchemy-2.0.45-py3-none-any.whl", hash = "sha256:5225a288e4c8cc2308dbdd874edad6e7d0fd38eac1e9e5f23503425c8eee20d0", size = 1936672, upload-time = "2025-12-09T21:54:52.608Z" }, ] [[package]] name = "sse-starlette" version = "3.1.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "anyio" }, { name = "starlette" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/62/08/8f554b0e5bad3e4e880521a1686d96c05198471eed860b0eb89b57ea3636/sse_starlette-3.1.1.tar.gz", hash = "sha256:bffa531420c1793ab224f63648c059bcadc412bf9fdb1301ac8de1cf9a67b7fb", size = 24306, upload-time = "2025-12-26T15:22:53.836Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/08/8f554b0e5bad3e4e880521a1686d96c05198471eed860b0eb89b57ea3636/sse_starlette-3.1.1.tar.gz", hash = "sha256:bffa531420c1793ab224f63648c059bcadc412bf9fdb1301ac8de1cf9a67b7fb", size = 24306, upload-time = "2025-12-26T15:22:53.836Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e3/31/4c281581a0f8de137b710a07f65518b34bcf333b201cfa06cfda9af05f8a/sse_starlette-3.1.1-py3-none-any.whl", hash = "sha256:bb38f71ae74cfd86b529907a9fda5632195dfa6ae120f214ea4c890c7ee9d436", size = 12442, upload-time = "2025-12-26T15:22:52.911Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/31/4c281581a0f8de137b710a07f65518b34bcf333b201cfa06cfda9af05f8a/sse_starlette-3.1.1-py3-none-any.whl", hash = "sha256:bb38f71ae74cfd86b529907a9fda5632195dfa6ae120f214ea4c890c7ee9d436", size = 12442, upload-time = "2025-12-26T15:22:52.911Z" }, ] [[package]] name = "starlette" version = "0.50.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/b8/73a0e6a6e079a9d9cfa64113d771e421640b6f679a52eeb9b32f72d871a1/starlette-0.50.0.tar.gz", hash = "sha256:a2a17b22203254bcbc2e1f926d2d55f3f9497f769416b3190768befe598fa3ca", size = 2646985, upload-time = "2025-11-01T15:25:27.516Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/b8/73a0e6a6e079a9d9cfa64113d771e421640b6f679a52eeb9b32f72d871a1/starlette-0.50.0.tar.gz", hash = "sha256:a2a17b22203254bcbc2e1f926d2d55f3f9497f769416b3190768befe598fa3ca", size = 2646985, upload-time = "2025-11-01T15:25:27.516Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d9/52/1064f510b141bd54025f9b55105e26d1fa970b9be67ad766380a3c9b74b0/starlette-0.50.0-py3-none-any.whl", hash = "sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca", size = 74033, upload-time = "2025-11-01T15:25:25.461Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/52/1064f510b141bd54025f9b55105e26d1fa970b9be67ad766380a3c9b74b0/starlette-0.50.0-py3-none-any.whl", hash = "sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca", size = 74033, upload-time = "2025-11-01T15:25:25.461Z" }, ] [[package]] name = "sympy" version = "1.14.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "mpmath" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921, upload-time = "2025-04-27T18:05:01.611Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921, upload-time = "2025-04-27T18:05:01.611Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" }, ] [[package]] name = "tavily-python" version = "0.7.17" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "httpx" }, { name = "requests" }, { name = "tiktoken" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5f/eb/d7371ee68119380ab6561c6998eacf3031327ba89c6081d36128ab4a2184/tavily_python-0.7.17.tar.gz", hash = "sha256:437ba064639dfdce1acdbc37cbb73246abe500ab735e988a4b8698a8d5fb7df7", size = 21321, upload-time = "2025-12-17T17:08:39.3Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/eb/d7371ee68119380ab6561c6998eacf3031327ba89c6081d36128ab4a2184/tavily_python-0.7.17.tar.gz", hash = "sha256:437ba064639dfdce1acdbc37cbb73246abe500ab735e988a4b8698a8d5fb7df7", size = 21321, upload-time = "2025-12-17T17:08:39.3Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/ce/88565f0c9f7654bc90e19f1e76b3bffee7ff9c1741a2124ec2f2900fb080/tavily_python-0.7.17-py3-none-any.whl", hash = "sha256:a2725b9cba71e404e73d19ff277df916283c10100137c336e07f8e1bd7789fcf", size = 18214, upload-time = "2025-12-17T17:08:38.442Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/ce/88565f0c9f7654bc90e19f1e76b3bffee7ff9c1741a2124ec2f2900fb080/tavily_python-0.7.17-py3-none-any.whl", hash = "sha256:a2725b9cba71e404e73d19ff277df916283c10100137c336e07f8e1bd7789fcf", size = 18214, upload-time = "2025-12-17T17:08:38.442Z" }, ] [[package]] name = "tenacity" version = "9.1.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, ] [[package]] name = "tiktoken" version = "0.12.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "regex" }, { name = "requests" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806, upload-time = "2025-10-06T20:22:45.419Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a4/85/be65d39d6b647c79800fd9d29241d081d4eeb06271f383bb87200d74cf76/tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8", size = 1050728, upload-time = "2025-10-06T20:21:52.756Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4a/42/6573e9129bc55c9bf7300b3a35bef2c6b9117018acca0dc760ac2d93dffe/tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b", size = 994049, upload-time = "2025-10-06T20:21:53.782Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/66/c5/ed88504d2f4a5fd6856990b230b56d85a777feab84e6129af0822f5d0f70/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37", size = 1129008, upload-time = "2025-10-06T20:21:54.832Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f4/90/3dae6cc5436137ebd38944d396b5849e167896fc2073da643a49f372dc4f/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad", size = 1152665, upload-time = "2025-10-06T20:21:56.129Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a3/fe/26df24ce53ffde419a42f5f53d755b995c9318908288c17ec3f3448313a3/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5", size = 1194230, upload-time = "2025-10-06T20:21:57.546Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/20/cc/b064cae1a0e9fac84b0d2c46b89f4e57051a5f41324e385d10225a984c24/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3", size = 1254688, upload-time = "2025-10-06T20:21:58.619Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/81/10/b8523105c590c5b8349f2587e2fdfe51a69544bd5a76295fc20f2374f470/tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd", size = 878694, upload-time = "2025-10-06T20:21:59.876Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/00/61/441588ee21e6b5cdf59d6870f86beb9789e532ee9718c251b391b70c68d6/tiktoken-0.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:775c2c55de2310cc1bc9a3ad8826761cbdc87770e586fd7b6da7d4589e13dab3", size = 1050802, upload-time = "2025-10-06T20:22:00.96Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1f/05/dcf94486d5c5c8d34496abe271ac76c5b785507c8eae71b3708f1ad9b45a/tiktoken-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a01b12f69052fbe4b080a2cfb867c4de12c704b56178edf1d1d7b273561db160", size = 993995, upload-time = "2025-10-06T20:22:02.788Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a0/70/5163fe5359b943f8db9946b62f19be2305de8c3d78a16f629d4165e2f40e/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:01d99484dc93b129cd0964f9d34eee953f2737301f18b3c7257bf368d7615baa", size = 1128948, upload-time = "2025-10-06T20:22:03.814Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0c/da/c028aa0babf77315e1cef357d4d768800c5f8a6de04d0eac0f377cb619fa/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4a1a4fcd021f022bfc81904a911d3df0f6543b9e7627b51411da75ff2fe7a1be", size = 1151986, upload-time = "2025-10-06T20:22:05.173Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a0/5a/886b108b766aa53e295f7216b509be95eb7d60b166049ce2c58416b25f2a/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:981a81e39812d57031efdc9ec59fa32b2a5a5524d20d4776574c4b4bd2e9014a", size = 1194222, upload-time = "2025-10-06T20:22:06.265Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f4/f8/4db272048397636ac7a078d22773dd2795b1becee7bc4922fe6207288d57/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9baf52f84a3f42eef3ff4e754a0db79a13a27921b457ca9832cf944c6be4f8f3", size = 1255097, upload-time = "2025-10-06T20:22:07.403Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8e/32/45d02e2e0ea2be3a9ed22afc47d93741247e75018aac967b713b2941f8ea/tiktoken-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b8a0cd0c789a61f31bf44851defbd609e8dd1e2c8589c614cc1060940ef1f697", size = 879117, upload-time = "2025-10-06T20:22:08.418Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/76/994fc868f88e016e6d05b0da5ac24582a14c47893f4474c3e9744283f1d5/tiktoken-0.12.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d5f89ea5680066b68bcb797ae85219c72916c922ef0fcdd3480c7d2315ffff16", size = 1050309, upload-time = "2025-10-06T20:22:10.939Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f6/b8/57ef1456504c43a849821920d582a738a461b76a047f352f18c0b26c6516/tiktoken-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b4e7ed1c6a7a8a60a3230965bdedba8cc58f68926b835e519341413370e0399a", size = 993712, upload-time = "2025-10-06T20:22:12.115Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/72/90/13da56f664286ffbae9dbcfadcc625439142675845baa62715e49b87b68b/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:fc530a28591a2d74bce821d10b418b26a094bf33839e69042a6e86ddb7a7fb27", size = 1128725, upload-time = "2025-10-06T20:22:13.541Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/05/df/4f80030d44682235bdaecd7346c90f67ae87ec8f3df4a3442cb53834f7e4/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:06a9f4f49884139013b138920a4c393aa6556b2f8f536345f11819389c703ebb", size = 1151875, upload-time = "2025-10-06T20:22:14.559Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/22/1f/ae535223a8c4ef4c0c1192e3f9b82da660be9eb66b9279e95c99288e9dab/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:04f0e6a985d95913cabc96a741c5ffec525a2c72e9df086ff17ebe35985c800e", size = 1194451, upload-time = "2025-10-06T20:22:15.545Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/78/a7/f8ead382fce0243cb625c4f266e66c27f65ae65ee9e77f59ea1653b6d730/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ee8f9ae00c41770b5f9b0bb1235474768884ae157de3beb5439ca0fd70f3e25", size = 1253794, upload-time = "2025-10-06T20:22:16.624Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/93/e0/6cc82a562bc6365785a3ff0af27a2a092d57c47d7a81d9e2295d8c36f011/tiktoken-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc2dd125a62cb2b3d858484d6c614d136b5b848976794edfb63688d539b8b93f", size = 878777, upload-time = "2025-10-06T20:22:18.036Z" }, +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806, upload-time = "2025-10-06T20:22:45.419Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a4/85/be65d39d6b647c79800fd9d29241d081d4eeb06271f383bb87200d74cf76/tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8", size = 1050728, upload-time = "2025-10-06T20:21:52.756Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4a/42/6573e9129bc55c9bf7300b3a35bef2c6b9117018acca0dc760ac2d93dffe/tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b", size = 994049, upload-time = "2025-10-06T20:21:53.782Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/c5/ed88504d2f4a5fd6856990b230b56d85a777feab84e6129af0822f5d0f70/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37", size = 1129008, upload-time = "2025-10-06T20:21:54.832Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f4/90/3dae6cc5436137ebd38944d396b5849e167896fc2073da643a49f372dc4f/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad", size = 1152665, upload-time = "2025-10-06T20:21:56.129Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a3/fe/26df24ce53ffde419a42f5f53d755b995c9318908288c17ec3f3448313a3/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5", size = 1194230, upload-time = "2025-10-06T20:21:57.546Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/cc/b064cae1a0e9fac84b0d2c46b89f4e57051a5f41324e385d10225a984c24/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3", size = 1254688, upload-time = "2025-10-06T20:21:58.619Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/81/10/b8523105c590c5b8349f2587e2fdfe51a69544bd5a76295fc20f2374f470/tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd", size = 878694, upload-time = "2025-10-06T20:21:59.876Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/00/61/441588ee21e6b5cdf59d6870f86beb9789e532ee9718c251b391b70c68d6/tiktoken-0.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:775c2c55de2310cc1bc9a3ad8826761cbdc87770e586fd7b6da7d4589e13dab3", size = 1050802, upload-time = "2025-10-06T20:22:00.96Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1f/05/dcf94486d5c5c8d34496abe271ac76c5b785507c8eae71b3708f1ad9b45a/tiktoken-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a01b12f69052fbe4b080a2cfb867c4de12c704b56178edf1d1d7b273561db160", size = 993995, upload-time = "2025-10-06T20:22:02.788Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a0/70/5163fe5359b943f8db9946b62f19be2305de8c3d78a16f629d4165e2f40e/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:01d99484dc93b129cd0964f9d34eee953f2737301f18b3c7257bf368d7615baa", size = 1128948, upload-time = "2025-10-06T20:22:03.814Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0c/da/c028aa0babf77315e1cef357d4d768800c5f8a6de04d0eac0f377cb619fa/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4a1a4fcd021f022bfc81904a911d3df0f6543b9e7627b51411da75ff2fe7a1be", size = 1151986, upload-time = "2025-10-06T20:22:05.173Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a0/5a/886b108b766aa53e295f7216b509be95eb7d60b166049ce2c58416b25f2a/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:981a81e39812d57031efdc9ec59fa32b2a5a5524d20d4776574c4b4bd2e9014a", size = 1194222, upload-time = "2025-10-06T20:22:06.265Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f4/f8/4db272048397636ac7a078d22773dd2795b1becee7bc4922fe6207288d57/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9baf52f84a3f42eef3ff4e754a0db79a13a27921b457ca9832cf944c6be4f8f3", size = 1255097, upload-time = "2025-10-06T20:22:07.403Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8e/32/45d02e2e0ea2be3a9ed22afc47d93741247e75018aac967b713b2941f8ea/tiktoken-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b8a0cd0c789a61f31bf44851defbd609e8dd1e2c8589c614cc1060940ef1f697", size = 879117, upload-time = "2025-10-06T20:22:08.418Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/76/994fc868f88e016e6d05b0da5ac24582a14c47893f4474c3e9744283f1d5/tiktoken-0.12.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d5f89ea5680066b68bcb797ae85219c72916c922ef0fcdd3480c7d2315ffff16", size = 1050309, upload-time = "2025-10-06T20:22:10.939Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f6/b8/57ef1456504c43a849821920d582a738a461b76a047f352f18c0b26c6516/tiktoken-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b4e7ed1c6a7a8a60a3230965bdedba8cc58f68926b835e519341413370e0399a", size = 993712, upload-time = "2025-10-06T20:22:12.115Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/90/13da56f664286ffbae9dbcfadcc625439142675845baa62715e49b87b68b/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:fc530a28591a2d74bce821d10b418b26a094bf33839e69042a6e86ddb7a7fb27", size = 1128725, upload-time = "2025-10-06T20:22:13.541Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/05/df/4f80030d44682235bdaecd7346c90f67ae87ec8f3df4a3442cb53834f7e4/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:06a9f4f49884139013b138920a4c393aa6556b2f8f536345f11819389c703ebb", size = 1151875, upload-time = "2025-10-06T20:22:14.559Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/1f/ae535223a8c4ef4c0c1192e3f9b82da660be9eb66b9279e95c99288e9dab/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:04f0e6a985d95913cabc96a741c5ffec525a2c72e9df086ff17ebe35985c800e", size = 1194451, upload-time = "2025-10-06T20:22:15.545Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/78/a7/f8ead382fce0243cb625c4f266e66c27f65ae65ee9e77f59ea1653b6d730/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ee8f9ae00c41770b5f9b0bb1235474768884ae157de3beb5439ca0fd70f3e25", size = 1253794, upload-time = "2025-10-06T20:22:16.624Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/93/e0/6cc82a562bc6365785a3ff0af27a2a092d57c47d7a81d9e2295d8c36f011/tiktoken-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc2dd125a62cb2b3d858484d6c614d136b5b848976794edfb63688d539b8b93f", size = 878777, upload-time = "2025-10-06T20:22:18.036Z" }, ] [[package]] name = "tornado" version = "6.4.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/45/a0daf161f7d6f36c3ea5fc0c2de619746cc3dd4c76402e9db545bd920f63/tornado-6.4.2.tar.gz", hash = "sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b", size = 501135, upload-time = "2024-11-22T03:06:38.036Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/45/a0daf161f7d6f36c3ea5fc0c2de619746cc3dd4c76402e9db545bd920f63/tornado-6.4.2.tar.gz", hash = "sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b", size = 501135, upload-time = "2024-11-22T03:06:38.036Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/7e/71f604d8cea1b58f82ba3590290b66da1e72d840aeb37e0d5f7291bd30db/tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1", size = 436299, upload-time = "2024-11-22T03:06:20.162Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/96/44/87543a3b99016d0bf54fdaab30d24bf0af2e848f1d13d34a3a5380aabe16/tornado-6.4.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803", size = 434253, upload-time = "2024-11-22T03:06:22.39Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/fb/fdf679b4ce51bcb7210801ef4f11fdac96e9885daa402861751353beea6e/tornado-6.4.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec", size = 437602, upload-time = "2024-11-22T03:06:24.214Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4f/3b/e31aeffffc22b475a64dbeb273026a21b5b566f74dee48742817626c47dc/tornado-6.4.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946", size = 436972, upload-time = "2024-11-22T03:06:25.559Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/22/55/b78a464de78051a30599ceb6983b01d8f732e6f69bf37b4ed07f642ac0fc/tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf", size = 437173, upload-time = "2024-11-22T03:06:27.584Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/79/5e/be4fb0d1684eb822c9a62fb18a3e44a06188f78aa466b2ad991d2ee31104/tornado-6.4.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634", size = 437892, upload-time = "2024-11-22T03:06:28.933Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f5/33/4f91fdd94ea36e1d796147003b490fe60a0215ac5737b6f9c65e160d4fe0/tornado-6.4.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73", size = 437334, upload-time = "2024-11-22T03:06:30.428Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2b/ae/c1b22d4524b0e10da2f29a176fb2890386f7bd1f63aacf186444873a88a0/tornado-6.4.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c", size = 437261, upload-time = "2024-11-22T03:06:32.458Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b5/25/36dbd49ab6d179bcfc4c6c093a51795a4f3bed380543a8242ac3517a1751/tornado-6.4.2-cp38-abi3-win32.whl", hash = "sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482", size = 438463, upload-time = "2024-11-22T03:06:34.71Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/cc/58b1adeb1bb46228442081e746fcdbc4540905c87e8add7c277540934edb/tornado-6.4.2-cp38-abi3-win_amd64.whl", hash = "sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38", size = 438907, upload-time = "2024-11-22T03:06:36.71Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/7e/71f604d8cea1b58f82ba3590290b66da1e72d840aeb37e0d5f7291bd30db/tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1", size = 436299, upload-time = "2024-11-22T03:06:20.162Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/96/44/87543a3b99016d0bf54fdaab30d24bf0af2e848f1d13d34a3a5380aabe16/tornado-6.4.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803", size = 434253, upload-time = "2024-11-22T03:06:22.39Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/fb/fdf679b4ce51bcb7210801ef4f11fdac96e9885daa402861751353beea6e/tornado-6.4.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec", size = 437602, upload-time = "2024-11-22T03:06:24.214Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4f/3b/e31aeffffc22b475a64dbeb273026a21b5b566f74dee48742817626c47dc/tornado-6.4.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946", size = 436972, upload-time = "2024-11-22T03:06:25.559Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/55/b78a464de78051a30599ceb6983b01d8f732e6f69bf37b4ed07f642ac0fc/tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf", size = 437173, upload-time = "2024-11-22T03:06:27.584Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/5e/be4fb0d1684eb822c9a62fb18a3e44a06188f78aa466b2ad991d2ee31104/tornado-6.4.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634", size = 437892, upload-time = "2024-11-22T03:06:28.933Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/33/4f91fdd94ea36e1d796147003b490fe60a0215ac5737b6f9c65e160d4fe0/tornado-6.4.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73", size = 437334, upload-time = "2024-11-22T03:06:30.428Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/ae/c1b22d4524b0e10da2f29a176fb2890386f7bd1f63aacf186444873a88a0/tornado-6.4.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c", size = 437261, upload-time = "2024-11-22T03:06:32.458Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b5/25/36dbd49ab6d179bcfc4c6c093a51795a4f3bed380543a8242ac3517a1751/tornado-6.4.2-cp38-abi3-win32.whl", hash = "sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482", size = 438463, upload-time = "2024-11-22T03:06:34.71Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/cc/58b1adeb1bb46228442081e746fcdbc4540905c87e8add7c277540934edb/tornado-6.4.2-cp38-abi3-win_amd64.whl", hash = "sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38", size = 438907, upload-time = "2024-11-22T03:06:36.71Z" }, ] [[package]] name = "tqdm" version = "4.67.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, ] [[package]] name = "trio" version = "0.32.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "attrs" }, { name = "cffi", marker = "implementation_name != 'pypy' and os_name == 'nt'" }, @@ -4251,165 +4242,165 @@ dependencies = [ { name = "sniffio" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d8/ce/0041ddd9160aac0031bcf5ab786c7640d795c797e67c438e15cfedf815c8/trio-0.32.0.tar.gz", hash = "sha256:150f29ec923bcd51231e1d4c71c7006e65247d68759dd1c19af4ea815a25806b", size = 605323, upload-time = "2025-10-31T07:18:17.466Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/ce/0041ddd9160aac0031bcf5ab786c7640d795c797e67c438e15cfedf815c8/trio-0.32.0.tar.gz", hash = "sha256:150f29ec923bcd51231e1d4c71c7006e65247d68759dd1c19af4ea815a25806b", size = 605323, upload-time = "2025-10-31T07:18:17.466Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/41/bf/945d527ff706233636c73880b22c7c953f3faeb9d6c7e2e85bfbfd0134a0/trio-0.32.0-py3-none-any.whl", hash = "sha256:4ab65984ef8370b79a76659ec87aa3a30c5c7c83ff250b4de88c29a8ab6123c5", size = 512030, upload-time = "2025-10-31T07:18:15.885Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/41/bf/945d527ff706233636c73880b22c7c953f3faeb9d6c7e2e85bfbfd0134a0/trio-0.32.0-py3-none-any.whl", hash = "sha256:4ab65984ef8370b79a76659ec87aa3a30c5c7c83ff250b4de88c29a8ab6123c5", size = 512030, upload-time = "2025-10-31T07:18:15.885Z" }, ] [[package]] name = "trio-websocket" version = "0.12.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "outcome" }, { name = "trio" }, { name = "wsproto" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/3c/8b4358e81f2f2cfe71b66a267f023a91db20a817b9425dd964873796980a/trio_websocket-0.12.2.tar.gz", hash = "sha256:22c72c436f3d1e264d0910a3951934798dcc5b00ae56fc4ee079d46c7cf20fae", size = 33549, upload-time = "2025-02-25T05:16:58.947Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/3c/8b4358e81f2f2cfe71b66a267f023a91db20a817b9425dd964873796980a/trio_websocket-0.12.2.tar.gz", hash = "sha256:22c72c436f3d1e264d0910a3951934798dcc5b00ae56fc4ee079d46c7cf20fae", size = 33549, upload-time = "2025-02-25T05:16:58.947Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/19/eb640a397bba49ba49ef9dbe2e7e5c04202ba045b6ce2ec36e9cadc51e04/trio_websocket-0.12.2-py3-none-any.whl", hash = "sha256:df605665f1db533f4a386c94525870851096a223adcb97f72a07e8b4beba45b6", size = 21221, upload-time = "2025-02-25T05:16:57.545Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/19/eb640a397bba49ba49ef9dbe2e7e5c04202ba045b6ce2ec36e9cadc51e04/trio_websocket-0.12.2-py3-none-any.whl", hash = "sha256:df605665f1db533f4a386c94525870851096a223adcb97f72a07e8b4beba45b6", size = 21221, upload-time = "2025-02-25T05:16:57.545Z" }, ] [[package]] name = "typer" version = "0.21.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "click" }, { name = "rich" }, { name = "shellingham" }, { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/85/30/ff9ede605e3bd086b4dd842499814e128500621f7951ca1e5ce84bbf61b1/typer-0.21.0.tar.gz", hash = "sha256:c87c0d2b6eee3b49c5c64649ec92425492c14488096dfbc8a0c2799b2f6f9c53", size = 106781, upload-time = "2025-12-25T09:54:53.651Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/85/30/ff9ede605e3bd086b4dd842499814e128500621f7951ca1e5ce84bbf61b1/typer-0.21.0.tar.gz", hash = "sha256:c87c0d2b6eee3b49c5c64649ec92425492c14488096dfbc8a0c2799b2f6f9c53", size = 106781, upload-time = "2025-12-25T09:54:53.651Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl", hash = "sha256:c79c01ca6b30af9fd48284058a7056ba0d3bf5cf10d0ff3d0c5b11b68c258ac6", size = 47109, upload-time = "2025-12-25T09:54:51.918Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e1/e4/5ebc1899d31d2b1601b32d21cfb4bba022ae6fce323d365f0448031b1660/typer-0.21.0-py3-none-any.whl", hash = "sha256:c79c01ca6b30af9fd48284058a7056ba0d3bf5cf10d0ff3d0c5b11b68c258ac6", size = 47109, upload-time = "2025-12-25T09:54:51.918Z" }, ] [[package]] name = "types-cffi" version = "1.17.0.20250915" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "types-setuptools" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2a/98/ea454cea03e5f351323af6a482c65924f3c26c515efd9090dede58f2b4b6/types_cffi-1.17.0.20250915.tar.gz", hash = "sha256:4362e20368f78dabd5c56bca8004752cc890e07a71605d9e0d9e069dbaac8c06", size = 17229, upload-time = "2025-09-15T03:01:25.31Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/98/ea454cea03e5f351323af6a482c65924f3c26c515efd9090dede58f2b4b6/types_cffi-1.17.0.20250915.tar.gz", hash = "sha256:4362e20368f78dabd5c56bca8004752cc890e07a71605d9e0d9e069dbaac8c06", size = 17229, upload-time = "2025-09-15T03:01:25.31Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/ec/092f2b74b49ec4855cdb53050deb9699f7105b8fda6fe034c0781b8687f3/types_cffi-1.17.0.20250915-py3-none-any.whl", hash = "sha256:cef4af1116c83359c11bb4269283c50f0688e9fc1d7f0eeb390f3661546da52c", size = 20112, upload-time = "2025-09-15T03:01:24.187Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/ec/092f2b74b49ec4855cdb53050deb9699f7105b8fda6fe034c0781b8687f3/types_cffi-1.17.0.20250915-py3-none-any.whl", hash = "sha256:cef4af1116c83359c11bb4269283c50f0688e9fc1d7f0eeb390f3661546da52c", size = 20112, upload-time = "2025-09-15T03:01:24.187Z" }, ] [[package]] name = "types-pyopenssl" version = "24.1.0.20240722" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cryptography" }, { name = "types-cffi" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/93/29/47a346550fd2020dac9a7a6d033ea03fccb92fa47c726056618cc889745e/types-pyOpenSSL-24.1.0.20240722.tar.gz", hash = "sha256:47913b4678a01d879f503a12044468221ed8576263c1540dcb0484ca21b08c39", size = 8458, upload-time = "2024-07-22T02:32:22.558Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/93/29/47a346550fd2020dac9a7a6d033ea03fccb92fa47c726056618cc889745e/types-pyOpenSSL-24.1.0.20240722.tar.gz", hash = "sha256:47913b4678a01d879f503a12044468221ed8576263c1540dcb0484ca21b08c39", size = 8458, upload-time = "2024-07-22T02:32:22.558Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/05/c868a850b6fbb79c26f5f299b768ee0adc1f9816d3461dcf4287916f655b/types_pyOpenSSL-24.1.0.20240722-py3-none-any.whl", hash = "sha256:6a7a5d2ec042537934cfb4c9d4deb0e16c4c6250b09358df1f083682fe6fda54", size = 7499, upload-time = "2024-07-22T02:32:21.232Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/05/c868a850b6fbb79c26f5f299b768ee0adc1f9816d3461dcf4287916f655b/types_pyOpenSSL-24.1.0.20240722-py3-none-any.whl", hash = "sha256:6a7a5d2ec042537934cfb4c9d4deb0e16c4c6250b09358df1f083682fe6fda54", size = 7499, upload-time = "2024-07-22T02:32:21.232Z" }, ] [[package]] name = "types-pyyaml" version = "6.0.12.20250915" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7e/69/3c51b36d04da19b92f9e815be12753125bd8bc247ba0470a982e6979e71c/types_pyyaml-6.0.12.20250915.tar.gz", hash = "sha256:0f8b54a528c303f0e6f7165687dd33fafa81c807fcac23f632b63aa624ced1d3", size = 17522, upload-time = "2025-09-15T03:01:00.728Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/69/3c51b36d04da19b92f9e815be12753125bd8bc247ba0470a982e6979e71c/types_pyyaml-6.0.12.20250915.tar.gz", hash = "sha256:0f8b54a528c303f0e6f7165687dd33fafa81c807fcac23f632b63aa624ced1d3", size = 17522, upload-time = "2025-09-15T03:01:00.728Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bd/e0/1eed384f02555dde685fff1a1ac805c1c7dcb6dd019c916fe659b1c1f9ec/types_pyyaml-6.0.12.20250915-py3-none-any.whl", hash = "sha256:e7d4d9e064e89a3b3cae120b4990cd370874d2bf12fa5f46c97018dd5d3c9ab6", size = 20338, upload-time = "2025-09-15T03:00:59.218Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bd/e0/1eed384f02555dde685fff1a1ac805c1c7dcb6dd019c916fe659b1c1f9ec/types_pyyaml-6.0.12.20250915-py3-none-any.whl", hash = "sha256:e7d4d9e064e89a3b3cae120b4990cd370874d2bf12fa5f46c97018dd5d3c9ab6", size = 20338, upload-time = "2025-09-15T03:00:59.218Z" }, ] [[package]] name = "types-redis" version = "4.6.0.20241004" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cryptography" }, { name = "types-pyopenssl" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3a/95/c054d3ac940e8bac4ca216470c80c26688a0e79e09f520a942bb27da3386/types-redis-4.6.0.20241004.tar.gz", hash = "sha256:5f17d2b3f9091ab75384153bfa276619ffa1cf6a38da60e10d5e6749cc5b902e", size = 49679, upload-time = "2024-10-04T02:43:59.224Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/95/c054d3ac940e8bac4ca216470c80c26688a0e79e09f520a942bb27da3386/types-redis-4.6.0.20241004.tar.gz", hash = "sha256:5f17d2b3f9091ab75384153bfa276619ffa1cf6a38da60e10d5e6749cc5b902e", size = 49679, upload-time = "2024-10-04T02:43:59.224Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/55/82/7d25dce10aad92d2226b269bce2f85cfd843b4477cd50245d7d40ecf8f89/types_redis-4.6.0.20241004-py3-none-any.whl", hash = "sha256:ef5da68cb827e5f606c8f9c0b49eeee4c2669d6d97122f301d3a55dc6a63f6ed", size = 58737, upload-time = "2024-10-04T02:43:57.968Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/55/82/7d25dce10aad92d2226b269bce2f85cfd843b4477cd50245d7d40ecf8f89/types_redis-4.6.0.20241004-py3-none-any.whl", hash = "sha256:ef5da68cb827e5f606c8f9c0b49eeee4c2669d6d97122f301d3a55dc6a63f6ed", size = 58737, upload-time = "2024-10-04T02:43:57.968Z" }, ] [[package]] name = "types-setuptools" version = "80.10.0.20260124" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/7e/116539b9610585e34771611e33c88a4c706491fa3565500f5a63139f8731/types_setuptools-80.10.0.20260124.tar.gz", hash = "sha256:1b86d9f0368858663276a0cbe5fe5a9722caf94b5acde8aba0399a6e90680f20", size = 43299, upload-time = "2026-01-24T03:18:39.527Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/7e/116539b9610585e34771611e33c88a4c706491fa3565500f5a63139f8731/types_setuptools-80.10.0.20260124.tar.gz", hash = "sha256:1b86d9f0368858663276a0cbe5fe5a9722caf94b5acde8aba0399a6e90680f20", size = 43299, upload-time = "2026-01-24T03:18:39.527Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2b/7f/016dc5cc718ec6ccaa84fb73ed409ef1c261793fd5e637cdfaa18beb40a9/types_setuptools-80.10.0.20260124-py3-none-any.whl", hash = "sha256:efed7e044f01adb9c2806c7a8e1b6aa3656b8e382379b53d5f26ee3db24d4c01", size = 64333, upload-time = "2026-01-24T03:18:38.344Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/7f/016dc5cc718ec6ccaa84fb73ed409ef1c261793fd5e637cdfaa18beb40a9/types_setuptools-80.10.0.20260124-py3-none-any.whl", hash = "sha256:efed7e044f01adb9c2806c7a8e1b6aa3656b8e382379b53d5f26ee3db24d4c01", size = 64333, upload-time = "2026-01-24T03:18:38.344Z" }, ] [[package]] name = "typing-extensions" version = "4.15.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] [[package]] name = "typing-inspection" version = "0.4.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] [[package]] name = "tzdata" version = "2025.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, ] [[package]] name = "uefi-firmware" version = "1.11" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "future" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/ca/139ef1b190af2280e3a149391ed43028c1d19283ad556aa090c49aab3f36/uefi_firmware-1.11.tar.gz", hash = "sha256:30e2a9d138ac1608bdfc1783a936931eb6f4292723919f1db2c1509ec18a6041" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/ca/139ef1b190af2280e3a149391ed43028c1d19283ad556aa090c49aab3f36/uefi_firmware-1.11.tar.gz", hash = "sha256:30e2a9d138ac1608bdfc1783a936931eb6f4292723919f1db2c1509ec18a6041" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/20/1f56471e7f882f92b6b5be80674ddded92a39da483b648120eb61bd2e362/uefi_firmware-1.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c927563154ce2e6ff522bda07c99ff3b4feba7167bf59fb516f755565a7523e7" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/72/28/137c6163823bb6f02a384c0a9dc0963dc70b0a89b077e2f3a2ed2f9f1f48/uefi_firmware-1.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fe45376980d1533e8faf80af1a19e8dcd1b8170a447e1fa39934f4fa91ea0a35" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/1e/a5e52142e0d50979ae6cb148348fa4c1d66eb06932dacade4057025a7d7e/uefi_firmware-1.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1cf627f257f14ed1bb63290c658e9adb772292927ad399ef70366801dc0cb9a5" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4f/58/37ba11ff39707b919b590dd7a8c0cae613bdc7171631963af16ef29b1f79/uefi_firmware-1.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4253b57873fc6127a50ca92797741a74b774d1aa3c994011bd196b21033ddc1" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/ab/b37ade211fc5ed704f685352fe0947cbeaf9165924fe2c0048120da4ccd4/uefi_firmware-1.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e71095839db1733d77e0001f906104e3084c6bc433dcc5ff8240a65a58d2945" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e6/a9/7ead995a7f5ffe77d21e3479e95ca857b7cc9c241271999cb780a2cfc950/uefi_firmware-1.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da64a6cedea68934dab6186b13a48df55027429490f3be02bc910803d040d733" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/49/e2/5d0c396fab59b6c16e41271b9c74820c0107163be967db0474226ffa31dd/uefi_firmware-1.11-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:07a891147c10a6112c6ae4d76efbd07e422ceb1b34e6aa1236d9beb21a6d48b6" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/8c/32adad2dddd768ec0a44aa2174a44864e03e5eab68c59c047148b8e3b2d2/uefi_firmware-1.11-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:75b2de62978767e2263f3299f3ed2d5daaee47cfeb77496769c531e35c2c3393" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/98/04155a6f6eded9d184692533ec55fd711d9a2e5ae4a5ed416689f48beb11/uefi_firmware-1.11-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5a45d398edbb985952ee4dc1987f40aecf9af2b151a783eaa70ee0447e7a8052" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/20/61/6e63948588d4bf75e94e45b57205113322972d3b87c3b1ea0062e8e26f0f/uefi_firmware-1.11-cp312-cp312-win32.whl", hash = "sha256:cda1eec452581e6a1fdca9b62c9e4fe9ab6284ef16334fab47b9f3426bbeb841" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d6/ea/8189bac9bf10dccc6690712aa5695bbd0b82bc5cd4f20defe5892912d364/uefi_firmware-1.11-cp312-cp312-win_amd64.whl", hash = "sha256:0d544e25dab9cefa23a9c2f43226f94d50f85b3b625fe47ce3df12b530e1a1fa" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/0e/778e3e72005711e6e886caa3f2a6e33dba4073f679df46c4204740761cc8/uefi_firmware-1.11-cp312-cp312-win_arm64.whl", hash = "sha256:25ddff80fc4d95199ad48e304f32566447acf7a593d0cd4d293629f2e3eabd45" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/20/1f56471e7f882f92b6b5be80674ddded92a39da483b648120eb61bd2e362/uefi_firmware-1.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c927563154ce2e6ff522bda07c99ff3b4feba7167bf59fb516f755565a7523e7" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/72/28/137c6163823bb6f02a384c0a9dc0963dc70b0a89b077e2f3a2ed2f9f1f48/uefi_firmware-1.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fe45376980d1533e8faf80af1a19e8dcd1b8170a447e1fa39934f4fa91ea0a35" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/1e/a5e52142e0d50979ae6cb148348fa4c1d66eb06932dacade4057025a7d7e/uefi_firmware-1.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1cf627f257f14ed1bb63290c658e9adb772292927ad399ef70366801dc0cb9a5" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4f/58/37ba11ff39707b919b590dd7a8c0cae613bdc7171631963af16ef29b1f79/uefi_firmware-1.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4253b57873fc6127a50ca92797741a74b774d1aa3c994011bd196b21033ddc1" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/ab/b37ade211fc5ed704f685352fe0947cbeaf9165924fe2c0048120da4ccd4/uefi_firmware-1.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e71095839db1733d77e0001f906104e3084c6bc433dcc5ff8240a65a58d2945" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e6/a9/7ead995a7f5ffe77d21e3479e95ca857b7cc9c241271999cb780a2cfc950/uefi_firmware-1.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da64a6cedea68934dab6186b13a48df55027429490f3be02bc910803d040d733" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/49/e2/5d0c396fab59b6c16e41271b9c74820c0107163be967db0474226ffa31dd/uefi_firmware-1.11-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:07a891147c10a6112c6ae4d76efbd07e422ceb1b34e6aa1236d9beb21a6d48b6" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/8c/32adad2dddd768ec0a44aa2174a44864e03e5eab68c59c047148b8e3b2d2/uefi_firmware-1.11-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:75b2de62978767e2263f3299f3ed2d5daaee47cfeb77496769c531e35c2c3393" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/98/04155a6f6eded9d184692533ec55fd711d9a2e5ae4a5ed416689f48beb11/uefi_firmware-1.11-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5a45d398edbb985952ee4dc1987f40aecf9af2b151a783eaa70ee0447e7a8052" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/61/6e63948588d4bf75e94e45b57205113322972d3b87c3b1ea0062e8e26f0f/uefi_firmware-1.11-cp312-cp312-win32.whl", hash = "sha256:cda1eec452581e6a1fdca9b62c9e4fe9ab6284ef16334fab47b9f3426bbeb841" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d6/ea/8189bac9bf10dccc6690712aa5695bbd0b82bc5cd4f20defe5892912d364/uefi_firmware-1.11-cp312-cp312-win_amd64.whl", hash = "sha256:0d544e25dab9cefa23a9c2f43226f94d50f85b3b625fe47ce3df12b530e1a1fa" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/0e/778e3e72005711e6e886caa3f2a6e33dba4073f679df46c4204740761cc8/uefi_firmware-1.11-cp312-cp312-win_arm64.whl", hash = "sha256:25ddff80fc4d95199ad48e304f32566447acf7a593d0cd4d293629f2e3eabd45" }, ] [[package]] name = "unique-log-filter" version = "0.1.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/5e/942062197dc9679e5d4fa112c3eb782236800cf2c238b08f116cfbd45895/unique_log_filter-0.1.0.tar.gz", hash = "sha256:411ca5b30572293fc37cd93a651da2a56d4b3a4fdafe9fdfaac14eee54d6a8db", size = 996, upload-time = "2023-12-20T16:31:01.268Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/5e/942062197dc9679e5d4fa112c3eb782236800cf2c238b08f116cfbd45895/unique_log_filter-0.1.0.tar.gz", hash = "sha256:411ca5b30572293fc37cd93a651da2a56d4b3a4fdafe9fdfaac14eee54d6a8db", size = 996, upload-time = "2023-12-20T16:31:01.268Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c1/e7/c5c1ddac18fee72373b03d3b091d7a5f2ef5ff96bea4491f23cc78e8aecd/unique_log_filter-0.1.0-py3-none-any.whl", hash = "sha256:e0e7012b4d5911233e02d5ae849fd716c1b8af14dfed0e456af1d6dcdd6a1195", size = 1481, upload-time = "2023-12-20T16:31:00.006Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/e7/c5c1ddac18fee72373b03d3b091d7a5f2ef5ff96bea4491f23cc78e8aecd/unique_log_filter-0.1.0-py3-none-any.whl", hash = "sha256:e0e7012b4d5911233e02d5ae849fd716c1b8af14dfed0e456af1d6dcdd6a1195", size = 1481, upload-time = "2023-12-20T16:31:00.006Z" }, ] [[package]] name = "urllib3" version = "2.6.2" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd/urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", size = 432930, upload-time = "2025-12-11T15:56:40.252Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd/urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", size = 432930, upload-time = "2025-12-11T15:56:40.252Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" }, ] [package.optional-dependencies] @@ -4420,49 +4411,49 @@ socks = [ [[package]] name = "urwid" version = "2.6.16" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "typing-extensions" }, { name = "wcwidth" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/21/ad23c9e961b2d36d57c63686a6f86768dd945d406323fb58c84f09478530/urwid-2.6.16.tar.gz", hash = "sha256:93ad239939e44c385e64aa00027878b9e5c486d59e855ec8ab5b1e1adcdb32a2", size = 848179, upload-time = "2024-10-15T16:07:24.297Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/21/ad23c9e961b2d36d57c63686a6f86768dd945d406323fb58c84f09478530/urwid-2.6.16.tar.gz", hash = "sha256:93ad239939e44c385e64aa00027878b9e5c486d59e855ec8ab5b1e1adcdb32a2", size = 848179, upload-time = "2024-10-15T16:07:24.297Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/cb/271a4f5a1bf4208dbdc96d85b9eae744cf4e5e11ac73eda76dc98c8fd2d7/urwid-2.6.16-py3-none-any.whl", hash = "sha256:de14896c6df9eb759ed1fd93e0384a5279e51e0dde8f621e4083f7a8368c0797", size = 297196, upload-time = "2024-10-15T16:07:22.521Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/cb/271a4f5a1bf4208dbdc96d85b9eae744cf4e5e11ac73eda76dc98c8fd2d7/urwid-2.6.16-py3-none-any.whl", hash = "sha256:de14896c6df9eb759ed1fd93e0384a5279e51e0dde8f621e4083f7a8368c0797", size = 297196, upload-time = "2024-10-15T16:07:22.521Z" }, ] [[package]] name = "uuid-utils" version = "0.12.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0b/0e/512fb221e4970c2f75ca9dae412d320b7d9ddc9f2b15e04ea8e44710396c/uuid_utils-0.12.0.tar.gz", hash = "sha256:252bd3d311b5d6b7f5dfce7a5857e27bb4458f222586bb439463231e5a9cbd64", size = 20889, upload-time = "2025-12-01T17:29:55.494Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8a/43/de5cd49a57b6293b911b6a9a62fc03e55db9f964da7d5882d9edbee1e9d2/uuid_utils-0.12.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:3b9b30707659292f207b98f294b0e081f6d77e1fbc760ba5b41331a39045f514", size = 603197, upload-time = "2025-12-01T17:29:30.104Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/fa/5fd1d8c9234e44f0c223910808cde0de43bb69f7df1349e49b1afa7f2baa/uuid_utils-0.12.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:add3d820c7ec14ed37317375bea30249699c5d08ff4ae4dbee9fc9bce3bfbf65", size = 305168, upload-time = "2025-12-01T17:29:31.384Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c8/c6/8633ac9942bf9dc97a897b5154e5dcffa58816ec4dd780b3b12b559ff05c/uuid_utils-0.12.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b8fce83ecb3b16af29c7809669056c4b6e7cc912cab8c6d07361645de12dd79", size = 340580, upload-time = "2025-12-01T17:29:32.362Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f3/88/8a61307b04b4da1c576373003e6d857a04dade52ab035151d62cb84d5cb5/uuid_utils-0.12.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec921769afcb905035d785582b0791d02304a7850fbd6ce924c1a8976380dfc6", size = 346771, upload-time = "2025-12-01T17:29:33.708Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1c/fb/aab2dcf94b991e62aa167457c7825b9b01055b884b888af926562864398c/uuid_utils-0.12.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f3b060330f5899a92d5c723547dc6a95adef42433e9748f14c66859a7396664", size = 474781, upload-time = "2025-12-01T17:29:35.237Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/7a/dbd5e49c91d6c86dba57158bbfa0e559e1ddf377bb46dcfd58aea4f0d567/uuid_utils-0.12.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:908dfef7f0bfcf98d406e5dc570c25d2f2473e49b376de41792b6e96c1d5d291", size = 343685, upload-time = "2025-12-01T17:29:36.677Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1a/19/8c4b1d9f450159733b8be421a4e1fb03533709b80ed3546800102d085572/uuid_utils-0.12.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c6a24148926bd0ca63e8a2dabf4cc9dc329a62325b3ad6578ecd60fbf926506", size = 366482, upload-time = "2025-12-01T17:29:37.979Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/82/43/c79a6e45687647f80a159c8ba34346f287b065452cc419d07d2212d38420/uuid_utils-0.12.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:64a91e632669f059ef605f1771d28490b1d310c26198e46f754e8846dddf12f4", size = 523132, upload-time = "2025-12-01T17:29:39.293Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/a2/b2d75a621260a40c438aa88593827dfea596d18316520a99e839f7a5fb9d/uuid_utils-0.12.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:93c082212470bb4603ca3975916c205a9d7ef1443c0acde8fbd1e0f5b36673c7", size = 614218, upload-time = "2025-12-01T17:29:40.315Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/13/6b/ba071101626edd5a6dabf8525c9a1537ff3d885dbc210540574a03901fef/uuid_utils-0.12.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:431b1fb7283ba974811b22abd365f2726f8f821ab33f0f715be389640e18d039", size = 546241, upload-time = "2025-12-01T17:29:41.656Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/01/12/9a942b81c0923268e6d85bf98d8f0a61fcbcd5e432fef94fdf4ce2ef8748/uuid_utils-0.12.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2ffd7838c40149100299fa37cbd8bab5ee382372e8e65a148002a37d380df7c8", size = 511842, upload-time = "2025-12-01T17:29:43.107Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a9/a7/c326f5163dd48b79368b87d8a05f5da4668dd228a3f5ca9d79d5fee2fc40/uuid_utils-0.12.0-cp39-abi3-win32.whl", hash = "sha256:487f17c0fee6cbc1d8b90fe811874174a9b1b5683bf2251549e302906a50fed3", size = 179088, upload-time = "2025-12-01T17:29:44.492Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/38/92/41c8734dd97213ee1d5ae435cf4499705dc4f2751e3b957fd12376f61784/uuid_utils-0.12.0-cp39-abi3-win_amd64.whl", hash = "sha256:9598e7c9da40357ae8fffc5d6938b1a7017f09a1acbcc95e14af8c65d48c655a", size = 183003, upload-time = "2025-12-01T17:29:45.47Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c9/f9/52ab0359618987331a1f739af837d26168a4b16281c9c3ab46519940c628/uuid_utils-0.12.0-cp39-abi3-win_arm64.whl", hash = "sha256:c9bea7c5b2aa6f57937ebebeee4d4ef2baad10f86f1b97b58a3f6f34c14b4e84", size = 182975, upload-time = "2025-12-01T17:29:46.444Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0b/0e/512fb221e4970c2f75ca9dae412d320b7d9ddc9f2b15e04ea8e44710396c/uuid_utils-0.12.0.tar.gz", hash = "sha256:252bd3d311b5d6b7f5dfce7a5857e27bb4458f222586bb439463231e5a9cbd64", size = 20889, upload-time = "2025-12-01T17:29:55.494Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/43/de5cd49a57b6293b911b6a9a62fc03e55db9f964da7d5882d9edbee1e9d2/uuid_utils-0.12.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:3b9b30707659292f207b98f294b0e081f6d77e1fbc760ba5b41331a39045f514", size = 603197, upload-time = "2025-12-01T17:29:30.104Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/fa/5fd1d8c9234e44f0c223910808cde0de43bb69f7df1349e49b1afa7f2baa/uuid_utils-0.12.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:add3d820c7ec14ed37317375bea30249699c5d08ff4ae4dbee9fc9bce3bfbf65", size = 305168, upload-time = "2025-12-01T17:29:31.384Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c8/c6/8633ac9942bf9dc97a897b5154e5dcffa58816ec4dd780b3b12b559ff05c/uuid_utils-0.12.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b8fce83ecb3b16af29c7809669056c4b6e7cc912cab8c6d07361645de12dd79", size = 340580, upload-time = "2025-12-01T17:29:32.362Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/88/8a61307b04b4da1c576373003e6d857a04dade52ab035151d62cb84d5cb5/uuid_utils-0.12.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec921769afcb905035d785582b0791d02304a7850fbd6ce924c1a8976380dfc6", size = 346771, upload-time = "2025-12-01T17:29:33.708Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/fb/aab2dcf94b991e62aa167457c7825b9b01055b884b888af926562864398c/uuid_utils-0.12.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f3b060330f5899a92d5c723547dc6a95adef42433e9748f14c66859a7396664", size = 474781, upload-time = "2025-12-01T17:29:35.237Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/7a/dbd5e49c91d6c86dba57158bbfa0e559e1ddf377bb46dcfd58aea4f0d567/uuid_utils-0.12.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:908dfef7f0bfcf98d406e5dc570c25d2f2473e49b376de41792b6e96c1d5d291", size = 343685, upload-time = "2025-12-01T17:29:36.677Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1a/19/8c4b1d9f450159733b8be421a4e1fb03533709b80ed3546800102d085572/uuid_utils-0.12.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c6a24148926bd0ca63e8a2dabf4cc9dc329a62325b3ad6578ecd60fbf926506", size = 366482, upload-time = "2025-12-01T17:29:37.979Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/82/43/c79a6e45687647f80a159c8ba34346f287b065452cc419d07d2212d38420/uuid_utils-0.12.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:64a91e632669f059ef605f1771d28490b1d310c26198e46f754e8846dddf12f4", size = 523132, upload-time = "2025-12-01T17:29:39.293Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/a2/b2d75a621260a40c438aa88593827dfea596d18316520a99e839f7a5fb9d/uuid_utils-0.12.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:93c082212470bb4603ca3975916c205a9d7ef1443c0acde8fbd1e0f5b36673c7", size = 614218, upload-time = "2025-12-01T17:29:40.315Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/13/6b/ba071101626edd5a6dabf8525c9a1537ff3d885dbc210540574a03901fef/uuid_utils-0.12.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:431b1fb7283ba974811b22abd365f2726f8f821ab33f0f715be389640e18d039", size = 546241, upload-time = "2025-12-01T17:29:41.656Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/01/12/9a942b81c0923268e6d85bf98d8f0a61fcbcd5e432fef94fdf4ce2ef8748/uuid_utils-0.12.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2ffd7838c40149100299fa37cbd8bab5ee382372e8e65a148002a37d380df7c8", size = 511842, upload-time = "2025-12-01T17:29:43.107Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a9/a7/c326f5163dd48b79368b87d8a05f5da4668dd228a3f5ca9d79d5fee2fc40/uuid_utils-0.12.0-cp39-abi3-win32.whl", hash = "sha256:487f17c0fee6cbc1d8b90fe811874174a9b1b5683bf2251549e302906a50fed3", size = 179088, upload-time = "2025-12-01T17:29:44.492Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/92/41c8734dd97213ee1d5ae435cf4499705dc4f2751e3b957fd12376f61784/uuid_utils-0.12.0-cp39-abi3-win_amd64.whl", hash = "sha256:9598e7c9da40357ae8fffc5d6938b1a7017f09a1acbcc95e14af8c65d48c655a", size = 183003, upload-time = "2025-12-01T17:29:45.47Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c9/f9/52ab0359618987331a1f739af837d26168a4b16281c9c3ab46519940c628/uuid_utils-0.12.0-cp39-abi3-win_arm64.whl", hash = "sha256:c9bea7c5b2aa6f57937ebebeee4d4ef2baad10f86f1b97b58a3f6f34c14b4e84", size = 182975, upload-time = "2025-12-01T17:29:46.444Z" }, ] [[package]] name = "uvicorn" version = "0.40.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "click" }, { name = "h11" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c3/d1/8f3c683c9561a4e6689dd3b1d345c815f10f86acd044ee1fb9a4dcd0b8c5/uvicorn-0.40.0.tar.gz", hash = "sha256:839676675e87e73694518b5574fd0f24c9d97b46bea16df7b8c05ea1a51071ea", size = 81761, upload-time = "2025-12-21T14:16:22.45Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c3/d1/8f3c683c9561a4e6689dd3b1d345c815f10f86acd044ee1fb9a4dcd0b8c5/uvicorn-0.40.0.tar.gz", hash = "sha256:839676675e87e73694518b5574fd0f24c9d97b46bea16df7b8c05ea1a51071ea", size = 81761, upload-time = "2025-12-21T14:16:22.45Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/d8/2083a1daa7439a66f3a48589a57d576aa117726762618f6bb09fe3798796/uvicorn-0.40.0-py3-none-any.whl", hash = "sha256:c6c8f55bc8bf13eb6fa9ff87ad62308bbbc33d0b67f84293151efe87e0d5f2ee", size = 68502, upload-time = "2025-12-21T14:16:21.041Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/d8/2083a1daa7439a66f3a48589a57d576aa117726762618f6bb09fe3798796/uvicorn-0.40.0-py3-none-any.whl", hash = "sha256:c6c8f55bc8bf13eb6fa9ff87ad62308bbbc33d0b67f84293151efe87e0d5f2ee", size = 68502, upload-time = "2025-12-21T14:16:21.041Z" }, ] [package.optional-dependencies] @@ -4479,384 +4470,384 @@ standard = [ [[package]] name = "uvloop" version = "0.22.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/f0/18d39dbd1971d6d62c4629cc7fa67f74821b0dc1f5a77af43719de7936a7/uvloop-0.22.1.tar.gz", hash = "sha256:6c84bae345b9147082b17371e3dd5d42775bddce91f885499017f4607fdaf39f", size = 2443250, upload-time = "2025-10-16T22:17:19.342Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/f0/18d39dbd1971d6d62c4629cc7fa67f74821b0dc1f5a77af43719de7936a7/uvloop-0.22.1.tar.gz", hash = "sha256:6c84bae345b9147082b17371e3dd5d42775bddce91f885499017f4607fdaf39f", size = 2443250, upload-time = "2025-10-16T22:17:19.342Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/ff/7f72e8170be527b4977b033239a83a68d5c881cc4775fca255c677f7ac5d/uvloop-0.22.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42", size = 1359936, upload-time = "2025-10-16T22:16:29.436Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c3/c6/e5d433f88fd54d81ef4be58b2b7b0cea13c442454a1db703a1eea0db1a59/uvloop-0.22.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:51eb9bd88391483410daad430813d982010f9c9c89512321f5b60e2cddbdddd6", size = 752769, upload-time = "2025-10-16T22:16:30.493Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/24/68/a6ac446820273e71aa762fa21cdcc09861edd3536ff47c5cd3b7afb10eeb/uvloop-0.22.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:700e674a166ca5778255e0e1dc4e9d79ab2acc57b9171b79e65feba7184b3370", size = 4317413, upload-time = "2025-10-16T22:16:31.644Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5f/6f/e62b4dfc7ad6518e7eff2516f680d02a0f6eb62c0c212e152ca708a0085e/uvloop-0.22.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b5b1ac819a3f946d3b2ee07f09149578ae76066d70b44df3fa990add49a82e4", size = 4426307, upload-time = "2025-10-16T22:16:32.917Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/90/60/97362554ac21e20e81bcef1150cb2a7e4ffdaf8ea1e5b2e8bf7a053caa18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e047cc068570bac9866237739607d1313b9253c3051ad84738cbb095be0537b2", size = 4131970, upload-time = "2025-10-16T22:16:34.015Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/99/39/6b3f7d234ba3964c428a6e40006340f53ba37993f46ed6e111c6e9141d18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:512fec6815e2dd45161054592441ef76c830eddaad55c8aa30952e6fe1ed07c0", size = 4296343, upload-time = "2025-10-16T22:16:35.149Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/89/8c/182a2a593195bfd39842ea68ebc084e20c850806117213f5a299dfc513d9/uvloop-0.22.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:561577354eb94200d75aca23fbde86ee11be36b00e52a4eaf8f50fb0c86b7705", size = 1358611, upload-time = "2025-10-16T22:16:36.833Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/14/e301ee96a6dc95224b6f1162cd3312f6d1217be3907b79173b06785f2fe7/uvloop-0.22.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cdf5192ab3e674ca26da2eada35b288d2fa49fdd0f357a19f0e7c4e7d5077c8", size = 751811, upload-time = "2025-10-16T22:16:38.275Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b7/02/654426ce265ac19e2980bfd9ea6590ca96a56f10c76e63801a2df01c0486/uvloop-0.22.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e2ea3d6190a2968f4a14a23019d3b16870dd2190cd69c8180f7c632d21de68d", size = 4288562, upload-time = "2025-10-16T22:16:39.375Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/15/c0/0be24758891ef825f2065cd5db8741aaddabe3e248ee6acc5e8a80f04005/uvloop-0.22.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0530a5fbad9c9e4ee3f2b33b148c6a64d47bbad8000ea63704fa8260f4cf728e", size = 4366890, upload-time = "2025-10-16T22:16:40.547Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d2/53/8369e5219a5855869bcee5f4d317f6da0e2c669aecf0ef7d371e3d084449/uvloop-0.22.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bc5ef13bbc10b5335792360623cc378d52d7e62c2de64660616478c32cd0598e", size = 4119472, upload-time = "2025-10-16T22:16:41.694Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f8/ba/d69adbe699b768f6b29a5eec7b47dd610bd17a69de51b251126a801369ea/uvloop-0.22.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1f38ec5e3f18c8a10ded09742f7fb8de0108796eb673f30ce7762ce1b8550cad", size = 4239051, upload-time = "2025-10-16T22:16:43.224Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/ff/7f72e8170be527b4977b033239a83a68d5c881cc4775fca255c677f7ac5d/uvloop-0.22.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42", size = 1359936, upload-time = "2025-10-16T22:16:29.436Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c3/c6/e5d433f88fd54d81ef4be58b2b7b0cea13c442454a1db703a1eea0db1a59/uvloop-0.22.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:51eb9bd88391483410daad430813d982010f9c9c89512321f5b60e2cddbdddd6", size = 752769, upload-time = "2025-10-16T22:16:30.493Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/24/68/a6ac446820273e71aa762fa21cdcc09861edd3536ff47c5cd3b7afb10eeb/uvloop-0.22.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:700e674a166ca5778255e0e1dc4e9d79ab2acc57b9171b79e65feba7184b3370", size = 4317413, upload-time = "2025-10-16T22:16:31.644Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/6f/e62b4dfc7ad6518e7eff2516f680d02a0f6eb62c0c212e152ca708a0085e/uvloop-0.22.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b5b1ac819a3f946d3b2ee07f09149578ae76066d70b44df3fa990add49a82e4", size = 4426307, upload-time = "2025-10-16T22:16:32.917Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/90/60/97362554ac21e20e81bcef1150cb2a7e4ffdaf8ea1e5b2e8bf7a053caa18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e047cc068570bac9866237739607d1313b9253c3051ad84738cbb095be0537b2", size = 4131970, upload-time = "2025-10-16T22:16:34.015Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/99/39/6b3f7d234ba3964c428a6e40006340f53ba37993f46ed6e111c6e9141d18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:512fec6815e2dd45161054592441ef76c830eddaad55c8aa30952e6fe1ed07c0", size = 4296343, upload-time = "2025-10-16T22:16:35.149Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/89/8c/182a2a593195bfd39842ea68ebc084e20c850806117213f5a299dfc513d9/uvloop-0.22.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:561577354eb94200d75aca23fbde86ee11be36b00e52a4eaf8f50fb0c86b7705", size = 1358611, upload-time = "2025-10-16T22:16:36.833Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/14/e301ee96a6dc95224b6f1162cd3312f6d1217be3907b79173b06785f2fe7/uvloop-0.22.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cdf5192ab3e674ca26da2eada35b288d2fa49fdd0f357a19f0e7c4e7d5077c8", size = 751811, upload-time = "2025-10-16T22:16:38.275Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/02/654426ce265ac19e2980bfd9ea6590ca96a56f10c76e63801a2df01c0486/uvloop-0.22.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e2ea3d6190a2968f4a14a23019d3b16870dd2190cd69c8180f7c632d21de68d", size = 4288562, upload-time = "2025-10-16T22:16:39.375Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/15/c0/0be24758891ef825f2065cd5db8741aaddabe3e248ee6acc5e8a80f04005/uvloop-0.22.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0530a5fbad9c9e4ee3f2b33b148c6a64d47bbad8000ea63704fa8260f4cf728e", size = 4366890, upload-time = "2025-10-16T22:16:40.547Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d2/53/8369e5219a5855869bcee5f4d317f6da0e2c669aecf0ef7d371e3d084449/uvloop-0.22.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bc5ef13bbc10b5335792360623cc378d52d7e62c2de64660616478c32cd0598e", size = 4119472, upload-time = "2025-10-16T22:16:41.694Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f8/ba/d69adbe699b768f6b29a5eec7b47dd610bd17a69de51b251126a801369ea/uvloop-0.22.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1f38ec5e3f18c8a10ded09742f7fb8de0108796eb673f30ce7762ce1b8550cad", size = 4239051, upload-time = "2025-10-16T22:16:43.224Z" }, ] [[package]] name = "virtualenv" version = "20.35.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/20/28/e6f1a6f655d620846bd9df527390ecc26b3805a0c5989048c210e22c5ca9/virtualenv-20.35.4.tar.gz", hash = "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c", size = 6028799, upload-time = "2025-10-29T06:57:40.511Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/28/e6f1a6f655d620846bd9df527390ecc26b3805a0c5989048c210e22c5ca9/virtualenv-20.35.4.tar.gz", hash = "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c", size = 6028799, upload-time = "2025-10-29T06:57:40.511Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl", hash = "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b", size = 6005095, upload-time = "2025-10-29T06:57:37.598Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl", hash = "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b", size = 6005095, upload-time = "2025-10-29T06:57:37.598Z" }, ] [[package]] name = "watchfiles" version = "1.1.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c2/c9/8869df9b2a2d6c59d79220a4db37679e74f807c559ffe5265e08b227a210/watchfiles-1.1.1.tar.gz", hash = "sha256:a173cb5c16c4f40ab19cecf48a534c409f7ea983ab8fed0741304a1c0a31b3f2", size = 94440, upload-time = "2025-10-14T15:06:21.08Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/74/d5/f039e7e3c639d9b1d09b07ea412a6806d38123f0508e5f9b48a87b0a76cc/watchfiles-1.1.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8c89f9f2f740a6b7dcc753140dd5e1ab9215966f7a3530d0c0705c83b401bd7d", size = 404745, upload-time = "2025-10-14T15:04:46.731Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a5/96/a881a13aa1349827490dab2d363c8039527060cfcc2c92cc6d13d1b1049e/watchfiles-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd404be08018c37350f0d6e34676bd1e2889990117a2b90070b3007f172d0610", size = 391769, upload-time = "2025-10-14T15:04:48.003Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4b/5b/d3b460364aeb8da471c1989238ea0e56bec24b6042a68046adf3d9ddb01c/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8526e8f916bb5b9a0a777c8317c23ce65de259422bba5b31325a6fa6029d33af", size = 449374, upload-time = "2025-10-14T15:04:49.179Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b9/44/5769cb62d4ed055cb17417c0a109a92f007114a4e07f30812a73a4efdb11/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2edc3553362b1c38d9f06242416a5d8e9fe235c204a4072e988ce2e5bb1f69f6", size = 459485, upload-time = "2025-10-14T15:04:50.155Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/19/0c/286b6301ded2eccd4ffd0041a1b726afda999926cf720aab63adb68a1e36/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30f7da3fb3f2844259cba4720c3fc7138eb0f7b659c38f3bfa65084c7fc7abce", size = 488813, upload-time = "2025-10-14T15:04:51.059Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c7/2b/8530ed41112dd4a22f4dcfdb5ccf6a1baad1ff6eed8dc5a5f09e7e8c41c7/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8979280bdafff686ba5e4d8f97840f929a87ed9cdf133cbbd42f7766774d2aa", size = 594816, upload-time = "2025-10-14T15:04:52.031Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/d2/f5f9fb49489f184f18470d4f99f4e862a4b3e9ac2865688eb2099e3d837a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcc5c24523771db3a294c77d94771abcfcb82a0e0ee8efd910c37c59ec1b31bb", size = 475186, upload-time = "2025-10-14T15:04:53.064Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cf/68/5707da262a119fb06fbe214d82dd1fe4a6f4af32d2d14de368d0349eb52a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db5d7ae38ff20153d542460752ff397fcf5c96090c1230803713cf3147a6803", size = 456812, upload-time = "2025-10-14T15:04:55.174Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/66/ab/3cbb8756323e8f9b6f9acb9ef4ec26d42b2109bce830cc1f3468df20511d/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:28475ddbde92df1874b6c5c8aaeb24ad5be47a11f87cde5a28ef3835932e3e94", size = 630196, upload-time = "2025-10-14T15:04:56.22Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/78/46/7152ec29b8335f80167928944a94955015a345440f524d2dfe63fc2f437b/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:36193ed342f5b9842edd3532729a2ad55c4160ffcfa3700e0d54be496b70dd43", size = 622657, upload-time = "2025-10-14T15:04:57.521Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/bf/95895e78dd75efe9a7f31733607f384b42eb5feb54bd2eb6ed57cc2e94f4/watchfiles-1.1.1-cp312-cp312-win32.whl", hash = "sha256:859e43a1951717cc8de7f4c77674a6d389b106361585951d9e69572823f311d9", size = 272042, upload-time = "2025-10-14T15:04:59.046Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/87/0a/90eb755f568de2688cb220171c4191df932232c20946966c27a59c400850/watchfiles-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:91d4c9a823a8c987cce8fa2690923b069966dabb196dd8d137ea2cede885fde9", size = 288410, upload-time = "2025-10-14T15:05:00.081Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/36/76/f322701530586922fbd6723c4f91ace21364924822a8772c549483abed13/watchfiles-1.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:a625815d4a2bdca61953dbba5a39d60164451ef34c88d751f6c368c3ea73d404", size = 278209, upload-time = "2025-10-14T15:05:01.168Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bb/f4/f750b29225fe77139f7ae5de89d4949f5a99f934c65a1f1c0b248f26f747/watchfiles-1.1.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:130e4876309e8686a5e37dba7d5e9bc77e6ed908266996ca26572437a5271e18", size = 404321, upload-time = "2025-10-14T15:05:02.063Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2b/f9/f07a295cde762644aa4c4bb0f88921d2d141af45e735b965fb2e87858328/watchfiles-1.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f3bde70f157f84ece3765b42b4a52c6ac1a50334903c6eaf765362f6ccca88a", size = 391783, upload-time = "2025-10-14T15:05:03.052Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bc/11/fc2502457e0bea39a5c958d86d2cb69e407a4d00b85735ca724bfa6e0d1a/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e0b1fe858430fc0251737ef3824c54027bedb8c37c38114488b8e131cf8219", size = 449279, upload-time = "2025-10-14T15:05:04.004Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e3/1f/d66bc15ea0b728df3ed96a539c777acfcad0eb78555ad9efcaa1274688f0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f27db948078f3823a6bb3b465180db8ebecf26dd5dae6f6180bd87383b6b4428", size = 459405, upload-time = "2025-10-14T15:05:04.942Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/be/90/9f4a65c0aec3ccf032703e6db02d89a157462fbb2cf20dd415128251cac0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:059098c3a429f62fc98e8ec62b982230ef2c8df68c79e826e37b895bc359a9c0", size = 488976, upload-time = "2025-10-14T15:05:05.905Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/37/57/ee347af605d867f712be7029bb94c8c071732a4b44792e3176fa3c612d39/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfb5862016acc9b869bb57284e6cb35fdf8e22fe59f7548858e2f971d045f150", size = 595506, upload-time = "2025-10-14T15:05:06.906Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a8/78/cc5ab0b86c122047f75e8fc471c67a04dee395daf847d3e59381996c8707/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:319b27255aacd9923b8a276bb14d21a5f7ff82564c744235fc5eae58d95422ae", size = 474936, upload-time = "2025-10-14T15:05:07.906Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/62/da/def65b170a3815af7bd40a3e7010bf6ab53089ef1b75d05dd5385b87cf08/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c755367e51db90e75b19454b680903631d41f9e3607fbd941d296a020c2d752d", size = 456147, upload-time = "2025-10-14T15:05:09.138Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/57/99/da6573ba71166e82d288d4df0839128004c67d2778d3b566c138695f5c0b/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c22c776292a23bfc7237a98f791b9ad3144b02116ff10d820829ce62dff46d0b", size = 630007, upload-time = "2025-10-14T15:05:10.117Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a8/51/7439c4dd39511368849eb1e53279cd3454b4a4dbace80bab88feeb83c6b5/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:3a476189be23c3686bc2f4321dd501cb329c0a0469e77b7b534ee10129ae6374", size = 622280, upload-time = "2025-10-14T15:05:11.146Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/9c/8ed97d4bba5db6fdcdb2b298d3898f2dd5c20f6b73aee04eabe56c59677e/watchfiles-1.1.1-cp313-cp313-win32.whl", hash = "sha256:bf0a91bfb5574a2f7fc223cf95eeea79abfefa404bf1ea5e339c0c1560ae99a0", size = 272056, upload-time = "2025-10-14T15:05:12.156Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1f/f3/c14e28429f744a260d8ceae18bf58c1d5fa56b50d006a7a9f80e1882cb0d/watchfiles-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:52e06553899e11e8074503c8e716d574adeeb7e68913115c4b3653c53f9bae42", size = 288162, upload-time = "2025-10-14T15:05:13.208Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/61/fe0e56c40d5cd29523e398d31153218718c5786b5e636d9ae8ae79453d27/watchfiles-1.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:ac3cc5759570cd02662b15fbcd9d917f7ecd47efe0d6b40474eafd246f91ea18", size = 277909, upload-time = "2025-10-14T15:05:14.49Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/79/42/e0a7d749626f1e28c7108a99fb9bf524b501bbbeb9b261ceecde644d5a07/watchfiles-1.1.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:563b116874a9a7ce6f96f87cd0b94f7faf92d08d0021e837796f0a14318ef8da", size = 403389, upload-time = "2025-10-14T15:05:15.777Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/15/49/08732f90ce0fbbc13913f9f215c689cfc9ced345fb1bcd8829a50007cc8d/watchfiles-1.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3ad9fe1dae4ab4212d8c91e80b832425e24f421703b5a42ef2e4a1e215aff051", size = 389964, upload-time = "2025-10-14T15:05:16.85Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/27/0d/7c315d4bd5f2538910491a0393c56bf70d333d51bc5b34bee8e68e8cea19/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce70f96a46b894b36eba678f153f052967a0d06d5b5a19b336ab0dbbd029f73e", size = 448114, upload-time = "2025-10-14T15:05:17.876Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c3/24/9e096de47a4d11bc4df41e9d1e61776393eac4cb6eb11b3e23315b78b2cc/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cb467c999c2eff23a6417e58d75e5828716f42ed8289fe6b77a7e5a91036ca70", size = 460264, upload-time = "2025-10-14T15:05:18.962Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cc/0f/e8dea6375f1d3ba5fcb0b3583e2b493e77379834c74fd5a22d66d85d6540/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:836398932192dae4146c8f6f737d74baeac8b70ce14831a239bdb1ca882fc261", size = 487877, upload-time = "2025-10-14T15:05:20.094Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ac/5b/df24cfc6424a12deb41503b64d42fbea6b8cb357ec62ca84a5a3476f654a/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:743185e7372b7bc7c389e1badcc606931a827112fbbd37f14c537320fca08620", size = 595176, upload-time = "2025-10-14T15:05:21.134Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8f/b5/853b6757f7347de4e9b37e8cc3289283fb983cba1ab4d2d7144694871d9c/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afaeff7696e0ad9f02cbb8f56365ff4686ab205fcf9c4c5b6fdfaaa16549dd04", size = 473577, upload-time = "2025-10-14T15:05:22.306Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e1/f7/0a4467be0a56e80447c8529c9fce5b38eab4f513cb3d9bf82e7392a5696b/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7eb7da0eb23aa2ba036d4f616d46906013a68caf61b7fdbe42fc8b25132e77", size = 455425, upload-time = "2025-10-14T15:05:23.348Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8e/e0/82583485ea00137ddf69bc84a2db88bd92ab4a6e3c405e5fb878ead8d0e7/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:831a62658609f0e5c64178211c942ace999517f5770fe9436be4c2faeba0c0ef", size = 628826, upload-time = "2025-10-14T15:05:24.398Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/28/9a/a785356fccf9fae84c0cc90570f11702ae9571036fb25932f1242c82191c/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:f9a2ae5c91cecc9edd47e041a930490c31c3afb1f5e6d71de3dc671bfaca02bf", size = 622208, upload-time = "2025-10-14T15:05:25.45Z" }, +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/c9/8869df9b2a2d6c59d79220a4db37679e74f807c559ffe5265e08b227a210/watchfiles-1.1.1.tar.gz", hash = "sha256:a173cb5c16c4f40ab19cecf48a534c409f7ea983ab8fed0741304a1c0a31b3f2", size = 94440, upload-time = "2025-10-14T15:06:21.08Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/74/d5/f039e7e3c639d9b1d09b07ea412a6806d38123f0508e5f9b48a87b0a76cc/watchfiles-1.1.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8c89f9f2f740a6b7dcc753140dd5e1ab9215966f7a3530d0c0705c83b401bd7d", size = 404745, upload-time = "2025-10-14T15:04:46.731Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a5/96/a881a13aa1349827490dab2d363c8039527060cfcc2c92cc6d13d1b1049e/watchfiles-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd404be08018c37350f0d6e34676bd1e2889990117a2b90070b3007f172d0610", size = 391769, upload-time = "2025-10-14T15:04:48.003Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4b/5b/d3b460364aeb8da471c1989238ea0e56bec24b6042a68046adf3d9ddb01c/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8526e8f916bb5b9a0a777c8317c23ce65de259422bba5b31325a6fa6029d33af", size = 449374, upload-time = "2025-10-14T15:04:49.179Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/44/5769cb62d4ed055cb17417c0a109a92f007114a4e07f30812a73a4efdb11/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2edc3553362b1c38d9f06242416a5d8e9fe235c204a4072e988ce2e5bb1f69f6", size = 459485, upload-time = "2025-10-14T15:04:50.155Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/0c/286b6301ded2eccd4ffd0041a1b726afda999926cf720aab63adb68a1e36/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30f7da3fb3f2844259cba4720c3fc7138eb0f7b659c38f3bfa65084c7fc7abce", size = 488813, upload-time = "2025-10-14T15:04:51.059Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c7/2b/8530ed41112dd4a22f4dcfdb5ccf6a1baad1ff6eed8dc5a5f09e7e8c41c7/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8979280bdafff686ba5e4d8f97840f929a87ed9cdf133cbbd42f7766774d2aa", size = 594816, upload-time = "2025-10-14T15:04:52.031Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/d2/f5f9fb49489f184f18470d4f99f4e862a4b3e9ac2865688eb2099e3d837a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcc5c24523771db3a294c77d94771abcfcb82a0e0ee8efd910c37c59ec1b31bb", size = 475186, upload-time = "2025-10-14T15:04:53.064Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cf/68/5707da262a119fb06fbe214d82dd1fe4a6f4af32d2d14de368d0349eb52a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db5d7ae38ff20153d542460752ff397fcf5c96090c1230803713cf3147a6803", size = 456812, upload-time = "2025-10-14T15:04:55.174Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/ab/3cbb8756323e8f9b6f9acb9ef4ec26d42b2109bce830cc1f3468df20511d/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:28475ddbde92df1874b6c5c8aaeb24ad5be47a11f87cde5a28ef3835932e3e94", size = 630196, upload-time = "2025-10-14T15:04:56.22Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/78/46/7152ec29b8335f80167928944a94955015a345440f524d2dfe63fc2f437b/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:36193ed342f5b9842edd3532729a2ad55c4160ffcfa3700e0d54be496b70dd43", size = 622657, upload-time = "2025-10-14T15:04:57.521Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/bf/95895e78dd75efe9a7f31733607f384b42eb5feb54bd2eb6ed57cc2e94f4/watchfiles-1.1.1-cp312-cp312-win32.whl", hash = "sha256:859e43a1951717cc8de7f4c77674a6d389b106361585951d9e69572823f311d9", size = 272042, upload-time = "2025-10-14T15:04:59.046Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/87/0a/90eb755f568de2688cb220171c4191df932232c20946966c27a59c400850/watchfiles-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:91d4c9a823a8c987cce8fa2690923b069966dabb196dd8d137ea2cede885fde9", size = 288410, upload-time = "2025-10-14T15:05:00.081Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/36/76/f322701530586922fbd6723c4f91ace21364924822a8772c549483abed13/watchfiles-1.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:a625815d4a2bdca61953dbba5a39d60164451ef34c88d751f6c368c3ea73d404", size = 278209, upload-time = "2025-10-14T15:05:01.168Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bb/f4/f750b29225fe77139f7ae5de89d4949f5a99f934c65a1f1c0b248f26f747/watchfiles-1.1.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:130e4876309e8686a5e37dba7d5e9bc77e6ed908266996ca26572437a5271e18", size = 404321, upload-time = "2025-10-14T15:05:02.063Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/f9/f07a295cde762644aa4c4bb0f88921d2d141af45e735b965fb2e87858328/watchfiles-1.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f3bde70f157f84ece3765b42b4a52c6ac1a50334903c6eaf765362f6ccca88a", size = 391783, upload-time = "2025-10-14T15:05:03.052Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bc/11/fc2502457e0bea39a5c958d86d2cb69e407a4d00b85735ca724bfa6e0d1a/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e0b1fe858430fc0251737ef3824c54027bedb8c37c38114488b8e131cf8219", size = 449279, upload-time = "2025-10-14T15:05:04.004Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/1f/d66bc15ea0b728df3ed96a539c777acfcad0eb78555ad9efcaa1274688f0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f27db948078f3823a6bb3b465180db8ebecf26dd5dae6f6180bd87383b6b4428", size = 459405, upload-time = "2025-10-14T15:05:04.942Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/be/90/9f4a65c0aec3ccf032703e6db02d89a157462fbb2cf20dd415128251cac0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:059098c3a429f62fc98e8ec62b982230ef2c8df68c79e826e37b895bc359a9c0", size = 488976, upload-time = "2025-10-14T15:05:05.905Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/37/57/ee347af605d867f712be7029bb94c8c071732a4b44792e3176fa3c612d39/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfb5862016acc9b869bb57284e6cb35fdf8e22fe59f7548858e2f971d045f150", size = 595506, upload-time = "2025-10-14T15:05:06.906Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a8/78/cc5ab0b86c122047f75e8fc471c67a04dee395daf847d3e59381996c8707/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:319b27255aacd9923b8a276bb14d21a5f7ff82564c744235fc5eae58d95422ae", size = 474936, upload-time = "2025-10-14T15:05:07.906Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/62/da/def65b170a3815af7bd40a3e7010bf6ab53089ef1b75d05dd5385b87cf08/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c755367e51db90e75b19454b680903631d41f9e3607fbd941d296a020c2d752d", size = 456147, upload-time = "2025-10-14T15:05:09.138Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/57/99/da6573ba71166e82d288d4df0839128004c67d2778d3b566c138695f5c0b/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c22c776292a23bfc7237a98f791b9ad3144b02116ff10d820829ce62dff46d0b", size = 630007, upload-time = "2025-10-14T15:05:10.117Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a8/51/7439c4dd39511368849eb1e53279cd3454b4a4dbace80bab88feeb83c6b5/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:3a476189be23c3686bc2f4321dd501cb329c0a0469e77b7b534ee10129ae6374", size = 622280, upload-time = "2025-10-14T15:05:11.146Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/9c/8ed97d4bba5db6fdcdb2b298d3898f2dd5c20f6b73aee04eabe56c59677e/watchfiles-1.1.1-cp313-cp313-win32.whl", hash = "sha256:bf0a91bfb5574a2f7fc223cf95eeea79abfefa404bf1ea5e339c0c1560ae99a0", size = 272056, upload-time = "2025-10-14T15:05:12.156Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1f/f3/c14e28429f744a260d8ceae18bf58c1d5fa56b50d006a7a9f80e1882cb0d/watchfiles-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:52e06553899e11e8074503c8e716d574adeeb7e68913115c4b3653c53f9bae42", size = 288162, upload-time = "2025-10-14T15:05:13.208Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/61/fe0e56c40d5cd29523e398d31153218718c5786b5e636d9ae8ae79453d27/watchfiles-1.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:ac3cc5759570cd02662b15fbcd9d917f7ecd47efe0d6b40474eafd246f91ea18", size = 277909, upload-time = "2025-10-14T15:05:14.49Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/42/e0a7d749626f1e28c7108a99fb9bf524b501bbbeb9b261ceecde644d5a07/watchfiles-1.1.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:563b116874a9a7ce6f96f87cd0b94f7faf92d08d0021e837796f0a14318ef8da", size = 403389, upload-time = "2025-10-14T15:05:15.777Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/15/49/08732f90ce0fbbc13913f9f215c689cfc9ced345fb1bcd8829a50007cc8d/watchfiles-1.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3ad9fe1dae4ab4212d8c91e80b832425e24f421703b5a42ef2e4a1e215aff051", size = 389964, upload-time = "2025-10-14T15:05:16.85Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/27/0d/7c315d4bd5f2538910491a0393c56bf70d333d51bc5b34bee8e68e8cea19/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce70f96a46b894b36eba678f153f052967a0d06d5b5a19b336ab0dbbd029f73e", size = 448114, upload-time = "2025-10-14T15:05:17.876Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c3/24/9e096de47a4d11bc4df41e9d1e61776393eac4cb6eb11b3e23315b78b2cc/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cb467c999c2eff23a6417e58d75e5828716f42ed8289fe6b77a7e5a91036ca70", size = 460264, upload-time = "2025-10-14T15:05:18.962Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cc/0f/e8dea6375f1d3ba5fcb0b3583e2b493e77379834c74fd5a22d66d85d6540/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:836398932192dae4146c8f6f737d74baeac8b70ce14831a239bdb1ca882fc261", size = 487877, upload-time = "2025-10-14T15:05:20.094Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ac/5b/df24cfc6424a12deb41503b64d42fbea6b8cb357ec62ca84a5a3476f654a/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:743185e7372b7bc7c389e1badcc606931a827112fbbd37f14c537320fca08620", size = 595176, upload-time = "2025-10-14T15:05:21.134Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8f/b5/853b6757f7347de4e9b37e8cc3289283fb983cba1ab4d2d7144694871d9c/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afaeff7696e0ad9f02cbb8f56365ff4686ab205fcf9c4c5b6fdfaaa16549dd04", size = 473577, upload-time = "2025-10-14T15:05:22.306Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e1/f7/0a4467be0a56e80447c8529c9fce5b38eab4f513cb3d9bf82e7392a5696b/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7eb7da0eb23aa2ba036d4f616d46906013a68caf61b7fdbe42fc8b25132e77", size = 455425, upload-time = "2025-10-14T15:05:23.348Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8e/e0/82583485ea00137ddf69bc84a2db88bd92ab4a6e3c405e5fb878ead8d0e7/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:831a62658609f0e5c64178211c942ace999517f5770fe9436be4c2faeba0c0ef", size = 628826, upload-time = "2025-10-14T15:05:24.398Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/28/9a/a785356fccf9fae84c0cc90570f11702ae9571036fb25932f1242c82191c/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:f9a2ae5c91cecc9edd47e041a930490c31c3afb1f5e6d71de3dc671bfaca02bf", size = 622208, upload-time = "2025-10-14T15:05:25.45Z" }, ] [[package]] name = "wcmatch" version = "10.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "bracex" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/79/3e/c0bdc27cf06f4e47680bd5803a07cb3dfd17de84cde92dd217dcb9e05253/wcmatch-10.1.tar.gz", hash = "sha256:f11f94208c8c8484a16f4f48638a85d771d9513f4ab3f37595978801cb9465af", size = 117421, upload-time = "2025-06-22T19:14:02.49Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/3e/c0bdc27cf06f4e47680bd5803a07cb3dfd17de84cde92dd217dcb9e05253/wcmatch-10.1.tar.gz", hash = "sha256:f11f94208c8c8484a16f4f48638a85d771d9513f4ab3f37595978801cb9465af", size = 117421, upload-time = "2025-06-22T19:14:02.49Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl", hash = "sha256:5848ace7dbb0476e5e55ab63c6bbd529745089343427caa5537f230cc01beb8a", size = 39854, upload-time = "2025-06-22T19:14:00.978Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl", hash = "sha256:5848ace7dbb0476e5e55ab63c6bbd529745089343427caa5537f230cc01beb8a", size = 39854, upload-time = "2025-06-22T19:14:00.978Z" }, ] [[package]] name = "wcwidth" version = "0.2.14" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, ] [[package]] name = "websocket-client" version = "1.9.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, ] [[package]] name = "websockets" version = "15.0.1" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440, upload-time = "2025-03-05T20:02:36.695Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098, upload-time = "2025-03-05T20:02:37.985Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329, upload-time = "2025-03-05T20:02:39.298Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111, upload-time = "2025-03-05T20:02:40.595Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054, upload-time = "2025-03-05T20:02:41.926Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496, upload-time = "2025-03-05T20:02:43.304Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829, upload-time = "2025-03-05T20:02:48.812Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217, upload-time = "2025-03-05T20:02:50.14Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440, upload-time = "2025-03-05T20:02:36.695Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098, upload-time = "2025-03-05T20:02:37.985Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329, upload-time = "2025-03-05T20:02:39.298Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111, upload-time = "2025-03-05T20:02:40.595Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054, upload-time = "2025-03-05T20:02:41.926Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496, upload-time = "2025-03-05T20:02:43.304Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829, upload-time = "2025-03-05T20:02:48.812Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217, upload-time = "2025-03-05T20:02:50.14Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, ] [[package]] name = "werkzeug" version = "3.1.4" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/45/ea/b0f8eeb287f8df9066e56e831c7824ac6bab645dd6c7a8f4b2d767944f9b/werkzeug-3.1.4.tar.gz", hash = "sha256:cd3cd98b1b92dc3b7b3995038826c68097dcb16f9baa63abe35f20eafeb9fe5e", size = 864687, upload-time = "2025-11-29T02:15:22.841Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/45/ea/b0f8eeb287f8df9066e56e831c7824ac6bab645dd6c7a8f4b2d767944f9b/werkzeug-3.1.4.tar.gz", hash = "sha256:cd3cd98b1b92dc3b7b3995038826c68097dcb16f9baa63abe35f20eafeb9fe5e", size = 864687, upload-time = "2025-11-29T02:15:22.841Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl", hash = "sha256:2ad50fb9ed09cc3af22c54698351027ace879a0b60a3b5edf5730b2f7d876905", size = 224960, upload-time = "2025-11-29T02:15:21.13Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2f/f9/9e082990c2585c744734f85bec79b5dae5df9c974ffee58fe421652c8e91/werkzeug-3.1.4-py3-none-any.whl", hash = "sha256:2ad50fb9ed09cc3af22c54698351027ace879a0b60a3b5edf5730b2f7d876905", size = 224960, upload-time = "2025-11-29T02:15:21.13Z" }, ] [[package]] name = "win32-setctime" version = "1.2.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b3/8f/705086c9d734d3b663af0e9bb3d4de6578d08f46b1b101c2442fd9aecaa2/win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0", size = 4867, upload-time = "2024-12-07T15:28:28.314Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b3/8f/705086c9d734d3b663af0e9bb3d4de6578d08f46b1b101c2442fd9aecaa2/win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0", size = 4867, upload-time = "2024-12-07T15:28:28.314Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390", size = 4083, upload-time = "2024-12-07T15:28:26.465Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390", size = 4083, upload-time = "2024-12-07T15:28:26.465Z" }, ] [[package]] name = "wrapt" version = "1.17.3" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277", size = 88072, upload-time = "2025-08-12T05:52:37.53Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d", size = 88214, upload-time = "2025-08-12T05:52:15.886Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa", size = 87105, upload-time = "2025-08-12T05:52:17.914Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050", size = 87766, upload-time = "2025-08-12T05:52:39.243Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8", size = 36711, upload-time = "2025-08-12T05:53:10.074Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb", size = 38885, upload-time = "2025-08-12T05:53:08.695Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16", size = 36896, upload-time = "2025-08-12T05:52:55.34Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277", size = 88072, upload-time = "2025-08-12T05:52:37.53Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d", size = 88214, upload-time = "2025-08-12T05:52:15.886Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa", size = 87105, upload-time = "2025-08-12T05:52:17.914Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050", size = 87766, upload-time = "2025-08-12T05:52:39.243Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8", size = 36711, upload-time = "2025-08-12T05:53:10.074Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb", size = 38885, upload-time = "2025-08-12T05:53:08.695Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16", size = 36896, upload-time = "2025-08-12T05:52:55.34Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, ] [[package]] name = "wsproto" version = "1.2.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "h11" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425, upload-time = "2022-08-23T19:58:21.447Z" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425, upload-time = "2022-08-23T19:58:21.447Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226, upload-time = "2022-08-23T19:58:19.96Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226, upload-time = "2022-08-23T19:58:19.96Z" }, ] [[package]] name = "xxhash" version = "3.6.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/84/30869e01909fb37a6cc7e18688ee8bf1e42d57e7e0777636bd47524c43c7/xxhash-3.6.0.tar.gz", hash = "sha256:f0162a78b13a0d7617b2845b90c763339d1f1d82bb04a4b07f4ab535cc5e05d6", size = 85160, upload-time = "2025-10-02T14:37:08.097Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/07/d9412f3d7d462347e4511181dea65e47e0d0e16e26fbee2ea86a2aefb657/xxhash-3.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:01362c4331775398e7bb34e3ab403bc9ee9f7c497bc7dee6272114055277dd3c", size = 32744, upload-time = "2025-10-02T14:34:34.622Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/79/35/0429ee11d035fc33abe32dca1b2b69e8c18d236547b9a9b72c1929189b9a/xxhash-3.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b7b2df81a23f8cb99656378e72501b2cb41b1827c0f5a86f87d6b06b69f9f204", size = 30816, upload-time = "2025-10-02T14:34:36.043Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b7/f2/57eb99aa0f7d98624c0932c5b9a170e1806406cdbcdb510546634a1359e0/xxhash-3.6.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:dc94790144e66b14f67b10ac8ed75b39ca47536bf8800eb7c24b50271ea0c490", size = 194035, upload-time = "2025-10-02T14:34:37.354Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4c/ed/6224ba353690d73af7a3f1c7cdb1fc1b002e38f783cb991ae338e1eb3d79/xxhash-3.6.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93f107c673bccf0d592cdba077dedaf52fe7f42dcd7676eba1f6d6f0c3efffd2", size = 212914, upload-time = "2025-10-02T14:34:38.6Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/38/86/fb6b6130d8dd6b8942cc17ab4d90e223653a89aa32ad2776f8af7064ed13/xxhash-3.6.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aa5ee3444c25b69813663c9f8067dcfaa2e126dc55e8dddf40f4d1c25d7effa", size = 212163, upload-time = "2025-10-02T14:34:39.872Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ee/dc/e84875682b0593e884ad73b2d40767b5790d417bde603cceb6878901d647/xxhash-3.6.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7f99123f0e1194fa59cc69ad46dbae2e07becec5df50a0509a808f90a0f03f0", size = 445411, upload-time = "2025-10-02T14:34:41.569Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/11/4f/426f91b96701ec2f37bb2b8cec664eff4f658a11f3fa9d94f0a887ea6d2b/xxhash-3.6.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49e03e6fe2cac4a1bc64952dd250cf0dbc5ef4ebb7b8d96bce82e2de163c82a2", size = 193883, upload-time = "2025-10-02T14:34:43.249Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/53/5a/ddbb83eee8e28b778eacfc5a85c969673e4023cdeedcfcef61f36731610b/xxhash-3.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bd17fede52a17a4f9a7bc4472a5867cb0b160deeb431795c0e4abe158bc784e9", size = 210392, upload-time = "2025-10-02T14:34:45.042Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/1e/c2/ff69efd07c8c074ccdf0a4f36fcdd3d27363665bcdf4ba399abebe643465/xxhash-3.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6fb5f5476bef678f69db04f2bd1efbed3030d2aba305b0fc1773645f187d6a4e", size = 197898, upload-time = "2025-10-02T14:34:46.302Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/58/ca/faa05ac19b3b622c7c9317ac3e23954187516298a091eb02c976d0d3dd45/xxhash-3.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:843b52f6d88071f87eba1631b684fcb4b2068cd2180a0224122fe4ef011a9374", size = 210655, upload-time = "2025-10-02T14:34:47.571Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d4/7a/06aa7482345480cc0cb597f5c875b11a82c3953f534394f620b0be2f700c/xxhash-3.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7d14a6cfaf03b1b6f5f9790f76880601ccc7896aff7ab9cd8978a939c1eb7e0d", size = 414001, upload-time = "2025-10-02T14:34:49.273Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/23/07/63ffb386cd47029aa2916b3d2f454e6cc5b9f5c5ada3790377d5430084e7/xxhash-3.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:418daf3db71e1413cfe211c2f9a528456936645c17f46b5204705581a45390ae", size = 191431, upload-time = "2025-10-02T14:34:50.798Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0f/93/14fde614cadb4ddf5e7cebf8918b7e8fac5ae7861c1875964f17e678205c/xxhash-3.6.0-cp312-cp312-win32.whl", hash = "sha256:50fc255f39428a27299c20e280d6193d8b63b8ef8028995323bf834a026b4fbb", size = 30617, upload-time = "2025-10-02T14:34:51.954Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/13/5d/0d125536cbe7565a83d06e43783389ecae0c0f2ed037b48ede185de477c0/xxhash-3.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:c0f2ab8c715630565ab8991b536ecded9416d615538be8ecddce43ccf26cbc7c", size = 31534, upload-time = "2025-10-02T14:34:53.276Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/54/85/6ec269b0952ec7e36ba019125982cf11d91256a778c7c3f98a4c5043d283/xxhash-3.6.0-cp312-cp312-win_arm64.whl", hash = "sha256:eae5c13f3bc455a3bbb68bdc513912dc7356de7e2280363ea235f71f54064829", size = 27876, upload-time = "2025-10-02T14:34:54.371Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/33/76/35d05267ac82f53ae9b0e554da7c5e281ee61f3cad44c743f0fcd354f211/xxhash-3.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:599e64ba7f67472481ceb6ee80fa3bd828fd61ba59fb11475572cc5ee52b89ec", size = 32738, upload-time = "2025-10-02T14:34:55.839Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/a8/3fbce1cd96534a95e35d5120637bf29b0d7f5d8fa2f6374e31b4156dd419/xxhash-3.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d8b8aaa30fca4f16f0c84a5c8d7ddee0e25250ec2796c973775373257dde8f1", size = 30821, upload-time = "2025-10-02T14:34:57.219Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0c/ea/d387530ca7ecfa183cb358027f1833297c6ac6098223fd14f9782cd0015c/xxhash-3.6.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d597acf8506d6e7101a4a44a5e428977a51c0fadbbfd3c39650cca9253f6e5a6", size = 194127, upload-time = "2025-10-02T14:34:59.21Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/0c/71435dcb99874b09a43b8d7c54071e600a7481e42b3e3ce1eb5226a5711a/xxhash-3.6.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:858dc935963a33bc33490128edc1c12b0c14d9c7ebaa4e387a7869ecc4f3e263", size = 212975, upload-time = "2025-10-02T14:35:00.816Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/84/7a/c2b3d071e4bb4a90b7057228a99b10d51744878f4a8a6dd643c8bd897620/xxhash-3.6.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba284920194615cb8edf73bf52236ce2e1664ccd4a38fdb543506413529cc546", size = 212241, upload-time = "2025-10-02T14:35:02.207Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/81/5f/640b6eac0128e215f177df99eadcd0f1b7c42c274ab6a394a05059694c5a/xxhash-3.6.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b54219177f6c6674d5378bd862c6aedf64725f70dd29c472eaae154df1a2e89", size = 445471, upload-time = "2025-10-02T14:35:03.61Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5e/1e/3c3d3ef071b051cc3abbe3721ffb8365033a172613c04af2da89d5548a87/xxhash-3.6.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42c36dd7dbad2f5238950c377fcbf6811b1cdb1c444fab447960030cea60504d", size = 193936, upload-time = "2025-10-02T14:35:05.013Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2c/bd/4a5f68381939219abfe1c22a9e3a5854a4f6f6f3c4983a87d255f21f2e5d/xxhash-3.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f22927652cba98c44639ffdc7aaf35828dccf679b10b31c4ad72a5b530a18eb7", size = 210440, upload-time = "2025-10-02T14:35:06.239Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/eb/37/b80fe3d5cfb9faff01a02121a0f4d565eb7237e9e5fc66e73017e74dcd36/xxhash-3.6.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b45fad44d9c5c119e9c6fbf2e1c656a46dc68e280275007bbfd3d572b21426db", size = 197990, upload-time = "2025-10-02T14:35:07.735Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d7/fd/2c0a00c97b9e18f72e1f240ad4e8f8a90fd9d408289ba9c7c495ed7dc05c/xxhash-3.6.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6f2580ffab1a8b68ef2b901cde7e55fa8da5e4be0977c68f78fc80f3c143de42", size = 210689, upload-time = "2025-10-02T14:35:09.438Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/93/86/5dd8076a926b9a95db3206aba20d89a7fc14dd5aac16e5c4de4b56033140/xxhash-3.6.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40c391dd3cd041ebc3ffe6f2c862f402e306eb571422e0aa918d8070ba31da11", size = 414068, upload-time = "2025-10-02T14:35:11.162Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/af/3c/0bb129170ee8f3650f08e993baee550a09593462a5cddd8e44d0011102b1/xxhash-3.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f205badabde7aafd1a31e8ca2a3e5a763107a71c397c4481d6a804eb5063d8bd", size = 191495, upload-time = "2025-10-02T14:35:12.971Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e9/3a/6797e0114c21d1725e2577508e24006fd7ff1d8c0c502d3b52e45c1771d8/xxhash-3.6.0-cp313-cp313-win32.whl", hash = "sha256:2577b276e060b73b73a53042ea5bd5203d3e6347ce0d09f98500f418a9fcf799", size = 30620, upload-time = "2025-10-02T14:35:14.129Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/86/15/9bc32671e9a38b413a76d24722a2bf8784a132c043063a8f5152d390b0f9/xxhash-3.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:757320d45d2fbcce8f30c42a6b2f47862967aea7bf458b9625b4bbe7ee390392", size = 31542, upload-time = "2025-10-02T14:35:15.21Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/39/c5/cc01e4f6188656e56112d6a8e0dfe298a16934b8c47a247236549a3f7695/xxhash-3.6.0-cp313-cp313-win_arm64.whl", hash = "sha256:457b8f85dec5825eed7b69c11ae86834a018b8e3df5e77783c999663da2f96d6", size = 27880, upload-time = "2025-10-02T14:35:16.315Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f3/30/25e5321c8732759e930c555176d37e24ab84365482d257c3b16362235212/xxhash-3.6.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a42e633d75cdad6d625434e3468126c73f13f7584545a9cf34e883aa1710e702", size = 32956, upload-time = "2025-10-02T14:35:17.413Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9f/3c/0573299560d7d9f8ab1838f1efc021a280b5ae5ae2e849034ef3dee18810/xxhash-3.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:568a6d743219e717b07b4e03b0a828ce593833e498c3b64752e0f5df6bfe84db", size = 31072, upload-time = "2025-10-02T14:35:18.844Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7a/1c/52d83a06e417cd9d4137722693424885cc9878249beb3a7c829e74bf7ce9/xxhash-3.6.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bec91b562d8012dae276af8025a55811b875baace6af510412a5e58e3121bc54", size = 196409, upload-time = "2025-10-02T14:35:20.31Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e3/8e/c6d158d12a79bbd0b878f8355432075fc82759e356ab5a111463422a239b/xxhash-3.6.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78e7f2f4c521c30ad5e786fdd6bae89d47a32672a80195467b5de0480aa97b1f", size = 215736, upload-time = "2025-10-02T14:35:21.616Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bc/68/c4c80614716345d55071a396cf03d06e34b5f4917a467faf43083c995155/xxhash-3.6.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3ed0df1b11a79856df5ffcab572cbd6b9627034c1c748c5566fa79df9048a7c5", size = 214833, upload-time = "2025-10-02T14:35:23.32Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7e/e9/ae27c8ffec8b953efa84c7c4a6c6802c263d587b9fc0d6e7cea64e08c3af/xxhash-3.6.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0e4edbfc7d420925b0dd5e792478ed393d6e75ff8fc219a6546fb446b6a417b1", size = 448348, upload-time = "2025-10-02T14:35:25.111Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d7/6b/33e21afb1b5b3f46b74b6bd1913639066af218d704cc0941404ca717fc57/xxhash-3.6.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fba27a198363a7ef87f8c0f6b171ec36b674fe9053742c58dd7e3201c1ab30ee", size = 196070, upload-time = "2025-10-02T14:35:26.586Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/96/b6/fcabd337bc5fa624e7203aa0fa7d0c49eed22f72e93229431752bddc83d9/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:794fe9145fe60191c6532fa95063765529770edcdd67b3d537793e8004cabbfd", size = 212907, upload-time = "2025-10-02T14:35:28.087Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4b/d3/9ee6160e644d660fcf176c5825e61411c7f62648728f69c79ba237250143/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6105ef7e62b5ac73a837778efc331a591d8442f8ef5c7e102376506cb4ae2729", size = 200839, upload-time = "2025-10-02T14:35:29.857Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0d/98/e8de5baa5109394baf5118f5e72ab21a86387c4f89b0e77ef3e2f6b0327b/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f01375c0e55395b814a679b3eea205db7919ac2af213f4a6682e01220e5fe292", size = 213304, upload-time = "2025-10-02T14:35:31.222Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7b/1d/71056535dec5c3177eeb53e38e3d367dd1d16e024e63b1cee208d572a033/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d706dca2d24d834a4661619dcacf51a75c16d65985718d6a7d73c1eeeb903ddf", size = 416930, upload-time = "2025-10-02T14:35:32.517Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/dc/6c/5cbde9de2cd967c322e651c65c543700b19e7ae3e0aae8ece3469bf9683d/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5f059d9faeacd49c0215d66f4056e1326c80503f51a1532ca336a385edadd033", size = 193787, upload-time = "2025-10-02T14:35:33.827Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/19/fa/0172e350361d61febcea941b0cc541d6e6c8d65d153e85f850a7b256ff8a/xxhash-3.6.0-cp313-cp313t-win32.whl", hash = "sha256:1244460adc3a9be84731d72b8e80625788e5815b68da3da8b83f78115a40a7ec", size = 30916, upload-time = "2025-10-02T14:35:35.107Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ad/e6/e8cf858a2b19d6d45820f072eff1bea413910592ff17157cabc5f1227a16/xxhash-3.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b1e420ef35c503869c4064f4a2f2b08ad6431ab7b229a05cce39d74268bca6b8", size = 31799, upload-time = "2025-10-02T14:35:36.165Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/56/15/064b197e855bfb7b343210e82490ae672f8bc7cdf3ddb02e92f64304ee8a/xxhash-3.6.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ec44b73a4220623235f67a996c862049f375df3b1052d9899f40a6382c32d746", size = 28044, upload-time = "2025-10-02T14:35:37.195Z" }, +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/84/30869e01909fb37a6cc7e18688ee8bf1e42d57e7e0777636bd47524c43c7/xxhash-3.6.0.tar.gz", hash = "sha256:f0162a78b13a0d7617b2845b90c763339d1f1d82bb04a4b07f4ab535cc5e05d6", size = 85160, upload-time = "2025-10-02T14:37:08.097Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/07/d9412f3d7d462347e4511181dea65e47e0d0e16e26fbee2ea86a2aefb657/xxhash-3.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:01362c4331775398e7bb34e3ab403bc9ee9f7c497bc7dee6272114055277dd3c", size = 32744, upload-time = "2025-10-02T14:34:34.622Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/79/35/0429ee11d035fc33abe32dca1b2b69e8c18d236547b9a9b72c1929189b9a/xxhash-3.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b7b2df81a23f8cb99656378e72501b2cb41b1827c0f5a86f87d6b06b69f9f204", size = 30816, upload-time = "2025-10-02T14:34:36.043Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/f2/57eb99aa0f7d98624c0932c5b9a170e1806406cdbcdb510546634a1359e0/xxhash-3.6.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:dc94790144e66b14f67b10ac8ed75b39ca47536bf8800eb7c24b50271ea0c490", size = 194035, upload-time = "2025-10-02T14:34:37.354Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4c/ed/6224ba353690d73af7a3f1c7cdb1fc1b002e38f783cb991ae338e1eb3d79/xxhash-3.6.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93f107c673bccf0d592cdba077dedaf52fe7f42dcd7676eba1f6d6f0c3efffd2", size = 212914, upload-time = "2025-10-02T14:34:38.6Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/86/fb6b6130d8dd6b8942cc17ab4d90e223653a89aa32ad2776f8af7064ed13/xxhash-3.6.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aa5ee3444c25b69813663c9f8067dcfaa2e126dc55e8dddf40f4d1c25d7effa", size = 212163, upload-time = "2025-10-02T14:34:39.872Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ee/dc/e84875682b0593e884ad73b2d40767b5790d417bde603cceb6878901d647/xxhash-3.6.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7f99123f0e1194fa59cc69ad46dbae2e07becec5df50a0509a808f90a0f03f0", size = 445411, upload-time = "2025-10-02T14:34:41.569Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/11/4f/426f91b96701ec2f37bb2b8cec664eff4f658a11f3fa9d94f0a887ea6d2b/xxhash-3.6.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49e03e6fe2cac4a1bc64952dd250cf0dbc5ef4ebb7b8d96bce82e2de163c82a2", size = 193883, upload-time = "2025-10-02T14:34:43.249Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/53/5a/ddbb83eee8e28b778eacfc5a85c969673e4023cdeedcfcef61f36731610b/xxhash-3.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bd17fede52a17a4f9a7bc4472a5867cb0b160deeb431795c0e4abe158bc784e9", size = 210392, upload-time = "2025-10-02T14:34:45.042Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1e/c2/ff69efd07c8c074ccdf0a4f36fcdd3d27363665bcdf4ba399abebe643465/xxhash-3.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6fb5f5476bef678f69db04f2bd1efbed3030d2aba305b0fc1773645f187d6a4e", size = 197898, upload-time = "2025-10-02T14:34:46.302Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/58/ca/faa05ac19b3b622c7c9317ac3e23954187516298a091eb02c976d0d3dd45/xxhash-3.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:843b52f6d88071f87eba1631b684fcb4b2068cd2180a0224122fe4ef011a9374", size = 210655, upload-time = "2025-10-02T14:34:47.571Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/7a/06aa7482345480cc0cb597f5c875b11a82c3953f534394f620b0be2f700c/xxhash-3.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7d14a6cfaf03b1b6f5f9790f76880601ccc7896aff7ab9cd8978a939c1eb7e0d", size = 414001, upload-time = "2025-10-02T14:34:49.273Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/23/07/63ffb386cd47029aa2916b3d2f454e6cc5b9f5c5ada3790377d5430084e7/xxhash-3.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:418daf3db71e1413cfe211c2f9a528456936645c17f46b5204705581a45390ae", size = 191431, upload-time = "2025-10-02T14:34:50.798Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0f/93/14fde614cadb4ddf5e7cebf8918b7e8fac5ae7861c1875964f17e678205c/xxhash-3.6.0-cp312-cp312-win32.whl", hash = "sha256:50fc255f39428a27299c20e280d6193d8b63b8ef8028995323bf834a026b4fbb", size = 30617, upload-time = "2025-10-02T14:34:51.954Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/13/5d/0d125536cbe7565a83d06e43783389ecae0c0f2ed037b48ede185de477c0/xxhash-3.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:c0f2ab8c715630565ab8991b536ecded9416d615538be8ecddce43ccf26cbc7c", size = 31534, upload-time = "2025-10-02T14:34:53.276Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/54/85/6ec269b0952ec7e36ba019125982cf11d91256a778c7c3f98a4c5043d283/xxhash-3.6.0-cp312-cp312-win_arm64.whl", hash = "sha256:eae5c13f3bc455a3bbb68bdc513912dc7356de7e2280363ea235f71f54064829", size = 27876, upload-time = "2025-10-02T14:34:54.371Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/33/76/35d05267ac82f53ae9b0e554da7c5e281ee61f3cad44c743f0fcd354f211/xxhash-3.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:599e64ba7f67472481ceb6ee80fa3bd828fd61ba59fb11475572cc5ee52b89ec", size = 32738, upload-time = "2025-10-02T14:34:55.839Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/a8/3fbce1cd96534a95e35d5120637bf29b0d7f5d8fa2f6374e31b4156dd419/xxhash-3.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d8b8aaa30fca4f16f0c84a5c8d7ddee0e25250ec2796c973775373257dde8f1", size = 30821, upload-time = "2025-10-02T14:34:57.219Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0c/ea/d387530ca7ecfa183cb358027f1833297c6ac6098223fd14f9782cd0015c/xxhash-3.6.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d597acf8506d6e7101a4a44a5e428977a51c0fadbbfd3c39650cca9253f6e5a6", size = 194127, upload-time = "2025-10-02T14:34:59.21Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/0c/71435dcb99874b09a43b8d7c54071e600a7481e42b3e3ce1eb5226a5711a/xxhash-3.6.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:858dc935963a33bc33490128edc1c12b0c14d9c7ebaa4e387a7869ecc4f3e263", size = 212975, upload-time = "2025-10-02T14:35:00.816Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/84/7a/c2b3d071e4bb4a90b7057228a99b10d51744878f4a8a6dd643c8bd897620/xxhash-3.6.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba284920194615cb8edf73bf52236ce2e1664ccd4a38fdb543506413529cc546", size = 212241, upload-time = "2025-10-02T14:35:02.207Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/81/5f/640b6eac0128e215f177df99eadcd0f1b7c42c274ab6a394a05059694c5a/xxhash-3.6.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b54219177f6c6674d5378bd862c6aedf64725f70dd29c472eaae154df1a2e89", size = 445471, upload-time = "2025-10-02T14:35:03.61Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5e/1e/3c3d3ef071b051cc3abbe3721ffb8365033a172613c04af2da89d5548a87/xxhash-3.6.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42c36dd7dbad2f5238950c377fcbf6811b1cdb1c444fab447960030cea60504d", size = 193936, upload-time = "2025-10-02T14:35:05.013Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2c/bd/4a5f68381939219abfe1c22a9e3a5854a4f6f6f3c4983a87d255f21f2e5d/xxhash-3.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f22927652cba98c44639ffdc7aaf35828dccf679b10b31c4ad72a5b530a18eb7", size = 210440, upload-time = "2025-10-02T14:35:06.239Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/eb/37/b80fe3d5cfb9faff01a02121a0f4d565eb7237e9e5fc66e73017e74dcd36/xxhash-3.6.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b45fad44d9c5c119e9c6fbf2e1c656a46dc68e280275007bbfd3d572b21426db", size = 197990, upload-time = "2025-10-02T14:35:07.735Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d7/fd/2c0a00c97b9e18f72e1f240ad4e8f8a90fd9d408289ba9c7c495ed7dc05c/xxhash-3.6.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6f2580ffab1a8b68ef2b901cde7e55fa8da5e4be0977c68f78fc80f3c143de42", size = 210689, upload-time = "2025-10-02T14:35:09.438Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/93/86/5dd8076a926b9a95db3206aba20d89a7fc14dd5aac16e5c4de4b56033140/xxhash-3.6.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40c391dd3cd041ebc3ffe6f2c862f402e306eb571422e0aa918d8070ba31da11", size = 414068, upload-time = "2025-10-02T14:35:11.162Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/af/3c/0bb129170ee8f3650f08e993baee550a09593462a5cddd8e44d0011102b1/xxhash-3.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f205badabde7aafd1a31e8ca2a3e5a763107a71c397c4481d6a804eb5063d8bd", size = 191495, upload-time = "2025-10-02T14:35:12.971Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/3a/6797e0114c21d1725e2577508e24006fd7ff1d8c0c502d3b52e45c1771d8/xxhash-3.6.0-cp313-cp313-win32.whl", hash = "sha256:2577b276e060b73b73a53042ea5bd5203d3e6347ce0d09f98500f418a9fcf799", size = 30620, upload-time = "2025-10-02T14:35:14.129Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/86/15/9bc32671e9a38b413a76d24722a2bf8784a132c043063a8f5152d390b0f9/xxhash-3.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:757320d45d2fbcce8f30c42a6b2f47862967aea7bf458b9625b4bbe7ee390392", size = 31542, upload-time = "2025-10-02T14:35:15.21Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/39/c5/cc01e4f6188656e56112d6a8e0dfe298a16934b8c47a247236549a3f7695/xxhash-3.6.0-cp313-cp313-win_arm64.whl", hash = "sha256:457b8f85dec5825eed7b69c11ae86834a018b8e3df5e77783c999663da2f96d6", size = 27880, upload-time = "2025-10-02T14:35:16.315Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f3/30/25e5321c8732759e930c555176d37e24ab84365482d257c3b16362235212/xxhash-3.6.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a42e633d75cdad6d625434e3468126c73f13f7584545a9cf34e883aa1710e702", size = 32956, upload-time = "2025-10-02T14:35:17.413Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/3c/0573299560d7d9f8ab1838f1efc021a280b5ae5ae2e849034ef3dee18810/xxhash-3.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:568a6d743219e717b07b4e03b0a828ce593833e498c3b64752e0f5df6bfe84db", size = 31072, upload-time = "2025-10-02T14:35:18.844Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7a/1c/52d83a06e417cd9d4137722693424885cc9878249beb3a7c829e74bf7ce9/xxhash-3.6.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bec91b562d8012dae276af8025a55811b875baace6af510412a5e58e3121bc54", size = 196409, upload-time = "2025-10-02T14:35:20.31Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/8e/c6d158d12a79bbd0b878f8355432075fc82759e356ab5a111463422a239b/xxhash-3.6.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78e7f2f4c521c30ad5e786fdd6bae89d47a32672a80195467b5de0480aa97b1f", size = 215736, upload-time = "2025-10-02T14:35:21.616Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bc/68/c4c80614716345d55071a396cf03d06e34b5f4917a467faf43083c995155/xxhash-3.6.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3ed0df1b11a79856df5ffcab572cbd6b9627034c1c748c5566fa79df9048a7c5", size = 214833, upload-time = "2025-10-02T14:35:23.32Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/e9/ae27c8ffec8b953efa84c7c4a6c6802c263d587b9fc0d6e7cea64e08c3af/xxhash-3.6.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0e4edbfc7d420925b0dd5e792478ed393d6e75ff8fc219a6546fb446b6a417b1", size = 448348, upload-time = "2025-10-02T14:35:25.111Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d7/6b/33e21afb1b5b3f46b74b6bd1913639066af218d704cc0941404ca717fc57/xxhash-3.6.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fba27a198363a7ef87f8c0f6b171ec36b674fe9053742c58dd7e3201c1ab30ee", size = 196070, upload-time = "2025-10-02T14:35:26.586Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/96/b6/fcabd337bc5fa624e7203aa0fa7d0c49eed22f72e93229431752bddc83d9/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:794fe9145fe60191c6532fa95063765529770edcdd67b3d537793e8004cabbfd", size = 212907, upload-time = "2025-10-02T14:35:28.087Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4b/d3/9ee6160e644d660fcf176c5825e61411c7f62648728f69c79ba237250143/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6105ef7e62b5ac73a837778efc331a591d8442f8ef5c7e102376506cb4ae2729", size = 200839, upload-time = "2025-10-02T14:35:29.857Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0d/98/e8de5baa5109394baf5118f5e72ab21a86387c4f89b0e77ef3e2f6b0327b/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f01375c0e55395b814a679b3eea205db7919ac2af213f4a6682e01220e5fe292", size = 213304, upload-time = "2025-10-02T14:35:31.222Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7b/1d/71056535dec5c3177eeb53e38e3d367dd1d16e024e63b1cee208d572a033/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d706dca2d24d834a4661619dcacf51a75c16d65985718d6a7d73c1eeeb903ddf", size = 416930, upload-time = "2025-10-02T14:35:32.517Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/6c/5cbde9de2cd967c322e651c65c543700b19e7ae3e0aae8ece3469bf9683d/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5f059d9faeacd49c0215d66f4056e1326c80503f51a1532ca336a385edadd033", size = 193787, upload-time = "2025-10-02T14:35:33.827Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/fa/0172e350361d61febcea941b0cc541d6e6c8d65d153e85f850a7b256ff8a/xxhash-3.6.0-cp313-cp313t-win32.whl", hash = "sha256:1244460adc3a9be84731d72b8e80625788e5815b68da3da8b83f78115a40a7ec", size = 30916, upload-time = "2025-10-02T14:35:35.107Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ad/e6/e8cf858a2b19d6d45820f072eff1bea413910592ff17157cabc5f1227a16/xxhash-3.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b1e420ef35c503869c4064f4a2f2b08ad6431ab7b229a05cce39d74268bca6b8", size = 31799, upload-time = "2025-10-02T14:35:36.165Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/56/15/064b197e855bfb7b343210e82490ae672f8bc7cdf3ddb02e92f64304ee8a/xxhash-3.6.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ec44b73a4220623235f67a996c862049f375df3b1052d9899f40a6382c32d746", size = 28044, upload-time = "2025-10-02T14:35:37.195Z" }, ] [[package]] name = "yarl" version = "1.22.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "idna" }, { name = "multidict" }, { name = "propcache" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/61/3a/caf4e25036db0f2da4ca22a353dfeb3c9d3c95d2761ebe9b14df8fc16eb0/yarl-1.22.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", size = 373243, upload-time = "2025-10-06T14:10:19.44Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/9e/51a77ac7516e8e7803b06e01f74e78649c24ee1021eca3d6a739cb6ea49c/yarl-1.22.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", size = 342361, upload-time = "2025-10-06T14:10:21.124Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d4/f8/33b92454789dde8407f156c00303e9a891f1f51a0330b0fad7c909f87692/yarl-1.22.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", size = 387036, upload-time = "2025-10-06T14:10:22.902Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d9/9a/c5db84ea024f76838220280f732970aa4ee154015d7f5c1bfb60a267af6f/yarl-1.22.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", size = 397671, upload-time = "2025-10-06T14:10:24.523Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", size = 377059, upload-time = "2025-10-06T14:10:26.406Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a1/b9/ab437b261702ced75122ed78a876a6dec0a1b0f5e17a4ac7a9a2482d8abe/yarl-1.22.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", size = 365356, upload-time = "2025-10-06T14:10:28.461Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b2/9d/8e1ae6d1d008a9567877b08f0ce4077a29974c04c062dabdb923ed98e6fe/yarl-1.22.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", size = 361331, upload-time = "2025-10-06T14:10:30.541Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ca/5a/09b7be3905962f145b73beb468cdd53db8aa171cf18c80400a54c5b82846/yarl-1.22.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", size = 382590, upload-time = "2025-10-06T14:10:33.352Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/7f/59ec509abf90eda5048b0bc3e2d7b5099dffdb3e6b127019895ab9d5ef44/yarl-1.22.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", size = 385316, upload-time = "2025-10-06T14:10:35.034Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e5/84/891158426bc8036bfdfd862fabd0e0fa25df4176ec793e447f4b85cf1be4/yarl-1.22.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", size = 374431, upload-time = "2025-10-06T14:10:37.76Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/bb/49/03da1580665baa8bef5e8ed34c6df2c2aca0a2f28bf397ed238cc1bbc6f2/yarl-1.22.0-cp313-cp313-win32.whl", hash = "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", size = 81555, upload-time = "2025-10-06T14:10:39.649Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl", hash = "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", size = 86965, upload-time = "2025-10-06T14:10:41.313Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/98/4d/264a01eae03b6cf629ad69bae94e3b0e5344741e929073678e84bf7a3e3b/yarl-1.22.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", size = 81205, upload-time = "2025-10-06T14:10:43.167Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/88/fc/6908f062a2f77b5f9f6d69cecb1747260831ff206adcbc5b510aff88df91/yarl-1.22.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", size = 146209, upload-time = "2025-10-06T14:10:44.643Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/65/47/76594ae8eab26210b4867be6f49129861ad33da1f1ebdf7051e98492bf62/yarl-1.22.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", size = 95966, upload-time = "2025-10-06T14:10:46.554Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ab/ce/05e9828a49271ba6b5b038b15b3934e996980dd78abdfeb52a04cfb9467e/yarl-1.22.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", size = 97312, upload-time = "2025-10-06T14:10:48.007Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/d1/c5/7dffad5e4f2265b29c9d7ec869c369e4223166e4f9206fc2243ee9eea727/yarl-1.22.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", size = 361967, upload-time = "2025-10-06T14:10:49.997Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/50/b2/375b933c93a54bff7fc041e1a6ad2c0f6f733ffb0c6e642ce56ee3b39970/yarl-1.22.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", size = 323949, upload-time = "2025-10-06T14:10:52.004Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/66/50/bfc2a29a1d78644c5a7220ce2f304f38248dc94124a326794e677634b6cf/yarl-1.22.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", size = 361818, upload-time = "2025-10-06T14:10:54.078Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/46/96/f3941a46af7d5d0f0498f86d71275696800ddcdd20426298e572b19b91ff/yarl-1.22.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", size = 372626, upload-time = "2025-10-06T14:10:55.767Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c1/42/8b27c83bb875cd89448e42cd627e0fb971fa1675c9ec546393d18826cb50/yarl-1.22.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", size = 341129, upload-time = "2025-10-06T14:10:57.985Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/49/36/99ca3122201b382a3cf7cc937b95235b0ac944f7e9f2d5331d50821ed352/yarl-1.22.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", size = 346776, upload-time = "2025-10-06T14:10:59.633Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/85/b4/47328bf996acd01a4c16ef9dcd2f59c969f495073616586f78cd5f2efb99/yarl-1.22.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", size = 334879, upload-time = "2025-10-06T14:11:01.454Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c2/ad/b77d7b3f14a4283bffb8e92c6026496f6de49751c2f97d4352242bba3990/yarl-1.22.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", size = 350996, upload-time = "2025-10-06T14:11:03.452Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/81/c8/06e1d69295792ba54d556f06686cbd6a7ce39c22307100e3fb4a2c0b0a1d/yarl-1.22.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", size = 356047, upload-time = "2025-10-06T14:11:05.115Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4b/b8/4c0e9e9f597074b208d18cef227d83aac36184bfbc6eab204ea55783dbc5/yarl-1.22.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", size = 342947, upload-time = "2025-10-06T14:11:08.137Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", size = 86943, upload-time = "2025-10-06T14:11:10.284Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249", size = 93715, upload-time = "2025-10-06T14:11:11.739Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", size = 83857, upload-time = "2025-10-06T14:11:13.586Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/3a/caf4e25036db0f2da4ca22a353dfeb3c9d3c95d2761ebe9b14df8fc16eb0/yarl-1.22.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", size = 373243, upload-time = "2025-10-06T14:10:19.44Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/9e/51a77ac7516e8e7803b06e01f74e78649c24ee1021eca3d6a739cb6ea49c/yarl-1.22.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", size = 342361, upload-time = "2025-10-06T14:10:21.124Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d4/f8/33b92454789dde8407f156c00303e9a891f1f51a0330b0fad7c909f87692/yarl-1.22.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", size = 387036, upload-time = "2025-10-06T14:10:22.902Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d9/9a/c5db84ea024f76838220280f732970aa4ee154015d7f5c1bfb60a267af6f/yarl-1.22.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", size = 397671, upload-time = "2025-10-06T14:10:24.523Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", size = 377059, upload-time = "2025-10-06T14:10:26.406Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a1/b9/ab437b261702ced75122ed78a876a6dec0a1b0f5e17a4ac7a9a2482d8abe/yarl-1.22.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", size = 365356, upload-time = "2025-10-06T14:10:28.461Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b2/9d/8e1ae6d1d008a9567877b08f0ce4077a29974c04c062dabdb923ed98e6fe/yarl-1.22.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", size = 361331, upload-time = "2025-10-06T14:10:30.541Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ca/5a/09b7be3905962f145b73beb468cdd53db8aa171cf18c80400a54c5b82846/yarl-1.22.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", size = 382590, upload-time = "2025-10-06T14:10:33.352Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/7f/59ec509abf90eda5048b0bc3e2d7b5099dffdb3e6b127019895ab9d5ef44/yarl-1.22.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", size = 385316, upload-time = "2025-10-06T14:10:35.034Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e5/84/891158426bc8036bfdfd862fabd0e0fa25df4176ec793e447f4b85cf1be4/yarl-1.22.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", size = 374431, upload-time = "2025-10-06T14:10:37.76Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bb/49/03da1580665baa8bef5e8ed34c6df2c2aca0a2f28bf397ed238cc1bbc6f2/yarl-1.22.0-cp313-cp313-win32.whl", hash = "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", size = 81555, upload-time = "2025-10-06T14:10:39.649Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl", hash = "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", size = 86965, upload-time = "2025-10-06T14:10:41.313Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/98/4d/264a01eae03b6cf629ad69bae94e3b0e5344741e929073678e84bf7a3e3b/yarl-1.22.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", size = 81205, upload-time = "2025-10-06T14:10:43.167Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/88/fc/6908f062a2f77b5f9f6d69cecb1747260831ff206adcbc5b510aff88df91/yarl-1.22.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", size = 146209, upload-time = "2025-10-06T14:10:44.643Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/65/47/76594ae8eab26210b4867be6f49129861ad33da1f1ebdf7051e98492bf62/yarl-1.22.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", size = 95966, upload-time = "2025-10-06T14:10:46.554Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ab/ce/05e9828a49271ba6b5b038b15b3934e996980dd78abdfeb52a04cfb9467e/yarl-1.22.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", size = 97312, upload-time = "2025-10-06T14:10:48.007Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/c5/7dffad5e4f2265b29c9d7ec869c369e4223166e4f9206fc2243ee9eea727/yarl-1.22.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", size = 361967, upload-time = "2025-10-06T14:10:49.997Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/b2/375b933c93a54bff7fc041e1a6ad2c0f6f733ffb0c6e642ce56ee3b39970/yarl-1.22.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", size = 323949, upload-time = "2025-10-06T14:10:52.004Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/66/50/bfc2a29a1d78644c5a7220ce2f304f38248dc94124a326794e677634b6cf/yarl-1.22.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", size = 361818, upload-time = "2025-10-06T14:10:54.078Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/46/96/f3941a46af7d5d0f0498f86d71275696800ddcdd20426298e572b19b91ff/yarl-1.22.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", size = 372626, upload-time = "2025-10-06T14:10:55.767Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c1/42/8b27c83bb875cd89448e42cd627e0fb971fa1675c9ec546393d18826cb50/yarl-1.22.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", size = 341129, upload-time = "2025-10-06T14:10:57.985Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/49/36/99ca3122201b382a3cf7cc937b95235b0ac944f7e9f2d5331d50821ed352/yarl-1.22.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", size = 346776, upload-time = "2025-10-06T14:10:59.633Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/85/b4/47328bf996acd01a4c16ef9dcd2f59c969f495073616586f78cd5f2efb99/yarl-1.22.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", size = 334879, upload-time = "2025-10-06T14:11:01.454Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c2/ad/b77d7b3f14a4283bffb8e92c6026496f6de49751c2f97d4352242bba3990/yarl-1.22.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", size = 350996, upload-time = "2025-10-06T14:11:03.452Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/81/c8/06e1d69295792ba54d556f06686cbd6a7ce39c22307100e3fb4a2c0b0a1d/yarl-1.22.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", size = 356047, upload-time = "2025-10-06T14:11:05.115Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4b/b8/4c0e9e9f597074b208d18cef227d83aac36184bfbc6eab204ea55783dbc5/yarl-1.22.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", size = 342947, upload-time = "2025-10-06T14:11:08.137Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", size = 86943, upload-time = "2025-10-06T14:11:10.284Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249", size = 93715, upload-time = "2025-10-06T14:11:11.739Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", size = 83857, upload-time = "2025-10-06T14:11:13.586Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, ] [[package]] name = "z3-solver" version = "4.13.0.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/3a/fd/e3f5850fd04480a942aca9f9f7520d3fa5b57731335c221a11f55bb6d91a/z3-solver-4.13.0.0.tar.gz", hash = "sha256:52588e92aec7cb338fd6288ce93758ae01770f62ca0c80e8f4f2b2333feaf51b", size = 4848532, upload-time = "2024-03-07T19:20:07.192Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/fd/e3f5850fd04480a942aca9f9f7520d3fa5b57731335c221a11f55bb6d91a/z3-solver-4.13.0.0.tar.gz", hash = "sha256:52588e92aec7cb338fd6288ce93758ae01770f62ca0c80e8f4f2b2333feaf51b", size = 4848532, upload-time = "2024-03-07T19:20:07.192Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4e/5b/934de9f1f31b1d0f3a8da0ff2e3092136fbffe737eca52965818464af4c3/z3_solver-4.13.0.0-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:bca7d59a699a440247537c2180c519d682c9df3520a16ce288fced61a70d253d", size = 27144281, upload-time = "2024-03-07T19:19:36.033Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/9c/20/f28dfa982bc820760117e5615d59d695d12a6fb31660f53a749be27cccca/z3_solver-4.13.0.0-py2.py3-none-macosx_11_0_x86_64.whl", hash = "sha256:4a4731fded91b32e1861e1c7c96e500da743bb9431246cac51f7c3ffc0f21b5d", size = 30107615, upload-time = "2024-03-07T19:19:45.679Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0e/8c/9058d3998fdc2148f3e6d3497e949d5dfc77c66b1cc1cb461554c0bba954/z3_solver-4.13.0.0-py2.py3-none-manylinux2014_aarch64.whl", hash = "sha256:9d622022a3511c059915c56b2c231c84b5c1be1b82f457d7560dda3d916474fe", size = 55585725, upload-time = "2024-03-07T19:19:49.81Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/c6/79/0255fe0efee7ea9db8987ced14c70028a0007d4d4aaaed8965310bbd7bb1/z3_solver-4.13.0.0-py2.py3-none-manylinux2014_x86_64.whl", hash = "sha256:8c42de82b6e3ff7ee61287d03c7af8a99f9f6554cdd1204c6b9bca96ff1cb7fb", size = 57305826, upload-time = "2024-03-07T19:19:54.261Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b9/27/ca09e1f4642b42a2972047f508bc4ecb0c5acf975c910eb0fdeaf9ec21d0/z3_solver-4.13.0.0-py2.py3-none-win32.whl", hash = "sha256:13468e1018c817b7f794898d3100f02541d15c13ab56c0785c5acdea32a066cf", size = 55429050, upload-time = "2024-03-07T19:19:58.867Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/25/c0/dd978c813288f6860bcfb9e4d2d1d3b311a42a2237a4766e5a0adbcaa79b/z3_solver-4.13.0.0-py2.py3-none-win_amd64.whl", hash = "sha256:3555436cfe9a5fa2d1b432fb9a5e4460e487649c22e5e68a56f7d81594d043e9", size = 58378460, upload-time = "2024-03-07T19:20:03.281Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4e/5b/934de9f1f31b1d0f3a8da0ff2e3092136fbffe737eca52965818464af4c3/z3_solver-4.13.0.0-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:bca7d59a699a440247537c2180c519d682c9df3520a16ce288fced61a70d253d", size = 27144281, upload-time = "2024-03-07T19:19:36.033Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/9c/20/f28dfa982bc820760117e5615d59d695d12a6fb31660f53a749be27cccca/z3_solver-4.13.0.0-py2.py3-none-macosx_11_0_x86_64.whl", hash = "sha256:4a4731fded91b32e1861e1c7c96e500da743bb9431246cac51f7c3ffc0f21b5d", size = 30107615, upload-time = "2024-03-07T19:19:45.679Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0e/8c/9058d3998fdc2148f3e6d3497e949d5dfc77c66b1cc1cb461554c0bba954/z3_solver-4.13.0.0-py2.py3-none-manylinux2014_aarch64.whl", hash = "sha256:9d622022a3511c059915c56b2c231c84b5c1be1b82f457d7560dda3d916474fe", size = 55585725, upload-time = "2024-03-07T19:19:49.81Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/c6/79/0255fe0efee7ea9db8987ced14c70028a0007d4d4aaaed8965310bbd7bb1/z3_solver-4.13.0.0-py2.py3-none-manylinux2014_x86_64.whl", hash = "sha256:8c42de82b6e3ff7ee61287d03c7af8a99f9f6554cdd1204c6b9bca96ff1cb7fb", size = 57305826, upload-time = "2024-03-07T19:19:54.261Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/27/ca09e1f4642b42a2972047f508bc4ecb0c5acf975c910eb0fdeaf9ec21d0/z3_solver-4.13.0.0-py2.py3-none-win32.whl", hash = "sha256:13468e1018c817b7f794898d3100f02541d15c13ab56c0785c5acdea32a066cf", size = 55429050, upload-time = "2024-03-07T19:19:58.867Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/25/c0/dd978c813288f6860bcfb9e4d2d1d3b311a42a2237a4766e5a0adbcaa79b/z3_solver-4.13.0.0-py2.py3-none-win_amd64.whl", hash = "sha256:3555436cfe9a5fa2d1b432fb9a5e4460e487649c22e5e68a56f7d81594d043e9", size = 58378460, upload-time = "2024-03-07T19:20:03.281Z" }, ] [[package]] name = "zipp" version = "3.23.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, ] [[package]] name = "zstandard" version = "0.23.0" -source = { registry = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" } +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation == 'PyPy'" }, ] -sdist = { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ed/f6/2ac0287b442160a89d726b17a9184a4c615bb5237db763791a7fd16d9df1/zstandard-0.23.0.tar.gz", hash = "sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09", size = 681701, upload-time = "2024-07-15T00:18:06.141Z" } -wheels = [ - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7b/83/f23338c963bd9de687d47bf32efe9fd30164e722ba27fb59df33e6b1719b/zstandard-0.23.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b4567955a6bc1b20e9c31612e615af6b53733491aeaa19a6b3b37f3b65477094", size = 788713, upload-time = "2024-07-15T00:15:35.815Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/5b/b3/1a028f6750fd9227ee0b937a278a434ab7f7fdc3066c3173f64366fe2466/zstandard-0.23.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e172f57cd78c20f13a3415cc8dfe24bf388614324d25539146594c16d78fcc8", size = 633459, upload-time = "2024-07-15T00:15:37.995Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/26/af/36d89aae0c1f95a0a98e50711bc5d92c144939efc1f81a2fcd3e78d7f4c1/zstandard-0.23.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0e166f698c5a3e914947388c162be2583e0c638a4703fc6a543e23a88dea3c1", size = 4945707, upload-time = "2024-07-15T00:15:39.872Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/cd/2e/2051f5c772f4dfc0aae3741d5fc72c3dcfe3aaeb461cc231668a4db1ce14/zstandard-0.23.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12a289832e520c6bd4dcaad68e944b86da3bad0d339ef7989fb7e88f92e96072", size = 5306545, upload-time = "2024-07-15T00:15:41.75Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/0a/9e/a11c97b087f89cab030fa71206963090d2fecd8eb83e67bb8f3ffb84c024/zstandard-0.23.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d50d31bfedd53a928fed6707b15a8dbeef011bb6366297cc435accc888b27c20", size = 5337533, upload-time = "2024-07-15T00:15:44.114Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fc/79/edeb217c57fe1bf16d890aa91a1c2c96b28c07b46afed54a5dcf310c3f6f/zstandard-0.23.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72c68dda124a1a138340fb62fa21b9bf4848437d9ca60bd35db36f2d3345f373", size = 5436510, upload-time = "2024-07-15T00:15:46.509Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/81/4f/c21383d97cb7a422ddf1ae824b53ce4b51063d0eeb2afa757eb40804a8ef/zstandard-0.23.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53dd9d5e3d29f95acd5de6802e909ada8d8d8cfa37a3ac64836f3bc4bc5512db", size = 4859973, upload-time = "2024-07-15T00:15:49.939Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ab/15/08d22e87753304405ccac8be2493a495f529edd81d39a0870621462276ef/zstandard-0.23.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:6a41c120c3dbc0d81a8e8adc73312d668cd34acd7725f036992b1b72d22c1772", size = 4936968, upload-time = "2024-07-15T00:15:52.025Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/eb/fa/f3670a597949fe7dcf38119a39f7da49a8a84a6f0b1a2e46b2f71a0ab83f/zstandard-0.23.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:40b33d93c6eddf02d2c19f5773196068d875c41ca25730e8288e9b672897c105", size = 5467179, upload-time = "2024-07-15T00:15:54.971Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/4e/a9/dad2ab22020211e380adc477a1dbf9f109b1f8d94c614944843e20dc2a99/zstandard-0.23.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9206649ec587e6b02bd124fb7799b86cddec350f6f6c14bc82a2b70183e708ba", size = 4848577, upload-time = "2024-07-15T00:15:57.634Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/08/03/dd28b4484b0770f1e23478413e01bee476ae8227bbc81561f9c329e12564/zstandard-0.23.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76e79bc28a65f467e0409098fa2c4376931fd3207fbeb6b956c7c476d53746dd", size = 4693899, upload-time = "2024-07-15T00:16:00.811Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/2b/64/3da7497eb635d025841e958bcd66a86117ae320c3b14b0ae86e9e8627518/zstandard-0.23.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:66b689c107857eceabf2cf3d3fc699c3c0fe8ccd18df2219d978c0283e4c508a", size = 5199964, upload-time = "2024-07-15T00:16:03.669Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/43/a4/d82decbab158a0e8a6ebb7fc98bc4d903266bce85b6e9aaedea1d288338c/zstandard-0.23.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9c236e635582742fee16603042553d276cca506e824fa2e6489db04039521e90", size = 5655398, upload-time = "2024-07-15T00:16:06.694Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/f2/61/ac78a1263bc83a5cf29e7458b77a568eda5a8f81980691bbc6eb6a0d45cc/zstandard-0.23.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35", size = 5191313, upload-time = "2024-07-15T00:16:09.758Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/e7/54/967c478314e16af5baf849b6ee9d6ea724ae5b100eb506011f045d3d4e16/zstandard-0.23.0-cp312-cp312-win32.whl", hash = "sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d", size = 430877, upload-time = "2024-07-15T00:16:11.758Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/75/37/872d74bd7739639c4553bf94c84af7d54d8211b626b352bc57f0fd8d1e3f/zstandard-0.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b", size = 495595, upload-time = "2024-07-15T00:16:13.731Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/80/f1/8386f3f7c10261fe85fbc2c012fdb3d4db793b921c9abcc995d8da1b7a80/zstandard-0.23.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:576856e8594e6649aee06ddbfc738fec6a834f7c85bf7cadd1c53d4a58186ef9", size = 788975, upload-time = "2024-07-15T00:16:16.005Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/16/e8/cbf01077550b3e5dc86089035ff8f6fbbb312bc0983757c2d1117ebba242/zstandard-0.23.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38302b78a850ff82656beaddeb0bb989a0322a8bbb1bf1ab10c17506681d772a", size = 633448, upload-time = "2024-07-15T00:16:17.897Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/06/27/4a1b4c267c29a464a161aeb2589aff212b4db653a1d96bffe3598f3f0d22/zstandard-0.23.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2240ddc86b74966c34554c49d00eaafa8200a18d3a5b6ffbf7da63b11d74ee2", size = 4945269, upload-time = "2024-07-15T00:16:20.136Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7c/64/d99261cc57afd9ae65b707e38045ed8269fbdae73544fd2e4a4d50d0ed83/zstandard-0.23.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ef230a8fd217a2015bc91b74f6b3b7d6522ba48be29ad4ea0ca3a3775bf7dd5", size = 5306228, upload-time = "2024-07-15T00:16:23.398Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/7a/cf/27b74c6f22541f0263016a0fd6369b1b7818941de639215c84e4e94b2a1c/zstandard-0.23.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:774d45b1fac1461f48698a9d4b5fa19a69d47ece02fa469825b442263f04021f", size = 5336891, upload-time = "2024-07-15T00:16:26.391Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/fa/18/89ac62eac46b69948bf35fcd90d37103f38722968e2981f752d69081ec4d/zstandard-0.23.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f77fa49079891a4aab203d0b1744acc85577ed16d767b52fc089d83faf8d8ed", size = 5436310, upload-time = "2024-07-15T00:16:29.018Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a8/a8/5ca5328ee568a873f5118d5b5f70d1f36c6387716efe2e369010289a5738/zstandard-0.23.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac184f87ff521f4840e6ea0b10c0ec90c6b1dcd0bad2f1e4a9a1b4fa177982ea", size = 4859912, upload-time = "2024-07-15T00:16:31.871Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ea/ca/3781059c95fd0868658b1cf0440edd832b942f84ae60685d0cfdb808bca1/zstandard-0.23.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c363b53e257246a954ebc7c488304b5592b9c53fbe74d03bc1c64dda153fb847", size = 4936946, upload-time = "2024-07-15T00:16:34.593Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ce/11/41a58986f809532742c2b832c53b74ba0e0a5dae7e8ab4642bf5876f35de/zstandard-0.23.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e7792606d606c8df5277c32ccb58f29b9b8603bf83b48639b7aedf6df4fe8171", size = 5466994, upload-time = "2024-07-15T00:16:36.887Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/83/e3/97d84fe95edd38d7053af05159465d298c8b20cebe9ccb3d26783faa9094/zstandard-0.23.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a0817825b900fcd43ac5d05b8b3079937073d2b1ff9cf89427590718b70dd840", size = 4848681, upload-time = "2024-07-15T00:16:39.709Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/6e/99/cb1e63e931de15c88af26085e3f2d9af9ce53ccafac73b6e48418fd5a6e6/zstandard-0.23.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9da6bc32faac9a293ddfdcb9108d4b20416219461e4ec64dfea8383cac186690", size = 4694239, upload-time = "2024-07-15T00:16:41.83Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/ab/50/b1e703016eebbc6501fc92f34db7b1c68e54e567ef39e6e59cf5fb6f2ec0/zstandard-0.23.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fd7699e8fd9969f455ef2926221e0233f81a2542921471382e77a9e2f2b57f4b", size = 5200149, upload-time = "2024-07-15T00:16:44.287Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/aa/e0/932388630aaba70197c78bdb10cce2c91fae01a7e553b76ce85471aec690/zstandard-0.23.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d477ed829077cd945b01fc3115edd132c47e6540ddcd96ca169facff28173057", size = 5655392, upload-time = "2024-07-15T00:16:46.423Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/02/90/2633473864f67a15526324b007a9f96c96f56d5f32ef2a56cc12f9548723/zstandard-0.23.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ce8b52c5987b3e34d5674b0ab529a4602b632ebab0a93b07bfb4dfc8f8a33", size = 5191299, upload-time = "2024-07-15T00:16:49.053Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/b0/4c/315ca5c32da7e2dc3455f3b2caee5c8c2246074a61aac6ec3378a97b7136/zstandard-0.23.0-cp313-cp313-win32.whl", hash = "sha256:a9b07268d0c3ca5c170a385a0ab9fb7fdd9f5fd866be004c4ea39e44edce47dd", size = 430862, upload-time = "2024-07-15T00:16:51.003Z" }, - { url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/packages/a2/bf/c6aaba098e2d04781e8f4f7c0ba3c7aa73d00e4c436bcc0cf059a66691d1/zstandard-0.23.0-cp313-cp313-win_amd64.whl", hash = "sha256:f3513916e8c645d0610815c257cbfd3242adfd5c4cfa78be514e5a3ebb42a41b", size = 495578, upload-time = "2024-07-15T00:16:53.135Z" }, +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ed/f6/2ac0287b442160a89d726b17a9184a4c615bb5237db763791a7fd16d9df1/zstandard-0.23.0.tar.gz", hash = "sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09", size = 681701, upload-time = "2024-07-15T00:18:06.141Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7b/83/f23338c963bd9de687d47bf32efe9fd30164e722ba27fb59df33e6b1719b/zstandard-0.23.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b4567955a6bc1b20e9c31612e615af6b53733491aeaa19a6b3b37f3b65477094", size = 788713, upload-time = "2024-07-15T00:15:35.815Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5b/b3/1a028f6750fd9227ee0b937a278a434ab7f7fdc3066c3173f64366fe2466/zstandard-0.23.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e172f57cd78c20f13a3415cc8dfe24bf388614324d25539146594c16d78fcc8", size = 633459, upload-time = "2024-07-15T00:15:37.995Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/26/af/36d89aae0c1f95a0a98e50711bc5d92c144939efc1f81a2fcd3e78d7f4c1/zstandard-0.23.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0e166f698c5a3e914947388c162be2583e0c638a4703fc6a543e23a88dea3c1", size = 4945707, upload-time = "2024-07-15T00:15:39.872Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cd/2e/2051f5c772f4dfc0aae3741d5fc72c3dcfe3aaeb461cc231668a4db1ce14/zstandard-0.23.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12a289832e520c6bd4dcaad68e944b86da3bad0d339ef7989fb7e88f92e96072", size = 5306545, upload-time = "2024-07-15T00:15:41.75Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/0a/9e/a11c97b087f89cab030fa71206963090d2fecd8eb83e67bb8f3ffb84c024/zstandard-0.23.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d50d31bfedd53a928fed6707b15a8dbeef011bb6366297cc435accc888b27c20", size = 5337533, upload-time = "2024-07-15T00:15:44.114Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fc/79/edeb217c57fe1bf16d890aa91a1c2c96b28c07b46afed54a5dcf310c3f6f/zstandard-0.23.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72c68dda124a1a138340fb62fa21b9bf4848437d9ca60bd35db36f2d3345f373", size = 5436510, upload-time = "2024-07-15T00:15:46.509Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/81/4f/c21383d97cb7a422ddf1ae824b53ce4b51063d0eeb2afa757eb40804a8ef/zstandard-0.23.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53dd9d5e3d29f95acd5de6802e909ada8d8d8cfa37a3ac64836f3bc4bc5512db", size = 4859973, upload-time = "2024-07-15T00:15:49.939Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ab/15/08d22e87753304405ccac8be2493a495f529edd81d39a0870621462276ef/zstandard-0.23.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:6a41c120c3dbc0d81a8e8adc73312d668cd34acd7725f036992b1b72d22c1772", size = 4936968, upload-time = "2024-07-15T00:15:52.025Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/eb/fa/f3670a597949fe7dcf38119a39f7da49a8a84a6f0b1a2e46b2f71a0ab83f/zstandard-0.23.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:40b33d93c6eddf02d2c19f5773196068d875c41ca25730e8288e9b672897c105", size = 5467179, upload-time = "2024-07-15T00:15:54.971Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4e/a9/dad2ab22020211e380adc477a1dbf9f109b1f8d94c614944843e20dc2a99/zstandard-0.23.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9206649ec587e6b02bd124fb7799b86cddec350f6f6c14bc82a2b70183e708ba", size = 4848577, upload-time = "2024-07-15T00:15:57.634Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/08/03/dd28b4484b0770f1e23478413e01bee476ae8227bbc81561f9c329e12564/zstandard-0.23.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76e79bc28a65f467e0409098fa2c4376931fd3207fbeb6b956c7c476d53746dd", size = 4693899, upload-time = "2024-07-15T00:16:00.811Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2b/64/3da7497eb635d025841e958bcd66a86117ae320c3b14b0ae86e9e8627518/zstandard-0.23.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:66b689c107857eceabf2cf3d3fc699c3c0fe8ccd18df2219d978c0283e4c508a", size = 5199964, upload-time = "2024-07-15T00:16:03.669Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/43/a4/d82decbab158a0e8a6ebb7fc98bc4d903266bce85b6e9aaedea1d288338c/zstandard-0.23.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9c236e635582742fee16603042553d276cca506e824fa2e6489db04039521e90", size = 5655398, upload-time = "2024-07-15T00:16:06.694Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f2/61/ac78a1263bc83a5cf29e7458b77a568eda5a8f81980691bbc6eb6a0d45cc/zstandard-0.23.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35", size = 5191313, upload-time = "2024-07-15T00:16:09.758Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e7/54/967c478314e16af5baf849b6ee9d6ea724ae5b100eb506011f045d3d4e16/zstandard-0.23.0-cp312-cp312-win32.whl", hash = "sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d", size = 430877, upload-time = "2024-07-15T00:16:11.758Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/75/37/872d74bd7739639c4553bf94c84af7d54d8211b626b352bc57f0fd8d1e3f/zstandard-0.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b", size = 495595, upload-time = "2024-07-15T00:16:13.731Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/80/f1/8386f3f7c10261fe85fbc2c012fdb3d4db793b921c9abcc995d8da1b7a80/zstandard-0.23.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:576856e8594e6649aee06ddbfc738fec6a834f7c85bf7cadd1c53d4a58186ef9", size = 788975, upload-time = "2024-07-15T00:16:16.005Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/16/e8/cbf01077550b3e5dc86089035ff8f6fbbb312bc0983757c2d1117ebba242/zstandard-0.23.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38302b78a850ff82656beaddeb0bb989a0322a8bbb1bf1ab10c17506681d772a", size = 633448, upload-time = "2024-07-15T00:16:17.897Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/06/27/4a1b4c267c29a464a161aeb2589aff212b4db653a1d96bffe3598f3f0d22/zstandard-0.23.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2240ddc86b74966c34554c49d00eaafa8200a18d3a5b6ffbf7da63b11d74ee2", size = 4945269, upload-time = "2024-07-15T00:16:20.136Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7c/64/d99261cc57afd9ae65b707e38045ed8269fbdae73544fd2e4a4d50d0ed83/zstandard-0.23.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ef230a8fd217a2015bc91b74f6b3b7d6522ba48be29ad4ea0ca3a3775bf7dd5", size = 5306228, upload-time = "2024-07-15T00:16:23.398Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7a/cf/27b74c6f22541f0263016a0fd6369b1b7818941de639215c84e4e94b2a1c/zstandard-0.23.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:774d45b1fac1461f48698a9d4b5fa19a69d47ece02fa469825b442263f04021f", size = 5336891, upload-time = "2024-07-15T00:16:26.391Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fa/18/89ac62eac46b69948bf35fcd90d37103f38722968e2981f752d69081ec4d/zstandard-0.23.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f77fa49079891a4aab203d0b1744acc85577ed16d767b52fc089d83faf8d8ed", size = 5436310, upload-time = "2024-07-15T00:16:29.018Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a8/a8/5ca5328ee568a873f5118d5b5f70d1f36c6387716efe2e369010289a5738/zstandard-0.23.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac184f87ff521f4840e6ea0b10c0ec90c6b1dcd0bad2f1e4a9a1b4fa177982ea", size = 4859912, upload-time = "2024-07-15T00:16:31.871Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ea/ca/3781059c95fd0868658b1cf0440edd832b942f84ae60685d0cfdb808bca1/zstandard-0.23.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c363b53e257246a954ebc7c488304b5592b9c53fbe74d03bc1c64dda153fb847", size = 4936946, upload-time = "2024-07-15T00:16:34.593Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ce/11/41a58986f809532742c2b832c53b74ba0e0a5dae7e8ab4642bf5876f35de/zstandard-0.23.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e7792606d606c8df5277c32ccb58f29b9b8603bf83b48639b7aedf6df4fe8171", size = 5466994, upload-time = "2024-07-15T00:16:36.887Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/83/e3/97d84fe95edd38d7053af05159465d298c8b20cebe9ccb3d26783faa9094/zstandard-0.23.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a0817825b900fcd43ac5d05b8b3079937073d2b1ff9cf89427590718b70dd840", size = 4848681, upload-time = "2024-07-15T00:16:39.709Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6e/99/cb1e63e931de15c88af26085e3f2d9af9ce53ccafac73b6e48418fd5a6e6/zstandard-0.23.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9da6bc32faac9a293ddfdcb9108d4b20416219461e4ec64dfea8383cac186690", size = 4694239, upload-time = "2024-07-15T00:16:41.83Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ab/50/b1e703016eebbc6501fc92f34db7b1c68e54e567ef39e6e59cf5fb6f2ec0/zstandard-0.23.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fd7699e8fd9969f455ef2926221e0233f81a2542921471382e77a9e2f2b57f4b", size = 5200149, upload-time = "2024-07-15T00:16:44.287Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/e0/932388630aaba70197c78bdb10cce2c91fae01a7e553b76ce85471aec690/zstandard-0.23.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d477ed829077cd945b01fc3115edd132c47e6540ddcd96ca169facff28173057", size = 5655392, upload-time = "2024-07-15T00:16:46.423Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/02/90/2633473864f67a15526324b007a9f96c96f56d5f32ef2a56cc12f9548723/zstandard-0.23.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ce8b52c5987b3e34d5674b0ab529a4602b632ebab0a93b07bfb4dfc8f8a33", size = 5191299, upload-time = "2024-07-15T00:16:49.053Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b0/4c/315ca5c32da7e2dc3455f3b2caee5c8c2246074a61aac6ec3378a97b7136/zstandard-0.23.0-cp313-cp313-win32.whl", hash = "sha256:a9b07268d0c3ca5c170a385a0ab9fb7fdd9f5fd866be004c4ea39e44edce47dd", size = 430862, upload-time = "2024-07-15T00:16:51.003Z" }, + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/bf/c6aaba098e2d04781e8f4f7c0ba3c7aa73d00e4c436bcc0cf059a66691d1/zstandard-0.23.0-cp313-cp313-win_amd64.whl", hash = "sha256:f3513916e8c645d0610815c257cbfd3242adfd5c4cfa78be514e5a3ebb42a41b", size = 495578, upload-time = "2024-07-15T00:16:53.135Z" }, ] diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 20f4f7d7b..a85ddb47a 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -208,6 +208,18 @@ services: condition: service_healthy + # CLI Agent base image build service (used by CLIContainerService for executions) + # This service only builds the image; it does not run as a long-lived container. + # Per-execution containers are dynamically created by CLIContainerService. + cli-agent-image: + image: joysafeter/cli-agent:latest + build: + context: .. + dockerfile: deploy/docker/cli-agent.Dockerfile + profiles: + - build + command: ["echo", "Image built successfully"] + # OpenClaw base image build service (used by backend to create per-user containers) # This service only builds the image; it does not run as a long-lived container. # Per-user OpenClaw instances are dynamically created by the backend's diff --git a/deploy/docker/cli-agent.Dockerfile b/deploy/docker/cli-agent.Dockerfile new file mode 100644 index 000000000..a8c1e80ff --- /dev/null +++ b/deploy/docker/cli-agent.Dockerfile @@ -0,0 +1,47 @@ +# ============================================================================= +# CLI Agent Docker Image +# ============================================================================= +# Pre-installs Claude Code CLI for autonomous agent execution. +# Used by CLIContainerService to spin up per-execution containers. +# +# Build: +# docker build -f deploy/docker/cli-agent.Dockerfile -t joysafeter/cli-agent:latest . +# ============================================================================= + +FROM node:22-slim + +# System deps +RUN apt-get update && apt-get install -y --no-install-recommends \ + git \ + curl \ + ca-certificates \ + openssh-client \ + jq \ + && rm -rf /var/lib/apt/lists/* + +# Install Claude Code CLI globally +RUN npm install -g @anthropic-ai/claude-code + +# Install Codex CLI +RUN npm install -g @openai/codex + +# Install OpenClaw (if available via npm, otherwise skip) +# RUN npm install -g openclaw@latest + +# Create non-root user +RUN groupadd -r agent && useradd -r -g agent -m -d /home/agent -s /bin/bash agent + +# Workspace directory +RUN mkdir -p /workspace && chown agent:agent /workspace + +# Default working directory +WORKDIR /workspace + +# Switch to non-root user +USER agent + +# Verify installation +RUN claude --version || echo "Claude CLI installed" + +# Default entrypoint keeps container alive for docker exec +CMD ["sleep", "infinity"] diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 561d1e679..1f6339ee3 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -276,25 +276,24 @@ sequenceDiagram ```mermaid sequenceDiagram participant Frontend as Frontend - participant API as REST API + participant API as API (WebSocket) participant Service as GraphService participant Runtime as LangGraph Runtime - participant SSE as SSE Stream - Frontend->>API: POST /api/chat (SSE) + Frontend->>API: WS /ws/chat (WebSocket) API->>Service: Load and compile graph Service-->>Runtime: CompiledStateGraph Service->>Runtime: ainvoke({"messages": [...]}) loop Each Node Runtime->>Runtime: Execute node - Runtime->>SSE: Push event (node_start/node_end) - SSE-->>Frontend: Stream update + Runtime->>API: Push event (node_start/node_end) + API-->>Frontend: Stream update via WebSocket end Runtime-->>Service: Final result - Service-->>SSE: End event - SSE-->>Frontend: Stream complete + Service-->>API: End event + API-->>Frontend: Stream complete ``` ### Data Flow diff --git a/docs/superpowers/plans/2026-03-18-skill-creator-agent.md b/docs/superpowers/plans/2026-03-18-skill-creator-agent.md deleted file mode 100644 index c9064dbae..000000000 --- a/docs/superpowers/plans/2026-03-18-skill-creator-agent.md +++ /dev/null @@ -1,1285 +0,0 @@ -# Skill Creator Agent — Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Allow users to create/modify Skills through AI Agent conversation in a Docker sandbox, preview results, and save to DB after confirmation. - -**Architecture:** Reuse existing `/v1/chat/stream` SSE architecture with a new `mode="skill_creator"` parameter. A dedicated `create_skill_creator_graph()` method in `GraphService` creates a single-node DeepAgents graph with skill-creator system prompt. The `preview_skill` builtin tool reads generated files from the sandbox for frontend rendering. Frontend adds a Skill Creator page with chat + preview panel layout, and a Dashboard entry card. - -**Tech Stack:** FastAPI, LangGraph, DeepAgents, Docker Sandbox (pydantic-ai-backend), Next.js 16 (App Router), React 19, TypeScript, Zustand, TanStack Query - -**Spec:** `docs/superpowers/specs/2026-03-18-skill-creator-agent-design.md` - ---- - -## File Structure - -### Backend — New Files - -| File | Responsibility | -|------|---------------| -| `backend/app/core/tools/buildin/preview_skill.py` | `preview_skill` tool: reads skill files from sandbox host path, validates, returns structured JSON | - -### Backend — Modified Files - -| File | Change | -|------|--------| -| `backend/app/schemas/chat.py` | Add `mode` and `edit_skill_id` fields to `ChatRequest` | -| `backend/app/api/v1/chat.py` | Handle `mode="skill_creator"` branch in `chat_stream` and `chat` | -| `backend/app/services/graph_service.py` | Add `create_skill_creator_graph()` method | -| `backend/app/core/tools/tool_registry.py` | Register `preview_skill` in `_initialize_builtin_tools()` | - -### Frontend — New Files - -| File | Responsibility | -|------|---------------| -| `frontend/app/skills/creator/page.tsx` | Skill Creator page (route: `/skills/creator`) | -| `frontend/app/skills/creator/components/SkillCreatorChat.tsx` | Chat panel wrapping `ChatInterface` with `mode=skill_creator` | -| `frontend/app/skills/creator/components/SkillPreviewPanel.tsx` | Right panel: file tree + content viewer + save button | -| `frontend/app/skills/creator/components/SkillFileTree.tsx` | File directory tree | -| `frontend/app/skills/creator/components/SkillFileViewer.tsx` | Single file content with syntax highlighting | -| `frontend/app/skills/creator/components/SkillSaveDialog.tsx` | Confirmation dialog before saving to DB | - -### Frontend — Modified Files - -| File | Change | -|------|--------| -| `frontend/app/chat/hooks/useBackendChatStream.ts` | Pass `mode` through to backend in `streamChat` call | -| `frontend/app/skills/page.tsx` | Add "AI Create" button linking to `/skills/creator` | -| `frontend/app/chat/components/ChatHome.tsx` | Add Skill Creator entry card on chat home | - ---- - -## Task 1: Backend — Extend ChatRequest Schema - -**Files:** -- Modify: `backend/app/schemas/chat.py:8-15` -- Test: `backend/tests/test_schemas/test_chat.py` (create if needed) - -- [ ] **Step 1: Write the failing test** - -```python -# backend/tests/test_schemas/test_chat.py -from app.schemas.chat import ChatRequest - - -def test_chat_request_with_mode(): - req = ChatRequest( - message="Create a skill", - mode="skill_creator", - edit_skill_id="some-uuid-string", - ) - assert req.mode == "skill_creator" - assert req.edit_skill_id == "some-uuid-string" - - -def test_chat_request_mode_defaults_to_none(): - req = ChatRequest(message="Hello") - assert req.mode is None - assert req.edit_skill_id is None - - -def test_chat_request_mode_validation(): - """mode must be None or 'skill_creator'""" - import pytest - from pydantic import ValidationError - - with pytest.raises(ValidationError): - ChatRequest(message="Hello", mode="invalid_mode") -``` - -- [ ] **Step 2: Run test to verify it fails** - -Run: `cd backend && python -m pytest tests/test_schemas/test_chat.py -v` -Expected: FAIL — `ChatRequest` doesn't accept `mode` or `edit_skill_id` - -- [ ] **Step 3: Implement schema changes** - -Edit `backend/app/schemas/chat.py`: - -```python -from typing import Any, Literal - -class ChatRequest(PydanticBaseModel): - message: str = Field(..., description="用户消息") - thread_id: str | None = Field(None, description="会话线程ID,不提供则创建新会话") - graph_id: uuid.UUID | None = Field(None, description="图ID,使用指定的图进行对话") - metadata: dict[str, Any] = Field(default_factory=dict, description="元数据") - mode: Literal["skill_creator"] | None = Field(None, description="特殊模式: skill_creator 使用 Skill 创建专用 Graph") - edit_skill_id: str | None = Field(None, description="修改已有 Skill 时传入 Skill ID") -``` - -- [ ] **Step 4: Run test to verify it passes** - -Run: `cd backend && python -m pytest tests/test_schemas/test_chat.py -v` -Expected: PASS - -- [ ] **Step 5: Commit** - -```bash -git add backend/app/schemas/chat.py backend/tests/test_schemas/test_chat.py -git commit -m "feat(schema): add mode and edit_skill_id to ChatRequest" -``` - ---- - -## Task 2: Backend — preview_skill Builtin Tool - -**Files:** -- Create: `backend/app/core/tools/buildin/preview_skill.py` -- Test: `backend/tests/test_tools/test_preview_skill.py` (create) - -- [ ] **Step 1: Write the failing test** - -```python -# backend/tests/test_tools/test_preview_skill.py -import json -import os -import tempfile -from pathlib import Path - -import pytest - -from app.core.tools.buildin.preview_skill import preview_skill_in_sandbox - - -@pytest.fixture -def skill_dir(): - """Create a temporary skill directory with SKILL.md and a script.""" - with tempfile.TemporaryDirectory() as tmpdir: - skill_path = Path(tmpdir) / "skills" / "test-skill" - skill_path.mkdir(parents=True) - - # Write SKILL.md - skill_md = skill_path / "SKILL.md" - skill_md.write_text( - "---\nname: test-skill\ndescription: A test skill\n---\n# Test Skill\nInstructions here." - ) - - # Write a script - scripts_dir = skill_path / "scripts" - scripts_dir.mkdir() - (scripts_dir / "run.py").write_text("print('hello')") - - yield tmpdir - - -def test_preview_skill_returns_structured_output(skill_dir): - result = preview_skill_in_sandbox( - skill_name="test-skill", - sandbox_root=skill_dir, - ) - data = json.loads(result) - assert data["skill_name"] == "test-skill" - assert len(data["files"]) == 2 - assert data["validation"]["valid"] is True - - file_paths = [f["path"] for f in data["files"]] - assert "SKILL.md" in file_paths - assert "scripts/run.py" in file_paths - - -def test_preview_skill_missing_skill_md(skill_dir): - """A skill without SKILL.md should fail validation.""" - skill_path = Path(skill_dir) / "skills" / "bad-skill" - skill_path.mkdir(parents=True) - (skill_path / "readme.txt").write_text("no skill md") - - result = preview_skill_in_sandbox( - skill_name="bad-skill", - sandbox_root=skill_dir, - ) - data = json.loads(result) - assert data["validation"]["valid"] is False - assert any("SKILL.md" in e for e in data["validation"]["errors"]) - - -def test_preview_skill_nonexistent_dir(skill_dir): - result = preview_skill_in_sandbox( - skill_name="nonexistent", - sandbox_root=skill_dir, - ) - data = json.loads(result) - assert data["validation"]["valid"] is False - assert any("not found" in e.lower() for e in data["validation"]["errors"]) -``` - -- [ ] **Step 2: Run test to verify it fails** - -Run: `cd backend && python -m pytest tests/test_tools/test_preview_skill.py -v` -Expected: FAIL — `ImportError: cannot import name 'preview_skill_in_sandbox'` - -- [ ] **Step 3: Implement preview_skill tool** - -Create `backend/app/core/tools/buildin/preview_skill.py`: - -```python -"""preview_skill — reads generated skill files from sandbox and returns structured JSON.""" -import json -from pathlib import Path -from typing import Optional - -from app.core.skill.validators import ( - validate_skill_description, - validate_skill_name, -) -from app.core.skill.yaml_parser import parse_skill_md - - -def _detect_file_type(path: str) -> str: - ext_map = { - ".py": "python", - ".md": "markdown", - ".json": "json", - ".yaml": "yaml", - ".yml": "yaml", - ".txt": "text", - ".sh": "shell", - ".js": "javascript", - ".ts": "typescript", - } - suffix = Path(path).suffix.lower() - return ext_map.get(suffix, "text") - - -def preview_skill_in_sandbox( - skill_name: str, - sandbox_root: str, - skills_subdir: str = "skills", -) -> str: - """Read all files from a skill directory in the sandbox and return structured JSON. - - Args: - skill_name: Directory name under /workspace/skills/ in the sandbox. - sandbox_root: Host-side sandbox root (e.g., /tmp/sandboxes/{user_id}). - skills_subdir: Subdirectory within sandbox_root where skills live. - - Returns: - JSON string with skill_name, files[], and validation{}. - """ - skill_dir = Path(sandbox_root) / skills_subdir / skill_name - errors: list[str] = [] - warnings: list[str] = [] - files: list[dict] = [] - - if not skill_dir.exists() or not skill_dir.is_dir(): - return json.dumps( - { - "skill_name": skill_name, - "files": [], - "validation": { - "valid": False, - "errors": [f"Skill directory not found: {skill_name}"], - "warnings": [], - }, - }, - ensure_ascii=False, - ) - - # Collect all files recursively - for file_path in sorted(skill_dir.rglob("*")): - if not file_path.is_file(): - continue - rel_path = str(file_path.relative_to(skill_dir)) - try: - content = file_path.read_text(encoding="utf-8") - except (UnicodeDecodeError, OSError): - content = f"[Binary or unreadable file: {rel_path}]" - files.append( - { - "path": rel_path, - "content": content, - "file_type": _detect_file_type(rel_path), - "size": file_path.stat().st_size, - } - ) - - # Validate: SKILL.md must exist - skill_md_files = [f for f in files if f["path"] == "SKILL.md"] - if not skill_md_files: - errors.append("Missing required file: SKILL.md") - else: - # Parse and validate frontmatter - skill_md_content = skill_md_files[0]["content"] - try: - frontmatter, body = parse_skill_md(skill_md_content) - name = frontmatter.get("name", "") - description = frontmatter.get("description", "") - - name_valid, name_msg = validate_skill_name(name) - if not name_valid: - errors.append(f"Name validation: {name_msg}") - - desc_valid, desc_msg = validate_skill_description(description) - if not desc_valid: - errors.append(f"Description validation: {desc_msg}") - - if not body.strip(): - warnings.append("SKILL.md body is empty") - - except Exception as e: - errors.append(f"Failed to parse SKILL.md: {e}") - - return json.dumps( - { - "skill_name": skill_name, - "files": files, - "validation": { - "valid": len(errors) == 0, - "errors": errors, - "warnings": warnings, - }, - }, - ensure_ascii=False, - ) -``` - -- [ ] **Step 4: Run test to verify it passes** - -Run: `cd backend && python -m pytest tests/test_tools/test_preview_skill.py -v` -Expected: PASS - -- [ ] **Step 5: Commit** - -```bash -git add backend/app/core/tools/buildin/preview_skill.py backend/tests/test_tools/test_preview_skill.py -git commit -m "feat(tools): add preview_skill builtin tool" -``` - ---- - -## Task 3: Backend — Register preview_skill in Tool Registry - -**Files:** -- Modify: `backend/app/core/tools/tool_registry.py:611-652` - -- [ ] **Step 1: Add import and registration** - -Edit `backend/app/core/tools/tool_registry.py`, inside `_initialize_builtin_tools()`, after the existing `skill_tools.deploy_local_skill` registration block: - -```python -from app.core.tools.buildin.preview_skill import preview_skill_in_sandbox - -registry.register_builtin( - callable_func=preview_skill_in_sandbox, - name="preview_skill", - description="Preview a skill generated in the sandbox. Reads all files from the skill directory and returns structured JSON with file contents and validation results.", - category="skill", - tags={"skill", "preview", "sandbox"}, -) -``` - -- [ ] **Step 2: Verify import works** - -Run: `cd backend && python -c "from app.core.tools.buildin.preview_skill import preview_skill_in_sandbox; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/core/tools/tool_registry.py -git commit -m "feat(tools): register preview_skill in builtin tool registry" -``` - ---- - -## Task 4: Backend — GraphService.create_skill_creator_graph() - -**Files:** -- Modify: `backend/app/services/graph_service.py:667-744` (add method after `create_default_deep_agents_graph`) - -- [ ] **Step 1: Read the existing `create_default_deep_agents_graph` method** - -Read `backend/app/services/graph_service.py` lines 667-744 to understand the exact pattern. - -- [ ] **Step 2: Implement `create_skill_creator_graph()`** - -Add new method to `GraphService` class, following the same pattern as `create_default_deep_agents_graph`: - -```python -async def create_skill_creator_graph( - self, - llm_model: Optional[str] = None, - api_key: Optional[str] = None, - base_url: Optional[str] = None, - max_tokens: int = 4096, - user_id: Optional[Any] = None, - edit_skill_id: Optional[str] = None, -) -> CompiledStateGraph: - """Create a specialized graph for the Skill Creator Agent. - - Uses the same single-node DeepAgents pattern as the default graph, - but with a skill-creator-specific system prompt and tool configuration. - """ - from app.core.skill.sandbox_loader import SkillSandboxLoader - - # Build skill creator system prompt - skill_creator_system_prompt = ( - "You are a Skill Creator Agent. Your job is to help users create and modify " - "Skills (reusable capability packages) through conversation.\n\n" - "## Workflow\n" - "1. Understand the user's requirements through conversation\n" - "2. Use init_skill.py to initialize the skill directory structure\n" - "3. Write SKILL.md with proper YAML frontmatter (name, description) + markdown body\n" - "4. Create supporting files in scripts/, references/, assets/ as needed\n" - "5. Run quick_validate.py to validate the skill\n" - "6. Call the preview_skill tool to output the final result for user review\n\n" - "## Rules\n" - "- Skill names must match: ^[a-z0-9]+(-[a-z0-9]+)*$ (max 64 chars)\n" - "- SKILL.md is required with YAML frontmatter containing 'name' and 'description'\n" - "- Always validate before previewing\n" - "- The skill-creator skill is pre-loaded at /workspace/skills/skill-creator/ — " - "use its scripts (init_skill.py, quick_validate.py) and references for guidance\n" - ) - - if edit_skill_id: - skill_creator_system_prompt += ( - f"\n## Editing Mode\n" - f"The user wants to modify an existing skill (ID: {edit_skill_id}). " - f"The skill files have been pre-loaded into the sandbox. " - f"Read the existing files first, then apply the user's requested changes.\n" - ) - - graph_id = uuid.uuid4() - graph = AgentGraph( - id=graph_id, - name="Skill Creator", - description="AI-powered skill creation and modification", - ) - - node = GraphNode( - id=uuid.uuid4(), - graph_id=graph_id, - type="agent", - data={ - "label": "Skill Creator Agent", - "config": { - "useDeepAgents": True, - "skills": ["*"], - "mode": "skill_creator", - "system_prompt": skill_creator_system_prompt, - }, - }, - position={"x": 0, "y": 0}, - ) - - builder = GraphBuilder( - graph=graph, - nodes=[node], - edges=[], - llm_model=llm_model, - api_key=api_key, - base_url=base_url, - max_tokens=max_tokens, - user_id=user_id, - ) - return await builder.build() -``` - -- [ ] **Step 3: Verify no import errors** - -Run: `cd backend && python -c "from app.services.graph_service import GraphService; print('OK')"` -Expected: `OK` - -- [ ] **Step 4: Commit** - -```bash -git add backend/app/services/graph_service.py -git commit -m "feat(graph): add create_skill_creator_graph() to GraphService" -``` - ---- - -## Task 5: Backend — Wire mode="skill_creator" into Chat Stream - -**Files:** -- Modify: `backend/app/api/v1/chat.py:694-713` (inside `event_generator()` in `chat_stream`) - -- [ ] **Step 1: Read the current branching logic** - -Read `backend/app/api/v1/chat.py` lines 690-720 to see the exact graph creation branch. - -- [ ] **Step 2: Add skill_creator mode branch** - -Insert the new branch between `graph_service = GraphService(db)` (line 694) and `if payload.graph_id is None` (line 695): - -```python -graph_service = GraphService(db) - -# Skill Creator mode — dedicated graph -if payload.mode == "skill_creator": - graph = await graph_service.create_skill_creator_graph( - llm_model=llm_model, - api_key=api_key, - base_url=base_url, - max_tokens=max_tokens, - user_id=str(current_user.id), - edit_skill_id=payload.edit_skill_id, - ) -elif payload.graph_id is None: - # ... existing default graph creation -``` - -Also add the same branch in the non-streaming `chat` endpoint (around lines 554-573) following the identical pattern. - -- [ ] **Step 3: Handle edit_skill_id preloading** - -After the graph is created in skill_creator mode, add skill preloading logic. If `edit_skill_id` is provided, load the target skill into the sandbox before the agent starts: - -```python -if payload.mode == "skill_creator" and payload.edit_skill_id: - try: - from app.core.skill.sandbox_loader import SkillSandboxLoader - from app.services.skill_service import SkillService - - skill_service = SkillService(db) - loader = SkillSandboxLoader(db, user_id=str(current_user.id)) - # The sandbox backend will be available from the graph's agent node - # Preloading happens at graph build time via DeepAgentsGraphBuilder - except Exception as e: - logger.warning(f"Failed to preload skill for editing: {e}") -``` - -Note: The actual preloading mechanism depends on how `DeepAgentsGraphBuilder` initializes the sandbox. The `edit_skill_id` is passed into the graph config so the builder can handle it during `build()`. Verify by reading `deep_agents_builder.py` before implementing this step. - -- [ ] **Step 4: Test manually** - -Run: `cd backend && python -c "from app.api.v1.chat import router; print('Router loaded OK')"` -Expected: `OK` (no import errors) - -- [ ] **Step 5: Commit** - -```bash -git add backend/app/api/v1/chat.py -git commit -m "feat(chat): wire mode=skill_creator into chat_stream endpoint" -``` - ---- - -## Task 6: Frontend — Skill Creator Page Layout - -**Files:** -- Create: `frontend/app/skills/creator/page.tsx` - -- [ ] **Step 1: Create the page** - -```tsx -// frontend/app/skills/creator/page.tsx -"use client"; - -import { useSearchParams } from "next/navigation"; -import { useState, useCallback } from "react"; -import { SkillCreatorChat } from "./components/SkillCreatorChat"; -import { SkillPreviewPanel } from "./components/SkillPreviewPanel"; - -export interface SkillPreviewData { - skill_name: string; - files: Array<{ - path: string; - content: string; - file_type: string; - size: number; - }>; - validation: { - valid: boolean; - errors: string[]; - warnings: string[]; - }; -} - -export default function SkillCreatorPage() { - const searchParams = useSearchParams(); - const editSkillId = searchParams.get("edit"); - const [previewData, setPreviewData] = useState(null); - - const handlePreviewUpdate = useCallback((data: SkillPreviewData) => { - setPreviewData(data); - }, []); - - return ( -
- {/* Left: Chat panel */} -
- -
- - {/* Right: Preview panel */} -
- -
-
- ); -} -``` - -- [ ] **Step 2: Verify route exists** - -Run: `ls frontend/app/skills/creator/page.tsx` -Expected: File exists - -- [ ] **Step 3: Commit** - -```bash -git add frontend/app/skills/creator/page.tsx -git commit -m "feat(frontend): add Skill Creator page layout" -``` - ---- - -## Task 7: Frontend — SkillCreatorChat Component - -**Files:** -- Create: `frontend/app/skills/creator/components/SkillCreatorChat.tsx` - -- [ ] **Step 1: Create the component** - -This component wraps the existing chat stream hook with `mode="skill_creator"`. It intercepts `tool_end` events for `preview_skill` to extract preview data. - -```tsx -// frontend/app/skills/creator/components/SkillCreatorChat.tsx -"use client"; - -import { useState, useCallback, useRef } from "react"; -import { useBackendChatStream } from "@/app/chat/hooks/useBackendChatStream"; -import type { SkillPreviewData } from "../page"; - -interface SkillCreatorChatProps { - editSkillId: string | null; - onPreviewUpdate: (data: SkillPreviewData) => void; -} - -interface ChatMessage { - id: string; - role: "user" | "assistant"; - content: string; -} - -export function SkillCreatorChat({ - editSkillId, - onPreviewUpdate, -}: SkillCreatorChatProps) { - const [messages, setMessages] = useState([]); - const [input, setInput] = useState(""); - const [isStreaming, setIsStreaming] = useState(false); - const threadIdRef = useRef(null); - const messagesEndRef = useRef(null); - - const { sendMessage } = useBackendChatStream(setMessages as any, { - onEvent: (event: any) => { - // Intercept preview_skill tool_end events - if ( - event.type === "tool_end" && - event.data?.tool_name === "preview_skill" - ) { - try { - const previewData = JSON.parse(event.data.output); - onPreviewUpdate(previewData); - } catch { - // ignore parse errors - } - } - if (event.type === "thread_id" && event.data?.thread_id) { - threadIdRef.current = event.data.thread_id; - } - }, - }); - - const handleSend = useCallback(async () => { - if (!input.trim() || isStreaming) return; - - const userMessage = input.trim(); - setInput(""); - setMessages((prev) => [ - ...prev, - { id: crypto.randomUUID(), role: "user", content: userMessage }, - ]); - setIsStreaming(true); - - try { - await sendMessage(userMessage, { - threadId: threadIdRef.current, - graphId: null, - metadata: { - mode: "skill_creator", - edit_skill_id: editSkillId, - }, - }); - } finally { - setIsStreaming(false); - } - }, [input, isStreaming, sendMessage, editSkillId]); - - return ( -
-
-

- {editSkillId ? "AI Skill Editor" : "AI Skill Creator"} -

-
- - {/* Messages */} -
- {messages.map((msg) => ( -
-
- {msg.content} -
-
- ))} -
-
- - {/* Input */} -
-
- setInput(e.target.value)} - onKeyDown={(e) => e.key === "Enter" && !e.shiftKey && handleSend()} - placeholder={ - editSkillId - ? "Describe what you want to change..." - : "Describe the skill you want to create..." - } - disabled={isStreaming} - /> - -
-
-
- ); -} -``` - -- [ ] **Step 2: Commit** - -```bash -git add frontend/app/skills/creator/components/SkillCreatorChat.tsx -git commit -m "feat(frontend): add SkillCreatorChat component" -``` - ---- - -## Task 8: Frontend — SkillPreviewPanel + File Viewer - -**Files:** -- Create: `frontend/app/skills/creator/components/SkillPreviewPanel.tsx` -- Create: `frontend/app/skills/creator/components/SkillFileTree.tsx` -- Create: `frontend/app/skills/creator/components/SkillFileViewer.tsx` -- Create: `frontend/app/skills/creator/components/SkillSaveDialog.tsx` - -- [ ] **Step 1: Create SkillFileTree** - -```tsx -// frontend/app/skills/creator/components/SkillFileTree.tsx -"use client"; - -interface FileEntry { - path: string; - file_type: string; - size: number; -} - -interface SkillFileTreeProps { - files: FileEntry[]; - selectedPath: string | null; - onSelectFile: (path: string) => void; -} - -const FILE_ICONS: Record = { - markdown: "📄", - python: "🐍", - json: "{ }", - yaml: "⚙️", - shell: "🖥️", - text: "📝", -}; - -export function SkillFileTree({ - files, - selectedPath, - onSelectFile, -}: SkillFileTreeProps) { - return ( -
- {files.map((file) => ( - - ))} -
- ); -} -``` - -- [ ] **Step 2: Create SkillFileViewer** - -```tsx -// frontend/app/skills/creator/components/SkillFileViewer.tsx -"use client"; - -interface SkillFileViewerProps { - path: string; - content: string; - fileType: string; -} - -export function SkillFileViewer({ path, content, fileType }: SkillFileViewerProps) { - return ( -
-
- {path} -
-
-        {content}
-      
-
- ); -} -``` - -- [ ] **Step 3: Create SkillSaveDialog** - -```tsx -// frontend/app/skills/creator/components/SkillSaveDialog.tsx -"use client"; - -import { useState } from "react"; -import type { SkillPreviewData } from "../page"; - -interface SkillSaveDialogProps { - data: SkillPreviewData; - editSkillId: string | null; - onConfirm: () => void; - onCancel: () => void; - isSaving: boolean; -} - -export function SkillSaveDialog({ - data, - editSkillId, - onConfirm, - onCancel, - isSaving, -}: SkillSaveDialogProps) { - return ( -
-
-

- {editSkillId ? "Update Skill" : "Save Skill"} -

- -
-
- Name: - {data.skill_name} -
-
- Files: - {data.files.length} -
- {data.validation.warnings.length > 0 && ( -
- {data.validation.warnings.map((w, i) => ( -
⚠ {w}
- ))} -
- )} -
- -
- - -
-
-
- ); -} -``` - -- [ ] **Step 4: Create SkillPreviewPanel** - -```tsx -// frontend/app/skills/creator/components/SkillPreviewPanel.tsx -"use client"; - -import { useState, useCallback } from "react"; -import { SkillFileTree } from "./SkillFileTree"; -import { SkillFileViewer } from "./SkillFileViewer"; -import { SkillSaveDialog } from "./SkillSaveDialog"; -import type { SkillPreviewData } from "../page"; - -interface SkillPreviewPanelProps { - data: SkillPreviewData | null; - editSkillId: string | null; -} - -export function SkillPreviewPanel({ data, editSkillId }: SkillPreviewPanelProps) { - const [selectedPath, setSelectedPath] = useState(null); - const [showSaveDialog, setShowSaveDialog] = useState(false); - const [isSaving, setIsSaving] = useState(false); - - const selectedFile = data?.files.find((f) => f.path === selectedPath) ?? null; - - const handleSave = useCallback(async () => { - if (!data) return; - setIsSaving(true); - try { - const skillFiles = data.files.map((f) => ({ - path: f.path, - file_name: f.path.split("/").pop() ?? f.path, - file_type: f.file_type, - content: f.content, - size: f.size, - })); - - // Parse name/description from SKILL.md frontmatter - const skillMd = data.files.find((f) => f.path === "SKILL.md"); - const frontmatterMatch = skillMd?.content.match( - /^---\n([\s\S]*?)\n---/ - ); - let name = data.skill_name; - let description = ""; - let content = skillMd?.content ?? ""; - - if (frontmatterMatch) { - const lines = frontmatterMatch[1].split("\n"); - for (const line of lines) { - const [key, ...vals] = line.split(":"); - if (key.trim() === "name") name = vals.join(":").trim(); - if (key.trim() === "description") description = vals.join(":").trim(); - } - // content = body after frontmatter - content = (skillMd?.content ?? "").replace(/^---\n[\s\S]*?\n---\n?/, ""); - } - - const payload = { - name, - description, - content, - tags: [], - is_public: false, - files: skillFiles, - }; - - const baseUrl = process.env.NEXT_PUBLIC_BACKEND_URL ?? ""; - const url = editSkillId - ? `${baseUrl}/api/v1/skills/${editSkillId}` - : `${baseUrl}/api/v1/skills`; - - const resp = await fetch(url, { - method: editSkillId ? "PUT" : "POST", - headers: { "Content-Type": "application/json" }, - credentials: "include", - body: JSON.stringify(payload), - }); - - if (!resp.ok) { - const err = await resp.json().catch(() => ({})); - throw new Error(err.detail ?? `HTTP ${resp.status}`); - } - - setShowSaveDialog(false); - // TODO: show success toast / redirect to skills list - } catch (error) { - console.error("Failed to save skill:", error); - // TODO: show error toast - } finally { - setIsSaving(false); - } - }, [data, editSkillId]); - - if (!data) { - return ( -
- Skill preview will appear here once the Agent generates it. -
- ); - } - - return ( -
- {/* Header */} -
-
-

{data.skill_name}/

- {!data.validation.valid && ( - - {data.validation.errors.join("; ")} - - )} -
- -
- - {/* File tree */} -
- -
- - {/* File content viewer */} -
- {selectedFile ? ( - - ) : ( -
- Select a file to preview -
- )} -
- - {/* Save dialog */} - {showSaveDialog && ( - setShowSaveDialog(false)} - isSaving={isSaving} - /> - )} -
- ); -} -``` - -- [ ] **Step 5: Commit** - -```bash -git add frontend/app/skills/creator/components/ -git commit -m "feat(frontend): add Skill preview panel, file tree, viewer, save dialog" -``` - ---- - -## Task 9: Frontend — Dashboard Entry Card + Skills Page Button - -**Files:** -- Modify: `frontend/app/chat/components/ChatHome.tsx` (add Skill Creator card) -- Modify: `frontend/app/skills/page.tsx` (add "AI Create" button) - -- [ ] **Step 1: Read existing ChatHome.tsx** - -Read `frontend/app/chat/components/ChatHome.tsx` to understand the current layout and how mode cards are rendered (Rapid Mode, Deep Mode, etc.). - -- [ ] **Step 2: Add Skill Creator card to ChatHome** - -Add a new card alongside existing mode cards. Follow the existing card pattern. Example addition: - -```tsx - -
-

Skill Creator

-

AI-powered skill creation and modification

-
- -``` - -Exact classes and structure must match the existing cards — read the file first. - -- [ ] **Step 3: Add "AI Create" button to Skills page** - -Edit `frontend/app/skills/page.tsx`. Add a button/link near the tab switcher: - -```tsx -import Link from "next/link"; - -// In the header/action area of the skills page: - - - -``` - -- [ ] **Step 4: Verify no build errors** - -Run: `cd frontend && npx next build --no-lint 2>&1 | tail -20` -Expected: No errors related to the new pages - -- [ ] **Step 5: Commit** - -```bash -git add frontend/app/chat/components/ChatHome.tsx frontend/app/skills/page.tsx -git commit -m "feat(frontend): add Skill Creator entry on chat home and skills page" -``` - ---- - -## Task 10: Backend — Pass mode through Chat Stream to Metadata - -**Files:** -- Modify: `frontend/app/chat/hooks/useBackendChatStream.ts` -- Modify: `frontend/services/chatBackend.ts` (or wherever `streamChat` is defined) - -- [ ] **Step 1: Read the streaming service** - -Read `frontend/app/chat/hooks/useBackendChatStream.ts` and the `streamChat` function to understand how metadata is passed to the backend. - -- [ ] **Step 2: Ensure mode passes through** - -The `metadata` field in `ChatRequest` already supports arbitrary keys. The `SkillCreatorChat` component passes `mode: "skill_creator"` via metadata. Verify that the `streamChat` function forwards metadata to the `POST /v1/chat/stream` body. If `mode` needs to be a top-level field (not inside metadata), update the `streamChat` function to include it. - -If `mode` is a top-level ChatRequest field (as designed in Task 1), the frontend `streamChat` call needs to pass it at the top level: - -```typescript -// In streamChat or equivalent: -const body = { - message: userPrompt, - thread_id: opts.threadId, - graph_id: opts.graphId, - mode: opts.metadata?.mode ?? null, - edit_skill_id: opts.metadata?.edit_skill_id ?? null, - metadata: opts.metadata ?? {}, -}; -``` - -- [ ] **Step 3: Commit** - -```bash -git add frontend/app/chat/hooks/useBackendChatStream.ts frontend/services/chatBackend.ts -git commit -m "feat(frontend): pass mode and edit_skill_id through to chat API" -``` - ---- - -## Task 11: Integration Test — End-to-End Skill Creator Flow - -**Files:** -- Create: `backend/tests/test_api/test_skill_creator.py` - -- [ ] **Step 1: Write integration test** - -```python -# backend/tests/test_api/test_skill_creator.py -"""Integration test for skill_creator mode in chat stream.""" -import pytest -from httpx import AsyncClient - - -@pytest.mark.asyncio -async def test_chat_stream_skill_creator_mode_accepted( - client: AsyncClient, auth_headers: dict -): - """Verify that mode=skill_creator is accepted by the chat stream endpoint.""" - response = await client.post( - "/api/v1/chat/stream", - json={ - "message": "Create a simple hello-world skill", - "mode": "skill_creator", - }, - headers=auth_headers, - ) - # SSE endpoint returns 200 with streaming response - assert response.status_code == 200 - - -@pytest.mark.asyncio -async def test_chat_request_rejects_invalid_mode( - client: AsyncClient, auth_headers: dict -): - """Verify that an invalid mode value is rejected.""" - response = await client.post( - "/api/v1/chat/stream", - json={ - "message": "Hello", - "mode": "invalid_mode", - }, - headers=auth_headers, - ) - assert response.status_code == 422 # Pydantic validation error -``` - -- [ ] **Step 2: Run test** - -Run: `cd backend && python -m pytest tests/test_api/test_skill_creator.py -v` -Expected: PASS (requires test fixtures — adapt to existing test setup) - -- [ ] **Step 3: Commit** - -```bash -git add backend/tests/test_api/test_skill_creator.py -git commit -m "test: add integration tests for skill_creator chat mode" -``` - ---- - -## Dependency Order - -``` -Task 1 (Schema) - ↓ -Task 2 (preview_skill tool) → Task 3 (Register tool) - ↓ -Task 4 (GraphService method) - ↓ -Task 5 (Wire into chat.py) — depends on Tasks 1, 3, 4 - ↓ -Task 6 (Page layout) → Task 7 (Chat component) → Task 8 (Preview components) - ↓ -Task 9 (Entry points) - ↓ -Task 10 (Frontend streaming passthrough) — depends on Tasks 7, 5 - ↓ -Task 11 (Integration test) — depends on all above -``` - -Tasks 1-5 are backend (sequential). Tasks 6-9 are frontend (can parallelize with backend after Task 1). Task 10 bridges both. Task 11 is final verification. diff --git a/docs/superpowers/plans/2026-03-19-workspace-member-auth-fixes.md b/docs/superpowers/plans/2026-03-19-workspace-member-auth-fixes.md deleted file mode 100644 index 6960c0251..000000000 --- a/docs/superpowers/plans/2026-03-19-workspace-member-auth-fixes.md +++ /dev/null @@ -1,586 +0,0 @@ -# Workspace Member Authorization System Fixes - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Fix all critical bugs, security holes, and inconsistencies in the workspace member authorization system so that "1 workspace = 1 team" with creator-managed membership is fully self-consistent end-to-end. - -**Architecture:** Fixes are organized into 4 phases — (P1) Backend critical route/security fixes, (P2) Backend service-layer logic fixes, (P3) Frontend bug fixes, (P4) Resource access control gaps. Each phase is independently testable and committable. - -**Tech Stack:** Python/FastAPI/SQLAlchemy (backend), TypeScript/Next.js/React Query (frontend) - ---- - -## Phase 1: Backend Critical Route & Security Fixes - -### Task 1: Fix route ordering — invitation routes shadowed by `/{workspace_id}` - -All `GET /invitations*` routes are declared AFTER `GET /{workspace_id}`, so FastAPI matches "invitations" as a `workspace_id` UUID and returns 422. Move all invitation routes before the dynamic `/{workspace_id}` route. - -Note: `/members/{user_id}` routes (PATCH/DELETE) are NOT affected by this shadowing issue — they have a different prefix segment ("members") and don't collide with `/{workspace_id}`. Only invitation routes need to be moved. - -**Files:** -- Modify: `backend/app/api/v1/workspaces.py` - -- [ ] **Step 1: Move all `/invitations*` routes before `/{workspace_id}`** - -Move the following route blocks (currently at lines 166-263) to appear BEFORE `@router.get("/{workspace_id}")` (currently at line 89): - -```python -# --- Static invitation routes (MUST be before /{workspace_id}) --- - -@router.get("/invitations") -async def list_invitations(...): - ... - -@router.get("/invitations/pending") -async def list_pending_invitations(...): - ... - -@router.get("/invitations/all") -async def list_all_invitations(...): - ... - -@router.post("/invitations") -async def create_invitation(...): - ... - -@router.get("/invitations/{token}") -async def get_invitation_by_token(...): - ... - -@router.post("/invitations/{invitation_id}/accept") -async def accept_invitation(...): - ... - -@router.post("/invitations/{invitation_id}/reject") -async def reject_invitation(...): - ... - -@router.post("/invitations/token/{token}/accept") -async def accept_invitation_by_token(...): - ... - -# --- Dynamic workspace routes (AFTER all static paths) --- - -@router.get("/{workspace_id}") -async def get_workspace(...): - ... -``` - -The final order in the file should be: -1. `GET /` (list workspaces) -2. `POST /` (create workspace) -3. All `/invitations*` routes (GET, POST, accept, reject, token-accept) -4. `GET /{workspace_id}` and other `/{workspace_id}/*` routes -5. `/members/{user_id}` routes (can stay at end — not shadowed) - -- [ ] **Step 2: Verify by starting the server and testing** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.api.v1.workspaces import router; print([r.path for r in router.routes])"` -Expected: `/invitations` appears before `/{workspace_id}` in the route list. - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/api/v1/workspaces.py -git commit -m "fix: reorder workspace routes to prevent invitation paths being shadowed by /{workspace_id}" -``` - ---- - -### Task 2: Delete unused `require_roles()` — dead code with broken logic - -`require_roles(*roles)` accepts roles but never checks them — any authenticated user passes. Confirmed via grep: this function is NOT called anywhere in the backend. It is only defined in `dependencies.py`. Delete it. - -**Files:** -- Modify: `backend/app/common/dependencies.py:138-146` - -- [ ] **Step 1: Delete the `require_roles` function (lines 138-146)** - -Remove the entire function: - -```python -# DELETE THIS ENTIRE BLOCK: -def require_roles(*roles: str): - """角色权限检查装饰器""" - - async def check_roles(current_user: User = Depends(get_current_user)): - if current_user.is_superuser: - return current_user - return current_user - - return Depends(check_roles) -``` - -- [ ] **Step 2: Verify no import breakage** - -```bash -cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter && grep -rn "require_roles" backend/ -``` - -Expected: Only appears in the import line of the file being edited (if any), and the definition itself. After deletion, zero matches. - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/common/dependencies.py -git commit -m "fix: remove unused require_roles function that silently bypassed role checks" -``` - ---- - -### Task 3: Protect owner from being removed via `remove_member` - -An admin can currently remove the workspace owner from `workspace_members`. Add a guard identical to what exists in `update_member_role`. - -**Files:** -- Modify: `backend/app/services/workspace_service.py:921-960` - -- [ ] **Step 1: Add owner removal guard** - -Add after the `NotFoundException` guard (after `if not target_member: raise NotFoundException(...)` at line 941), before `current_role` is fetched: - -```python -# 不能移除工作空间拥有者 -if str(workspace.owner_id) == str(target_user_id): - raise BadRequestException("Cannot remove workspace owner") -``` - -- [ ] **Step 2: Commit** - -```bash -git add backend/app/services/workspace_service.py -git commit -m "fix: prevent workspace owner from being removed via remove_member" -``` - ---- - -## Phase 2: Backend Service Logic Fixes - -### Task 4: Fix repository `update_status` double-commit breaking transaction atomicity - -`WorkspaceInvitationRepository.update_status()` calls `self.db.commit()` directly, but its callers (`accept_invitation`, `reject_invitation`) also call `self.commit()`. This breaks atomicity — the invitation status update and member creation happen in separate transactions. - -**Files:** -- Modify: `backend/app/repositories/workspace.py:136-144` - -- [ ] **Step 1: Replace `commit()` with `flush()` in `update_status`** - -```python -async def update_status(self, invitation_id: uuid.UUID, status: WorkspaceInvitationStatus) -> WorkspaceInvitation: - """更新邀请状态""" - invitation = await self.get(invitation_id) - if not invitation: - raise NotFoundException("Invitation not found") - invitation.status = status - await self.db.flush() # flush, not commit — let the service layer control the transaction - await self.db.refresh(invitation) - return invitation -``` - -- [ ] **Step 2: Commit** - -```bash -git add backend/app/repositories/workspace.py -git commit -m "fix: use flush instead of commit in invitation update_status to preserve transaction atomicity" -``` - ---- - -### Task 5: Fix `accept_invitation` — mutates state then raises error for existing members - -**Dependency: Task 4 must be completed first** (Task 4 changes `update_status` from `commit()` to `flush()`, which this task relies on for correct transaction behavior). - -When a user is already a member, the code marks the invitation as `accepted` and THEN raises a 400 error. The invitation is permanently consumed for no reason. Fix: return success instead (idempotent behavior). Note: `accept_invitation_by_token` (line 673-678) calls this method internally, so it also gets the fix. - -**Files:** -- Modify: `backend/app/services/workspace_service.py:620-626` - -- [ ] **Step 1: Return success instead of raising error when already a member** - -Replace lines 620-626: - -```python -# 检查用户是否已经是成员 -existing_member = await self.member_repo.get_member(invitation.workspace_id, current_user.id) -if existing_member: - # 用户已是成员 — 标记邀请为已接受并返回成功(幂等操作) - await self.invitation_repo.update_status(invitation.id, WorkspaceInvitationStatus.accepted) - await self.commit() - workspace = await self.workspace_repo.get(invitation.workspace_id) - return { - "success": True, - "workspace": await self._serialize_workspace(workspace, current_user), - "message": "You are already a member of this workspace", - } -``` - -- [ ] **Step 2: Commit** - -```bash -git add backend/app/services/workspace_service.py -git commit -m "fix: accept_invitation returns success for existing members instead of error" -``` - ---- - -### Task 6: Add duplicate invitation check in `create_invitation` - -`find_pending()` repository method exists but is never called. An admin can spam unlimited invitations to the same email. - -**Files:** -- Modify: `backend/app/services/workspace_service.py:269-310` - -- [ ] **Step 1: Add duplicate check after existing-member check (around line 295)** - -Insert after the existing-member check block: - -```python -# 检查是否已有未过期的待处理邀请 -existing_pending = await self.invitation_repo.find_pending(workspace_id, email.lower()) -if existing_pending: - if existing_pending.expires_at and existing_pending.expires_at > datetime.now(timezone.utc): - raise BadRequestException( - f"A pending invitation already exists for {email}. 该用户已有待处理的邀请" - ) -``` - -- [ ] **Step 2: Normalize email to lowercase before storing** - -Change line 302 from `"email": email,` to `"email": email.lower(),`. - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/services/workspace_service.py -git commit -m "fix: prevent duplicate invitations and normalize email to lowercase" -``` - ---- - -### Task 7: Remove dead code — `datetime.utcnow()` call and deprecated method - -**Files:** -- Modify: `backend/app/services/workspace_service.py` - -- [ ] **Step 1: Verify no callers of deprecated method exist** - -```bash -cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter && grep -rn "list_all_invitations_for_user[^_]" backend/ -``` - -Expected: Only the method definition itself appears. If any route or service calls it, do NOT delete — update the caller to use the paginated version first. - -- [ ] **Step 2: Remove orphaned `datetime.utcnow()` call at line 134** - -Delete the line `datetime.utcnow()` in `create_workspace`. - -- [ ] **Step 3: Remove deprecated `list_all_invitations_for_user` method (lines 439-478)** - -Delete the entire method that is marked `已废弃,使用分页版本`. - -- [ ] **Step 4: Commit** - -```bash -git add backend/app/services/workspace_service.py -git commit -m "chore: remove dead code (orphaned datetime call, deprecated invitation list method)" -``` - ---- - -### Task 8: Delete unused `_ensure_workspace_role` in environment.py - -The local helper in `environment.py` (lines 34-46) doesn't handle superusers or owners not in the members table. However, **the function is never called** — the actual workspace routes in this file already use `require_workspace_role` from `dependencies.py` as a FastAPI dependency. Simply delete the dead code. - -**Files:** -- Modify: `backend/app/api/v1/environment.py:34-46` - -- [ ] **Step 1: Delete the `_ensure_workspace_role` function and its unused import** - -Delete lines 34-46 (the entire function). Also remove the unused import of `WorkspaceMemberRepository` at line 24 if it's no longer used elsewhere in the file. - -- [ ] **Step 2: Verify no callers remain** - -```bash -grep -n "_ensure_workspace_role" backend/app/api/v1/environment.py -``` - -Expected: Zero matches after deletion. - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/api/v1/environment.py -git commit -m "fix: environment workspace role check now handles superuser and owner-not-in-members" -``` - ---- - -## Phase 3: Frontend Bug Fixes - -### Task 9: Fix invitation accept page — wrong `/auth/signin` redirect - -The actual signin route is `/signin` (Next.js route group `(auth)/signin`), not `/auth/signin`. - -**Files:** -- Modify: `frontend/app/workspace/invitations/accept/page.tsx:94,119` - -- [ ] **Step 1: Replace `/auth/signin` with `/signin`** - -Line 94: -```typescript -router.push(`/signin?callbackUrl=${encodeURIComponent(`/workspace/invitations/accept?token=${token}`)}`) -``` - -Line 119: -```typescript -router.push(`/signin?callbackUrl=${encodeURIComponent(`/workspace/invitations/accept?token=${token}`)}`) -``` - -- [ ] **Step 2: Commit** - -```bash -git add frontend/app/workspace/invitations/accept/page.tsx -git commit -m "fix: correct signin redirect path in invitation accept page (/signin not /auth/signin)" -``` - ---- - -### Task 10: Fix `acceptInvitation` in workspaceService — token vs ID inconsistency - -The accept page uses `token` but calls `acceptInvitation(token)` which hits `/invitations/{token}/accept`. The backend has TWO accept endpoints: `/invitations/{invitation_id}/accept` (by ID) and `/invitations/token/{token}/accept` (by token). The frontend service should use the token-specific endpoint when passing a token. - -**Files:** -- Modify: `frontend/services/workspaceService.ts:215-219` - -- [ ] **Step 1: Add separate methods for accept-by-ID and accept-by-token** - -```typescript -/** - * Accept invitation by ID (for notification banner) - */ -async acceptInvitationById(invitationId: string): Promise { - return apiPost( - `${API_ENDPOINTS.workspaces}/invitations/${invitationId}/accept` - ) -}, - -/** - * Accept invitation by token (for email link) - */ -async acceptInvitationByToken(token: string): Promise { - return apiPost( - `${API_ENDPOINTS.workspaces}/invitations/token/${token}/accept` - ) -}, -``` - -Keep the old `acceptInvitation` as an alias for `acceptInvitationById` for backward compat: - -```typescript -async acceptInvitation(invitationId: string): Promise { - return this.acceptInvitationById(invitationId) -}, -``` - -- [ ] **Step 2: Update the accept page to use `acceptInvitationByToken`** - -In `frontend/app/workspace/invitations/accept/page.tsx`, change the mutation: - -```typescript -mutationFn: async () => { - if (!token) throw new Error('Token is required') - return workspaceService.acceptInvitationByToken(token) -}, -``` - -- [ ] **Step 3: Verify notification banner uses `acceptInvitationById` with `invitation.id`** - -Search for `acceptInvitation` calls in notification components and ensure they pass `invitation.id` and call `acceptInvitationById` (or the existing `acceptInvitation` alias). - -- [ ] **Step 4: Commit** - -```bash -git add frontend/services/workspaceService.ts frontend/app/workspace/invitations/accept/page.tsx -git commit -m "fix: distinguish acceptInvitationById vs acceptInvitationByToken to fix token/ID mismatch" -``` - ---- - -### Task 11: Fix workspace switcher menu — hide admin-only items from non-admin users - -The workspace context menu in the header shows "Members Management" and "API Keys" to all roles, including viewers. - -**Files:** -- Modify: `frontend/components/sidebar/components/workspace-header/workspace-header.tsx` - -**Context:** This component does NOT currently import `useWorkspacePermissions` or `useUserPermissions`. However, each workspace object in the `workspaces` list already carries a `role` field (serialized by the backend's `_serialize_workspace`). Use this existing `role` field directly instead of adding new hook calls. - -- [ ] **Step 1: Find the context menu rendering (around lines 740-803)** - -Read the file to locate the exact menu items for "Members Management" and "API Keys", and confirm the workspace object structure includes `role`. - -- [ ] **Step 2: Gate admin-only menu items using the workspace's `role` field** - -Check the role of the active workspace and conditionally render: - -```tsx -{(activeWorkspace.role === 'owner' || activeWorkspace.role === 'admin') && ( - <> - Members Management - API Keys - -)} -``` - -- [ ] **Step 3: Commit** - -```bash -git add frontend/components/sidebar/components/workspace-header/workspace-header.tsx -git commit -m "fix: hide admin-only menu items (Members, API Keys) from non-admin users in workspace switcher" -``` - ---- - -## Phase 4: Resource Access Control Gaps - -### Task 12: Add workspace membership check to Traces API - -Currently any authenticated user can query any workspace's traces by passing an arbitrary `workspace_id`. Add workspace membership validation. - -**Files:** -- Modify: `backend/app/api/v1/traces.py:162-198` - -- [ ] **Step 1: Add workspace membership check when `workspace_id` is provided** - -In `list_traces`, after the service is created and before querying: - -```python -# 如果指定了 workspace_id,校验当前用户是否有权限访问该工作空间 -if workspace_id: - from app.services.workspace_permission import check_workspace_access - from app.models.workspace import WorkspaceMemberRole - has_access = await check_workspace_access(db, workspace_id, current_user, WorkspaceMemberRole.viewer) - if not has_access: - raise ForbiddenException("No access to workspace traces") -``` - -Add the import at the top: -```python -from app.common.exceptions import ForbiddenException -``` - -- [ ] **Step 2: Same check in `get_trace_detail` — validate workspace ownership of the trace** - -After fetching the trace, if `trace.workspace_id` is set, check membership: - -```python -if trace.workspace_id: - from app.services.workspace_permission import check_workspace_access - from app.models.workspace import WorkspaceMemberRole - has_access = await check_workspace_access(db, trace.workspace_id, current_user, WorkspaceMemberRole.viewer) - if not has_access: - raise ForbiddenException("No access to workspace traces") -``` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/api/v1/traces.py -git commit -m "fix: add workspace membership check to traces API endpoints" -``` - ---- - -### Task 13: Add workspace access check to Copilot endpoints - -The copilot history/messages endpoints under `/graphs/{graph_id}/copilot/*` never check graph or workspace access. - -**Files:** -- Modify: `backend/app/api/v1/graphs.py` (copilot endpoints) - -- [ ] **Step 1: Identify the copilot endpoints in graphs.py** - -Search for `copilot` in the file to find exact line numbers. - -- [ ] **Step 2: Add workspace access check to each copilot endpoint** - -The copilot endpoints use `CopilotService`, not the graph service. To look up the graph's workspace, you need to query the graph separately. The existing `_ensure_workspace_member` helper in `graphs.py` calls `check_workspace_access` and raises `ForbiddenException` — reuse it. - -For each copilot endpoint (`GET /{graph_id}/copilot/history`, `DELETE /{graph_id}/copilot/history`, `POST /{graph_id}/copilot/messages`): - -1. Import and instantiate the graph repository to look up the graph -2. Use the existing `_ensure_workspace_member` helper - -```python -from app.repositories.graph import GraphRepository - -# At the start of the copilot endpoint: -graph_repo = GraphRepository(db) -graph = await graph_repo.get(graph_id) -if graph and graph.workspace_id: - await _ensure_workspace_member(db, graph.workspace_id, current_user, WorkspaceMemberRole.viewer) -``` - -For write operations (POST messages, DELETE history), use `WorkspaceMemberRole.member` instead of `viewer`. - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/api/v1/graphs.py -git commit -m "fix: add workspace access check to copilot history and messages endpoints" -``` - ---- - -### Task 14: Add workspace membership check to graph schema import - -`POST /schema/import` passes `workspace_id` from the request body to create a graph without checking membership. - -**Files:** -- Modify: `backend/app/api/v1/graph_schemas.py` - -- [ ] **Step 1: Read the file to find the import endpoint** - -```bash -grep -n "import" backend/app/api/v1/graph_schemas.py -``` - -- [ ] **Step 2: Add workspace membership check before creating the graph** - -```python -if workspace_id: - from app.services.workspace_permission import check_workspace_access - from app.models.workspace import WorkspaceMemberRole - has_access = await check_workspace_access(db, workspace_id, current_user, WorkspaceMemberRole.member) - if not has_access: - raise ForbiddenException("No access to import into this workspace") -``` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/api/v1/graph_schemas.py -git commit -m "fix: add workspace membership check to graph schema import endpoint" -``` - ---- - -## Summary of All Changes - -| # | File | Change | Severity | Deps | -|---|------|--------|----------|------| -| 1 | `workspaces.py` | Reorder invitation routes before `/{workspace_id}` | CRITICAL | — | -| 2 | `dependencies.py` | Delete unused `require_roles` (broken no-op) | CRITICAL | — | -| 3 | `workspace_service.py` | Prevent owner removal in `remove_member` | CRITICAL | — | -| 4 | `repositories/workspace.py` | `flush()` instead of `commit()` in `update_status` | HIGH | — | -| 5 | `workspace_service.py` | Accept-invitation idempotent for existing members | HIGH | Task 4 | -| 6 | `workspace_service.py` | Duplicate invitation check + email normalization | HIGH | — | -| 7 | `workspace_service.py` | Remove dead code (datetime call + deprecated method) | LOW | — | -| 8 | `environment.py` | Delete unused `_ensure_workspace_role` helper | MEDIUM | — | -| 9 | `accept/page.tsx` | Fix `/auth/signin` → `/signin` | CRITICAL | — | -| 10 | `workspaceService.ts` + `accept/page.tsx` | Token vs ID accept distinction | HIGH | Task 1 | -| 11 | `workspace-header.tsx` | Hide admin-only menu items via `workspace.role` | HIGH | — | -| 12 | `traces.py` | Add workspace membership check | CRITICAL | — | -| 13 | `graphs.py` (copilot) | Add workspace access check via graph lookup | HIGH | — | -| 14 | `graph_schemas.py` | Add workspace membership check to import | HIGH | — | diff --git a/docs/superpowers/plans/2026-03-20-chat-interaction-refactor.md b/docs/superpowers/plans/2026-03-20-chat-interaction-refactor.md deleted file mode 100644 index 54fa5cd50..000000000 --- a/docs/superpowers/plans/2026-03-20-chat-interaction-refactor.md +++ /dev/null @@ -1,1335 +0,0 @@ -# Chat Interaction Refactor Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Refactor Chat to borrow Skill Creator's proven UX patterns (human-readable tool calls, persistent preview panel, per-message actions, starter prompts) while preserving free-form conversation. - -**Architecture:** Two-phase approach. Phase 1 extracts ChatInterface's 14 useState into a useReducer + Context, splits the 683-line component into focused modules (ChatLayout, ConversationPanel, PreviewPanel, ChatProvider). Phase 2 introduces shared components (ToolCallDisplay, ActionBar, StarterPrompts) and converts the overlay-based side panels into a ResizablePanel column. - -**Tech Stack:** React 18, Next.js App Router, TypeScript, Tailwind CSS, shadcn/ui ResizablePanel, TanStack Query - -**Spec:** `docs/superpowers/specs/2026-03-20-chat-interaction-refactor-design.md` - ---- - -## File Structure - -All paths relative to `frontend/app/`. - -**Phase 1 — New files:** -| File | Responsibility | -|------|---------------| -| `chat/hooks/useChatReducer.ts` | ChatState/ChatAction types, reducer function, initial state | -| `chat/ChatProvider.tsx` | ChatStateContext + ChatStreamContext providers | -| `chat/ChatLayout.tsx` | Three-column ResizablePanelGroup skeleton | -| `chat/conversation/ConversationPanel.tsx` | Message list + streaming + input container | -| `chat/conversation/MessageList.tsx` | Message rendering (from ThreadContent) | -| `chat/conversation/MessageBubble.tsx` | Single message (from MessageItem) | -| `chat/conversation/ChatInput.tsx` | Input (moved from components/) | -| `chat/conversation/index.ts` | Barrel export | -| `chat/preview/PreviewPanel.tsx` | Tab-based preview container | -| `chat/preview/FileTreePreview.tsx` | File tree + code viewer (from ArtifactPanel) | -| `chat/preview/index.ts` | Barrel export | -| `chat/hooks/usePreviewTrigger.ts` | Auto-expand/collapse logic | -| `chat/types.ts` | Extended with FileTreeEntry, NodeLogEntry, MessageMetadata | - -**Phase 1 — Modified files:** -| File | Change | -|------|--------| -| `chat/ChatInterface.tsx` | Rename to ChatPage.tsx, reduce to <50 lines | -| `chat/page.tsx` | Update import from ChatInterface to ChatPage | -| `chat/hooks/useBackendChatStream.ts` | Accept dispatch instead of setMessages | - -**Phase 1 — Deleted files (Phase 2 Step 2):** -| File | Replaced by | -|------|------------| -| `chat/components/ArtifactsDrawer.tsx` | preview/PreviewPanel | -| `chat/components/CompactArtifactStatus.tsx` | PreviewPanel auto-expand | -| `chat/components/ToolExecutionPanel.tsx` | preview/PreviewPanel tool tab | -| `chat/components/CompactToolStatus.tsx` | shared/ToolCallDisplay | - -**Phase 2 — New files:** -| File | Responsibility | -|------|---------------| -| `shared/ToolCallDisplay/toolDisplayRegistry.ts` | Tool name → label registry | -| `shared/ToolCallDisplay/ToolCallBadge.tsx` | Compact inline tool display | -| `shared/ToolCallDisplay/ToolCallDetail.tsx` | Expanded tool detail view | -| `shared/ToolCallDisplay/index.ts` | Barrel export | -| `shared/ActionBar/ActionBar.tsx` | Per-message action container | -| `shared/ActionBar/actions/CopyAction.tsx` | Copy message content | -| `shared/ActionBar/actions/RetryAction.tsx` | Retry message | -| `shared/ActionBar/index.ts` | Barrel export | -| `shared/StarterPrompts/StarterPrompts.tsx` | Guided start chips | -| `shared/StarterPrompts/index.ts` | Barrel export | - ---- - -## Phase 1: Architecture Cleanup - -### Task 1: Extend types.ts with typed metadata - -**Files:** -- Modify: `chat/types.ts` (71 lines) - -- [ ] **Step 1: Add FileTreeEntry, NodeLogEntry, MessageMetadata types** - -Add above the existing `Message` interface at line 25: - -```typescript -export interface FileTreeEntry { - action: string - size?: number - timestamp?: number -} - -export interface NodeLogEntry { - type: 'command' | 'route_decision' | 'loop_iteration' | 'parallel_task' | 'state_update' | 'node_transition' - nodeName: string - timestamp: number - data?: Record -} - -export interface MessageMetadata { - fileTree?: Record - nodeExecutionLog?: NodeLogEntry[] - currentNode?: string - lastNode?: string - lastRunId?: string - lastUpdate?: number - lastRouteDecision?: any - lastLoopIteration?: any - [key: string]: any // keep backwards compat -} -``` - -Update the `Message` interface to use `MessageMetadata`: - -```typescript -export interface Message { - // ... existing fields unchanged - metadata?: MessageMetadata -} -``` - -- [ ] **Step 2: Verify TypeScript compiles** - -Run: `cd frontend && npx tsc --noEmit --pretty 2>&1 | head -30` -Expected: No new errors (existing errors may remain) - -- [ ] **Step 3: Commit** - -```bash -git add frontend/app/chat/types.ts -git commit -m "refactor(chat): add typed FileTreeEntry, NodeLogEntry, MessageMetadata to types.ts" -``` - ---- - -### Task 2: Create useChatReducer and ChatProvider - -**Files:** -- Create: `chat/hooks/useChatReducer.ts` -- Create: `chat/ChatProvider.tsx` - -- [ ] **Step 1: Create useChatReducer.ts** - -```typescript -'use client' - -import { useReducer } from 'react' -import type { Message, ToolCall, FileTreeEntry, NodeLogEntry } from '../types' - -// ─── State ─────────────────────────────────────────────────────────────────── -export interface ChatState { - messages: Message[] - threadId: string | null - input: string - streaming: { - isProcessing: boolean - isSubmitting: boolean - text: string - nodeExecutionLog: NodeLogEntry[] - } - preview: { - visible: boolean - fileTree: Record - activeFile: string | null - userDismissed: boolean - } - ui: { - sidebarVisible: boolean - selectedTool: ToolCall | null - showNoDefaultModelNotice: boolean - } - mode: { - currentMode: string | undefined - currentGraphId: string | null - hasShownApkPrompt: boolean - } -} - -export const initialChatState: ChatState = { - messages: [], - threadId: null, - input: '', - streaming: { - isProcessing: false, - isSubmitting: false, - text: '', - nodeExecutionLog: [], - }, - preview: { - visible: false, - fileTree: {}, - activeFile: null, - userDismissed: false, - }, - ui: { - sidebarVisible: false, - selectedTool: null, - showNoDefaultModelNotice: false, - }, - mode: { - currentMode: undefined, - currentGraphId: null, - hasShownApkPrompt: false, - }, -} - -// ─── Actions ───────────────────────────────────────────────────────────────── -export type ChatAction = - // Thread - | { type: 'SET_THREAD'; threadId: string } - | { type: 'RESET' } - // Messages - | { type: 'APPEND_MESSAGE'; message: Message } - | { type: 'UPDATE_MESSAGE'; id: string; patch: Partial } - | { type: 'SET_MESSAGES'; messages: Message[] } - // Input - | { type: 'SET_INPUT'; value: string } - // Streaming lifecycle - | { type: 'STREAM_START' } - | { type: 'STREAM_CONTENT'; delta: string } - | { type: 'STREAM_DONE' } - | { type: 'STREAM_ERROR'; error: string } - // File & tool events - | { type: 'FILE_EVENT'; path: string; info: FileTreeEntry } - | { type: 'TOOL_START'; tool: ToolCall } - | { type: 'TOOL_END'; id: string; result: string } - // Node execution (agent mode) - | { type: 'NODE_START'; nodeId: string; label: string } - | { type: 'NODE_END'; nodeId: string } - | { type: 'NODE_LOG'; entry: NodeLogEntry } - // UI - | { type: 'TOGGLE_SIDEBAR' } - | { type: 'SHOW_PREVIEW'; tab?: string } - | { type: 'HIDE_PREVIEW' } - | { type: 'SELECT_TOOL'; tool: ToolCall | null } - | { type: 'DISMISS_MODEL_NOTICE' } - | { type: 'SHOW_MODEL_NOTICE' } - // Mode - | { type: 'SET_MODE'; mode: string; graphId: string | null } - | { type: 'SET_APK_PROMPT_SHOWN' } - -// ─── Reducer ───────────────────────────────────────────────────────────────── -export function chatReducer(state: ChatState, action: ChatAction): ChatState { - switch (action.type) { - case 'SET_THREAD': - return { ...state, threadId: action.threadId } - - case 'RESET': - return { - ...initialChatState, - ui: { ...initialChatState.ui, sidebarVisible: state.ui.sidebarVisible }, - } - - case 'APPEND_MESSAGE': - return { ...state, messages: [...state.messages, action.message] } - - case 'UPDATE_MESSAGE': - return { - ...state, - messages: state.messages.map((m) => - m.id === action.id ? { ...m, ...action.patch } : m - ), - } - - case 'SET_MESSAGES': - return { ...state, messages: action.messages } - - case 'SET_INPUT': - return { ...state, input: action.value } - - case 'STREAM_START': - return { - ...state, - streaming: { - ...state.streaming, - isProcessing: true, - isSubmitting: false, - text: '', - nodeExecutionLog: [], - }, - preview: { ...state.preview, userDismissed: false }, - } - - case 'STREAM_CONTENT': { - const lastMsg = state.messages[state.messages.length - 1] - if (!lastMsg || lastMsg.role !== 'assistant') return state - return { - ...state, - streaming: { ...state.streaming, text: (lastMsg.content ?? '') + action.delta }, - } - } - - case 'STREAM_DONE': - return { - ...state, - streaming: { ...state.streaming, isProcessing: false, isSubmitting: false, text: '' }, - } - - case 'STREAM_ERROR': - return { - ...state, - streaming: { ...state.streaming, isProcessing: false, isSubmitting: false }, - } - - case 'FILE_EVENT': - return { - ...state, - preview: { - ...state.preview, - fileTree: { ...state.preview.fileTree, [action.path]: action.info }, - }, - } - - case 'TOOL_START': - return { - ...state, - messages: state.messages.map((m, i) => - i === state.messages.length - 1 - ? { ...m, tool_calls: [...(m.tool_calls ?? []), action.tool] } - : m - ), - } - - case 'TOOL_END': - return { - ...state, - messages: state.messages.map((m, i) => - i === state.messages.length - 1 - ? { - ...m, - tool_calls: m.tool_calls?.map((tc) => - tc.id === action.id ? { ...tc, status: 'completed' as const, result: action.result, endTime: Date.now() } : tc - ), - } - : m - ), - } - - case 'NODE_START': - return { - ...state, - messages: state.messages.map((m, i) => - i === state.messages.length - 1 - ? { ...m, metadata: { ...m.metadata, currentNode: action.label } } - : m - ), - } - - case 'NODE_END': - return state // currentNode cleared on next NODE_START or STREAM_DONE - - case 'NODE_LOG': - return { - ...state, - streaming: { - ...state.streaming, - nodeExecutionLog: [...state.streaming.nodeExecutionLog, action.entry], - }, - } - - case 'TOGGLE_SIDEBAR': - return { ...state, ui: { ...state.ui, sidebarVisible: !state.ui.sidebarVisible } } - - case 'SHOW_PREVIEW': - return { ...state, preview: { ...state.preview, visible: true } } - - case 'HIDE_PREVIEW': - return { ...state, preview: { ...state.preview, visible: false, userDismissed: true } } - - case 'SELECT_TOOL': - return { ...state, ui: { ...state.ui, selectedTool: action.tool } } - - case 'DISMISS_MODEL_NOTICE': - return { ...state, ui: { ...state.ui, showNoDefaultModelNotice: false } } - - case 'SHOW_MODEL_NOTICE': - return { ...state, ui: { ...state.ui, showNoDefaultModelNotice: true } } - - case 'SET_MODE': - return { - ...state, - mode: { ...state.mode, currentMode: action.mode, currentGraphId: action.graphId }, - } - - case 'SET_APK_PROMPT_SHOWN': - return { ...state, mode: { ...state.mode, hasShownApkPrompt: true } } - - default: - return state - } -} - -export function useChatReducer(initialState?: Partial) { - return useReducer(chatReducer, { ...initialChatState, ...initialState }) -} -``` - -- [ ] **Step 2: Create ChatProvider.tsx** - -```typescript -'use client' - -import React, { createContext, useContext, useMemo } from 'react' -import type { ChatState, ChatAction } from './hooks/useChatReducer' -import { useChatReducer, initialChatState } from './hooks/useChatReducer' - -// Low-frequency context: messages, UI, mode -interface ChatStateContextValue { - state: ChatState - dispatch: React.Dispatch -} - -// High-frequency context: streaming text, isProcessing -interface ChatStreamContextValue { - text: string - isProcessing: boolean - isSubmitting: boolean -} - -const ChatStateContext = createContext(null) -const ChatStreamContext = createContext(null) - -export function ChatProvider({ children }: { children: React.ReactNode }) { - const [state, dispatch] = useChatReducer() - - const stateValue = useMemo( - () => ({ state, dispatch }), - // Exclude streaming fields from dependency to avoid re-rendering state consumers on every delta - // eslint-disable-next-line react-hooks/exhaustive-deps - [state.messages, state.threadId, state.input, state.preview, state.ui, state.mode, dispatch] - ) - - const streamValue = useMemo( - () => ({ - text: state.streaming.text, - isProcessing: state.streaming.isProcessing, - isSubmitting: state.streaming.isSubmitting, - }), - [state.streaming.text, state.streaming.isProcessing, state.streaming.isSubmitting] - ) - - return ( - - - {children} - - - ) -} - -export function useChatState() { - const ctx = useContext(ChatStateContext) - if (!ctx) throw new Error('useChatState must be used within ChatProvider') - return ctx -} - -export function useChatStream() { - const ctx = useContext(ChatStreamContext) - if (!ctx) throw new Error('useChatStream must be used within ChatProvider') - return ctx -} - -export { ChatStateContext, ChatStreamContext } -``` - -- [ ] **Step 3: Verify TypeScript compiles** - -Run: `cd frontend && npx tsc --noEmit --pretty 2>&1 | head -30` -Expected: No new errors - -- [ ] **Step 4: Commit** - -```bash -git add frontend/app/chat/hooks/useChatReducer.ts frontend/app/chat/ChatProvider.tsx -git commit -m "refactor(chat): add useChatReducer and ChatProvider with dual-context split" -``` - ---- - -### Task 3: Adapt useBackendChatStream to dispatch - -**Files:** -- Modify: `chat/hooks/useBackendChatStream.ts` (549 lines) - -This is the most critical migration step. The hook must accept `dispatch` instead of `setMessages` and convert every SSE event handler from `safeSetMessages(prev => ...)` to `dispatch({ type: ... })`. - -- [ ] **Step 1: Change hook signature** - -Replace the function signature (line 26): - -```typescript -// Before: -export const useBackendChatStream = ( - setMessages: React.Dispatch>, -) - -// After: -export const useBackendChatStream = ( - dispatch: React.Dispatch, -) -``` - -Add import at top: -```typescript -import type { ChatAction } from './useChatReducer' -``` - -- [ ] **Step 2: Replace all safeSetMessages calls with dispatch calls** - -Key transformations (referencing actual event handlers in the file): - -| SSE Event | Current pattern | New pattern | -|-----------|----------------|-------------| -| Before stream (blank assistant msg) | `setMessages(prev => [...prev, blankMsg])` | `dispatch({ type: 'APPEND_MESSAGE', message: blankMsg })` | -| `content` | `safeSetMessages(prev => prev.map(...update last msg content))` | `dispatch({ type: 'UPDATE_MESSAGE', id: lastMsgId, patch: { content: accumulated } })` | -| `tool_start` | `safeSetMessages(prev => prev.map(...push tool to last msg))` | `dispatch({ type: 'TOOL_START', tool: { id, name, args, status: 'running', startTime } })` | -| `tool_end` | `safeSetMessages(prev => prev.map(...update tool status))` | `dispatch({ type: 'TOOL_END', id, result })` | -| `file_event` | `safeSetMessages(prev => prev.map(...update metadata.fileTree))` | `dispatch({ type: 'FILE_EVENT', path, info: { action, size, timestamp } })` | -| `node_start` | `safeSetMessages(prev => prev.map(...set metadata.currentNode))` | `dispatch({ type: 'NODE_START', nodeId, label })` | -| `node_end` | `safeSetMessages(prev => prev.map(...clear currentNode))` | `dispatch({ type: 'NODE_END', nodeId })` | -| `command`/`route_decision`/etc. | `nodeExecutionLog.push(...); safeSetMessages(...)` | `dispatch({ type: 'NODE_LOG', entry: { type, nodeName, timestamp, data } })` | -| `error` | `safeSetMessages(prev => prev.map(...append error))` | `dispatch({ type: 'STREAM_ERROR', error: text })` | -| `done` | `safeSetMessages(prev => prev.map(...set isStreaming false))` | `dispatch({ type: 'STREAM_DONE' })` | -| `thread_id` | `threadIdRef.current = id` | Keep ref + `dispatch({ type: 'SET_THREAD', threadId: id })` | - -Remove the `nodeExecutionLog` closure variable — it is now in the reducer state. - -Remove `safeSetMessages` wrapper — dispatch is already safe to call after unmount (no-op on unmounted reducer). - -Keep `abortRef` and `isMountedRef` for abort logic. - -- [ ] **Step 3: Update sendMessage to dispatch STREAM_START** - -At the beginning of `sendMessage`, before creating the blank assistant message: -```typescript -dispatch({ type: 'STREAM_START' }) -``` - -- [ ] **Step 4: Keep the lastMsgId tracking** - -The hook needs to track the ID of the current assistant message being streamed. Use a ref: -```typescript -const currentMsgIdRef = useRef('') -// Set when creating blank assistant message -currentMsgIdRef.current = blankMsg.id -// Use in UPDATE_MESSAGE dispatches -dispatch({ type: 'UPDATE_MESSAGE', id: currentMsgIdRef.current, patch: { ... } }) -``` - -- [ ] **Step 5: Verify TypeScript compiles** - -Run: `cd frontend && npx tsc --noEmit --pretty 2>&1 | head -30` -Expected: Errors in ChatInterface.tsx (expected — it still passes setMessages). No errors in useBackendChatStream.ts itself. - -- [ ] **Step 6: Commit** - -```bash -git add frontend/app/chat/hooks/useBackendChatStream.ts -git commit -m "refactor(chat): adapt useBackendChatStream to dispatch-based state management" -``` - ---- - -### Task 4: Create ConversationPanel and move components - -**Files:** -- Create: `chat/conversation/ConversationPanel.tsx` -- Create: `chat/conversation/MessageList.tsx` (copy from `chat/components/ThreadContent.tsx`) -- Create: `chat/conversation/MessageBubble.tsx` (copy from `chat/components/MessageItem.tsx`) -- Move: `chat/components/ChatInput.tsx` → `chat/conversation/ChatInput.tsx` -- Create: `chat/conversation/index.ts` - -- [ ] **Step 1: Copy ThreadContent.tsx to MessageList.tsx** - -Copy `chat/components/ThreadContent.tsx` to `chat/conversation/MessageList.tsx`. Update: -- Rename component from `ThreadContent` to `MessageList` -- Update import of `MessageItem` to `MessageBubble` from `./MessageBubble` -- The props interface stays the same for now (will consume Context in Task 6) - -- [ ] **Step 2: Copy MessageItem.tsx to MessageBubble.tsx** - -Copy `chat/components/MessageItem.tsx` to `chat/conversation/MessageBubble.tsx`. Update: -- Rename component from `MessageItem` to `MessageBubble` -- Rename `MessageItemProps` to `MessageBubbleProps` -- Update import paths for types (now `../../types` instead of `../types`) - -- [ ] **Step 3: Move ChatInput.tsx** - -Copy `chat/components/ChatInput.tsx` to `chat/conversation/ChatInput.tsx`. Update import paths: -- `../hooks/useFileUpload` → `../../hooks/useFileUpload` (or from hooks directory) -- `../services/modeHandlers/types` → `../../services/modeHandlers/types` - -- [ ] **Step 4: Create ConversationPanel.tsx** - -This component replaces the middle section of ChatInterface (lines 561-616). It consumes ChatStateContext: - -```typescript -'use client' - -import React, { useRef, useEffect, useMemo } from 'react' -import { useChatState, useChatStream } from '../ChatProvider' -import MessageList from './MessageList' -import ChatInput from './ChatInput' -import type { ToolCall } from '../types' - -interface ConversationPanelProps { - onSubmit: (text: string, mode?: string, graphId?: string | null, files?: any[]) => void - onStop: () => void - onToolClick: (toolCall: ToolCall) => void -} - -export default function ConversationPanel({ onSubmit, onStop, onToolClick }: ConversationPanelProps) { - const { state, dispatch } = useChatState() - const stream = useChatStream() - const scrollRef = useRef(null) - - // Auto-scroll - useEffect(() => { - const id = requestAnimationFrame(() => { - requestAnimationFrame(() => { - if (scrollRef.current) { - scrollRef.current.scrollTop = scrollRef.current.scrollHeight - } - }) - }) - return () => cancelAnimationFrame(id) - }, [state.messages, stream.isProcessing]) - - const agentStatus = useMemo<'idle' | 'running' | 'connecting' | 'error'>( - () => (stream.isProcessing || stream.isSubmitting ? 'running' : 'idle'), - [stream.isProcessing, stream.isSubmitting], - ) - - const lastMsg = state.messages[state.messages.length - 1] - const streamingText = useMemo(() => { - if (!lastMsg || lastMsg.role !== 'assistant') return '' - if (!stream.isProcessing && !lastMsg.isStreaming) return '' - return lastMsg.content ?? '' - }, [lastMsg, stream.isProcessing]) - - const currentNodeLabel = useMemo( - () => lastMsg?.role === 'assistant' ? (lastMsg.metadata?.currentNode ?? undefined) : undefined, - [lastMsg], - ) - - return ( -
-
-
- -
-
-
- dispatch({ type: 'SET_INPUT', value: v })} - onSubmit={onSubmit} - isProcessing={stream.isProcessing} - onStop={onStop} - currentMode={state.mode.currentMode} - currentGraphId={state.mode.currentGraphId} - /> -
-
- ) -} -``` - -- [ ] **Step 5: Create barrel export** - -```typescript -// chat/conversation/index.ts -export { default as ConversationPanel } from './ConversationPanel' -export { default as MessageList } from './MessageList' -export { default as MessageBubble } from './MessageBubble' -export { default as ChatInput } from './ChatInput' -``` - -- [ ] **Step 6: Verify TypeScript compiles** - -Run: `cd frontend && npx tsc --noEmit --pretty 2>&1 | head -30` - -- [ ] **Step 7: Commit** - -```bash -git add frontend/app/chat/conversation/ -git commit -m "refactor(chat): create conversation/ module with ConversationPanel, MessageList, MessageBubble" -``` - ---- - -### Task 5: Create PreviewPanel and FileTreePreview - -**Files:** -- Create: `chat/preview/PreviewPanel.tsx` -- Create: `chat/preview/FileTreePreview.tsx` (from ArtifactPanel) -- Create: `chat/preview/index.ts` -- Create: `chat/hooks/usePreviewTrigger.ts` - -- [ ] **Step 1: Copy ArtifactPanel.tsx to FileTreePreview.tsx** - -Copy `chat/components/ArtifactPanel.tsx` (198 lines) to `chat/preview/FileTreePreview.tsx`. Update: -- Rename component from `ArtifactPanel` to `FileTreePreview` -- Update import paths - -- [ ] **Step 2: Create PreviewPanel.tsx** - -Tab-based container wrapping FileTreePreview and tool detail: - -```typescript -'use client' - -import React, { useState } from 'react' -import { X, FolderTree, Wrench } from 'lucide-react' -import { useChatState } from '../ChatProvider' -import FileTreePreview from './FileTreePreview' -import type { ToolCall } from '../types' - -export default function PreviewPanel() { - const { state, dispatch } = useChatState() - const { preview, ui, threadId } = state - const [activeTab, setActiveTab] = useState<'files' | 'tool'>('files') - - const hasFiles = Object.keys(preview.fileTree).length > 0 - const hasTool = !!ui.selectedTool - - return ( -
- {/* Header with tabs */} -
-
- {hasFiles && ( - - )} - {hasTool && ( - - )} -
- -
- - {/* Content */} -
- {activeTab === 'files' && threadId && ( - - )} - {activeTab === 'tool' && ui.selectedTool && ( -
- {/* Inline tool detail — simplified from ToolExecutionPanel for now */} -
{JSON.stringify(ui.selectedTool, null, 2)}
-
- )} -
-
- ) -} -``` - -- [ ] **Step 3: Create usePreviewTrigger.ts** - -```typescript -'use client' - -import { useEffect, useRef } from 'react' -import type { ChatState, ChatAction } from './useChatReducer' - -export function usePreviewTrigger( - state: ChatState, - dispatch: React.Dispatch, -) { - const prevFileCountRef = useRef(0) - - useEffect(() => { - const currentFileCount = Object.keys(state.preview.fileTree).length - const isNew = currentFileCount > prevFileCountRef.current - - // Auto-show when new files appear (unless user dismissed) - if (isNew && currentFileCount > 0 && !state.preview.visible && !state.preview.userDismissed) { - dispatch({ type: 'SHOW_PREVIEW', tab: 'files' }) - } - - prevFileCountRef.current = currentFileCount - }, [state.preview.fileTree, state.preview.visible, state.preview.userDismissed, dispatch]) - - // Auto-hide when stream ends with no files - useEffect(() => { - if ( - !state.streaming.isProcessing && - Object.keys(state.preview.fileTree).length === 0 && - state.preview.visible - ) { - dispatch({ type: 'HIDE_PREVIEW' }) - } - }, [state.streaming.isProcessing, state.preview.fileTree, state.preview.visible, dispatch]) -} -``` - -- [ ] **Step 4: Create barrel export** - -```typescript -// chat/preview/index.ts -export { default as PreviewPanel } from './PreviewPanel' -export { default as FileTreePreview } from './FileTreePreview' -``` - -- [ ] **Step 5: Verify TypeScript compiles** - -Run: `cd frontend && npx tsc --noEmit --pretty 2>&1 | head -30` - -- [ ] **Step 6: Commit** - -```bash -git add frontend/app/chat/preview/ frontend/app/chat/hooks/usePreviewTrigger.ts -git commit -m "refactor(chat): create preview/ module with PreviewPanel, FileTreePreview, usePreviewTrigger" -``` - ---- - -### Task 6: Create ChatLayout and wire everything together - -**Files:** -- Create: `chat/ChatLayout.tsx` -- Modify: `chat/ChatInterface.tsx` → rename to `chat/ChatPage.tsx` -- Modify: `chat/page.tsx` - -- [ ] **Step 1: Create ChatLayout.tsx** - -```typescript -'use client' - -import React, { useEffect, useCallback } from 'react' -import { useRouter } from 'next/navigation' -import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@/components/ui/resizable' -import { useDeployedGraphs, useWorkspaces } from '@/hooks/queries' -import { useAvailableModels } from '@/hooks/queries/models' -import { useTranslation } from '@/lib/i18n' -import { conversationService } from '@/services/conversationService' - -import ChatSidebar from './components/ChatSidebar' -import ChatHome from './components/ChatHome' -import { ConversationPanel } from './conversation' -import { PreviewPanel } from './preview' -import { useChatState, useChatStream } from './ChatProvider' -import { useBackendChatStream } from './hooks/useBackendChatStream' -import { usePreviewTrigger } from './hooks/usePreviewTrigger' -import { graphResolutionService } from './services/graphResolutionService' -import { generateId, Message } from './types' -import type { ToolCall } from './types' -// Import model notice dialog (extracted from old ChatInterface) -import { ModelNoticeDialog } from './components/ModelNoticeDialog' - -export default function ChatLayout({ chatId: propChatId }: { chatId?: string | null }) { - const { state, dispatch } = useChatState() - const stream = useChatStream() - const { t } = useTranslation() - const router = useRouter() - - // Data fetching - const { data: deployedAgents = [] } = useDeployedGraphs() - const { data: workspacesData } = useWorkspaces() - const personalWorkspaceId = workspacesData?.find((w) => w.type === 'personal')?.id ?? null - const { data: availableModels = [], isSuccess: modelsLoaded, isError: modelsError } = useAvailableModels('chat', { enabled: true }) - - // Hook integrations - const { sendMessage, stopMessage } = useBackendChatStream(dispatch) - usePreviewTrigger(state, dispatch) - - // Keyboard shortcut: Cmd+B toggle sidebar - useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - if ((e.metaKey || e.ctrlKey) && e.key === 'b') { - e.preventDefault() - dispatch({ type: 'TOGGLE_SIDEBAR' }) - } - } - window.addEventListener('keydown', handleKeyDown) - return () => window.removeEventListener('keydown', handleKeyDown) - }, [dispatch]) - - // Model notice check - // ... (migrate useEffect from ChatInterface lines 86-103) - - // Sync propChatId - // ... (migrate useEffect from ChatInterface lines 172-190) - - // handleSubmit, handleSelectConversation, handleNewChat, handleToolClick - // ... (migrate from ChatInterface lines 244-430, using dispatch instead of setState) - - const hasMessages = state.messages.length > 0 || !!state.threadId || !!propChatId - - return ( -
- - {/* Sidebar */} - {state.ui.sidebarVisible && ( - <> - - dispatch({ type: 'TOGGLE_SIDEBAR' })} - onSelectConversation={handleSelectConversation} - currentThreadId={state.threadId} - onNewChat={handleNewChat} - /> - - - - )} - - {/* Conversation */} - - {!hasMessages ? ( - stopMessage(state.threadId)} - /> - ) : ( - stopMessage(state.threadId)} - onToolClick={handleToolClick} - /> - )} - - - {/* Preview */} - {state.preview.visible && ( - <> - - - - - - )} - - - -
- ) -} -``` - -Note: The `handleSubmit`, `handleSelectConversation`, `handleNewChat`, `handleToolClick` callbacks are migrated directly from ChatInterface lines 244-430, replacing all `setXxx()` calls with `dispatch({ type: 'XXX', ... })`. - -- [ ] **Step 2: Rename ChatInterface.tsx to ChatPage.tsx** - -Replace entire content with: - -```typescript -'use client' - -import { ChatProvider } from './ChatProvider' -import ChatLayout from './ChatLayout' - -interface ChatPageProps { - chatId?: string | null -} - -export default function ChatPage({ chatId }: ChatPageProps) { - return ( - - - - ) -} -``` - -- [ ] **Step 3: Update page.tsx import** - -In `chat/page.tsx` (line 5), change: -```typescript -// Before: -import ChatInterface from './ChatInterface' -// After: -import ChatPage from './ChatPage' -``` - -And update the JSX (line 15): -```typescript -// Before: - -// After: - -``` - -- [ ] **Step 4: Extract ModelNoticeDialog** - -Create `chat/components/ModelNoticeDialog.tsx` containing the AlertDialog from ChatInterface lines 648-679. This component consumes ChatStateContext for `showNoDefaultModelNotice` and dispatches `DISMISS_MODEL_NOTICE`. - -- [ ] **Step 5: Verify app compiles and runs** - -Run: `cd frontend && npx tsc --noEmit --pretty 2>&1 | head -30` -Run: `cd frontend && npm run dev` — verify chat page loads, can send messages, sidebar works, conversation switching works. - -- [ ] **Step 6: Commit** - -```bash -git add frontend/app/chat/ChatLayout.tsx frontend/app/chat/ChatPage.tsx frontend/app/chat/page.tsx frontend/app/chat/components/ModelNoticeDialog.tsx -git rm frontend/app/chat/ChatInterface.tsx -git commit -m "refactor(chat): replace ChatInterface with ChatProvider + ChatLayout + ChatPage (<50 lines)" -``` - ---- - -## Phase 2: Interaction Enhancement - -### Task 7: Shared ToolCallDisplay components - -**Files:** -- Create: `shared/ToolCallDisplay/toolDisplayRegistry.ts` -- Create: `shared/ToolCallDisplay/ToolCallBadge.tsx` -- Create: `shared/ToolCallDisplay/ToolCallDetail.tsx` -- Create: `shared/ToolCallDisplay/index.ts` - -- [ ] **Step 1: Create toolDisplayRegistry.ts** - -Migrate and generalize from `skills/creator/components/toolDisplayUtils.ts` (140 lines). Include all tool name mappings from that file plus the icon logic from `MessageItem.tsx`'s `ToolCallItem`. - -```typescript -export interface ToolDisplayConfig { - label: string - icon?: string // lucide icon name - formatArgs?: (args: Record) => string - formatDetail?: (args: Record) => string - category: 'file' | 'code' | 'search' | 'network' | 'other' -} - -const registry = new Map() - -// Register all known tools (from toolDisplayUtils.ts) -function registerDefaults() { - register('read_file', { label: 'Reading', category: 'file', formatArgs: a => shortenPath(a.path || a.file_path) }) - register('read', { label: 'Reading', category: 'file', formatArgs: a => shortenPath(a.path || a.file_path) }) - register('write_file', { label: 'Writing', category: 'file', formatArgs: a => shortenPath(a.path || a.file_path) }) - register('write', { label: 'Writing', category: 'file', formatArgs: a => shortenPath(a.path || a.file_path) }) - register('create_file', { label: 'Creating', category: 'file', formatArgs: a => shortenPath(a.path || a.file_path) }) - register('edit_file', { label: 'Editing', category: 'file', formatArgs: a => shortenPath(a.path || a.file_path) }) - register('edit', { label: 'Editing', category: 'file', formatArgs: a => shortenPath(a.path || a.file_path) }) - register('str_replace_editor', { label: 'Editing', category: 'file', formatArgs: a => shortenPath(a.path) }) - register('execute', { label: 'Executing', category: 'code', formatArgs: a => truncate(a.command, 60) }) - register('bash', { label: 'Running', category: 'code', formatArgs: a => truncate(a.command, 60) }) - register('run_command', { label: 'Running', category: 'code', formatArgs: a => truncate(a.command, 60) }) - register('python', { label: 'Python', category: 'code', formatArgs: a => truncate(a.code?.split('\n')[0], 60) }) - register('python_interpreter', { label: 'Python', category: 'code' }) - register('web_search', { label: 'Searching', category: 'search', formatArgs: a => a.query }) - register('preview_skill', { label: 'Deploying skill', category: 'other', formatArgs: a => a.skill_name }) - register('glob', { label: 'Finding files', category: 'search' }) - register('find_files', { label: 'Finding files', category: 'search' }) - register('grep', { label: 'Searching code', category: 'search' }) - register('search', { label: 'Searching', category: 'search' }) - register('ls', { label: 'Listing', category: 'file', formatArgs: a => shortenPath(a.path) }) - register('list_directory', { label: 'Listing', category: 'file', formatArgs: a => shortenPath(a.path) }) - register('think', { label: 'Thinking...', category: 'other' }) - register('reasoning', { label: 'Thinking...', category: 'other' }) - register('write_todos', { label: 'Updating plan', category: 'other' }) - register('todo_write', { label: 'Updating plan', category: 'other' }) - register('planner', { label: 'Planning', category: 'other' }) -} - -export function register(name: string, config: ToolDisplayConfig) { registry.set(name, config) } -export function getToolDisplay(name: string, args: Record): { label: string; detail: string; category: string } { /* ... */ } - -function shortenPath(p?: string): string { /* from toolDisplayUtils.ts */ } -function truncate(s?: string, max = 60): string { /* ... */ } - -registerDefaults() -``` - -- [ ] **Step 2: Create ToolCallBadge.tsx** - -Compact inline badge showing icon + label + args summary + status indicator. Replaces `ToolCallItem` inside `MessageItem.tsx`. - -- [ ] **Step 3: Create ToolCallDetail.tsx** - -Generalized from `ToolExecutionPanel.tsx` (375 lines) — shows tool input JSON, output (JSON/Markdown/text), copy buttons, timestamp. - -- [ ] **Step 4: Create barrel export** - -- [ ] **Step 5: Integrate into MessageBubble.tsx** - -Replace the inline `ToolCallItem` in `MessageBubble.tsx` with `ToolCallBadge` from the shared library. - -- [ ] **Step 6: Verify TypeScript compiles and tool display renders correctly** - -- [ ] **Step 7: Commit** - -```bash -git add frontend/app/shared/ToolCallDisplay/ -git commit -m "feat(chat): add shared ToolCallDisplay with human-readable tool labels and badge" -``` - ---- - -### Task 8: Persistent preview panel (layout switch) - -**Files:** -- Modify: `chat/ChatLayout.tsx` (already has ResizablePanel structure from Task 6) -- Delete: `chat/components/ArtifactsDrawer.tsx` -- Delete: `chat/components/CompactArtifactStatus.tsx` -- Delete: `chat/components/ToolExecutionPanel.tsx` -- Delete: `chat/components/CompactToolStatus.tsx` -- Modify: `chat/conversation/ChatInput.tsx` — remove `compactToolStatus` and `compactArtifactStatus` props - -- [ ] **Step 1: Remove overlay rendering from ChatLayout** - -Remove the `renderFloatingPanel` pattern and the `SIDE_PANEL_WIDTH` / `CONTENT_PR` / `CONTENT_MR` constants. The ResizablePanel preview column replaces them. - -- [ ] **Step 2: Remove compact status slot props from ChatInput** - -Remove `compactToolStatus` and `compactArtifactStatus` props from `ChatInput.tsx` — the preview panel is now always visible when content exists, no compact trigger needed. - -- [ ] **Step 3: Delete old overlay components** - -```bash -git rm frontend/app/chat/components/ArtifactsDrawer.tsx -git rm frontend/app/chat/components/CompactArtifactStatus.tsx -git rm frontend/app/chat/components/ToolExecutionPanel.tsx -git rm frontend/app/chat/components/CompactToolStatus.tsx -``` - -- [ ] **Step 4: Add responsive fallback** - -In `ChatLayout.tsx`, add a media query check. For `window.innerWidth < 768`, render PreviewPanel as a slide-over overlay instead of a ResizablePanel column. - -- [ ] **Step 5: Verify app works end-to-end** - -Manual test: send a message that triggers file creation, verify preview panel auto-opens with file tree, close it manually, send another message and verify `userDismissed` suppresses auto-open, verify new conversation resets the flag. - -- [ ] **Step 6: Commit** - -```bash -git add -A -git commit -m "feat(chat): replace overlay panels with persistent ResizablePanel preview column" -``` - ---- - -### Task 9: Per-message ActionBar - -**Files:** -- Create: `shared/ActionBar/ActionBar.tsx` -- Create: `shared/ActionBar/actions/CopyAction.tsx` -- Create: `shared/ActionBar/actions/RetryAction.tsx` -- Create: `shared/ActionBar/index.ts` -- Modify: `chat/conversation/MessageBubble.tsx` - -- [ ] **Step 1: Create ActionBar.tsx** - -```typescript -interface ActionConfig { - id: string - label: string - icon: React.ComponentType<{ size?: number }> - onClick: () => void - show?: boolean -} - -interface ActionBarProps { - actions: ActionConfig[] - visible: boolean // hover state or isLast -} -``` - -Renders a row of icon buttons. Fade in/out via `opacity` + `transition`. - -- [ ] **Step 2: Create CopyAction and RetryAction** - -`CopyAction`: copies message content to clipboard, shows checkmark for 2s. -`RetryAction`: calls `onRetry(messageId)` which re-sends the preceding user message. - -- [ ] **Step 3: Integrate into MessageBubble** - -Add `ActionBar` below assistant message content. Show on hover (via `group-hover` Tailwind class). Always show on the last assistant message. - -- [ ] **Step 4: Create barrel export** - -- [ ] **Step 5: Verify actions work** - -- [ ] **Step 6: Commit** - -```bash -git add frontend/app/shared/ActionBar/ -git commit -m "feat(chat): add per-message ActionBar with Copy and Retry actions" -``` - ---- - -### Task 10: Starter prompts for guided entry - -**Files:** -- Create: `shared/StarterPrompts/StarterPrompts.tsx` -- Create: `shared/StarterPrompts/index.ts` -- Modify: `chat/config/modeConfig.ts` — add `starterPrompts` field -- Modify: `chat/components/ChatHome.tsx` — integrate StarterPrompts - -- [ ] **Step 1: Add starterPrompts to ModeConfig** - -In `modeConfig.ts`, extend the interface: - -```typescript -export interface StarterPrompt { - labelKey: string - promptKey: string - icon: any -} - -export interface ModeConfig { - // ... existing fields - starterPrompts?: StarterPrompt[] -} -``` - -Add prompts to `default-chat`: -```typescript -{ - id: 'default-chat', - // ... existing - starterPrompts: [ - { labelKey: 'chat.starter.analyzeCode', promptKey: 'chat.starter.analyzeCodePrompt', icon: Code }, - { labelKey: 'chat.starter.writeScript', promptKey: 'chat.starter.writeScriptPrompt', icon: Terminal }, - { labelKey: 'chat.starter.explainConcept', promptKey: 'chat.starter.explainConceptPrompt', icon: BookOpen }, - ] -} -``` - -- [ ] **Step 2: Create StarterPrompts.tsx** - -```typescript -interface StarterPromptsProps { - prompts: StarterPrompt[] - onSelect: (prompt: string) => void -} -``` - -Renders a row of clickable chips. On click: calls `onSelect(t(prompt.promptKey))`, adds brief highlight animation. - -- [ ] **Step 3: Integrate into ChatHome** - -Below the mode cards in `ChatHome.tsx`, render `StarterPrompts` for the currently selected mode. On select, fill the input and focus the textarea. - -- [ ] **Step 4: Commit** - -```bash -git add frontend/app/shared/StarterPrompts/ frontend/app/chat/config/modeConfig.ts frontend/app/chat/components/ChatHome.tsx -git commit -m "feat(chat): add starter prompts for guided entry experience" -``` - ---- - -### Task 11: Skill Creator migration to shared components - -**Files:** -- Modify: `skills/creator/components/SkillCreatorChat.tsx` -- Modify: `skills/creator/components/toolDisplayUtils.ts` → deprecate, import from shared registry - -- [ ] **Step 1: Replace toolDisplayUtils with shared registry** - -In `SkillCreatorChat.tsx`, replace: -```typescript -import { formatToolDisplay } from './toolDisplayUtils' -``` -with: -```typescript -import { getToolDisplay } from '@/app/shared/ToolCallDisplay' -``` - -Update all `formatToolDisplay()` calls to use `getToolDisplay()`. - -- [ ] **Step 2: Replace inline tool badges with ToolCallBadge** - -If the Skill Creator renders custom tool badges inline, replace them with `ToolCallBadge` from the shared library. - -- [ ] **Step 3: Verify Skill Creator still works** - -Manual test: navigate to `/skills/creator`, create a skill with AI, verify tool display is correct and preview works. - -- [ ] **Step 4: Delete or deprecate toolDisplayUtils.ts** - -Add a deprecation comment or delete if all imports are migrated. - -- [ ] **Step 5: Commit** - -```bash -git add frontend/app/skills/creator/ frontend/app/shared/ToolCallDisplay/ -git commit -m "refactor(skills): migrate Skill Creator to shared ToolCallDisplay components" -``` - ---- - -## Final Cleanup - -### Task 12: Remove dead code and update imports - -- [ ] **Step 1: Remove old ThreadContent and MessageItem** - -If no other files import the old components: -```bash -git rm frontend/app/chat/components/ThreadContent.tsx -git rm frontend/app/chat/components/MessageItem.tsx -``` - -Keep `ChatSidebar.tsx` and `ChatHome.tsx` in `components/` — they are still used. - -- [ ] **Step 2: Verify no broken imports** - -Run: `cd frontend && npx tsc --noEmit --pretty 2>&1 | head -50` - -- [ ] **Step 3: Final commit** - -```bash -git add -A -git commit -m "refactor(chat): remove deprecated components and clean up imports" -``` diff --git a/docs/superpowers/plans/2026-03-20-skill-versioning-permissions-api.md b/docs/superpowers/plans/2026-03-20-skill-versioning-permissions-api.md deleted file mode 100644 index 64c17070f..000000000 --- a/docs/superpowers/plans/2026-03-20-skill-versioning-permissions-api.md +++ /dev/null @@ -1,2942 +0,0 @@ -# Skill Versioning, Permissions & Token API Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Add semantic versioning, team collaboration permissions, and PlatformToken auth to the Skill system. - -**Architecture:** 4 new DB tables (skill_versions, skill_version_files, skill_collaborators, platform_tokens) with zero changes to existing tables. New repos/services/routes follow existing layered pattern (Repository → Service → API). A unified `check_skill_access()` replaces hardcoded `owner_id` checks. Dual-mode auth dependency supports session + `sk_` PlatformToken. - -**Tech Stack:** FastAPI, SQLAlchemy async (PostgreSQL), Alembic, Pydantic v2, `semver` PyPI package, `secrets` stdlib. - -**Spec:** `docs/superpowers/specs/2026-03-20-skill-versioning-permissions-api-design.md` - ---- - -## File Structure - -### New Files -| File | Responsibility | -|------|---------------| -| `backend/app/models/skill_version.py` | SkillVersion + SkillVersionFile ORM models | -| `backend/app/models/skill_collaborator.py` | CollaboratorRole enum + SkillCollaborator ORM model | -| `backend/app/models/platform_token.py` | PlatformToken ORM model | -| `backend/app/schemas/skill_version.py` | Pydantic schemas for version CRUD | -| `backend/app/schemas/skill_collaborator.py` | Pydantic schemas for collaborator CRUD | -| `backend/app/schemas/platform_token.py` | Pydantic schemas for token CRUD | -| `backend/app/repositories/skill_version.py` | SkillVersion + SkillVersionFile repository | -| `backend/app/repositories/skill_collaborator.py` | SkillCollaborator repository | -| `backend/app/repositories/platform_token.py` | PlatformToken repository | -| `backend/app/services/skill_version_service.py` | Version publish/list/restore logic | -| `backend/app/services/skill_collaborator_service.py` | Collaborator CRUD + transfer | -| `backend/app/services/platform_token_service.py` | Token create/list/revoke | -| `backend/app/common/skill_permissions.py` | `check_skill_access()` unified permission check | -| `backend/app/common/auth_dependency.py` | `get_current_user_or_token()` dual-mode auth | -| `backend/app/api/v1/skill_versions.py` | Version API routes | -| `backend/app/api/v1/skill_collaborators.py` | Collaborator API routes | -| `backend/app/api/v1/tokens.py` | Token API routes | -| `backend/alembic/versions/20260321_000011_add_skill_versioning_permissions_tokens.py` | Migration | -| `backend/tests/test_api/test_skill_versions.py` | Version API tests | -| `backend/tests/test_api/test_skill_collaborators.py` | Collaborator API tests | -| `backend/tests/test_api/test_platform_tokens.py` | Token API tests | -| `backend/tests/test_services/test_skill_permissions.py` | Permission utility tests | - -### Modified Files -| File | Change | -|------|--------| -| `backend/app/models/__init__.py` | Register 4 new models + CollaboratorRole enum | -| `backend/app/api/v1/__init__.py` | Register 3 new routers | -| `backend/app/repositories/skill.py` | Extend `list_by_user()` with collaborator subquery | -| `backend/app/services/skill_service.py` | Replace `owner_id` checks with `check_skill_access()` | -| `backend/app/schemas/skill.py` | Add `latest_version` field to SkillSchema | - ---- - -### Task 1: SkillCollaborator Model + CollaboratorRole Enum - -**Files:** -- Create: `backend/app/models/skill_collaborator.py` -- Test: `backend/tests/test_services/test_skill_permissions.py` (placeholder) - -- [ ] **Step 1: Create the SkillCollaborator model file** - -```python -# backend/app/models/skill_collaborator.py -"""Skill Collaborator model — per-skill role-based access control.""" - -from __future__ import annotations - -import enum -from typing import TYPE_CHECKING - -from sqlalchemy import Enum, ForeignKey, Index, String, UniqueConstraint -from sqlalchemy.dialects.postgresql import UUID -from sqlalchemy.orm import Mapped, mapped_column, relationship - -from .base import BaseModel - -if TYPE_CHECKING: - from .auth import AuthUser - from .skill import Skill - - -class CollaboratorRole(str, enum.Enum): - """Roles ordered by privilege: viewer < editor < publisher < admin.""" - viewer = "viewer" - editor = "editor" - publisher = "publisher" - admin = "admin" - - @classmethod - def rank(cls, role: "CollaboratorRole") -> int: - _order = [cls.viewer, cls.editor, cls.publisher, cls.admin] - return _order.index(role) - - def __ge__(self, other): - if not isinstance(other, CollaboratorRole): - return NotImplemented - return CollaboratorRole.rank(self) >= CollaboratorRole.rank(other) - - def __gt__(self, other): - if not isinstance(other, CollaboratorRole): - return NotImplemented - return CollaboratorRole.rank(self) > CollaboratorRole.rank(other) - - def __le__(self, other): - if not isinstance(other, CollaboratorRole): - return NotImplemented - return CollaboratorRole.rank(self) <= CollaboratorRole.rank(other) - - def __lt__(self, other): - if not isinstance(other, CollaboratorRole): - return NotImplemented - return CollaboratorRole.rank(self) < CollaboratorRole.rank(other) - - -class SkillCollaborator(BaseModel): - """Per-skill collaborator with role.""" - - __tablename__ = "skill_collaborators" - - skill_id: Mapped["uuid.UUID"] = mapped_column( - UUID(as_uuid=True), - ForeignKey("skills.id", ondelete="CASCADE"), - nullable=False, - ) - user_id: Mapped[str] = mapped_column( - String(255), - ForeignKey("user.id", ondelete="CASCADE"), - nullable=False, - ) - role: Mapped[CollaboratorRole] = mapped_column( - Enum(CollaboratorRole, name="collaborator_role", create_constraint=True), - nullable=False, - ) - invited_by: Mapped[str] = mapped_column( - String(255), - ForeignKey("user.id", ondelete="CASCADE"), - nullable=False, - ) - - # Relationships - skill: Mapped["Skill"] = relationship("Skill", lazy="selectin") - user: Mapped["AuthUser"] = relationship("AuthUser", foreign_keys=[user_id], lazy="selectin") - inviter: Mapped["AuthUser"] = relationship("AuthUser", foreign_keys=[invited_by], lazy="selectin") - - __table_args__ = ( - UniqueConstraint("skill_id", "user_id", name="skill_collaborators_skill_user_unique"), - Index("skill_collaborators_user_skill_idx", "user_id", "skill_id"), - ) -``` - -Add the missing `import uuid` at the top (after `import enum`): -```python -import uuid -``` - -- [ ] **Step 2: Verify the file is syntactically correct** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.models.skill_collaborator import SkillCollaborator, CollaboratorRole; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/models/skill_collaborator.py -git commit -m "feat(models): add SkillCollaborator model and CollaboratorRole enum" -``` - ---- - -### Task 2: SkillVersion + SkillVersionFile Models - -**Files:** -- Create: `backend/app/models/skill_version.py` - -- [ ] **Step 1: Create the SkillVersion model file** - -```python -# backend/app/models/skill_version.py -"""Immutable skill version snapshots.""" - -from __future__ import annotations - -import uuid -from typing import TYPE_CHECKING, List, Optional - -from sqlalchemy import DateTime, ForeignKey, Index, Integer, String, Text, UniqueConstraint -from sqlalchemy.dialects.postgresql import JSONB, UUID -from sqlalchemy.orm import Mapped, mapped_column, relationship - -from .base import BaseModel - -if TYPE_CHECKING: - from .auth import AuthUser - from .skill import Skill - - -class SkillVersion(BaseModel): - """Published immutable version snapshot of a Skill.""" - - __tablename__ = "skill_versions" - - skill_id: Mapped[uuid.UUID] = mapped_column( - UUID(as_uuid=True), - ForeignKey("skills.id", ondelete="CASCADE"), - nullable=False, - ) - version: Mapped[str] = mapped_column(String(20), nullable=False) - release_notes: Mapped[Optional[str]] = mapped_column(Text, nullable=True) - - # Snapshot fields - skill_name: Mapped[str] = mapped_column(String(64), nullable=False) - skill_description: Mapped[str] = mapped_column(String(1024), nullable=False) - content: Mapped[str] = mapped_column(Text, nullable=False) - tags: Mapped[list] = mapped_column(JSONB, nullable=False, default=list) - meta_data: Mapped[dict] = mapped_column("metadata", JSONB, nullable=False, default=dict) - allowed_tools: Mapped[list] = mapped_column(JSONB, nullable=False, default=list) - compatibility: Mapped[Optional[str]] = mapped_column(String(500), nullable=True) - license: Mapped[Optional[str]] = mapped_column(String(100), nullable=True) - - published_by_id: Mapped[str] = mapped_column( - String(255), - ForeignKey("user.id", ondelete="CASCADE"), - nullable=False, - ) - published_at: Mapped["datetime"] = mapped_column( - DateTime(timezone=True), - nullable=False, - ) - - # Relationships - skill: Mapped["Skill"] = relationship("Skill", lazy="selectin") - published_by: Mapped["AuthUser"] = relationship("AuthUser", lazy="selectin") - files: Mapped[List["SkillVersionFile"]] = relationship( - "SkillVersionFile", - back_populates="version", - cascade="all, delete-orphan", - lazy="selectin", - ) - - __table_args__ = ( - UniqueConstraint("skill_id", "version", name="skill_versions_skill_version_unique"), - Index("skill_versions_skill_idx", "skill_id"), - Index("skill_versions_published_at_idx", "published_at"), - ) - - -class SkillVersionFile(BaseModel): - """File snapshot belonging to a published version.""" - - __tablename__ = "skill_version_files" - - version_id: Mapped[uuid.UUID] = mapped_column( - UUID(as_uuid=True), - ForeignKey("skill_versions.id", ondelete="CASCADE"), - nullable=False, - ) - path: Mapped[str] = mapped_column(String(512), nullable=False) - file_name: Mapped[str] = mapped_column(String(255), nullable=False) - file_type: Mapped[str] = mapped_column(String(50), nullable=False) - content: Mapped[Optional[str]] = mapped_column(Text, nullable=True) - storage_type: Mapped[str] = mapped_column(String(20), nullable=False, default="database") - storage_key: Mapped[Optional[str]] = mapped_column(String(512), nullable=True) - size: Mapped[int] = mapped_column(Integer, nullable=False, default=0) - - # Relationship - version: Mapped["SkillVersion"] = relationship("SkillVersion", back_populates="files", lazy="selectin") - - __table_args__ = ( - Index("skill_version_files_version_idx", "version_id"), - ) -``` - -Add `from datetime import datetime` at top (after `import uuid`). - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.models.skill_version import SkillVersion, SkillVersionFile; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/models/skill_version.py -git commit -m "feat(models): add SkillVersion and SkillVersionFile models" -``` - ---- - -### Task 3: PlatformToken Model - -**Files:** -- Create: `backend/app/models/platform_token.py` - -- [ ] **Step 1: Create the PlatformToken model file** - -```python -# backend/app/models/platform_token.py -"""Universal PlatformToken for API authentication.""" - -from __future__ import annotations - -import uuid -from datetime import datetime -from typing import TYPE_CHECKING, Optional - -from sqlalchemy import Boolean, DateTime, ForeignKey, Index, String -from sqlalchemy.dialects.postgresql import JSONB, UUID -from sqlalchemy.orm import Mapped, mapped_column, relationship - -from .base import BaseModel - -if TYPE_CHECKING: - from .auth import AuthUser - - -class PlatformToken(BaseModel): - """API token with scoped permissions.""" - - __tablename__ = "platform_tokens" - - user_id: Mapped[str] = mapped_column( - String(255), - ForeignKey("user.id", ondelete="CASCADE"), - nullable=False, - ) - name: Mapped[str] = mapped_column(String(255), nullable=False) - token_hash: Mapped[str] = mapped_column(String(64), nullable=False, unique=True) - token_prefix: Mapped[str] = mapped_column(String(12), nullable=False) - scopes: Mapped[list] = mapped_column(JSONB, nullable=False, default=list) - resource_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True) - resource_id: Mapped[Optional[uuid.UUID]] = mapped_column(UUID(as_uuid=True), nullable=True) - expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) - last_used_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) - is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) - - # Relationship - user: Mapped["AuthUser"] = relationship("AuthUser", lazy="selectin") - - __table_args__ = ( - Index("platform_tokens_user_idx", "user_id"), - Index("platform_tokens_hash_idx", "token_hash"), - Index("platform_tokens_active_idx", "is_active"), - ) -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.models.platform_token import PlatformToken; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/models/platform_token.py -git commit -m "feat(models): add PlatformToken model" -``` - ---- - -### Task 4: Register Models in `__init__.py` - -**Files:** -- Modify: `backend/app/models/__init__.py` - -- [ ] **Step 1: Add imports and __all__ entries** - -Add these imports after `from .skill import Skill, SkillFile`: -```python -from .skill_collaborator import CollaboratorRole, SkillCollaborator -from .skill_version import SkillVersion, SkillVersionFile -from .platform_token import PlatformToken -``` - -Add to `__all__`: -```python - "CollaboratorRole", - "SkillCollaborator", - "SkillVersion", - "SkillVersionFile", - "PlatformToken", -``` - -- [ ] **Step 2: Verify import** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.models import SkillVersion, SkillVersionFile, SkillCollaborator, CollaboratorRole, PlatformToken; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/models/__init__.py -git commit -m "feat(models): register new models in __init__.py" -``` - ---- - -### Task 5: Alembic Migration - -**Files:** -- Create: `backend/alembic/versions/20260321_000011_add_skill_versioning_permissions_tokens.py` - -- [ ] **Step 1: Generate migration** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && alembic revision --autogenerate -m "add_skill_versioning_permissions_tokens"` - -If autogenerate fails, create manually. The migration must create these 4 tables: -- `skill_collaborators` (with `collaborator_role` enum type) -- `skill_versions` -- `skill_version_files` -- `platform_tokens` - -- [ ] **Step 2: Review the generated migration** - -Open the generated file and verify: -1. `collaborator_role` enum is created before table -2. All columns, FKs, indexes, unique constraints match the spec -3. `downgrade()` drops tables in correct order (version_files before versions) and drops the enum - -- [ ] **Step 3: Test migration runs** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && alembic upgrade head` -Expected: No errors, 4 tables created. - -- [ ] **Step 4: Commit** - -```bash -git add backend/alembic/versions/ -git commit -m "feat(migration): add skill_versions, skill_collaborators, platform_tokens tables" -``` - ---- - -### Task 6: Skill Permission Utility — `check_skill_access()` - -**Files:** -- Create: `backend/app/common/skill_permissions.py` -- Test: `backend/tests/test_services/test_skill_permissions.py` - -- [ ] **Step 1: Write failing tests** - -```python -# backend/tests/test_services/test_skill_permissions.py -"""Tests for check_skill_access unified permission check.""" - -import uuid -from unittest.mock import AsyncMock, MagicMock, patch - -import pytest - -from app.common.exceptions import ForbiddenException -from app.common.skill_permissions import check_skill_access -from app.models.skill_collaborator import CollaboratorRole - - -def _make_skill(owner_id="owner-1", is_public=False): - skill = MagicMock() - skill.id = uuid.uuid4() - skill.owner_id = owner_id - skill.is_public = is_public - return skill - - -def _make_user(user_id="user-1", is_superuser=False): - user = MagicMock() - user.id = user_id - user.is_superuser = is_superuser - return user - - -@pytest.mark.asyncio -async def test_superuser_always_passes(): - skill = _make_skill(owner_id="other") - db = AsyncMock() - await check_skill_access(db, skill, "super-1", CollaboratorRole.admin, is_superuser=True) - # Should not raise - - -@pytest.mark.asyncio -async def test_owner_always_passes(): - skill = _make_skill(owner_id="owner-1") - db = AsyncMock() - await check_skill_access(db, skill, "owner-1", CollaboratorRole.admin) - # Should not raise - - -@pytest.mark.asyncio -async def test_collaborator_with_sufficient_role(): - skill = _make_skill(owner_id="other") - db = AsyncMock() - mock_collab = MagicMock() - mock_collab.role = CollaboratorRole.editor - with patch("app.common.skill_permissions._get_collaborator", return_value=mock_collab): - await check_skill_access(db, skill, "user-1", CollaboratorRole.editor) - - -@pytest.mark.asyncio -async def test_collaborator_with_insufficient_role(): - skill = _make_skill(owner_id="other") - db = AsyncMock() - mock_collab = MagicMock() - mock_collab.role = CollaboratorRole.viewer - with patch("app.common.skill_permissions._get_collaborator", return_value=mock_collab): - with pytest.raises(ForbiddenException): - await check_skill_access(db, skill, "user-1", CollaboratorRole.editor) - - -@pytest.mark.asyncio -async def test_public_skill_viewer_access(): - skill = _make_skill(owner_id="other", is_public=True) - db = AsyncMock() - with patch("app.common.skill_permissions._get_collaborator", return_value=None): - await check_skill_access(db, skill, "user-1", CollaboratorRole.viewer) - - -@pytest.mark.asyncio -async def test_public_skill_editor_access_denied(): - skill = _make_skill(owner_id="other", is_public=True) - db = AsyncMock() - with patch("app.common.skill_permissions._get_collaborator", return_value=None): - with pytest.raises(ForbiddenException): - await check_skill_access(db, skill, "user-1", CollaboratorRole.editor) - - -@pytest.mark.asyncio -async def test_token_scope_check_passes(): - skill = _make_skill(owner_id="owner-1") - db = AsyncMock() - await check_skill_access( - db, skill, "owner-1", CollaboratorRole.viewer, - token_scopes=["skills:read"], required_scope="skills:read", - ) - - -@pytest.mark.asyncio -async def test_token_scope_check_fails(): - skill = _make_skill(owner_id="owner-1") - db = AsyncMock() - with pytest.raises(ForbiddenException): - await check_skill_access( - db, skill, "owner-1", CollaboratorRole.viewer, - token_scopes=["skills:read"], required_scope="skills:write", - ) -``` - -- [ ] **Step 2: Run tests to verify they fail** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -m pytest tests/test_services/test_skill_permissions.py -v` -Expected: FAIL — `ModuleNotFoundError: No module named 'app.common.skill_permissions'` - -- [ ] **Step 3: Implement `check_skill_access()`** - -```python -# backend/app/common/skill_permissions.py -"""Unified skill permission check — replaces hardcoded owner_id comparisons.""" - -from __future__ import annotations - -from typing import List, Optional - -from sqlalchemy import and_, select -from sqlalchemy.ext.asyncio import AsyncSession - -from app.common.exceptions import ForbiddenException -from app.models.skill import Skill -from app.models.skill_collaborator import CollaboratorRole, SkillCollaborator - - -async def _get_collaborator( - db: AsyncSession, - skill_id, - user_id: str, -) -> Optional[SkillCollaborator]: - result = await db.execute( - select(SkillCollaborator).where( - and_( - SkillCollaborator.skill_id == skill_id, - SkillCollaborator.user_id == user_id, - ) - ) - ) - return result.scalar_one_or_none() - - -async def check_skill_access( - db: AsyncSession, - skill: Skill, - user_id: str, - min_role: CollaboratorRole, - *, - is_superuser: bool = False, - token_scopes: Optional[List[str]] = None, - required_scope: Optional[str] = None, -) -> None: - """ - Unified permission check. - - Raises ForbiddenException if the user lacks sufficient access. - """ - # 1. Superuser bypass - if is_superuser: - _check_token_scope(token_scopes, required_scope) - return - - # 2. Owner always passes - if skill.owner_id and skill.owner_id == user_id: - _check_token_scope(token_scopes, required_scope) - return - - # 3. Check collaborator role - collab = await _get_collaborator(db, skill.id, user_id) - if collab and collab.role >= min_role: - _check_token_scope(token_scopes, required_scope) - return - - # 4. Public skill + viewer access - if skill.is_public and min_role == CollaboratorRole.viewer: - _check_token_scope(token_scopes, required_scope) - return - - raise ForbiddenException("You don't have permission to access this skill") - - -def _check_token_scope( - token_scopes: Optional[List[str]], - required_scope: Optional[str], -) -> None: - """If request came via PlatformToken, verify scope.""" - if token_scopes is not None and required_scope is not None: - if required_scope not in token_scopes: - raise ForbiddenException(f"Token missing required scope: {required_scope}") -``` - -- [ ] **Step 4: Run tests to verify they pass** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -m pytest tests/test_services/test_skill_permissions.py -v` -Expected: All 8 tests PASS - -- [ ] **Step 5: Commit** - -```bash -git add backend/app/common/skill_permissions.py backend/tests/test_services/test_skill_permissions.py -git commit -m "feat(permissions): add check_skill_access() unified permission utility" -``` - ---- - -### Task 7: Dual-Mode Auth Dependency — `get_current_user_or_token()` - -**Files:** -- Create: `backend/app/common/auth_dependency.py` - -- [ ] **Step 1: Implement the dual-mode auth dependency** - -```python -# backend/app/common/auth_dependency.py -"""Dual-mode authentication: session/JWT + PlatformToken (sk_ prefix).""" - -from __future__ import annotations - -import hashlib -from dataclasses import dataclass -from datetime import datetime, timezone -from typing import List, Optional - -from fastapi import Depends, Request -from fastapi.security import OAuth2PasswordBearer -from sqlalchemy import select -from sqlalchemy.ext.asyncio import AsyncSession - -from app.common.dependencies import get_current_user -from app.common.exceptions import UnauthorizedException -from app.core.database import get_db -from app.models.auth import AuthUser as User -from app.models.platform_token import PlatformToken - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login", auto_error=False) - -# Debounce interval for last_used_at updates (5 minutes) -_LAST_USED_DEBOUNCE_SECONDS = 300 - - -@dataclass -class AuthContext: - """Result of authentication — carries user + optional token scopes.""" - user: User - token_scopes: Optional[List[str]] = None - - @property - def is_token_auth(self) -> bool: - return self.token_scopes is not None - - -async def get_current_user_or_token( - token: Optional[str] = Depends(oauth2_scheme), - request: Request = None, - db: AsyncSession = Depends(get_db), -) -> AuthContext: - """ - Authenticate via session/JWT or PlatformToken. - - If Bearer token starts with 'sk_', route to PlatformToken path. - Otherwise, fall through to existing session/JWT auth. - """ - # Try to extract token from cookie if not in header - raw_token = token - if not raw_token and request: - from app.core.settings import settings - raw_token = ( - request.cookies.get(settings.cookie_name) - or request.cookies.get("session-token") - or request.cookies.get("session_token") - or request.cookies.get("access_token") - or request.cookies.get("Authorization") - or request.cookies.get("auth_token") - ) - - # PlatformToken path - if raw_token and raw_token.startswith("sk_"): - return await _authenticate_platform_token(raw_token, db) - - # Fall through to existing session/JWT auth - user = await get_current_user(token=token, request=request, db=db) - return AuthContext(user=user, token_scopes=None) - - -async def _authenticate_platform_token( - raw_token: str, - db: AsyncSession, -) -> AuthContext: - """Verify a PlatformToken and return AuthContext with scopes.""" - token_hash = hashlib.sha256(raw_token.encode()).hexdigest() - - result = await db.execute( - select(PlatformToken).where(PlatformToken.token_hash == token_hash) - ) - pt = result.scalar_one_or_none() - - if not pt: - raise UnauthorizedException("Invalid API token") - - if not pt.is_active: - raise UnauthorizedException("API token has been revoked") - - if pt.expires_at and pt.expires_at < datetime.now(timezone.utc): - raise UnauthorizedException("API token has expired") - - # Debounce last_used_at update - now = datetime.now(timezone.utc) - if not pt.last_used_at or (now - pt.last_used_at).total_seconds() > _LAST_USED_DEBOUNCE_SECONDS: - pt.last_used_at = now - await db.commit() - - # Load the user - user_result = await db.execute(select(User).where(User.id == pt.user_id)) - user = user_result.scalar_one_or_none() - if not user or not user.is_active: - raise UnauthorizedException("Token owner account is inactive") - - return AuthContext(user=user, token_scopes=list(pt.scopes)) -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.common.auth_dependency import get_current_user_or_token, AuthContext; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/common/auth_dependency.py -git commit -m "feat(auth): add get_current_user_or_token() dual-mode auth dependency" -``` - ---- - -### Task 8: Repositories — SkillCollaborator - -**Files:** -- Create: `backend/app/repositories/skill_collaborator.py` - -- [ ] **Step 1: Create SkillCollaborator repository** - -```python -# backend/app/repositories/skill_collaborator.py -"""Skill Collaborator Repository.""" - -from __future__ import annotations - -import uuid -from typing import List, Optional - -from sqlalchemy import and_, select -from sqlalchemy.ext.asyncio import AsyncSession - -from app.models.skill_collaborator import CollaboratorRole, SkillCollaborator - -from .base import BaseRepository - - -class SkillCollaboratorRepository(BaseRepository[SkillCollaborator]): - def __init__(self, db: AsyncSession): - super().__init__(SkillCollaborator, db) - - async def get_by_skill_and_user( - self, skill_id: uuid.UUID, user_id: str - ) -> Optional[SkillCollaborator]: - result = await self.db.execute( - select(SkillCollaborator).where( - and_( - SkillCollaborator.skill_id == skill_id, - SkillCollaborator.user_id == user_id, - ) - ) - ) - return result.scalar_one_or_none() - - async def list_by_skill(self, skill_id: uuid.UUID) -> List[SkillCollaborator]: - result = await self.db.execute( - select(SkillCollaborator).where(SkillCollaborator.skill_id == skill_id) - ) - return list(result.scalars().all()) - - async def list_skill_ids_for_user(self, user_id: str) -> List[uuid.UUID]: - """Return skill IDs where user is a collaborator (used by list_by_user).""" - result = await self.db.execute( - select(SkillCollaborator.skill_id).where( - SkillCollaborator.user_id == user_id - ) - ) - return [row[0] for row in result.all()] - - async def delete_by_skill_and_user( - self, skill_id: uuid.UUID, user_id: str - ) -> bool: - collab = await self.get_by_skill_and_user(skill_id, user_id) - if not collab: - return False - await self.db.delete(collab) - await self.db.flush() - return True -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.repositories.skill_collaborator import SkillCollaboratorRepository; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/repositories/skill_collaborator.py -git commit -m "feat(repos): add SkillCollaboratorRepository" -``` - ---- - -### Task 9: Repositories — SkillVersion + SkillVersionFile - -**Files:** -- Create: `backend/app/repositories/skill_version.py` - -- [ ] **Step 1: Create SkillVersion repository** - -```python -# backend/app/repositories/skill_version.py -"""Skill Version Repository.""" - -from __future__ import annotations - -import uuid -from typing import List, Optional - -from sqlalchemy import and_, select -from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy.orm import selectinload - -from app.models.skill_version import SkillVersion, SkillVersionFile - -from .base import BaseRepository - - -class SkillVersionRepository(BaseRepository[SkillVersion]): - def __init__(self, db: AsyncSession): - super().__init__(SkillVersion, db) - - async def list_by_skill(self, skill_id: uuid.UUID) -> List[SkillVersion]: - result = await self.db.execute( - select(SkillVersion) - .where(SkillVersion.skill_id == skill_id) - .options(selectinload(SkillVersion.files)) - .order_by(SkillVersion.published_at.desc()) - ) - return list(result.scalars().all()) - - async def get_latest(self, skill_id: uuid.UUID) -> Optional[SkillVersion]: - result = await self.db.execute( - select(SkillVersion) - .where(SkillVersion.skill_id == skill_id) - .options(selectinload(SkillVersion.files)) - .order_by(SkillVersion.published_at.desc()) - .limit(1) - ) - return result.scalar_one_or_none() - - async def get_by_version( - self, skill_id: uuid.UUID, version: str - ) -> Optional[SkillVersion]: - result = await self.db.execute( - select(SkillVersion) - .where( - and_( - SkillVersion.skill_id == skill_id, - SkillVersion.version == version, - ) - ) - .options(selectinload(SkillVersion.files)) - ) - return result.scalar_one_or_none() - - async def get_highest_version_str(self, skill_id: uuid.UUID) -> Optional[str]: - """Return the highest semver version string for a skill.""" - versions = await self.list_by_skill(skill_id) - if not versions: - return None - import semver - parsed = [(v, semver.Version.parse(v.version)) for v in versions] - parsed.sort(key=lambda x: x[1], reverse=True) - return parsed[0][0].version - - -class SkillVersionFileRepository(BaseRepository[SkillVersionFile]): - def __init__(self, db: AsyncSession): - super().__init__(SkillVersionFile, db) - - async def list_by_version(self, version_id: uuid.UUID) -> List[SkillVersionFile]: - result = await self.db.execute( - select(SkillVersionFile).where( - SkillVersionFile.version_id == version_id - ) - ) - return list(result.scalars().all()) -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.repositories.skill_version import SkillVersionRepository, SkillVersionFileRepository; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/repositories/skill_version.py -git commit -m "feat(repos): add SkillVersionRepository and SkillVersionFileRepository" -``` - ---- - -### Task 10: Repository — PlatformToken - -**Files:** -- Create: `backend/app/repositories/platform_token.py` - -- [ ] **Step 1: Create PlatformToken repository** - -```python -# backend/app/repositories/platform_token.py -"""PlatformToken Repository.""" - -from __future__ import annotations - -from typing import List, Optional - -from sqlalchemy import and_, func, select -from sqlalchemy.ext.asyncio import AsyncSession - -from app.models.platform_token import PlatformToken - -from .base import BaseRepository - - -class PlatformTokenRepository(BaseRepository[PlatformToken]): - def __init__(self, db: AsyncSession): - super().__init__(PlatformToken, db) - - async def get_by_hash(self, token_hash: str) -> Optional[PlatformToken]: - result = await self.db.execute( - select(PlatformToken).where(PlatformToken.token_hash == token_hash) - ) - return result.scalar_one_or_none() - - async def list_by_user(self, user_id: str) -> List[PlatformToken]: - result = await self.db.execute( - select(PlatformToken) - .where(PlatformToken.user_id == user_id) - .order_by(PlatformToken.created_at.desc()) - ) - return list(result.scalars().all()) - - async def count_active_by_user(self, user_id: str) -> int: - result = await self.db.execute( - select(func.count()).select_from(PlatformToken).where( - and_( - PlatformToken.user_id == user_id, - PlatformToken.is_active.is_(True), - ) - ) - ) - return result.scalar() or 0 -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.repositories.platform_token import PlatformTokenRepository; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/repositories/platform_token.py -git commit -m "feat(repos): add PlatformTokenRepository" -``` - ---- - -### Task 11: Extend `SkillRepository.list_by_user()` for Collaborator Access - -**Files:** -- Modify: `backend/app/repositories/skill.py:23-66` - -- [ ] **Step 1: Add collaborator subquery to list_by_user** - -In `backend/app/repositories/skill.py`, add import at top: -```python -from app.models.skill_collaborator import SkillCollaborator -``` - -Modify the `list_by_user` method — in the `if user_id:` block where `include_public` is True, change: -```python -# OLD -conditions.append( - or_( - Skill.owner_id == user_id, - Skill.is_public.is_(True), - Skill.owner_id.is_(None), - ) -) -``` -to: -```python -# NEW — include skills where user is a collaborator -collab_subquery = select(SkillCollaborator.skill_id).where( - SkillCollaborator.user_id == user_id -).scalar_subquery() -conditions.append( - or_( - Skill.owner_id == user_id, - Skill.id.in_(collab_subquery), - Skill.is_public.is_(True), - Skill.owner_id.is_(None), - ) -) -``` - -And the `include_public=False` branch: -```python -# OLD -conditions.append(Skill.owner_id == user_id) -``` -to: -```python -# NEW -collab_subquery = select(SkillCollaborator.skill_id).where( - SkillCollaborator.user_id == user_id -).scalar_subquery() -conditions.append( - or_( - Skill.owner_id == user_id, - Skill.id.in_(collab_subquery), - ) -) -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.repositories.skill import SkillRepository; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/repositories/skill.py -git commit -m "feat(repos): extend list_by_user to include collaborator skills" -``` - ---- - -### Task 12: Pydantic Schemas — SkillCollaborator - -**Files:** -- Create: `backend/app/schemas/skill_collaborator.py` - -- [ ] **Step 1: Create schemas** - -```python -# backend/app/schemas/skill_collaborator.py -"""Pydantic schemas for Skill Collaborator API.""" - -import uuid -from datetime import datetime -from typing import Optional - -from pydantic import BaseModel, Field, field_validator - -from app.models.skill_collaborator import CollaboratorRole - - -class CollaboratorCreate(BaseModel): - user_id: str = Field(..., description="User ID to add as collaborator") - role: CollaboratorRole = Field(..., description="Role to assign") - - -class CollaboratorUpdate(BaseModel): - role: CollaboratorRole = Field(..., description="New role") - - -class CollaboratorSchema(BaseModel): - id: str - skill_id: str - user_id: str - role: CollaboratorRole - invited_by: str - created_at: Optional[str] = None - - @field_validator("id", "skill_id", mode="before") - @classmethod - def convert_uuid_to_str(cls, v): - if isinstance(v, uuid.UUID): - return str(v) - return v - - @field_validator("created_at", mode="before") - @classmethod - def convert_datetime_to_str(cls, v): - if isinstance(v, datetime): - return v.isoformat() - return v - - class Config: - from_attributes = True - - -class TransferOwnershipRequest(BaseModel): - new_owner_id: str = Field(..., description="User ID of new owner") -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.schemas.skill_collaborator import CollaboratorCreate, CollaboratorSchema, TransferOwnershipRequest; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/schemas/skill_collaborator.py -git commit -m "feat(schemas): add skill collaborator Pydantic schemas" -``` - ---- - -### Task 13: Pydantic Schemas — SkillVersion - -**Files:** -- Create: `backend/app/schemas/skill_version.py` - -- [ ] **Step 1: Create schemas** - -```python -# backend/app/schemas/skill_version.py -"""Pydantic schemas for Skill Version API.""" - -import uuid -from datetime import datetime -from typing import List, Optional - -from pydantic import BaseModel, Field, field_validator - - -class VersionPublishRequest(BaseModel): - version: str = Field(..., description="Semver MAJOR.MINOR.PATCH", max_length=20) - release_notes: Optional[str] = Field(None, description="Changelog / release notes") - - -class VersionRestoreRequest(BaseModel): - version: str = Field(..., description="Version to restore draft from") - - -class VersionFileSchema(BaseModel): - id: str - version_id: str - path: str - file_name: str - file_type: str - content: Optional[str] = None - storage_type: str = "database" - storage_key: Optional[str] = None - size: int = 0 - - @field_validator("id", "version_id", mode="before") - @classmethod - def convert_uuid_to_str(cls, v): - if isinstance(v, uuid.UUID): - return str(v) - return v - - class Config: - from_attributes = True - - -class VersionSchema(BaseModel): - id: str - skill_id: str - version: str - release_notes: Optional[str] = None - skill_name: str - skill_description: str - content: str - tags: List[str] = Field(default_factory=list) - metadata: dict = Field(default_factory=dict, validation_alias="meta_data") - allowed_tools: List[str] = Field(default_factory=list) - compatibility: Optional[str] = None - license: Optional[str] = None - published_by_id: str - published_at: Optional[str] = None - created_at: Optional[str] = None - files: Optional[List[VersionFileSchema]] = None - - @field_validator("id", "skill_id", mode="before") - @classmethod - def convert_uuid_to_str(cls, v): - if isinstance(v, uuid.UUID): - return str(v) - return v - - @field_validator("published_at", "created_at", mode="before") - @classmethod - def convert_datetime_to_str(cls, v): - if isinstance(v, datetime): - return v.isoformat() - return v - - class Config: - from_attributes = True - populate_by_name = True - - -class VersionSummarySchema(BaseModel): - """Lightweight version info for embedding in SkillSchema.""" - version: str - release_notes: Optional[str] = None - published_at: Optional[str] = None - - @field_validator("published_at", mode="before") - @classmethod - def convert_datetime_to_str(cls, v): - if isinstance(v, datetime): - return v.isoformat() - return v - - class Config: - from_attributes = True -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.schemas.skill_version import VersionPublishRequest, VersionSchema, VersionSummarySchema; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/schemas/skill_version.py -git commit -m "feat(schemas): add skill version Pydantic schemas" -``` - ---- - -### Task 14: Pydantic Schemas — PlatformToken - -**Files:** -- Create: `backend/app/schemas/platform_token.py` - -- [ ] **Step 1: Create schemas** - -```python -# backend/app/schemas/platform_token.py -"""Pydantic schemas for PlatformToken API.""" - -import uuid -from datetime import datetime -from typing import List, Optional - -from pydantic import BaseModel, Field, field_validator - - -class TokenCreate(BaseModel): - name: str = Field(..., max_length=255) - scopes: List[str] = Field(..., description="e.g. ['skills:read', 'skills:write']") - resource_type: Optional[str] = Field(None, max_length=50) - resource_id: Optional[str] = None - expires_at: Optional[datetime] = None - - -class TokenCreateResponse(BaseModel): - """Returned only once at creation — contains plaintext token.""" - id: str - name: str - token: str # plaintext, shown only once - token_prefix: str - scopes: List[str] - expires_at: Optional[str] = None - - @field_validator("id", mode="before") - @classmethod - def convert_uuid_to_str(cls, v): - if isinstance(v, uuid.UUID): - return str(v) - return v - - @field_validator("expires_at", mode="before") - @classmethod - def convert_datetime_to_str(cls, v): - if isinstance(v, datetime): - return v.isoformat() - return v - - -class TokenSchema(BaseModel): - """List view — never contains plaintext token.""" - id: str - name: str - token_prefix: str - scopes: List[str] - resource_type: Optional[str] = None - resource_id: Optional[str] = None - expires_at: Optional[str] = None - last_used_at: Optional[str] = None - is_active: bool - created_at: Optional[str] = None - - @field_validator("id", mode="before") - @classmethod - def convert_uuid_to_str(cls, v): - if isinstance(v, uuid.UUID): - return str(v) - return v - - @field_validator("resource_id", mode="before") - @classmethod - def convert_resource_id(cls, v): - if isinstance(v, uuid.UUID): - return str(v) - return v - - @field_validator("expires_at", "last_used_at", "created_at", mode="before") - @classmethod - def convert_datetime_to_str(cls, v): - if isinstance(v, datetime): - return v.isoformat() - return v - - class Config: - from_attributes = True -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.schemas.platform_token import TokenCreate, TokenCreateResponse, TokenSchema; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/schemas/platform_token.py -git commit -m "feat(schemas): add PlatformToken Pydantic schemas" -``` - ---- - -### Task 15: SkillCollaborator Service - -**Files:** -- Create: `backend/app/services/skill_collaborator_service.py` -- Test: `backend/tests/test_api/test_skill_collaborators.py` (later in Task 21) - -- [ ] **Step 1: Implement service** - -```python -# backend/app/services/skill_collaborator_service.py -"""Skill Collaborator Service — add/update/remove collaborators + ownership transfer.""" - -from __future__ import annotations - -import uuid -from typing import List - -from app.common.exceptions import BadRequestException, ForbiddenException, NotFoundException -from app.common.skill_permissions import check_skill_access -from app.models.skill import Skill -from app.models.skill_collaborator import CollaboratorRole, SkillCollaborator -from app.repositories.skill import SkillRepository -from app.repositories.skill_collaborator import SkillCollaboratorRepository - -from .base import BaseService - - -class SkillCollaboratorService(BaseService[SkillCollaborator]): - def __init__(self, db): - super().__init__(db) - self.repo = SkillCollaboratorRepository(db) - self.skill_repo = SkillRepository(db) - - async def list_collaborators( - self, - skill_id: uuid.UUID, - current_user_id: str, - is_superuser: bool = False, - ) -> List[SkillCollaborator]: - skill = await self._get_skill_or_404(skill_id) - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.viewer, - is_superuser=is_superuser, - ) - return await self.repo.list_by_skill(skill_id) - - async def add_collaborator( - self, - skill_id: uuid.UUID, - current_user_id: str, - target_user_id: str, - role: CollaboratorRole, - is_superuser: bool = False, - ) -> SkillCollaborator: - skill = await self._get_skill_or_404(skill_id) - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.admin, - is_superuser=is_superuser, - ) - - if target_user_id == skill.owner_id: - raise BadRequestException("Cannot add the owner as a collaborator") - - existing = await self.repo.get_by_skill_and_user(skill_id, target_user_id) - if existing: - raise BadRequestException("User is already a collaborator") - - collab = SkillCollaborator( - skill_id=skill_id, - user_id=target_user_id, - role=role, - invited_by=current_user_id, - ) - self.db.add(collab) - await self.db.commit() - await self.db.refresh(collab) - return collab - - async def update_collaborator_role( - self, - skill_id: uuid.UUID, - current_user_id: str, - target_user_id: str, - new_role: CollaboratorRole, - is_superuser: bool = False, - ) -> SkillCollaborator: - skill = await self._get_skill_or_404(skill_id) - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.admin, - is_superuser=is_superuser, - ) - - collab = await self.repo.get_by_skill_and_user(skill_id, target_user_id) - if not collab: - raise NotFoundException("Collaborator not found") - - collab.role = new_role - await self.db.commit() - await self.db.refresh(collab) - return collab - - async def remove_collaborator( - self, - skill_id: uuid.UUID, - current_user_id: str, - target_user_id: str, - is_superuser: bool = False, - ) -> None: - skill = await self._get_skill_or_404(skill_id) - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.admin, - is_superuser=is_superuser, - ) - - deleted = await self.repo.delete_by_skill_and_user(skill_id, target_user_id) - if not deleted: - raise NotFoundException("Collaborator not found") - await self.db.commit() - - async def transfer_ownership( - self, - skill_id: uuid.UUID, - current_user_id: str, - new_owner_id: str, - ) -> Skill: - """Transfer ownership. Only the current owner can do this.""" - skill = await self._get_skill_or_404(skill_id) - - if skill.owner_id != current_user_id: - raise ForbiddenException("Only the owner can transfer ownership") - - # Check new owner doesn't have a skill with the same name - existing = await self.skill_repo.get_by_name_and_owner(skill.name, new_owner_id) - if existing: - raise BadRequestException( - f"New owner already has a skill named '{skill.name}'" - ) - - # Remove new owner from collaborators if present - await self.repo.delete_by_skill_and_user(skill_id, new_owner_id) - - # Add old owner as admin collaborator - old_owner_collab = SkillCollaborator( - skill_id=skill_id, - user_id=current_user_id, - role=CollaboratorRole.admin, - invited_by=current_user_id, - ) - self.db.add(old_owner_collab) - - # Transfer - skill.owner_id = new_owner_id - await self.db.commit() - await self.db.refresh(skill) - return skill - - async def _get_skill_or_404(self, skill_id: uuid.UUID) -> Skill: - skill = await self.skill_repo.get(skill_id) - if not skill: - raise NotFoundException("Skill not found") - return skill -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.services.skill_collaborator_service import SkillCollaboratorService; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/services/skill_collaborator_service.py -git commit -m "feat(services): add SkillCollaboratorService" -``` - ---- - -### Task 16: SkillVersion Service - -**Files:** -- Create: `backend/app/services/skill_version_service.py` - -- [ ] **Step 1: Implement service** - -```python -# backend/app/services/skill_version_service.py -"""Skill Version Service — publish, list, get, delete, restore.""" - -from __future__ import annotations - -import uuid -from datetime import datetime, timezone -from typing import List, Optional - -import semver - -from app.common.exceptions import BadRequestException, NotFoundException -from app.common.skill_permissions import check_skill_access -from app.models.skill import Skill, SkillFile -from app.models.skill_collaborator import CollaboratorRole -from app.models.skill_version import SkillVersion, SkillVersionFile -from app.repositories.skill import SkillFileRepository, SkillRepository -from app.repositories.skill_version import SkillVersionFileRepository, SkillVersionRepository - -from .base import BaseService - - -class SkillVersionService(BaseService[SkillVersion]): - def __init__(self, db): - super().__init__(db) - self.repo = SkillVersionRepository(db) - self.file_repo = SkillVersionFileRepository(db) - self.skill_repo = SkillRepository(db) - self.skill_file_repo = SkillFileRepository(db) - - async def publish_version( - self, - skill_id: uuid.UUID, - current_user_id: str, - version_str: str, - release_notes: Optional[str] = None, - is_superuser: bool = False, - token_scopes: Optional[List[str]] = None, - ) -> SkillVersion: - skill = await self._get_skill_or_404(skill_id) - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.publisher, - is_superuser=is_superuser, - token_scopes=token_scopes, required_scope="skills:publish", - ) - - # Validate semver format - try: - new_ver = semver.Version.parse(version_str) - except ValueError: - raise BadRequestException( - f"Invalid version format: '{version_str}'. Must be MAJOR.MINOR.PATCH" - ) - # Reject pre-release / build metadata - if new_ver.prerelease or new_ver.build: - raise BadRequestException("Pre-release and build metadata are not supported") - - # Check > highest existing - highest_str = await self.repo.get_highest_version_str(skill_id) - if highest_str: - highest = semver.Version.parse(highest_str) - if new_ver <= highest: - raise BadRequestException( - f"Version {version_str} must be greater than current highest {highest_str}" - ) - - # Snapshot - sv = SkillVersion( - skill_id=skill_id, - version=version_str, - release_notes=release_notes, - skill_name=skill.name, - skill_description=skill.description, - content=skill.content, - tags=list(skill.tags) if skill.tags else [], - meta_data=dict(skill.meta_data) if skill.meta_data else {}, - allowed_tools=list(skill.allowed_tools) if skill.allowed_tools else [], - compatibility=skill.compatibility, - license=skill.license, - published_by_id=current_user_id, - published_at=datetime.now(timezone.utc), - ) - self.db.add(sv) - await self.db.flush() - await self.db.refresh(sv) - - # Copy files - skill_files = await self.skill_file_repo.list_by_skill(skill_id) - for sf in skill_files: - vf = SkillVersionFile( - version_id=sv.id, - path=sf.path, - file_name=sf.file_name, - file_type=sf.file_type, - content=sf.content, - storage_type=sf.storage_type, - storage_key=sf.storage_key, - size=sf.size, - ) - self.db.add(vf) - - await self.db.commit() - await self.db.refresh(sv) - return sv - - async def list_versions( - self, - skill_id: uuid.UUID, - current_user_id: str, - is_superuser: bool = False, - token_scopes: Optional[List[str]] = None, - ) -> List[SkillVersion]: - skill = await self._get_skill_or_404(skill_id) - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.viewer, - is_superuser=is_superuser, - token_scopes=token_scopes, required_scope="skills:read", - ) - return await self.repo.list_by_skill(skill_id) - - async def get_version( - self, - skill_id: uuid.UUID, - version_str: str, - current_user_id: str, - is_superuser: bool = False, - token_scopes: Optional[List[str]] = None, - ) -> SkillVersion: - skill = await self._get_skill_or_404(skill_id) - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.viewer, - is_superuser=is_superuser, - token_scopes=token_scopes, required_scope="skills:read", - ) - sv = await self.repo.get_by_version(skill_id, version_str) - if not sv: - raise NotFoundException(f"Version {version_str} not found") - return sv - - async def get_latest_version( - self, - skill_id: uuid.UUID, - current_user_id: str, - is_superuser: bool = False, - token_scopes: Optional[List[str]] = None, - ) -> SkillVersion: - skill = await self._get_skill_or_404(skill_id) - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.viewer, - is_superuser=is_superuser, - token_scopes=token_scopes, required_scope="skills:read", - ) - sv = await self.repo.get_latest(skill_id) - if not sv: - raise NotFoundException("No published versions found") - return sv - - async def delete_version( - self, - skill_id: uuid.UUID, - version_str: str, - current_user_id: str, - is_superuser: bool = False, - token_scopes: Optional[List[str]] = None, - ) -> None: - skill = await self._get_skill_or_404(skill_id) - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.admin, - is_superuser=is_superuser, - token_scopes=token_scopes, required_scope="skills:admin", - ) - sv = await self.repo.get_by_version(skill_id, version_str) - if not sv: - raise NotFoundException(f"Version {version_str} not found") - await self.db.delete(sv) - await self.db.commit() - - async def restore_draft( - self, - skill_id: uuid.UUID, - version_str: str, - current_user_id: str, - is_superuser: bool = False, - token_scopes: Optional[List[str]] = None, - ) -> Skill: - skill = await self._get_skill_or_404(skill_id) - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.publisher, - is_superuser=is_superuser, - token_scopes=token_scopes, required_scope="skills:write", - ) - sv = await self.repo.get_by_version(skill_id, version_str) - if not sv: - raise NotFoundException(f"Version {version_str} not found") - - # Overwrite draft - skill.name = sv.skill_name - skill.description = sv.skill_description - skill.content = sv.content - skill.tags = list(sv.tags) if sv.tags else [] - skill.meta_data = dict(sv.meta_data) if sv.meta_data else {} - skill.allowed_tools = list(sv.allowed_tools) if sv.allowed_tools else [] - skill.compatibility = sv.compatibility - skill.license = sv.license - - # Replace draft files - await self.skill_file_repo.delete_by_skill(skill_id) - version_files = await self.file_repo.list_by_version(sv.id) - for vf in version_files: - sf = SkillFile( - skill_id=skill_id, - path=vf.path, - file_name=vf.file_name, - file_type=vf.file_type, - content=vf.content, - storage_type=vf.storage_type, - storage_key=vf.storage_key, - size=vf.size, - ) - self.db.add(sf) - - await self.db.commit() - await self.db.refresh(skill) - return skill - - async def _get_skill_or_404(self, skill_id: uuid.UUID) -> Skill: - skill = await self.skill_repo.get_with_files(skill_id) - if not skill: - raise NotFoundException("Skill not found") - return skill -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.services.skill_version_service import SkillVersionService; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/services/skill_version_service.py -git commit -m "feat(services): add SkillVersionService with publish/restore/delete" -``` - ---- - -### Task 17: PlatformToken Service - -**Files:** -- Create: `backend/app/services/platform_token_service.py` - -- [ ] **Step 1: Implement service** - -```python -# backend/app/services/platform_token_service.py -"""PlatformToken Service — create, list, revoke.""" - -from __future__ import annotations - -import hashlib -import secrets -import uuid -from datetime import datetime -from typing import List, Optional, Tuple - -from app.common.exceptions import BadRequestException, ForbiddenException, NotFoundException -from app.models.platform_token import PlatformToken -from app.repositories.platform_token import PlatformTokenRepository - -from .base import BaseService - -MAX_ACTIVE_TOKENS_PER_USER = 50 -TOKEN_PREFIX = "sk_" - - -class PlatformTokenService(BaseService[PlatformToken]): - def __init__(self, db): - super().__init__(db) - self.repo = PlatformTokenRepository(db) - - async def create_token( - self, - user_id: str, - name: str, - scopes: List[str], - resource_type: Optional[str] = None, - resource_id: Optional[uuid.UUID] = None, - expires_at: Optional[datetime] = None, - ) -> Tuple[PlatformToken, str]: - """Create a new token. Returns (token_record, plaintext_token).""" - # Check limit - active_count = await self.repo.count_active_by_user(user_id) - if active_count >= MAX_ACTIVE_TOKENS_PER_USER: - raise BadRequestException( - f"Maximum of {MAX_ACTIVE_TOKENS_PER_USER} active tokens reached" - ) - - # Generate token - raw_secret = secrets.token_urlsafe(36) # ~48 chars - plaintext = f"{TOKEN_PREFIX}{raw_secret}" - token_hash = hashlib.sha256(plaintext.encode()).hexdigest() - token_prefix = plaintext[:12] - - pt = PlatformToken( - user_id=user_id, - name=name, - token_hash=token_hash, - token_prefix=token_prefix, - scopes=scopes, - resource_type=resource_type, - resource_id=resource_id, - expires_at=expires_at, - is_active=True, - ) - self.db.add(pt) - await self.db.commit() - await self.db.refresh(pt) - return pt, plaintext - - async def list_tokens(self, user_id: str) -> List[PlatformToken]: - return await self.repo.list_by_user(user_id) - - async def revoke_token( - self, - token_id: uuid.UUID, - user_id: str, - ) -> None: - pt = await self.repo.get(token_id) - if not pt: - raise NotFoundException("Token not found") - if pt.user_id != user_id: - raise ForbiddenException("You can only revoke your own tokens") - pt.is_active = False - await self.db.commit() -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.services.platform_token_service import PlatformTokenService; print('OK')"` -Expected: `OK` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/services/platform_token_service.py -git commit -m "feat(services): add PlatformTokenService with create/list/revoke" -``` - ---- - -### Task 18: Update SkillService — Replace Hardcoded Permission Checks - -**Files:** -- Modify: `backend/app/services/skill_service.py` - -- [ ] **Step 1: Add imports at top of skill_service.py** - -Add after the existing imports: -```python -from app.common.skill_permissions import check_skill_access -from app.models.skill_collaborator import CollaboratorRole -``` - -- [ ] **Step 2: Replace permission checks in `get_skill()`** - -Replace lines 66-68: -```python -# OLD -if skill.owner_id and skill.owner_id != current_user_id and not skill.is_public: - raise ForbiddenException("You don't have permission to access this skill") -``` -with: -```python -# NEW -if current_user_id: - await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.viewer, - ) -elif not skill.is_public: - raise ForbiddenException("You don't have permission to access this skill") -``` - -- [ ] **Step 3: Replace permission check in `update_skill()`** - -Replace lines 310-312: -```python -# OLD -if skill.owner_id != current_user_id: - raise ForbiddenException("You can only update your own skills") -``` -with: -```python -# NEW -await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.editor, -) -``` - -- [ ] **Step 4: Replace permission check in `delete_skill()`** - -Replace lines 473-475: -```python -# OLD -if skill.owner_id != current_user_id: - raise ForbiddenException("You can only delete your own skills") -``` -with: -```python -# NEW — only owner can delete -if skill.owner_id != current_user_id: - raise ForbiddenException("Only the owner can delete a skill") -``` - -(Keep owner-only for delete — spec says owner only.) - -- [ ] **Step 5: Replace permission checks in `add_file()`, `delete_file()`, `update_file()`** - -In `add_file()` (around line 501-503), replace: -```python -if skill.owner_id != current_user_id: - raise ForbiddenException("You can only add files to your own skills") -``` -with: -```python -await check_skill_access( - self.db, skill, current_user_id, CollaboratorRole.editor, -) -``` - -Apply the same pattern to `delete_file()` (around line 559-561) and `update_file()` (around line 583-585). - -- [ ] **Step 6: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.services.skill_service import SkillService; print('OK')"` -Expected: `OK` - -- [ ] **Step 7: Commit** - -```bash -git add backend/app/services/skill_service.py -git commit -m "refactor(services): replace hardcoded owner_id checks with check_skill_access()" -``` - ---- - -### Task 19: Skill Versions API Routes - -**Files:** -- Create: `backend/app/api/v1/skill_versions.py` - -- [ ] **Step 1: Write the route file** - -```python -"""Skill Version API routes.""" - -from __future__ import annotations - -import uuid -from typing import Optional - -from fastapi import APIRouter, Depends -from sqlalchemy.ext.asyncio import AsyncSession - -from app.common.auth_dependency import AuthContext, get_current_user_or_token -from app.common.dependencies import get_current_user -from app.core.database import get_db -from app.models.auth import AuthUser as User -from app.schemas.skill_version import ( - VersionPublishRequest, - VersionRestoreRequest, - VersionSchema, - VersionSummarySchema, -) -from app.services.skill_version_service import SkillVersionService - -router = APIRouter(prefix="/v1/skills", tags=["Skill Versions"]) - - -@router.post("/{skill_id}/versions") -async def publish_version( - skill_id: uuid.UUID, - payload: VersionPublishRequest, - db: AsyncSession = Depends(get_db), - auth: AuthContext = Depends(get_current_user_or_token), -): - """发布新版本(快照当前 draft)。""" - service = SkillVersionService(db) - version = await service.publish_version( - skill_id=skill_id, - current_user_id=auth.user.id, - version_str=payload.version, - release_notes=payload.release_notes, - is_superuser=auth.user.is_superuser, - token_scopes=auth.scopes, - ) - return { - "success": True, - "data": VersionSchema.model_validate(version).model_dump(), - } - - -@router.get("/{skill_id}/versions") -async def list_versions( - skill_id: uuid.UUID, - db: AsyncSession = Depends(get_db), - auth: AuthContext = Depends(get_current_user_or_token), -): - """列出所有已发布版本(按版本号降序)。""" - service = SkillVersionService(db) - versions = await service.list_versions( - skill_id=skill_id, - current_user_id=auth.user.id, - is_superuser=auth.user.is_superuser, - token_scopes=auth.scopes, - ) - return { - "success": True, - "data": [VersionSummarySchema.model_validate(v).model_dump() for v in versions], - } - - -@router.get("/{skill_id}/versions/latest") -async def get_latest_version( - skill_id: uuid.UUID, - db: AsyncSession = Depends(get_db), - auth: AuthContext = Depends(get_current_user_or_token), -): - """获取最新已发布版本详情(含文件)。""" - service = SkillVersionService(db) - version = await service.get_latest_version( - skill_id=skill_id, - current_user_id=auth.user.id, - is_superuser=auth.user.is_superuser, - token_scopes=auth.scopes, - ) - return { - "success": True, - "data": VersionSchema.model_validate(version).model_dump(), - } - - -@router.get("/{skill_id}/versions/{version}") -async def get_version( - skill_id: uuid.UUID, - version: str, - db: AsyncSession = Depends(get_db), - auth: AuthContext = Depends(get_current_user_or_token), -): - """获取特定版本详情(含文件)。""" - service = SkillVersionService(db) - ver = await service.get_version( - skill_id=skill_id, - version_str=version, - current_user_id=auth.user.id, - is_superuser=auth.user.is_superuser, - token_scopes=auth.scopes, - ) - return { - "success": True, - "data": VersionSchema.model_validate(ver).model_dump(), - } - - -@router.delete("/{skill_id}/versions/{version}") -async def delete_version( - skill_id: uuid.UUID, - version: str, - db: AsyncSession = Depends(get_db), - current_user: User = Depends(get_current_user), -): - """删除版本(admin+ 权限,仅 session auth)。""" - service = SkillVersionService(db) - await service.delete_version( - skill_id=skill_id, - version_str=version, - current_user_id=current_user.id, - is_superuser=current_user.is_superuser, - ) - return {"success": True} - - -@router.post("/{skill_id}/restore") -async def restore_version( - skill_id: uuid.UUID, - payload: VersionRestoreRequest, - db: AsyncSession = Depends(get_db), - current_user: User = Depends(get_current_user), -): - """基于历史版本恢复 draft(仅 session auth)。""" - service = SkillVersionService(db) - skill = await service.restore_draft( - skill_id=skill_id, - version_str=payload.version, - current_user_id=current_user.id, - is_superuser=current_user.is_superuser, - ) - from app.schemas.skill import SkillSchema - - return { - "success": True, - "data": SkillSchema.model_validate(skill).model_dump(), - } -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.api.v1.skill_versions import router; print(len(router.routes), 'routes')"` -Expected: `6 routes` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/api/v1/skill_versions.py -git commit -m "feat(api): add skill versions API routes" -``` - ---- - -### Task 20: Skill Collaborators API Routes - -**Files:** -- Create: `backend/app/api/v1/skill_collaborators.py` - -- [ ] **Step 1: Write the route file** - -```python -"""Skill Collaborator API routes.""" - -from __future__ import annotations - -import uuid - -from fastapi import APIRouter, Depends -from sqlalchemy.ext.asyncio import AsyncSession - -from app.common.dependencies import get_current_user -from app.core.database import get_db -from app.models.auth import AuthUser as User -from app.schemas.skill_collaborator import ( - CollaboratorCreate, - CollaboratorSchema, - CollaboratorUpdate, - TransferOwnershipRequest, -) -from app.services.skill_collaborator_service import SkillCollaboratorService - -router = APIRouter(prefix="/v1/skills", tags=["Skill Collaborators"]) - - -@router.get("/{skill_id}/collaborators") -async def list_collaborators( - skill_id: uuid.UUID, - db: AsyncSession = Depends(get_db), - current_user: User = Depends(get_current_user), -): - """列出 skill 的所有协作者。""" - service = SkillCollaboratorService(db) - collaborators = await service.list_collaborators( - skill_id=skill_id, - current_user_id=current_user.id, - is_superuser=current_user.is_superuser, - ) - return { - "success": True, - "data": [CollaboratorSchema.model_validate(c).model_dump() for c in collaborators], - } - - -@router.post("/{skill_id}/collaborators") -async def add_collaborator( - skill_id: uuid.UUID, - payload: CollaboratorCreate, - db: AsyncSession = Depends(get_db), - current_user: User = Depends(get_current_user), -): - """添加协作者(admin+ 权限)。""" - service = SkillCollaboratorService(db) - collaborator = await service.add_collaborator( - skill_id=skill_id, - current_user_id=current_user.id, - target_user_id=payload.user_id, - role=payload.role, - is_superuser=current_user.is_superuser, - ) - return { - "success": True, - "data": CollaboratorSchema.model_validate(collaborator).model_dump(), - } - - -@router.put("/{skill_id}/collaborators/{target_user_id}") -async def update_collaborator( - skill_id: uuid.UUID, - target_user_id: str, - payload: CollaboratorUpdate, - db: AsyncSession = Depends(get_db), - current_user: User = Depends(get_current_user), -): - """修改协作者角色(admin+ 权限)。""" - service = SkillCollaboratorService(db) - collaborator = await service.update_collaborator_role( - skill_id=skill_id, - current_user_id=current_user.id, - target_user_id=target_user_id, - new_role=payload.role, - is_superuser=current_user.is_superuser, - ) - return { - "success": True, - "data": CollaboratorSchema.model_validate(collaborator).model_dump(), - } - - -@router.delete("/{skill_id}/collaborators/{target_user_id}") -async def remove_collaborator( - skill_id: uuid.UUID, - target_user_id: str, - db: AsyncSession = Depends(get_db), - current_user: User = Depends(get_current_user), -): - """移除协作者(admin+ 权限)。""" - service = SkillCollaboratorService(db) - await service.remove_collaborator( - skill_id=skill_id, - current_user_id=current_user.id, - target_user_id=target_user_id, - is_superuser=current_user.is_superuser, - ) - return {"success": True} - - -@router.post("/{skill_id}/transfer") -async def transfer_ownership( - skill_id: uuid.UUID, - payload: TransferOwnershipRequest, - db: AsyncSession = Depends(get_db), - current_user: User = Depends(get_current_user), -): - """转让 ownership(仅 owner 可操作)。""" - service = SkillCollaboratorService(db) - await service.transfer_ownership( - skill_id=skill_id, - current_user_id=current_user.id, - new_owner_id=payload.new_owner_id, - is_superuser=current_user.is_superuser, - ) - return {"success": True} -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.api.v1.skill_collaborators import router; print(len(router.routes), 'routes')"` -Expected: `5 routes` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/api/v1/skill_collaborators.py -git commit -m "feat(api): add skill collaborators API routes" -``` - ---- - -### Task 21: Token API Routes - -**Files:** -- Create: `backend/app/api/v1/tokens.py` - -- [ ] **Step 1: Write the route file** - -```python -"""PlatformToken API routes. - -Token management is session-auth only — PlatformToken cannot manage PlatformToken. -""" - -from __future__ import annotations - -import uuid - -from fastapi import APIRouter, Depends -from sqlalchemy.ext.asyncio import AsyncSession - -from app.common.dependencies import get_current_user -from app.core.database import get_db -from app.models.auth import AuthUser as User -from app.schemas.platform_token import ( - TokenCreate, - TokenCreateResponse, - TokenSchema, -) -from app.services.platform_token_service import PlatformTokenService - -router = APIRouter(prefix="/v1/tokens", tags=["Tokens"]) - - -@router.post("") -async def create_token( - payload: TokenCreate, - db: AsyncSession = Depends(get_db), - current_user: User = Depends(get_current_user), -): - """创建 token(返回明文,仅此一次)。""" - service = PlatformTokenService(db) - token_record, raw_token = await service.create_token( - user_id=current_user.id, - name=payload.name, - scopes=payload.scopes, - resource_type=payload.resource_type, - resource_id=payload.resource_id, - expires_at=payload.expires_at, - ) - resp = TokenCreateResponse.model_validate(token_record) - # Inject the raw token (not stored in DB) - data = resp.model_dump() - data["token"] = raw_token - return {"success": True, "data": data} - - -@router.get("") -async def list_tokens( - db: AsyncSession = Depends(get_db), - current_user: User = Depends(get_current_user), -): - """列出我的 tokens(不含明文,显示 prefix)。""" - service = PlatformTokenService(db) - tokens = await service.list_tokens(user_id=current_user.id) - return { - "success": True, - "data": [TokenSchema.model_validate(t).model_dump() for t in tokens], - } - - -@router.delete("/{token_id}") -async def revoke_token( - token_id: uuid.UUID, - db: AsyncSession = Depends(get_db), - current_user: User = Depends(get_current_user), -): - """撤销 token(soft delete: is_active = False)。""" - service = PlatformTokenService(db) - await service.revoke_token(token_id=token_id, user_id=current_user.id) - return {"success": True} -``` - -- [ ] **Step 2: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.api.v1.tokens import router; print(len(router.routes), 'routes')"` -Expected: `3 routes` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/api/v1/tokens.py -git commit -m "feat(api): add platform token API routes" -``` - ---- - -### Task 22: Register New Routers - -**Files:** -- Modify: `backend/app/api/v1/__init__.py` - -- [ ] **Step 1: Add imports** - -After `from .skills import router as skills_router` (line 31), add: - -```python -from .skill_collaborators import router as skill_collaborators_router -from .skill_versions import router as skill_versions_router -from .tokens import router as tokens_router -``` - -- [ ] **Step 2: Add to ROUTERS list** - -After `skills_router,` (line 58), add: - -```python - skill_versions_router, - skill_collaborators_router, - tokens_router, -``` - -- [ ] **Step 3: Verify import** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.api.v1 import api_router; print(len(api_router.routes), 'total routes')"` -Expected: prints route count (should be previous count + 14 new routes) - -- [ ] **Step 4: Commit** - -```bash -git add backend/app/api/v1/__init__.py -git commit -m "feat(api): register skill versions, collaborators, and token routers" -``` - ---- - -### Task 23: Update SkillSchema — Add `latest_version` Field - -**Files:** -- Modify: `backend/app/schemas/skill.py:65-133` - -- [ ] **Step 1: Add `latest_version` to SkillSchema** - -In `SkillSchema` class (line 65), add a new optional field after `files`: - -```python - files: Optional[List[SkillFileSchema]] = None - latest_version: Optional[str] = None -``` - -- [ ] **Step 2: Update `map_meta_data_from_attributes` validator** - -In the `model_validator` method (line 103-129), update the loop that gets extra attributes (line 120) to include `latest_version`: - -Replace: -```python - for key in ["id", "created_at", "updated_at", "files"]: -``` -with: -```python - for key in ["id", "created_at", "updated_at", "files", "latest_version"]: -``` - -- [ ] **Step 3: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.schemas.skill import SkillSchema; print(SkillSchema.model_fields.keys())"` -Expected: includes `latest_version` - -- [ ] **Step 4: Commit** - -```bash -git add backend/app/schemas/skill.py -git commit -m "feat(schemas): add latest_version field to SkillSchema" -``` - ---- - -### Task 24: Populate `latest_version` in SkillService - -**Files:** -- Modify: `backend/app/services/skill_service.py` - -Note: Task 11 already handles the `list_by_user()` collaborator subquery. This task adds `latest_version` population. - -- [ ] **Step 1: Add helper to populate latest_version** - -In `SkillService`, add a helper method: - -```python -from app.repositories.skill_version import SkillVersionRepository - -async def _attach_latest_version(self, skill): - """Attach latest_version string to skill for API response.""" - ver_repo = SkillVersionRepository(self.db) - latest = await ver_repo.get_latest(skill.id) - skill.latest_version = latest.version if latest else None - return skill -``` - -- [ ] **Step 2: Call helper in `get_skill()`** - -At the end of `get_skill()`, before returning the skill, call: -```python -skill = await self._attach_latest_version(skill) -``` - -- [ ] **Step 3: Verify syntax** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -c "from app.services.skill_service import SkillService; print('OK')"` -Expected: `OK` - -- [ ] **Step 4: Commit** - -```bash -git add backend/app/services/skill_service.py -git commit -m "feat(services): populate latest_version on skill responses" -``` - ---- - -### Task 25: Unit Tests — Skill Permissions Utility - -**Files:** -- Create: `backend/tests/test_services/__init__.py` -- Create: `backend/tests/test_services/test_skill_permissions.py` - -- [ ] **Step 1: Create `__init__.py`** - -```python -# (empty) -``` - -- [ ] **Step 2: Write tests for `check_skill_access`** - -```python -"""Unit tests for check_skill_access permission utility.""" - -from __future__ import annotations - -import uuid -from unittest.mock import AsyncMock, MagicMock - -import pytest - -from app.common.skill_permissions import check_skill_access -from app.models.skill_collaborator import CollaboratorRole - - -def _mock_skill(owner_id: str = "owner-1", is_public: bool = False): - s = MagicMock() - s.id = uuid.uuid4() - s.owner_id = owner_id - s.is_public = is_public - return s - - -def _mock_db(collaborator_role=None): - """Return an AsyncMock db session. - - If collaborator_role is given, simulate a SkillCollaborator record. - """ - db = AsyncMock() - result_mock = MagicMock() - if collaborator_role is not None: - collab = MagicMock() - collab.role = collaborator_role - result_mock.scalar_one_or_none.return_value = collab - else: - result_mock.scalar_one_or_none.return_value = None - db.execute.return_value = result_mock - return db - - -class TestCheckSkillAccess: - """Verify the unified permission checking logic.""" - - @pytest.mark.asyncio - async def test_owner_always_passes(self): - skill = _mock_skill(owner_id="user-1") - db = _mock_db() - # Owner should pass even with admin requirement - await check_skill_access(db, skill, "user-1", CollaboratorRole.admin) - - @pytest.mark.asyncio - async def test_superuser_always_passes(self): - skill = _mock_skill(owner_id="other") - db = _mock_db() - # Superuser bypasses all role checks via is_superuser param - await check_skill_access( - db, skill, "superadmin", CollaboratorRole.admin, - is_superuser=True, - ) - - @pytest.mark.asyncio - async def test_collaborator_with_sufficient_role(self): - skill = _mock_skill(owner_id="other") - db = _mock_db(collaborator_role=CollaboratorRole.editor) - await check_skill_access(db, skill, "collab-1", CollaboratorRole.editor) - - @pytest.mark.asyncio - async def test_collaborator_with_insufficient_role(self): - skill = _mock_skill(owner_id="other") - db = _mock_db(collaborator_role=CollaboratorRole.viewer) - from app.common.exceptions import ForbiddenException - - with pytest.raises(ForbiddenException): - await check_skill_access(db, skill, "collab-1", CollaboratorRole.editor) - - @pytest.mark.asyncio - async def test_public_skill_viewer_access(self): - skill = _mock_skill(owner_id="other", is_public=True) - db = _mock_db() - await check_skill_access(db, skill, "random-user", CollaboratorRole.viewer) - - @pytest.mark.asyncio - async def test_public_skill_edit_denied(self): - skill = _mock_skill(owner_id="other", is_public=True) - db = _mock_db() - from app.common.exceptions import ForbiddenException - - with pytest.raises(ForbiddenException): - await check_skill_access(db, skill, "random-user", CollaboratorRole.editor) - - @pytest.mark.asyncio - async def test_no_access_denied(self): - skill = _mock_skill(owner_id="other", is_public=False) - db = _mock_db() - from app.common.exceptions import ForbiddenException - - with pytest.raises(ForbiddenException): - await check_skill_access(db, skill, "stranger", CollaboratorRole.viewer) -``` - -- [ ] **Step 3: Run tests** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -m pytest tests/test_services/test_skill_permissions.py -v` -Expected: All 7 tests pass - -- [ ] **Step 4: Commit** - -```bash -git add backend/tests/test_services/ -git commit -m "test: add unit tests for check_skill_access permission utility" -``` - ---- - -### Task 26: Unit Tests — Skill Version Service - -**Files:** -- Create: `backend/tests/test_services/test_skill_version_service.py` - -- [ ] **Step 1: Write tests** - -```python -"""Unit tests for SkillVersionService.""" - -from __future__ import annotations - -import uuid -from unittest.mock import AsyncMock, MagicMock, patch - -import pytest - - -def _mock_skill(owner_id="user-1", name="test-skill", content="body"): - s = MagicMock() - s.id = uuid.uuid4() - s.owner_id = owner_id - s.name = name - s.description = "desc" - s.content = content - s.tags = ["a"] - s.meta_data = {} - s.allowed_tools = [] - s.compatibility = None - s.license = None - s.is_public = False - s.files = [] - return s - - -def _mock_db(): - db = AsyncMock() - db.commit = AsyncMock() - db.flush = AsyncMock() - db.refresh = AsyncMock() - db.add = MagicMock() - return db - - -class TestSkillVersionServicePublish: - """Test version publishing logic.""" - - @pytest.mark.asyncio - async def test_publish_validates_semver_format(self): - """Invalid semver should raise BadRequestException.""" - from app.common.exceptions import BadRequestException - - db = _mock_db() - skill = _mock_skill() - with patch("app.services.skill_version_service.SkillRepository") as MockSkillRepo, \ - patch("app.services.skill_version_service.SkillVersionRepository") as MockVerRepo, \ - patch("app.services.skill_version_service.check_skill_access", new_callable=AsyncMock): - MockSkillRepo.return_value.get.return_value = skill - from app.services.skill_version_service import SkillVersionService - - service = SkillVersionService(db) - with pytest.raises(BadRequestException, match="semver"): - await service.publish_version( - skill_id=skill.id, user_id="user-1", - version="invalid", release_notes="", - ) - - @pytest.mark.asyncio - async def test_publish_rejects_lower_version(self): - """New version must be greater than existing highest.""" - from app.common.exceptions import BadRequestException - - db = _mock_db() - skill = _mock_skill() - existing_version = MagicMock() - existing_version.version = "2.0.0" - - with patch("app.services.skill_version_service.SkillRepository") as MockSkillRepo, \ - patch("app.services.skill_version_service.SkillVersionRepository") as MockVerRepo, \ - patch("app.services.skill_version_service.check_skill_access", new_callable=AsyncMock): - MockSkillRepo.return_value.get.return_value = skill - MockVerRepo.return_value.get_latest_version.return_value = existing_version - from app.services.skill_version_service import SkillVersionService - - service = SkillVersionService(db) - with pytest.raises(BadRequestException, match="greater"): - await service.publish_version( - skill_id=skill.id, user_id="user-1", - version="1.0.0", release_notes="", - ) -``` - -- [ ] **Step 2: Run tests** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -m pytest tests/test_services/test_skill_version_service.py -v` -Expected: All 2 tests pass - -- [ ] **Step 3: Commit** - -```bash -git add backend/tests/test_services/test_skill_version_service.py -git commit -m "test: add unit tests for SkillVersionService publish logic" -``` - ---- - -### Task 27: Unit Tests — Platform Token Service - -**Files:** -- Create: `backend/tests/test_services/test_platform_token_service.py` - -- [ ] **Step 1: Write tests** - -```python -"""Unit tests for PlatformTokenService.""" - -from __future__ import annotations - -import uuid -from unittest.mock import AsyncMock, MagicMock, patch - -import pytest - - -def _mock_db(): - db = AsyncMock() - db.commit = AsyncMock() - db.flush = AsyncMock() - db.refresh = AsyncMock() - db.add = MagicMock() - return db - - -class TestPlatformTokenServiceCreate: - """Test token creation logic.""" - - @pytest.mark.asyncio - async def test_create_returns_raw_token_starting_with_sk(self): - """Created token should start with 'sk_' prefix.""" - db = _mock_db() - with patch("app.services.platform_token_service.PlatformTokenRepository") as MockRepo: - MockRepo.return_value.count_active_by_user.return_value = 0 - MockRepo.return_value.create.return_value = MagicMock( - id=uuid.uuid4(), - token_prefix="sk_testprefix", - ) - db.refresh = AsyncMock() - from app.services.platform_token_service import PlatformTokenService - - service = PlatformTokenService(db) - record, raw_token = await service.create_token( - user_id="user-1", - name="test", - scopes=["skills:read"], - ) - assert raw_token.startswith("sk_") - assert len(raw_token) > 12 - - @pytest.mark.asyncio - async def test_create_rejects_when_limit_exceeded(self): - """Should raise BadRequestException when user has 50 active tokens.""" - from app.common.exceptions import BadRequestException - - db = _mock_db() - with patch("app.services.platform_token_service.PlatformTokenRepository") as MockRepo: - MockRepo.return_value.count_active_by_user.return_value = 50 - from app.services.platform_token_service import PlatformTokenService - - service = PlatformTokenService(db) - with pytest.raises(BadRequestException, match="50"): - await service.create_token( - user_id="user-1", - name="test", - scopes=["skills:read"], - ) - - -class TestPlatformTokenServiceRevoke: - """Test token revocation logic.""" - - @pytest.mark.asyncio - async def test_revoke_sets_inactive(self): - """Revoke should set is_active to False.""" - db = _mock_db() - token = MagicMock() - token.id = uuid.uuid4() - token.user_id = "user-1" - token.is_active = True - with patch("app.services.platform_token_service.PlatformTokenRepository") as MockRepo: - MockRepo.return_value.get.return_value = token - from app.services.platform_token_service import PlatformTokenService - - service = PlatformTokenService(db) - await service.revoke_token(token_id=token.id, user_id="user-1") - assert token.is_active is False - - @pytest.mark.asyncio - async def test_revoke_wrong_user_denied(self): - """Should raise ForbiddenException when revoking another user's token.""" - from app.common.exceptions import ForbiddenException - - db = _mock_db() - token = MagicMock() - token.id = uuid.uuid4() - token.user_id = "user-1" - token.is_active = True - with patch("app.services.platform_token_service.PlatformTokenRepository") as MockRepo: - MockRepo.return_value.get.return_value = token - from app.services.platform_token_service import PlatformTokenService - - service = PlatformTokenService(db) - with pytest.raises(ForbiddenException): - await service.revoke_token(token_id=token.id, user_id="user-2") -``` - -- [ ] **Step 2: Run tests** - -Run: `cd /Users/yuzhenjiang1/Downloads/workspace/JoySafeter/backend && python -m pytest tests/test_services/test_platform_token_service.py -v` -Expected: All 4 tests pass - -- [ ] **Step 3: Commit** - -```bash -git add backend/tests/test_services/test_platform_token_service.py -git commit -m "test: add unit tests for PlatformTokenService" -``` - ---- - -## Summary - -| Task | Component | Files | -|------|-----------|-------| -| 1 | CollaboratorRole enum + SkillCollaborator model | `models/skill_collaborator.py` | -| 2 | SkillVersion + SkillVersionFile models | `models/skill_version.py` | -| 3 | PlatformToken model | `models/platform_token.py` | -| 4 | Register models in `__init__` | `models/__init__.py` | -| 5 | Alembic migration | `alembic/versions/...` | -| 6 | Skill permissions utility | `common/skill_permissions.py` | -| 7 | Dual-mode auth dependency | `common/auth_dependency.py` | -| 8 | SkillCollaborator repository | `repositories/skill_collaborator.py` | -| 9 | SkillVersion + SkillVersionFile repository | `repositories/skill_version.py` | -| 10 | PlatformToken repository | `repositories/platform_token.py` | -| 11 | Extend `list_by_user()` with collaborator subquery | `repositories/skill.py` | -| 12 | SkillCollaborator schemas | `schemas/skill_collaborator.py` | -| 13 | SkillVersion schemas | `schemas/skill_version.py` | -| 14 | PlatformToken schemas | `schemas/platform_token.py` | -| 15 | SkillCollaboratorService | `services/skill_collaborator_service.py` | -| 16 | SkillVersionService | `services/skill_version_service.py` | -| 17 | PlatformTokenService | `services/platform_token_service.py` | -| 18 | Update SkillService permission checks | `services/skill_service.py` | -| 19 | Skill Versions API routes | `api/v1/skill_versions.py` | -| 20 | Skill Collaborators API routes | `api/v1/skill_collaborators.py` | -| 21 | Token API routes | `api/v1/tokens.py` | -| 22 | Register new routers | `api/v1/__init__.py` | -| 23 | SkillSchema `latest_version` field | `schemas/skill.py` | -| 24 | Populate `latest_version` in SkillService | `services/skill_service.py` | -| 25 | Tests — skill permissions | `tests/test_services/test_skill_permissions.py` | -| 26 | Tests — version service | `tests/test_services/test_skill_version_service.py` | -| 27 | Tests — token service | `tests/test_services/test_platform_token_service.py` | diff --git a/docs/superpowers/plans/2026-03-21-chat-layout-interaction-alignment.md b/docs/superpowers/plans/2026-03-21-chat-layout-interaction-alignment.md deleted file mode 100644 index 23b48277f..000000000 --- a/docs/superpowers/plans/2026-03-21-chat-layout-interaction-alignment.md +++ /dev/null @@ -1,731 +0,0 @@ -# Chat Layout & Interaction Alignment Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Align the Chat page's layout structure and interaction patterns with the Skill page by refactoring the sidebar, upgrading mode cards, and redesigning the input area. - -**Architecture:** Extract duplicated sidebar JSX into a reusable `ConversationGroup` component, replace conditional DOM mount/unmount with `ResizablePanel` collapsible animation, upgrade mode card styling to match SkillCard, and compact the input area to match Skill Creator's gray-bg pill pattern. - -**Tech Stack:** Next.js, React, Tailwind CSS, react-resizable-panels, lucide-react, shadcn/ui AlertDialog - -**Spec:** `docs/superpowers/specs/2026-03-21-chat-layout-interaction-alignment-design.md` - -**Verification:** No test infrastructure exists in frontend. All verification is visual — run `npm run dev` from `frontend/` and check the Chat page in browser. - ---- - -## File Structure - -| File | Action | Responsibility | -|------|--------|---------------| -| `frontend/app/chat/components/ConversationGroup.tsx` | Create | `ConversationItem` + `ConversationGroup` — extracted sidebar row + group | -| `frontend/app/chat/components/ChatSidebar.tsx` | Modify | Use `ConversationGroup` instead of 3 duplicated blocks | -| `frontend/app/chat/hooks/useChatReducer.ts` | Modify | Add `SET_SIDEBAR_VISIBLE` action | -| `frontend/app/chat/ChatLayout.tsx` | Modify | Collapsible sidebar panel with ref-based toggle | -| `frontend/app/chat/components/ChatHome.tsx` | Modify | Mode card styling + input area compaction | -| `frontend/app/chat/components/ChatInput.tsx` | Modify | Input area compaction | -| `frontend/app/chat/conversation/ConversationPanel.tsx` | Modify | Input wrapper styling | - ---- - -### Task 1: Extract ConversationGroup Component (Area 1) - -**Files:** -- Create: `frontend/app/chat/components/ConversationGroup.tsx` -- Modify: `frontend/app/chat/components/ChatSidebar.tsx` - -- [ ] **Step 1: Create `ConversationGroup.tsx` with both components** - -Create `frontend/app/chat/components/ConversationGroup.tsx`: - -```tsx -'use client' - -import { MessageSquare, Trash2, ChevronDown, ChevronRight } from 'lucide-react' - -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, - AlertDialogTrigger, -} from '@/components/ui/alert-dialog' -import { cn } from '@/lib/utils' -import { useTranslation } from '@/lib/i18n' - -interface Conversation { - thread_id: string - title: string - updated_at: string -} - -interface ConversationItemProps { - conv: Conversation - isActive: boolean - isCollapsed: boolean - onSelect: (threadId: string) => void - onDeleteClick: (e: React.MouseEvent, threadId: string, title: string) => void - formatTime: (date: string) => string - deleteConfirmOpen: boolean - conversationToDelete: { threadId: string; title: string } | null - onDeleteConfirmChange: (open: boolean) => void - onConfirmDelete: () => void - onCancelDelete: () => void -} - -function ConversationItem({ - conv, - isActive, - isCollapsed, - onSelect, - onDeleteClick, - formatTime, - deleteConfirmOpen, - conversationToDelete, - onDeleteConfirmChange, - onConfirmDelete, - onCancelDelete, -}: ConversationItemProps) { - const { t } = useTranslation() - - if (isCollapsed) { - return ( -
onSelect(conv.thread_id)} - title={conv.title || t('chat.untitled')} - > - -
- ) - } - - return ( -
onSelect(conv.thread_id)} - > - -
-

- {conv.title || t('chat.untitled')} -

-

{formatTime(conv.updated_at)}

-
- - - - - - - {t('chat.deleteConversation')} - - {t('chat.deleteConversationConfirm', { - title: conversationToDelete?.title || t('chat.untitled'), - })} - - - - {t('common.cancel')} - - {t('common.delete')} - - - - -
- ) -} - -interface ConversationGroupProps { - label: string - conversations: Conversation[] - isExpanded: boolean - onToggleExpand: () => void - isCollapsed: boolean - currentThreadId: string | null - onSelectConversation: (threadId: string) => void - onDeleteClick: (e: React.MouseEvent, threadId: string, title: string) => void - formatTime: (date: string) => string - maxItems?: number - deleteConfirmOpen: boolean - conversationToDelete: { threadId: string; title: string } | null - onDeleteConfirmChange: (open: boolean) => void - onConfirmDelete: () => void - onCancelDelete: () => void -} - -export default function ConversationGroup({ - label, - conversations, - isExpanded, - onToggleExpand, - isCollapsed, - currentThreadId, - onSelectConversation, - onDeleteClick, - formatTime, - maxItems, - deleteConfirmOpen, - conversationToDelete, - onDeleteConfirmChange, - onConfirmDelete, - onCancelDelete, -}: ConversationGroupProps) { - if (conversations.length === 0) return null - - const displayConversations = maxItems ? conversations.slice(0, maxItems) : conversations - - return ( -
- {!isCollapsed && ( - - )} - {(isExpanded || isCollapsed) && ( -
- {displayConversations.map((conv) => ( - - ))} -
- )} -
- ) -} -``` - -- [ ] **Step 2: Refactor ChatSidebar to use ConversationGroup** - -In `frontend/app/chat/components/ChatSidebar.tsx`: - -**2a.** Add import at top (after other imports): -```tsx -import ConversationGroup from './ConversationGroup' -``` - -**2b.** Replace the three state variables (lines 81-83): -```tsx -// Before: -const [isTodayCollapsed, setIsTodayCollapsed] = useState(false) -const [isThisMonthCollapsed, setIsThisMonthCollapsed] = useState(true) -const [isOlderCollapsed, setIsOlderCollapsed] = useState(true) - -// After: -const [isTodayExpanded, setIsTodayExpanded] = useState(true) -const [isThisMonthExpanded, setIsThisMonthExpanded] = useState(false) -const [isOlderExpanded, setIsOlderExpanded] = useState(false) -``` - -**2c.** Replace the entire conversation list section (the three groups of todayConvs, monthConvs, olderConvs — approximately lines 185-535) with: - -```tsx - setIsTodayExpanded(!isTodayExpanded)} - isCollapsed={isCollapsed} - currentThreadId={currentThreadId} - onSelectConversation={onSelectConversation} - onDeleteClick={handleDeleteConversation} - formatTime={formatTime} - deleteConfirmOpen={deleteConfirmOpen} - conversationToDelete={conversationToDelete} - onDeleteConfirmChange={setDeleteConfirmOpen} - onConfirmDelete={handleConfirmDelete} - onCancelDelete={handleCancelDelete} -/> - setIsThisMonthExpanded(!isThisMonthExpanded)} - isCollapsed={isCollapsed} - currentThreadId={currentThreadId} - onSelectConversation={onSelectConversation} - onDeleteClick={handleDeleteConversation} - formatTime={formatTime} - deleteConfirmOpen={deleteConfirmOpen} - conversationToDelete={conversationToDelete} - onDeleteConfirmChange={setDeleteConfirmOpen} - onConfirmDelete={handleConfirmDelete} - onCancelDelete={handleCancelDelete} -/> - setIsOlderExpanded(!isOlderExpanded)} - isCollapsed={isCollapsed} - currentThreadId={currentThreadId} - onSelectConversation={onSelectConversation} - onDeleteClick={handleDeleteConversation} - formatTime={formatTime} - maxItems={10} - deleteConfirmOpen={deleteConfirmOpen} - conversationToDelete={conversationToDelete} - onDeleteConfirmChange={setDeleteConfirmOpen} - onConfirmDelete={handleConfirmDelete} - onCancelDelete={handleCancelDelete} -/> -``` - -**2d.** Remove unused imports that were only used by the inlined conversation rows: `MessageSquare`, `Trash2`, `ChevronDown`, `ChevronRight` (if no longer referenced elsewhere in the file), and remove all `AlertDialog*` imports. - -**2e.** The existing `handleDeleteConversation` handler (line 101) is kept as-is. Add two new handlers for confirm/cancel if they don't exist: - -```tsx -const handleConfirmDelete = async () => { - if (conversationToDelete) { - await deleteConversation(conversationToDelete.threadId) - } - setDeleteConfirmOpen(false) - setConversationToDelete(null) -} - -const handleCancelDelete = () => { - setDeleteConfirmOpen(false) - setConversationToDelete(null) -} -``` - -Check the existing code — if `handleConfirmDelete` already exists with this logic inline in the AlertDialog, extract it. If `handleCancelDelete` logic is inline, extract it too. - -- [ ] **Step 3: Visual verification** - -Run: `cd frontend && npm run dev` - -Check: -- Sidebar shows three conversation groups (Today, This Month, Older) -- Clicking group headers expands/collapses them -- Today and This Month start expanded, Older starts collapsed -- Conversation rows show icon, title, time, delete button on hover -- Delete confirmation dialog works -- Active conversation is highlighted in blue - -- [ ] **Step 4: Commit** - -```bash -git add frontend/app/chat/components/ConversationGroup.tsx frontend/app/chat/components/ChatSidebar.tsx -git commit -m "refactor: extract ConversationGroup component from ChatSidebar to deduplicate conversation row JSX" -``` - ---- - -### Task 2: Sidebar Collapse Animation (Area 2) - -**Files:** -- Modify: `frontend/app/chat/hooks/useChatReducer.ts` -- Modify: `frontend/app/chat/ChatLayout.tsx` - -- [ ] **Step 1: Add `SET_SIDEBAR_VISIBLE` action to reducer** - -In `frontend/app/chat/hooks/useChatReducer.ts`: - -**1a.** Add to the `ChatAction` type union (near line 95 where other actions are defined): -```tsx -| { type: 'SET_SIDEBAR_VISIBLE'; visible: boolean } -``` - -**1b.** Add reducer case (near `TOGGLE_SIDEBAR` case around line 266): -```tsx -case 'SET_SIDEBAR_VISIBLE': - return { ...state, ui: { ...state.ui, sidebarVisible: action.visible } } -``` - -- [ ] **Step 2: Refactor ChatLayout sidebar to use collapsible panel** - -In `frontend/app/chat/ChatLayout.tsx`: - -**2a.** Update imports — add `ImperativePanelHandle` from `react-resizable-panels` and `useRef` is already imported: -```tsx -// Before (line 8): -import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@/components/ui/resizable' - -// After: -import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@/components/ui/resizable' -import type { ImperativePanelHandle } from 'react-resizable-panels' -``` - -**2b.** Add panel ref after other refs (around line 44): -```tsx -const sidebarPanelRef = useRef(null) -``` - -**2c.** Replace the Cmd+B shortcut handler (lines 48-57): -```tsx -// Before: -useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - if ((e.metaKey || e.ctrlKey) && e.key === 'b') { - e.preventDefault() - dispatch({ type: 'TOGGLE_SIDEBAR' }) - } - } - window.addEventListener('keydown', handleKeyDown) - return () => window.removeEventListener('keydown', handleKeyDown) -}, [dispatch]) - -// After: -useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - if ((e.metaKey || e.ctrlKey) && e.key === 'b') { - e.preventDefault() - if (state.ui.sidebarVisible) { - sidebarPanelRef.current?.collapse() - } else { - sidebarPanelRef.current?.expand() - } - } - } - window.addEventListener('keydown', handleKeyDown) - return () => window.removeEventListener('keydown', handleKeyDown) -}, [state.ui.sidebarVisible]) -``` - -**2d.** Replace the header toggle button onClick (line 258): -```tsx -// Before: -onClick={() => dispatch({ type: 'TOGGLE_SIDEBAR' })} - -// After: -onClick={() => { - if (state.ui.sidebarVisible) { - sidebarPanelRef.current?.collapse() - } else { - sidebarPanelRef.current?.expand() - } -}} -``` - -**2e.** Replace the sidebar panel section (lines 322-341): -```tsx -// Before: -{state.ui.sidebarVisible && ( - <> - - dispatch({ type: 'TOGGLE_SIDEBAR' })} - onSelectConversation={handleSelectConversation} - currentThreadId={state.threadId} - onNewChat={handleNewChat} - /> - - - -)} - -// After: - dispatch({ type: 'SET_SIDEBAR_VISIBLE', visible: false })} - onExpand={() => dispatch({ type: 'SET_SIDEBAR_VISIBLE', visible: true })} - className="overflow-hidden transition-all duration-300" -> - { - if (state.ui.sidebarVisible) { - sidebarPanelRef.current?.collapse() - } else { - sidebarPanelRef.current?.expand() - } - }} - onSelectConversation={handleSelectConversation} - currentThreadId={state.threadId} - onNewChat={handleNewChat} - /> - - -``` - -- [ ] **Step 3: Visual verification** - -Run: `cd frontend && npm run dev` - -Check: -- Sidebar toggle button collapses/expands the sidebar -- Cmd+B shortcut works -- Sidebar animates (or at least doesn't flash/unmount) -- When collapsed, sidebar takes zero width -- ResizableHandle remains visible as panel edge -- Sidebar isCollapsed prop now triggers icon-only mode in ChatSidebar (if collapsed while visible) - -- [ ] **Step 4: Commit** - -```bash -git add frontend/app/chat/hooks/useChatReducer.ts frontend/app/chat/ChatLayout.tsx -git commit -m "feat: replace sidebar mount/unmount with ResizablePanel collapsible animation" -``` - ---- - -### Task 3: Mode Card Beautification (Area 3) - -**Files:** -- Modify: `frontend/app/chat/components/ChatHome.tsx` - -- [ ] **Step 1: Update mode card container className** - -In `frontend/app/chat/components/ChatHome.tsx`, find the mode card `className` (around line 644-648): - -```tsx -// Before: -'group flex cursor-pointer items-start gap-4 rounded-xl border p-4 transition-all', -isSelected - ? 'border-blue-500 bg-blue-50 shadow-md ring-1 ring-blue-100' - : 'border-gray-200 bg-white hover:border-blue-300 hover:shadow-md', - -// After: -'group flex cursor-pointer items-start gap-4 overflow-hidden rounded-xl border bg-white p-4 transition-all duration-200', -isSelected - ? 'border-blue-500 bg-blue-50 shadow-md ring-1 ring-blue-100' - : 'border-gray-200 hover:border-blue-200 hover:shadow-lg', -``` - -- [ ] **Step 2: Update icon container className** - -Find the icon container inside each card (around line 651-654): - -```tsx -// Before: -
- -// After: -
-``` - -- [ ] **Step 3: Visual verification** - -Run: `cd frontend && npm run dev` - -Navigate to Chat home page. Check: -- Mode cards have smooth `duration-200` hover transition -- Hover shows `shadow-lg` and `border-blue-200` (softer than before) -- Icon containers are uniformly blue (`bg-blue-50` with `border-blue-100`) regardless of selected state -- Selected card still shows blue ring and blue background -- Cards have `overflow-hidden` - -- [ ] **Step 4: Commit** - -```bash -git add frontend/app/chat/components/ChatHome.tsx -git commit -m "style: upgrade mode card styling to match SkillCard design language" -``` - ---- - -### Task 4: Input Area Alignment (Area 4) - -**Files:** -- Modify: `frontend/app/chat/conversation/ConversationPanel.tsx` -- Modify: `frontend/app/chat/components/ChatInput.tsx` -- Modify: `frontend/app/chat/components/ChatHome.tsx` - -- [ ] **Step 1: Update ConversationPanel input wrapper** - -In `frontend/app/chat/conversation/ConversationPanel.tsx` line 76: - -```tsx -// Before: -
- -// After: -
-``` - -- [ ] **Step 2: Update ChatInput container** - -In `frontend/app/chat/components/ChatInput.tsx` line 134: - -```tsx -// Before: -'flex items-end gap-3 rounded-[24px] border border-gray-200 bg-white p-4 shadow-md transition-all', - -// After: -'flex items-end gap-2 rounded-2xl border border-gray-200 bg-gray-50 px-4 py-3 transition-all', -``` - -- [ ] **Step 3: Update ChatInput textarea** - -In `frontend/app/chat/components/ChatInput.tsx` line 157: - -```tsx -// Before: -className="max-h-[200px] min-h-[100px] flex-1 resize-none overflow-y-auto border-none bg-transparent px-0.5 pb-6 pt-4 text-base shadow-none placeholder:text-gray-400 focus:outline-none focus-visible:ring-0" - -// After: -className="max-h-[160px] min-h-[24px] flex-1 resize-none overflow-y-auto border-none bg-transparent text-sm shadow-none placeholder:text-gray-400 focus:outline-none focus-visible:ring-0" -``` - -- [ ] **Step 4: Update ChatInput buttons** - -In `frontend/app/chat/components/ChatInput.tsx`: - -Attach button (line 169): change `h-10 w-10 rounded-2xl` to `h-8 w-8 rounded-xl` -Stop button (line 180): change `h-10 w-10` to `h-8 w-8` -Send button (line 191): change `h-10 w-10` to `h-8 w-8` - -- [ ] **Step 5: Update ChatInput auto-resize cap** - -In `frontend/app/chat/components/ChatInput.tsx` line 58: - -```tsx -// Before: -textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 200)}px` - -// After: -textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 160)}px` -``` - -- [ ] **Step 6: Update ChatHome input outer container** - -In `frontend/app/chat/components/ChatHome.tsx` around line 419: - -```tsx -// Before: -
- -// After: -
-``` - -- [ ] **Step 7: Update ChatHome input inner container** - -In `frontend/app/chat/components/ChatHome.tsx` around line 420: - -```tsx -// Before: -
- -// After: -
-``` - -- [ ] **Step 8: Update ChatHome textarea** - -In `frontend/app/chat/components/ChatHome.tsx` around line 480: - -```tsx -// Before: -className="max-h-[240px] min-h-[120px] w-full resize-none overflow-y-auto border-none bg-transparent px-1 pb-14 pt-5 text-base shadow-none transition-all duration-200 placeholder:text-gray-400 focus:outline-none focus-visible:ring-0" - -// After: -className="max-h-[160px] min-h-[24px] w-full resize-none overflow-y-auto border-none bg-transparent text-sm shadow-none placeholder:text-gray-400 focus:outline-none focus-visible:ring-0" -``` - -- [ ] **Step 9: Update ChatHome bottom buttons position** - -In `frontend/app/chat/components/ChatHome.tsx` around line 484, the absolutely-positioned buttons container: - -```tsx -// Before: -absolute bottom-2 left-1 - -// After: -absolute bottom-1 left-1 -``` - -- [ ] **Step 10: Update ChatHome buttons size** - -In `frontend/app/chat/components/ChatHome.tsx` (lines 552-609), change all button sizes: - -All `h-10 w-10` → `h-8 w-8` (attach, stop, send buttons) - -- [ ] **Step 11: Update ChatHome auto-resize cap** - -In `frontend/app/chat/components/ChatHome.tsx` around line 137: - -```tsx -// Before: -textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 200)}px` - -// After: -textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 160)}px` -``` - -- [ ] **Step 12: Visual verification** - -Run: `cd frontend && npm run dev` - -Check Chat home page: -- Input area uses gray background (`bg-gray-50`) -- Input is compact — no oversized textarea -- Buttons are smaller (`h-8 w-8`) -- No bottom overflow on small viewports -- Text is `text-sm` (not `text-base`) -- Bottom buttons don't overlap text content - -Check Chat conversation page: -- Input wrapper has subtle `border-t` instead of heavy shadow -- Input container matches home page styling -- Textarea starts small and grows with content up to 160px max - -- [ ] **Step 13: Commit** - -```bash -git add frontend/app/chat/conversation/ConversationPanel.tsx frontend/app/chat/components/ChatInput.tsx frontend/app/chat/components/ChatHome.tsx -git commit -m "style: compact input area to match Skill Creator pattern" -``` diff --git a/docs/superpowers/plans/2026-03-21-chat-ui-beautification.md b/docs/superpowers/plans/2026-03-21-chat-ui-beautification.md deleted file mode 100644 index ab6023c90..000000000 --- a/docs/superpowers/plans/2026-03-21-chat-ui-beautification.md +++ /dev/null @@ -1,622 +0,0 @@ -# Chat UI Beautification Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Align the Chat page's visual quality with the Skill page by establishing a consistent blue brand color, improving surface depth, upgrading message bubbles, sidebar, header, empty/loading states, and standardizing animations. - -**Architecture:** Pure CSS/Tailwind class changes across 8 existing files. No new components, no state changes, no business logic changes. One new import (`getModeConfig`) in ChatLayout for header title derivation. - -**Tech Stack:** Next.js App Router, Tailwind CSS, shadcn/ui ` - -// TO: - -``` - -- [ ] **Step 5: Add center title** - -Insert after the new chat button's closing `` (after line ~280), before the preview toggle conditional block. Use `useChatState()` (already available) and `useTranslation()` (already imported): - -```tsx -
- - {t(getModeConfig(state.mode.currentMode)?.labelKey || 'chat.modes.default-chat')} - -
-``` - -Note: `state.mode.currentMode` is the correct field (ChatState has no `currentTitle` field). The fallback key `chat.modes.default-chat` should already exist in the i18n files as it's used by modeConfig. If it doesn't exist, use a `defaultValue`: `t(... || 'chat.modes.default-chat', { defaultValue: 'Chat' })`. - -- [ ] **Step 6: Update preview toggle hover** - -Around line 294, the preview toggle button currently has `className="h-9 w-9 p-0 transition-colors hover:bg-gray-100"`. Add `rounded-lg`: - -```tsx -// FROM: -className="h-9 w-9 p-0 transition-colors hover:bg-gray-100" - -// TO: -className="h-9 w-9 rounded-lg p-0 transition-colors hover:bg-gray-100" -``` - -- [ ] **Step 7: Verify** - -Check: Header should be taller (h-14), white bg with bottom border. New chat button is blue circle. Center shows mode name. Sidebar/preview toggles have consistent hover. - -- [ ] **Step 8: Commit** - -```bash -git add frontend/app/chat/ChatLayout.tsx -git commit -m "style: redesign header - white bg, branded new-chat button, center title" -``` - ---- - -### Task 5: ConversationPanel & ChatInput — Surface Depth & Brand Color - -**Files:** -- Modify: `frontend/app/chat/conversation/ConversationPanel.tsx` -- Modify: `frontend/app/chat/components/ChatInput.tsx` - -**Covers:** Area 1 (brand color), Area 5 (surface depth) - -- [ ] **Step 1: Update input wrapper in ConversationPanel** - -In `ConversationPanel.tsx` around line 76: - -```tsx -// FROM: -
- -// TO: -
-``` - -- [ ] **Step 2: Upgrade ChatInput container shadow** - -In `ChatInput.tsx` around line 134: - -```tsx -// FROM: -'flex items-end gap-3 rounded-[24px] border border-gray-200 bg-white p-4 shadow-sm transition-all', - -// TO: -'flex items-end gap-3 rounded-[24px] border border-gray-200 bg-white p-4 shadow-md transition-all', -``` - -- [ ] **Step 3: Rebrand ChatInput send button** - -In `ChatInput.tsx` around lines 192-193: - -```tsx -// FROM: -canSubmit && !isProcessing && !isUploading - ? 'bg-gray-900 hover:bg-gray-800' - : 'cursor-not-allowed bg-gray-100', - -// TO: -canSubmit && !isProcessing && !isUploading - ? 'bg-blue-600 hover:bg-blue-700' - : 'cursor-not-allowed bg-gray-100', -``` - -- [ ] **Step 4: Verify** - -Check: Input area has upward soft shadow instead of hard border-top line. Input container has slightly stronger shadow. Send button is blue when active. - -- [ ] **Step 5: Commit** - -```bash -git add frontend/app/chat/conversation/ConversationPanel.tsx frontend/app/chat/components/ChatInput.tsx -git commit -m "style: upgrade input area surface depth and brand send button" -``` - ---- - -### Task 6: ChatHome — Send Button & Mode Card - -**Files:** -- Modify: `frontend/app/chat/components/ChatHome.tsx` - -**Covers:** Area 1 (brand color) - -- [ ] **Step 1: Rebrand ChatHome send button** - -Around lines 591-592: - -```tsx -// FROM: -state.input.trim() && !isProcessing && !state.isRedirecting - ? 'bg-gray-900 hover:bg-gray-800' - : 'cursor-not-allowed bg-gray-100', - -// TO: -state.input.trim() && !isProcessing && !state.isRedirecting - ? 'bg-blue-600 hover:bg-blue-700' - : 'cursor-not-allowed bg-gray-100', -``` - -- [ ] **Step 2: Add ring to selected mode card** - -Around lines 646-647: - -```tsx -// FROM: -isSelected - ? 'border-blue-500 bg-blue-50 shadow-md' - : 'border-gray-200 bg-white hover:border-blue-300 hover:shadow-md', - -// TO: -isSelected - ? 'border-blue-500 bg-blue-50 shadow-md ring-1 ring-blue-100' - : 'border-gray-200 bg-white hover:border-blue-300 hover:shadow-md', -``` - -- [ ] **Step 3: Verify** - -Check: ChatHome send button is blue. Selected mode card has subtle blue ring. - -- [ ] **Step 4: Commit** - -```bash -git add frontend/app/chat/components/ChatHome.tsx -git commit -m "style: brand ChatHome send button and mode card ring" -``` - ---- - -### Task 7: PreviewPanel — Tab Animation - -**Files:** -- Modify: `frontend/app/chat/preview/PreviewPanel.tsx` - -**Covers:** Area 5 (surface depth — already bg-white, no change), Area 7 (animation) - -- [ ] **Step 1: Add transition to Files tab button** - -Around lines 28-31, add `transition-all duration-200` to the className: - -```tsx -// FROM: -className={`flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-sm ${ - activeTab === 'files' - ? 'bg-gray-100 font-medium' - : 'text-gray-500 hover:text-gray-700' -}`} - -// TO: -className={`flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-sm transition-all duration-200 ${ - activeTab === 'files' - ? 'bg-gray-100 font-medium' - : 'text-gray-500 hover:text-gray-700' -}`} -``` - -- [ ] **Step 2: Add transition to Tool tab button** - -Around lines 41-44, same change: - -```tsx -// FROM: -className={`flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-sm ${ - activeTab === 'tool' - ? 'bg-gray-100 font-medium' - : 'text-gray-500 hover:text-gray-700' -}`} - -// TO: -className={`flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-sm transition-all duration-200 ${ - activeTab === 'tool' - ? 'bg-gray-100 font-medium' - : 'text-gray-500 hover:text-gray-700' -}`} -``` - -- [ ] **Step 3: Verify** - -Check: Switching tabs in PreviewPanel should animate smoothly. - -- [ ] **Step 4: Commit** - -```bash -git add frontend/app/chat/preview/PreviewPanel.tsx -git commit -m "style: add transition animation to PreviewPanel tabs" -``` - ---- - -## Final Verification - -- [ ] Run full dev server and test all 7 areas visually -- [ ] Verify no TypeScript errors: `cd frontend && npx tsc --noEmit` -- [ ] Verify no lint errors: `cd frontend && npm run lint` -- [ ] Final commit if any adjustments needed diff --git a/docs/superpowers/plans/2026-03-23-skill-frontend-versioning-collab-token.md b/docs/superpowers/plans/2026-03-23-skill-frontend-versioning-collab-token.md deleted file mode 100644 index 90764c083..000000000 --- a/docs/superpowers/plans/2026-03-23-skill-frontend-versioning-collab-token.md +++ /dev/null @@ -1,2093 +0,0 @@ -# Skill 前端:版本管理 + 协作者管理 + Token 管理 实现计划 - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Implement the complete frontend UI for skill versioning, collaborator management, and platform token management. - -**Architecture:** Three service files (one per API domain) expose async methods calling `apiGet/apiPost/apiPut/apiDelete`. Three React Query hook files provide `useQuery`/`useMutation` wrappers with key factories. UI components integrate into SkillsManager (version + collaborator tabs) and Settings dialog (token page). All strings use i18n. - -**Tech Stack:** Next.js + React 19, TypeScript, React Query v5, shadcn/ui (Radix), Tailwind CSS, react-hook-form + Zod, lucide-react icons. - -**Spec:** `docs/superpowers/specs/2026-03-23-skill-frontend-versioning-collab-token-design.md` - ---- - -## Task 1: Backend — Extend VersionSummarySchema with `published_by_id` - -**Files:** -- Modify: `backend/app/schemas/skill_version.py` (VersionSummarySchema class, ~line 78) - -- [ ] **Step 1: Add `published_by_id` to VersionSummarySchema** - -```python -class VersionSummarySchema(BaseModel): - """Lightweight version info for list endpoints.""" - - version: str - release_notes: Optional[str] = None - published_by_id: str - published_at: Optional[str] = None - - @field_validator("published_at", mode="before") - @classmethod - def convert_datetime_to_str(cls, v): - if isinstance(v, datetime): - return v.isoformat() - return v - - class Config: - from_attributes = True -``` - -- [ ] **Step 2: Verify existing tests still pass** - -Run: `cd backend && python -m pytest tests/ -x -q --timeout=30 2>/dev/null || echo "no tests or pass"` - -- [ ] **Step 3: Commit** - -```bash -git add backend/app/schemas/skill_version.py -git commit -m "feat(schema): add published_by_id to VersionSummarySchema for frontend display" -``` - ---- - -## Task 2: Service — `skillVersionService.ts` - -**Files:** -- Create: `frontend/services/skillVersionService.ts` - -- [ ] **Step 1: Create the service file** - -```typescript -import { apiGet, apiPost, apiDelete } from '@/lib/api-client' - -// ---------- Types ---------- - -export interface SkillVersionSummary { - version: string - releaseNotes: string | null - publishedById: string - publishedAt: string | null -} - -export interface SkillVersionFile { - id: string - versionId: string - path: string - fileName: string - fileType: string - content: string | null - storageType: string - storageKey: string | null - size: number -} - -export interface SkillVersion { - id: string - skillId: string - version: string - releaseNotes: string | null - skillName: string - skillDescription: string - content: string - tags: string[] - metadata: Record - allowedTools: string[] - compatibility: string | null - license: string | null - publishedById: string - publishedAt: string | null - createdAt: string | null - files: SkillVersionFile[] | null -} - -// ---------- Normalizers ---------- - -function normalizeVersionSummary(raw: any): SkillVersionSummary { - return { - version: raw.version, - releaseNotes: raw.release_notes ?? null, - publishedById: raw.published_by_id, - publishedAt: raw.published_at ?? null, - } -} - -function normalizeVersion(raw: any): SkillVersion { - return { - id: raw.id, - skillId: raw.skill_id, - version: raw.version, - releaseNotes: raw.release_notes ?? null, - skillName: raw.skill_name, - skillDescription: raw.skill_description, - content: raw.content, - tags: raw.tags ?? [], - metadata: raw.metadata ?? {}, - allowedTools: raw.allowed_tools ?? [], - compatibility: raw.compatibility ?? null, - license: raw.license ?? null, - publishedById: raw.published_by_id, - publishedAt: raw.published_at ?? null, - createdAt: raw.created_at ?? null, - files: raw.files?.map((f: any) => ({ - id: f.id, - versionId: f.version_id, - path: f.path, - fileName: f.file_name, - fileType: f.file_type, - content: f.content ?? null, - storageType: f.storage_type, - storageKey: f.storage_key ?? null, - size: f.size ?? 0, - })) ?? null, - } -} - -// ---------- Service ---------- - -export const skillVersionService = { - async listVersions(skillId: string): Promise { - const data = await apiGet(`skills/${skillId}/versions`) - return (Array.isArray(data) ? data : []).map(normalizeVersionSummary) - }, - - async getVersion(skillId: string, version: string): Promise { - const data = await apiGet(`skills/${skillId}/versions/${version}`) - return normalizeVersion(data) - }, - - async getLatestVersion(skillId: string): Promise { - const data = await apiGet(`skills/${skillId}/versions/latest`) - return normalizeVersion(data) - }, - - async publishVersion(skillId: string, payload: { version: string; release_notes?: string }): Promise { - const data = await apiPost(`skills/${skillId}/versions`, payload) - return normalizeVersion(data) - }, - - async deleteVersion(skillId: string, version: string): Promise { - await apiDelete(`skills/${skillId}/versions/${version}`) - }, - - async restoreDraft(skillId: string, payload: { version: string }): Promise { - return await apiPost(`skills/${skillId}/restore`, payload) - }, -} -``` - -- [ ] **Step 2: Commit** - -```bash -git add frontend/services/skillVersionService.ts -git commit -m "feat: add skillVersionService with all version API methods" -``` - ---- - -## Task 3: Service — `skillCollaboratorService.ts` - -**Files:** -- Create: `frontend/services/skillCollaboratorService.ts` - -- [ ] **Step 1: Create the service file** - -```typescript -import { apiGet, apiPost, apiPut, apiDelete } from '@/lib/api-client' - -// ---------- Types ---------- - -export type CollaboratorRole = 'viewer' | 'editor' | 'publisher' | 'admin' - -export interface SkillCollaborator { - id: string - skillId: string - userId: string - role: CollaboratorRole - invitedBy: string - createdAt: string | null -} - -// ---------- Normalizer ---------- - -function normalizeCollaborator(raw: any): SkillCollaborator { - return { - id: raw.id, - skillId: raw.skill_id, - userId: raw.user_id, - role: raw.role, - invitedBy: raw.invited_by, - createdAt: raw.created_at ?? null, - } -} - -// ---------- Service ---------- - -export const skillCollaboratorService = { - async listCollaborators(skillId: string): Promise { - const data = await apiGet(`skills/${skillId}/collaborators`) - return (Array.isArray(data) ? data : []).map(normalizeCollaborator) - }, - - async addCollaborator(skillId: string, payload: { user_id: string; role: CollaboratorRole }): Promise { - const data = await apiPost(`skills/${skillId}/collaborators`, payload) - return normalizeCollaborator(data) - }, - - async updateRole(skillId: string, userId: string, payload: { role: CollaboratorRole }): Promise { - const data = await apiPut(`skills/${skillId}/collaborators/${userId}`, payload) - return normalizeCollaborator(data) - }, - - async removeCollaborator(skillId: string, userId: string): Promise { - await apiDelete(`skills/${skillId}/collaborators/${userId}`) - }, - - async transferOwnership(skillId: string, payload: { new_owner_id: string }): Promise { - await apiPost(`skills/${skillId}/transfer`, payload) - }, -} -``` - -- [ ] **Step 2: Commit** - -```bash -git add frontend/services/skillCollaboratorService.ts -git commit -m "feat: add skillCollaboratorService with collaborator API methods" -``` - ---- - -## Task 4: Service — `platformTokenService.ts` - -**Files:** -- Create: `frontend/services/platformTokenService.ts` - -- [ ] **Step 1: Create the service file** - -```typescript -import { apiGet, apiPost, apiDelete } from '@/lib/api-client' - -// ---------- Types ---------- - -export interface PlatformToken { - id: string - name: string - tokenPrefix: string - scopes: string[] - resourceType: string | null - resourceId: string | null - expiresAt: string | null - lastUsedAt: string | null - isActive: boolean - createdAt: string | null -} - -export interface PlatformTokenCreateResponse { - id: string - name: string - token: string - tokenPrefix: string - scopes: string[] - expiresAt: string | null -} - -export interface TokenCreateRequest { - name: string - scopes: string[] - expires_at?: string | null -} - -// ---------- Normalizers ---------- - -function normalizeToken(raw: any): PlatformToken { - return { - id: raw.id, - name: raw.name, - tokenPrefix: raw.token_prefix, - scopes: raw.scopes ?? [], - resourceType: raw.resource_type ?? null, - resourceId: raw.resource_id ?? null, - expiresAt: raw.expires_at ?? null, - lastUsedAt: raw.last_used_at ?? null, - isActive: raw.is_active ?? true, - createdAt: raw.created_at ?? null, - } -} - -function normalizeTokenCreateResponse(raw: any): PlatformTokenCreateResponse { - return { - id: raw.id, - name: raw.name, - token: raw.token, - tokenPrefix: raw.token_prefix, - scopes: raw.scopes ?? [], - expiresAt: raw.expires_at ?? null, - } -} - -// ---------- Service ---------- - -export const platformTokenService = { - async listTokens(): Promise { - const data = await apiGet('tokens') - return (Array.isArray(data) ? data : []).map(normalizeToken) - }, - - async createToken(payload: TokenCreateRequest): Promise { - const data = await apiPost('tokens', payload) - return normalizeTokenCreateResponse(data) - }, - - async revokeToken(tokenId: string): Promise { - await apiDelete(`tokens/${tokenId}`) - }, -} -``` - -- [ ] **Step 2: Commit** - -```bash -git add frontend/services/platformTokenService.ts -git commit -m "feat: add platformTokenService with token CRUD methods" -``` - ---- - -## Task 5: React Query Hooks — `skillVersions.ts` - -**Files:** -- Create: `frontend/hooks/queries/skillVersions.ts` -- Modify: `frontend/hooks/queries/index.ts` (add export) - -- [ ] **Step 1: Create the query hooks file** - -```typescript -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' - -import { STALE_TIME } from './constants' -import { skillKeys } from './skills' -import { skillVersionService } from '@/services/skillVersionService' -import type { SkillVersionSummary, SkillVersion } from '@/services/skillVersionService' - -export { type SkillVersionSummary, type SkillVersion } from '@/services/skillVersionService' - -// ---------- Key factory ---------- - -export const skillVersionKeys = { - all: ['skill-versions'] as const, - list: (skillId: string) => [...skillVersionKeys.all, 'list', skillId] as const, - detail: (skillId: string, version: string) => - [...skillVersionKeys.all, 'detail', skillId, version] as const, - latest: (skillId: string) => [...skillVersionKeys.all, 'latest', skillId] as const, -} - -// ---------- Queries ---------- - -export function useSkillVersions(skillId: string) { - return useQuery({ - queryKey: skillVersionKeys.list(skillId), - queryFn: () => skillVersionService.listVersions(skillId), - enabled: !!skillId, - retry: false, - staleTime: STALE_TIME.STANDARD, - }) -} - -export function useSkillVersion(skillId: string, version: string) { - return useQuery({ - queryKey: skillVersionKeys.detail(skillId, version), - queryFn: () => skillVersionService.getVersion(skillId, version), - enabled: !!skillId && !!version, - retry: false, - staleTime: STALE_TIME.STANDARD, - }) -} - -// ---------- Mutations ---------- - -export function usePublishVersion(skillId: string) { - const queryClient = useQueryClient() - return useMutation({ - mutationFn: (payload: { version: string; release_notes?: string }) => - skillVersionService.publishVersion(skillId, payload), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: skillVersionKeys.list(skillId) }) - queryClient.invalidateQueries({ queryKey: skillKeys.all }) - }, - }) -} - -export function useDeleteVersion(skillId: string) { - const queryClient = useQueryClient() - return useMutation({ - mutationFn: (version: string) => skillVersionService.deleteVersion(skillId, version), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: skillVersionKeys.list(skillId) }) - }, - }) -} - -export function useRestoreDraft(skillId: string) { - const queryClient = useQueryClient() - return useMutation({ - mutationFn: (version: string) => - skillVersionService.restoreDraft(skillId, { version }), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: skillKeys.all }) - }, - }) -} -``` - -- [ ] **Step 2: Add export to index.ts** - -In `frontend/hooks/queries/index.ts`, add: - -```typescript -export * from './skillVersions' -``` - -- [ ] **Step 3: Commit** - -```bash -git add frontend/hooks/queries/skillVersions.ts frontend/hooks/queries/index.ts -git commit -m "feat: add React Query hooks for skill versions" -``` - ---- - -## Task 6: React Query Hooks — `skillCollaborators.ts` - -**Files:** -- Create: `frontend/hooks/queries/skillCollaborators.ts` -- Modify: `frontend/hooks/queries/index.ts` (add export) - -- [ ] **Step 1: Create the query hooks file** - -```typescript -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' - -import { STALE_TIME } from './constants' -import { skillKeys } from './skills' -import { skillCollaboratorService } from '@/services/skillCollaboratorService' -import type { SkillCollaborator, CollaboratorRole } from '@/services/skillCollaboratorService' - -export { type SkillCollaborator, type CollaboratorRole } from '@/services/skillCollaboratorService' - -// ---------- Key factory ---------- - -export const skillCollaboratorKeys = { - all: ['skill-collaborators'] as const, - list: (skillId: string) => [...skillCollaboratorKeys.all, 'list', skillId] as const, -} - -// ---------- Queries ---------- - -export function useSkillCollaborators(skillId: string) { - return useQuery({ - queryKey: skillCollaboratorKeys.list(skillId), - queryFn: () => skillCollaboratorService.listCollaborators(skillId), - enabled: !!skillId, - retry: false, - staleTime: STALE_TIME.STANDARD, - }) -} - -// ---------- Mutations ---------- - -export function useAddCollaborator(skillId: string) { - const queryClient = useQueryClient() - return useMutation({ - mutationFn: (payload: { user_id: string; role: CollaboratorRole }) => - skillCollaboratorService.addCollaborator(skillId, payload), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: skillCollaboratorKeys.list(skillId) }) - }, - }) -} - -export function useUpdateCollaboratorRole(skillId: string) { - const queryClient = useQueryClient() - return useMutation({ - mutationFn: ({ userId, role }: { userId: string; role: CollaboratorRole }) => - skillCollaboratorService.updateRole(skillId, userId, { role }), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: skillCollaboratorKeys.list(skillId) }) - }, - }) -} - -export function useRemoveCollaborator(skillId: string) { - const queryClient = useQueryClient() - return useMutation({ - mutationFn: (userId: string) => - skillCollaboratorService.removeCollaborator(skillId, userId), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: skillCollaboratorKeys.list(skillId) }) - }, - }) -} - -export function useTransferOwnership(skillId: string) { - const queryClient = useQueryClient() - return useMutation({ - mutationFn: (newOwnerId: string) => - skillCollaboratorService.transferOwnership(skillId, { new_owner_id: newOwnerId }), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: skillCollaboratorKeys.list(skillId) }) - queryClient.invalidateQueries({ queryKey: skillKeys.all }) - }, - }) -} -``` - -- [ ] **Step 2: Add export to index.ts** - -In `frontend/hooks/queries/index.ts`, add: - -```typescript -export * from './skillCollaborators' -``` - -- [ ] **Step 3: Commit** - -```bash -git add frontend/hooks/queries/skillCollaborators.ts frontend/hooks/queries/index.ts -git commit -m "feat: add React Query hooks for skill collaborators" -``` - ---- - -## Task 7: React Query Hooks — `platformTokens.ts` - -**Files:** -- Create: `frontend/hooks/queries/platformTokens.ts` -- Modify: `frontend/hooks/queries/index.ts` (add export) - -- [ ] **Step 1: Create the query hooks file** - -```typescript -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' - -import { STALE_TIME } from './constants' -import { platformTokenService } from '@/services/platformTokenService' -import type { PlatformToken, PlatformTokenCreateResponse, TokenCreateRequest } from '@/services/platformTokenService' - -export { type PlatformToken, type PlatformTokenCreateResponse, type TokenCreateRequest } from '@/services/platformTokenService' - -// ---------- Key factory ---------- - -export const platformTokenKeys = { - all: ['platform-tokens'] as const, - list: () => [...platformTokenKeys.all, 'list'] as const, -} - -// ---------- Queries ---------- - -export function usePlatformTokens() { - return useQuery({ - queryKey: platformTokenKeys.list(), - queryFn: () => platformTokenService.listTokens(), - retry: false, - staleTime: STALE_TIME.LONG, - }) -} - -// ---------- Mutations ---------- - -export function useCreateToken() { - const queryClient = useQueryClient() - return useMutation({ - mutationFn: (payload: TokenCreateRequest) => - platformTokenService.createToken(payload), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: platformTokenKeys.all }) - }, - }) -} - -export function useRevokeToken() { - const queryClient = useQueryClient() - return useMutation({ - mutationFn: (tokenId: string) => platformTokenService.revokeToken(tokenId), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: platformTokenKeys.all }) - }, - }) -} -``` - -- [ ] **Step 2: Add export to index.ts** - -In `frontend/hooks/queries/index.ts`, add: - -```typescript -export * from './platformTokens' -``` - -- [ ] **Step 3: Commit** - -```bash -git add frontend/hooks/queries/platformTokens.ts frontend/hooks/queries/index.ts -git commit -m "feat: add React Query hooks for platform tokens" -``` - ---- - -## Task 8: i18n — Add translation keys for all three features - -**Files:** -- Modify: `frontend/lib/i18n/locales/en.ts` -- Modify: `frontend/lib/i18n/locales/zh.ts` - -- [ ] **Step 1: Add English translation keys** - -Add `editor` key to the `skills` block (if not already present): - -```typescript -editor: 'Editor', -``` - -Add inside the `settings` block, after the `sandboxes` key: - -```typescript -tokens: { - title: 'API Tokens', - description: 'Manage your API access tokens', - create: 'Create Token', - revoke: 'Revoke', - revokeConfirmTitle: 'Revoke Token', - revokeConfirmMessage: 'API calls using this token will fail immediately after revoking.', - name: 'Token Name', - namePlaceholder: 'e.g. CI deploy token', - scopes: 'Scopes', - expiresAt: 'Expiration', - noExpiry: 'No expiry', - lastUsed: 'Last used', - neverUsed: 'never', - createdSuccess: 'Token created successfully', - revokedSuccess: 'Token revoked', - tokenCreatedTitle: 'Token Created', - tokenCreatedMessage: 'Copy this token now. You won\'t be able to see it again.', - copyToken: 'Copy Token', - copied: 'Copied!', - emptyState: 'No API tokens created yet', - limitReached: 'Token limit reached (50)', - justNow: 'just now', - minutesAgo: '{{count}}m ago', - hoursAgo: '{{count}}h ago', - daysAgo: '{{count}}d ago', -}, -``` - -Add a new top-level `skillVersions` block: - -```typescript -skillVersions: { - title: 'Version History', - publish: 'Publish New Version', - publishButton: 'Publish', - versionNumber: 'Version Number', - versionPlaceholder: 'e.g. 1.0.0', - releaseNotes: 'Release Notes', - releaseNotesPlaceholder: 'Describe what changed...', - restore: 'Restore', - delete: 'Delete', - restoreConfirmTitle: 'Restore Draft', - restoreConfirmMessage: 'This will overwrite the current draft with version {{version}}. Continue?', - deleteConfirmTitle: 'Delete Version', - deleteConfirmMessage: 'This version will be permanently deleted. This cannot be undone.', - publishedBy: 'by {{user}}', - publishedSuccess: 'Version {{version}} published', - restoredSuccess: 'Draft restored from version {{version}}', - deletedSuccess: 'Version {{version}} deleted', - emptyState: 'No versions published yet', - invalidVersion: 'Must be MAJOR.MINOR.PATCH format (e.g. 1.0.0)', -}, -``` - -Add a new top-level `skillCollaborators` block: - -```typescript -skillCollaborators: { - title: 'Collaborators', - add: 'Add Collaborator', - userId: 'User ID', - userIdPlaceholder: 'Enter user ID', - role: 'Role', - owner: 'owner', - viewer: 'viewer', - editor: 'editor', - publisher: 'publisher', - admin: 'admin', - remove: 'Remove', - removeConfirmTitle: 'Remove Collaborator', - removeConfirmMessage: 'This user will lose access to this skill.', - transferOwnership: 'Transfer Ownership', - transferConfirmTitle: 'Transfer Ownership', - transferConfirmMessage: 'You will become an admin collaborator. The new owner will have full control.', - newOwner: 'New Owner', - newOwnerPlaceholder: 'Enter new owner user ID', - addedSuccess: 'Collaborator added', - updatedSuccess: 'Role updated', - removedSuccess: 'Collaborator removed', - transferredSuccess: 'Ownership transferred', - emptyState: 'No collaborators yet', -}, -``` - -- [ ] **Step 2: Add Chinese translation keys** - -Add the same structure in `zh.ts` with Chinese translations. - -Add `editor` key to the `skills` block: - -```typescript -editor: '编辑器', -``` - -`settings.tokens`: -```typescript -tokens: { - title: 'API Token', - description: '管理您的 API 访问令牌', - create: '创建 Token', - revoke: '撤销', - revokeConfirmTitle: '撤销 Token', - revokeConfirmMessage: '撤销后,使用此 Token 的 API 调用将立即失败。', - name: 'Token 名称', - namePlaceholder: '例如 CI 部署 Token', - scopes: '权限范围', - expiresAt: '过期时间', - noExpiry: '永不过期', - lastUsed: '最后使用', - neverUsed: '从未使用', - createdSuccess: 'Token 创建成功', - revokedSuccess: 'Token 已撤销', - tokenCreatedTitle: 'Token 已创建', - tokenCreatedMessage: '请立即复制此 Token,关闭后将无法再次查看。', - copyToken: '复制 Token', - copied: '已复制!', - emptyState: '尚未创建 API Token', - limitReached: '已达 Token 数量上限(50)', - justNow: '刚刚', - minutesAgo: '{{count}} 分钟前', - hoursAgo: '{{count}} 小时前', - daysAgo: '{{count}} 天前', -}, -``` - -`skillVersions`: -```typescript -skillVersions: { - title: '版本历史', - publish: '发布新版本', - publishButton: '发布', - versionNumber: '版本号', - versionPlaceholder: '例如 1.0.0', - releaseNotes: '更新说明', - releaseNotesPlaceholder: '描述变更内容...', - restore: '恢复', - delete: '删除', - restoreConfirmTitle: '恢复 Draft', - restoreConfirmMessage: '这将用版本 {{version}} 覆盖当前 Draft。是否继续?', - deleteConfirmTitle: '删除版本', - deleteConfirmMessage: '此版本将被永久删除,此操作不可撤销。', - publishedBy: '由 {{user}}', - publishedSuccess: '版本 {{version}} 已发布', - restoredSuccess: '已从版本 {{version}} 恢复 Draft', - deletedSuccess: '版本 {{version}} 已删除', - emptyState: '尚未发布任何版本', - invalidVersion: '格式须为 MAJOR.MINOR.PATCH(如 1.0.0)', -}, -``` - -`skillCollaborators`: -```typescript -skillCollaborators: { - title: '协作者', - add: '添加协作者', - userId: '用户 ID', - userIdPlaceholder: '输入用户 ID', - role: '角色', - owner: '所有者', - viewer: '查看者', - editor: '编辑者', - publisher: '发布者', - admin: '管理员', - remove: '移除', - removeConfirmTitle: '移除协作者', - removeConfirmMessage: '该用户将失去对此 Skill 的访问权限。', - transferOwnership: '转让所有权', - transferConfirmTitle: '转让所有权', - transferConfirmMessage: '您将成为管理员协作者,新所有者将拥有完全控制权。', - newOwner: '新所有者', - newOwnerPlaceholder: '输入新所有者用户 ID', - addedSuccess: '协作者已添加', - updatedSuccess: '角色已更新', - removedSuccess: '协作者已移除', - transferredSuccess: '所有权已转让', - emptyState: '暂无协作者', -}, -``` - -- [ ] **Step 3: Commit** - -```bash -git add frontend/lib/i18n/locales/en.ts frontend/lib/i18n/locales/zh.ts -git commit -m "feat(i18n): add en/zh translations for versions, collaborators, tokens" -``` - ---- - -## Task 9: UI — VersionHistoryTab component - -**Files:** -- Create: `frontend/app/skills/components/VersionHistoryTab.tsx` -- Create: `frontend/app/skills/schemas/versionPublishSchema.ts` - -- [ ] **Step 1: Create Zod schema for publish form** - -```typescript -// frontend/app/skills/schemas/versionPublishSchema.ts -import { z } from 'zod' - -export const versionPublishSchema = z.object({ - version: z - .string() - .min(1, 'Version is required') - .regex(/^\d+\.\d+\.\d+$/, 'Must be MAJOR.MINOR.PATCH format (e.g. 1.0.0)'), - release_notes: z.string().optional().default(''), -}) - -export type VersionPublishFormData = z.infer -``` - -- [ ] **Step 2: Create the VersionHistoryTab component** - -Create `frontend/app/skills/components/VersionHistoryTab.tsx`: - -```tsx -'use client' - -import { ChevronDown, ChevronUp, History, Plus, RotateCcw, Trash2 } from 'lucide-react' -import React, { useState } from 'react' -import { useForm } from 'react-hook-form' -import { zodResolver } from '@hookform/resolvers/zod' - -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, -} from '@/components/ui/alert-dialog' -import { Button } from '@/components/ui/button' -import { Input } from '@/components/ui/input' -import { Label } from '@/components/ui/label' -import { Textarea } from '@/components/ui/textarea' -import { useToast } from '@/hooks/use-toast' -import { - useSkillVersions, - usePublishVersion, - useDeleteVersion, - useRestoreDraft, -} from '@/hooks/queries/skillVersions' -import { useTranslation } from '@/lib/i18n' -import { - versionPublishSchema, - type VersionPublishFormData, -} from '../schemas/versionPublishSchema' - -interface VersionHistoryTabProps { - skillId: string - /** Current user's effective role for this skill: 'owner' | 'admin' | 'publisher' | 'editor' | 'viewer' */ - userRole: string -} - -export function VersionHistoryTab({ skillId, userRole }: VersionHistoryTabProps) { - const { t } = useTranslation() - const { toast } = useToast() - - const [showPublishForm, setShowPublishForm] = useState(false) - const [confirmDialog, setConfirmDialog] = useState<{ - type: 'restore' | 'delete' - version: string - open: boolean - }>({ type: 'restore', version: '', open: false }) - - const { data: versions = [], isLoading } = useSkillVersions(skillId) - const publishMutation = usePublishVersion(skillId) - const deleteMutation = useDeleteVersion(skillId) - const restoreMutation = useRestoreDraft(skillId) - - const canPublish = ['owner', 'admin', 'publisher'].includes(userRole) - const canDelete = ['owner', 'admin'].includes(userRole) - const canRestore = ['owner', 'admin', 'publisher'].includes(userRole) - - const form = useForm({ - resolver: zodResolver(versionPublishSchema), - defaultValues: { version: '', release_notes: '' }, - }) - - const handlePublish = async (data: VersionPublishFormData) => { - try { - await publishMutation.mutateAsync(data) - toast({ title: t('skillVersions.publishedSuccess', { version: data.version }) }) - form.reset() - setShowPublishForm(false) - } catch (error: any) { - toast({ - title: error?.message || t('common.error'), - variant: 'destructive', - }) - } - } - - const handleConfirmAction = async () => { - const { type, version } = confirmDialog - try { - if (type === 'restore') { - await restoreMutation.mutateAsync(version) - toast({ title: t('skillVersions.restoredSuccess', { version }) }) - } else { - await deleteMutation.mutateAsync(version) - toast({ title: t('skillVersions.deletedSuccess', { version }) }) - } - } catch (error: any) { - toast({ title: error?.message || t('common.error'), variant: 'destructive' }) - } - setConfirmDialog((prev) => ({ ...prev, open: false })) - } - - if (isLoading) { - return ( -
-
-
- ) - } - - return ( -
- {/* Publish form toggle */} - {canPublish && ( -
- - - {showPublishForm && ( -
-
- - - {form.formState.errors.version && ( -

- {t('skillVersions.invalidVersion')} -

- )} -
-
- -