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.
Files changed (156) hide show
  1. firme_tutor-0.2.0/PKG-INFO +15 -0
  2. firme_tutor-0.2.0/README.md +184 -0
  3. firme_tutor-0.2.0/__init__.py +46 -0
  4. firme_tutor-0.2.0/__main__.py +8 -0
  5. firme_tutor-0.2.0/curriculum.py +5623 -0
  6. firme_tutor-0.2.0/db/__init__.py +16 -0
  7. firme_tutor-0.2.0/db/engine.py +42 -0
  8. firme_tutor-0.2.0/db/models.py +160 -0
  9. firme_tutor-0.2.0/firme_logo_purple.png +0 -0
  10. firme_tutor-0.2.0/firme_tutor.egg-info/PKG-INFO +15 -0
  11. firme_tutor-0.2.0/firme_tutor.egg-info/SOURCES.txt +301 -0
  12. firme_tutor-0.2.0/firme_tutor.egg-info/dependency_links.txt +1 -0
  13. firme_tutor-0.2.0/firme_tutor.egg-info/requires.txt +11 -0
  14. firme_tutor-0.2.0/firme_tutor.egg-info/top_level.txt +1 -0
  15. firme_tutor-0.2.0/multimodal/__init__.py +0 -0
  16. firme_tutor-0.2.0/multimodal/modes.py +66 -0
  17. firme_tutor-0.2.0/prompts.py +183 -0
  18. firme_tutor-0.2.0/pyproject.toml +32 -0
  19. firme_tutor-0.2.0/setup.cfg +4 -0
  20. firme_tutor-0.2.0/tutor.py +137 -0
  21. firme_tutor-0.2.0/typing_game/__init__.py +0 -0
  22. firme_tutor-0.2.0/typing_game/keyboard.py +77 -0
  23. firme_tutor-0.2.0/typing_game/scoring.py +22 -0
  24. firme_tutor-0.2.0/typing_game/sentences.py +229 -0
  25. firme_tutor-0.2.0/web/__init__.py +22 -0
  26. firme_tutor-0.2.0/web/app.py +60 -0
  27. firme_tutor-0.2.0/web/config.py +38 -0
  28. firme_tutor-0.2.0/web/dependencies.py +59 -0
  29. firme_tutor-0.2.0/web/dist/assets/arc-B8bv5B3N.js +1 -0
  30. firme_tutor-0.2.0/web/dist/assets/arc-hcHIXwUj.js +1 -0
  31. firme_tutor-0.2.0/web/dist/assets/architecture-7EHR7CIX-CfWJRDbS.js +1 -0
  32. firme_tutor-0.2.0/web/dist/assets/architecture-7EHR7CIX-D7wqdsRm.js +1 -0
  33. firme_tutor-0.2.0/web/dist/assets/architectureDiagram-3BPJPVTR-CjMDtn76.js +36 -0
  34. firme_tutor-0.2.0/web/dist/assets/architectureDiagram-3BPJPVTR-DP_FUTYE.js +36 -0
  35. firme_tutor-0.2.0/web/dist/assets/blockDiagram-GPEHLZMM-BwUytfp7.js +132 -0
  36. firme_tutor-0.2.0/web/dist/assets/blockDiagram-GPEHLZMM-aYsXAwRW.js +132 -0
  37. firme_tutor-0.2.0/web/dist/assets/c4Diagram-AAUBKEIU-Bp77wM0V.js +10 -0
  38. firme_tutor-0.2.0/web/dist/assets/c4Diagram-AAUBKEIU-H-Jn5xGT.js +10 -0
  39. firme_tutor-0.2.0/web/dist/assets/channel-D3zhJf12.js +1 -0
  40. firme_tutor-0.2.0/web/dist/assets/channel-DUET4myG.js +1 -0
  41. firme_tutor-0.2.0/web/dist/assets/chunk-2J33WTMH-B2JfwxXI.js +1 -0
  42. firme_tutor-0.2.0/web/dist/assets/chunk-2J33WTMH-CmbDIqse.js +1 -0
  43. firme_tutor-0.2.0/web/dist/assets/chunk-4BX2VUAB-CiRJvBSS.js +1 -0
  44. firme_tutor-0.2.0/web/dist/assets/chunk-4BX2VUAB-DFJ9PiVX.js +1 -0
  45. firme_tutor-0.2.0/web/dist/assets/chunk-55IACEB6-D3HDZt19.js +1 -0
  46. firme_tutor-0.2.0/web/dist/assets/chunk-55IACEB6-DDqBhfOL.js +1 -0
  47. firme_tutor-0.2.0/web/dist/assets/chunk-727SXJPM-DOKYRhEn.js +206 -0
  48. firme_tutor-0.2.0/web/dist/assets/chunk-727SXJPM-dQ45P2iw.js +206 -0
  49. firme_tutor-0.2.0/web/dist/assets/chunk-AQP2D5EJ-Bee_W2_Y.js +231 -0
  50. firme_tutor-0.2.0/web/dist/assets/chunk-AQP2D5EJ-f6mrCGpl.js +231 -0
  51. firme_tutor-0.2.0/web/dist/assets/chunk-FMBD7UC4-BlVqdx0u.js +15 -0
  52. firme_tutor-0.2.0/web/dist/assets/chunk-FMBD7UC4-CsLkUbYG.js +15 -0
  53. firme_tutor-0.2.0/web/dist/assets/chunk-ND2GUHAM-BE3EMr9M.js +1 -0
  54. firme_tutor-0.2.0/web/dist/assets/chunk-ND2GUHAM-DPCZFRwg.js +1 -0
  55. firme_tutor-0.2.0/web/dist/assets/chunk-QZHKN3VN-C2EmNhuC.js +1 -0
  56. firme_tutor-0.2.0/web/dist/assets/chunk-QZHKN3VN-CsETkrdx.js +1 -0
  57. firme_tutor-0.2.0/web/dist/assets/classDiagram-4FO5ZUOK-6z0PHbLf.js +1 -0
  58. firme_tutor-0.2.0/web/dist/assets/classDiagram-4FO5ZUOK-_VQcyODs.js +1 -0
  59. firme_tutor-0.2.0/web/dist/assets/classDiagram-v2-Q7XG4LA2-6z0PHbLf.js +1 -0
  60. firme_tutor-0.2.0/web/dist/assets/classDiagram-v2-Q7XG4LA2-_VQcyODs.js +1 -0
  61. firme_tutor-0.2.0/web/dist/assets/cose-bilkent-S5V4N54A-DDbXV7Jg.js +1 -0
  62. firme_tutor-0.2.0/web/dist/assets/cose-bilkent-S5V4N54A-b1UkYwjp.js +1 -0
  63. firme_tutor-0.2.0/web/dist/assets/cytoscape.esm-FqbQrHcz.js +321 -0
  64. firme_tutor-0.2.0/web/dist/assets/dagre-BM42HDAG-BsNa8bKt.js +4 -0
  65. firme_tutor-0.2.0/web/dist/assets/dagre-BM42HDAG-Sj4pza0E.js +4 -0
  66. firme_tutor-0.2.0/web/dist/assets/dagre-Bx709z4p.js +1 -0
  67. firme_tutor-0.2.0/web/dist/assets/defaultLocale-C8Fc0cco.js +1 -0
  68. firme_tutor-0.2.0/web/dist/assets/diagram-2AECGRRQ-BG1EVSbc.js +43 -0
  69. firme_tutor-0.2.0/web/dist/assets/diagram-2AECGRRQ-BKbqr1fn.js +43 -0
  70. firme_tutor-0.2.0/web/dist/assets/diagram-5GNKFQAL-BNip8_sK.js +10 -0
  71. firme_tutor-0.2.0/web/dist/assets/diagram-5GNKFQAL-zB-3Fy6R.js +10 -0
  72. firme_tutor-0.2.0/web/dist/assets/diagram-KO2AKTUF-BjYQE0x7.js +3 -0
  73. firme_tutor-0.2.0/web/dist/assets/diagram-KO2AKTUF-_PS8ucO2.js +3 -0
  74. firme_tutor-0.2.0/web/dist/assets/diagram-LMA3HP47-CwrlWP0x.js +24 -0
  75. firme_tutor-0.2.0/web/dist/assets/diagram-LMA3HP47-DthtUw5L.js +24 -0
  76. firme_tutor-0.2.0/web/dist/assets/diagram-OG6HWLK6-DVwpvzfb.js +24 -0
  77. firme_tutor-0.2.0/web/dist/assets/diagram-OG6HWLK6-qEpybCEy.js +24 -0
  78. firme_tutor-0.2.0/web/dist/assets/erDiagram-TEJ5UH35-ClFzIpuj.js +85 -0
  79. firme_tutor-0.2.0/web/dist/assets/erDiagram-TEJ5UH35-Hd0qiO8b.js +85 -0
  80. firme_tutor-0.2.0/web/dist/assets/eventmodeling-FCH6USID--Mtgjm_v.js +1 -0
  81. firme_tutor-0.2.0/web/dist/assets/eventmodeling-FCH6USID-D_pZo8i_.js +1 -0
  82. firme_tutor-0.2.0/web/dist/assets/flowDiagram-I6XJVG4X-Ig0KZKOS.js +162 -0
  83. firme_tutor-0.2.0/web/dist/assets/flowDiagram-I6XJVG4X-um4xeAwx.js +162 -0
  84. firme_tutor-0.2.0/web/dist/assets/ganttDiagram-6RSMTGT7-BKf9wbVM.js +292 -0
  85. firme_tutor-0.2.0/web/dist/assets/ganttDiagram-6RSMTGT7-C0geFI1t.js +292 -0
  86. firme_tutor-0.2.0/web/dist/assets/gitGraph-WXDBUCRP-CX6Fr11a.js +1 -0
  87. firme_tutor-0.2.0/web/dist/assets/gitGraph-WXDBUCRP-D6XLrz9f.js +1 -0
  88. firme_tutor-0.2.0/web/dist/assets/gitGraphDiagram-PVQCEYII-B9ranWDI.js +106 -0
  89. firme_tutor-0.2.0/web/dist/assets/gitGraphDiagram-PVQCEYII-CvumOUae.js +106 -0
  90. firme_tutor-0.2.0/web/dist/assets/graphlib-B8gBHxth.js +1 -0
  91. firme_tutor-0.2.0/web/dist/assets/index-BTb5-sb9.js +339 -0
  92. firme_tutor-0.2.0/web/dist/assets/index-BVsG-zyT.css +1 -0
  93. firme_tutor-0.2.0/web/dist/assets/index-BsQieKqg.js +339 -0
  94. firme_tutor-0.2.0/web/dist/assets/index-DzgywBd5.css +1 -0
  95. firme_tutor-0.2.0/web/dist/assets/info-J43DQDTF-BIlDfkV-.js +1 -0
  96. firme_tutor-0.2.0/web/dist/assets/info-J43DQDTF-Cl5xrj6u.js +1 -0
  97. firme_tutor-0.2.0/web/dist/assets/infoDiagram-5YYISTIA-LFNqA-Ef.js +2 -0
  98. firme_tutor-0.2.0/web/dist/assets/infoDiagram-5YYISTIA-gh4R7xRA.js +2 -0
  99. firme_tutor-0.2.0/web/dist/assets/init-D6jRqBbL.js +1 -0
  100. firme_tutor-0.2.0/web/dist/assets/ishikawaDiagram-YF4QCWOH-Cm_oPlFP.js +70 -0
  101. firme_tutor-0.2.0/web/dist/assets/ishikawaDiagram-YF4QCWOH-CxggAMWN.js +70 -0
  102. firme_tutor-0.2.0/web/dist/assets/journeyDiagram-JHISSGLW-CX0FSEjo.js +139 -0
  103. firme_tutor-0.2.0/web/dist/assets/journeyDiagram-JHISSGLW-D7I1V3cu.js +139 -0
  104. firme_tutor-0.2.0/web/dist/assets/kanban-definition-UN3LZRKU-ABQNt4rG.js +89 -0
  105. firme_tutor-0.2.0/web/dist/assets/kanban-definition-UN3LZRKU-C5n2jO9q.js +89 -0
  106. firme_tutor-0.2.0/web/dist/assets/katex-Vhh-h91d.js +257 -0
  107. firme_tutor-0.2.0/web/dist/assets/linear-CD4Oo35k.js +1 -0
  108. firme_tutor-0.2.0/web/dist/assets/linear-CtNFkBk8.js +1 -0
  109. firme_tutor-0.2.0/web/dist/assets/mermaid-parser.core-78hM4Y96.js +161 -0
  110. firme_tutor-0.2.0/web/dist/assets/mermaid-parser.core-BkDxsFuj.js +161 -0
  111. firme_tutor-0.2.0/web/dist/assets/mindmap-definition-RKZ34NQL-C1pGZ1LG.js +96 -0
  112. firme_tutor-0.2.0/web/dist/assets/mindmap-definition-RKZ34NQL-GGLqgti3.js +96 -0
  113. firme_tutor-0.2.0/web/dist/assets/ordinal-hYBb2elL.js +1 -0
  114. firme_tutor-0.2.0/web/dist/assets/packet-YPE3B663-B8-1g1QF.js +1 -0
  115. firme_tutor-0.2.0/web/dist/assets/packet-YPE3B663-DqtUQHPE.js +1 -0
  116. firme_tutor-0.2.0/web/dist/assets/pie-LRSECV5Y-BPuzttrq.js +1 -0
  117. firme_tutor-0.2.0/web/dist/assets/pie-LRSECV5Y-DwwS2nmL.js +1 -0
  118. firme_tutor-0.2.0/web/dist/assets/pieDiagram-4H26LBE5-DtT_nRRn.js +30 -0
  119. firme_tutor-0.2.0/web/dist/assets/pieDiagram-4H26LBE5-LYEy49q8.js +30 -0
  120. firme_tutor-0.2.0/web/dist/assets/quadrantDiagram-W4KKPZXB-Bvd1jbhg.js +7 -0
  121. firme_tutor-0.2.0/web/dist/assets/quadrantDiagram-W4KKPZXB-D1ov-gdL.js +7 -0
  122. firme_tutor-0.2.0/web/dist/assets/radar-GUYGQ44K-DXtzkNxC.js +1 -0
  123. firme_tutor-0.2.0/web/dist/assets/radar-GUYGQ44K-TjLlmiCU.js +1 -0
  124. firme_tutor-0.2.0/web/dist/assets/requirementDiagram-4Y6WPE33-B1VZI8BL.js +84 -0
  125. firme_tutor-0.2.0/web/dist/assets/requirementDiagram-4Y6WPE33-CCfFYSqM.js +84 -0
  126. firme_tutor-0.2.0/web/dist/assets/sankeyDiagram-5OEKKPKP-BztZ_EFc.js +40 -0
  127. firme_tutor-0.2.0/web/dist/assets/sankeyDiagram-5OEKKPKP-CXb7EmOJ.js +40 -0
  128. firme_tutor-0.2.0/web/dist/assets/sequenceDiagram-3UESZ5HK-QX4NdcK_.js +162 -0
  129. firme_tutor-0.2.0/web/dist/assets/sequenceDiagram-3UESZ5HK-Sp2tvkoT.js +162 -0
  130. firme_tutor-0.2.0/web/dist/assets/stateDiagram-AJRCARHV-CpsWzZ9I.js +1 -0
  131. firme_tutor-0.2.0/web/dist/assets/stateDiagram-AJRCARHV-DIOdasDM.js +1 -0
  132. firme_tutor-0.2.0/web/dist/assets/stateDiagram-v2-BHNVJYJU-Jt9E-Zt_.js +1 -0
  133. firme_tutor-0.2.0/web/dist/assets/stateDiagram-v2-BHNVJYJU-LfyaYy96.js +1 -0
  134. firme_tutor-0.2.0/web/dist/assets/timeline-definition-PNZ67QCA-D0_o57jX.js +120 -0
  135. firme_tutor-0.2.0/web/dist/assets/timeline-definition-PNZ67QCA-Ue-hnFjk.js +120 -0
  136. firme_tutor-0.2.0/web/dist/assets/treeView-BLDUP644-BueViHYx.js +1 -0
  137. firme_tutor-0.2.0/web/dist/assets/treeView-BLDUP644-ZtLGkb3B.js +1 -0
  138. firme_tutor-0.2.0/web/dist/assets/treemap-LRROVOQU-BBsbNAZ6.js +1 -0
  139. firme_tutor-0.2.0/web/dist/assets/treemap-LRROVOQU-Cm4jfzQA.js +1 -0
  140. firme_tutor-0.2.0/web/dist/assets/vennDiagram-CIIHVFJN-DihoR2xs.js +34 -0
  141. firme_tutor-0.2.0/web/dist/assets/vennDiagram-CIIHVFJN-NQ-U2Ihc.js +34 -0
  142. firme_tutor-0.2.0/web/dist/assets/wardley-L42UT6IY-mqWJpr_T.js +1 -0
  143. firme_tutor-0.2.0/web/dist/assets/wardley-L42UT6IY-nzZZ6F8x.js +1 -0
  144. firme_tutor-0.2.0/web/dist/assets/wardleyDiagram-YWT4CUSO-BXAvaj3_.js +78 -0
  145. firme_tutor-0.2.0/web/dist/assets/wardleyDiagram-YWT4CUSO-ChvZuWwP.js +78 -0
  146. firme_tutor-0.2.0/web/dist/assets/xychartDiagram-2RQKCTM6-BaC7fSuu.js +7 -0
  147. firme_tutor-0.2.0/web/dist/assets/xychartDiagram-2RQKCTM6-BvyHx8AJ.js +7 -0
  148. firme_tutor-0.2.0/web/dist/favicon.svg +1 -0
  149. firme_tutor-0.2.0/web/dist/firme_logo_purple.png +0 -0
  150. firme_tutor-0.2.0/web/dist/icons.svg +24 -0
  151. firme_tutor-0.2.0/web/dist/index.html +14 -0
  152. firme_tutor-0.2.0/web/routers/__init__.py +0 -0
  153. firme_tutor-0.2.0/web/routers/auth.py +43 -0
  154. firme_tutor-0.2.0/web/routers/chat.py +244 -0
  155. firme_tutor-0.2.0/web/routers/progress.py +242 -0
  156. 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
+ ]
@@ -0,0 +1,8 @@
1
+ """
2
+ Allow running the web server with: python -m firme_tutor
3
+ """
4
+
5
+ from firme_tutor.web import run_server
6
+
7
+ if __name__ == "__main__":
8
+ run_server()