clawed 2.3.0__tar.gz → 2.3.2__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 (230) hide show
  1. {clawed-2.3.0 → clawed-2.3.2}/PKG-INFO +1 -1
  2. {clawed-2.3.0 → clawed-2.3.2}/clawed/__init__.py +1 -1
  3. {clawed-2.3.0 → clawed-2.3.2}/clawed/export_pptx.py +132 -48
  4. {clawed-2.3.0 → clawed-2.3.2}/clawed/onboarding.py +22 -5
  5. {clawed-2.3.0 → clawed-2.3.2}/pyproject.toml +1 -1
  6. {clawed-2.3.0 → clawed-2.3.2}/.gitignore +0 -0
  7. {clawed-2.3.0 → clawed-2.3.2}/LICENSE +0 -0
  8. {clawed-2.3.0 → clawed-2.3.2}/README.md +0 -0
  9. {clawed-2.3.0 → clawed-2.3.2}/clawed/__main__.py +0 -0
  10. {clawed-2.3.0 → clawed-2.3.2}/clawed/_legacy_gateway.py +0 -0
  11. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent.py +0 -0
  12. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/__init__.py +0 -0
  13. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/approvals.py +0 -0
  14. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/autonomy.py +0 -0
  15. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/context.py +0 -0
  16. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/core.py +0 -0
  17. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/custom_tools.py +0 -0
  18. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/drive/__init__.py +0 -0
  19. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/drive/auth.py +0 -0
  20. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/drive/client.py +0 -0
  21. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/fake_llm.py +0 -0
  22. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/loop.py +0 -0
  23. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/memory/__init__.py +0 -0
  24. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/memory/curriculum.py +0 -0
  25. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/memory/curriculum_kb.py +0 -0
  26. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/memory/embeddings.py +0 -0
  27. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/memory/episodes.py +0 -0
  28. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/memory/identity.py +0 -0
  29. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/memory/loader.py +0 -0
  30. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/memory/preferences.py +0 -0
  31. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/planner.py +0 -0
  32. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/prompt.py +0 -0
  33. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/scheduler.py +0 -0
  34. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/__init__.py +0 -0
  35. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/base.py +0 -0
  36. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/configure_profile.py +0 -0
  37. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/curriculum_map.py +0 -0
  38. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/drive_create_doc.py +0 -0
  39. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/drive_create_slides.py +0 -0
  40. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/drive_list.py +0 -0
  41. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/drive_organize.py +0 -0
  42. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/drive_read.py +0 -0
  43. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/drive_upload.py +0 -0
  44. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/export_document.py +0 -0
  45. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/gap_analysis.py +0 -0
  46. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/generate_assessment.py +0 -0
  47. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/generate_lesson.py +0 -0
  48. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/generate_lesson_bundle.py +0 -0
  49. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/generate_materials.py +0 -0
  50. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/generate_unit.py +0 -0
  51. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/ingest_materials.py +0 -0
  52. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/parent_comm.py +0 -0
  53. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/read_heartbeat.py +0 -0
  54. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/read_workspace.py +0 -0
  55. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/request_approval.py +0 -0
  56. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/schedule_task.py +0 -0
  57. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/search_lessons.py +0 -0
  58. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/search_my_materials.py +0 -0
  59. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/search_standards.py +0 -0
  60. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/student_insights.py +0 -0
  61. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/sub_packet.py +0 -0
  62. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/switch_model.py +0 -0
  63. {clawed-2.3.0 → clawed-2.3.2}/clawed/agent_core/tools/update_soul.py +0 -0
  64. {clawed-2.3.0 → clawed-2.3.2}/clawed/analytics.py +0 -0
  65. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/__init__.py +0 -0
  66. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/deps.py +0 -0
  67. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/__init__.py +0 -0
  68. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/chat.py +0 -0
  69. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/export.py +0 -0
  70. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/feedback.py +0 -0
  71. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/gateway_chat.py +0 -0
  72. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/generate.py +0 -0
  73. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/ingest.py +0 -0
  74. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/lessons.py +0 -0
  75. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/school.py +0 -0
  76. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/settings.py +0 -0
  77. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/routes/tools.py +0 -0
  78. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/server.py +0 -0
  79. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/static/app.js +0 -0
  80. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/static/style.css +0 -0
  81. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/static/widget.js +0 -0
  82. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/templates/analytics.html +0 -0
  83. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/templates/base.html +0 -0
  84. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/templates/dashboard.html +0 -0
  85. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/templates/generate.html +0 -0
  86. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/templates/index.html +0 -0
  87. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/templates/lesson.html +0 -0
  88. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/templates/profile.html +0 -0
  89. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/templates/settings.html +0 -0
  90. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/templates/stats.html +0 -0
  91. {clawed-2.3.0 → clawed-2.3.2}/clawed/api/templates/students.html +0 -0
  92. {clawed-2.3.0 → clawed-2.3.2}/clawed/assessment.py +0 -0
  93. {clawed-2.3.0 → clawed-2.3.2}/clawed/asset_registry.py +0 -0
  94. {clawed-2.3.0 → clawed-2.3.2}/clawed/auth/__init__.py +0 -0
  95. {clawed-2.3.0 → clawed-2.3.2}/clawed/auth/google_auth.py +0 -0
  96. {clawed-2.3.0 → clawed-2.3.2}/clawed/bot_state.py +0 -0
  97. {clawed-2.3.0 → clawed-2.3.2}/clawed/chat.py +0 -0
  98. {clawed-2.3.0 → clawed-2.3.2}/clawed/cli.py +0 -0
  99. {clawed-2.3.0 → clawed-2.3.2}/clawed/cli_chat.py +0 -0
  100. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/__init__.py +0 -0
  101. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/_helpers.py +0 -0
  102. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/bot.py +0 -0
  103. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/config.py +0 -0
  104. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/config_llm.py +0 -0
  105. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/config_profile.py +0 -0
  106. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/export.py +0 -0
  107. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/generate.py +0 -0
  108. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/generate_assessment.py +0 -0
  109. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/generate_unit.py +0 -0
  110. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/queue.py +0 -0
  111. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/schedule_cmd.py +0 -0
  112. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/sub.py +0 -0
  113. {clawed-2.3.0 → clawed-2.3.2}/clawed/commands/workspace_cmd.py +0 -0
  114. {clawed-2.3.0 → clawed-2.3.2}/clawed/config.py +0 -0
  115. {clawed-2.3.0 → clawed-2.3.2}/clawed/corpus.py +0 -0
  116. {clawed-2.3.0 → clawed-2.3.2}/clawed/curriculum_map.py +0 -0
  117. {clawed-2.3.0 → clawed-2.3.2}/clawed/database.py +0 -0
  118. {clawed-2.3.0 → clawed-2.3.2}/clawed/demo/__init__.py +0 -0
  119. {clawed-2.3.0 → clawed-2.3.2}/clawed/demo/demo_assessment.json +0 -0
  120. {clawed-2.3.0 → clawed-2.3.2}/clawed/demo/demo_lesson_science_g6.json +0 -0
  121. {clawed-2.3.0 → clawed-2.3.2}/clawed/demo/demo_lesson_social_studies_g8.json +0 -0
  122. {clawed-2.3.0 → clawed-2.3.2}/clawed/demo/demo_unit_plan.json +0 -0
  123. {clawed-2.3.0 → clawed-2.3.2}/clawed/differentiation.py +0 -0
  124. {clawed-2.3.0 → clawed-2.3.2}/clawed/doc_export.py +0 -0
  125. {clawed-2.3.0 → clawed-2.3.2}/clawed/drive.py +0 -0
  126. {clawed-2.3.0 → clawed-2.3.2}/clawed/evaluation.py +0 -0
  127. {clawed-2.3.0 → clawed-2.3.2}/clawed/export_docx.py +0 -0
  128. {clawed-2.3.0 → clawed-2.3.2}/clawed/export_handout.py +0 -0
  129. {clawed-2.3.0 → clawed-2.3.2}/clawed/export_markdown.py +0 -0
  130. {clawed-2.3.0 → clawed-2.3.2}/clawed/export_pdf.py +0 -0
  131. {clawed-2.3.0 → clawed-2.3.2}/clawed/export_templates.py +0 -0
  132. {clawed-2.3.0 → clawed-2.3.2}/clawed/export_theme.py +0 -0
  133. {clawed-2.3.0 → clawed-2.3.2}/clawed/exporter.py +0 -0
  134. {clawed-2.3.0 → clawed-2.3.2}/clawed/feedback.py +0 -0
  135. {clawed-2.3.0 → clawed-2.3.2}/clawed/formats/__init__.py +0 -0
  136. {clawed-2.3.0 → clawed-2.3.2}/clawed/formats/flipchart.py +0 -0
  137. {clawed-2.3.0 → clawed-2.3.2}/clawed/formats/notebook.py +0 -0
  138. {clawed-2.3.0 → clawed-2.3.2}/clawed/formats/xbk.py +0 -0
  139. {clawed-2.3.0 → clawed-2.3.2}/clawed/gateway.py +0 -0
  140. {clawed-2.3.0 → clawed-2.3.2}/clawed/gateway_response.py +0 -0
  141. {clawed-2.3.0 → clawed-2.3.2}/clawed/generation.py +0 -0
  142. {clawed-2.3.0 → clawed-2.3.2}/clawed/handlers/__init__.py +0 -0
  143. {clawed-2.3.0 → clawed-2.3.2}/clawed/handlers/export.py +0 -0
  144. {clawed-2.3.0 → clawed-2.3.2}/clawed/handlers/feedback.py +0 -0
  145. {clawed-2.3.0 → clawed-2.3.2}/clawed/handlers/gaps.py +0 -0
  146. {clawed-2.3.0 → clawed-2.3.2}/clawed/handlers/generate.py +0 -0
  147. {clawed-2.3.0 → clawed-2.3.2}/clawed/handlers/ingest.py +0 -0
  148. {clawed-2.3.0 → clawed-2.3.2}/clawed/handlers/misc.py +0 -0
  149. {clawed-2.3.0 → clawed-2.3.2}/clawed/handlers/onboard.py +0 -0
  150. {clawed-2.3.0 → clawed-2.3.2}/clawed/handlers/schedule.py +0 -0
  151. {clawed-2.3.0 → clawed-2.3.2}/clawed/handlers/standards.py +0 -0
  152. {clawed-2.3.0 → clawed-2.3.2}/clawed/improver.py +0 -0
  153. {clawed-2.3.0 → clawed-2.3.2}/clawed/ingestor.py +0 -0
  154. {clawed-2.3.0 → clawed-2.3.2}/clawed/io.py +0 -0
  155. {clawed-2.3.0 → clawed-2.3.2}/clawed/lesson.py +0 -0
  156. {clawed-2.3.0 → clawed-2.3.2}/clawed/llm.py +0 -0
  157. {clawed-2.3.0 → clawed-2.3.2}/clawed/materials.py +0 -0
  158. {clawed-2.3.0 → clawed-2.3.2}/clawed/mcp_server.py +0 -0
  159. {clawed-2.3.0 → clawed-2.3.2}/clawed/memory_engine.py +0 -0
  160. {clawed-2.3.0 → clawed-2.3.2}/clawed/model_router.py +0 -0
  161. {clawed-2.3.0 → clawed-2.3.2}/clawed/models.py +0 -0
  162. {clawed-2.3.0 → clawed-2.3.2}/clawed/openclaw_plugin.py +0 -0
  163. {clawed-2.3.0 → clawed-2.3.2}/clawed/parent_comm.py +0 -0
  164. {clawed-2.3.0 → clawed-2.3.2}/clawed/persona.py +0 -0
  165. {clawed-2.3.0 → clawed-2.3.2}/clawed/planner.py +0 -0
  166. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/504_accommodations.txt +0 -0
  167. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/admin_lesson_plan.txt +0 -0
  168. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/assessment.txt +0 -0
  169. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/curriculum_gaps.txt +0 -0
  170. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/dbq_assessment.txt +0 -0
  171. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/differentiation.txt +0 -0
  172. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/formative_assessment.txt +0 -0
  173. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/iep_modification.txt +0 -0
  174. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/lesson_plan.txt +0 -0
  175. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/pacing_guide.txt +0 -0
  176. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/parent_note.txt +0 -0
  177. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/persona_extract.txt +0 -0
  178. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/quiz.txt +0 -0
  179. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/rubric.txt +0 -0
  180. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/student_packet.txt +0 -0
  181. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/sub_packet.txt +0 -0
  182. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/summative_assessment.txt +0 -0
  183. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/tiered_assignments.txt +0 -0
  184. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/unit_plan.txt +0 -0
  185. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/worksheet.txt +0 -0
  186. {clawed-2.3.0 → clawed-2.3.2}/clawed/prompts/year_map.txt +0 -0
  187. {clawed-2.3.0 → clawed-2.3.2}/clawed/quality.py +0 -0
  188. {clawed-2.3.0 → clawed-2.3.2}/clawed/reading_report.py +0 -0
  189. {clawed-2.3.0 → clawed-2.3.2}/clawed/router.py +0 -0
  190. {clawed-2.3.0 → clawed-2.3.2}/clawed/sanitize.py +0 -0
  191. {clawed-2.3.0 → clawed-2.3.2}/clawed/scheduler.py +0 -0
  192. {clawed-2.3.0 → clawed-2.3.2}/clawed/school.py +0 -0
  193. {clawed-2.3.0 → clawed-2.3.2}/clawed/search.py +0 -0
  194. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/__init__.py +0 -0
  195. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/art.py +0 -0
  196. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/base.py +0 -0
  197. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/computer_science.py +0 -0
  198. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/ela.py +0 -0
  199. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/foreign_language.py +0 -0
  200. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/history.py +0 -0
  201. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/library.py +0 -0
  202. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/math.py +0 -0
  203. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/music.py +0 -0
  204. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/physical_education.py +0 -0
  205. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/science.py +0 -0
  206. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/social_studies.py +0 -0
  207. {clawed-2.3.0 → clawed-2.3.2}/clawed/skills/special_education.py +0 -0
  208. {clawed-2.3.0 → clawed-2.3.2}/clawed/slide_images.py +0 -0
  209. {clawed-2.3.0 → clawed-2.3.2}/clawed/standards.py +0 -0
  210. {clawed-2.3.0 → clawed-2.3.2}/clawed/state.py +0 -0
  211. {clawed-2.3.0 → clawed-2.3.2}/clawed/state_standards.py +0 -0
  212. {clawed-2.3.0 → clawed-2.3.2}/clawed/student_bot.py +0 -0
  213. {clawed-2.3.0 → clawed-2.3.2}/clawed/student_cli.py +0 -0
  214. {clawed-2.3.0 → clawed-2.3.2}/clawed/student_telegram_bot.py +0 -0
  215. {clawed-2.3.0 → clawed-2.3.2}/clawed/sub_packet.py +0 -0
  216. {clawed-2.3.0 → clawed-2.3.2}/clawed/task_queue.py +0 -0
  217. {clawed-2.3.0 → clawed-2.3.2}/clawed/templates_lib.py +0 -0
  218. {clawed-2.3.0 → clawed-2.3.2}/clawed/tools.py +0 -0
  219. {clawed-2.3.0 → clawed-2.3.2}/clawed/transports/__init__.py +0 -0
  220. {clawed-2.3.0 → clawed-2.3.2}/clawed/transports/cli.py +0 -0
  221. {clawed-2.3.0 → clawed-2.3.2}/clawed/transports/openclaw.py +0 -0
  222. {clawed-2.3.0 → clawed-2.3.2}/clawed/transports/student_telegram.py +0 -0
  223. {clawed-2.3.0 → clawed-2.3.2}/clawed/transports/telegram.py +0 -0
  224. {clawed-2.3.0 → clawed-2.3.2}/clawed/transports/web.py +0 -0
  225. {clawed-2.3.0 → clawed-2.3.2}/clawed/tui.py +0 -0
  226. {clawed-2.3.0 → clawed-2.3.2}/clawed/tui_chat.py +0 -0
  227. {clawed-2.3.0 → clawed-2.3.2}/clawed/voice.py +0 -0
  228. {clawed-2.3.0 → clawed-2.3.2}/clawed/workspace.py +0 -0
  229. {clawed-2.3.0 → clawed-2.3.2}/eduagent/__init__.py +0 -0
  230. {clawed-2.3.0 → clawed-2.3.2}/eduagent/_compat.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clawed
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Claw-ED — personal AI teaching agent. Learns your voice, works while you sleep.
5
5
  Project-URL: Homepage, https://github.com/SirhanMacx/Claw-ED
