Spaces:
Running
Running
Merge pull request #16 from The-Obstacle-Is-The-Way/feat/mario-integration
Browse files- .env.example +9 -0
- docs/workflow-diagrams.md +662 -0
- examples/modal_demo/test_code_execution.py +169 -0
- examples/modal_demo/verify_sandbox.py +298 -0
- pyproject.toml +12 -0
- src/agents/analysis_agent.py +379 -0
- src/services/embeddings.py +9 -3
- src/services/llamaindex_rag.py +264 -0
- src/tools/code_execution.py +256 -0
- src/utils/config.py +16 -0
- uv.lock +712 -44
.env.example
CHANGED
|
@@ -11,3 +11,12 @@ HF_TOKEN=hf_your-token-here
|
|
| 11 |
# Agent Config
|
| 12 |
MAX_ITERATIONS=10
|
| 13 |
LOG_LEVEL=INFO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
# Agent Config
|
| 12 |
MAX_ITERATIONS=10
|
| 13 |
LOG_LEVEL=INFO
|
| 14 |
+
|
| 15 |
+
# ============== PARTNER SERVICES (Mario's Modal Integration) ==============
|
| 16 |
+
|
| 17 |
+
# Modal (Code Execution)
|
| 18 |
+
MODAL_TOKEN_ID=ak-your-modal-token-id-here
|
| 19 |
+
MODAL_TOKEN_SECRET=your-modal-token-secret-here
|
| 20 |
+
|
| 21 |
+
# Vector Database
|
| 22 |
+
CHROMA_DB_PATH=./chroma_db
|
docs/workflow-diagrams.md
ADDED
|
@@ -0,0 +1,662 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# DeepCritical Workflow - Simplified Magentic Architecture
|
| 2 |
+
|
| 3 |
+
> **Architecture Pattern**: Microsoft Magentic Orchestration
|
| 4 |
+
> **Design Philosophy**: Simple, dynamic, manager-driven coordination
|
| 5 |
+
> **Key Innovation**: Intelligent manager replaces rigid sequential phases
|
| 6 |
+
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
## 1. High-Level Magentic Workflow
|
| 10 |
+
|
| 11 |
+
```mermaid
|
| 12 |
+
flowchart TD
|
| 13 |
+
Start([User Query]) --> Manager[Magentic Manager<br/>Plan • Select • Assess • Adapt]
|
| 14 |
+
|
| 15 |
+
Manager -->|Plans| Task1[Task Decomposition]
|
| 16 |
+
Task1 --> Manager
|
| 17 |
+
|
| 18 |
+
Manager -->|Selects & Executes| HypAgent[Hypothesis Agent]
|
| 19 |
+
Manager -->|Selects & Executes| SearchAgent[Search Agent]
|
| 20 |
+
Manager -->|Selects & Executes| AnalysisAgent[Analysis Agent]
|
| 21 |
+
Manager -->|Selects & Executes| ReportAgent[Report Agent]
|
| 22 |
+
|
| 23 |
+
HypAgent -->|Results| Manager
|
| 24 |
+
SearchAgent -->|Results| Manager
|
| 25 |
+
AnalysisAgent -->|Results| Manager
|
| 26 |
+
ReportAgent -->|Results| Manager
|
| 27 |
+
|
| 28 |
+
Manager -->|Assesses Quality| Decision{Good Enough?}
|
| 29 |
+
Decision -->|No - Refine| Manager
|
| 30 |
+
Decision -->|No - Different Agent| Manager
|
| 31 |
+
Decision -->|No - Stalled| Replan[Reset Plan]
|
| 32 |
+
Replan --> Manager
|
| 33 |
+
|
| 34 |
+
Decision -->|Yes| Synthesis[Synthesize Final Result]
|
| 35 |
+
Synthesis --> Output([Research Report])
|
| 36 |
+
|
| 37 |
+
style Start fill:#e1f5e1
|
| 38 |
+
style Manager fill:#ffe6e6
|
| 39 |
+
style HypAgent fill:#fff4e6
|
| 40 |
+
style SearchAgent fill:#fff4e6
|
| 41 |
+
style AnalysisAgent fill:#fff4e6
|
| 42 |
+
style ReportAgent fill:#fff4e6
|
| 43 |
+
style Decision fill:#ffd6d6
|
| 44 |
+
style Synthesis fill:#d4edda
|
| 45 |
+
style Output fill:#e1f5e1
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
## 2. Magentic Manager: The 6-Phase Cycle
|
| 49 |
+
|
| 50 |
+
```mermaid
|
| 51 |
+
flowchart LR
|
| 52 |
+
P1[1. Planning<br/>Analyze task<br/>Create strategy] --> P2[2. Agent Selection<br/>Pick best agent<br/>for subtask]
|
| 53 |
+
P2 --> P3[3. Execution<br/>Run selected<br/>agent with tools]
|
| 54 |
+
P3 --> P4[4. Assessment<br/>Evaluate quality<br/>Check progress]
|
| 55 |
+
P4 --> Decision{Quality OK?<br/>Progress made?}
|
| 56 |
+
Decision -->|Yes| P6[6. Synthesis<br/>Combine results<br/>Generate report]
|
| 57 |
+
Decision -->|No| P5[5. Iteration<br/>Adjust plan<br/>Try again]
|
| 58 |
+
P5 --> P2
|
| 59 |
+
P6 --> Done([Complete])
|
| 60 |
+
|
| 61 |
+
style P1 fill:#fff4e6
|
| 62 |
+
style P2 fill:#ffe6e6
|
| 63 |
+
style P3 fill:#e6f3ff
|
| 64 |
+
style P4 fill:#ffd6d6
|
| 65 |
+
style P5 fill:#fff3cd
|
| 66 |
+
style P6 fill:#d4edda
|
| 67 |
+
style Done fill:#e1f5e1
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
## 3. Simplified Agent Architecture
|
| 71 |
+
|
| 72 |
+
```mermaid
|
| 73 |
+
graph TB
|
| 74 |
+
subgraph "Orchestration Layer"
|
| 75 |
+
Manager[Magentic Manager<br/>• Plans workflow<br/>• Selects agents<br/>• Assesses quality<br/>• Adapts strategy]
|
| 76 |
+
SharedContext[(Shared Context<br/>• Hypotheses<br/>• Search Results<br/>• Analysis<br/>• Progress)]
|
| 77 |
+
Manager <--> SharedContext
|
| 78 |
+
end
|
| 79 |
+
|
| 80 |
+
subgraph "Specialist Agents"
|
| 81 |
+
HypAgent[Hypothesis Agent<br/>• Domain understanding<br/>• Hypothesis generation<br/>• Testability refinement]
|
| 82 |
+
SearchAgent[Search Agent<br/>• Multi-source search<br/>• RAG retrieval<br/>• Result ranking]
|
| 83 |
+
AnalysisAgent[Analysis Agent<br/>• Evidence extraction<br/>• Statistical analysis<br/>• Code execution]
|
| 84 |
+
ReportAgent[Report Agent<br/>• Report assembly<br/>• Visualization<br/>• Citation formatting]
|
| 85 |
+
end
|
| 86 |
+
|
| 87 |
+
subgraph "MCP Tools"
|
| 88 |
+
WebSearch[Web Search<br/>PubMed • arXiv • bioRxiv]
|
| 89 |
+
CodeExec[Code Execution<br/>Sandboxed Python]
|
| 90 |
+
RAG[RAG Retrieval<br/>Vector DB • Embeddings]
|
| 91 |
+
Viz[Visualization<br/>Charts • Graphs]
|
| 92 |
+
end
|
| 93 |
+
|
| 94 |
+
Manager -->|Selects & Directs| HypAgent
|
| 95 |
+
Manager -->|Selects & Directs| SearchAgent
|
| 96 |
+
Manager -->|Selects & Directs| AnalysisAgent
|
| 97 |
+
Manager -->|Selects & Directs| ReportAgent
|
| 98 |
+
|
| 99 |
+
HypAgent --> SharedContext
|
| 100 |
+
SearchAgent --> SharedContext
|
| 101 |
+
AnalysisAgent --> SharedContext
|
| 102 |
+
ReportAgent --> SharedContext
|
| 103 |
+
|
| 104 |
+
SearchAgent --> WebSearch
|
| 105 |
+
SearchAgent --> RAG
|
| 106 |
+
AnalysisAgent --> CodeExec
|
| 107 |
+
ReportAgent --> CodeExec
|
| 108 |
+
ReportAgent --> Viz
|
| 109 |
+
|
| 110 |
+
style Manager fill:#ffe6e6
|
| 111 |
+
style SharedContext fill:#ffe6f0
|
| 112 |
+
style HypAgent fill:#fff4e6
|
| 113 |
+
style SearchAgent fill:#fff4e6
|
| 114 |
+
style AnalysisAgent fill:#fff4e6
|
| 115 |
+
style ReportAgent fill:#fff4e6
|
| 116 |
+
style WebSearch fill:#e6f3ff
|
| 117 |
+
style CodeExec fill:#e6f3ff
|
| 118 |
+
style RAG fill:#e6f3ff
|
| 119 |
+
style Viz fill:#e6f3ff
|
| 120 |
+
```
|
| 121 |
+
|
| 122 |
+
## 4. Dynamic Workflow Example
|
| 123 |
+
|
| 124 |
+
```mermaid
|
| 125 |
+
sequenceDiagram
|
| 126 |
+
participant User
|
| 127 |
+
participant Manager
|
| 128 |
+
participant HypAgent
|
| 129 |
+
participant SearchAgent
|
| 130 |
+
participant AnalysisAgent
|
| 131 |
+
participant ReportAgent
|
| 132 |
+
|
| 133 |
+
User->>Manager: "Research protein folding in Alzheimer's"
|
| 134 |
+
|
| 135 |
+
Note over Manager: PLAN: Generate hypotheses → Search → Analyze → Report
|
| 136 |
+
|
| 137 |
+
Manager->>HypAgent: Generate 3 hypotheses
|
| 138 |
+
HypAgent-->>Manager: Returns 3 hypotheses
|
| 139 |
+
Note over Manager: ASSESS: Good quality, proceed
|
| 140 |
+
|
| 141 |
+
Manager->>SearchAgent: Search literature for hypothesis 1
|
| 142 |
+
SearchAgent-->>Manager: Returns 15 papers
|
| 143 |
+
Note over Manager: ASSESS: Good results, continue
|
| 144 |
+
|
| 145 |
+
Manager->>SearchAgent: Search for hypothesis 2
|
| 146 |
+
SearchAgent-->>Manager: Only 2 papers found
|
| 147 |
+
Note over Manager: ASSESS: Insufficient, refine search
|
| 148 |
+
|
| 149 |
+
Manager->>SearchAgent: Refined query for hypothesis 2
|
| 150 |
+
SearchAgent-->>Manager: Returns 12 papers
|
| 151 |
+
Note over Manager: ASSESS: Better, proceed
|
| 152 |
+
|
| 153 |
+
Manager->>AnalysisAgent: Analyze evidence for all hypotheses
|
| 154 |
+
AnalysisAgent-->>Manager: Returns analysis with code
|
| 155 |
+
Note over Manager: ASSESS: Complete, generate report
|
| 156 |
+
|
| 157 |
+
Manager->>ReportAgent: Create comprehensive report
|
| 158 |
+
ReportAgent-->>Manager: Returns formatted report
|
| 159 |
+
Note over Manager: SYNTHESIZE: Combine all results
|
| 160 |
+
|
| 161 |
+
Manager->>User: Final Research Report
|
| 162 |
+
```
|
| 163 |
+
|
| 164 |
+
## 5. Manager Decision Logic
|
| 165 |
+
|
| 166 |
+
```mermaid
|
| 167 |
+
flowchart TD
|
| 168 |
+
Start([Manager Receives Task]) --> Plan[Create Initial Plan]
|
| 169 |
+
|
| 170 |
+
Plan --> Select[Select Agent for Next Subtask]
|
| 171 |
+
Select --> Execute[Execute Agent]
|
| 172 |
+
Execute --> Collect[Collect Results]
|
| 173 |
+
|
| 174 |
+
Collect --> Assess[Assess Quality & Progress]
|
| 175 |
+
|
| 176 |
+
Assess --> Q1{Quality Sufficient?}
|
| 177 |
+
Q1 -->|No| Q2{Same Agent Can Fix?}
|
| 178 |
+
Q2 -->|Yes| Feedback[Provide Specific Feedback]
|
| 179 |
+
Feedback --> Execute
|
| 180 |
+
Q2 -->|No| Different[Try Different Agent]
|
| 181 |
+
Different --> Select
|
| 182 |
+
|
| 183 |
+
Q1 -->|Yes| Q3{Task Complete?}
|
| 184 |
+
Q3 -->|No| Q4{Making Progress?}
|
| 185 |
+
Q4 -->|Yes| Select
|
| 186 |
+
Q4 -->|No - Stalled| Replan[Reset Plan & Approach]
|
| 187 |
+
Replan --> Plan
|
| 188 |
+
|
| 189 |
+
Q3 -->|Yes| Synth[Synthesize Final Result]
|
| 190 |
+
Synth --> Done([Return Report])
|
| 191 |
+
|
| 192 |
+
style Start fill:#e1f5e1
|
| 193 |
+
style Plan fill:#fff4e6
|
| 194 |
+
style Select fill:#ffe6e6
|
| 195 |
+
style Execute fill:#e6f3ff
|
| 196 |
+
style Assess fill:#ffd6d6
|
| 197 |
+
style Q1 fill:#ffe6e6
|
| 198 |
+
style Q2 fill:#ffe6e6
|
| 199 |
+
style Q3 fill:#ffe6e6
|
| 200 |
+
style Q4 fill:#ffe6e6
|
| 201 |
+
style Synth fill:#d4edda
|
| 202 |
+
style Done fill:#e1f5e1
|
| 203 |
+
```
|
| 204 |
+
|
| 205 |
+
## 6. Hypothesis Agent Workflow
|
| 206 |
+
|
| 207 |
+
```mermaid
|
| 208 |
+
flowchart LR
|
| 209 |
+
Input[Research Query] --> Domain[Identify Domain<br/>& Key Concepts]
|
| 210 |
+
Domain --> Context[Retrieve Background<br/>Knowledge]
|
| 211 |
+
Context --> Generate[Generate 3-5<br/>Initial Hypotheses]
|
| 212 |
+
Generate --> Refine[Refine for<br/>Testability]
|
| 213 |
+
Refine --> Rank[Rank by<br/>Quality Score]
|
| 214 |
+
Rank --> Output[Return Top<br/>Hypotheses]
|
| 215 |
+
|
| 216 |
+
Output --> Struct[Hypothesis Structure:<br/>• Statement<br/>• Rationale<br/>• Testability Score<br/>• Data Requirements<br/>• Expected Outcomes]
|
| 217 |
+
|
| 218 |
+
style Input fill:#e1f5e1
|
| 219 |
+
style Output fill:#fff4e6
|
| 220 |
+
style Struct fill:#e6f3ff
|
| 221 |
+
```
|
| 222 |
+
|
| 223 |
+
## 7. Search Agent Workflow
|
| 224 |
+
|
| 225 |
+
```mermaid
|
| 226 |
+
flowchart TD
|
| 227 |
+
Input[Hypotheses] --> Strategy[Formulate Search<br/>Strategy per Hypothesis]
|
| 228 |
+
|
| 229 |
+
Strategy --> Multi[Multi-Source Search]
|
| 230 |
+
|
| 231 |
+
Multi --> PubMed[PubMed Search<br/>via MCP]
|
| 232 |
+
Multi --> ArXiv[arXiv Search<br/>via MCP]
|
| 233 |
+
Multi --> BioRxiv[bioRxiv Search<br/>via MCP]
|
| 234 |
+
|
| 235 |
+
PubMed --> Aggregate[Aggregate Results]
|
| 236 |
+
ArXiv --> Aggregate
|
| 237 |
+
BioRxiv --> Aggregate
|
| 238 |
+
|
| 239 |
+
Aggregate --> Filter[Filter & Rank<br/>by Relevance]
|
| 240 |
+
Filter --> Dedup[Deduplicate<br/>Cross-Reference]
|
| 241 |
+
Dedup --> Embed[Embed Documents<br/>via MCP]
|
| 242 |
+
Embed --> Vector[(Vector DB)]
|
| 243 |
+
Vector --> RAGRetrieval[RAG Retrieval<br/>Top-K per Hypothesis]
|
| 244 |
+
RAGRetrieval --> Output[Return Contextualized<br/>Search Results]
|
| 245 |
+
|
| 246 |
+
style Input fill:#fff4e6
|
| 247 |
+
style Multi fill:#ffe6e6
|
| 248 |
+
style Vector fill:#ffe6f0
|
| 249 |
+
style Output fill:#e6f3ff
|
| 250 |
+
```
|
| 251 |
+
|
| 252 |
+
## 8. Analysis Agent Workflow
|
| 253 |
+
|
| 254 |
+
```mermaid
|
| 255 |
+
flowchart TD
|
| 256 |
+
Input1[Hypotheses] --> Extract
|
| 257 |
+
Input2[Search Results] --> Extract[Extract Evidence<br/>per Hypothesis]
|
| 258 |
+
|
| 259 |
+
Extract --> Methods[Determine Analysis<br/>Methods Needed]
|
| 260 |
+
|
| 261 |
+
Methods --> Branch{Requires<br/>Computation?}
|
| 262 |
+
Branch -->|Yes| GenCode[Generate Python<br/>Analysis Code]
|
| 263 |
+
Branch -->|No| Qual[Qualitative<br/>Synthesis]
|
| 264 |
+
|
| 265 |
+
GenCode --> Execute[Execute Code<br/>via MCP Sandbox]
|
| 266 |
+
Execute --> Interpret1[Interpret<br/>Results]
|
| 267 |
+
Qual --> Interpret2[Interpret<br/>Findings]
|
| 268 |
+
|
| 269 |
+
Interpret1 --> Synthesize[Synthesize Evidence<br/>Across Sources]
|
| 270 |
+
Interpret2 --> Synthesize
|
| 271 |
+
|
| 272 |
+
Synthesize --> Verdict[Determine Verdict<br/>per Hypothesis]
|
| 273 |
+
Verdict --> Support[• Supported<br/>• Refuted<br/>• Inconclusive]
|
| 274 |
+
Support --> Gaps[Identify Knowledge<br/>Gaps & Limitations]
|
| 275 |
+
Gaps --> Output[Return Analysis<br/>Report]
|
| 276 |
+
|
| 277 |
+
style Input1 fill:#fff4e6
|
| 278 |
+
style Input2 fill:#e6f3ff
|
| 279 |
+
style Execute fill:#ffe6e6
|
| 280 |
+
style Output fill:#e6ffe6
|
| 281 |
+
```
|
| 282 |
+
|
| 283 |
+
## 9. Report Agent Workflow
|
| 284 |
+
|
| 285 |
+
```mermaid
|
| 286 |
+
flowchart TD
|
| 287 |
+
Input1[Query] --> Assemble
|
| 288 |
+
Input2[Hypotheses] --> Assemble
|
| 289 |
+
Input3[Search Results] --> Assemble
|
| 290 |
+
Input4[Analysis] --> Assemble[Assemble Report<br/>Sections]
|
| 291 |
+
|
| 292 |
+
Assemble --> Exec[Executive Summary]
|
| 293 |
+
Assemble --> Intro[Introduction]
|
| 294 |
+
Assemble --> Methods[Methods]
|
| 295 |
+
Assemble --> Results[Results per<br/>Hypothesis]
|
| 296 |
+
Assemble --> Discussion[Discussion]
|
| 297 |
+
Assemble --> Future[Future Directions]
|
| 298 |
+
Assemble --> Refs[References]
|
| 299 |
+
|
| 300 |
+
Results --> VizCheck{Needs<br/>Visualization?}
|
| 301 |
+
VizCheck -->|Yes| GenViz[Generate Viz Code]
|
| 302 |
+
GenViz --> ExecViz[Execute via MCP<br/>Create Charts]
|
| 303 |
+
ExecViz --> Combine
|
| 304 |
+
VizCheck -->|No| Combine[Combine All<br/>Sections]
|
| 305 |
+
|
| 306 |
+
Exec --> Combine
|
| 307 |
+
Intro --> Combine
|
| 308 |
+
Methods --> Combine
|
| 309 |
+
Discussion --> Combine
|
| 310 |
+
Future --> Combine
|
| 311 |
+
Refs --> Combine
|
| 312 |
+
|
| 313 |
+
Combine --> Format[Format Output]
|
| 314 |
+
Format --> MD[Markdown]
|
| 315 |
+
Format --> PDF[PDF]
|
| 316 |
+
Format --> JSON[JSON]
|
| 317 |
+
|
| 318 |
+
MD --> Output[Return Final<br/>Report]
|
| 319 |
+
PDF --> Output
|
| 320 |
+
JSON --> Output
|
| 321 |
+
|
| 322 |
+
style Input1 fill:#e1f5e1
|
| 323 |
+
style Input2 fill:#fff4e6
|
| 324 |
+
style Input3 fill:#e6f3ff
|
| 325 |
+
style Input4 fill:#e6ffe6
|
| 326 |
+
style Output fill:#d4edda
|
| 327 |
+
```
|
| 328 |
+
|
| 329 |
+
## 10. Data Flow & Event Streaming
|
| 330 |
+
|
| 331 |
+
```mermaid
|
| 332 |
+
flowchart TD
|
| 333 |
+
User[👤 User] -->|Research Query| UI[Gradio UI]
|
| 334 |
+
UI -->|Submit| Manager[Magentic Manager]
|
| 335 |
+
|
| 336 |
+
Manager -->|Event: Planning| UI
|
| 337 |
+
Manager -->|Select Agent| HypAgent[Hypothesis Agent]
|
| 338 |
+
HypAgent -->|Event: Delta/Message| UI
|
| 339 |
+
HypAgent -->|Hypotheses| Context[(Shared Context)]
|
| 340 |
+
|
| 341 |
+
Context -->|Retrieved by| Manager
|
| 342 |
+
Manager -->|Select Agent| SearchAgent[Search Agent]
|
| 343 |
+
SearchAgent -->|MCP Request| WebSearch[Web Search Tool]
|
| 344 |
+
WebSearch -->|Results| SearchAgent
|
| 345 |
+
SearchAgent -->|Event: Delta/Message| UI
|
| 346 |
+
SearchAgent -->|Documents| Context
|
| 347 |
+
SearchAgent -->|Embeddings| VectorDB[(Vector DB)]
|
| 348 |
+
|
| 349 |
+
Context -->|Retrieved by| Manager
|
| 350 |
+
Manager -->|Select Agent| AnalysisAgent[Analysis Agent]
|
| 351 |
+
AnalysisAgent -->|MCP Request| CodeExec[Code Execution Tool]
|
| 352 |
+
CodeExec -->|Results| AnalysisAgent
|
| 353 |
+
AnalysisAgent -->|Event: Delta/Message| UI
|
| 354 |
+
AnalysisAgent -->|Analysis| Context
|
| 355 |
+
|
| 356 |
+
Context -->|Retrieved by| Manager
|
| 357 |
+
Manager -->|Select Agent| ReportAgent[Report Agent]
|
| 358 |
+
ReportAgent -->|MCP Request| CodeExec
|
| 359 |
+
ReportAgent -->|Event: Delta/Message| UI
|
| 360 |
+
ReportAgent -->|Report| Context
|
| 361 |
+
|
| 362 |
+
Manager -->|Event: Final Result| UI
|
| 363 |
+
UI -->|Display| User
|
| 364 |
+
|
| 365 |
+
style User fill:#e1f5e1
|
| 366 |
+
style UI fill:#e6f3ff
|
| 367 |
+
style Manager fill:#ffe6e6
|
| 368 |
+
style Context fill:#ffe6f0
|
| 369 |
+
style VectorDB fill:#ffe6f0
|
| 370 |
+
style WebSearch fill:#f0f0f0
|
| 371 |
+
style CodeExec fill:#f0f0f0
|
| 372 |
+
```
|
| 373 |
+
|
| 374 |
+
## 11. MCP Tool Architecture
|
| 375 |
+
|
| 376 |
+
```mermaid
|
| 377 |
+
graph TB
|
| 378 |
+
subgraph "Agent Layer"
|
| 379 |
+
Manager[Magentic Manager]
|
| 380 |
+
HypAgent[Hypothesis Agent]
|
| 381 |
+
SearchAgent[Search Agent]
|
| 382 |
+
AnalysisAgent[Analysis Agent]
|
| 383 |
+
ReportAgent[Report Agent]
|
| 384 |
+
end
|
| 385 |
+
|
| 386 |
+
subgraph "MCP Protocol Layer"
|
| 387 |
+
Registry[MCP Tool Registry<br/>• Discovers tools<br/>• Routes requests<br/>• Manages connections]
|
| 388 |
+
end
|
| 389 |
+
|
| 390 |
+
subgraph "MCP Servers"
|
| 391 |
+
Server1[Web Search Server<br/>localhost:8001<br/>• PubMed<br/>• arXiv<br/>• bioRxiv]
|
| 392 |
+
Server2[Code Execution Server<br/>localhost:8002<br/>• Sandboxed Python<br/>• Package management]
|
| 393 |
+
Server3[RAG Server<br/>localhost:8003<br/>• Vector embeddings<br/>• Similarity search]
|
| 394 |
+
Server4[Visualization Server<br/>localhost:8004<br/>• Chart generation<br/>• Plot rendering]
|
| 395 |
+
end
|
| 396 |
+
|
| 397 |
+
subgraph "External Services"
|
| 398 |
+
PubMed[PubMed API]
|
| 399 |
+
ArXiv[arXiv API]
|
| 400 |
+
BioRxiv[bioRxiv API]
|
| 401 |
+
Modal[Modal Sandbox]
|
| 402 |
+
ChromaDB[(ChromaDB)]
|
| 403 |
+
end
|
| 404 |
+
|
| 405 |
+
SearchAgent -->|Request| Registry
|
| 406 |
+
AnalysisAgent -->|Request| Registry
|
| 407 |
+
ReportAgent -->|Request| Registry
|
| 408 |
+
|
| 409 |
+
Registry --> Server1
|
| 410 |
+
Registry --> Server2
|
| 411 |
+
Registry --> Server3
|
| 412 |
+
Registry --> Server4
|
| 413 |
+
|
| 414 |
+
Server1 --> PubMed
|
| 415 |
+
Server1 --> ArXiv
|
| 416 |
+
Server1 --> BioRxiv
|
| 417 |
+
Server2 --> Modal
|
| 418 |
+
Server3 --> ChromaDB
|
| 419 |
+
|
| 420 |
+
style Manager fill:#ffe6e6
|
| 421 |
+
style Registry fill:#fff4e6
|
| 422 |
+
style Server1 fill:#e6f3ff
|
| 423 |
+
style Server2 fill:#e6f3ff
|
| 424 |
+
style Server3 fill:#e6f3ff
|
| 425 |
+
style Server4 fill:#e6f3ff
|
| 426 |
+
```
|
| 427 |
+
|
| 428 |
+
## 12. Progress Tracking & Stall Detection
|
| 429 |
+
|
| 430 |
+
```mermaid
|
| 431 |
+
stateDiagram-v2
|
| 432 |
+
[*] --> Initialization: User Query
|
| 433 |
+
|
| 434 |
+
Initialization --> Planning: Manager starts
|
| 435 |
+
|
| 436 |
+
Planning --> AgentExecution: Select agent
|
| 437 |
+
|
| 438 |
+
AgentExecution --> Assessment: Collect results
|
| 439 |
+
|
| 440 |
+
Assessment --> QualityCheck: Evaluate output
|
| 441 |
+
|
| 442 |
+
QualityCheck --> AgentExecution: Poor quality<br/>(retry < max_rounds)
|
| 443 |
+
QualityCheck --> Planning: Poor quality<br/>(try different agent)
|
| 444 |
+
QualityCheck --> NextAgent: Good quality<br/>(task incomplete)
|
| 445 |
+
QualityCheck --> Synthesis: Good quality<br/>(task complete)
|
| 446 |
+
|
| 447 |
+
NextAgent --> AgentExecution: Select next agent
|
| 448 |
+
|
| 449 |
+
state StallDetection <<choice>>
|
| 450 |
+
Assessment --> StallDetection: Check progress
|
| 451 |
+
StallDetection --> Planning: No progress<br/>(stall count < max)
|
| 452 |
+
StallDetection --> ErrorRecovery: No progress<br/>(max stalls reached)
|
| 453 |
+
|
| 454 |
+
ErrorRecovery --> PartialReport: Generate partial results
|
| 455 |
+
PartialReport --> [*]
|
| 456 |
+
|
| 457 |
+
Synthesis --> FinalReport: Combine all outputs
|
| 458 |
+
FinalReport --> [*]
|
| 459 |
+
|
| 460 |
+
note right of QualityCheck
|
| 461 |
+
Manager assesses:
|
| 462 |
+
• Output completeness
|
| 463 |
+
• Quality metrics
|
| 464 |
+
• Progress made
|
| 465 |
+
end note
|
| 466 |
+
|
| 467 |
+
note right of StallDetection
|
| 468 |
+
Stall = no new progress
|
| 469 |
+
after agent execution
|
| 470 |
+
Triggers plan reset
|
| 471 |
+
end note
|
| 472 |
+
```
|
| 473 |
+
|
| 474 |
+
## 13. Gradio UI Integration
|
| 475 |
+
|
| 476 |
+
```mermaid
|
| 477 |
+
graph TD
|
| 478 |
+
App[Gradio App<br/>DeepCritical Research Agent]
|
| 479 |
+
|
| 480 |
+
App --> Input[Input Section]
|
| 481 |
+
App --> Status[Status Section]
|
| 482 |
+
App --> Output[Output Section]
|
| 483 |
+
|
| 484 |
+
Input --> Query[Research Question<br/>Text Area]
|
| 485 |
+
Input --> Controls[Controls]
|
| 486 |
+
Controls --> MaxHyp[Max Hypotheses: 1-10]
|
| 487 |
+
Controls --> MaxRounds[Max Rounds: 5-20]
|
| 488 |
+
Controls --> Submit[Start Research Button]
|
| 489 |
+
|
| 490 |
+
Status --> Log[Real-time Event Log<br/>• Manager planning<br/>• Agent selection<br/>• Execution updates<br/>• Quality assessment]
|
| 491 |
+
Status --> Progress[Progress Tracker<br/>• Current agent<br/>• Round count<br/>• Stall count]
|
| 492 |
+
|
| 493 |
+
Output --> Tabs[Tabbed Results]
|
| 494 |
+
Tabs --> Tab1[Hypotheses Tab<br/>Generated hypotheses with scores]
|
| 495 |
+
Tabs --> Tab2[Search Results Tab<br/>Papers & sources found]
|
| 496 |
+
Tabs --> Tab3[Analysis Tab<br/>Evidence & verdicts]
|
| 497 |
+
Tabs --> Tab4[Report Tab<br/>Final research report]
|
| 498 |
+
Tab4 --> Download[Download Report<br/>MD / PDF / JSON]
|
| 499 |
+
|
| 500 |
+
Submit -.->|Triggers| Workflow[Magentic Workflow]
|
| 501 |
+
Workflow -.->|MagenticOrchestratorMessageEvent| Log
|
| 502 |
+
Workflow -.->|MagenticAgentDeltaEvent| Log
|
| 503 |
+
Workflow -.->|MagenticAgentMessageEvent| Log
|
| 504 |
+
Workflow -.->|MagenticFinalResultEvent| Tab4
|
| 505 |
+
|
| 506 |
+
style App fill:#e1f5e1
|
| 507 |
+
style Input fill:#fff4e6
|
| 508 |
+
style Status fill:#e6f3ff
|
| 509 |
+
style Output fill:#e6ffe6
|
| 510 |
+
style Workflow fill:#ffe6e6
|
| 511 |
+
```
|
| 512 |
+
|
| 513 |
+
## 14. Complete System Context
|
| 514 |
+
|
| 515 |
+
```mermaid
|
| 516 |
+
graph LR
|
| 517 |
+
User[👤 Researcher<br/>Asks research questions] -->|Submits query| DC[DeepCritical<br/>Magentic Workflow]
|
| 518 |
+
|
| 519 |
+
DC -->|Literature search| PubMed[PubMed API<br/>Medical papers]
|
| 520 |
+
DC -->|Preprint search| ArXiv[arXiv API<br/>Scientific preprints]
|
| 521 |
+
DC -->|Biology search| BioRxiv[bioRxiv API<br/>Biology preprints]
|
| 522 |
+
DC -->|Agent reasoning| Claude[Claude API<br/>Sonnet 4 / Opus]
|
| 523 |
+
DC -->|Code execution| Modal[Modal Sandbox<br/>Safe Python env]
|
| 524 |
+
DC -->|Vector storage| Chroma[ChromaDB<br/>Embeddings & RAG]
|
| 525 |
+
|
| 526 |
+
DC -->|Deployed on| HF[HuggingFace Spaces<br/>Gradio 6.0]
|
| 527 |
+
|
| 528 |
+
PubMed -->|Results| DC
|
| 529 |
+
ArXiv -->|Results| DC
|
| 530 |
+
BioRxiv -->|Results| DC
|
| 531 |
+
Claude -->|Responses| DC
|
| 532 |
+
Modal -->|Output| DC
|
| 533 |
+
Chroma -->|Context| DC
|
| 534 |
+
|
| 535 |
+
DC -->|Research report| User
|
| 536 |
+
|
| 537 |
+
style User fill:#e1f5e1
|
| 538 |
+
style DC fill:#ffe6e6
|
| 539 |
+
style PubMed fill:#e6f3ff
|
| 540 |
+
style ArXiv fill:#e6f3ff
|
| 541 |
+
style BioRxiv fill:#e6f3ff
|
| 542 |
+
style Claude fill:#ffd6d6
|
| 543 |
+
style Modal fill:#f0f0f0
|
| 544 |
+
style Chroma fill:#ffe6f0
|
| 545 |
+
style HF fill:#d4edda
|
| 546 |
+
```
|
| 547 |
+
|
| 548 |
+
## 15. Workflow Timeline (Simplified)
|
| 549 |
+
|
| 550 |
+
```mermaid
|
| 551 |
+
gantt
|
| 552 |
+
title DeepCritical Magentic Workflow - Typical Execution
|
| 553 |
+
dateFormat mm:ss
|
| 554 |
+
axisFormat %M:%S
|
| 555 |
+
|
| 556 |
+
section Manager Planning
|
| 557 |
+
Initial planning :p1, 00:00, 10s
|
| 558 |
+
|
| 559 |
+
section Hypothesis Agent
|
| 560 |
+
Generate hypotheses :h1, after p1, 30s
|
| 561 |
+
Manager assessment :h2, after h1, 5s
|
| 562 |
+
|
| 563 |
+
section Search Agent
|
| 564 |
+
Search hypothesis 1 :s1, after h2, 20s
|
| 565 |
+
Search hypothesis 2 :s2, after s1, 20s
|
| 566 |
+
Search hypothesis 3 :s3, after s2, 20s
|
| 567 |
+
RAG processing :s4, after s3, 15s
|
| 568 |
+
Manager assessment :s5, after s4, 5s
|
| 569 |
+
|
| 570 |
+
section Analysis Agent
|
| 571 |
+
Evidence extraction :a1, after s5, 15s
|
| 572 |
+
Code generation :a2, after a1, 20s
|
| 573 |
+
Code execution :a3, after a2, 25s
|
| 574 |
+
Synthesis :a4, after a3, 20s
|
| 575 |
+
Manager assessment :a5, after a4, 5s
|
| 576 |
+
|
| 577 |
+
section Report Agent
|
| 578 |
+
Report assembly :r1, after a5, 30s
|
| 579 |
+
Visualization :r2, after r1, 15s
|
| 580 |
+
Formatting :r3, after r2, 10s
|
| 581 |
+
|
| 582 |
+
section Manager Synthesis
|
| 583 |
+
Final synthesis :f1, after r3, 10s
|
| 584 |
+
```
|
| 585 |
+
|
| 586 |
+
---
|
| 587 |
+
|
| 588 |
+
## Key Differences from Original Design
|
| 589 |
+
|
| 590 |
+
| Aspect | Original (Judge-in-Loop) | New (Magentic) |
|
| 591 |
+
|--------|-------------------------|----------------|
|
| 592 |
+
| **Control Flow** | Fixed sequential phases | Dynamic agent selection |
|
| 593 |
+
| **Quality Control** | Separate Judge Agent | Manager assessment built-in |
|
| 594 |
+
| **Retry Logic** | Phase-level with feedback | Agent-level with adaptation |
|
| 595 |
+
| **Flexibility** | Rigid 4-phase pipeline | Adaptive workflow |
|
| 596 |
+
| **Complexity** | 5 agents (including Judge) | 4 agents (no Judge) |
|
| 597 |
+
| **Progress Tracking** | Manual state management | Built-in round/stall detection |
|
| 598 |
+
| **Agent Coordination** | Sequential handoff | Manager-driven dynamic selection |
|
| 599 |
+
| **Error Recovery** | Retry same phase | Try different agent or replan |
|
| 600 |
+
|
| 601 |
+
---
|
| 602 |
+
|
| 603 |
+
## Simplified Design Principles
|
| 604 |
+
|
| 605 |
+
1. **Manager is Intelligent**: LLM-powered manager handles planning, selection, and quality assessment
|
| 606 |
+
2. **No Separate Judge**: Manager's assessment phase replaces dedicated Judge Agent
|
| 607 |
+
3. **Dynamic Workflow**: Agents can be called multiple times in any order based on need
|
| 608 |
+
4. **Built-in Safety**: max_round_count (15) and max_stall_count (3) prevent infinite loops
|
| 609 |
+
5. **Event-Driven UI**: Real-time streaming updates to Gradio interface
|
| 610 |
+
6. **MCP-Powered Tools**: All external capabilities via Model Context Protocol
|
| 611 |
+
7. **Shared Context**: Centralized state accessible to all agents
|
| 612 |
+
8. **Progress Awareness**: Manager tracks what's been done and what's needed
|
| 613 |
+
|
| 614 |
+
---
|
| 615 |
+
|
| 616 |
+
## Legend
|
| 617 |
+
|
| 618 |
+
- 🔴 **Red/Pink**: Manager, orchestration, decision-making
|
| 619 |
+
- 🟡 **Yellow/Orange**: Specialist agents, processing
|
| 620 |
+
- 🔵 **Blue**: Data, tools, MCP services
|
| 621 |
+
- 🟣 **Purple/Pink**: Storage, databases, state
|
| 622 |
+
- 🟢 **Green**: User interactions, final outputs
|
| 623 |
+
- ⚪ **Gray**: External services, APIs
|
| 624 |
+
|
| 625 |
+
---
|
| 626 |
+
|
| 627 |
+
## Implementation Highlights
|
| 628 |
+
|
| 629 |
+
**Simple 4-Agent Setup:**
|
| 630 |
+
```python
|
| 631 |
+
workflow = (
|
| 632 |
+
MagenticBuilder()
|
| 633 |
+
.participants(
|
| 634 |
+
hypothesis=HypothesisAgent(tools=[background_tool]),
|
| 635 |
+
search=SearchAgent(tools=[web_search, rag_tool]),
|
| 636 |
+
analysis=AnalysisAgent(tools=[code_execution]),
|
| 637 |
+
report=ReportAgent(tools=[code_execution, visualization])
|
| 638 |
+
)
|
| 639 |
+
.with_standard_manager(
|
| 640 |
+
chat_client=AnthropicClient(model="claude-sonnet-4"),
|
| 641 |
+
max_round_count=15, # Prevent infinite loops
|
| 642 |
+
max_stall_count=3 # Detect stuck workflows
|
| 643 |
+
)
|
| 644 |
+
.build()
|
| 645 |
+
)
|
| 646 |
+
```
|
| 647 |
+
|
| 648 |
+
**Manager handles quality assessment in its instructions:**
|
| 649 |
+
- Checks hypothesis quality (testable, novel, clear)
|
| 650 |
+
- Validates search results (relevant, authoritative, recent)
|
| 651 |
+
- Assesses analysis soundness (methodology, evidence, conclusions)
|
| 652 |
+
- Ensures report completeness (all sections, proper citations)
|
| 653 |
+
|
| 654 |
+
No separate Judge Agent needed - manager does it all!
|
| 655 |
+
|
| 656 |
+
---
|
| 657 |
+
|
| 658 |
+
**Document Version**: 2.0 (Magentic Simplified)
|
| 659 |
+
**Last Updated**: 2025-11-24
|
| 660 |
+
**Architecture**: Microsoft Magentic Orchestration Pattern
|
| 661 |
+
**Agents**: 4 (Hypothesis, Search, Analysis, Report) + 1 Manager
|
| 662 |
+
**License**: MIT
|
examples/modal_demo/test_code_execution.py
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Demo script to test Modal code execution integration.
|
| 2 |
+
|
| 3 |
+
Run with: uv run python examples/modal_demo/test_code_execution.py
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import sys
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
|
| 9 |
+
# Add src to path
|
| 10 |
+
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
| 11 |
+
|
| 12 |
+
from src.tools.code_execution import CodeExecutionError, get_code_executor
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def test_basic_execution():
|
| 16 |
+
"""Test basic code execution."""
|
| 17 |
+
print("\n=== Test 1: Basic Execution ===")
|
| 18 |
+
executor = get_code_executor()
|
| 19 |
+
|
| 20 |
+
code = """
|
| 21 |
+
print("Hello from Modal sandbox!")
|
| 22 |
+
result = 2 + 2
|
| 23 |
+
print(f"2 + 2 = {result}")
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
result = executor.execute(code)
|
| 27 |
+
print(f"Success: {result['success']}")
|
| 28 |
+
print(f"Stdout:\n{result['stdout']}")
|
| 29 |
+
if result["stderr"]:
|
| 30 |
+
print(f"Stderr:\n{result['stderr']}")
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def test_scientific_computing():
|
| 34 |
+
"""Test scientific computing libraries."""
|
| 35 |
+
print("\n=== Test 2: Scientific Computing ===")
|
| 36 |
+
executor = get_code_executor()
|
| 37 |
+
|
| 38 |
+
code = """
|
| 39 |
+
import pandas as pd
|
| 40 |
+
import numpy as np
|
| 41 |
+
|
| 42 |
+
# Create sample data
|
| 43 |
+
data = {
|
| 44 |
+
'drug': ['DrugA', 'DrugB', 'DrugC'],
|
| 45 |
+
'efficacy': [0.75, 0.82, 0.68],
|
| 46 |
+
'sample_size': [100, 150, 120]
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
df = pd.DataFrame(data)
|
| 50 |
+
|
| 51 |
+
# Calculate weighted average
|
| 52 |
+
weighted_avg = np.average(df['efficacy'], weights=df['sample_size'])
|
| 53 |
+
|
| 54 |
+
print(f"Drugs tested: {len(df)}")
|
| 55 |
+
print(f"Weighted average efficacy: {weighted_avg:.3f}")
|
| 56 |
+
print("\\nDataFrame:")
|
| 57 |
+
print(df.to_string())
|
| 58 |
+
"""
|
| 59 |
+
|
| 60 |
+
result = executor.execute(code)
|
| 61 |
+
print(f"Success: {result['success']}")
|
| 62 |
+
print(f"Output:\n{result['stdout']}")
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def test_statistical_analysis():
|
| 66 |
+
"""Test statistical analysis."""
|
| 67 |
+
print("\n=== Test 3: Statistical Analysis ===")
|
| 68 |
+
executor = get_code_executor()
|
| 69 |
+
|
| 70 |
+
code = """
|
| 71 |
+
import numpy as np
|
| 72 |
+
from scipy import stats
|
| 73 |
+
|
| 74 |
+
# Simulate two treatment groups
|
| 75 |
+
np.random.seed(42)
|
| 76 |
+
control_group = np.random.normal(100, 15, 50)
|
| 77 |
+
treatment_group = np.random.normal(110, 15, 50)
|
| 78 |
+
|
| 79 |
+
# Perform t-test
|
| 80 |
+
t_stat, p_value = stats.ttest_ind(treatment_group, control_group)
|
| 81 |
+
|
| 82 |
+
print(f"Control mean: {np.mean(control_group):.2f}")
|
| 83 |
+
print(f"Treatment mean: {np.mean(treatment_group):.2f}")
|
| 84 |
+
print(f"T-statistic: {t_stat:.3f}")
|
| 85 |
+
print(f"P-value: {p_value:.4f}")
|
| 86 |
+
|
| 87 |
+
if p_value < 0.05:
|
| 88 |
+
print("Result: Statistically significant difference")
|
| 89 |
+
else:
|
| 90 |
+
print("Result: No significant difference")
|
| 91 |
+
"""
|
| 92 |
+
|
| 93 |
+
result = executor.execute(code)
|
| 94 |
+
print(f"Success: {result['success']}")
|
| 95 |
+
print(f"Output:\n{result['stdout']}")
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def test_with_return_value():
|
| 99 |
+
"""Test execute_with_return method."""
|
| 100 |
+
print("\n=== Test 4: Return Value ===")
|
| 101 |
+
executor = get_code_executor()
|
| 102 |
+
|
| 103 |
+
code = """
|
| 104 |
+
import numpy as np
|
| 105 |
+
|
| 106 |
+
# Calculate something
|
| 107 |
+
data = np.array([1, 2, 3, 4, 5])
|
| 108 |
+
result = {
|
| 109 |
+
'mean': float(np.mean(data)),
|
| 110 |
+
'std': float(np.std(data)),
|
| 111 |
+
'sum': int(np.sum(data))
|
| 112 |
+
}
|
| 113 |
+
"""
|
| 114 |
+
|
| 115 |
+
try:
|
| 116 |
+
result = executor.execute_with_return(code)
|
| 117 |
+
print(f"Returned result: {result}")
|
| 118 |
+
print(f"Mean: {result['mean']}")
|
| 119 |
+
print(f"Std: {result['std']}")
|
| 120 |
+
print(f"Sum: {result['sum']}")
|
| 121 |
+
except CodeExecutionError as e:
|
| 122 |
+
print(f"Error: {e}")
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def test_error_handling():
|
| 126 |
+
"""Test error handling."""
|
| 127 |
+
print("\n=== Test 5: Error Handling ===")
|
| 128 |
+
executor = get_code_executor()
|
| 129 |
+
|
| 130 |
+
code = """
|
| 131 |
+
# This will fail
|
| 132 |
+
x = 1 / 0
|
| 133 |
+
"""
|
| 134 |
+
|
| 135 |
+
result = executor.execute(code)
|
| 136 |
+
print(f"Success: {result['success']}")
|
| 137 |
+
print(f"Error: {result['error']}")
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
def main():
|
| 141 |
+
"""Run all tests."""
|
| 142 |
+
print("=" * 60)
|
| 143 |
+
print("Modal Code Execution Demo")
|
| 144 |
+
print("=" * 60)
|
| 145 |
+
|
| 146 |
+
tests = [
|
| 147 |
+
test_basic_execution,
|
| 148 |
+
test_scientific_computing,
|
| 149 |
+
test_statistical_analysis,
|
| 150 |
+
test_with_return_value,
|
| 151 |
+
test_error_handling,
|
| 152 |
+
]
|
| 153 |
+
|
| 154 |
+
for test in tests:
|
| 155 |
+
try:
|
| 156 |
+
test()
|
| 157 |
+
except Exception as e:
|
| 158 |
+
print(f"\n❌ Test failed: {e}")
|
| 159 |
+
import traceback
|
| 160 |
+
|
| 161 |
+
traceback.print_exc()
|
| 162 |
+
|
| 163 |
+
print("\n" + "=" * 60)
|
| 164 |
+
print("Demo completed!")
|
| 165 |
+
print("=" * 60)
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
if __name__ == "__main__":
|
| 169 |
+
main()
|
examples/modal_demo/verify_sandbox.py
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Verification script to prove code is running in Modal sandboxes, not locally.
|
| 2 |
+
|
| 3 |
+
This script runs tests that would behave differently in a sandbox vs local execution.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import sys
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
|
| 9 |
+
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
| 10 |
+
|
| 11 |
+
from src.tools.code_execution import SANDBOX_LIBRARIES, get_code_executor
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def test_1_hostname_check():
|
| 15 |
+
"""Test 1: Check hostname - should be different in sandbox."""
|
| 16 |
+
print("\n" + "=" * 60)
|
| 17 |
+
print("TEST 1: Hostname Check")
|
| 18 |
+
print("=" * 60)
|
| 19 |
+
|
| 20 |
+
executor = get_code_executor()
|
| 21 |
+
|
| 22 |
+
# Get local hostname
|
| 23 |
+
import socket
|
| 24 |
+
|
| 25 |
+
local_hostname = socket.gethostname()
|
| 26 |
+
print(f"Local hostname: {local_hostname}")
|
| 27 |
+
|
| 28 |
+
# Get sandbox hostname
|
| 29 |
+
code = """
|
| 30 |
+
import socket
|
| 31 |
+
hostname = socket.gethostname()
|
| 32 |
+
print(f"Sandbox hostname: {hostname}")
|
| 33 |
+
"""
|
| 34 |
+
|
| 35 |
+
result = executor.execute(code)
|
| 36 |
+
print(f"\n{result['stdout']}")
|
| 37 |
+
|
| 38 |
+
if local_hostname in result["stdout"]:
|
| 39 |
+
print("⚠️ WARNING: Hostnames match - might be running locally!")
|
| 40 |
+
return False
|
| 41 |
+
else:
|
| 42 |
+
print("✅ SUCCESS: Different hostnames - running in sandbox!")
|
| 43 |
+
return True
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def test_2_file_system_isolation():
|
| 47 |
+
"""Test 2: Try to access local files - should fail in sandbox."""
|
| 48 |
+
print("\n" + "=" * 60)
|
| 49 |
+
print("TEST 2: File System Isolation")
|
| 50 |
+
print("=" * 60)
|
| 51 |
+
|
| 52 |
+
executor = get_code_executor()
|
| 53 |
+
|
| 54 |
+
# Try to read our own source file
|
| 55 |
+
local_file = Path(__file__).resolve()
|
| 56 |
+
print(f"Local file exists: {local_file}")
|
| 57 |
+
print(f"Can read locally: {local_file.exists()}")
|
| 58 |
+
|
| 59 |
+
# Try to access it from sandbox (use POSIX path for Windows compatibility)
|
| 60 |
+
code = f"""
|
| 61 |
+
from pathlib import Path
|
| 62 |
+
file_path = Path("{local_file.as_posix()}")
|
| 63 |
+
exists = file_path.exists()
|
| 64 |
+
print(f"File exists in sandbox: {{exists}}")
|
| 65 |
+
if exists:
|
| 66 |
+
print("⚠️ Can access local filesystem!")
|
| 67 |
+
else:
|
| 68 |
+
print("✅ Filesystem is isolated!")
|
| 69 |
+
"""
|
| 70 |
+
|
| 71 |
+
result = executor.execute(code)
|
| 72 |
+
print(f"\n{result['stdout']}")
|
| 73 |
+
|
| 74 |
+
if "File exists in sandbox: True" in result["stdout"]:
|
| 75 |
+
print("\n⚠️ WARNING: Can access local files - not properly sandboxed!")
|
| 76 |
+
return False
|
| 77 |
+
else:
|
| 78 |
+
print("\n✅ SUCCESS: Cannot access local files - properly sandboxed!")
|
| 79 |
+
return True
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def test_3_process_information():
|
| 83 |
+
"""Test 3: Check process and container info."""
|
| 84 |
+
print("\n" + "=" * 60)
|
| 85 |
+
print("TEST 3: Process Information")
|
| 86 |
+
print("=" * 60)
|
| 87 |
+
|
| 88 |
+
executor = get_code_executor()
|
| 89 |
+
|
| 90 |
+
code = """
|
| 91 |
+
import os
|
| 92 |
+
import sys
|
| 93 |
+
import platform
|
| 94 |
+
|
| 95 |
+
print(f"Python version: {sys.version}")
|
| 96 |
+
print(f"Platform: {platform.platform()}")
|
| 97 |
+
print(f"Machine: {platform.machine()}")
|
| 98 |
+
print(f"Process ID: {os.getpid()}")
|
| 99 |
+
print(f"User: {os.getenv('USER', 'unknown')}")
|
| 100 |
+
print(f"Home: {os.getenv('HOME', 'unknown')}")
|
| 101 |
+
print(f"Working directory: {os.getcwd()}")
|
| 102 |
+
|
| 103 |
+
# Check if running in container
|
| 104 |
+
in_container = os.path.exists('/.dockerenv') or os.path.exists('/run/.containerenv')
|
| 105 |
+
print(f"In container: {in_container}")
|
| 106 |
+
"""
|
| 107 |
+
|
| 108 |
+
result = executor.execute(code)
|
| 109 |
+
print(f"\n{result['stdout']}")
|
| 110 |
+
|
| 111 |
+
if "In container: True" in result["stdout"]:
|
| 112 |
+
print("\n✅ SUCCESS: Running in containerized environment!")
|
| 113 |
+
return True
|
| 114 |
+
else:
|
| 115 |
+
print("\n⚠️ WARNING: Not detecting container environment")
|
| 116 |
+
return False
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def test_4_library_versions():
|
| 120 |
+
"""Test 4: Check if scientific libraries match Modal image specs."""
|
| 121 |
+
print("\n" + "=" * 60)
|
| 122 |
+
print("TEST 4: Library Versions (Should match Modal image)")
|
| 123 |
+
print("=" * 60)
|
| 124 |
+
|
| 125 |
+
executor = get_code_executor()
|
| 126 |
+
|
| 127 |
+
code = """
|
| 128 |
+
import pandas as pd
|
| 129 |
+
import numpy as np
|
| 130 |
+
import scipy
|
| 131 |
+
import matplotlib
|
| 132 |
+
import sklearn
|
| 133 |
+
import statsmodels
|
| 134 |
+
|
| 135 |
+
print(f"pandas: {pd.__version__}")
|
| 136 |
+
print(f"numpy: {np.__version__}")
|
| 137 |
+
print(f"scipy: {scipy.__version__}")
|
| 138 |
+
print(f"matplotlib: {matplotlib.__version__}")
|
| 139 |
+
print(f"scikit-learn: {sklearn.__version__}")
|
| 140 |
+
print(f"statsmodels: {statsmodels.__version__}")
|
| 141 |
+
"""
|
| 142 |
+
|
| 143 |
+
result = executor.execute(code)
|
| 144 |
+
print(f"\n{result['stdout']}")
|
| 145 |
+
|
| 146 |
+
# Check if versions match what we specified in code_execution.py
|
| 147 |
+
expected_versions = {
|
| 148 |
+
f"pandas: {SANDBOX_LIBRARIES['pandas']}": True,
|
| 149 |
+
f"numpy: {SANDBOX_LIBRARIES['numpy']}": True,
|
| 150 |
+
f"scipy: {SANDBOX_LIBRARIES['scipy']}": True,
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
matches = 0
|
| 154 |
+
for expected in expected_versions:
|
| 155 |
+
if expected in result["stdout"]:
|
| 156 |
+
matches += 1
|
| 157 |
+
print(f"✅ {expected}")
|
| 158 |
+
|
| 159 |
+
if matches >= 2:
|
| 160 |
+
print(f"\n✅ SUCCESS: Library versions match Modal image spec ({matches}/3)")
|
| 161 |
+
return True
|
| 162 |
+
else:
|
| 163 |
+
print(f"\n⚠️ WARNING: Library versions don't match ({matches}/3)")
|
| 164 |
+
return False
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
def test_5_destructive_operations():
|
| 168 |
+
"""Test 5: Try destructive operations that would be dangerous locally."""
|
| 169 |
+
print("\n" + "=" * 60)
|
| 170 |
+
print("TEST 5: Destructive Operations (Safe in sandbox)")
|
| 171 |
+
print("=" * 60)
|
| 172 |
+
|
| 173 |
+
executor = get_code_executor()
|
| 174 |
+
|
| 175 |
+
code = """
|
| 176 |
+
import os
|
| 177 |
+
import tempfile
|
| 178 |
+
|
| 179 |
+
# Try to write to /tmp (should work)
|
| 180 |
+
tmp_file = "/tmp/test_modal_sandbox.txt"
|
| 181 |
+
try:
|
| 182 |
+
with open(tmp_file, 'w') as f:
|
| 183 |
+
f.write("Test write to /tmp")
|
| 184 |
+
print(f"✅ Can write to /tmp: {tmp_file}")
|
| 185 |
+
os.remove(tmp_file)
|
| 186 |
+
print("✅ Can delete from /tmp")
|
| 187 |
+
except Exception as e:
|
| 188 |
+
print(f"❌ Error with /tmp: {e}")
|
| 189 |
+
|
| 190 |
+
# Try to write to /root (might fail due to permissions)
|
| 191 |
+
try:
|
| 192 |
+
test_file = "/root/test.txt"
|
| 193 |
+
with open(test_file, 'w') as f:
|
| 194 |
+
f.write("Test")
|
| 195 |
+
print(f"✅ Can write to /root (running as root in container)")
|
| 196 |
+
os.remove(test_file)
|
| 197 |
+
except Exception as e:
|
| 198 |
+
print(f"⚠️ Cannot write to /root: {e}")
|
| 199 |
+
|
| 200 |
+
# Check what user we're running as
|
| 201 |
+
print(f"Running as UID: {os.getuid()}")
|
| 202 |
+
print(f"Running as GID: {os.getgid()}")
|
| 203 |
+
"""
|
| 204 |
+
|
| 205 |
+
result = executor.execute(code)
|
| 206 |
+
print(f"\n{result['stdout']}")
|
| 207 |
+
|
| 208 |
+
if "Can write to /tmp" in result["stdout"]:
|
| 209 |
+
print("\n✅ SUCCESS: Sandbox has expected filesystem permissions!")
|
| 210 |
+
return True
|
| 211 |
+
else:
|
| 212 |
+
print("\n⚠️ WARNING: Unexpected filesystem behavior")
|
| 213 |
+
return False
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
def test_6_network_isolation():
|
| 217 |
+
"""Test 6: Check network access (should be allowed by default in our config)."""
|
| 218 |
+
print("\n" + "=" * 60)
|
| 219 |
+
print("TEST 6: Network Access Check")
|
| 220 |
+
print("=" * 60)
|
| 221 |
+
|
| 222 |
+
executor = get_code_executor()
|
| 223 |
+
|
| 224 |
+
code = """
|
| 225 |
+
import socket
|
| 226 |
+
|
| 227 |
+
# Try to resolve a hostname
|
| 228 |
+
try:
|
| 229 |
+
ip = socket.gethostbyname('google.com')
|
| 230 |
+
print(f"✅ Can resolve DNS: google.com -> {ip}")
|
| 231 |
+
print("(Network is enabled - can be disabled for security)")
|
| 232 |
+
except Exception as e:
|
| 233 |
+
print(f"❌ Cannot resolve DNS: {e}")
|
| 234 |
+
print("(Network is blocked)")
|
| 235 |
+
"""
|
| 236 |
+
|
| 237 |
+
result = executor.execute(code)
|
| 238 |
+
print(f"\n{result['stdout']}")
|
| 239 |
+
|
| 240 |
+
return True # Either result is valid
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
def main():
|
| 244 |
+
"""Run all verification tests."""
|
| 245 |
+
print("\n" + "=" * 70)
|
| 246 |
+
print(" " * 15 + "MODAL SANDBOX VERIFICATION")
|
| 247 |
+
print("=" * 70)
|
| 248 |
+
print("\nThese tests verify code is running in Modal sandboxes, not locally.")
|
| 249 |
+
print("=" * 70)
|
| 250 |
+
|
| 251 |
+
tests = [
|
| 252 |
+
("Hostname Isolation", test_1_hostname_check),
|
| 253 |
+
("Filesystem Isolation", test_2_file_system_isolation),
|
| 254 |
+
("Container Detection", test_3_process_information),
|
| 255 |
+
("Library Versions", test_4_library_versions),
|
| 256 |
+
("Destructive Operations", test_5_destructive_operations),
|
| 257 |
+
("Network Access", test_6_network_isolation),
|
| 258 |
+
]
|
| 259 |
+
|
| 260 |
+
results = []
|
| 261 |
+
for name, test_func in tests:
|
| 262 |
+
try:
|
| 263 |
+
passed = test_func()
|
| 264 |
+
results.append((name, passed))
|
| 265 |
+
except Exception as e:
|
| 266 |
+
print(f"\n❌ Test failed with exception: {e}")
|
| 267 |
+
import traceback
|
| 268 |
+
|
| 269 |
+
traceback.print_exc()
|
| 270 |
+
results.append((name, False))
|
| 271 |
+
|
| 272 |
+
# Summary
|
| 273 |
+
print("\n" + "=" * 70)
|
| 274 |
+
print(" " * 25 + "SUMMARY")
|
| 275 |
+
print("=" * 70)
|
| 276 |
+
|
| 277 |
+
passed = sum(1 for _, result in results if result)
|
| 278 |
+
total = len(results)
|
| 279 |
+
|
| 280 |
+
for name, result in results:
|
| 281 |
+
status = "✅ PASS" if result else "❌ FAIL"
|
| 282 |
+
print(f"{status} - {name}")
|
| 283 |
+
|
| 284 |
+
print("=" * 70)
|
| 285 |
+
print(f"\nResults: {passed}/{total} tests passed")
|
| 286 |
+
|
| 287 |
+
if passed >= 4:
|
| 288 |
+
print("\n🎉 Modal sandboxing is working correctly!")
|
| 289 |
+
elif passed >= 2:
|
| 290 |
+
print("\n⚠️ Some tests failed - review output above")
|
| 291 |
+
else:
|
| 292 |
+
print("\n❌ Modal sandboxing may not be working - check configuration")
|
| 293 |
+
|
| 294 |
+
print("=" * 70)
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
if __name__ == "__main__":
|
| 298 |
+
main()
|
pyproject.toml
CHANGED
|
@@ -47,6 +47,15 @@ embeddings = [
|
|
| 47 |
"chromadb>=0.4.0",
|
| 48 |
"sentence-transformers>=2.2.0",
|
| 49 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
[build-system]
|
| 52 |
requires = ["hatchling"]
|
|
@@ -75,6 +84,9 @@ select = [
|
|
| 75 |
ignore = [
|
| 76 |
"PLR0913", # Too many arguments (agents need many params)
|
| 77 |
"PLR0912", # Too many branches (complex orchestrator logic)
|
|
|
|
|
|
|
|
|
|
| 78 |
"PLC0415", # Lazy imports for optional dependencies
|
| 79 |
"E402", # Module level import not at top (needed for pytest.importorskip)
|
| 80 |
"RUF100", # Unused noqa (version differences between local/CI)
|
|
|
|
| 47 |
"chromadb>=0.4.0",
|
| 48 |
"sentence-transformers>=2.2.0",
|
| 49 |
]
|
| 50 |
+
modal = [
|
| 51 |
+
# Mario's Modal code execution + LlamaIndex RAG
|
| 52 |
+
"modal>=0.63.0",
|
| 53 |
+
"llama-index>=0.11.0",
|
| 54 |
+
"llama-index-llms-openai",
|
| 55 |
+
"llama-index-embeddings-openai",
|
| 56 |
+
"llama-index-vector-stores-chroma",
|
| 57 |
+
"chromadb>=0.4.0",
|
| 58 |
+
]
|
| 59 |
|
| 60 |
[build-system]
|
| 61 |
requires = ["hatchling"]
|
|
|
|
| 84 |
ignore = [
|
| 85 |
"PLR0913", # Too many arguments (agents need many params)
|
| 86 |
"PLR0912", # Too many branches (complex orchestrator logic)
|
| 87 |
+
"PLR0911", # Too many return statements (complex agent logic)
|
| 88 |
+
"PLR2004", # Magic values (statistical constants like p-values)
|
| 89 |
+
"PLW0603", # Global statement (singleton pattern for Modal)
|
| 90 |
"PLC0415", # Lazy imports for optional dependencies
|
| 91 |
"E402", # Module level import not at top (needed for pytest.importorskip)
|
| 92 |
"RUF100", # Unused noqa (version differences between local/CI)
|
src/agents/analysis_agent.py
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Analysis agent for statistical analysis using Modal code execution."""
|
| 2 |
+
|
| 3 |
+
import asyncio
|
| 4 |
+
from collections.abc import AsyncIterable
|
| 5 |
+
from functools import partial
|
| 6 |
+
from typing import TYPE_CHECKING, Any
|
| 7 |
+
|
| 8 |
+
from agent_framework import (
|
| 9 |
+
AgentRunResponse,
|
| 10 |
+
AgentRunResponseUpdate,
|
| 11 |
+
AgentThread,
|
| 12 |
+
BaseAgent,
|
| 13 |
+
ChatMessage,
|
| 14 |
+
Role,
|
| 15 |
+
)
|
| 16 |
+
from pydantic import BaseModel, Field
|
| 17 |
+
from pydantic_ai import Agent
|
| 18 |
+
|
| 19 |
+
from src.agent_factory.judges import get_model
|
| 20 |
+
from src.tools.code_execution import (
|
| 21 |
+
CodeExecutionError,
|
| 22 |
+
get_code_executor,
|
| 23 |
+
get_sandbox_library_prompt,
|
| 24 |
+
)
|
| 25 |
+
from src.utils.models import Evidence
|
| 26 |
+
|
| 27 |
+
if TYPE_CHECKING:
|
| 28 |
+
from src.services.embeddings import EmbeddingService
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class AnalysisResult(BaseModel):
|
| 32 |
+
"""Result of statistical analysis."""
|
| 33 |
+
|
| 34 |
+
verdict: str = Field(
|
| 35 |
+
description="SUPPORTED, REFUTED, or INCONCLUSIVE",
|
| 36 |
+
)
|
| 37 |
+
confidence: float = Field(ge=0.0, le=1.0, description="Confidence in verdict (0-1)")
|
| 38 |
+
statistical_evidence: str = Field(
|
| 39 |
+
description="Summary of statistical findings from code execution"
|
| 40 |
+
)
|
| 41 |
+
code_generated: str = Field(description="Python code that was executed")
|
| 42 |
+
execution_output: str = Field(description="Output from code execution")
|
| 43 |
+
key_findings: list[str] = Field(default_factory=list, description="Key takeaways from analysis")
|
| 44 |
+
limitations: list[str] = Field(default_factory=list, description="Limitations of the analysis")
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
class AnalysisAgent(BaseAgent): # type: ignore[misc]
|
| 48 |
+
"""Performs statistical analysis using Modal code execution.
|
| 49 |
+
|
| 50 |
+
This agent:
|
| 51 |
+
1. Retrieves relevant evidence using RAG (if available)
|
| 52 |
+
2. Generates Python code for statistical analysis
|
| 53 |
+
3. Executes code in Modal sandbox
|
| 54 |
+
4. Interprets results
|
| 55 |
+
5. Returns verdict (SUPPORTED/REFUTED/INCONCLUSIVE)
|
| 56 |
+
"""
|
| 57 |
+
|
| 58 |
+
def __init__(
|
| 59 |
+
self,
|
| 60 |
+
evidence_store: dict[str, Any],
|
| 61 |
+
embedding_service: "EmbeddingService | None" = None,
|
| 62 |
+
) -> None:
|
| 63 |
+
super().__init__(
|
| 64 |
+
name="AnalysisAgent",
|
| 65 |
+
description="Performs statistical analysis of evidence using secure code execution",
|
| 66 |
+
)
|
| 67 |
+
self._evidence_store = evidence_store
|
| 68 |
+
self._embeddings = embedding_service
|
| 69 |
+
self._code_executor: Any = None # Lazy initialized
|
| 70 |
+
self._agent: Agent[None, str] | None = None # LLM for code generation
|
| 71 |
+
|
| 72 |
+
def _get_code_executor(self) -> Any:
|
| 73 |
+
"""Lazy initialization of code executor (avoids failing if Modal not configured)."""
|
| 74 |
+
if self._code_executor is None:
|
| 75 |
+
self._code_executor = get_code_executor()
|
| 76 |
+
return self._code_executor
|
| 77 |
+
|
| 78 |
+
def _get_agent(self) -> Agent[None, str]:
|
| 79 |
+
"""Lazy initialization of LLM agent."""
|
| 80 |
+
if self._agent is None:
|
| 81 |
+
self._agent = Agent(
|
| 82 |
+
model=get_model(),
|
| 83 |
+
output_type=str, # Returns code as string
|
| 84 |
+
system_prompt=self._get_system_prompt(),
|
| 85 |
+
)
|
| 86 |
+
return self._agent
|
| 87 |
+
|
| 88 |
+
def _get_system_prompt(self) -> str:
|
| 89 |
+
"""System prompt for code generation."""
|
| 90 |
+
library_versions = get_sandbox_library_prompt()
|
| 91 |
+
return f"""You are a biomedical data scientist specializing in statistical analysis.
|
| 92 |
+
|
| 93 |
+
Your task: Generate Python code to analyze research evidence and test hypotheses.
|
| 94 |
+
|
| 95 |
+
Guidelines:
|
| 96 |
+
1. Use pandas, numpy, scipy.stats for analysis
|
| 97 |
+
2. Generate code that prints clear, interpretable results
|
| 98 |
+
3. Include statistical tests (t-tests, chi-square, meta-analysis, etc.)
|
| 99 |
+
4. Calculate effect sizes and confidence intervals
|
| 100 |
+
5. Print summary statistics and test results
|
| 101 |
+
6. Keep code concise (<50 lines)
|
| 102 |
+
7. Set a variable called 'result' with final verdict
|
| 103 |
+
|
| 104 |
+
Available libraries:
|
| 105 |
+
{library_versions}
|
| 106 |
+
|
| 107 |
+
Output format:
|
| 108 |
+
Return ONLY executable Python code, no explanations or markdown.
|
| 109 |
+
"""
|
| 110 |
+
|
| 111 |
+
async def run(
|
| 112 |
+
self,
|
| 113 |
+
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
|
| 114 |
+
*,
|
| 115 |
+
thread: AgentThread | None = None,
|
| 116 |
+
**kwargs: Any,
|
| 117 |
+
) -> AgentRunResponse:
|
| 118 |
+
"""Analyze evidence and return verdict."""
|
| 119 |
+
# Extract query and hypothesis
|
| 120 |
+
query = self._extract_query(messages)
|
| 121 |
+
hypotheses = self._evidence_store.get("hypotheses", [])
|
| 122 |
+
evidence = self._evidence_store.get("current", [])
|
| 123 |
+
|
| 124 |
+
if not hypotheses:
|
| 125 |
+
return self._error_response("No hypotheses available. Run HypothesisAgent first.")
|
| 126 |
+
|
| 127 |
+
if not evidence:
|
| 128 |
+
return self._error_response("No evidence available. Run SearchAgent first.")
|
| 129 |
+
|
| 130 |
+
# Get primary hypothesis (guaranteed to exist after check above)
|
| 131 |
+
primary = hypotheses[0]
|
| 132 |
+
|
| 133 |
+
# Retrieve relevant evidence using RAG (if available)
|
| 134 |
+
relevant_evidence = await self._retrieve_relevant_evidence(primary, evidence)
|
| 135 |
+
|
| 136 |
+
# Generate analysis code
|
| 137 |
+
code_prompt = self._create_code_generation_prompt(query, primary, relevant_evidence)
|
| 138 |
+
|
| 139 |
+
try:
|
| 140 |
+
# Generate code using LLM
|
| 141 |
+
agent = self._get_agent()
|
| 142 |
+
code_result = await agent.run(code_prompt)
|
| 143 |
+
generated_code = code_result.output
|
| 144 |
+
|
| 145 |
+
# Execute code in Modal sandbox (run in thread to avoid blocking event loop)
|
| 146 |
+
loop = asyncio.get_running_loop()
|
| 147 |
+
executor = self._get_code_executor()
|
| 148 |
+
execution_result = await loop.run_in_executor(
|
| 149 |
+
None, partial(executor.execute, generated_code, timeout=120)
|
| 150 |
+
)
|
| 151 |
+
|
| 152 |
+
if not execution_result["success"]:
|
| 153 |
+
return self._error_response(f"Code execution failed: {execution_result['error']}")
|
| 154 |
+
|
| 155 |
+
# Interpret results
|
| 156 |
+
analysis_result = await self._interpret_results(
|
| 157 |
+
query, primary, generated_code, execution_result
|
| 158 |
+
)
|
| 159 |
+
|
| 160 |
+
# Store analysis in shared context
|
| 161 |
+
self._evidence_store["analysis"] = analysis_result.model_dump()
|
| 162 |
+
|
| 163 |
+
# Format response
|
| 164 |
+
response_text = self._format_response(analysis_result)
|
| 165 |
+
|
| 166 |
+
return AgentRunResponse(
|
| 167 |
+
messages=[ChatMessage(role=Role.ASSISTANT, text=response_text)],
|
| 168 |
+
response_id=f"analysis-{analysis_result.verdict.lower()}",
|
| 169 |
+
additional_properties={"analysis": analysis_result.model_dump()},
|
| 170 |
+
)
|
| 171 |
+
|
| 172 |
+
except CodeExecutionError as e:
|
| 173 |
+
return self._error_response(f"Analysis failed: {e}")
|
| 174 |
+
except Exception as e:
|
| 175 |
+
return self._error_response(f"Unexpected error: {e}")
|
| 176 |
+
|
| 177 |
+
async def _retrieve_relevant_evidence(
|
| 178 |
+
self, hypothesis: Any, all_evidence: list[Evidence]
|
| 179 |
+
) -> list[Evidence]:
|
| 180 |
+
"""Retrieve most relevant evidence using RAG (if available).
|
| 181 |
+
|
| 182 |
+
TODO: When embeddings service is available (self._embeddings),
|
| 183 |
+
use semantic search to find evidence most relevant to the hypothesis.
|
| 184 |
+
For now, returns top 10 evidence items.
|
| 185 |
+
"""
|
| 186 |
+
# Future: Use self._embeddings for semantic search
|
| 187 |
+
return all_evidence[:10]
|
| 188 |
+
|
| 189 |
+
def _create_code_generation_prompt(
|
| 190 |
+
self, query: str, hypothesis: Any, evidence: list[Evidence]
|
| 191 |
+
) -> str:
|
| 192 |
+
"""Create prompt for code generation."""
|
| 193 |
+
# Extract data from evidence
|
| 194 |
+
evidence_summary = self._summarize_evidence(evidence)
|
| 195 |
+
|
| 196 |
+
prompt = f"""Generate Python code to statistically analyze the following hypothesis:
|
| 197 |
+
|
| 198 |
+
**Original Question**: {query}
|
| 199 |
+
|
| 200 |
+
**Hypothesis**: {hypothesis.drug} → {hypothesis.target} → {hypothesis.pathway} → {hypothesis.effect}
|
| 201 |
+
**Confidence**: {hypothesis.confidence:.0%}
|
| 202 |
+
|
| 203 |
+
**Evidence Summary**:
|
| 204 |
+
{evidence_summary}
|
| 205 |
+
|
| 206 |
+
**Task**:
|
| 207 |
+
1. Parse the evidence data
|
| 208 |
+
2. Perform appropriate statistical tests
|
| 209 |
+
3. Calculate effect sizes and confidence intervals
|
| 210 |
+
4. Determine verdict: SUPPORTED, REFUTED, or INCONCLUSIVE
|
| 211 |
+
5. Set result variable to verdict string
|
| 212 |
+
|
| 213 |
+
Generate executable Python code only (no markdown, no explanations).
|
| 214 |
+
"""
|
| 215 |
+
return prompt
|
| 216 |
+
|
| 217 |
+
def _summarize_evidence(self, evidence: list[Evidence]) -> str:
|
| 218 |
+
"""Summarize evidence for code generation prompt."""
|
| 219 |
+
if not evidence:
|
| 220 |
+
return "No evidence available."
|
| 221 |
+
|
| 222 |
+
lines = []
|
| 223 |
+
for i, ev in enumerate(evidence[:5], 1): # Top 5 most relevant
|
| 224 |
+
lines.append(f"{i}. {ev.content[:200]}...")
|
| 225 |
+
lines.append(f" Source: {ev.citation.title}")
|
| 226 |
+
lines.append(f" Relevance: {ev.relevance:.0%}\n")
|
| 227 |
+
|
| 228 |
+
return "\n".join(lines)
|
| 229 |
+
|
| 230 |
+
async def _interpret_results(
|
| 231 |
+
self,
|
| 232 |
+
query: str,
|
| 233 |
+
hypothesis: Any,
|
| 234 |
+
code: str,
|
| 235 |
+
execution_result: dict[str, Any],
|
| 236 |
+
) -> AnalysisResult:
|
| 237 |
+
"""Interpret code execution results using LLM."""
|
| 238 |
+
import re
|
| 239 |
+
|
| 240 |
+
# Extract verdict from output using robust word-boundary matching
|
| 241 |
+
stdout = execution_result["stdout"]
|
| 242 |
+
stdout_upper = stdout.upper()
|
| 243 |
+
verdict = "INCONCLUSIVE" # Default
|
| 244 |
+
|
| 245 |
+
# Avoid false positives like "NOT SUPPORTED" or "UNSUPPORTED"
|
| 246 |
+
if re.search(r"\bSUPPORTED\b", stdout_upper) and not re.search(
|
| 247 |
+
r"\b(?:NOT|UN)SUPPORTED\b", stdout_upper
|
| 248 |
+
):
|
| 249 |
+
verdict = "SUPPORTED"
|
| 250 |
+
elif re.search(r"\bREFUTED\b", stdout_upper):
|
| 251 |
+
verdict = "REFUTED"
|
| 252 |
+
elif re.search(r"\bINCONCLUSIVE\b", stdout_upper):
|
| 253 |
+
verdict = "INCONCLUSIVE"
|
| 254 |
+
|
| 255 |
+
# Parse key findings from output
|
| 256 |
+
key_findings = self._extract_findings(stdout)
|
| 257 |
+
|
| 258 |
+
# Calculate confidence based on statistical significance
|
| 259 |
+
confidence = self._calculate_confidence(stdout)
|
| 260 |
+
|
| 261 |
+
return AnalysisResult(
|
| 262 |
+
verdict=verdict,
|
| 263 |
+
confidence=confidence,
|
| 264 |
+
statistical_evidence=stdout.strip(),
|
| 265 |
+
code_generated=code,
|
| 266 |
+
execution_output=stdout,
|
| 267 |
+
key_findings=key_findings,
|
| 268 |
+
limitations=[
|
| 269 |
+
"Analysis based on summary data only",
|
| 270 |
+
"Limited to available evidence",
|
| 271 |
+
"Statistical tests assume data independence",
|
| 272 |
+
],
|
| 273 |
+
)
|
| 274 |
+
|
| 275 |
+
def _extract_findings(self, output: str) -> list[str]:
|
| 276 |
+
"""Extract key findings from code output."""
|
| 277 |
+
findings = []
|
| 278 |
+
|
| 279 |
+
# Look for common statistical patterns
|
| 280 |
+
lines = output.split("\n")
|
| 281 |
+
for line in lines:
|
| 282 |
+
line_lower = line.lower()
|
| 283 |
+
if any(
|
| 284 |
+
keyword in line_lower
|
| 285 |
+
for keyword in ["p-value", "significant", "effect size", "correlation", "mean"]
|
| 286 |
+
):
|
| 287 |
+
findings.append(line.strip())
|
| 288 |
+
|
| 289 |
+
return findings[:5] # Top 5 findings
|
| 290 |
+
|
| 291 |
+
def _calculate_confidence(self, output: str) -> float:
|
| 292 |
+
"""Calculate confidence based on statistical results."""
|
| 293 |
+
# Look for p-values
|
| 294 |
+
import re
|
| 295 |
+
|
| 296 |
+
p_values = re.findall(r"p[-\s]?value[:\s]+(\d+\.?\d*)", output.lower())
|
| 297 |
+
|
| 298 |
+
if p_values:
|
| 299 |
+
try:
|
| 300 |
+
min_p = min(float(p) for p in p_values)
|
| 301 |
+
# Higher confidence for lower p-values
|
| 302 |
+
if min_p < 0.001:
|
| 303 |
+
return 0.95
|
| 304 |
+
elif min_p < 0.01:
|
| 305 |
+
return 0.90
|
| 306 |
+
elif min_p < 0.05:
|
| 307 |
+
return 0.80
|
| 308 |
+
else:
|
| 309 |
+
return 0.60
|
| 310 |
+
except ValueError:
|
| 311 |
+
pass
|
| 312 |
+
|
| 313 |
+
# Default medium confidence
|
| 314 |
+
return 0.70
|
| 315 |
+
|
| 316 |
+
def _format_response(self, result: AnalysisResult) -> str:
|
| 317 |
+
"""Format analysis result as markdown."""
|
| 318 |
+
lines = [
|
| 319 |
+
"## Statistical Analysis Complete\n",
|
| 320 |
+
f"### Verdict: **{result.verdict}**",
|
| 321 |
+
f"**Confidence**: {result.confidence:.0%}\n",
|
| 322 |
+
"### Key Findings",
|
| 323 |
+
]
|
| 324 |
+
|
| 325 |
+
for finding in result.key_findings:
|
| 326 |
+
lines.append(f"- {finding}")
|
| 327 |
+
|
| 328 |
+
lines.extend(
|
| 329 |
+
[
|
| 330 |
+
"\n### Statistical Evidence",
|
| 331 |
+
"```",
|
| 332 |
+
result.statistical_evidence,
|
| 333 |
+
"```",
|
| 334 |
+
"\n### Generated Code",
|
| 335 |
+
"```python",
|
| 336 |
+
result.code_generated,
|
| 337 |
+
"```",
|
| 338 |
+
"\n### Limitations",
|
| 339 |
+
]
|
| 340 |
+
)
|
| 341 |
+
|
| 342 |
+
for limitation in result.limitations:
|
| 343 |
+
lines.append(f"- {limitation}")
|
| 344 |
+
|
| 345 |
+
return "\n".join(lines)
|
| 346 |
+
|
| 347 |
+
def _error_response(self, message: str) -> AgentRunResponse:
|
| 348 |
+
"""Create error response."""
|
| 349 |
+
return AgentRunResponse(
|
| 350 |
+
messages=[ChatMessage(role=Role.ASSISTANT, text=f"❌ **Error**: {message}")],
|
| 351 |
+
response_id="analysis-error",
|
| 352 |
+
)
|
| 353 |
+
|
| 354 |
+
def _extract_query(
|
| 355 |
+
self, messages: str | ChatMessage | list[str] | list[ChatMessage] | None
|
| 356 |
+
) -> str:
|
| 357 |
+
"""Extract query from messages."""
|
| 358 |
+
if isinstance(messages, str):
|
| 359 |
+
return messages
|
| 360 |
+
elif isinstance(messages, ChatMessage):
|
| 361 |
+
return messages.text or ""
|
| 362 |
+
elif isinstance(messages, list):
|
| 363 |
+
for msg in reversed(messages):
|
| 364 |
+
if isinstance(msg, ChatMessage) and msg.role == Role.USER:
|
| 365 |
+
return msg.text or ""
|
| 366 |
+
elif isinstance(msg, str):
|
| 367 |
+
return msg
|
| 368 |
+
return ""
|
| 369 |
+
|
| 370 |
+
async def run_stream(
|
| 371 |
+
self,
|
| 372 |
+
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
|
| 373 |
+
*,
|
| 374 |
+
thread: AgentThread | None = None,
|
| 375 |
+
**kwargs: Any,
|
| 376 |
+
) -> AsyncIterable[AgentRunResponseUpdate]:
|
| 377 |
+
"""Streaming wrapper."""
|
| 378 |
+
result = await self.run(messages, thread=thread, **kwargs)
|
| 379 |
+
yield AgentRunResponseUpdate(messages=result.messages, response_id=result.response_id)
|
src/services/embeddings.py
CHANGED
|
@@ -11,18 +11,24 @@ import chromadb
|
|
| 11 |
import structlog
|
| 12 |
from sentence_transformers import SentenceTransformer
|
| 13 |
|
|
|
|
| 14 |
from src.utils.models import Evidence
|
| 15 |
|
| 16 |
|
| 17 |
class EmbeddingService:
|
| 18 |
-
"""Handles text embedding and vector storage.
|
| 19 |
|
| 20 |
All embedding operations run in a thread pool to avoid blocking
|
| 21 |
the async event loop.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
"""
|
| 23 |
|
| 24 |
-
def __init__(self, model_name: str =
|
| 25 |
-
self.
|
|
|
|
| 26 |
self._client = chromadb.Client() # In-memory for hackathon
|
| 27 |
self._collection = self._client.create_collection(
|
| 28 |
name="evidence", metadata={"hnsw:space": "cosine"}
|
|
|
|
| 11 |
import structlog
|
| 12 |
from sentence_transformers import SentenceTransformer
|
| 13 |
|
| 14 |
+
from src.utils.config import settings
|
| 15 |
from src.utils.models import Evidence
|
| 16 |
|
| 17 |
|
| 18 |
class EmbeddingService:
|
| 19 |
+
"""Handles text embedding and vector storage using local sentence-transformers.
|
| 20 |
|
| 21 |
All embedding operations run in a thread pool to avoid blocking
|
| 22 |
the async event loop.
|
| 23 |
+
|
| 24 |
+
Note:
|
| 25 |
+
Uses local sentence-transformers models (no API key required).
|
| 26 |
+
Model is configured via settings.local_embedding_model.
|
| 27 |
"""
|
| 28 |
|
| 29 |
+
def __init__(self, model_name: str | None = None):
|
| 30 |
+
self._model_name = model_name or settings.local_embedding_model
|
| 31 |
+
self._model = SentenceTransformer(self._model_name)
|
| 32 |
self._client = chromadb.Client() # In-memory for hackathon
|
| 33 |
self._collection = self._client.create_collection(
|
| 34 |
name="evidence", metadata={"hnsw:space": "cosine"}
|
src/services/llamaindex_rag.py
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""LlamaIndex RAG service for evidence retrieval and indexing.
|
| 2 |
+
|
| 3 |
+
Requires optional dependencies: uv sync --extra modal
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from typing import Any
|
| 7 |
+
|
| 8 |
+
import structlog
|
| 9 |
+
|
| 10 |
+
from src.utils.config import settings
|
| 11 |
+
from src.utils.exceptions import ConfigurationError
|
| 12 |
+
from src.utils.models import Evidence
|
| 13 |
+
|
| 14 |
+
logger = structlog.get_logger()
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class LlamaIndexRAGService:
|
| 18 |
+
"""RAG service using LlamaIndex with ChromaDB vector store.
|
| 19 |
+
|
| 20 |
+
Note:
|
| 21 |
+
This service is currently OpenAI-only. It uses OpenAI embeddings and LLM
|
| 22 |
+
regardless of the global `settings.llm_provider` configuration.
|
| 23 |
+
Requires OPENAI_API_KEY to be set.
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
def __init__(
|
| 27 |
+
self,
|
| 28 |
+
collection_name: str = "deepcritical_evidence",
|
| 29 |
+
persist_dir: str | None = None,
|
| 30 |
+
embedding_model: str | None = None,
|
| 31 |
+
similarity_top_k: int = 5,
|
| 32 |
+
) -> None:
|
| 33 |
+
"""
|
| 34 |
+
Initialize LlamaIndex RAG service.
|
| 35 |
+
|
| 36 |
+
Args:
|
| 37 |
+
collection_name: Name of the ChromaDB collection
|
| 38 |
+
persist_dir: Directory to persist ChromaDB data
|
| 39 |
+
embedding_model: OpenAI embedding model (defaults to settings.openai_embedding_model)
|
| 40 |
+
similarity_top_k: Number of top results to retrieve
|
| 41 |
+
"""
|
| 42 |
+
# Lazy import - only when instantiated
|
| 43 |
+
try:
|
| 44 |
+
import chromadb
|
| 45 |
+
from llama_index.core import Document, Settings, StorageContext, VectorStoreIndex
|
| 46 |
+
from llama_index.core.retrievers import VectorIndexRetriever
|
| 47 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 48 |
+
from llama_index.llms.openai import OpenAI
|
| 49 |
+
from llama_index.vector_stores.chroma import ChromaVectorStore
|
| 50 |
+
except ImportError as e:
|
| 51 |
+
raise ImportError(
|
| 52 |
+
"LlamaIndex dependencies not installed. Run: uv sync --extra modal"
|
| 53 |
+
) from e
|
| 54 |
+
|
| 55 |
+
# Store references for use in other methods
|
| 56 |
+
self._chromadb = chromadb
|
| 57 |
+
self._Document = Document
|
| 58 |
+
self._Settings = Settings
|
| 59 |
+
self._StorageContext = StorageContext
|
| 60 |
+
self._VectorStoreIndex = VectorStoreIndex
|
| 61 |
+
self._VectorIndexRetriever = VectorIndexRetriever
|
| 62 |
+
self._ChromaVectorStore = ChromaVectorStore
|
| 63 |
+
|
| 64 |
+
self.collection_name = collection_name
|
| 65 |
+
self.persist_dir = persist_dir or settings.chroma_db_path
|
| 66 |
+
self.similarity_top_k = similarity_top_k
|
| 67 |
+
self.embedding_model = embedding_model or settings.openai_embedding_model
|
| 68 |
+
|
| 69 |
+
# Validate API key before use
|
| 70 |
+
if not settings.openai_api_key:
|
| 71 |
+
raise ConfigurationError("OPENAI_API_KEY required for LlamaIndex RAG service")
|
| 72 |
+
|
| 73 |
+
# Configure LlamaIndex settings (use centralized config)
|
| 74 |
+
self._Settings.llm = OpenAI(
|
| 75 |
+
model=settings.openai_model,
|
| 76 |
+
api_key=settings.openai_api_key,
|
| 77 |
+
)
|
| 78 |
+
self._Settings.embed_model = OpenAIEmbedding(
|
| 79 |
+
model=self.embedding_model,
|
| 80 |
+
api_key=settings.openai_api_key,
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
# Initialize ChromaDB client
|
| 84 |
+
self.chroma_client = self._chromadb.PersistentClient(path=self.persist_dir)
|
| 85 |
+
|
| 86 |
+
# Get or create collection
|
| 87 |
+
try:
|
| 88 |
+
self.collection = self.chroma_client.get_collection(self.collection_name)
|
| 89 |
+
logger.info("loaded_existing_collection", name=self.collection_name)
|
| 90 |
+
except Exception:
|
| 91 |
+
self.collection = self.chroma_client.create_collection(self.collection_name)
|
| 92 |
+
logger.info("created_new_collection", name=self.collection_name)
|
| 93 |
+
|
| 94 |
+
# Initialize vector store and index
|
| 95 |
+
self.vector_store = self._ChromaVectorStore(chroma_collection=self.collection)
|
| 96 |
+
self.storage_context = self._StorageContext.from_defaults(vector_store=self.vector_store)
|
| 97 |
+
|
| 98 |
+
# Try to load existing index, or create empty one
|
| 99 |
+
try:
|
| 100 |
+
self.index = self._VectorStoreIndex.from_vector_store(
|
| 101 |
+
vector_store=self.vector_store,
|
| 102 |
+
storage_context=self.storage_context,
|
| 103 |
+
)
|
| 104 |
+
logger.info("loaded_existing_index")
|
| 105 |
+
except Exception:
|
| 106 |
+
self.index = self._VectorStoreIndex([], storage_context=self.storage_context)
|
| 107 |
+
logger.info("created_new_index")
|
| 108 |
+
|
| 109 |
+
def ingest_evidence(self, evidence_list: list[Evidence]) -> None:
|
| 110 |
+
"""
|
| 111 |
+
Ingest evidence into the vector store.
|
| 112 |
+
|
| 113 |
+
Args:
|
| 114 |
+
evidence_list: List of Evidence objects to ingest
|
| 115 |
+
"""
|
| 116 |
+
if not evidence_list:
|
| 117 |
+
logger.warning("no_evidence_to_ingest")
|
| 118 |
+
return
|
| 119 |
+
|
| 120 |
+
# Convert Evidence objects to LlamaIndex Documents
|
| 121 |
+
documents = []
|
| 122 |
+
for evidence in evidence_list:
|
| 123 |
+
metadata = {
|
| 124 |
+
"source": evidence.citation.source,
|
| 125 |
+
"title": evidence.citation.title,
|
| 126 |
+
"url": evidence.citation.url,
|
| 127 |
+
"date": evidence.citation.date,
|
| 128 |
+
"authors": ", ".join(evidence.citation.authors),
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
doc = self._Document(
|
| 132 |
+
text=evidence.content,
|
| 133 |
+
metadata=metadata,
|
| 134 |
+
doc_id=evidence.citation.url, # Use URL as unique ID
|
| 135 |
+
)
|
| 136 |
+
documents.append(doc)
|
| 137 |
+
|
| 138 |
+
# Insert documents into index
|
| 139 |
+
try:
|
| 140 |
+
for doc in documents:
|
| 141 |
+
self.index.insert(doc)
|
| 142 |
+
logger.info("ingested_evidence", count=len(documents))
|
| 143 |
+
except Exception as e:
|
| 144 |
+
logger.error("failed_to_ingest_evidence", error=str(e))
|
| 145 |
+
raise
|
| 146 |
+
|
| 147 |
+
def ingest_documents(self, documents: list[Any]) -> None:
|
| 148 |
+
"""
|
| 149 |
+
Ingest raw LlamaIndex Documents.
|
| 150 |
+
|
| 151 |
+
Args:
|
| 152 |
+
documents: List of LlamaIndex Document objects
|
| 153 |
+
"""
|
| 154 |
+
if not documents:
|
| 155 |
+
logger.warning("no_documents_to_ingest")
|
| 156 |
+
return
|
| 157 |
+
|
| 158 |
+
try:
|
| 159 |
+
for doc in documents:
|
| 160 |
+
self.index.insert(doc)
|
| 161 |
+
logger.info("ingested_documents", count=len(documents))
|
| 162 |
+
except Exception as e:
|
| 163 |
+
logger.error("failed_to_ingest_documents", error=str(e))
|
| 164 |
+
raise
|
| 165 |
+
|
| 166 |
+
def retrieve(self, query: str, top_k: int | None = None) -> list[dict[str, Any]]:
|
| 167 |
+
"""
|
| 168 |
+
Retrieve relevant documents for a query.
|
| 169 |
+
|
| 170 |
+
Args:
|
| 171 |
+
query: Query string
|
| 172 |
+
top_k: Number of results to return (defaults to similarity_top_k)
|
| 173 |
+
|
| 174 |
+
Returns:
|
| 175 |
+
List of retrieved documents with metadata and scores
|
| 176 |
+
"""
|
| 177 |
+
k = top_k or self.similarity_top_k
|
| 178 |
+
|
| 179 |
+
# Create retriever
|
| 180 |
+
retriever = self._VectorIndexRetriever(
|
| 181 |
+
index=self.index,
|
| 182 |
+
similarity_top_k=k,
|
| 183 |
+
)
|
| 184 |
+
|
| 185 |
+
try:
|
| 186 |
+
# Retrieve nodes
|
| 187 |
+
nodes = retriever.retrieve(query)
|
| 188 |
+
|
| 189 |
+
# Convert to dict format
|
| 190 |
+
results = []
|
| 191 |
+
for node in nodes:
|
| 192 |
+
results.append(
|
| 193 |
+
{
|
| 194 |
+
"text": node.node.get_content(),
|
| 195 |
+
"score": node.score,
|
| 196 |
+
"metadata": node.node.metadata,
|
| 197 |
+
}
|
| 198 |
+
)
|
| 199 |
+
|
| 200 |
+
logger.info("retrieved_documents", query=query[:50], count=len(results))
|
| 201 |
+
return results
|
| 202 |
+
|
| 203 |
+
except Exception as e:
|
| 204 |
+
logger.error("failed_to_retrieve", error=str(e), query=query[:50])
|
| 205 |
+
raise # Re-raise to allow callers to distinguish errors from empty results
|
| 206 |
+
|
| 207 |
+
def query(self, query_str: str, top_k: int | None = None) -> str:
|
| 208 |
+
"""
|
| 209 |
+
Query the RAG system and get a synthesized response.
|
| 210 |
+
|
| 211 |
+
Args:
|
| 212 |
+
query_str: Query string
|
| 213 |
+
top_k: Number of results to use (defaults to similarity_top_k)
|
| 214 |
+
|
| 215 |
+
Returns:
|
| 216 |
+
Synthesized response string
|
| 217 |
+
"""
|
| 218 |
+
k = top_k or self.similarity_top_k
|
| 219 |
+
|
| 220 |
+
# Create query engine
|
| 221 |
+
query_engine = self.index.as_query_engine(
|
| 222 |
+
similarity_top_k=k,
|
| 223 |
+
)
|
| 224 |
+
|
| 225 |
+
try:
|
| 226 |
+
response = query_engine.query(query_str)
|
| 227 |
+
logger.info("generated_response", query=query_str[:50])
|
| 228 |
+
return str(response)
|
| 229 |
+
|
| 230 |
+
except Exception as e:
|
| 231 |
+
logger.error("failed_to_query", error=str(e), query=query_str[:50])
|
| 232 |
+
raise # Re-raise to allow callers to handle errors explicitly
|
| 233 |
+
|
| 234 |
+
def clear_collection(self) -> None:
|
| 235 |
+
"""Clear all documents from the collection."""
|
| 236 |
+
try:
|
| 237 |
+
self.chroma_client.delete_collection(self.collection_name)
|
| 238 |
+
self.collection = self.chroma_client.create_collection(self.collection_name)
|
| 239 |
+
self.vector_store = self._ChromaVectorStore(chroma_collection=self.collection)
|
| 240 |
+
self.storage_context = self._StorageContext.from_defaults(
|
| 241 |
+
vector_store=self.vector_store
|
| 242 |
+
)
|
| 243 |
+
self.index = self._VectorStoreIndex([], storage_context=self.storage_context)
|
| 244 |
+
logger.info("cleared_collection", name=self.collection_name)
|
| 245 |
+
except Exception as e:
|
| 246 |
+
logger.error("failed_to_clear_collection", error=str(e))
|
| 247 |
+
raise
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
def get_rag_service(
|
| 251 |
+
collection_name: str = "deepcritical_evidence",
|
| 252 |
+
**kwargs: Any,
|
| 253 |
+
) -> LlamaIndexRAGService:
|
| 254 |
+
"""
|
| 255 |
+
Get or create a RAG service instance.
|
| 256 |
+
|
| 257 |
+
Args:
|
| 258 |
+
collection_name: Name of the ChromaDB collection
|
| 259 |
+
**kwargs: Additional arguments for LlamaIndexRAGService
|
| 260 |
+
|
| 261 |
+
Returns:
|
| 262 |
+
Configured LlamaIndexRAGService instance
|
| 263 |
+
"""
|
| 264 |
+
return LlamaIndexRAGService(collection_name=collection_name, **kwargs)
|
src/tools/code_execution.py
CHANGED
|
@@ -0,0 +1,256 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Modal-based secure code execution tool for statistical analysis.
|
| 2 |
+
|
| 3 |
+
This module provides sandboxed Python code execution using Modal's serverless infrastructure.
|
| 4 |
+
It's designed for running LLM-generated statistical analysis code safely.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import os
|
| 8 |
+
from functools import lru_cache
|
| 9 |
+
from typing import Any
|
| 10 |
+
|
| 11 |
+
import structlog
|
| 12 |
+
|
| 13 |
+
logger = structlog.get_logger(__name__)
|
| 14 |
+
|
| 15 |
+
# Shared library versions for Modal sandbox - used by both executor and LLM prompts
|
| 16 |
+
# Keep these in sync to avoid version mismatch between generated code and execution
|
| 17 |
+
SANDBOX_LIBRARIES: dict[str, str] = {
|
| 18 |
+
"pandas": "2.2.0",
|
| 19 |
+
"numpy": "1.26.4",
|
| 20 |
+
"scipy": "1.11.4",
|
| 21 |
+
"matplotlib": "3.8.2",
|
| 22 |
+
"scikit-learn": "1.4.0",
|
| 23 |
+
"statsmodels": "0.14.1",
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def get_sandbox_library_list() -> list[str]:
|
| 28 |
+
"""Get list of library==version strings for Modal image."""
|
| 29 |
+
return [f"{lib}=={ver}" for lib, ver in SANDBOX_LIBRARIES.items()]
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def get_sandbox_library_prompt() -> str:
|
| 33 |
+
"""Get formatted library versions for LLM prompts."""
|
| 34 |
+
return "\n".join(f"- {lib}=={ver}" for lib, ver in SANDBOX_LIBRARIES.items())
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class CodeExecutionError(Exception):
|
| 38 |
+
"""Raised when code execution fails."""
|
| 39 |
+
|
| 40 |
+
pass
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
class ModalCodeExecutor:
|
| 44 |
+
"""Execute Python code securely using Modal sandboxes.
|
| 45 |
+
|
| 46 |
+
This class provides a safe environment for executing LLM-generated code,
|
| 47 |
+
particularly for scientific computing and statistical analysis tasks.
|
| 48 |
+
|
| 49 |
+
Features:
|
| 50 |
+
- Sandboxed execution (isolated from host system)
|
| 51 |
+
- Pre-installed scientific libraries (numpy, scipy, pandas, matplotlib)
|
| 52 |
+
- Network isolation for security
|
| 53 |
+
- Timeout protection
|
| 54 |
+
- Stdout/stderr capture
|
| 55 |
+
|
| 56 |
+
Example:
|
| 57 |
+
>>> executor = ModalCodeExecutor()
|
| 58 |
+
>>> result = executor.execute('''
|
| 59 |
+
... import pandas as pd
|
| 60 |
+
... df = pd.DataFrame({'a': [1, 2, 3]})
|
| 61 |
+
... result = df['a'].sum()
|
| 62 |
+
... ''')
|
| 63 |
+
>>> print(result['stdout'])
|
| 64 |
+
6
|
| 65 |
+
"""
|
| 66 |
+
|
| 67 |
+
def __init__(self) -> None:
|
| 68 |
+
"""Initialize Modal code executor.
|
| 69 |
+
|
| 70 |
+
Note:
|
| 71 |
+
Logs a warning if Modal credentials are not configured.
|
| 72 |
+
Execution will fail at runtime without valid credentials.
|
| 73 |
+
"""
|
| 74 |
+
# Check for Modal credentials
|
| 75 |
+
self.modal_token_id = os.getenv("MODAL_TOKEN_ID")
|
| 76 |
+
self.modal_token_secret = os.getenv("MODAL_TOKEN_SECRET")
|
| 77 |
+
|
| 78 |
+
if not self.modal_token_id or not self.modal_token_secret:
|
| 79 |
+
logger.warning(
|
| 80 |
+
"Modal credentials not found. Code execution will fail unless modal setup is run."
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
def execute(self, code: str, timeout: int = 60, allow_network: bool = False) -> dict[str, Any]:
|
| 84 |
+
"""Execute Python code in a Modal sandbox.
|
| 85 |
+
|
| 86 |
+
Args:
|
| 87 |
+
code: Python code to execute
|
| 88 |
+
timeout: Maximum execution time in seconds (default: 60)
|
| 89 |
+
allow_network: Whether to allow network access (default: False for security)
|
| 90 |
+
|
| 91 |
+
Returns:
|
| 92 |
+
Dictionary containing:
|
| 93 |
+
- stdout: Standard output from code execution
|
| 94 |
+
- stderr: Standard error from code execution
|
| 95 |
+
- success: Boolean indicating if execution succeeded
|
| 96 |
+
- error: Error message if execution failed
|
| 97 |
+
|
| 98 |
+
Raises:
|
| 99 |
+
CodeExecutionError: If execution fails or times out
|
| 100 |
+
"""
|
| 101 |
+
try:
|
| 102 |
+
import modal
|
| 103 |
+
except ImportError as e:
|
| 104 |
+
raise CodeExecutionError(
|
| 105 |
+
"Modal SDK not installed. Run: uv sync or pip install modal>=0.63.0"
|
| 106 |
+
) from e
|
| 107 |
+
|
| 108 |
+
logger.info("executing_code", code_length=len(code), timeout=timeout)
|
| 109 |
+
|
| 110 |
+
try:
|
| 111 |
+
# Create or lookup Modal app
|
| 112 |
+
app = modal.App.lookup("deepcritical-code-execution", create_if_missing=True)
|
| 113 |
+
|
| 114 |
+
# Define scientific computing image with common libraries
|
| 115 |
+
scientific_image = modal.Image.debian_slim(python_version="3.11").uv_pip_install(
|
| 116 |
+
*get_sandbox_library_list()
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
# Create sandbox with security restrictions
|
| 120 |
+
sandbox = modal.Sandbox.create(
|
| 121 |
+
app=app,
|
| 122 |
+
image=scientific_image,
|
| 123 |
+
timeout=timeout,
|
| 124 |
+
block_network=not allow_network, # Wire the network control
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
try:
|
| 128 |
+
# Execute the code
|
| 129 |
+
# Wrap code to capture result
|
| 130 |
+
wrapped_code = f"""
|
| 131 |
+
import sys
|
| 132 |
+
import io
|
| 133 |
+
from contextlib import redirect_stdout, redirect_stderr
|
| 134 |
+
|
| 135 |
+
stdout_io = io.StringIO()
|
| 136 |
+
stderr_io = io.StringIO()
|
| 137 |
+
|
| 138 |
+
try:
|
| 139 |
+
with redirect_stdout(stdout_io), redirect_stderr(stderr_io):
|
| 140 |
+
{self._indent_code(code, 8)}
|
| 141 |
+
print("__EXECUTION_SUCCESS__")
|
| 142 |
+
except Exception as e:
|
| 143 |
+
print(f"__EXECUTION_ERROR__: {{type(e).__name__}}: {{e}}", file=sys.stderr)
|
| 144 |
+
|
| 145 |
+
print("__STDOUT_START__")
|
| 146 |
+
print(stdout_io.getvalue())
|
| 147 |
+
print("__STDOUT_END__")
|
| 148 |
+
print("__STDERR_START__")
|
| 149 |
+
print(stderr_io.getvalue(), file=sys.stderr)
|
| 150 |
+
print("__STDERR_END__", file=sys.stderr)
|
| 151 |
+
"""
|
| 152 |
+
|
| 153 |
+
# Run the wrapped code
|
| 154 |
+
process = sandbox.exec("python", "-c", wrapped_code, timeout=timeout)
|
| 155 |
+
|
| 156 |
+
# Read output
|
| 157 |
+
stdout_raw = process.stdout.read()
|
| 158 |
+
stderr_raw = process.stderr.read()
|
| 159 |
+
finally:
|
| 160 |
+
# Always clean up sandbox to prevent resource leaks
|
| 161 |
+
sandbox.terminate()
|
| 162 |
+
|
| 163 |
+
# Parse output
|
| 164 |
+
success = "__EXECUTION_SUCCESS__" in stdout_raw
|
| 165 |
+
|
| 166 |
+
# Extract actual stdout/stderr
|
| 167 |
+
stdout = self._extract_output(stdout_raw, "__STDOUT_START__", "__STDOUT_END__")
|
| 168 |
+
stderr = self._extract_output(stderr_raw, "__STDERR_START__", "__STDERR_END__")
|
| 169 |
+
|
| 170 |
+
result = {
|
| 171 |
+
"stdout": stdout,
|
| 172 |
+
"stderr": stderr,
|
| 173 |
+
"success": success,
|
| 174 |
+
"error": stderr if not success else None,
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
logger.info(
|
| 178 |
+
"code_execution_completed",
|
| 179 |
+
success=success,
|
| 180 |
+
stdout_length=len(stdout),
|
| 181 |
+
stderr_length=len(stderr),
|
| 182 |
+
)
|
| 183 |
+
|
| 184 |
+
return result
|
| 185 |
+
|
| 186 |
+
except Exception as e:
|
| 187 |
+
logger.error("code_execution_failed", error=str(e), error_type=type(e).__name__)
|
| 188 |
+
raise CodeExecutionError(f"Code execution failed: {e}") from e
|
| 189 |
+
|
| 190 |
+
def execute_with_return(self, code: str, timeout: int = 60) -> Any:
|
| 191 |
+
"""Execute code and return the value of the 'result' variable.
|
| 192 |
+
|
| 193 |
+
Convenience method that executes code and extracts a return value.
|
| 194 |
+
The code should assign its final result to a variable named 'result'.
|
| 195 |
+
|
| 196 |
+
Args:
|
| 197 |
+
code: Python code to execute (must set 'result' variable)
|
| 198 |
+
timeout: Maximum execution time in seconds
|
| 199 |
+
|
| 200 |
+
Returns:
|
| 201 |
+
The value of the 'result' variable from the executed code
|
| 202 |
+
|
| 203 |
+
Example:
|
| 204 |
+
>>> executor.execute_with_return("result = 2 + 2")
|
| 205 |
+
4
|
| 206 |
+
"""
|
| 207 |
+
# Modify code to print result as JSON
|
| 208 |
+
wrapped = f"""
|
| 209 |
+
import json
|
| 210 |
+
{code}
|
| 211 |
+
print(json.dumps({{"__RESULT__": result}}))
|
| 212 |
+
"""
|
| 213 |
+
|
| 214 |
+
execution_result = self.execute(wrapped, timeout=timeout)
|
| 215 |
+
|
| 216 |
+
if not execution_result["success"]:
|
| 217 |
+
raise CodeExecutionError(f"Execution failed: {execution_result['error']}")
|
| 218 |
+
|
| 219 |
+
# Parse result from stdout
|
| 220 |
+
import json
|
| 221 |
+
|
| 222 |
+
try:
|
| 223 |
+
output = execution_result["stdout"].strip()
|
| 224 |
+
if "__RESULT__" in output:
|
| 225 |
+
# Extract JSON line
|
| 226 |
+
for line in output.split("\n"):
|
| 227 |
+
if "__RESULT__" in line:
|
| 228 |
+
data = json.loads(line)
|
| 229 |
+
return data["__RESULT__"]
|
| 230 |
+
raise ValueError("Result not found in output")
|
| 231 |
+
except (json.JSONDecodeError, ValueError) as e:
|
| 232 |
+
logger.warning(
|
| 233 |
+
"failed_to_parse_result", error=str(e), stdout=execution_result["stdout"]
|
| 234 |
+
)
|
| 235 |
+
return execution_result["stdout"]
|
| 236 |
+
|
| 237 |
+
def _indent_code(self, code: str, spaces: int) -> str:
|
| 238 |
+
"""Indent code by specified number of spaces."""
|
| 239 |
+
indent = " " * spaces
|
| 240 |
+
return "\n".join(indent + line if line.strip() else line for line in code.split("\n"))
|
| 241 |
+
|
| 242 |
+
def _extract_output(self, text: str, start_marker: str, end_marker: str) -> str:
|
| 243 |
+
"""Extract content between markers."""
|
| 244 |
+
try:
|
| 245 |
+
start_idx = text.index(start_marker) + len(start_marker)
|
| 246 |
+
end_idx = text.index(end_marker)
|
| 247 |
+
return text[start_idx:end_idx].strip()
|
| 248 |
+
except ValueError:
|
| 249 |
+
# Markers not found, return original text
|
| 250 |
+
return text.strip()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
@lru_cache(maxsize=1)
|
| 254 |
+
def get_code_executor() -> ModalCodeExecutor:
|
| 255 |
+
"""Get or create singleton code executor instance (thread-safe via lru_cache)."""
|
| 256 |
+
return ModalCodeExecutor()
|
src/utils/config.py
CHANGED
|
@@ -29,6 +29,17 @@ class Settings(BaseSettings):
|
|
| 29 |
openai_model: str = Field(default="gpt-4o", description="OpenAI model name")
|
| 30 |
anthropic_model: str = Field(default="claude-sonnet-4-20250514", description="Anthropic model")
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
# PubMed Configuration
|
| 33 |
ncbi_api_key: str | None = Field(
|
| 34 |
default=None, description="NCBI API key for higher rate limits"
|
|
@@ -41,6 +52,11 @@ class Settings(BaseSettings):
|
|
| 41 |
# Logging
|
| 42 |
log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = "INFO"
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
def get_api_key(self) -> str:
|
| 45 |
"""Get the API key for the configured provider."""
|
| 46 |
if self.llm_provider == "openai":
|
|
|
|
| 29 |
openai_model: str = Field(default="gpt-4o", description="OpenAI model name")
|
| 30 |
anthropic_model: str = Field(default="claude-sonnet-4-20250514", description="Anthropic model")
|
| 31 |
|
| 32 |
+
# Embedding Configuration
|
| 33 |
+
# Note: OpenAI embeddings require OPENAI_API_KEY (Anthropic has no embeddings API)
|
| 34 |
+
openai_embedding_model: str = Field(
|
| 35 |
+
default="text-embedding-3-small",
|
| 36 |
+
description="OpenAI embedding model (used by LlamaIndex RAG)",
|
| 37 |
+
)
|
| 38 |
+
local_embedding_model: str = Field(
|
| 39 |
+
default="all-MiniLM-L6-v2",
|
| 40 |
+
description="Local sentence-transformers model (used by EmbeddingService)",
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
# PubMed Configuration
|
| 44 |
ncbi_api_key: str | None = Field(
|
| 45 |
default=None, description="NCBI API key for higher rate limits"
|
|
|
|
| 52 |
# Logging
|
| 53 |
log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = "INFO"
|
| 54 |
|
| 55 |
+
# Partner Service Configuration (Mario's Modal Integration)
|
| 56 |
+
modal_token_id: str | None = Field(default=None, description="Modal token ID")
|
| 57 |
+
modal_token_secret: str | None = Field(default=None, description="Modal token secret")
|
| 58 |
+
chroma_db_path: str = Field(default="./chroma_db", description="ChromaDB storage path")
|
| 59 |
+
|
| 60 |
def get_api_key(self) -> str:
|
| 61 |
"""Get the API key for the configured provider."""
|
| 62 |
if self.llm_provider == "openai":
|
uv.lock
CHANGED
|
@@ -174,6 +174,18 @@ wheels = [
|
|
| 174 |
{ url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490 },
|
| 175 |
]
|
| 176 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
[[package]]
|
| 178 |
name = "annotated-doc"
|
| 179 |
version = "0.0.4"
|
|
@@ -358,6 +370,22 @@ wheels = [
|
|
| 358 |
{ url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181 },
|
| 359 |
]
|
| 360 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 361 |
[[package]]
|
| 362 |
name = "bcrypt"
|
| 363 |
version = "5.0.0"
|
|
@@ -549,6 +577,47 @@ wheels = [
|
|
| 549 |
{ url = "https://files.pythonhosted.org/packages/e6/46/eb6eca305c77a4489affe1c5d8f4cae82f285d9addd8de4ec084a7184221/cachetools-6.2.2-py3-none-any.whl", hash = "sha256:6c09c98183bf58560c97b2abfcedcbaf6a896a490f534b031b661d3723b45ace", size = 11503 },
|
| 550 |
]
|
| 551 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 552 |
[[package]]
|
| 553 |
name = "certifi"
|
| 554 |
version = "2025.11.12"
|
|
@@ -974,6 +1043,19 @@ wheels = [
|
|
| 974 |
{ url = "https://files.pythonhosted.org/packages/b6/00/a9b81bdba88e2904602e970e46ffd18b6a833d902f18d91bdce6fc271c49/cyclopts-4.2.5-py3-none-any.whl", hash = "sha256:361be316ce7f6ce674cad8d34bf6c5e39c34daaeceae40632a55b599472975c7", size = 185196 },
|
| 975 |
]
|
| 976 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 977 |
[[package]]
|
| 978 |
name = "deepcritical"
|
| 979 |
version = "0.1.0"
|
|
@@ -1013,6 +1095,14 @@ embeddings = [
|
|
| 1013 |
magentic = [
|
| 1014 |
{ name = "agent-framework-core" },
|
| 1015 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1016 |
|
| 1017 |
[package.metadata]
|
| 1018 |
requires-dist = [
|
|
@@ -1020,8 +1110,14 @@ requires-dist = [
|
|
| 1020 |
{ name = "anthropic", specifier = ">=0.18.0" },
|
| 1021 |
{ name = "beautifulsoup4", specifier = ">=4.12" },
|
| 1022 |
{ name = "chromadb", marker = "extra == 'embeddings'", specifier = ">=0.4.0" },
|
|
|
|
| 1023 |
{ name = "gradio", specifier = ">=5.0" },
|
| 1024 |
{ name = "httpx", specifier = ">=0.27" },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1025 |
{ name = "mypy", marker = "extra == 'dev'", specifier = ">=1.10" },
|
| 1026 |
{ name = "openai", specifier = ">=1.0.0" },
|
| 1027 |
{ name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.7" },
|
|
@@ -1042,7 +1138,37 @@ requires-dist = [
|
|
| 1042 |
{ name = "tenacity", specifier = ">=8.2" },
|
| 1043 |
{ name = "xmltodict", specifier = ">=0.13" },
|
| 1044 |
]
|
| 1045 |
-
provides-extras = ["dev", "magentic", "embeddings"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1046 |
|
| 1047 |
[[package]]
|
| 1048 |
name = "diskcache"
|
|
@@ -1250,6 +1376,15 @@ wheels = [
|
|
| 1250 |
{ url = "https://files.pythonhosted.org/packages/76/91/7216b27286936c16f5b4d0c530087e4a54eead683e6b0b73dd0c64844af6/filelock-3.20.0-py3-none-any.whl", hash = "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2", size = 16054 },
|
| 1251 |
]
|
| 1252 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1253 |
[[package]]
|
| 1254 |
name = "flatbuffers"
|
| 1255 |
version = "25.9.23"
|
|
@@ -1486,6 +1621,56 @@ wheels = [
|
|
| 1486 |
{ url = "https://files.pythonhosted.org/packages/be/8a/f2a47134c5b5a7f3bad27eae749589a80d81efaaad8f59af47c136712bf6/gradio_client-1.14.0-py3-none-any.whl", hash = "sha256:9a2f5151978411e0f8b55a2d38cddd0a94491851149d14db4af96f5a09774825", size = 325555 },
|
| 1487 |
]
|
| 1488 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1489 |
[[package]]
|
| 1490 |
name = "griffe"
|
| 1491 |
version = "1.15.0"
|
|
@@ -1575,6 +1760,19 @@ wheels = [
|
|
| 1575 |
{ url = "https://files.pythonhosted.org/packages/19/41/0b430b01a2eb38ee887f88c1f07644a1df8e289353b78e82b37ef988fb64/grpcio-1.76.0-cp314-cp314-win_amd64.whl", hash = "sha256:922fa70ba549fce362d2e2871ab542082d66e2aaf0c19480ea453905b01f384e", size = 4834462 },
|
| 1576 |
]
|
| 1577 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1578 |
[[package]]
|
| 1579 |
name = "h11"
|
| 1580 |
version = "0.16.0"
|
|
@@ -1584,6 +1782,19 @@ wheels = [
|
|
| 1584 |
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515 },
|
| 1585 |
]
|
| 1586 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1587 |
[[package]]
|
| 1588 |
name = "hf-xet"
|
| 1589 |
version = "1.2.0"
|
|
@@ -1613,6 +1824,15 @@ wheels = [
|
|
| 1613 |
{ url = "https://files.pythonhosted.org/packages/cb/44/870d44b30e1dcfb6a65932e3e1506c103a8a5aea9103c337e7a53180322c/hf_xet-1.2.0-cp37-abi3-win_amd64.whl", hash = "sha256:e6584a52253f72c9f52f9e549d5895ca7a471608495c4ecaa6cc73dba2b24d69", size = 2905735 },
|
| 1614 |
]
|
| 1615 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1616 |
[[package]]
|
| 1617 |
name = "httpcore"
|
| 1618 |
version = "1.0.9"
|
|
@@ -1722,6 +1942,15 @@ wheels = [
|
|
| 1722 |
{ url = "https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", size = 86794 },
|
| 1723 |
]
|
| 1724 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1725 |
[[package]]
|
| 1726 |
name = "identify"
|
| 1727 |
version = "2.6.15"
|
|
@@ -2020,6 +2249,231 @@ wheels = [
|
|
| 2020 |
{ url = "https://files.pythonhosted.org/packages/ca/ec/65f7d563aa4a62dd58777e8f6aa882f15db53b14eb29aba0c28a20f7eb26/kubernetes-34.1.0-py2.py3-none-any.whl", hash = "sha256:bffba2272534e224e6a7a74d582deb0b545b7c9879d2cd9e4aae9481d1f2cc2a", size = 2008380 },
|
| 2021 |
]
|
| 2022 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2023 |
[[package]]
|
| 2024 |
name = "logfire"
|
| 2025 |
version = "4.15.1"
|
|
@@ -2138,6 +2592,18 @@ wheels = [
|
|
| 2138 |
{ url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146 },
|
| 2139 |
]
|
| 2140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2141 |
[[package]]
|
| 2142 |
name = "mcp"
|
| 2143 |
version = "1.22.0"
|
|
@@ -2291,6 +2757,31 @@ wheels = [
|
|
| 2291 |
{ url = "https://files.pythonhosted.org/packages/6a/fc/0e61d9a4e29c8679356795a40e48f647b4aad58d71bfc969f0f8f56fb912/mmh3-5.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9", size = 40455 },
|
| 2292 |
]
|
| 2293 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2294 |
[[package]]
|
| 2295 |
name = "more-itertools"
|
| 2296 |
version = "10.8.0"
|
|
@@ -2499,6 +2990,15 @@ wheels = [
|
|
| 2499 |
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963 },
|
| 2500 |
]
|
| 2501 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2502 |
[[package]]
|
| 2503 |
name = "networkx"
|
| 2504 |
version = "3.6"
|
|
@@ -2520,6 +3020,21 @@ wheels = [
|
|
| 2520 |
{ url = "https://files.pythonhosted.org/packages/bf/2f/9e9d0dcaa4c6ffa22b7aa31069a8a264c753ff8027b36af602cce038c92f/nexus_rpc-1.1.0-py3-none-any.whl", hash = "sha256:d1b007af2aba186a27e736f8eaae39c03aed05b488084ff6c3d1785c9ba2ad38", size = 27743 },
|
| 2521 |
]
|
| 2522 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2523 |
[[package]]
|
| 2524 |
name = "nodeenv"
|
| 2525 |
version = "1.9.1"
|
|
@@ -3053,7 +3568,7 @@ wheels = [
|
|
| 3053 |
|
| 3054 |
[[package]]
|
| 3055 |
name = "pandas"
|
| 3056 |
-
version = "2.
|
| 3057 |
source = { registry = "https://pypi.org/simple" }
|
| 3058 |
dependencies = [
|
| 3059 |
{ name = "numpy" },
|
|
@@ -3061,48 +3576,35 @@ dependencies = [
|
|
| 3061 |
{ name = "pytz" },
|
| 3062 |
{ name = "tzdata" },
|
| 3063 |
]
|
| 3064 |
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
| 3065 |
-
wheels = [
|
| 3066 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3067 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3068 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3069 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3070 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3071 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3072 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3073 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3074 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3075 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3076 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3077 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3078 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3079 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3080 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3081 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3082 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3083 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3084 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3085 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3086 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3087 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3088 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3089 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3090 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3091 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3092 |
-
{ url = "https://files.pythonhosted.org/packages/
|
| 3093 |
-
{ url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635 },
|
| 3094 |
-
{ url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079 },
|
| 3095 |
-
{ url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049 },
|
| 3096 |
-
{ url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638 },
|
| 3097 |
-
{ url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834 },
|
| 3098 |
-
{ url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925 },
|
| 3099 |
-
{ url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071 },
|
| 3100 |
-
{ url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504 },
|
| 3101 |
-
{ url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702 },
|
| 3102 |
-
{ url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535 },
|
| 3103 |
-
{ url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582 },
|
| 3104 |
-
{ url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963 },
|
| 3105 |
-
{ url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175 },
|
| 3106 |
]
|
| 3107 |
|
| 3108 |
[[package]]
|
|
@@ -3883,6 +4385,15 @@ crypto = [
|
|
| 3883 |
{ name = "cryptography" },
|
| 3884 |
]
|
| 3885 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3886 |
[[package]]
|
| 3887 |
name = "pyperclip"
|
| 3888 |
version = "1.11.0"
|
|
@@ -4666,6 +5177,48 @@ wheels = [
|
|
| 4666 |
{ url = "https://files.pythonhosted.org/packages/14/a0/bb38d3b76b8cae341dad93a2dd83ab7462e6dbcdd84d43f54ee60a8dc167/soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c", size = 36679 },
|
| 4667 |
]
|
| 4668 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4669 |
[[package]]
|
| 4670 |
name = "sse-starlette"
|
| 4671 |
version = "3.0.3"
|
|
@@ -4691,6 +5244,15 @@ wheels = [
|
|
| 4691 |
{ url = "https://files.pythonhosted.org/packages/d9/52/1064f510b141bd54025f9b55105e26d1fa970b9be67ad766380a3c9b74b0/starlette-0.50.0-py3-none-any.whl", hash = "sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca", size = 74033 },
|
| 4692 |
]
|
| 4693 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4694 |
[[package]]
|
| 4695 |
name = "structlog"
|
| 4696 |
version = "25.5.0"
|
|
@@ -4712,6 +5274,18 @@ wheels = [
|
|
| 4712 |
{ url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353 },
|
| 4713 |
]
|
| 4714 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4715 |
[[package]]
|
| 4716 |
name = "temporalio"
|
| 4717 |
version = "1.19.0"
|
|
@@ -4757,6 +5331,60 @@ wheels = [
|
|
| 4757 |
{ url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638 },
|
| 4758 |
]
|
| 4759 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4760 |
[[package]]
|
| 4761 |
name = "tokenizers"
|
| 4762 |
version = "0.22.1"
|
|
@@ -4782,6 +5410,15 @@ wheels = [
|
|
| 4782 |
{ url = "https://files.pythonhosted.org/packages/b3/46/e33a8c93907b631a99377ef4c5f817ab453d0b34f93529421f42ff559671/tokenizers-0.22.1-cp39-abi3-win_amd64.whl", hash = "sha256:65fd6e3fb11ca1e78a6a93602490f134d1fdeb13bcef99389d5102ea318ed138", size = 2674684 },
|
| 4783 |
]
|
| 4784 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4785 |
[[package]]
|
| 4786 |
name = "tomli"
|
| 4787 |
version = "2.3.0"
|
|
@@ -4957,6 +5594,15 @@ wheels = [
|
|
| 4957 |
{ url = "https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl", hash = "sha256:5b463df6793ec1dca6213a3cf4c0f03bc6e322ac5e16e13ddd622a889489784a", size = 47028 },
|
| 4958 |
]
|
| 4959 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4960 |
[[package]]
|
| 4961 |
name = "types-protobuf"
|
| 4962 |
version = "6.32.1.20251105"
|
|
@@ -4978,6 +5624,15 @@ wheels = [
|
|
| 4978 |
{ url = "https://files.pythonhosted.org/packages/2a/20/9a227ea57c1285986c4cf78400d0a91615d25b24e257fd9e2969606bdfae/types_requests-2.32.4.20250913-py3-none-any.whl", hash = "sha256:78c9c1fffebbe0fa487a418e0fa5252017e9c60d1a2da394077f1780f655d7e1", size = 20658 },
|
| 4979 |
]
|
| 4980 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4981 |
[[package]]
|
| 4982 |
name = "typing-extensions"
|
| 4983 |
version = "4.15.0"
|
|
@@ -4987,6 +5642,19 @@ wheels = [
|
|
| 4987 |
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614 },
|
| 4988 |
]
|
| 4989 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4990 |
[[package]]
|
| 4991 |
name = "typing-inspection"
|
| 4992 |
version = "0.4.2"
|
|
|
|
| 174 |
{ url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490 },
|
| 175 |
]
|
| 176 |
|
| 177 |
+
[[package]]
|
| 178 |
+
name = "aiosqlite"
|
| 179 |
+
version = "0.21.0"
|
| 180 |
+
source = { registry = "https://pypi.org/simple" }
|
| 181 |
+
dependencies = [
|
| 182 |
+
{ name = "typing-extensions" },
|
| 183 |
+
]
|
| 184 |
+
sdist = { url = "https://files.pythonhosted.org/packages/13/7d/8bca2bf9a247c2c5dfeec1d7a5f40db6518f88d314b8bca9da29670d2671/aiosqlite-0.21.0.tar.gz", hash = "sha256:131bb8056daa3bc875608c631c678cda73922a2d4ba8aec373b19f18c17e7aa3", size = 13454 }
|
| 185 |
+
wheels = [
|
| 186 |
+
{ url = "https://files.pythonhosted.org/packages/f5/10/6c25ed6de94c49f88a91fa5018cb4c0f3625f31d5be9f771ebe5cc7cd506/aiosqlite-0.21.0-py3-none-any.whl", hash = "sha256:2549cf4057f95f53dcba16f2b64e8e2791d7e1adedb13197dd8ed77bb226d7d0", size = 15792 },
|
| 187 |
+
]
|
| 188 |
+
|
| 189 |
[[package]]
|
| 190 |
name = "annotated-doc"
|
| 191 |
version = "0.0.4"
|
|
|
|
| 370 |
{ url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181 },
|
| 371 |
]
|
| 372 |
|
| 373 |
+
[[package]]
|
| 374 |
+
name = "banks"
|
| 375 |
+
version = "2.2.0"
|
| 376 |
+
source = { registry = "https://pypi.org/simple" }
|
| 377 |
+
dependencies = [
|
| 378 |
+
{ name = "deprecated" },
|
| 379 |
+
{ name = "griffe" },
|
| 380 |
+
{ name = "jinja2" },
|
| 381 |
+
{ name = "platformdirs" },
|
| 382 |
+
{ name = "pydantic" },
|
| 383 |
+
]
|
| 384 |
+
sdist = { url = "https://files.pythonhosted.org/packages/7d/f8/25ef24814f77f3fd7f0fd3bd1ef3749e38a9dbd23502fbb53034de49900c/banks-2.2.0.tar.gz", hash = "sha256:d1446280ce6e00301e3e952dd754fd8cee23ff277d29ed160994a84d0d7ffe62", size = 179052 }
|
| 385 |
+
wheels = [
|
| 386 |
+
{ url = "https://files.pythonhosted.org/packages/b4/d6/f9168956276934162ec8d48232f9920f2985ee45aa7602e3c6b4bc203613/banks-2.2.0-py3-none-any.whl", hash = "sha256:963cd5c85a587b122abde4f4064078def35c50c688c1b9d36f43c92503854e7d", size = 29244 },
|
| 387 |
+
]
|
| 388 |
+
|
| 389 |
[[package]]
|
| 390 |
name = "bcrypt"
|
| 391 |
version = "5.0.0"
|
|
|
|
| 577 |
{ url = "https://files.pythonhosted.org/packages/e6/46/eb6eca305c77a4489affe1c5d8f4cae82f285d9addd8de4ec084a7184221/cachetools-6.2.2-py3-none-any.whl", hash = "sha256:6c09c98183bf58560c97b2abfcedcbaf6a896a490f534b031b661d3723b45ace", size = 11503 },
|
| 578 |
]
|
| 579 |
|
| 580 |
+
[[package]]
|
| 581 |
+
name = "cbor2"
|
| 582 |
+
version = "5.7.1"
|
| 583 |
+
source = { registry = "https://pypi.org/simple" }
|
| 584 |
+
sdist = { url = "https://files.pythonhosted.org/packages/a2/b8/c0f6a7d46f816cb18b1fda61a2fe648abe16039f1ff93ea720a6e9fb3cee/cbor2-5.7.1.tar.gz", hash = "sha256:7a405a1d7c8230ee9acf240aad48ae947ef584e8af05f169f3c1bde8f01f8b71", size = 102467 }
|
| 585 |
+
wheels = [
|
| 586 |
+
{ url = "https://files.pythonhosted.org/packages/52/67/319baac9c51de0053f58fa74a9548f93f3629aa3adeebd7d2c99d1379370/cbor2-5.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2b1efbe6e82721be44b9faf47d0fd97b0150213eb6a4ba554f4947442bc4e13f", size = 67894 },
|
| 587 |
+
{ url = "https://files.pythonhosted.org/packages/2c/53/d23d0a234a4a098b019ac1cadd33631c973142fc947a68c4a38ca47aa5dc/cbor2-5.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fb94bab27e00283bdd8f160e125e17dbabec4c9e6ffc8da91c36547ec1eb707f", size = 68444 },
|
| 588 |
+
{ url = "https://files.pythonhosted.org/packages/3a/a2/a6fa59e1c23b0bc77628d64153eb9fc69ac8dde5f8ed41a7d5316fcd0bcd/cbor2-5.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29f22266b5e08e0e4152e87ba185e04d3a84a4fd545b99ae3ebe42c658c66a53", size = 261600 },
|
| 589 |
+
{ url = "https://files.pythonhosted.org/packages/3d/cb/e0fa066aa7a09b15b8f56bafef6b2be19d9db31310310b0a5601af5c0128/cbor2-5.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25d4c7554d6627da781c9bd1d0dd0709456eecb71f605829f98961bb98487dda", size = 254904 },
|
| 590 |
+
{ url = "https://files.pythonhosted.org/packages/2c/d5/b1fb4a3828c440e100a4b2658dd2e8f422faf08f4fcc8e2c92b240656b44/cbor2-5.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1e15c3a08008cf13ce1dfc64d17c960df5d66d935788d28ec7df54bf0ffb0ef", size = 257388 },
|
| 591 |
+
{ url = "https://files.pythonhosted.org/packages/34/d5/252657bc5af964fc5f19c0e0e82031b4c32eba5d3ed4098e963e0e8c47a6/cbor2-5.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9f6cdf7eb604ea0e7ef34e3f0b5447da0029ecd3ab7b2dc70e43fa5f7bcfca89", size = 251494 },
|
| 592 |
+
{ url = "https://files.pythonhosted.org/packages/8a/3a/503ea4c2977411858ca287808d077fdb4bb1fafdb4b39177b8ce3d5619ac/cbor2-5.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:dd25cbef8e8e6dbf69f0de95311aecaca7217230cda83ae99fdc37cd20d99250", size = 68147 },
|
| 593 |
+
{ url = "https://files.pythonhosted.org/packages/49/9e/fe4c9703fd444da193f892787110c5da2a85c16d26917fcb2584f5d00077/cbor2-5.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:40cc9c67242a7abac5a4e062bc4d1d2376979878c0565a4b2f08fd9ed9212945", size = 64126 },
|
| 594 |
+
{ url = "https://files.pythonhosted.org/packages/56/54/48426472f0c051982c647331441aed09b271a0500356ae0b7054c813d174/cbor2-5.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bd5ca44891c06f6b85d440836c967187dc1d30b15f86f315d55c675d3a841078", size = 69031 },
|
| 595 |
+
{ url = "https://files.pythonhosted.org/packages/d3/68/1dd58c7706e9752188358223db58c83f3c48e07f728aa84221ffd244652f/cbor2-5.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:537d73ef930ccc1a7b6a2e8d2cbf81407d270deb18e40cda5eb511bd70f71078", size = 68825 },
|
| 596 |
+
{ url = "https://files.pythonhosted.org/packages/09/4e/380562fe9f9995a1875fb5ec26fd041e19d61f4630cb690a98c5195945fc/cbor2-5.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:edbf814dd7763b6eda27a5770199f6ccd55bd78be8f4367092460261bfbf19d0", size = 286222 },
|
| 597 |
+
{ url = "https://files.pythonhosted.org/packages/7c/bb/9eccdc1ea3c4d5c7cdb2e49b9de49534039616be5455ce69bd64c0b2efe2/cbor2-5.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9fc81da8c0e09beb42923e455e477b36ff14a03b9ca18a8a2e9b462de9a953e8", size = 285688 },
|
| 598 |
+
{ url = "https://files.pythonhosted.org/packages/59/8c/4696d82f5bd04b3d45d9a64ec037fa242630c134e3218d6c252b4f59b909/cbor2-5.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e4a7d660d428911a3aadb7105e94438d7671ab977356fdf647a91aab751033bd", size = 277063 },
|
| 599 |
+
{ url = "https://files.pythonhosted.org/packages/95/50/6538e44ca970caaad2fa376b81701d073d84bf597aac07a59d0a253b1a7f/cbor2-5.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:228e0af9c0a9ddf6375b6ae010eaa1942a1901d403f134ac9ee6a76a322483f9", size = 278334 },
|
| 600 |
+
{ url = "https://files.pythonhosted.org/packages/64/a9/156ccd2207fb26b5b61d23728b4dbdc595d1600125aa79683a4a8ddc9313/cbor2-5.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:2d08a6c0d9ed778448e185508d870f4160ba74f59bb17a966abd0d14d0ff4dd3", size = 68404 },
|
| 601 |
+
{ url = "https://files.pythonhosted.org/packages/4f/49/adc53615e9dd32c4421f6935dfa2235013532c6e6b28ee515bbdd92618be/cbor2-5.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:752506cfe72da0f4014b468b30191470ee8919a64a0772bd3b36a4fccf5fcefc", size = 64047 },
|
| 602 |
+
{ url = "https://files.pythonhosted.org/packages/16/b1/51fb868fe38d893c570bb90b38d365ff0f00421402c1ae8f63b31b25d665/cbor2-5.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:59d5da59fffe89692d5bd1530eef4d26e4eb7aa794aaa1f4e192614786409009", size = 69068 },
|
| 603 |
+
{ url = "https://files.pythonhosted.org/packages/b9/db/5abc62ec456f552f617aac3359a5d7114b23be9c4d886169592cd5f074b9/cbor2-5.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:533117918d518e01348f8cd0331271c207e7224b9a1ed492a0ff00847f28edc8", size = 68927 },
|
| 604 |
+
{ url = "https://files.pythonhosted.org/packages/9a/c2/58d787395c99874d2a2395b3a22c9d48a3cfc5a7dcd5817bf74764998b75/cbor2-5.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8d6d9436ff3c3323ea5863ecf7ae1139590991685b44b9eb6b7bb1734a594af6", size = 285185 },
|
| 605 |
+
{ url = "https://files.pythonhosted.org/packages/d0/9c/b680b264a8f4b9aa59c95e166c816275a13138cbee92dd2917f58bca47b9/cbor2-5.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:661b871ca754a619fcd98c13a38b4696b2b57dab8b24235c00b0ba322c040d24", size = 284440 },
|
| 606 |
+
{ url = "https://files.pythonhosted.org/packages/1f/59/68183c655d6226d0eee10027f52516882837802a8d5746317a88362ed686/cbor2-5.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8065aa90d715fd9bb28727b2d774ee16e695a0e1627ae76e54bf19f9d99d63f", size = 276876 },
|
| 607 |
+
{ url = "https://files.pythonhosted.org/packages/ee/a2/1964e0a569d2b81e8f4862753fee7701ae5773c22e45492a26f92f62e75a/cbor2-5.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cb1b7047d73590cfe8e373e2c804fa99be47e55b1b6186602d0f86f384cecec1", size = 278216 },
|
| 608 |
+
{ url = "https://files.pythonhosted.org/packages/00/78/9b566d68cb88bb1ecebe354765625161c9d6060a16e55008006d6359f776/cbor2-5.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:31d511df7ebd6624fdb4cecdafb4ffb9a205f9ff8c8d98edd1bef0d27f944d74", size = 68451 },
|
| 609 |
+
{ url = "https://files.pythonhosted.org/packages/db/85/7a6a922d147d027fd5d8fd5224b39e8eaf152a42e8cf16351458096d3d62/cbor2-5.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:f5d37f7b0f84394d2995bd8722cb01c86a885c4821a864a34b7b4d9950c5e26e", size = 64111 },
|
| 610 |
+
{ url = "https://files.pythonhosted.org/packages/5f/f0/f220222a57371e33434ba7bdc25de31d611cbc0ade2a868e03c3553305e7/cbor2-5.7.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e5826e4fa4c33661960073f99cf67c82783895524fb66f3ebdd635c19b5a7d68", size = 69002 },
|
| 611 |
+
{ url = "https://files.pythonhosted.org/packages/c7/3c/34b62ba5173541659f248f005d13373530f02fb997b78fde00bf01ede4f4/cbor2-5.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f19a00d6ac9a77cb611073250b06bf4494b41ba78a1716704f7008e0927d9366", size = 69177 },
|
| 612 |
+
{ url = "https://files.pythonhosted.org/packages/77/fd/2400d820d9733df00a5c18aa74201e51d710fb91588687eb594f4a7688ea/cbor2-5.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d2113aea044cd172f199da3520bc4401af69eae96c5180ca7eb660941928cb89", size = 284259 },
|
| 613 |
+
{ url = "https://files.pythonhosted.org/packages/42/65/280488ef196c1d71ba123cd406ea47727bb3a0e057767a733d9793fcc428/cbor2-5.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f17eacea2d28fecf28ac413c1d7927cde0a11957487d2630655d6b5c9c46a0b", size = 281958 },
|
| 614 |
+
{ url = "https://files.pythonhosted.org/packages/42/82/bcdd3fdc73bd5f4194fdb08c808112010add9530bae1dcfdb1e2b2ceae19/cbor2-5.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d65deea39cae533a629561e7da672402c46731122b6129ed7c8eaa1efe04efce", size = 276025 },
|
| 615 |
+
{ url = "https://files.pythonhosted.org/packages/ae/a8/a6065dd6a157b877d7d8f3fe96f410fb191a2db1e6588f4d20b5f9a507c2/cbor2-5.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:57d8cc29ec1fd20500748e0e767ff88c13afcee839081ba4478c41fcda6ee18b", size = 275978 },
|
| 616 |
+
{ url = "https://files.pythonhosted.org/packages/62/f4/37934045174af9e4253a340b43f07197af54002070cb80fae82d878f1f14/cbor2-5.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:94fb939d0946f80c49ba45105ca3a3e13e598fc9abd63efc6661b02d4b4d2c50", size = 70269 },
|
| 617 |
+
{ url = "https://files.pythonhosted.org/packages/0b/fd/933416643e7f5540ae818691fb23fa4189010c6efa39a12c4f59d825da28/cbor2-5.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4fd7225ac820bbb9f03bd16bc1a7efb6c4d1c451f22c0a153ff4ec46495c59c5", size = 66182 },
|
| 618 |
+
{ url = "https://files.pythonhosted.org/packages/d5/7d/383bafeabb54c17fe5b6d5aca4e863e6b7df10bcc833b34aa169e9dfce1a/cbor2-5.7.1-py3-none-any.whl", hash = "sha256:68834e4eff2f56629ce6422b0634bc3f74c5a4269de5363f5265fe452c706ba7", size = 23829 },
|
| 619 |
+
]
|
| 620 |
+
|
| 621 |
[[package]]
|
| 622 |
name = "certifi"
|
| 623 |
version = "2025.11.12"
|
|
|
|
| 1043 |
{ url = "https://files.pythonhosted.org/packages/b6/00/a9b81bdba88e2904602e970e46ffd18b6a833d902f18d91bdce6fc271c49/cyclopts-4.2.5-py3-none-any.whl", hash = "sha256:361be316ce7f6ce674cad8d34bf6c5e39c34daaeceae40632a55b599472975c7", size = 185196 },
|
| 1044 |
]
|
| 1045 |
|
| 1046 |
+
[[package]]
|
| 1047 |
+
name = "dataclasses-json"
|
| 1048 |
+
version = "0.6.7"
|
| 1049 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1050 |
+
dependencies = [
|
| 1051 |
+
{ name = "marshmallow" },
|
| 1052 |
+
{ name = "typing-inspect" },
|
| 1053 |
+
]
|
| 1054 |
+
sdist = { url = "https://files.pythonhosted.org/packages/64/a4/f71d9cf3a5ac257c993b5ca3f93df5f7fb395c725e7f1e6479d2514173c3/dataclasses_json-0.6.7.tar.gz", hash = "sha256:b6b3e528266ea45b9535223bc53ca645f5208833c29229e847b3f26a1cc55fc0", size = 32227 }
|
| 1055 |
+
wheels = [
|
| 1056 |
+
{ url = "https://files.pythonhosted.org/packages/c3/be/d0d44e092656fe7a06b55e6103cbce807cdbdee17884a5367c68c9860853/dataclasses_json-0.6.7-py3-none-any.whl", hash = "sha256:0dbf33f26c8d5305befd61b39d2b3414e8a407bedc2834dea9b8d642666fb40a", size = 28686 },
|
| 1057 |
+
]
|
| 1058 |
+
|
| 1059 |
[[package]]
|
| 1060 |
name = "deepcritical"
|
| 1061 |
version = "0.1.0"
|
|
|
|
| 1095 |
magentic = [
|
| 1096 |
{ name = "agent-framework-core" },
|
| 1097 |
]
|
| 1098 |
+
modal = [
|
| 1099 |
+
{ name = "chromadb" },
|
| 1100 |
+
{ name = "llama-index" },
|
| 1101 |
+
{ name = "llama-index-embeddings-openai" },
|
| 1102 |
+
{ name = "llama-index-llms-openai" },
|
| 1103 |
+
{ name = "llama-index-vector-stores-chroma" },
|
| 1104 |
+
{ name = "modal" },
|
| 1105 |
+
]
|
| 1106 |
|
| 1107 |
[package.metadata]
|
| 1108 |
requires-dist = [
|
|
|
|
| 1110 |
{ name = "anthropic", specifier = ">=0.18.0" },
|
| 1111 |
{ name = "beautifulsoup4", specifier = ">=4.12" },
|
| 1112 |
{ name = "chromadb", marker = "extra == 'embeddings'", specifier = ">=0.4.0" },
|
| 1113 |
+
{ name = "chromadb", marker = "extra == 'modal'", specifier = ">=0.4.0" },
|
| 1114 |
{ name = "gradio", specifier = ">=5.0" },
|
| 1115 |
{ name = "httpx", specifier = ">=0.27" },
|
| 1116 |
+
{ name = "llama-index", marker = "extra == 'modal'", specifier = ">=0.11.0" },
|
| 1117 |
+
{ name = "llama-index-embeddings-openai", marker = "extra == 'modal'" },
|
| 1118 |
+
{ name = "llama-index-llms-openai", marker = "extra == 'modal'" },
|
| 1119 |
+
{ name = "llama-index-vector-stores-chroma", marker = "extra == 'modal'" },
|
| 1120 |
+
{ name = "modal", marker = "extra == 'modal'", specifier = ">=0.63.0" },
|
| 1121 |
{ name = "mypy", marker = "extra == 'dev'", specifier = ">=1.10" },
|
| 1122 |
{ name = "openai", specifier = ">=1.0.0" },
|
| 1123 |
{ name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.7" },
|
|
|
|
| 1138 |
{ name = "tenacity", specifier = ">=8.2" },
|
| 1139 |
{ name = "xmltodict", specifier = ">=0.13" },
|
| 1140 |
]
|
| 1141 |
+
provides-extras = ["dev", "magentic", "embeddings", "modal"]
|
| 1142 |
+
|
| 1143 |
+
[[package]]
|
| 1144 |
+
name = "defusedxml"
|
| 1145 |
+
version = "0.7.1"
|
| 1146 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1147 |
+
sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520 }
|
| 1148 |
+
wheels = [
|
| 1149 |
+
{ url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604 },
|
| 1150 |
+
]
|
| 1151 |
+
|
| 1152 |
+
[[package]]
|
| 1153 |
+
name = "deprecated"
|
| 1154 |
+
version = "1.2.18"
|
| 1155 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1156 |
+
dependencies = [
|
| 1157 |
+
{ name = "wrapt" },
|
| 1158 |
+
]
|
| 1159 |
+
sdist = { url = "https://files.pythonhosted.org/packages/98/97/06afe62762c9a8a86af0cfb7bfdab22a43ad17138b07af5b1a58442690a2/deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d", size = 2928744 }
|
| 1160 |
+
wheels = [
|
| 1161 |
+
{ url = "https://files.pythonhosted.org/packages/6e/c6/ac0b6c1e2d138f1002bcf799d330bd6d85084fece321e662a14223794041/Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec", size = 9998 },
|
| 1162 |
+
]
|
| 1163 |
+
|
| 1164 |
+
[[package]]
|
| 1165 |
+
name = "dirtyjson"
|
| 1166 |
+
version = "1.0.8"
|
| 1167 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1168 |
+
sdist = { url = "https://files.pythonhosted.org/packages/db/04/d24f6e645ad82ba0ef092fa17d9ef7a21953781663648a01c9371d9e8e98/dirtyjson-1.0.8.tar.gz", hash = "sha256:90ca4a18f3ff30ce849d100dcf4a003953c79d3a2348ef056f1d9c22231a25fd", size = 30782 }
|
| 1169 |
+
wheels = [
|
| 1170 |
+
{ url = "https://files.pythonhosted.org/packages/68/69/1bcf70f81de1b4a9f21b3a62ec0c83bdff991c88d6cc2267d02408457e88/dirtyjson-1.0.8-py3-none-any.whl", hash = "sha256:125e27248435a58acace26d5c2c4c11a1c0de0a9c5124c5a94ba78e517d74f53", size = 25197 },
|
| 1171 |
+
]
|
| 1172 |
|
| 1173 |
[[package]]
|
| 1174 |
name = "diskcache"
|
|
|
|
| 1376 |
{ url = "https://files.pythonhosted.org/packages/76/91/7216b27286936c16f5b4d0c530087e4a54eead683e6b0b73dd0c64844af6/filelock-3.20.0-py3-none-any.whl", hash = "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2", size = 16054 },
|
| 1377 |
]
|
| 1378 |
|
| 1379 |
+
[[package]]
|
| 1380 |
+
name = "filetype"
|
| 1381 |
+
version = "1.2.0"
|
| 1382 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1383 |
+
sdist = { url = "https://files.pythonhosted.org/packages/bb/29/745f7d30d47fe0f251d3ad3dc2978a23141917661998763bebb6da007eb1/filetype-1.2.0.tar.gz", hash = "sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb", size = 998020 }
|
| 1384 |
+
wheels = [
|
| 1385 |
+
{ url = "https://files.pythonhosted.org/packages/18/79/1b8fa1bb3568781e84c9200f951c735f3f157429f44be0495da55894d620/filetype-1.2.0-py2.py3-none-any.whl", hash = "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25", size = 19970 },
|
| 1386 |
+
]
|
| 1387 |
+
|
| 1388 |
[[package]]
|
| 1389 |
name = "flatbuffers"
|
| 1390 |
version = "25.9.23"
|
|
|
|
| 1621 |
{ url = "https://files.pythonhosted.org/packages/be/8a/f2a47134c5b5a7f3bad27eae749589a80d81efaaad8f59af47c136712bf6/gradio_client-1.14.0-py3-none-any.whl", hash = "sha256:9a2f5151978411e0f8b55a2d38cddd0a94491851149d14db4af96f5a09774825", size = 325555 },
|
| 1622 |
]
|
| 1623 |
|
| 1624 |
+
[[package]]
|
| 1625 |
+
name = "greenlet"
|
| 1626 |
+
version = "3.2.4"
|
| 1627 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1628 |
+
sdist = { url = "https://files.pythonhosted.org/packages/03/b8/704d753a5a45507a7aab61f18db9509302ed3d0a27ac7e0359ec2905b1a6/greenlet-3.2.4.tar.gz", hash = "sha256:0dca0d95ff849f9a364385f36ab49f50065d76964944638be9691e1832e9f86d", size = 188260 }
|
| 1629 |
+
wheels = [
|
| 1630 |
+
{ url = "https://files.pythonhosted.org/packages/a4/de/f28ced0a67749cac23fecb02b694f6473f47686dff6afaa211d186e2ef9c/greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2", size = 272305 },
|
| 1631 |
+
{ url = "https://files.pythonhosted.org/packages/09/16/2c3792cba130000bf2a31c5272999113f4764fd9d874fb257ff588ac779a/greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246", size = 632472 },
|
| 1632 |
+
{ url = "https://files.pythonhosted.org/packages/ae/8f/95d48d7e3d433e6dae5b1682e4292242a53f22df82e6d3dda81b1701a960/greenlet-3.2.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94abf90142c2a18151632371140b3dba4dee031633fe614cb592dbb6c9e17bc3", size = 644646 },
|
| 1633 |
+
{ url = "https://files.pythonhosted.org/packages/d5/5e/405965351aef8c76b8ef7ad370e5da58d57ef6068df197548b015464001a/greenlet-3.2.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:4d1378601b85e2e5171b99be8d2dc85f594c79967599328f95c1dc1a40f1c633", size = 640519 },
|
| 1634 |
+
{ url = "https://files.pythonhosted.org/packages/25/5d/382753b52006ce0218297ec1b628e048c4e64b155379331f25a7316eb749/greenlet-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0db5594dce18db94f7d1650d7489909b57afde4c580806b8d9203b6e79cdc079", size = 639707 },
|
| 1635 |
+
{ url = "https://files.pythonhosted.org/packages/1f/8e/abdd3f14d735b2929290a018ecf133c901be4874b858dd1c604b9319f064/greenlet-3.2.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8", size = 587684 },
|
| 1636 |
+
{ url = "https://files.pythonhosted.org/packages/5d/65/deb2a69c3e5996439b0176f6651e0052542bb6c8f8ec2e3fba97c9768805/greenlet-3.2.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52", size = 1116647 },
|
| 1637 |
+
{ url = "https://files.pythonhosted.org/packages/3f/cc/b07000438a29ac5cfb2194bfc128151d52f333cee74dd7dfe3fb733fc16c/greenlet-3.2.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:55e9c5affaa6775e2c6b67659f3a71684de4c549b3dd9afca3bc773533d284fa", size = 1142073 },
|
| 1638 |
+
{ url = "https://files.pythonhosted.org/packages/67/24/28a5b2fa42d12b3d7e5614145f0bd89714c34c08be6aabe39c14dd52db34/greenlet-3.2.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9c6de1940a7d828635fbd254d69db79e54619f165ee7ce32fda763a9cb6a58c", size = 1548385 },
|
| 1639 |
+
{ url = "https://files.pythonhosted.org/packages/6a/05/03f2f0bdd0b0ff9a4f7b99333d57b53a7709c27723ec8123056b084e69cd/greenlet-3.2.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03c5136e7be905045160b1b9fdca93dd6727b180feeafda6818e6496434ed8c5", size = 1613329 },
|
| 1640 |
+
{ url = "https://files.pythonhosted.org/packages/d8/0f/30aef242fcab550b0b3520b8e3561156857c94288f0332a79928c31a52cf/greenlet-3.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:9c40adce87eaa9ddb593ccb0fa6a07caf34015a29bf8d344811665b573138db9", size = 299100 },
|
| 1641 |
+
{ url = "https://files.pythonhosted.org/packages/44/69/9b804adb5fd0671f367781560eb5eb586c4d495277c93bde4307b9e28068/greenlet-3.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd", size = 274079 },
|
| 1642 |
+
{ url = "https://files.pythonhosted.org/packages/46/e9/d2a80c99f19a153eff70bc451ab78615583b8dac0754cfb942223d2c1a0d/greenlet-3.2.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb", size = 640997 },
|
| 1643 |
+
{ url = "https://files.pythonhosted.org/packages/3b/16/035dcfcc48715ccd345f3a93183267167cdd162ad123cd93067d86f27ce4/greenlet-3.2.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f28588772bb5fb869a8eb331374ec06f24a83a9c25bfa1f38b6993afe9c1e968", size = 655185 },
|
| 1644 |
+
{ url = "https://files.pythonhosted.org/packages/31/da/0386695eef69ffae1ad726881571dfe28b41970173947e7c558d9998de0f/greenlet-3.2.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:5c9320971821a7cb77cfab8d956fa8e39cd07ca44b6070db358ceb7f8797c8c9", size = 649926 },
|
| 1645 |
+
{ url = "https://files.pythonhosted.org/packages/68/88/69bf19fd4dc19981928ceacbc5fd4bb6bc2215d53199e367832e98d1d8fe/greenlet-3.2.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c60a6d84229b271d44b70fb6e5fa23781abb5d742af7b808ae3f6efd7c9c60f6", size = 651839 },
|
| 1646 |
+
{ url = "https://files.pythonhosted.org/packages/19/0d/6660d55f7373b2ff8152401a83e02084956da23ae58cddbfb0b330978fe9/greenlet-3.2.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0", size = 607586 },
|
| 1647 |
+
{ url = "https://files.pythonhosted.org/packages/8e/1a/c953fdedd22d81ee4629afbb38d2f9d71e37d23caace44775a3a969147d4/greenlet-3.2.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0", size = 1123281 },
|
| 1648 |
+
{ url = "https://files.pythonhosted.org/packages/3f/c7/12381b18e21aef2c6bd3a636da1088b888b97b7a0362fac2e4de92405f97/greenlet-3.2.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20fb936b4652b6e307b8f347665e2c615540d4b42b3b4c8a321d8286da7e520f", size = 1151142 },
|
| 1649 |
+
{ url = "https://files.pythonhosted.org/packages/27/45/80935968b53cfd3f33cf99ea5f08227f2646e044568c9b1555b58ffd61c2/greenlet-3.2.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee7a6ec486883397d70eec05059353b8e83eca9168b9f3f9a361971e77e0bcd0", size = 1564846 },
|
| 1650 |
+
{ url = "https://files.pythonhosted.org/packages/69/02/b7c30e5e04752cb4db6202a3858b149c0710e5453b71a3b2aec5d78a1aab/greenlet-3.2.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:326d234cbf337c9c3def0676412eb7040a35a768efc92504b947b3e9cfc7543d", size = 1633814 },
|
| 1651 |
+
{ url = "https://files.pythonhosted.org/packages/e9/08/b0814846b79399e585f974bbeebf5580fbe59e258ea7be64d9dfb253c84f/greenlet-3.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:a7d4e128405eea3814a12cc2605e0e6aedb4035bf32697f72deca74de4105e02", size = 299899 },
|
| 1652 |
+
{ url = "https://files.pythonhosted.org/packages/49/e8/58c7f85958bda41dafea50497cbd59738c5c43dbbea5ee83d651234398f4/greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31", size = 272814 },
|
| 1653 |
+
{ url = "https://files.pythonhosted.org/packages/62/dd/b9f59862e9e257a16e4e610480cfffd29e3fae018a68c2332090b53aac3d/greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945", size = 641073 },
|
| 1654 |
+
{ url = "https://files.pythonhosted.org/packages/f7/0b/bc13f787394920b23073ca3b6c4a7a21396301ed75a655bcb47196b50e6e/greenlet-3.2.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:710638eb93b1fa52823aa91bf75326f9ecdfd5e0466f00789246a5280f4ba0fc", size = 655191 },
|
| 1655 |
+
{ url = "https://files.pythonhosted.org/packages/f2/d6/6adde57d1345a8d0f14d31e4ab9c23cfe8e2cd39c3baf7674b4b0338d266/greenlet-3.2.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c5111ccdc9c88f423426df3fd1811bfc40ed66264d35aa373420a34377efc98a", size = 649516 },
|
| 1656 |
+
{ url = "https://files.pythonhosted.org/packages/7f/3b/3a3328a788d4a473889a2d403199932be55b1b0060f4ddd96ee7cdfcad10/greenlet-3.2.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76383238584e9711e20ebe14db6c88ddcedc1829a9ad31a584389463b5aa504", size = 652169 },
|
| 1657 |
+
{ url = "https://files.pythonhosted.org/packages/ee/43/3cecdc0349359e1a527cbf2e3e28e5f8f06d3343aaf82ca13437a9aa290f/greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671", size = 610497 },
|
| 1658 |
+
{ url = "https://files.pythonhosted.org/packages/b8/19/06b6cf5d604e2c382a6f31cafafd6f33d5dea706f4db7bdab184bad2b21d/greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b", size = 1121662 },
|
| 1659 |
+
{ url = "https://files.pythonhosted.org/packages/a2/15/0d5e4e1a66fab130d98168fe984c509249c833c1a3c16806b90f253ce7b9/greenlet-3.2.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d25c5091190f2dc0eaa3f950252122edbbadbb682aa7b1ef2f8af0f8c0afefae", size = 1149210 },
|
| 1660 |
+
{ url = "https://files.pythonhosted.org/packages/1c/53/f9c440463b3057485b8594d7a638bed53ba531165ef0ca0e6c364b5cc807/greenlet-3.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e343822feb58ac4d0a1211bd9399de2b3a04963ddeec21530fc426cc121f19b", size = 1564759 },
|
| 1661 |
+
{ url = "https://files.pythonhosted.org/packages/47/e4/3bb4240abdd0a8d23f4f88adec746a3099f0d86bfedb623f063b2e3b4df0/greenlet-3.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca7f6f1f2649b89ce02f6f229d7c19f680a6238af656f61e0115b24857917929", size = 1634288 },
|
| 1662 |
+
{ url = "https://files.pythonhosted.org/packages/0b/55/2321e43595e6801e105fcfdee02b34c0f996eb71e6ddffca6b10b7e1d771/greenlet-3.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:554b03b6e73aaabec3745364d6239e9e012d64c68ccd0b8430c64ccc14939a8b", size = 299685 },
|
| 1663 |
+
{ url = "https://files.pythonhosted.org/packages/22/5c/85273fd7cc388285632b0498dbbab97596e04b154933dfe0f3e68156c68c/greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0", size = 273586 },
|
| 1664 |
+
{ url = "https://files.pythonhosted.org/packages/d1/75/10aeeaa3da9332c2e761e4c50d4c3556c21113ee3f0afa2cf5769946f7a3/greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f", size = 686346 },
|
| 1665 |
+
{ url = "https://files.pythonhosted.org/packages/c0/aa/687d6b12ffb505a4447567d1f3abea23bd20e73a5bed63871178e0831b7a/greenlet-3.2.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c17b6b34111ea72fc5a4e4beec9711d2226285f0386ea83477cbb97c30a3f3a5", size = 699218 },
|
| 1666 |
+
{ url = "https://files.pythonhosted.org/packages/dc/8b/29aae55436521f1d6f8ff4e12fb676f3400de7fcf27fccd1d4d17fd8fecd/greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1", size = 694659 },
|
| 1667 |
+
{ url = "https://files.pythonhosted.org/packages/92/2e/ea25914b1ebfde93b6fc4ff46d6864564fba59024e928bdc7de475affc25/greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735", size = 695355 },
|
| 1668 |
+
{ url = "https://files.pythonhosted.org/packages/72/60/fc56c62046ec17f6b0d3060564562c64c862948c9d4bc8aa807cf5bd74f4/greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337", size = 657512 },
|
| 1669 |
+
{ url = "https://files.pythonhosted.org/packages/23/6e/74407aed965a4ab6ddd93a7ded3180b730d281c77b765788419484cdfeef/greenlet-3.2.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2917bdf657f5859fbf3386b12d68ede4cf1f04c90c3a6bc1f013dd68a22e2269", size = 1612508 },
|
| 1670 |
+
{ url = "https://files.pythonhosted.org/packages/0d/da/343cd760ab2f92bac1845ca07ee3faea9fe52bee65f7bcb19f16ad7de08b/greenlet-3.2.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:015d48959d4add5d6c9f6c5210ee3803a830dce46356e3bc326d6776bde54681", size = 1680760 },
|
| 1671 |
+
{ url = "https://files.pythonhosted.org/packages/e3/a5/6ddab2b4c112be95601c13428db1d8b6608a8b6039816f2ba09c346c08fc/greenlet-3.2.4-cp314-cp314-win_amd64.whl", hash = "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01", size = 303425 },
|
| 1672 |
+
]
|
| 1673 |
+
|
| 1674 |
[[package]]
|
| 1675 |
name = "griffe"
|
| 1676 |
version = "1.15.0"
|
|
|
|
| 1760 |
{ url = "https://files.pythonhosted.org/packages/19/41/0b430b01a2eb38ee887f88c1f07644a1df8e289353b78e82b37ef988fb64/grpcio-1.76.0-cp314-cp314-win_amd64.whl", hash = "sha256:922fa70ba549fce362d2e2871ab542082d66e2aaf0c19480ea453905b01f384e", size = 4834462 },
|
| 1761 |
]
|
| 1762 |
|
| 1763 |
+
[[package]]
|
| 1764 |
+
name = "grpclib"
|
| 1765 |
+
version = "0.4.8"
|
| 1766 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1767 |
+
dependencies = [
|
| 1768 |
+
{ name = "h2" },
|
| 1769 |
+
{ name = "multidict" },
|
| 1770 |
+
]
|
| 1771 |
+
sdist = { url = "https://files.pythonhosted.org/packages/19/75/0f0d3524b38b35e5cd07334b754aa9bd0570140ad982131b04ebfa3b0374/grpclib-0.4.8.tar.gz", hash = "sha256:d8823763780ef94fed8b2c562f7485cf0bbee15fc7d065a640673667f7719c9a", size = 62793 }
|
| 1772 |
+
wheels = [
|
| 1773 |
+
{ url = "https://files.pythonhosted.org/packages/03/8b/ad381ec1b8195fa4a9a693cb8087e031b99530c0d6b8ad036dcb99e144c4/grpclib-0.4.8-py3-none-any.whl", hash = "sha256:a5047733a7acc1c1cee6abf3c841c7c6fab67d2844a45a853b113fa2e6cd2654", size = 76311 },
|
| 1774 |
+
]
|
| 1775 |
+
|
| 1776 |
[[package]]
|
| 1777 |
name = "h11"
|
| 1778 |
version = "0.16.0"
|
|
|
|
| 1782 |
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515 },
|
| 1783 |
]
|
| 1784 |
|
| 1785 |
+
[[package]]
|
| 1786 |
+
name = "h2"
|
| 1787 |
+
version = "4.3.0"
|
| 1788 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1789 |
+
dependencies = [
|
| 1790 |
+
{ name = "hpack" },
|
| 1791 |
+
{ name = "hyperframe" },
|
| 1792 |
+
]
|
| 1793 |
+
sdist = { url = "https://files.pythonhosted.org/packages/1d/17/afa56379f94ad0fe8defd37d6eb3f89a25404ffc71d4d848893d270325fc/h2-4.3.0.tar.gz", hash = "sha256:6c59efe4323fa18b47a632221a1888bd7fde6249819beda254aeca909f221bf1", size = 2152026 }
|
| 1794 |
+
wheels = [
|
| 1795 |
+
{ url = "https://files.pythonhosted.org/packages/69/b2/119f6e6dcbd96f9069ce9a2665e0146588dc9f88f29549711853645e736a/h2-4.3.0-py3-none-any.whl", hash = "sha256:c438f029a25f7945c69e0ccf0fb951dc3f73a5f6412981daee861431b70e2bdd", size = 61779 },
|
| 1796 |
+
]
|
| 1797 |
+
|
| 1798 |
[[package]]
|
| 1799 |
name = "hf-xet"
|
| 1800 |
version = "1.2.0"
|
|
|
|
| 1824 |
{ url = "https://files.pythonhosted.org/packages/cb/44/870d44b30e1dcfb6a65932e3e1506c103a8a5aea9103c337e7a53180322c/hf_xet-1.2.0-cp37-abi3-win_amd64.whl", hash = "sha256:e6584a52253f72c9f52f9e549d5895ca7a471608495c4ecaa6cc73dba2b24d69", size = 2905735 },
|
| 1825 |
]
|
| 1826 |
|
| 1827 |
+
[[package]]
|
| 1828 |
+
name = "hpack"
|
| 1829 |
+
version = "4.1.0"
|
| 1830 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1831 |
+
sdist = { url = "https://files.pythonhosted.org/packages/2c/48/71de9ed269fdae9c8057e5a4c0aa7402e8bb16f2c6e90b3aa53327b113f8/hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca", size = 51276 }
|
| 1832 |
+
wheels = [
|
| 1833 |
+
{ url = "https://files.pythonhosted.org/packages/07/c6/80c95b1b2b94682a72cbdbfb85b81ae2daffa4291fbfa1b1464502ede10d/hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496", size = 34357 },
|
| 1834 |
+
]
|
| 1835 |
+
|
| 1836 |
[[package]]
|
| 1837 |
name = "httpcore"
|
| 1838 |
version = "1.0.9"
|
|
|
|
| 1942 |
{ url = "https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", size = 86794 },
|
| 1943 |
]
|
| 1944 |
|
| 1945 |
+
[[package]]
|
| 1946 |
+
name = "hyperframe"
|
| 1947 |
+
version = "6.1.0"
|
| 1948 |
+
source = { registry = "https://pypi.org/simple" }
|
| 1949 |
+
sdist = { url = "https://files.pythonhosted.org/packages/02/e7/94f8232d4a74cc99514c13a9f995811485a6903d48e5d952771ef6322e30/hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08", size = 26566 }
|
| 1950 |
+
wheels = [
|
| 1951 |
+
{ url = "https://files.pythonhosted.org/packages/48/30/47d0bf6072f7252e6521f3447ccfa40b421b6824517f82854703d0f5a98b/hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5", size = 13007 },
|
| 1952 |
+
]
|
| 1953 |
+
|
| 1954 |
[[package]]
|
| 1955 |
name = "identify"
|
| 1956 |
version = "2.6.15"
|
|
|
|
| 2249 |
{ url = "https://files.pythonhosted.org/packages/ca/ec/65f7d563aa4a62dd58777e8f6aa882f15db53b14eb29aba0c28a20f7eb26/kubernetes-34.1.0-py2.py3-none-any.whl", hash = "sha256:bffba2272534e224e6a7a74d582deb0b545b7c9879d2cd9e4aae9481d1f2cc2a", size = 2008380 },
|
| 2250 |
]
|
| 2251 |
|
| 2252 |
+
[[package]]
|
| 2253 |
+
name = "llama-cloud"
|
| 2254 |
+
version = "0.1.35"
|
| 2255 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2256 |
+
dependencies = [
|
| 2257 |
+
{ name = "certifi" },
|
| 2258 |
+
{ name = "httpx" },
|
| 2259 |
+
{ name = "pydantic" },
|
| 2260 |
+
]
|
| 2261 |
+
sdist = { url = "https://files.pythonhosted.org/packages/9b/72/816e6e900448e1b4a8137d90e65876b296c5264a23db6ae888bd3e6660ba/llama_cloud-0.1.35.tar.gz", hash = "sha256:200349d5d57424d7461f304cdb1355a58eea3e6ca1e6b0d75c66b2e937216983", size = 106403 }
|
| 2262 |
+
wheels = [
|
| 2263 |
+
{ url = "https://files.pythonhosted.org/packages/1d/d2/8d18a021ab757cea231428404f21fe3186bf1ebaac3f57a73c379483fd3f/llama_cloud-0.1.35-py3-none-any.whl", hash = "sha256:b7abab4423118e6f638d2f326749e7a07c6426543bea6da99b623c715b22af71", size = 303280 },
|
| 2264 |
+
]
|
| 2265 |
+
|
| 2266 |
+
[[package]]
|
| 2267 |
+
name = "llama-cloud-services"
|
| 2268 |
+
version = "0.6.54"
|
| 2269 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2270 |
+
dependencies = [
|
| 2271 |
+
{ name = "click" },
|
| 2272 |
+
{ name = "llama-cloud" },
|
| 2273 |
+
{ name = "llama-index-core" },
|
| 2274 |
+
{ name = "platformdirs" },
|
| 2275 |
+
{ name = "pydantic" },
|
| 2276 |
+
{ name = "python-dotenv" },
|
| 2277 |
+
{ name = "tenacity" },
|
| 2278 |
+
]
|
| 2279 |
+
sdist = { url = "https://files.pythonhosted.org/packages/8a/0c/8ca87d33bea0340a8ed791f36390112aeb29fd3eebfd64b6aef6204a03f0/llama_cloud_services-0.6.54.tar.gz", hash = "sha256:baf65d9bffb68f9dca98ac6e22908b6675b2038b021e657ead1ffc0e43cbd45d", size = 53468 }
|
| 2280 |
+
wheels = [
|
| 2281 |
+
{ url = "https://files.pythonhosted.org/packages/7f/48/4e295e3f791b279885a2e584f71e75cbe4ac84e93bba3c36e2668f60a8ac/llama_cloud_services-0.6.54-py3-none-any.whl", hash = "sha256:07f595f7a0ba40c6a1a20543d63024ca7600fe65c4811d1951039977908997be", size = 63874 },
|
| 2282 |
+
]
|
| 2283 |
+
|
| 2284 |
+
[[package]]
|
| 2285 |
+
name = "llama-index"
|
| 2286 |
+
version = "0.14.8"
|
| 2287 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2288 |
+
dependencies = [
|
| 2289 |
+
{ name = "llama-index-cli" },
|
| 2290 |
+
{ name = "llama-index-core" },
|
| 2291 |
+
{ name = "llama-index-embeddings-openai" },
|
| 2292 |
+
{ name = "llama-index-indices-managed-llama-cloud" },
|
| 2293 |
+
{ name = "llama-index-llms-openai" },
|
| 2294 |
+
{ name = "llama-index-readers-file" },
|
| 2295 |
+
{ name = "llama-index-readers-llama-parse" },
|
| 2296 |
+
{ name = "nltk" },
|
| 2297 |
+
]
|
| 2298 |
+
sdist = { url = "https://files.pythonhosted.org/packages/ce/ff/f230bd1b27f77a10de0d4c6a4942b31f5947fc3e170b6c49e3cc2c8a4352/llama_index-0.14.8.tar.gz", hash = "sha256:b4f5fcf5376e10acf691a2c8bdd019df189f1635b831bbc35894ecf1042e3743", size = 8462 }
|
| 2299 |
+
wheels = [
|
| 2300 |
+
{ url = "https://files.pythonhosted.org/packages/78/d8/0da07894f6388206fdadcd0ef8655b45d31176fb5052bcce9fede5d3cb63/llama_index-0.14.8-py3-none-any.whl", hash = "sha256:26755032aefb2ca355c5e263eaa3d0c5ed955afa9e95781340c9068916826397", size = 7447 },
|
| 2301 |
+
]
|
| 2302 |
+
|
| 2303 |
+
[[package]]
|
| 2304 |
+
name = "llama-index-cli"
|
| 2305 |
+
version = "0.5.3"
|
| 2306 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2307 |
+
dependencies = [
|
| 2308 |
+
{ name = "llama-index-core" },
|
| 2309 |
+
{ name = "llama-index-embeddings-openai" },
|
| 2310 |
+
{ name = "llama-index-llms-openai" },
|
| 2311 |
+
]
|
| 2312 |
+
sdist = { url = "https://files.pythonhosted.org/packages/67/84/41e820efffbe327c38228d3b37fe42512a37e0c3ee4ff6bf97a394e9577a/llama_index_cli-0.5.3.tar.gz", hash = "sha256:ebaf39e785efbfa8d50d837f60cb0f95125c04bf73ed1f92092a2a5f506172f8", size = 24821 }
|
| 2313 |
+
wheels = [
|
| 2314 |
+
{ url = "https://files.pythonhosted.org/packages/54/81/b7b3778aa8662913760fbbee77578daf4407aeaa677ccbf0125c4cfa2e67/llama_index_cli-0.5.3-py3-none-any.whl", hash = "sha256:7deb1e953e582bd885443881ce8bd6ab2817b594fef00079dce9993c47d990f7", size = 28173 },
|
| 2315 |
+
]
|
| 2316 |
+
|
| 2317 |
+
[[package]]
|
| 2318 |
+
name = "llama-index-core"
|
| 2319 |
+
version = "0.14.8"
|
| 2320 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2321 |
+
dependencies = [
|
| 2322 |
+
{ name = "aiohttp" },
|
| 2323 |
+
{ name = "aiosqlite" },
|
| 2324 |
+
{ name = "banks" },
|
| 2325 |
+
{ name = "dataclasses-json" },
|
| 2326 |
+
{ name = "deprecated" },
|
| 2327 |
+
{ name = "dirtyjson" },
|
| 2328 |
+
{ name = "filetype" },
|
| 2329 |
+
{ name = "fsspec" },
|
| 2330 |
+
{ name = "httpx" },
|
| 2331 |
+
{ name = "llama-index-workflows" },
|
| 2332 |
+
{ name = "nest-asyncio" },
|
| 2333 |
+
{ name = "networkx" },
|
| 2334 |
+
{ name = "nltk" },
|
| 2335 |
+
{ name = "numpy" },
|
| 2336 |
+
{ name = "pillow" },
|
| 2337 |
+
{ name = "platformdirs" },
|
| 2338 |
+
{ name = "pydantic" },
|
| 2339 |
+
{ name = "pyyaml" },
|
| 2340 |
+
{ name = "requests" },
|
| 2341 |
+
{ name = "setuptools" },
|
| 2342 |
+
{ name = "sqlalchemy", extra = ["asyncio"] },
|
| 2343 |
+
{ name = "tenacity" },
|
| 2344 |
+
{ name = "tiktoken" },
|
| 2345 |
+
{ name = "tqdm" },
|
| 2346 |
+
{ name = "typing-extensions" },
|
| 2347 |
+
{ name = "typing-inspect" },
|
| 2348 |
+
{ name = "wrapt" },
|
| 2349 |
+
]
|
| 2350 |
+
sdist = { url = "https://files.pythonhosted.org/packages/b0/ee/3f68cfac0eba7085aaeede5d179d31097d8351cbeae333859aabd0e20ed7/llama_index_core-0.14.8.tar.gz", hash = "sha256:8865a8546746b8c5f0684085ccfcf900aeb04862ebfe2077ad522374cf71e58e", size = 11579082 }
|
| 2351 |
+
wheels = [
|
| 2352 |
+
{ url = "https://files.pythonhosted.org/packages/27/61/bdc7d7e818f07ae8208786581608043c95a510f3f0906d7f6f53a69a1712/llama_index_core-0.14.8-py3-none-any.whl", hash = "sha256:e54046f09507aeb2fad51d8e9686dc0fa41c77d3925892e55c3756ca31f1c0c3", size = 11920547 },
|
| 2353 |
+
]
|
| 2354 |
+
|
| 2355 |
+
[[package]]
|
| 2356 |
+
name = "llama-index-embeddings-openai"
|
| 2357 |
+
version = "0.5.1"
|
| 2358 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2359 |
+
dependencies = [
|
| 2360 |
+
{ name = "llama-index-core" },
|
| 2361 |
+
{ name = "openai" },
|
| 2362 |
+
]
|
| 2363 |
+
sdist = { url = "https://files.pythonhosted.org/packages/10/36/90336d054a5061a3f5bc17ac2c18ef63d9d84c55c14d557de484e811ea4d/llama_index_embeddings_openai-0.5.1.tar.gz", hash = "sha256:1c89867a48b0d0daa3d2d44f5e76b394b2b2ef9935932daf921b9e77939ccda8", size = 7020 }
|
| 2364 |
+
wheels = [
|
| 2365 |
+
{ url = "https://files.pythonhosted.org/packages/23/4a/8ab11026cf8deff8f555aa73919be0bac48332683111e5fc4290f352dc50/llama_index_embeddings_openai-0.5.1-py3-none-any.whl", hash = "sha256:a2fcda3398bbd987b5ce3f02367caee8e84a56b930fdf43cc1d059aa9fd20ca5", size = 7011 },
|
| 2366 |
+
]
|
| 2367 |
+
|
| 2368 |
+
[[package]]
|
| 2369 |
+
name = "llama-index-indices-managed-llama-cloud"
|
| 2370 |
+
version = "0.9.4"
|
| 2371 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2372 |
+
dependencies = [
|
| 2373 |
+
{ name = "deprecated" },
|
| 2374 |
+
{ name = "llama-cloud" },
|
| 2375 |
+
{ name = "llama-index-core" },
|
| 2376 |
+
]
|
| 2377 |
+
sdist = { url = "https://files.pythonhosted.org/packages/61/4a/79044fcb3209583d1ffe0c2a7c19dddfb657a03faeb9fe0cf5a74027e646/llama_index_indices_managed_llama_cloud-0.9.4.tar.gz", hash = "sha256:b5e00752ab30564abf19c57595a2107f5697c3b03b085817b4fca84a38ebbd59", size = 15146 }
|
| 2378 |
+
wheels = [
|
| 2379 |
+
{ url = "https://files.pythonhosted.org/packages/a6/6a/0e33245df06afc9766c46a1fe92687be8a09da5d0d0128bc08d84a9f5efa/llama_index_indices_managed_llama_cloud-0.9.4-py3-none-any.whl", hash = "sha256:535a08811046803ca6ab7f8e9d510e926aa5306608b02201ad3d9d21701383bc", size = 17005 },
|
| 2380 |
+
]
|
| 2381 |
+
|
| 2382 |
+
[[package]]
|
| 2383 |
+
name = "llama-index-instrumentation"
|
| 2384 |
+
version = "0.4.2"
|
| 2385 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2386 |
+
dependencies = [
|
| 2387 |
+
{ name = "deprecated" },
|
| 2388 |
+
{ name = "pydantic" },
|
| 2389 |
+
]
|
| 2390 |
+
sdist = { url = "https://files.pythonhosted.org/packages/af/b9/a7a74de6d8aacf4be329329495983d78d96b1a6e69b6d9fcf4a233febd4b/llama_index_instrumentation-0.4.2.tar.gz", hash = "sha256:dc4957b64da0922060690e85a6be9698ac08e34e0f69e90b01364ddec4f3de7f", size = 46146 }
|
| 2391 |
+
wheels = [
|
| 2392 |
+
{ url = "https://files.pythonhosted.org/packages/40/54/df8063b0441242e250e03d1e31ebde5dffbe24e1af32b025cb1a4544150c/llama_index_instrumentation-0.4.2-py3-none-any.whl", hash = "sha256:b4989500e6454059ab3f3c4a193575d47ab1fadb730c2e8f2b962649ae88b70b", size = 15411 },
|
| 2393 |
+
]
|
| 2394 |
+
|
| 2395 |
+
[[package]]
|
| 2396 |
+
name = "llama-index-llms-openai"
|
| 2397 |
+
version = "0.6.9"
|
| 2398 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2399 |
+
dependencies = [
|
| 2400 |
+
{ name = "llama-index-core" },
|
| 2401 |
+
{ name = "openai" },
|
| 2402 |
+
]
|
| 2403 |
+
sdist = { url = "https://files.pythonhosted.org/packages/2b/6a/3b0225298b10ace4b5c08f564dfc5ddcdbd1792b027097628c120a00d0af/llama_index_llms_openai-0.6.9.tar.gz", hash = "sha256:4c8c91a5e5b0e59b44ecd8fe43156e93c6abf1c9ca8e1e4ad3e4834c84f51199", size = 25535 }
|
| 2404 |
+
wheels = [
|
| 2405 |
+
{ url = "https://files.pythonhosted.org/packages/76/74/103b4f967f589f92e43b55f4dcfa5ad3544a475ff9103e15dcfc57e3c28e/llama_index_llms_openai-0.6.9-py3-none-any.whl", hash = "sha256:02eec6ef46ac67be76607ea28c6fbe4c95a6713adc2da629e3682a6b3802cf38", size = 26532 },
|
| 2406 |
+
]
|
| 2407 |
+
|
| 2408 |
+
[[package]]
|
| 2409 |
+
name = "llama-index-readers-file"
|
| 2410 |
+
version = "0.5.5"
|
| 2411 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2412 |
+
dependencies = [
|
| 2413 |
+
{ name = "beautifulsoup4" },
|
| 2414 |
+
{ name = "defusedxml" },
|
| 2415 |
+
{ name = "llama-index-core" },
|
| 2416 |
+
{ name = "pandas" },
|
| 2417 |
+
{ name = "pypdf" },
|
| 2418 |
+
{ name = "striprtf" },
|
| 2419 |
+
]
|
| 2420 |
+
sdist = { url = "https://files.pythonhosted.org/packages/99/13/5bb486c57832efdd8dddc28fc04535f74dcc6ea07847b1ab2075a9d9c6e8/llama_index_readers_file-0.5.5.tar.gz", hash = "sha256:024b841cfdf6d37e4e24cea6c89edfac5f0eaffcbcfc4904e4b0b169847c10e5", size = 32563 }
|
| 2421 |
+
wheels = [
|
| 2422 |
+
{ url = "https://files.pythonhosted.org/packages/19/f6/0dc2a15f8d821721cc958873c8c83367d7fbbd411c512d0262b64c055ce3/llama_index_readers_file-0.5.5-py3-none-any.whl", hash = "sha256:948adef8d0aff839c99c95ae876c3ae57a58b319e3dd0862d68932dbd408a022", size = 51826 },
|
| 2423 |
+
]
|
| 2424 |
+
|
| 2425 |
+
[[package]]
|
| 2426 |
+
name = "llama-index-readers-llama-parse"
|
| 2427 |
+
version = "0.5.1"
|
| 2428 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2429 |
+
dependencies = [
|
| 2430 |
+
{ name = "llama-index-core" },
|
| 2431 |
+
{ name = "llama-parse" },
|
| 2432 |
+
]
|
| 2433 |
+
sdist = { url = "https://files.pythonhosted.org/packages/b3/77/5bfaab20e6ec8428dbf2352e18be550c957602723d69383908176b5686cd/llama_index_readers_llama_parse-0.5.1.tar.gz", hash = "sha256:2b78b73faa933e30e6c69df351e4e9f36dfe2ae142e2ab3969ddd2ac48930e37", size = 3858 }
|
| 2434 |
+
wheels = [
|
| 2435 |
+
{ url = "https://files.pythonhosted.org/packages/68/81/52410c7245dcbf1a54756a9ce3892cdd167ec0b884d696de1304ca3f452e/llama_index_readers_llama_parse-0.5.1-py3-none-any.whl", hash = "sha256:0d41450ed29b0c49c024e206ef6c8e662b1854e77a1c5faefed3b958be54f880", size = 3203 },
|
| 2436 |
+
]
|
| 2437 |
+
|
| 2438 |
+
[[package]]
|
| 2439 |
+
name = "llama-index-vector-stores-chroma"
|
| 2440 |
+
version = "0.5.3"
|
| 2441 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2442 |
+
dependencies = [
|
| 2443 |
+
{ name = "chromadb" },
|
| 2444 |
+
{ name = "llama-index-core" },
|
| 2445 |
+
]
|
| 2446 |
+
sdist = { url = "https://files.pythonhosted.org/packages/ce/d3/2a1c3a4d3f32b35875c6ab4f33d2390acbf2346d87633126643109c51e20/llama_index_vector_stores_chroma-0.5.3.tar.gz", hash = "sha256:a066b9ee3dc5110a0e13b9dfeb1f4ae0b48931c04644ca7f534a69043c29149a", size = 7948 }
|
| 2447 |
+
wheels = [
|
| 2448 |
+
{ url = "https://files.pythonhosted.org/packages/aa/8e/699ffdf950f5c04200ed5129e244f1ea92ff4f2651d16eaeb6fec0e3d320/llama_index_vector_stores_chroma-0.5.3-py3-none-any.whl", hash = "sha256:f958553e421068681f5bc5581dfa63c768922f26280717dfeaf86677c6d583ee", size = 7751 },
|
| 2449 |
+
]
|
| 2450 |
+
|
| 2451 |
+
[[package]]
|
| 2452 |
+
name = "llama-index-workflows"
|
| 2453 |
+
version = "2.11.5"
|
| 2454 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2455 |
+
dependencies = [
|
| 2456 |
+
{ name = "llama-index-instrumentation" },
|
| 2457 |
+
{ name = "pydantic" },
|
| 2458 |
+
{ name = "typing-extensions" },
|
| 2459 |
+
]
|
| 2460 |
+
sdist = { url = "https://files.pythonhosted.org/packages/d4/14/b15613ece1d7bfbe3f3b1a7f76cf9eaa603b55dd6b5921e81de2ee21f580/llama_index_workflows-2.11.5.tar.gz", hash = "sha256:defba6c5169a9c986fe06dd9f3ee5e1a6cc5f58c776605c0458baa0a55f07643", size = 70743 }
|
| 2461 |
+
wheels = [
|
| 2462 |
+
{ url = "https://files.pythonhosted.org/packages/90/ac/e911594a2f10445717ea45b61b3a93f3bb91594320745fe1bb796c2dc87a/llama_index_workflows-2.11.5-py3-none-any.whl", hash = "sha256:3c5a419129114bb0b1bd83b88aa5f653f84181b2e39e33473e8747ec6e88538e", size = 91982 },
|
| 2463 |
+
]
|
| 2464 |
+
|
| 2465 |
+
[[package]]
|
| 2466 |
+
name = "llama-parse"
|
| 2467 |
+
version = "0.6.54"
|
| 2468 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2469 |
+
dependencies = [
|
| 2470 |
+
{ name = "llama-cloud-services" },
|
| 2471 |
+
]
|
| 2472 |
+
sdist = { url = "https://files.pythonhosted.org/packages/08/f6/93b5d123c480bc8c93e6dc3ea930f4f8df8da27f829bb011100ba3ce23dc/llama_parse-0.6.54.tar.gz", hash = "sha256:c707b31152155c9bae84e316fab790bbc8c85f4d8825ce5ee386ebeb7db258f1", size = 3577 }
|
| 2473 |
+
wheels = [
|
| 2474 |
+
{ url = "https://files.pythonhosted.org/packages/05/50/c5ccd2a50daa0a10c7f3f7d4e6992392454198cd8a7d99fcb96cb60d0686/llama_parse-0.6.54-py3-none-any.whl", hash = "sha256:c66c8d51cf6f29a44eaa8595a595de5d2598afc86e5a33a4cebe5fe228036920", size = 4879 },
|
| 2475 |
+
]
|
| 2476 |
+
|
| 2477 |
[[package]]
|
| 2478 |
name = "logfire"
|
| 2479 |
version = "4.15.1"
|
|
|
|
| 2592 |
{ url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146 },
|
| 2593 |
]
|
| 2594 |
|
| 2595 |
+
[[package]]
|
| 2596 |
+
name = "marshmallow"
|
| 2597 |
+
version = "3.26.1"
|
| 2598 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2599 |
+
dependencies = [
|
| 2600 |
+
{ name = "packaging" },
|
| 2601 |
+
]
|
| 2602 |
+
sdist = { url = "https://files.pythonhosted.org/packages/ab/5e/5e53d26b42ab75491cda89b871dab9e97c840bf12c63ec58a1919710cd06/marshmallow-3.26.1.tar.gz", hash = "sha256:e6d8affb6cb61d39d26402096dc0aee12d5a26d490a121f118d2e81dc0719dc6", size = 221825 }
|
| 2603 |
+
wheels = [
|
| 2604 |
+
{ url = "https://files.pythonhosted.org/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", size = 50878 },
|
| 2605 |
+
]
|
| 2606 |
+
|
| 2607 |
[[package]]
|
| 2608 |
name = "mcp"
|
| 2609 |
version = "1.22.0"
|
|
|
|
| 2757 |
{ url = "https://files.pythonhosted.org/packages/6a/fc/0e61d9a4e29c8679356795a40e48f647b4aad58d71bfc969f0f8f56fb912/mmh3-5.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9", size = 40455 },
|
| 2758 |
]
|
| 2759 |
|
| 2760 |
+
[[package]]
|
| 2761 |
+
name = "modal"
|
| 2762 |
+
version = "1.2.4"
|
| 2763 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2764 |
+
dependencies = [
|
| 2765 |
+
{ name = "aiohttp" },
|
| 2766 |
+
{ name = "cbor2" },
|
| 2767 |
+
{ name = "certifi" },
|
| 2768 |
+
{ name = "click" },
|
| 2769 |
+
{ name = "grpclib" },
|
| 2770 |
+
{ name = "protobuf" },
|
| 2771 |
+
{ name = "rich" },
|
| 2772 |
+
{ name = "synchronicity" },
|
| 2773 |
+
{ name = "toml" },
|
| 2774 |
+
{ name = "typer" },
|
| 2775 |
+
{ name = "types-certifi" },
|
| 2776 |
+
{ name = "types-toml" },
|
| 2777 |
+
{ name = "typing-extensions" },
|
| 2778 |
+
{ name = "watchfiles" },
|
| 2779 |
+
]
|
| 2780 |
+
sdist = { url = "https://files.pythonhosted.org/packages/91/b1/7bd589a3e1cc1ffc3fc2c05d1fab4b02459552d1ed416e00f19969e54f32/modal-1.2.4.tar.gz", hash = "sha256:5acb4a57a4bc857944579a3cf36e93f38d39499837628e9acf591d45d0c88c89", size = 645018 }
|
| 2781 |
+
wheels = [
|
| 2782 |
+
{ url = "https://files.pythonhosted.org/packages/ad/5a/a6bb9d01111109398bad8405587dde4f65088604b958c4f5e8cc5b212460/modal-1.2.4-py3-none-any.whl", hash = "sha256:cf4f01081bd9e5e1ec844d87a2c6a5805fd7c8f4deff5671c20d3b1505899aa8", size = 742291 },
|
| 2783 |
+
]
|
| 2784 |
+
|
| 2785 |
[[package]]
|
| 2786 |
name = "more-itertools"
|
| 2787 |
version = "10.8.0"
|
|
|
|
| 2990 |
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963 },
|
| 2991 |
]
|
| 2992 |
|
| 2993 |
+
[[package]]
|
| 2994 |
+
name = "nest-asyncio"
|
| 2995 |
+
version = "1.6.0"
|
| 2996 |
+
source = { registry = "https://pypi.org/simple" }
|
| 2997 |
+
sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418 }
|
| 2998 |
+
wheels = [
|
| 2999 |
+
{ url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195 },
|
| 3000 |
+
]
|
| 3001 |
+
|
| 3002 |
[[package]]
|
| 3003 |
name = "networkx"
|
| 3004 |
version = "3.6"
|
|
|
|
| 3020 |
{ url = "https://files.pythonhosted.org/packages/bf/2f/9e9d0dcaa4c6ffa22b7aa31069a8a264c753ff8027b36af602cce038c92f/nexus_rpc-1.1.0-py3-none-any.whl", hash = "sha256:d1b007af2aba186a27e736f8eaae39c03aed05b488084ff6c3d1785c9ba2ad38", size = 27743 },
|
| 3021 |
]
|
| 3022 |
|
| 3023 |
+
[[package]]
|
| 3024 |
+
name = "nltk"
|
| 3025 |
+
version = "3.9.2"
|
| 3026 |
+
source = { registry = "https://pypi.org/simple" }
|
| 3027 |
+
dependencies = [
|
| 3028 |
+
{ name = "click" },
|
| 3029 |
+
{ name = "joblib" },
|
| 3030 |
+
{ name = "regex" },
|
| 3031 |
+
{ name = "tqdm" },
|
| 3032 |
+
]
|
| 3033 |
+
sdist = { url = "https://files.pythonhosted.org/packages/f9/76/3a5e4312c19a028770f86fd7c058cf9f4ec4321c6cf7526bab998a5b683c/nltk-3.9.2.tar.gz", hash = "sha256:0f409e9b069ca4177c1903c3e843eef90c7e92992fa4931ae607da6de49e1419", size = 2887629 }
|
| 3034 |
+
wheels = [
|
| 3035 |
+
{ url = "https://files.pythonhosted.org/packages/60/90/81ac364ef94209c100e12579629dc92bf7a709a84af32f8c551b02c07e94/nltk-3.9.2-py3-none-any.whl", hash = "sha256:1e209d2b3009110635ed9709a67a1a3e33a10f799490fa71cf4bec218c11c88a", size = 1513404 },
|
| 3036 |
+
]
|
| 3037 |
+
|
| 3038 |
[[package]]
|
| 3039 |
name = "nodeenv"
|
| 3040 |
version = "1.9.1"
|
|
|
|
| 3568 |
|
| 3569 |
[[package]]
|
| 3570 |
name = "pandas"
|
| 3571 |
+
version = "2.2.3"
|
| 3572 |
source = { registry = "https://pypi.org/simple" }
|
| 3573 |
dependencies = [
|
| 3574 |
{ name = "numpy" },
|
|
|
|
| 3576 |
{ name = "pytz" },
|
| 3577 |
{ name = "tzdata" },
|
| 3578 |
]
|
| 3579 |
+
sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213 }
|
| 3580 |
+
wheels = [
|
| 3581 |
+
{ url = "https://files.pythonhosted.org/packages/a8/44/d9502bf0ed197ba9bf1103c9867d5904ddcaf869e52329787fc54ed70cc8/pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039", size = 12602222 },
|
| 3582 |
+
{ url = "https://files.pythonhosted.org/packages/52/11/9eac327a38834f162b8250aab32a6781339c69afe7574368fffe46387edf/pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd", size = 11321274 },
|
| 3583 |
+
{ url = "https://files.pythonhosted.org/packages/45/fb/c4beeb084718598ba19aa9f5abbc8aed8b42f90930da861fcb1acdb54c3a/pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698", size = 15579836 },
|
| 3584 |
+
{ url = "https://files.pythonhosted.org/packages/cd/5f/4dba1d39bb9c38d574a9a22548c540177f78ea47b32f99c0ff2ec499fac5/pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc", size = 13058505 },
|
| 3585 |
+
{ url = "https://files.pythonhosted.org/packages/b9/57/708135b90391995361636634df1f1130d03ba456e95bcf576fada459115a/pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3", size = 16744420 },
|
| 3586 |
+
{ url = "https://files.pythonhosted.org/packages/86/4a/03ed6b7ee323cf30404265c284cee9c65c56a212e0a08d9ee06984ba2240/pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32", size = 14440457 },
|
| 3587 |
+
{ url = "https://files.pythonhosted.org/packages/ed/8c/87ddf1fcb55d11f9f847e3c69bb1c6f8e46e2f40ab1a2d2abadb2401b007/pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5", size = 11617166 },
|
| 3588 |
+
{ url = "https://files.pythonhosted.org/packages/17/a3/fb2734118db0af37ea7433f57f722c0a56687e14b14690edff0cdb4b7e58/pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", size = 12529893 },
|
| 3589 |
+
{ url = "https://files.pythonhosted.org/packages/e1/0c/ad295fd74bfac85358fd579e271cded3ac969de81f62dd0142c426b9da91/pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4", size = 11363475 },
|
| 3590 |
+
{ url = "https://files.pythonhosted.org/packages/c6/2a/4bba3f03f7d07207481fed47f5b35f556c7441acddc368ec43d6643c5777/pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3", size = 15188645 },
|
| 3591 |
+
{ url = "https://files.pythonhosted.org/packages/38/f8/d8fddee9ed0d0c0f4a2132c1dfcf0e3e53265055da8df952a53e7eaf178c/pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319", size = 12739445 },
|
| 3592 |
+
{ url = "https://files.pythonhosted.org/packages/20/e8/45a05d9c39d2cea61ab175dbe6a2de1d05b679e8de2011da4ee190d7e748/pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8", size = 16359235 },
|
| 3593 |
+
{ url = "https://files.pythonhosted.org/packages/1d/99/617d07a6a5e429ff90c90da64d428516605a1ec7d7bea494235e1c3882de/pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", size = 14056756 },
|
| 3594 |
+
{ url = "https://files.pythonhosted.org/packages/29/d4/1244ab8edf173a10fd601f7e13b9566c1b525c4f365d6bee918e68381889/pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", size = 11504248 },
|
| 3595 |
+
{ url = "https://files.pythonhosted.org/packages/64/22/3b8f4e0ed70644e85cfdcd57454686b9057c6c38d2f74fe4b8bc2527214a/pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", size = 12477643 },
|
| 3596 |
+
{ url = "https://files.pythonhosted.org/packages/e4/93/b3f5d1838500e22c8d793625da672f3eec046b1a99257666c94446969282/pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", size = 11281573 },
|
| 3597 |
+
{ url = "https://files.pythonhosted.org/packages/f5/94/6c79b07f0e5aab1dcfa35a75f4817f5c4f677931d4234afcd75f0e6a66ca/pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", size = 15196085 },
|
| 3598 |
+
{ url = "https://files.pythonhosted.org/packages/e8/31/aa8da88ca0eadbabd0a639788a6da13bb2ff6edbbb9f29aa786450a30a91/pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", size = 12711809 },
|
| 3599 |
+
{ url = "https://files.pythonhosted.org/packages/ee/7c/c6dbdb0cb2a4344cacfb8de1c5808ca885b2e4dcfde8008266608f9372af/pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659", size = 16356316 },
|
| 3600 |
+
{ url = "https://files.pythonhosted.org/packages/57/b7/8b757e7d92023b832869fa8881a992696a0bfe2e26f72c9ae9f255988d42/pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", size = 14022055 },
|
| 3601 |
+
{ url = "https://files.pythonhosted.org/packages/3b/bc/4b18e2b8c002572c5a441a64826252ce5da2aa738855747247a971988043/pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", size = 11481175 },
|
| 3602 |
+
{ url = "https://files.pythonhosted.org/packages/76/a3/a5d88146815e972d40d19247b2c162e88213ef51c7c25993942c39dbf41d/pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", size = 12615650 },
|
| 3603 |
+
{ url = "https://files.pythonhosted.org/packages/9c/8c/f0fd18f6140ddafc0c24122c8a964e48294acc579d47def376fef12bcb4a/pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18", size = 11290177 },
|
| 3604 |
+
{ url = "https://files.pythonhosted.org/packages/ed/f9/e995754eab9c0f14c6777401f7eece0943840b7a9fc932221c19d1abee9f/pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2", size = 14651526 },
|
| 3605 |
+
{ url = "https://files.pythonhosted.org/packages/25/b0/98d6ae2e1abac4f35230aa756005e8654649d305df9a28b16b9ae4353bff/pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", size = 11871013 },
|
| 3606 |
+
{ url = "https://files.pythonhosted.org/packages/cc/57/0f72a10f9db6a4628744c8e8f0df4e6e21de01212c7c981d31e50ffc8328/pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d", size = 15711620 },
|
| 3607 |
+
{ url = "https://files.pythonhosted.org/packages/ab/5f/b38085618b950b79d2d9164a711c52b10aefc0ae6833b96f626b7021b2ed/pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", size = 13098436 },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3608 |
]
|
| 3609 |
|
| 3610 |
[[package]]
|
|
|
|
| 4385 |
{ name = "cryptography" },
|
| 4386 |
]
|
| 4387 |
|
| 4388 |
+
[[package]]
|
| 4389 |
+
name = "pypdf"
|
| 4390 |
+
version = "6.4.0"
|
| 4391 |
+
source = { registry = "https://pypi.org/simple" }
|
| 4392 |
+
sdist = { url = "https://files.pythonhosted.org/packages/f3/01/f7510cc6124f494cfbec2e8d3c2e1a20d4f6c18622b0c03a3a70e968bacb/pypdf-6.4.0.tar.gz", hash = "sha256:4769d471f8ddc3341193ecc5d6560fa44cf8cd0abfabf21af4e195cc0c224072", size = 5276661 }
|
| 4393 |
+
wheels = [
|
| 4394 |
+
{ url = "https://files.pythonhosted.org/packages/cd/f2/9c9429411c91ac1dd5cd66780f22b6df20c64c3646cdd1e6d67cf38579c4/pypdf-6.4.0-py3-none-any.whl", hash = "sha256:55ab9837ed97fd7fcc5c131d52fcc2223bc5c6b8a1488bbf7c0e27f1f0023a79", size = 329497 },
|
| 4395 |
+
]
|
| 4396 |
+
|
| 4397 |
[[package]]
|
| 4398 |
name = "pyperclip"
|
| 4399 |
version = "1.11.0"
|
|
|
|
| 5177 |
{ url = "https://files.pythonhosted.org/packages/14/a0/bb38d3b76b8cae341dad93a2dd83ab7462e6dbcdd84d43f54ee60a8dc167/soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c", size = 36679 },
|
| 5178 |
]
|
| 5179 |
|
| 5180 |
+
[[package]]
|
| 5181 |
+
name = "sqlalchemy"
|
| 5182 |
+
version = "2.0.44"
|
| 5183 |
+
source = { registry = "https://pypi.org/simple" }
|
| 5184 |
+
dependencies = [
|
| 5185 |
+
{ 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'" },
|
| 5186 |
+
{ name = "typing-extensions" },
|
| 5187 |
+
]
|
| 5188 |
+
sdist = { url = "https://files.pythonhosted.org/packages/f0/f2/840d7b9496825333f532d2e3976b8eadbf52034178aac53630d09fe6e1ef/sqlalchemy-2.0.44.tar.gz", hash = "sha256:0ae7454e1ab1d780aee69fd2aae7d6b8670a581d8847f2d1e0f7ddfbf47e5a22", size = 9819830 }
|
| 5189 |
+
wheels = [
|
| 5190 |
+
{ url = "https://files.pythonhosted.org/packages/e3/81/15d7c161c9ddf0900b076b55345872ed04ff1ed6a0666e5e94ab44b0163c/sqlalchemy-2.0.44-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0fe3917059c7ab2ee3f35e77757062b1bea10a0b6ca633c58391e3f3c6c488dd", size = 2140517 },
|
| 5191 |
+
{ url = "https://files.pythonhosted.org/packages/d4/d5/4abd13b245c7d91bdf131d4916fd9e96a584dac74215f8b5bc945206a974/sqlalchemy-2.0.44-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:de4387a354ff230bc979b46b2207af841dc8bf29847b6c7dbe60af186d97aefa", size = 2130738 },
|
| 5192 |
+
{ url = "https://files.pythonhosted.org/packages/cb/3c/8418969879c26522019c1025171cefbb2a8586b6789ea13254ac602986c0/sqlalchemy-2.0.44-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3678a0fb72c8a6a29422b2732fe423db3ce119c34421b5f9955873eb9b62c1e", size = 3304145 },
|
| 5193 |
+
{ url = "https://files.pythonhosted.org/packages/94/2d/fdb9246d9d32518bda5d90f4b65030b9bf403a935cfe4c36a474846517cb/sqlalchemy-2.0.44-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cf6872a23601672d61a68f390e44703442639a12ee9dd5a88bbce52a695e46e", size = 3304511 },
|
| 5194 |
+
{ url = "https://files.pythonhosted.org/packages/7d/fb/40f2ad1da97d5c83f6c1269664678293d3fe28e90ad17a1093b735420549/sqlalchemy-2.0.44-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:329aa42d1be9929603f406186630135be1e7a42569540577ba2c69952b7cf399", size = 3235161 },
|
| 5195 |
+
{ url = "https://files.pythonhosted.org/packages/95/cb/7cf4078b46752dca917d18cf31910d4eff6076e5b513c2d66100c4293d83/sqlalchemy-2.0.44-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:70e03833faca7166e6a9927fbee7c27e6ecde436774cd0b24bbcc96353bce06b", size = 3261426 },
|
| 5196 |
+
{ url = "https://files.pythonhosted.org/packages/f8/3b/55c09b285cb2d55bdfa711e778bdffdd0dc3ffa052b0af41f1c5d6e582fa/sqlalchemy-2.0.44-cp311-cp311-win32.whl", hash = "sha256:253e2f29843fb303eca6b2fc645aca91fa7aa0aa70b38b6950da92d44ff267f3", size = 2105392 },
|
| 5197 |
+
{ url = "https://files.pythonhosted.org/packages/c7/23/907193c2f4d680aedbfbdf7bf24c13925e3c7c292e813326c1b84a0b878e/sqlalchemy-2.0.44-cp311-cp311-win_amd64.whl", hash = "sha256:7a8694107eb4308a13b425ca8c0e67112f8134c846b6e1f722698708741215d5", size = 2130293 },
|
| 5198 |
+
{ url = "https://files.pythonhosted.org/packages/62/c4/59c7c9b068e6813c898b771204aad36683c96318ed12d4233e1b18762164/sqlalchemy-2.0.44-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72fea91746b5890f9e5e0997f16cbf3d53550580d76355ba2d998311b17b2250", size = 2139675 },
|
| 5199 |
+
{ url = "https://files.pythonhosted.org/packages/d6/ae/eeb0920537a6f9c5a3708e4a5fc55af25900216bdb4847ec29cfddf3bf3a/sqlalchemy-2.0.44-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:585c0c852a891450edbb1eaca8648408a3cc125f18cf433941fa6babcc359e29", size = 2127726 },
|
| 5200 |
+
{ url = "https://files.pythonhosted.org/packages/d8/d5/2ebbabe0379418eda8041c06b0b551f213576bfe4c2f09d77c06c07c8cc5/sqlalchemy-2.0.44-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b94843a102efa9ac68a7a30cd46df3ff1ed9c658100d30a725d10d9c60a2f44", size = 3327603 },
|
| 5201 |
+
{ url = "https://files.pythonhosted.org/packages/45/e5/5aa65852dadc24b7d8ae75b7efb8d19303ed6ac93482e60c44a585930ea5/sqlalchemy-2.0.44-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:119dc41e7a7defcefc57189cfa0e61b1bf9c228211aba432b53fb71ef367fda1", size = 3337842 },
|
| 5202 |
+
{ url = "https://files.pythonhosted.org/packages/41/92/648f1afd3f20b71e880ca797a960f638d39d243e233a7082c93093c22378/sqlalchemy-2.0.44-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0765e318ee9179b3718c4fd7ba35c434f4dd20332fbc6857a5e8df17719c24d7", size = 3264558 },
|
| 5203 |
+
{ url = "https://files.pythonhosted.org/packages/40/cf/e27d7ee61a10f74b17740918e23cbc5bc62011b48282170dc4c66da8ec0f/sqlalchemy-2.0.44-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2e7b5b079055e02d06a4308d0481658e4f06bc7ef211567edc8f7d5dce52018d", size = 3301570 },
|
| 5204 |
+
{ url = "https://files.pythonhosted.org/packages/3b/3d/3116a9a7b63e780fb402799b6da227435be878b6846b192f076d2f838654/sqlalchemy-2.0.44-cp312-cp312-win32.whl", hash = "sha256:846541e58b9a81cce7dee8329f352c318de25aa2f2bbe1e31587eb1f057448b4", size = 2103447 },
|
| 5205 |
+
{ url = "https://files.pythonhosted.org/packages/25/83/24690e9dfc241e6ab062df82cc0df7f4231c79ba98b273fa496fb3dd78ed/sqlalchemy-2.0.44-cp312-cp312-win_amd64.whl", hash = "sha256:7cbcb47fd66ab294703e1644f78971f6f2f1126424d2b300678f419aa73c7b6e", size = 2130912 },
|
| 5206 |
+
{ url = "https://files.pythonhosted.org/packages/45/d3/c67077a2249fdb455246e6853166360054c331db4613cda3e31ab1cadbef/sqlalchemy-2.0.44-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ff486e183d151e51b1d694c7aa1695747599bb00b9f5f604092b54b74c64a8e1", size = 2135479 },
|
| 5207 |
+
{ url = "https://files.pythonhosted.org/packages/2b/91/eabd0688330d6fd114f5f12c4f89b0d02929f525e6bf7ff80aa17ca802af/sqlalchemy-2.0.44-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b1af8392eb27b372ddb783b317dea0f650241cea5bd29199b22235299ca2e45", size = 2123212 },
|
| 5208 |
+
{ url = "https://files.pythonhosted.org/packages/b0/bb/43e246cfe0e81c018076a16036d9b548c4cc649de241fa27d8d9ca6f85ab/sqlalchemy-2.0.44-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b61188657e3a2b9ac4e8f04d6cf8e51046e28175f79464c67f2fd35bceb0976", size = 3255353 },
|
| 5209 |
+
{ url = "https://files.pythonhosted.org/packages/b9/96/c6105ed9a880abe346b64d3b6ddef269ddfcab04f7f3d90a0bf3c5a88e82/sqlalchemy-2.0.44-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b87e7b91a5d5973dda5f00cd61ef72ad75a1db73a386b62877d4875a8840959c", size = 3260222 },
|
| 5210 |
+
{ url = "https://files.pythonhosted.org/packages/44/16/1857e35a47155b5ad927272fee81ae49d398959cb749edca6eaa399b582f/sqlalchemy-2.0.44-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:15f3326f7f0b2bfe406ee562e17f43f36e16167af99c4c0df61db668de20002d", size = 3189614 },
|
| 5211 |
+
{ url = "https://files.pythonhosted.org/packages/88/ee/4afb39a8ee4fc786e2d716c20ab87b5b1fb33d4ac4129a1aaa574ae8a585/sqlalchemy-2.0.44-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e77faf6ff919aa8cd63f1c4e561cac1d9a454a191bb864d5dd5e545935e5a40", size = 3226248 },
|
| 5212 |
+
{ url = "https://files.pythonhosted.org/packages/32/d5/0e66097fc64fa266f29a7963296b40a80d6a997b7ac13806183700676f86/sqlalchemy-2.0.44-cp313-cp313-win32.whl", hash = "sha256:ee51625c2d51f8baadf2829fae817ad0b66b140573939dd69284d2ba3553ae73", size = 2101275 },
|
| 5213 |
+
{ url = "https://files.pythonhosted.org/packages/03/51/665617fe4f8c6450f42a6d8d69243f9420f5677395572c2fe9d21b493b7b/sqlalchemy-2.0.44-cp313-cp313-win_amd64.whl", hash = "sha256:c1c80faaee1a6c3428cecf40d16a2365bcf56c424c92c2b6f0f9ad204b899e9e", size = 2127901 },
|
| 5214 |
+
{ url = "https://files.pythonhosted.org/packages/9c/5e/6a29fa884d9fb7ddadf6b69490a9d45fded3b38541713010dad16b77d015/sqlalchemy-2.0.44-py3-none-any.whl", hash = "sha256:19de7ca1246fbef9f9d1bff8f1ab25641569df226364a0e40457dc5457c54b05", size = 1928718 },
|
| 5215 |
+
]
|
| 5216 |
+
|
| 5217 |
+
[package.optional-dependencies]
|
| 5218 |
+
asyncio = [
|
| 5219 |
+
{ name = "greenlet" },
|
| 5220 |
+
]
|
| 5221 |
+
|
| 5222 |
[[package]]
|
| 5223 |
name = "sse-starlette"
|
| 5224 |
version = "3.0.3"
|
|
|
|
| 5244 |
{ url = "https://files.pythonhosted.org/packages/d9/52/1064f510b141bd54025f9b55105e26d1fa970b9be67ad766380a3c9b74b0/starlette-0.50.0-py3-none-any.whl", hash = "sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca", size = 74033 },
|
| 5245 |
]
|
| 5246 |
|
| 5247 |
+
[[package]]
|
| 5248 |
+
name = "striprtf"
|
| 5249 |
+
version = "0.0.26"
|
| 5250 |
+
source = { registry = "https://pypi.org/simple" }
|
| 5251 |
+
sdist = { url = "https://files.pythonhosted.org/packages/25/20/3d419008265346452d09e5dadfd5d045b64b40d8fc31af40588e6c76997a/striprtf-0.0.26.tar.gz", hash = "sha256:fdb2bba7ac440072d1c41eab50d8d74ae88f60a8b6575c6e2c7805dc462093aa", size = 6258 }
|
| 5252 |
+
wheels = [
|
| 5253 |
+
{ url = "https://files.pythonhosted.org/packages/a3/cf/0fea4f4ba3fc2772ac2419278aa9f6964124d4302117d61bc055758e000c/striprtf-0.0.26-py3-none-any.whl", hash = "sha256:8c8f9d32083cdc2e8bfb149455aa1cc5a4e0a035893bedc75db8b73becb3a1bb", size = 6914 },
|
| 5254 |
+
]
|
| 5255 |
+
|
| 5256 |
[[package]]
|
| 5257 |
name = "structlog"
|
| 5258 |
version = "25.5.0"
|
|
|
|
| 5274 |
{ url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353 },
|
| 5275 |
]
|
| 5276 |
|
| 5277 |
+
[[package]]
|
| 5278 |
+
name = "synchronicity"
|
| 5279 |
+
version = "0.10.4"
|
| 5280 |
+
source = { registry = "https://pypi.org/simple" }
|
| 5281 |
+
dependencies = [
|
| 5282 |
+
{ name = "typing-extensions" },
|
| 5283 |
+
]
|
| 5284 |
+
sdist = { url = "https://files.pythonhosted.org/packages/9e/92/2abaf9f4d846c2b7c240e9ce3c9198abf6660265bc1031640cbca5365351/synchronicity-0.10.4.tar.gz", hash = "sha256:3a9ac19f9a58cad64fcb3729812b828b77e54e0a90ced4439e09d3d9c19a90f0", size = 66903 }
|
| 5285 |
+
wheels = [
|
| 5286 |
+
{ url = "https://files.pythonhosted.org/packages/01/c6/a3631d119c9979816c0ed0354aa9fb829a14f53a43337f263dc3329b3a6e/synchronicity-0.10.4-py3-none-any.whl", hash = "sha256:0e3f00b2123cf2a77a8bb3b65fbeccad04adea682bfbd50c01637b75a168c73b", size = 39652 },
|
| 5287 |
+
]
|
| 5288 |
+
|
| 5289 |
[[package]]
|
| 5290 |
name = "temporalio"
|
| 5291 |
version = "1.19.0"
|
|
|
|
| 5331 |
{ url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638 },
|
| 5332 |
]
|
| 5333 |
|
| 5334 |
+
[[package]]
|
| 5335 |
+
name = "tiktoken"
|
| 5336 |
+
version = "0.12.0"
|
| 5337 |
+
source = { registry = "https://pypi.org/simple" }
|
| 5338 |
+
dependencies = [
|
| 5339 |
+
{ name = "regex" },
|
| 5340 |
+
{ name = "requests" },
|
| 5341 |
+
]
|
| 5342 |
+
sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/4d017d0f76ec3171d469d80fc03dfbb4e48a4bcaddaa831b31d526f05edc/tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931", size = 37806 }
|
| 5343 |
+
wheels = [
|
| 5344 |
+
{ url = "https://files.pythonhosted.org/packages/de/46/21ea696b21f1d6d1efec8639c204bdf20fde8bafb351e1355c72c5d7de52/tiktoken-0.12.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e227c7f96925003487c33b1b32265fad2fbcec2b7cf4817afb76d416f40f6bb", size = 1051565 },
|
| 5345 |
+
{ url = "https://files.pythonhosted.org/packages/c9/d9/35c5d2d9e22bb2a5f74ba48266fb56c63d76ae6f66e02feb628671c0283e/tiktoken-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c06cf0fcc24c2cb2adb5e185c7082a82cba29c17575e828518c2f11a01f445aa", size = 995284 },
|
| 5346 |
+
{ url = "https://files.pythonhosted.org/packages/01/84/961106c37b8e49b9fdcf33fe007bb3a8fdcc380c528b20cc7fbba80578b8/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f18f249b041851954217e9fd8e5c00b024ab2315ffda5ed77665a05fa91f42dc", size = 1129201 },
|
| 5347 |
+
{ url = "https://files.pythonhosted.org/packages/6a/d0/3d9275198e067f8b65076a68894bb52fd253875f3644f0a321a720277b8a/tiktoken-0.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:47a5bc270b8c3db00bb46ece01ef34ad050e364b51d406b6f9730b64ac28eded", size = 1152444 },
|
| 5348 |
+
{ url = "https://files.pythonhosted.org/packages/78/db/a58e09687c1698a7c592e1038e01c206569b86a0377828d51635561f8ebf/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:508fa71810c0efdcd1b898fda574889ee62852989f7c1667414736bcb2b9a4bd", size = 1195080 },
|
| 5349 |
+
{ url = "https://files.pythonhosted.org/packages/9e/1b/a9e4d2bf91d515c0f74afc526fd773a812232dd6cda33ebea7f531202325/tiktoken-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1af81a6c44f008cba48494089dd98cccb8b313f55e961a52f5b222d1e507967", size = 1255240 },
|
| 5350 |
+
{ url = "https://files.pythonhosted.org/packages/9d/15/963819345f1b1fb0809070a79e9dd96938d4ca41297367d471733e79c76c/tiktoken-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e68e3e593637b53e56f7237be560f7a394451cb8c11079755e80ae64b9e6def", size = 879422 },
|
| 5351 |
+
{ url = "https://files.pythonhosted.org/packages/a4/85/be65d39d6b647c79800fd9d29241d081d4eeb06271f383bb87200d74cf76/tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8", size = 1050728 },
|
| 5352 |
+
{ url = "https://files.pythonhosted.org/packages/4a/42/6573e9129bc55c9bf7300b3a35bef2c6b9117018acca0dc760ac2d93dffe/tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b", size = 994049 },
|
| 5353 |
+
{ url = "https://files.pythonhosted.org/packages/66/c5/ed88504d2f4a5fd6856990b230b56d85a777feab84e6129af0822f5d0f70/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37", size = 1129008 },
|
| 5354 |
+
{ url = "https://files.pythonhosted.org/packages/f4/90/3dae6cc5436137ebd38944d396b5849e167896fc2073da643a49f372dc4f/tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad", size = 1152665 },
|
| 5355 |
+
{ url = "https://files.pythonhosted.org/packages/a3/fe/26df24ce53ffde419a42f5f53d755b995c9318908288c17ec3f3448313a3/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5", size = 1194230 },
|
| 5356 |
+
{ url = "https://files.pythonhosted.org/packages/20/cc/b064cae1a0e9fac84b0d2c46b89f4e57051a5f41324e385d10225a984c24/tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3", size = 1254688 },
|
| 5357 |
+
{ url = "https://files.pythonhosted.org/packages/81/10/b8523105c590c5b8349f2587e2fdfe51a69544bd5a76295fc20f2374f470/tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd", size = 878694 },
|
| 5358 |
+
{ url = "https://files.pythonhosted.org/packages/00/61/441588ee21e6b5cdf59d6870f86beb9789e532ee9718c251b391b70c68d6/tiktoken-0.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:775c2c55de2310cc1bc9a3ad8826761cbdc87770e586fd7b6da7d4589e13dab3", size = 1050802 },
|
| 5359 |
+
{ url = "https://files.pythonhosted.org/packages/1f/05/dcf94486d5c5c8d34496abe271ac76c5b785507c8eae71b3708f1ad9b45a/tiktoken-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a01b12f69052fbe4b080a2cfb867c4de12c704b56178edf1d1d7b273561db160", size = 993995 },
|
| 5360 |
+
{ url = "https://files.pythonhosted.org/packages/a0/70/5163fe5359b943f8db9946b62f19be2305de8c3d78a16f629d4165e2f40e/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:01d99484dc93b129cd0964f9d34eee953f2737301f18b3c7257bf368d7615baa", size = 1128948 },
|
| 5361 |
+
{ url = "https://files.pythonhosted.org/packages/0c/da/c028aa0babf77315e1cef357d4d768800c5f8a6de04d0eac0f377cb619fa/tiktoken-0.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4a1a4fcd021f022bfc81904a911d3df0f6543b9e7627b51411da75ff2fe7a1be", size = 1151986 },
|
| 5362 |
+
{ url = "https://files.pythonhosted.org/packages/a0/5a/886b108b766aa53e295f7216b509be95eb7d60b166049ce2c58416b25f2a/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:981a81e39812d57031efdc9ec59fa32b2a5a5524d20d4776574c4b4bd2e9014a", size = 1194222 },
|
| 5363 |
+
{ url = "https://files.pythonhosted.org/packages/f4/f8/4db272048397636ac7a078d22773dd2795b1becee7bc4922fe6207288d57/tiktoken-0.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9baf52f84a3f42eef3ff4e754a0db79a13a27921b457ca9832cf944c6be4f8f3", size = 1255097 },
|
| 5364 |
+
{ url = "https://files.pythonhosted.org/packages/8e/32/45d02e2e0ea2be3a9ed22afc47d93741247e75018aac967b713b2941f8ea/tiktoken-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b8a0cd0c789a61f31bf44851defbd609e8dd1e2c8589c614cc1060940ef1f697", size = 879117 },
|
| 5365 |
+
{ url = "https://files.pythonhosted.org/packages/ce/76/994fc868f88e016e6d05b0da5ac24582a14c47893f4474c3e9744283f1d5/tiktoken-0.12.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d5f89ea5680066b68bcb797ae85219c72916c922ef0fcdd3480c7d2315ffff16", size = 1050309 },
|
| 5366 |
+
{ url = "https://files.pythonhosted.org/packages/f6/b8/57ef1456504c43a849821920d582a738a461b76a047f352f18c0b26c6516/tiktoken-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b4e7ed1c6a7a8a60a3230965bdedba8cc58f68926b835e519341413370e0399a", size = 993712 },
|
| 5367 |
+
{ url = "https://files.pythonhosted.org/packages/72/90/13da56f664286ffbae9dbcfadcc625439142675845baa62715e49b87b68b/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:fc530a28591a2d74bce821d10b418b26a094bf33839e69042a6e86ddb7a7fb27", size = 1128725 },
|
| 5368 |
+
{ url = "https://files.pythonhosted.org/packages/05/df/4f80030d44682235bdaecd7346c90f67ae87ec8f3df4a3442cb53834f7e4/tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:06a9f4f49884139013b138920a4c393aa6556b2f8f536345f11819389c703ebb", size = 1151875 },
|
| 5369 |
+
{ url = "https://files.pythonhosted.org/packages/22/1f/ae535223a8c4ef4c0c1192e3f9b82da660be9eb66b9279e95c99288e9dab/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:04f0e6a985d95913cabc96a741c5ffec525a2c72e9df086ff17ebe35985c800e", size = 1194451 },
|
| 5370 |
+
{ url = "https://files.pythonhosted.org/packages/78/a7/f8ead382fce0243cb625c4f266e66c27f65ae65ee9e77f59ea1653b6d730/tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ee8f9ae00c41770b5f9b0bb1235474768884ae157de3beb5439ca0fd70f3e25", size = 1253794 },
|
| 5371 |
+
{ url = "https://files.pythonhosted.org/packages/93/e0/6cc82a562bc6365785a3ff0af27a2a092d57c47d7a81d9e2295d8c36f011/tiktoken-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc2dd125a62cb2b3d858484d6c614d136b5b848976794edfb63688d539b8b93f", size = 878777 },
|
| 5372 |
+
{ url = "https://files.pythonhosted.org/packages/72/05/3abc1db5d2c9aadc4d2c76fa5640134e475e58d9fbb82b5c535dc0de9b01/tiktoken-0.12.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a90388128df3b3abeb2bfd1895b0681412a8d7dc644142519e6f0a97c2111646", size = 1050188 },
|
| 5373 |
+
{ url = "https://files.pythonhosted.org/packages/e3/7b/50c2f060412202d6c95f32b20755c7a6273543b125c0985d6fa9465105af/tiktoken-0.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:da900aa0ad52247d8794e307d6446bd3cdea8e192769b56276695d34d2c9aa88", size = 993978 },
|
| 5374 |
+
{ url = "https://files.pythonhosted.org/packages/14/27/bf795595a2b897e271771cd31cb847d479073497344c637966bdf2853da1/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:285ba9d73ea0d6171e7f9407039a290ca77efcdb026be7769dccc01d2c8d7fff", size = 1129271 },
|
| 5375 |
+
{ url = "https://files.pythonhosted.org/packages/f5/de/9341a6d7a8f1b448573bbf3425fa57669ac58258a667eb48a25dfe916d70/tiktoken-0.12.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:d186a5c60c6a0213f04a7a802264083dea1bbde92a2d4c7069e1a56630aef830", size = 1151216 },
|
| 5376 |
+
{ url = "https://files.pythonhosted.org/packages/75/0d/881866647b8d1be4d67cb24e50d0c26f9f807f994aa1510cb9ba2fe5f612/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:604831189bd05480f2b885ecd2d1986dc7686f609de48208ebbbddeea071fc0b", size = 1194860 },
|
| 5377 |
+
{ url = "https://files.pythonhosted.org/packages/b3/1e/b651ec3059474dab649b8d5b69f5c65cd8fcd8918568c1935bd4136c9392/tiktoken-0.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8f317e8530bb3a222547b85a58583238c8f74fd7a7408305f9f63246d1a0958b", size = 1254567 },
|
| 5378 |
+
{ url = "https://files.pythonhosted.org/packages/80/57/ce64fd16ac390fafde001268c364d559447ba09b509181b2808622420eec/tiktoken-0.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:399c3dd672a6406719d84442299a490420b458c44d3ae65516302a99675888f3", size = 921067 },
|
| 5379 |
+
{ url = "https://files.pythonhosted.org/packages/ac/a4/72eed53e8976a099539cdd5eb36f241987212c29629d0a52c305173e0a68/tiktoken-0.12.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2c714c72bc00a38ca969dae79e8266ddec999c7ceccd603cc4f0d04ccd76365", size = 1050473 },
|
| 5380 |
+
{ url = "https://files.pythonhosted.org/packages/e6/d7/0110b8f54c008466b19672c615f2168896b83706a6611ba6e47313dbc6e9/tiktoken-0.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cbb9a3ba275165a2cb0f9a83f5d7025afe6b9d0ab01a22b50f0e74fee2ad253e", size = 993855 },
|
| 5381 |
+
{ url = "https://files.pythonhosted.org/packages/5f/77/4f268c41a3957c418b084dd576ea2fad2e95da0d8e1ab705372892c2ca22/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:dfdfaa5ffff8993a3af94d1125870b1d27aed7cb97aa7eb8c1cefdbc87dbee63", size = 1129022 },
|
| 5382 |
+
{ url = "https://files.pythonhosted.org/packages/4e/2b/fc46c90fe5028bd094cd6ee25a7db321cb91d45dc87531e2bdbb26b4867a/tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:584c3ad3d0c74f5269906eb8a659c8bfc6144a52895d9261cdaf90a0ae5f4de0", size = 1150736 },
|
| 5383 |
+
{ url = "https://files.pythonhosted.org/packages/28/c0/3c7a39ff68022ddfd7d93f3337ad90389a342f761c4d71de99a3ccc57857/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54c891b416a0e36b8e2045b12b33dd66fb34a4fe7965565f1b482da50da3e86a", size = 1194908 },
|
| 5384 |
+
{ url = "https://files.pythonhosted.org/packages/ab/0d/c1ad6f4016a3968c048545f5d9b8ffebf577774b2ede3e2e352553b685fe/tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5edb8743b88d5be814b1a8a8854494719080c28faaa1ccbef02e87354fe71ef0", size = 1253706 },
|
| 5385 |
+
{ url = "https://files.pythonhosted.org/packages/af/df/c7891ef9d2712ad774777271d39fdef63941ffba0a9d59b7ad1fd2765e57/tiktoken-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f61c0aea5565ac82e2ec50a05e02a6c44734e91b51c10510b084ea1b8e633a71", size = 920667 },
|
| 5386 |
+
]
|
| 5387 |
+
|
| 5388 |
[[package]]
|
| 5389 |
name = "tokenizers"
|
| 5390 |
version = "0.22.1"
|
|
|
|
| 5410 |
{ url = "https://files.pythonhosted.org/packages/b3/46/e33a8c93907b631a99377ef4c5f817ab453d0b34f93529421f42ff559671/tokenizers-0.22.1-cp39-abi3-win_amd64.whl", hash = "sha256:65fd6e3fb11ca1e78a6a93602490f134d1fdeb13bcef99389d5102ea318ed138", size = 2674684 },
|
| 5411 |
]
|
| 5412 |
|
| 5413 |
+
[[package]]
|
| 5414 |
+
name = "toml"
|
| 5415 |
+
version = "0.10.2"
|
| 5416 |
+
source = { registry = "https://pypi.org/simple" }
|
| 5417 |
+
sdist = { url = "https://files.pythonhosted.org/packages/be/ba/1f744cdc819428fc6b5084ec34d9b30660f6f9daaf70eead706e3203ec3c/toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f", size = 22253 }
|
| 5418 |
+
wheels = [
|
| 5419 |
+
{ url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588 },
|
| 5420 |
+
]
|
| 5421 |
+
|
| 5422 |
[[package]]
|
| 5423 |
name = "tomli"
|
| 5424 |
version = "2.3.0"
|
|
|
|
| 5594 |
{ url = "https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl", hash = "sha256:5b463df6793ec1dca6213a3cf4c0f03bc6e322ac5e16e13ddd622a889489784a", size = 47028 },
|
| 5595 |
]
|
| 5596 |
|
| 5597 |
+
[[package]]
|
| 5598 |
+
name = "types-certifi"
|
| 5599 |
+
version = "2021.10.8.3"
|
| 5600 |
+
source = { registry = "https://pypi.org/simple" }
|
| 5601 |
+
sdist = { url = "https://files.pythonhosted.org/packages/52/68/943c3aeaf14624712a0357c4a67814dba5cea36d194f5c764dad7959a00c/types-certifi-2021.10.8.3.tar.gz", hash = "sha256:72cf7798d165bc0b76e1c10dd1ea3097c7063c42c21d664523b928e88b554a4f", size = 2095 }
|
| 5602 |
+
wheels = [
|
| 5603 |
+
{ url = "https://files.pythonhosted.org/packages/b5/63/2463d89481e811f007b0e1cd0a91e52e141b47f9de724d20db7b861dcfec/types_certifi-2021.10.8.3-py3-none-any.whl", hash = "sha256:b2d1e325e69f71f7c78e5943d410e650b4707bb0ef32e4ddf3da37f54176e88a", size = 2136 },
|
| 5604 |
+
]
|
| 5605 |
+
|
| 5606 |
[[package]]
|
| 5607 |
name = "types-protobuf"
|
| 5608 |
version = "6.32.1.20251105"
|
|
|
|
| 5624 |
{ url = "https://files.pythonhosted.org/packages/2a/20/9a227ea57c1285986c4cf78400d0a91615d25b24e257fd9e2969606bdfae/types_requests-2.32.4.20250913-py3-none-any.whl", hash = "sha256:78c9c1fffebbe0fa487a418e0fa5252017e9c60d1a2da394077f1780f655d7e1", size = 20658 },
|
| 5625 |
]
|
| 5626 |
|
| 5627 |
+
[[package]]
|
| 5628 |
+
name = "types-toml"
|
| 5629 |
+
version = "0.10.8.20240310"
|
| 5630 |
+
source = { registry = "https://pypi.org/simple" }
|
| 5631 |
+
sdist = { url = "https://files.pythonhosted.org/packages/86/47/3e4c75042792bff8e90d7991aa5c51812cc668828cc6cce711e97f63a607/types-toml-0.10.8.20240310.tar.gz", hash = "sha256:3d41501302972436a6b8b239c850b26689657e25281b48ff0ec06345b8830331", size = 4392 }
|
| 5632 |
+
wheels = [
|
| 5633 |
+
{ url = "https://files.pythonhosted.org/packages/da/a2/d32ab58c0b216912638b140ab2170ee4b8644067c293b170e19fba340ccc/types_toml-0.10.8.20240310-py3-none-any.whl", hash = "sha256:627b47775d25fa29977d9c70dc0cbab3f314f32c8d8d0c012f2ef5de7aaec05d", size = 4777 },
|
| 5634 |
+
]
|
| 5635 |
+
|
| 5636 |
[[package]]
|
| 5637 |
name = "typing-extensions"
|
| 5638 |
version = "4.15.0"
|
|
|
|
| 5642 |
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614 },
|
| 5643 |
]
|
| 5644 |
|
| 5645 |
+
[[package]]
|
| 5646 |
+
name = "typing-inspect"
|
| 5647 |
+
version = "0.9.0"
|
| 5648 |
+
source = { registry = "https://pypi.org/simple" }
|
| 5649 |
+
dependencies = [
|
| 5650 |
+
{ name = "mypy-extensions" },
|
| 5651 |
+
{ name = "typing-extensions" },
|
| 5652 |
+
]
|
| 5653 |
+
sdist = { url = "https://files.pythonhosted.org/packages/dc/74/1789779d91f1961fa9438e9a8710cdae6bd138c80d7303996933d117264a/typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78", size = 13825 }
|
| 5654 |
+
wheels = [
|
| 5655 |
+
{ url = "https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f", size = 8827 },
|
| 5656 |
+
]
|
| 5657 |
+
|
| 5658 |
[[package]]
|
| 5659 |
name = "typing-inspection"
|
| 5660 |
version = "0.4.2"
|