firme-tutor 0.2.0__tar.gz
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.
- firme_tutor-0.2.0/PKG-INFO +15 -0
- firme_tutor-0.2.0/README.md +184 -0
- firme_tutor-0.2.0/__init__.py +46 -0
- firme_tutor-0.2.0/__main__.py +8 -0
- firme_tutor-0.2.0/curriculum.py +5623 -0
- firme_tutor-0.2.0/db/__init__.py +16 -0
- firme_tutor-0.2.0/db/engine.py +42 -0
- firme_tutor-0.2.0/db/models.py +160 -0
- firme_tutor-0.2.0/firme_logo_purple.png +0 -0
- firme_tutor-0.2.0/firme_tutor.egg-info/PKG-INFO +15 -0
- firme_tutor-0.2.0/firme_tutor.egg-info/SOURCES.txt +301 -0
- firme_tutor-0.2.0/firme_tutor.egg-info/dependency_links.txt +1 -0
- firme_tutor-0.2.0/firme_tutor.egg-info/requires.txt +11 -0
- firme_tutor-0.2.0/firme_tutor.egg-info/top_level.txt +1 -0
- firme_tutor-0.2.0/multimodal/__init__.py +0 -0
- firme_tutor-0.2.0/multimodal/modes.py +66 -0
- firme_tutor-0.2.0/prompts.py +183 -0
- firme_tutor-0.2.0/pyproject.toml +32 -0
- firme_tutor-0.2.0/setup.cfg +4 -0
- firme_tutor-0.2.0/tutor.py +137 -0
- firme_tutor-0.2.0/typing_game/__init__.py +0 -0
- firme_tutor-0.2.0/typing_game/keyboard.py +77 -0
- firme_tutor-0.2.0/typing_game/scoring.py +22 -0
- firme_tutor-0.2.0/typing_game/sentences.py +229 -0
- firme_tutor-0.2.0/web/__init__.py +22 -0
- firme_tutor-0.2.0/web/app.py +60 -0
- firme_tutor-0.2.0/web/config.py +38 -0
- firme_tutor-0.2.0/web/dependencies.py +59 -0
- firme_tutor-0.2.0/web/dist/assets/arc-B8bv5B3N.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/arc-hcHIXwUj.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/architecture-7EHR7CIX-CfWJRDbS.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/architecture-7EHR7CIX-D7wqdsRm.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/architectureDiagram-3BPJPVTR-CjMDtn76.js +36 -0
- firme_tutor-0.2.0/web/dist/assets/architectureDiagram-3BPJPVTR-DP_FUTYE.js +36 -0
- firme_tutor-0.2.0/web/dist/assets/blockDiagram-GPEHLZMM-BwUytfp7.js +132 -0
- firme_tutor-0.2.0/web/dist/assets/blockDiagram-GPEHLZMM-aYsXAwRW.js +132 -0
- firme_tutor-0.2.0/web/dist/assets/c4Diagram-AAUBKEIU-Bp77wM0V.js +10 -0
- firme_tutor-0.2.0/web/dist/assets/c4Diagram-AAUBKEIU-H-Jn5xGT.js +10 -0
- firme_tutor-0.2.0/web/dist/assets/channel-D3zhJf12.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/channel-DUET4myG.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-2J33WTMH-B2JfwxXI.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-2J33WTMH-CmbDIqse.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-4BX2VUAB-CiRJvBSS.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-4BX2VUAB-DFJ9PiVX.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-55IACEB6-D3HDZt19.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-55IACEB6-DDqBhfOL.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-727SXJPM-DOKYRhEn.js +206 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-727SXJPM-dQ45P2iw.js +206 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-AQP2D5EJ-Bee_W2_Y.js +231 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-AQP2D5EJ-f6mrCGpl.js +231 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-FMBD7UC4-BlVqdx0u.js +15 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-FMBD7UC4-CsLkUbYG.js +15 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-ND2GUHAM-BE3EMr9M.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-ND2GUHAM-DPCZFRwg.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-QZHKN3VN-C2EmNhuC.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/chunk-QZHKN3VN-CsETkrdx.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/classDiagram-4FO5ZUOK-6z0PHbLf.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/classDiagram-4FO5ZUOK-_VQcyODs.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/classDiagram-v2-Q7XG4LA2-6z0PHbLf.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/classDiagram-v2-Q7XG4LA2-_VQcyODs.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/cose-bilkent-S5V4N54A-DDbXV7Jg.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/cose-bilkent-S5V4N54A-b1UkYwjp.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/cytoscape.esm-FqbQrHcz.js +321 -0
- firme_tutor-0.2.0/web/dist/assets/dagre-BM42HDAG-BsNa8bKt.js +4 -0
- firme_tutor-0.2.0/web/dist/assets/dagre-BM42HDAG-Sj4pza0E.js +4 -0
- firme_tutor-0.2.0/web/dist/assets/dagre-Bx709z4p.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/defaultLocale-C8Fc0cco.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/diagram-2AECGRRQ-BG1EVSbc.js +43 -0
- firme_tutor-0.2.0/web/dist/assets/diagram-2AECGRRQ-BKbqr1fn.js +43 -0
- firme_tutor-0.2.0/web/dist/assets/diagram-5GNKFQAL-BNip8_sK.js +10 -0
- firme_tutor-0.2.0/web/dist/assets/diagram-5GNKFQAL-zB-3Fy6R.js +10 -0
- firme_tutor-0.2.0/web/dist/assets/diagram-KO2AKTUF-BjYQE0x7.js +3 -0
- firme_tutor-0.2.0/web/dist/assets/diagram-KO2AKTUF-_PS8ucO2.js +3 -0
- firme_tutor-0.2.0/web/dist/assets/diagram-LMA3HP47-CwrlWP0x.js +24 -0
- firme_tutor-0.2.0/web/dist/assets/diagram-LMA3HP47-DthtUw5L.js +24 -0
- firme_tutor-0.2.0/web/dist/assets/diagram-OG6HWLK6-DVwpvzfb.js +24 -0
- firme_tutor-0.2.0/web/dist/assets/diagram-OG6HWLK6-qEpybCEy.js +24 -0
- firme_tutor-0.2.0/web/dist/assets/erDiagram-TEJ5UH35-ClFzIpuj.js +85 -0
- firme_tutor-0.2.0/web/dist/assets/erDiagram-TEJ5UH35-Hd0qiO8b.js +85 -0
- firme_tutor-0.2.0/web/dist/assets/eventmodeling-FCH6USID--Mtgjm_v.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/eventmodeling-FCH6USID-D_pZo8i_.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/flowDiagram-I6XJVG4X-Ig0KZKOS.js +162 -0
- firme_tutor-0.2.0/web/dist/assets/flowDiagram-I6XJVG4X-um4xeAwx.js +162 -0
- firme_tutor-0.2.0/web/dist/assets/ganttDiagram-6RSMTGT7-BKf9wbVM.js +292 -0
- firme_tutor-0.2.0/web/dist/assets/ganttDiagram-6RSMTGT7-C0geFI1t.js +292 -0
- firme_tutor-0.2.0/web/dist/assets/gitGraph-WXDBUCRP-CX6Fr11a.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/gitGraph-WXDBUCRP-D6XLrz9f.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/gitGraphDiagram-PVQCEYII-B9ranWDI.js +106 -0
- firme_tutor-0.2.0/web/dist/assets/gitGraphDiagram-PVQCEYII-CvumOUae.js +106 -0
- firme_tutor-0.2.0/web/dist/assets/graphlib-B8gBHxth.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/index-BTb5-sb9.js +339 -0
- firme_tutor-0.2.0/web/dist/assets/index-BVsG-zyT.css +1 -0
- firme_tutor-0.2.0/web/dist/assets/index-BsQieKqg.js +339 -0
- firme_tutor-0.2.0/web/dist/assets/index-DzgywBd5.css +1 -0
- firme_tutor-0.2.0/web/dist/assets/info-J43DQDTF-BIlDfkV-.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/info-J43DQDTF-Cl5xrj6u.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/infoDiagram-5YYISTIA-LFNqA-Ef.js +2 -0
- firme_tutor-0.2.0/web/dist/assets/infoDiagram-5YYISTIA-gh4R7xRA.js +2 -0
- firme_tutor-0.2.0/web/dist/assets/init-D6jRqBbL.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/ishikawaDiagram-YF4QCWOH-Cm_oPlFP.js +70 -0
- firme_tutor-0.2.0/web/dist/assets/ishikawaDiagram-YF4QCWOH-CxggAMWN.js +70 -0
- firme_tutor-0.2.0/web/dist/assets/journeyDiagram-JHISSGLW-CX0FSEjo.js +139 -0
- firme_tutor-0.2.0/web/dist/assets/journeyDiagram-JHISSGLW-D7I1V3cu.js +139 -0
- firme_tutor-0.2.0/web/dist/assets/kanban-definition-UN3LZRKU-ABQNt4rG.js +89 -0
- firme_tutor-0.2.0/web/dist/assets/kanban-definition-UN3LZRKU-C5n2jO9q.js +89 -0
- firme_tutor-0.2.0/web/dist/assets/katex-Vhh-h91d.js +257 -0
- firme_tutor-0.2.0/web/dist/assets/linear-CD4Oo35k.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/linear-CtNFkBk8.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/mermaid-parser.core-78hM4Y96.js +161 -0
- firme_tutor-0.2.0/web/dist/assets/mermaid-parser.core-BkDxsFuj.js +161 -0
- firme_tutor-0.2.0/web/dist/assets/mindmap-definition-RKZ34NQL-C1pGZ1LG.js +96 -0
- firme_tutor-0.2.0/web/dist/assets/mindmap-definition-RKZ34NQL-GGLqgti3.js +96 -0
- firme_tutor-0.2.0/web/dist/assets/ordinal-hYBb2elL.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/packet-YPE3B663-B8-1g1QF.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/packet-YPE3B663-DqtUQHPE.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/pie-LRSECV5Y-BPuzttrq.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/pie-LRSECV5Y-DwwS2nmL.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/pieDiagram-4H26LBE5-DtT_nRRn.js +30 -0
- firme_tutor-0.2.0/web/dist/assets/pieDiagram-4H26LBE5-LYEy49q8.js +30 -0
- firme_tutor-0.2.0/web/dist/assets/quadrantDiagram-W4KKPZXB-Bvd1jbhg.js +7 -0
- firme_tutor-0.2.0/web/dist/assets/quadrantDiagram-W4KKPZXB-D1ov-gdL.js +7 -0
- firme_tutor-0.2.0/web/dist/assets/radar-GUYGQ44K-DXtzkNxC.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/radar-GUYGQ44K-TjLlmiCU.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/requirementDiagram-4Y6WPE33-B1VZI8BL.js +84 -0
- firme_tutor-0.2.0/web/dist/assets/requirementDiagram-4Y6WPE33-CCfFYSqM.js +84 -0
- firme_tutor-0.2.0/web/dist/assets/sankeyDiagram-5OEKKPKP-BztZ_EFc.js +40 -0
- firme_tutor-0.2.0/web/dist/assets/sankeyDiagram-5OEKKPKP-CXb7EmOJ.js +40 -0
- firme_tutor-0.2.0/web/dist/assets/sequenceDiagram-3UESZ5HK-QX4NdcK_.js +162 -0
- firme_tutor-0.2.0/web/dist/assets/sequenceDiagram-3UESZ5HK-Sp2tvkoT.js +162 -0
- firme_tutor-0.2.0/web/dist/assets/stateDiagram-AJRCARHV-CpsWzZ9I.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/stateDiagram-AJRCARHV-DIOdasDM.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/stateDiagram-v2-BHNVJYJU-Jt9E-Zt_.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/stateDiagram-v2-BHNVJYJU-LfyaYy96.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/timeline-definition-PNZ67QCA-D0_o57jX.js +120 -0
- firme_tutor-0.2.0/web/dist/assets/timeline-definition-PNZ67QCA-Ue-hnFjk.js +120 -0
- firme_tutor-0.2.0/web/dist/assets/treeView-BLDUP644-BueViHYx.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/treeView-BLDUP644-ZtLGkb3B.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/treemap-LRROVOQU-BBsbNAZ6.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/treemap-LRROVOQU-Cm4jfzQA.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/vennDiagram-CIIHVFJN-DihoR2xs.js +34 -0
- firme_tutor-0.2.0/web/dist/assets/vennDiagram-CIIHVFJN-NQ-U2Ihc.js +34 -0
- firme_tutor-0.2.0/web/dist/assets/wardley-L42UT6IY-mqWJpr_T.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/wardley-L42UT6IY-nzZZ6F8x.js +1 -0
- firme_tutor-0.2.0/web/dist/assets/wardleyDiagram-YWT4CUSO-BXAvaj3_.js +78 -0
- firme_tutor-0.2.0/web/dist/assets/wardleyDiagram-YWT4CUSO-ChvZuWwP.js +78 -0
- firme_tutor-0.2.0/web/dist/assets/xychartDiagram-2RQKCTM6-BaC7fSuu.js +7 -0
- firme_tutor-0.2.0/web/dist/assets/xychartDiagram-2RQKCTM6-BvyHx8AJ.js +7 -0
- firme_tutor-0.2.0/web/dist/favicon.svg +1 -0
- firme_tutor-0.2.0/web/dist/firme_logo_purple.png +0 -0
- firme_tutor-0.2.0/web/dist/icons.svg +24 -0
- firme_tutor-0.2.0/web/dist/index.html +14 -0
- firme_tutor-0.2.0/web/routers/__init__.py +0 -0
- firme_tutor-0.2.0/web/routers/auth.py +43 -0
- firme_tutor-0.2.0/web/routers/chat.py +244 -0
- firme_tutor-0.2.0/web/routers/progress.py +242 -0
- firme_tutor-0.2.0/web/routers/typing_game.py +217 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: firme-tutor
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Socratic AI tutor and typing practice for Firme Coding fellows
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: anthropic>=0.105.0
|
|
7
|
+
Requires-Dist: fastapi>=0.136.0
|
|
8
|
+
Requires-Dist: uvicorn>=0.48.0
|
|
9
|
+
Requires-Dist: sqlalchemy>=2.0.50
|
|
10
|
+
Requires-Dist: pydantic>=2.13.0
|
|
11
|
+
Requires-Dist: pydantic-settings>=2.14.0
|
|
12
|
+
Requires-Dist: python-dotenv>=1.2.0
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: ruff; extra == "dev"
|
|
15
|
+
Requires-Dist: pytest; extra == "dev"
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Firme Tutor
|
|
2
|
+
|
|
3
|
+
A Socratic AI tutor and typing practice app for [Firme Coding](https://firmecoding.org) fellows. Built with FastAPI + React, powered by Claude.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- AI tutor that guides learners with questions (never gives direct answers)
|
|
8
|
+
- Browser-based typing game with reentry-themed content
|
|
9
|
+
- Multi-modal teaching (text, visual, audio, hands-on)
|
|
10
|
+
- Fellow memory — the tutor learns about each person across sessions
|
|
11
|
+
- Progress dashboard for staff and funders
|
|
12
|
+
|
|
13
|
+
## Quick Start (Local Development)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# 1. Clone the repo
|
|
17
|
+
git clone git@gitlab.com:firme-coding/firme-tutor.git
|
|
18
|
+
cd firme-tutor
|
|
19
|
+
|
|
20
|
+
# 2. Create a virtual environment and install
|
|
21
|
+
python -m venv venv
|
|
22
|
+
source venv/bin/activate # macOS/Linux
|
|
23
|
+
pip install -e ".[dev]"
|
|
24
|
+
|
|
25
|
+
# 3. Add your API key
|
|
26
|
+
cp .env.example .env
|
|
27
|
+
# Edit .env and add your ANTHROPIC_API_KEY
|
|
28
|
+
|
|
29
|
+
# 4. Start the backend
|
|
30
|
+
python -m firme_tutor
|
|
31
|
+
|
|
32
|
+
# 5. In a separate terminal, start the frontend
|
|
33
|
+
cd firme_tutor/frontend
|
|
34
|
+
npm install
|
|
35
|
+
npm run dev
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The app will be at `http://localhost:5173` (frontend) proxying to `http://localhost:8000` (API).
|
|
39
|
+
|
|
40
|
+
## Adding firme-tutor to Your Project (Step by Step)
|
|
41
|
+
|
|
42
|
+
### Step 1: Install the package
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install firme-tutor
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
That's it. Same as installing any other Python package.
|
|
49
|
+
|
|
50
|
+
### Step 2: Save it to your dependencies
|
|
51
|
+
|
|
52
|
+
So other people (or your deployment) can install it too.
|
|
53
|
+
|
|
54
|
+
**If your project uses `requirements.txt`:**
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
firme-tutor
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**If your project uses `pyproject.toml`:**
|
|
61
|
+
|
|
62
|
+
```toml
|
|
63
|
+
[project]
|
|
64
|
+
dependencies = [
|
|
65
|
+
"firme-tutor",
|
|
66
|
+
]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Step 3: Set the API key
|
|
70
|
+
|
|
71
|
+
The tutor needs an `ANTHROPIC_API_KEY` to talk to Claude. Create a `.env` file in your project:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
echo "ANTHROPIC_API_KEY=your-key-here" > .env
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Make sure `.env` is in your `.gitignore` so the key doesn't get committed.
|
|
78
|
+
|
|
79
|
+
### Step 4: Use it in your code
|
|
80
|
+
|
|
81
|
+
**Use just the tutor (for chatting):**
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from firme_tutor import FirmeTutor
|
|
85
|
+
|
|
86
|
+
tutor = FirmeTutor(topic="What is a variable?")
|
|
87
|
+
reply = tutor.chat("I don't understand what a variable does")
|
|
88
|
+
print(reply)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Run the full web app (tutor + typing game + progress dashboard):**
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from firme_tutor.web import run_server
|
|
95
|
+
|
|
96
|
+
run_server() # Starts at http://localhost:8000
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Or from the command line:**
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python -m firme_tutor
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Updating to the latest version
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
pip install --upgrade firme-tutor
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Publishing a New Version to PyPI
|
|
112
|
+
|
|
113
|
+
This is for maintainers — how to release a new version so `pip install firme-tutor` gets the latest code.
|
|
114
|
+
|
|
115
|
+
### One-time setup
|
|
116
|
+
|
|
117
|
+
1. Create a free account at https://pypi.org/account/register/
|
|
118
|
+
2. Go to https://pypi.org/manage/account/token/ and create an API token
|
|
119
|
+
3. In GitLab, go to **Settings > CI/CD > Variables** and add:
|
|
120
|
+
- **Key:** `PYPI_TOKEN`
|
|
121
|
+
- **Value:** the token from PyPI (starts with `pypi-`)
|
|
122
|
+
- **Check** "Mask variable"
|
|
123
|
+
|
|
124
|
+
### Releasing a new version
|
|
125
|
+
|
|
126
|
+
1. Update the version number in `__init__.py`:
|
|
127
|
+
```python
|
|
128
|
+
__version__ = "0.3.0"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
2. Commit, tag, and push:
|
|
132
|
+
```bash
|
|
133
|
+
git add .
|
|
134
|
+
git commit -m "release v0.3.0"
|
|
135
|
+
git tag v0.3.0
|
|
136
|
+
git push origin main --tags
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
3. GitLab CI automatically builds and publishes to PyPI. Within a few minutes, anyone can run:
|
|
140
|
+
```bash
|
|
141
|
+
pip install --upgrade firme-tutor
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Environment Variables
|
|
145
|
+
|
|
146
|
+
| Variable | Required | Description |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| `ANTHROPIC_API_KEY` | Yes | Claude API key |
|
|
149
|
+
| `FIRME_HOST` | No | Server host (default: `127.0.0.1`) |
|
|
150
|
+
| `FIRME_PORT` | No | Server port (default: `8000`) |
|
|
151
|
+
| `FIRME_DATABASE_URL` | No | SQLAlchemy DB URL (default: SQLite at `~/.firme-tutor/firme_tutor.db`) |
|
|
152
|
+
| `FIRME_DEBUG` | No | Enable debug mode (default: `false`) |
|
|
153
|
+
|
|
154
|
+
For local dev, put these in a `.env` file. For deployment, set them in your hosting platform or GitLab CI/CD Variables.
|
|
155
|
+
|
|
156
|
+
## Deployment
|
|
157
|
+
|
|
158
|
+
The repo includes a `Dockerfile` and `.gitlab-ci.yml` for CI/CD:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Build the Docker image
|
|
162
|
+
docker build -t firme-tutor .
|
|
163
|
+
|
|
164
|
+
# Run it (pass the API key at runtime, never bake it into the image)
|
|
165
|
+
docker run -p 8000:8000 -e ANTHROPIC_API_KEY=sk-ant-... firme-tutor
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
GitLab CI will automatically lint, build the frontend, and push a Docker image to the GitLab Container Registry on pushes to `main`.
|
|
169
|
+
|
|
170
|
+
## Project Structure
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
firme_tutor/
|
|
174
|
+
tutor.py # FirmeTutor class — one instance per session
|
|
175
|
+
prompts.py # System prompts (Socratic persona, insight extraction)
|
|
176
|
+
curriculum.py # Module and curriculum content
|
|
177
|
+
db/ # SQLAlchemy models and engine
|
|
178
|
+
multimodal/ # Learning mode definitions (text/visual/audio/kinesthetic)
|
|
179
|
+
typing_game/ # Sentence content, keyboard mapping, scoring
|
|
180
|
+
web/ # FastAPI app, routers, config
|
|
181
|
+
routers/ # API endpoints (auth, chat, typing, progress)
|
|
182
|
+
dist/ # Built React frontend (generated by npm run build)
|
|
183
|
+
frontend/ # React + TypeScript + Vite source
|
|
184
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
firme-tutor
|
|
3
|
+
-----------
|
|
4
|
+
AI-powered Socratic tutor for Firme Coding fellows.
|
|
5
|
+
Built on the Claude API. Designed to guide learners through
|
|
6
|
+
lessons and homework without giving direct answers.
|
|
7
|
+
|
|
8
|
+
Includes:
|
|
9
|
+
- Socratic AI tutor with multi-modal teaching (text, visual, audio, hands-on)
|
|
10
|
+
- Typing practice game with reentry-themed content
|
|
11
|
+
- Progress tracking API for staff and funders
|
|
12
|
+
- Fellow memory — the tutor remembers each learner across sessions
|
|
13
|
+
|
|
14
|
+
Basic usage:
|
|
15
|
+
from firme_tutor import FirmeTutor
|
|
16
|
+
|
|
17
|
+
tutor = FirmeTutor(topic="What is a variable?")
|
|
18
|
+
reply = tutor.chat("I don't understand what a variable does")
|
|
19
|
+
print(reply)
|
|
20
|
+
|
|
21
|
+
Run the web app:
|
|
22
|
+
pip install "firme-tutor[web]"
|
|
23
|
+
firme-tutor-web
|
|
24
|
+
|
|
25
|
+
# or
|
|
26
|
+
python -m firme_tutor
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from .tutor import FirmeTutor
|
|
30
|
+
from .prompts import build_system_prompt, BASE_SYSTEM_PROMPT
|
|
31
|
+
from .curriculum import MODULES, get_curriculum_for_module
|
|
32
|
+
from .multimodal.modes import LearningMode
|
|
33
|
+
from .typing_game.sentences import STAGES as TYPING_STAGES
|
|
34
|
+
|
|
35
|
+
__version__ = "0.2.0"
|
|
36
|
+
__author__ = "Maria D. Martinez <maria@firmecoding.org>"
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"FirmeTutor",
|
|
40
|
+
"build_system_prompt",
|
|
41
|
+
"BASE_SYSTEM_PROMPT",
|
|
42
|
+
"MODULES",
|
|
43
|
+
"get_curriculum_for_module",
|
|
44
|
+
"LearningMode",
|
|
45
|
+
"TYPING_STAGES",
|
|
46
|
+
]
|