coregrai 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coregrai-2.0.0.dist-info/METADATA +455 -0
- coregrai-2.0.0.dist-info/RECORD +12 -0
- coregrai-2.0.0.dist-info/WHEEL +5 -0
- coregrai-2.0.0.dist-info/entry_points.txt +2 -0
- coregrai-2.0.0.dist-info/licenses/LICENSE +21 -0
- coregrai-2.0.0.dist-info/top_level.txt +1 -0
- grai_cli/__init__.py +54 -0
- grai_cli/__main__.py +11 -0
- grai_cli/auth.py +93 -0
- grai_cli/cli.py +583 -0
- grai_cli/client.py +259 -0
- grai_cli/config.py +67 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: coregrai
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: AI-powered study assistant for the ACR Core Exam and diagnostic radiology
|
|
5
|
+
Home-page: https://coregrai.com
|
|
6
|
+
Author: GRAi Team
|
|
7
|
+
Author-email: GRAi Team <support@coregrai.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Project-URL: Homepage, https://coregrai.com
|
|
10
|
+
Project-URL: Documentation, https://docs.coregrai.com
|
|
11
|
+
Project-URL: Repository, https://github.com/coregrai/grai-cli
|
|
12
|
+
Project-URL: Changelog, https://github.com/coregrai/grai-cli/blob/main/CHANGELOG.md
|
|
13
|
+
Project-URL: Issues, https://github.com/coregrai/grai-cli/issues
|
|
14
|
+
Keywords: radiology,medical,education,ACR,exam,study,AI,differential-diagnosis
|
|
15
|
+
Classifier: Development Status :: 4 - Beta
|
|
16
|
+
Classifier: Environment :: Console
|
|
17
|
+
Classifier: Intended Audience :: Healthcare Industry
|
|
18
|
+
Classifier: Intended Audience :: Education
|
|
19
|
+
Classifier: Topic :: Education
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
27
|
+
Classifier: Operating System :: OS Independent
|
|
28
|
+
Requires-Python: >=3.8
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: click>=8.0.0
|
|
32
|
+
Requires-Dist: requests>=2.28.0
|
|
33
|
+
Requires-Dist: rich>=13.0.0
|
|
34
|
+
Provides-Extra: secure
|
|
35
|
+
Requires-Dist: keyring>=23.0.0; extra == "secure"
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
39
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
40
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
41
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
42
|
+
Requires-Dist: build>=1.0.0; extra == "dev"
|
|
43
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
44
|
+
Dynamic: author
|
|
45
|
+
Dynamic: home-page
|
|
46
|
+
Dynamic: license-file
|
|
47
|
+
Dynamic: requires-python
|
|
48
|
+
|
|
49
|
+
# GRAi CLI
|
|
50
|
+
|
|
51
|
+
> AI-powered study assistant for the ACR Core Exam and diagnostic radiology
|
|
52
|
+
|
|
53
|
+
[](https://badge.fury.io/py/grai-cli)
|
|
54
|
+
[](https://pypi.org/project/grai-cli/)
|
|
55
|
+
[](https://opensource.org/licenses/MIT)
|
|
56
|
+
|
|
57
|
+
## Overview
|
|
58
|
+
|
|
59
|
+
GRAi CLI brings the power of AI-assisted radiology education to your terminal. Study for the ACR Core Exam with interactive chat, practice quizzes, and comprehensive lessons - all from the command line.
|
|
60
|
+
|
|
61
|
+
### Features
|
|
62
|
+
|
|
63
|
+
- **Interactive Chat**: Ask questions about any radiology topic and get AI-powered explanations
|
|
64
|
+
- **Practice Quizzes**: Board-style questions with adaptive difficulty
|
|
65
|
+
- **Comprehensive Lessons**: 572+ pre-generated lessons covering all ACR topics
|
|
66
|
+
- **Progress Tracking**: Monitor your study statistics and performance
|
|
67
|
+
- **Offline Export**: Save lessons to markdown files for offline study
|
|
68
|
+
- **Beautiful Terminal UI**: Rich, colorful interface with syntax highlighting
|
|
69
|
+
|
|
70
|
+
## Installation
|
|
71
|
+
|
|
72
|
+
### From PyPI (Recommended)
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install grai-cli
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### From Source
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
git clone https://github.com/yourusername/grai-cli.git
|
|
82
|
+
cd grai-cli
|
|
83
|
+
pip install -e .
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Requirements
|
|
87
|
+
|
|
88
|
+
- Python 3.8 or higher
|
|
89
|
+
- Active internet connection (for API access)
|
|
90
|
+
- GRAi account (free registration at https://coregrai.com)
|
|
91
|
+
|
|
92
|
+
## Quick Start
|
|
93
|
+
|
|
94
|
+
### 1. Login
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
grai login
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
You'll be prompted for your email and password. Don't have an account? Register at https://coregrai.com
|
|
101
|
+
|
|
102
|
+
### 2. Ask Questions
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Single question
|
|
106
|
+
grai chat "What are the CT findings in pulmonary embolism?"
|
|
107
|
+
|
|
108
|
+
# Interactive chat session
|
|
109
|
+
grai chat -i
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 3. Take a Quiz
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Random quiz (5 questions)
|
|
116
|
+
grai quiz
|
|
117
|
+
|
|
118
|
+
# Topic-specific quiz
|
|
119
|
+
grai quiz --topic chest-ct --count 10
|
|
120
|
+
|
|
121
|
+
# Adaptive difficulty based on your performance
|
|
122
|
+
grai quiz --adaptive
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 4. Study Lessons
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# List all available lessons
|
|
129
|
+
grai lesson --list
|
|
130
|
+
|
|
131
|
+
# Search for lessons
|
|
132
|
+
grai lesson --search "cardiac"
|
|
133
|
+
|
|
134
|
+
# Read a specific lesson
|
|
135
|
+
grai lesson chest-radiography-basics
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 5. Check Your Progress
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
grai stats
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Usage Guide
|
|
145
|
+
|
|
146
|
+
### Chat Commands
|
|
147
|
+
|
|
148
|
+
**Single Query:**
|
|
149
|
+
```bash
|
|
150
|
+
grai chat "Explain MRI sequences"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Interactive Mode:**
|
|
154
|
+
```bash
|
|
155
|
+
grai chat -i
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**With Sources:**
|
|
159
|
+
```bash
|
|
160
|
+
grai chat --sources "What is the ACR TI-RADS classification?"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Specify Model:**
|
|
164
|
+
```bash
|
|
165
|
+
grai chat --model gemini "Describe CT protocols"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Quiz Commands
|
|
169
|
+
|
|
170
|
+
**Basic Quiz:**
|
|
171
|
+
```bash
|
|
172
|
+
grai quiz
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Topic-Specific:**
|
|
176
|
+
```bash
|
|
177
|
+
# Available topics: chest-xray, chest-ct, neuro-ct, neuro-mri,
|
|
178
|
+
# abdominal-ct, abdominal-mri, msk, nuclear-medicine, ultrasound, etc.
|
|
179
|
+
grai quiz --topic neuro-mri
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Set Difficulty:**
|
|
183
|
+
```bash
|
|
184
|
+
grai quiz --difficulty hard --count 10
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Adaptive Mode:**
|
|
188
|
+
```bash
|
|
189
|
+
# Questions adjust based on your performance
|
|
190
|
+
grai quiz --adaptive
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Lesson Commands
|
|
194
|
+
|
|
195
|
+
**List Lessons:**
|
|
196
|
+
```bash
|
|
197
|
+
grai lesson --list
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Search Lessons:**
|
|
201
|
+
```bash
|
|
202
|
+
grai lesson --search "mri"
|
|
203
|
+
grai lesson --search "cardiac" --category cardiothoracic
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Read a Lesson:**
|
|
207
|
+
```bash
|
|
208
|
+
grai lesson chest-radiography-basics
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Export Lesson:**
|
|
212
|
+
```bash
|
|
213
|
+
grai export chest-radiography-basics --output ~/study/chest.md
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Configuration
|
|
217
|
+
|
|
218
|
+
**Show Current Config:**
|
|
219
|
+
```bash
|
|
220
|
+
grai config --show
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Change Server URL:**
|
|
224
|
+
```bash
|
|
225
|
+
grai config --server https://your-server.com
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**View Statistics:**
|
|
229
|
+
```bash
|
|
230
|
+
grai stats
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Logout:**
|
|
234
|
+
```bash
|
|
235
|
+
grai logout
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Advanced Usage
|
|
239
|
+
|
|
240
|
+
### Custom Server
|
|
241
|
+
|
|
242
|
+
If you're running your own GRAi instance:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
grai config --server http://localhost:5000
|
|
246
|
+
grai login
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Batch Operations
|
|
250
|
+
|
|
251
|
+
Study multiple topics in sequence:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
# Create a study script
|
|
255
|
+
#!/bin/bash
|
|
256
|
+
grai quiz --topic chest-ct --count 5
|
|
257
|
+
grai quiz --topic chest-xray --count 5
|
|
258
|
+
grai quiz --topic neuro-ct --count 5
|
|
259
|
+
grai stats
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Export Study Materials
|
|
263
|
+
|
|
264
|
+
Export all cardiothoracic lessons:
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
#!/bin/bash
|
|
268
|
+
for lesson in $(grai lesson --list --category cardiothoracic | grep -oP '^\S+'); do
|
|
269
|
+
grai export "$lesson" --output "study/${lesson}.md"
|
|
270
|
+
done
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Configuration File
|
|
274
|
+
|
|
275
|
+
GRAi CLI stores configuration in `~/.grai/config.json`:
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"server_url": "https://coregrai.com",
|
|
280
|
+
"default_model": "deepseek",
|
|
281
|
+
"show_sources": false,
|
|
282
|
+
"color_output": true,
|
|
283
|
+
"auth_token": "<your-token>",
|
|
284
|
+
"user_email": "your@email.com"
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Features in Detail
|
|
289
|
+
|
|
290
|
+
### Interactive Chat
|
|
291
|
+
|
|
292
|
+
The interactive chat mode provides a conversational interface:
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
> You: What causes pneumothorax on chest x-ray?
|
|
296
|
+
|
|
297
|
+
GRAi: Pneumothorax appears on chest radiographs as...
|
|
298
|
+
[detailed explanation with key findings]
|
|
299
|
+
|
|
300
|
+
Sources:
|
|
301
|
+
1. Chest Radiography Fundamentals
|
|
302
|
+
2. Emergency Radiology - Pneumothorax
|
|
303
|
+
3. ACR Appropriateness Criteria
|
|
304
|
+
|
|
305
|
+
> You: How do you measure it?
|
|
306
|
+
...
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Practice Quizzes
|
|
310
|
+
|
|
311
|
+
Board-style questions with immediate feedback:
|
|
312
|
+
|
|
313
|
+
```
|
|
314
|
+
Question 1/10:
|
|
315
|
+
A 45-year-old male presents with chest pain...
|
|
316
|
+
Which finding is most concerning?
|
|
317
|
+
|
|
318
|
+
1. Cardiomegaly
|
|
319
|
+
2. Pleural effusion
|
|
320
|
+
3. Pneumomediastinum
|
|
321
|
+
4. Atelectasis
|
|
322
|
+
|
|
323
|
+
Your answer: 3
|
|
324
|
+
|
|
325
|
+
Correct! Pneumomediastinum in the setting of chest pain
|
|
326
|
+
may indicate esophageal perforation, which requires urgent
|
|
327
|
+
evaluation.
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Progress Tracking
|
|
331
|
+
|
|
332
|
+
Monitor your improvement:
|
|
333
|
+
|
|
334
|
+
```
|
|
335
|
+
Your Study Statistics
|
|
336
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
337
|
+
Questions Answered 847
|
|
338
|
+
Lessons Completed 42
|
|
339
|
+
Study Streak 14 days
|
|
340
|
+
Average Score 84.5%
|
|
341
|
+
Total Study Time 23h 15m
|
|
342
|
+
|
|
343
|
+
Areas to Focus On:
|
|
344
|
+
- Nuclear Medicine Physics
|
|
345
|
+
- Interventional Radiology
|
|
346
|
+
- Ultrasound Artifacts
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Troubleshooting
|
|
350
|
+
|
|
351
|
+
### Connection Issues
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
# Check server connectivity
|
|
355
|
+
curl https://coregrai.com/api/health
|
|
356
|
+
|
|
357
|
+
# Try alternative server
|
|
358
|
+
grai config --server https://backup.coregrai.com
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Authentication Problems
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
# Re-login
|
|
365
|
+
grai logout
|
|
366
|
+
grai login
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Clear Configuration
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
# Remove config file
|
|
373
|
+
rm ~/.grai/config.json
|
|
374
|
+
|
|
375
|
+
# Login again
|
|
376
|
+
grai login
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Development
|
|
380
|
+
|
|
381
|
+
### Setup Development Environment
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
git clone https://github.com/yourusername/grai-cli.git
|
|
385
|
+
cd grai-cli
|
|
386
|
+
python -m venv venv
|
|
387
|
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
388
|
+
pip install -r requirements-dev.txt
|
|
389
|
+
pip install -e .
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Run Tests
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
pytest
|
|
396
|
+
pytest --cov=grai_cli
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Code Formatting
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
black grai_cli/
|
|
403
|
+
flake8 grai_cli/
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Build Package
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
python -m build
|
|
410
|
+
twine check dist/*
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Publish to PyPI
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
# Test PyPI
|
|
417
|
+
twine upload --repository testpypi dist/*
|
|
418
|
+
|
|
419
|
+
# Production PyPI
|
|
420
|
+
twine upload dist/*
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
## Contributing
|
|
424
|
+
|
|
425
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
426
|
+
|
|
427
|
+
1. Fork the repository
|
|
428
|
+
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
|
|
429
|
+
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
|
|
430
|
+
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
|
431
|
+
5. Open a Pull Request
|
|
432
|
+
|
|
433
|
+
## License
|
|
434
|
+
|
|
435
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
436
|
+
|
|
437
|
+
## Support
|
|
438
|
+
|
|
439
|
+
- **Documentation**: https://docs.coregrai.com
|
|
440
|
+
- **Issues**: https://github.com/yourusername/grai-cli/issues
|
|
441
|
+
- **Email**: support@coregrai.com
|
|
442
|
+
|
|
443
|
+
## Changelog
|
|
444
|
+
|
|
445
|
+
See [CHANGELOG.md](CHANGELOG.md) for a list of changes.
|
|
446
|
+
|
|
447
|
+
## Acknowledgments
|
|
448
|
+
|
|
449
|
+
- Built with [Click](https://click.palletsprojects.com/)
|
|
450
|
+
- Beautiful terminal output powered by [Rich](https://rich.readthedocs.io/)
|
|
451
|
+
- ACR content based on official ACR guidelines and appropriateness criteria
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
**Made with ❤️ for radiology residents everywhere**
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
coregrai-2.0.0.dist-info/licenses/LICENSE,sha256=nDSoZ7aXIrx2Ei9YgwtmYPy3u0UvaPYO7_L-yfPNECY,1087
|
|
2
|
+
grai_cli/__init__.py,sha256=S9QJvY87bXYFTSLxPQRkYSJ740cHUxiZp6HxP3Q8LrI,1529
|
|
3
|
+
grai_cli/__main__.py,sha256=7sbobcqXuIuhPRY_ye1vzg6Jk_P4fvI0gOODs7ENklo,174
|
|
4
|
+
grai_cli/auth.py,sha256=HzsTSARz9QD_hg4iQzLLN79jsf7cN1O_MV20FfLB0N0,2391
|
|
5
|
+
grai_cli/cli.py,sha256=MVB89rqztxrB-dT1TBtDzKzdH5CJbLT8jrNJAGyKNeM,20881
|
|
6
|
+
grai_cli/client.py,sha256=-ko18X8eGgLR0JZz6vr0k-DOclbkU2RYBEDGw2V_hQI,7902
|
|
7
|
+
grai_cli/config.py,sha256=UkQOJOVumvsLWFcYAp3N8_p09p-UBF514-TV3lyCUII,2023
|
|
8
|
+
coregrai-2.0.0.dist-info/METADATA,sha256=YK17PIAgYgV6lE02dYIwmQGXFmfgqIKyBP8xtgiiDzY,9977
|
|
9
|
+
coregrai-2.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
10
|
+
coregrai-2.0.0.dist-info/entry_points.txt,sha256=bdyTzcZdwIyAL_CGrJR4qujOE0p-w_AUmka4WwyT_L4,43
|
|
11
|
+
coregrai-2.0.0.dist-info/top_level.txt,sha256=JfIomgA4AYIJ1Uz5xwvrre6ERYONhbeGxt74gqAdf8M,9
|
|
12
|
+
coregrai-2.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 GRAi Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
grai_cli
|
grai_cli/__init__.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GRAi CLI - Command-line interface for Diagnostic Radiology AI Assistant
|
|
3
|
+
|
|
4
|
+
A powerful command-line tool for radiology residents preparing for the ACR Core Exam.
|
|
5
|
+
Features include AI-powered chat, practice quizzes, comprehensive lessons, and
|
|
6
|
+
differential diagnosis generation.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__version__ = "2.0.0"
|
|
10
|
+
__author__ = "GRAi Team"
|
|
11
|
+
__email__ = "support@coregrai.com"
|
|
12
|
+
__description__ = "AI-powered study assistant for the ACR Core Exam and diagnostic radiology"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def __getattr__(name):
|
|
16
|
+
"""Lazy import for public API."""
|
|
17
|
+
if name == "main":
|
|
18
|
+
from .cli import main
|
|
19
|
+
return main
|
|
20
|
+
elif name == "cli":
|
|
21
|
+
from .cli import cli
|
|
22
|
+
return cli
|
|
23
|
+
elif name == "GraiClient":
|
|
24
|
+
from .client import GraiClient
|
|
25
|
+
return GraiClient
|
|
26
|
+
elif name == "Config":
|
|
27
|
+
from .config import Config
|
|
28
|
+
return Config
|
|
29
|
+
elif name == "authenticate":
|
|
30
|
+
from .auth import authenticate
|
|
31
|
+
return authenticate
|
|
32
|
+
elif name == "logout":
|
|
33
|
+
from .auth import logout
|
|
34
|
+
return logout
|
|
35
|
+
elif name == "check_auth":
|
|
36
|
+
from .auth import check_auth
|
|
37
|
+
return check_auth
|
|
38
|
+
elif name == "get_current_user":
|
|
39
|
+
from .auth import get_current_user
|
|
40
|
+
return get_current_user
|
|
41
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
__all__ = [
|
|
45
|
+
"main",
|
|
46
|
+
"cli",
|
|
47
|
+
"GraiClient",
|
|
48
|
+
"Config",
|
|
49
|
+
"authenticate",
|
|
50
|
+
"logout",
|
|
51
|
+
"check_auth",
|
|
52
|
+
"get_current_user",
|
|
53
|
+
"__version__",
|
|
54
|
+
]
|
grai_cli/__main__.py
ADDED
grai_cli/auth.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Authentication handling for GRAi CLI
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
from typing import Tuple
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def authenticate(config, email: str, password: str) -> Tuple[bool, str]:
|
|
10
|
+
"""
|
|
11
|
+
Authenticate user with email and password
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
config: Configuration object
|
|
15
|
+
email: User email
|
|
16
|
+
password: User password
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
Tuple of (success, message)
|
|
20
|
+
"""
|
|
21
|
+
server_url = config.get('server_url', 'https://coregrai.com')
|
|
22
|
+
url = f"{server_url}/api/auth/login"
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
response = requests.post(url, json={
|
|
26
|
+
'email': email,
|
|
27
|
+
'password': password
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
if response.status_code == 200:
|
|
31
|
+
data = response.json()
|
|
32
|
+
if data.get('success'):
|
|
33
|
+
token = data.get('token')
|
|
34
|
+
user = data.get('user', {})
|
|
35
|
+
|
|
36
|
+
# Save credentials
|
|
37
|
+
config.set('auth_token', token)
|
|
38
|
+
config.set('user_email', user.get('email'))
|
|
39
|
+
config.set('user_name', user.get('username'))
|
|
40
|
+
|
|
41
|
+
return True, "Login successful"
|
|
42
|
+
|
|
43
|
+
# Login failed
|
|
44
|
+
error_data = response.json() if response.headers.get('content-type', '').startswith('application/json') else {}
|
|
45
|
+
error_msg = error_data.get('error', 'Invalid credentials')
|
|
46
|
+
return False, error_msg
|
|
47
|
+
|
|
48
|
+
except requests.exceptions.ConnectionError:
|
|
49
|
+
return False, "Could not connect to server"
|
|
50
|
+
except Exception as e:
|
|
51
|
+
return False, f"Authentication error: {str(e)}"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def logout(config) -> None:
|
|
55
|
+
"""
|
|
56
|
+
Log out user by clearing credentials
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
config: Configuration object
|
|
60
|
+
"""
|
|
61
|
+
config.delete('auth_token')
|
|
62
|
+
config.delete('user_email')
|
|
63
|
+
config.delete('user_name')
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def check_auth(config) -> bool:
|
|
67
|
+
"""
|
|
68
|
+
Check if user is authenticated
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
config: Configuration object
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
True if authenticated, False otherwise
|
|
75
|
+
"""
|
|
76
|
+
return config.get('auth_token') is not None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def get_current_user(config) -> dict:
|
|
80
|
+
"""
|
|
81
|
+
Get current authenticated user info
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
config: Configuration object
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
User info dictionary
|
|
88
|
+
"""
|
|
89
|
+
return {
|
|
90
|
+
'email': config.get('user_email'),
|
|
91
|
+
'name': config.get('user_name'),
|
|
92
|
+
'token': config.get('auth_token')
|
|
93
|
+
}
|