6
6
  Project-URL: Documentation, https://github.com/SirhanMacx/Claw-ED#readme
@@ -17,7 +17,7 @@ if hasattr(sys.stderr, "reconfigure"):
17
17
  except Exception:
18
18
  pass
19
19
 
20
- __version__ = "2.3.0"
20
+ __version__ = "2.3.2"
21
21
  __author__ = "Jon Maccarello & Claw-ED contributors"
22
22
  __description__ = "Personal AI teaching agent. Learns your voice, works while you sleep."
23
23
 
@@ -455,7 +455,7 @@ def export_lesson_pptx(
455
455
 
456
456
  # Lesson title -- 44pt white bold, centered
457
457
  tb = slide.shapes.add_textbox(
458
- Inches(1.5), Inches(2.0), slide_w - Inches(3.0), Inches(2.5),
458
+ Inches(1.5), Inches(1.5), slide_w - Inches(3.0), Inches(2.5),
459
459
  )
460
460
  tf = tb.text_frame
461
461
  tf.word_wrap = True
@@ -465,9 +465,30 @@ def export_lesson_pptx(
465
465
  run.text = lesson.title
466
466
  _set_text_props(run, 44, theme["text_light"], bold=True)
467
467
 
468
- # Subtitle: "Lesson N | Teacher Name | Date" -- 20pt white
468
+ # Aim -- the driving question, centered below title
469
+ aim_text = lesson.objective
470
+ if aim_text and not aim_text.lower().startswith("students will"):
471
+ aim_display = f"Aim: {aim_text}"
472
+ elif aim_text:
473
+ aim_display = aim_text
474
+ else:
475
+ aim_display = ""
476
+ if aim_display:
477
+ tb_aim = slide.shapes.add_textbox(
478
+ Inches(1.5), Inches(4.0), slide_w - Inches(3.0), Inches(1.0),
479
+ )
480
+ tf_aim = tb_aim.text_frame
481
+ tf_aim.word_wrap = True
482
+ p_aim = tf_aim.paragraphs[0]
483
+ p_aim.alignment = PP_ALIGN.CENTER
484
+ run_aim = p_aim.add_run()
485
+ run_aim.text = aim_display
486
+ _set_text_props(run_aim, 20, "EEEEEE")
487
+ run_aim.font.italic = True
488
+
489
+ # Subtitle: "Teacher Name | Date" -- 16pt
469
490
  tb2 = slide.shapes.add_textbox(
470
- Inches(1.5), Inches(4.8), slide_w - Inches(3.0), Inches(1.0),
491
+ Inches(1.5), Inches(5.2), slide_w - Inches(3.0), Inches(0.8),
471
492
  )
472
493
  tf2 = tb2.text_frame
473
494
  tf2.word_wrap = True
@@ -475,11 +496,10 @@ def export_lesson_pptx(
475
496
  p2.alignment = PP_ALIGN.CENTER
476
497
  run2 = p2.add_run()
477
498
  run2.text = (
478
- f"Lesson {lesson.lesson_number} | "
479
499
  f"{teacher_display_name} | "
480
500
  f"{date.today().strftime('%B %d, %Y')}"
481
501
  )
482
- _set_text_props(run2, 20, "DDDDDD")
502
+ _set_text_props(run2, 16, "BBBBBB")
483
503
 
484
504
  # Bottom accent bar in subject color
485
505
  _bar(slide, Emu(0), slide_h - Inches(0.15), slide_w, Inches(0.15), theme["secondary"])
@@ -535,7 +555,7 @@ def export_lesson_pptx(
535
555
  run.text = "Standards Addressed"
536
556
  _set_text_props(run, 16, "888888", bold=True)
537
557
 
538
- for std in lesson.standards[:5]:
558
+ for std in lesson.standards[:3]:
539
559
  p = tf.add_paragraph()
540
560
  p.space_before = Pt(6)
541
561
  run = p.add_run()
@@ -577,9 +597,22 @@ def export_lesson_pptx(
577
597
  p = tf.paragraphs[0]
578
598
  p.line_spacing = Pt(38)
579
599
  run = p.add_run()
580
- run.text = lesson.do_now
600
+ # Brief prompt on slide face, full text in speaker notes
601
+ dn_text = lesson.do_now
602
+ if len(dn_text) > 250:
603
+ cutoff = dn_text[:250].rfind(". ")
604
+ dn_display = dn_text[:cutoff + 1] if cutoff > 80 else dn_text[:250].rsplit(" ", 1)[0] + "..."
605
+ else:
606
+ dn_display = dn_text
607
+ run.text = dn_display
581
608
  _set_text_props(run, 28, theme["text_dark"])
582
609
 
610
+ # Full Do Now in speaker notes
611
+ if len(dn_text) > 250:
612
+ notes_slide = slide.notes_slide
613
+ notes_tf = notes_slide.notes_text_frame
614
+ notes_tf.text = dn_text
615
+
583
616
  if do_now_img:
584
617
  from clawed.slide_images import _extract_key_concepts
585
618
  concepts = _extract_key_concepts(lesson.do_now)
@@ -663,41 +696,45 @@ def export_lesson_pptx(
663
696
 
664
697
  _add_footer(slide, slide_num[0])
665
698
 
666
- # ── Vocabulary slide (if terms detected) ───────────────────
667
- # Try multiple patterns for vocabulary extraction
668
- di_text_raw = lesson.direct_instruction or ""
669
- vocab_patterns: list[tuple[str, str]] = []
670
-
671
- # Pattern 1: **Bold Term** definition
672
- vocab_patterns = re.findall(
673
- r'\*\*([A-Z][^*]{2,30})\*\*\s*[-—:]+\s*([^*\n]{15,200})',
674
- di_text_raw,
675
- )
676
- # Pattern 2: KEY TERM: definition or Term: definition (capitalized)
677
- if not vocab_patterns:
699
+ # ── Vocabulary slide ───────────────────────────────────────
700
+ # Prefer structured vocabulary from v2.3 model fields
701
+ vocab_pairs: list[tuple[str, str]] = []
702
+ if hasattr(lesson, "vocabulary") and lesson.vocabulary:
703
+ for vt in lesson.vocabulary:
704
+ term = getattr(vt, "term", "") if hasattr(vt, "term") else vt.get("term", "")
705
+ defn = getattr(vt, "definition", "") if hasattr(vt, "definition") else vt.get("definition", "")
706
+ if term and defn:
707
+ vocab_pairs.append((term, defn))
708
+
709
+ # Fallback: regex extraction from DI text
710
+ if not vocab_pairs:
711
+ di_text_raw = lesson.direct_instruction or ""
678
712
  vocab_patterns = re.findall(
679
- r'(?:^|\n)\s*\*?\*?([A-Z][a-z]+(?:\s+[A-Za-z]+){0,3})\*?\*?\s*[-—:]+\s+'
680
- r'([A-Za-z][^\n]{15,200})',
713
+ r'\*\*([A-Z][^*]{2,30})\*\*\s*[-—:]+\s*([^*\n]{15,200})',
681
714
  di_text_raw,
682
715
  )
683
-
684
- # Filter out instructional directions and non-vocabulary content
685
- INSTRUCTIONAL_WORDS = {
686
- "check", "ask", "call", "facilitate", "transition", "minutes",
687
- "discuss", "display", "distribute", "brief", "move", "moved",
688
- "students", "responses", "excellent", "turn", "now", "let",
689
- "today", "good", "morning", "scholars", "friends", "class",
690
- "next", "first", "take", "look", "read", "write", "complete",
691
- }
692
- vocab_patterns = [
693
- (term.strip(), defn.strip()) for term, defn in vocab_patterns
694
- if 1 <= len(term.split()) <= 4
695
- and len(defn.split()) >= 3
696
- and not any(w in defn.lower().split()[:3] for w in INSTRUCTIONAL_WORDS)
697
- and not any(w in term.lower().split() for w in INSTRUCTIONAL_WORDS)
698
- ]
699
-
700
- if vocab_patterns:
716
+ if not vocab_patterns:
717
+ vocab_patterns = re.findall(
718
+ r'(?:^|\n)\s*\*?\*?([A-Z][a-z]+(?:\s+[A-Za-z]+){0,3})\*?\*?\s*[-—:]+\s+'
719
+ r'([A-Za-z][^\n]{15,200})',
720
+ di_text_raw,
721
+ )
722
+ INSTRUCTIONAL_WORDS = {
723
+ "check", "ask", "call", "facilitate", "transition", "minutes",
724
+ "discuss", "display", "distribute", "brief", "move", "moved",
725
+ "students", "responses", "excellent", "turn", "now", "let",
726
+ "today", "good", "morning", "scholars", "friends", "class",
727
+ "next", "first", "take", "look", "read", "write", "complete",
728
+ }
729
+ vocab_pairs = [
730
+ (term.strip(), defn.strip()) for term, defn in vocab_patterns
731
+ if 1 <= len(term.split()) <= 4
732
+ and len(defn.split()) >= 3
733
+ and not any(w in defn.lower().split()[:3] for w in INSTRUCTIONAL_WORDS)
734
+ and not any(w in term.lower().split() for w in INSTRUCTIONAL_WORDS)
735
+ ]
736
+
737
+ if vocab_pairs:
701
738
  slide = _next_slide()
702
739
  _white_bg(slide)
703
740
 
@@ -724,7 +761,7 @@ def export_lesson_pptx(
724
761
  tf = tb.text_frame
725
762
  tf.word_wrap = True
726
763
 
727
- for idx, (term, definition) in enumerate(vocab_patterns[:8]):
764
+ for idx, (term, definition) in enumerate(vocab_pairs[:8]):
728
765
  p = tf.paragraphs[0] if idx == 0 else tf.add_paragraph()
729
766
  p.space_before = Pt(10)
730
767
  p.line_spacing = Pt(36)
@@ -808,7 +845,11 @@ def export_lesson_pptx(
808
845
  # SECTION DIVIDER: "Let's Practice Together"
809
846
  # ═══════════════════════════════════════════════════════════════════
810
847
  if lesson.guided_practice:
811
- _section_divider(prs, slide_num, "Let's Practice Together", theme, slide_w, slide_h)
848
+ gp_min = lesson.time_estimates.get("guided_practice", 15)
849
+ _section_divider(
850
+ prs, slide_num, f"Let's Practice Together\n({gp_min} minutes)",
851
+ theme, slide_w, slide_h,
852
+ )
812
853
 
813
854
  # ═══════════════════════════════════════════════════════════════════
814
855
  # GUIDED PRACTICE -- "Your Turn" header
@@ -832,7 +873,16 @@ def export_lesson_pptx(
832
873
 
833
874
  # No image on Guided Practice -- keep clean for readability
834
875
 
835
- # Activity instructions -- 24pt
876
+ # Brief student-facing instructions on slide face (first 2-3 sentences)
877
+ gp_text = lesson.guided_practice
878
+ gp_summary = gp_text
879
+ if len(gp_text) > 250:
880
+ cutoff = gp_text[:250].rfind(". ")
881
+ if cutoff > 80:
882
+ gp_summary = gp_text[:cutoff + 1]
883
+ else:
884
+ gp_summary = gp_text[:250].rsplit(" ", 1)[0] + "..."
885
+
836
886
  tb = slide.shapes.add_textbox(
837
887
  Inches(0.8), Inches(1.8), slide_w - Inches(2.0), Inches(4.5),
838
888
  )
@@ -841,9 +891,14 @@ def export_lesson_pptx(
841
891
  p = tf.paragraphs[0]
842
892
  p.line_spacing = Pt(34)
843
893
  run = p.add_run()
844
- run.text = lesson.guided_practice
894
+ run.text = gp_summary
845
895
  _set_text_props(run, 24, theme["text_dark"])
846
896
 
897
+ # Full guided practice in speaker notes
898
+ notes_slide = slide.notes_slide
899
+ notes_tf = notes_slide.notes_text_frame
900
+ notes_tf.text = gp_text
901
+
847
902
  # Time estimate
848
903
  minutes = lesson.time_estimates.get("guided_practice", 15)
849
904
  tb_time = slide.shapes.add_textbox(
@@ -883,7 +938,16 @@ def export_lesson_pptx(
883
938
 
884
939
  # No image on Independent Work -- keep clean for readability
885
940
 
886
- # Task description -- 24pt
941
+ # Brief student-facing instructions on slide face
942
+ iw_text = lesson.independent_work
943
+ iw_summary = iw_text
944
+ if len(iw_text) > 250:
945
+ cutoff = iw_text[:250].rfind(". ")
946
+ if cutoff > 80:
947
+ iw_summary = iw_text[:cutoff + 1]
948
+ else:
949
+ iw_summary = iw_text[:250].rsplit(" ", 1)[0] + "..."
950
+
887
951
  tb = slide.shapes.add_textbox(
888
952
  Inches(1.0), Inches(1.8), slide_w - Inches(2.0), Inches(4.5),
889
953
  )
@@ -892,9 +956,14 @@ def export_lesson_pptx(
892
956
  p = tf.paragraphs[0]
893
957
  p.line_spacing = Pt(34)
894
958
  run = p.add_run()
895
- run.text = lesson.independent_work
959
+ run.text = iw_summary
896
960
  _set_text_props(run, 24, theme["text_dark"])
897
961
 
962
+ # Full independent work in speaker notes
963
+ notes_slide = slide.notes_slide
964
+ notes_tf = notes_slide.notes_text_frame
965
+ notes_tf.text = iw_text
966
+
898
967
  # Time estimate in corner
899
968
  minutes = lesson.time_estimates.get("independent_work", 10)
900
969
  _rounded_card(
@@ -919,7 +988,7 @@ def export_lesson_pptx(
919
988
  # SECTION DIVIDER: "Show What You Know"
920
989
  # ═══════════════════════════════════════════════════════════════════
921
990
  if lesson.exit_ticket:
922
- _section_divider(prs, slide_num, "Show What You Know", theme, slide_w, slide_h)
991
+ _section_divider(prs, slide_num, "Show What You Know\n(Exit Ticket)", theme, slide_w, slide_h)
923
992
 
924
993
  # ═══════════════════════════════════════════════════════════════════
925
994
  # EXIT TICKET -- distinctive assessment design
@@ -972,7 +1041,11 @@ def export_lesson_pptx(
972
1041
  tf = tb.text_frame
973
1042
  tf.word_wrap = True
974
1043
  run = tf.paragraphs[0].add_run()
975
- run.text = q.question
1044
+ # Truncate long questions for slide readability
1045
+ q_text = q.question
1046
+ if len(q_text) > 120:
1047
+ q_text = q_text[:120].rsplit(" ", 1)[0] + "..."
1048
+ run.text = q_text
976
1049
  _set_text_props(run, 20, theme["text_dark"])
977
1050
 
978
1051
  q_top += Inches(1.3)
@@ -1025,8 +1098,19 @@ def export_lesson_pptx(
1025
1098
  p = tf.paragraphs[0]
1026
1099
  p.line_spacing = Pt(30)
1027
1100
  run = p.add_run()
1028
- run.text = lesson.homework
1101
+ # Brief homework summary on slide, full in notes
1102
+ hw_text = lesson.homework
1103
+ if len(hw_text) > 200:
1104
+ cutoff = hw_text[:200].rfind(". ")
1105
+ hw_display = hw_text[:cutoff + 1] if cutoff > 60 else hw_text[:200].rsplit(" ", 1)[0] + "..."
1106
+ else:
1107
+ hw_display = hw_text
1108
+ run.text = hw_display
1029
1109
  _set_text_props(run, 22, "DDDDDD")
1110
+ if len(hw_text) > 200:
1111
+ notes_slide = slide.notes_slide
1112
+ notes_tf = notes_slide.notes_text_frame
1113
+ notes_tf.text = f"HOMEWORK (full text):\n{hw_text}"
1030
1114
  else:
1031
1115
  # "Key Takeaway" or "Questions?"
1032
1116
  tb = slide.shapes.add_textbox(
@@ -73,22 +73,35 @@ def _ask_provider() -> tuple[LLMProvider, str | None]:
73
73
  table.add_column("Provider")
74
74
  table.add_column("Cost")
75
75
  table.add_column("Notes")
76
- table.add_row("1", "Anthropic (Claude)", "Pay per token", "Best quality")
77
- table.add_row("2", "OpenAI (GPT-4o)", "Pay per token", "Widely used")
78
- table.add_row("3", "Ollama", "Free", "Runs locally \u2014 no API key needed")
76
+ table.add_row("1", "Google Gemini", "Free tier available", "Best for getting started \u2014 generous free quota")
77
+ table.add_row("2", "Anthropic (Claude)", "Pay per token", "Highest quality")
78
+ table.add_row("3", "OpenAI (GPT-4o)", "Pay per token", "Widely used")
79
+ table.add_row("4", "Ollama (local)", "Free", "Runs on your machine \u2014 no internet needed")
79
80
  console.print()
80
81
  console.print(table)
81
82
 
82
83
  while True:
83
- choice = Prompt.ask("\n[bold]Pick a provider[/bold]", choices=["1", "2", "3"], default="1")
84
+ choice = Prompt.ask(
85
+ "\n[bold]Pick a provider[/bold]", choices=["1", "2", "3", "4"], default="1",
86
+ )
84
87
  if choice == "1":
88
+ provider = LLMProvider.GOOGLE
89
+ console.print(
90
+ "\n [dim]Get a free API key at: https://aistudio.google.com/apikey[/dim]",
91
+ )
92
+ key = Prompt.ask(" [bold]Google AI API key[/bold] [dim](AIza...)[/dim]")
93
+ if not key.strip():
94
+ console.print(" [red]API key cannot be empty.[/red]")
95
+ continue
96
+ return provider, key.strip()
97
+ elif choice == "2":
85
98
  provider = LLMProvider.ANTHROPIC
86
99
  key = Prompt.ask(" [bold]Anthropic API key[/bold] [dim](sk-ant-...)[/dim]")
87
100
  if not key.strip():
88
101
  console.print(" [red]API key cannot be empty.[/red]")
89
102
  continue
90
103
  return provider, key.strip()
91
- elif choice == "2":
104
+ elif choice == "3":
92
105
  provider = LLMProvider.OPENAI
93
106
  key = Prompt.ask(" [bold]OpenAI API key[/bold] [dim](sk-...)[/dim]")
94
107
  if not key.strip():
@@ -126,6 +139,10 @@ def _detect_available_models() -> tuple[LLMProvider | None, str]:
126
139
  and Ollama running locally.
127
140
  Returns (provider, description) or (None, message).
128
141
  """
142
+ # Check Google Gemini (free tier)
143
+ if os.environ.get("GOOGLE_API_KEY"):
144
+ return LLMProvider.GOOGLE, "Google Gemini API key found in environment"
145
+
129
146
  # Check Anthropic
130
147
  if os.environ.get("ANTHROPIC_API_KEY"):
131
148
  return LLMProvider.ANTHROPIC, "Anthropic API key found in environment"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "clawed"
7
- version = "2.3.0"
7
+ version = "2.3.2"
8
8
  description = "Claw-ED — personal AI teaching agent. Learns your voice, works while you sleep."
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes