clawed 2.3.0__tar.gz → 2.3.1__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.
- {clawed-2.3.0 → clawed-2.3.1}/PKG-INFO +1 -1
- {clawed-2.3.0 → clawed-2.3.1}/clawed/__init__.py +1 -1
- {clawed-2.3.0 → clawed-2.3.1}/clawed/export_pptx.py +100 -44
- {clawed-2.3.0 → clawed-2.3.1}/clawed/onboarding.py +22 -5
- {clawed-2.3.0 → clawed-2.3.1}/pyproject.toml +1 -1
- {clawed-2.3.0 → clawed-2.3.1}/.gitignore +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/LICENSE +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/README.md +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/__main__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/_legacy_gateway.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/approvals.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/autonomy.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/context.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/core.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/custom_tools.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/drive/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/drive/auth.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/drive/client.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/fake_llm.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/loop.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/memory/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/memory/curriculum.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/memory/curriculum_kb.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/memory/embeddings.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/memory/episodes.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/memory/identity.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/memory/loader.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/memory/preferences.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/planner.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/prompt.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/scheduler.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/base.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/configure_profile.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/curriculum_map.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/drive_create_doc.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/drive_create_slides.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/drive_list.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/drive_organize.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/drive_read.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/drive_upload.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/export_document.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/gap_analysis.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/generate_assessment.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/generate_lesson.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/generate_lesson_bundle.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/generate_materials.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/generate_unit.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/ingest_materials.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/parent_comm.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/read_heartbeat.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/read_workspace.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/request_approval.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/schedule_task.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/search_lessons.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/search_my_materials.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/search_standards.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/student_insights.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/sub_packet.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/switch_model.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/agent_core/tools/update_soul.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/analytics.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/deps.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/chat.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/export.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/feedback.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/gateway_chat.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/generate.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/ingest.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/lessons.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/school.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/settings.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/routes/tools.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/server.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/static/app.js +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/static/style.css +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/static/widget.js +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/templates/analytics.html +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/templates/base.html +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/templates/dashboard.html +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/templates/generate.html +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/templates/index.html +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/templates/lesson.html +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/templates/profile.html +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/templates/settings.html +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/templates/stats.html +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/api/templates/students.html +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/assessment.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/asset_registry.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/auth/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/auth/google_auth.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/bot_state.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/chat.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/cli.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/cli_chat.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/_helpers.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/bot.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/config.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/config_llm.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/config_profile.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/export.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/generate.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/generate_assessment.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/generate_unit.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/queue.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/schedule_cmd.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/sub.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/commands/workspace_cmd.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/config.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/corpus.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/curriculum_map.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/database.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/demo/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/demo/demo_assessment.json +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/demo/demo_lesson_science_g6.json +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/demo/demo_lesson_social_studies_g8.json +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/demo/demo_unit_plan.json +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/differentiation.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/doc_export.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/drive.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/evaluation.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/export_docx.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/export_handout.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/export_markdown.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/export_pdf.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/export_templates.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/export_theme.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/exporter.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/feedback.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/formats/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/formats/flipchart.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/formats/notebook.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/formats/xbk.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/gateway.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/gateway_response.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/generation.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/handlers/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/handlers/export.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/handlers/feedback.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/handlers/gaps.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/handlers/generate.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/handlers/ingest.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/handlers/misc.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/handlers/onboard.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/handlers/schedule.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/handlers/standards.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/improver.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/ingestor.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/io.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/lesson.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/llm.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/materials.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/mcp_server.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/memory_engine.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/model_router.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/models.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/openclaw_plugin.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/parent_comm.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/persona.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/planner.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/504_accommodations.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/admin_lesson_plan.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/assessment.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/curriculum_gaps.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/dbq_assessment.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/differentiation.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/formative_assessment.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/iep_modification.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/lesson_plan.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/pacing_guide.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/parent_note.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/persona_extract.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/quiz.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/rubric.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/student_packet.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/sub_packet.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/summative_assessment.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/tiered_assignments.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/unit_plan.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/worksheet.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/prompts/year_map.txt +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/quality.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/reading_report.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/router.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/sanitize.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/scheduler.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/school.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/search.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/art.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/base.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/computer_science.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/ela.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/foreign_language.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/history.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/library.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/math.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/music.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/physical_education.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/science.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/social_studies.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/skills/special_education.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/slide_images.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/standards.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/state.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/state_standards.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/student_bot.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/student_cli.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/student_telegram_bot.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/sub_packet.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/task_queue.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/templates_lib.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/tools.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/transports/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/transports/cli.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/transports/openclaw.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/transports/student_telegram.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/transports/telegram.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/transports/web.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/tui.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/tui_chat.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/voice.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/clawed/workspace.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/eduagent/__init__.py +0 -0
- {clawed-2.3.0 → clawed-2.3.1}/eduagent/_compat.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clawed
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.1
|
|
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.
|
|
20
|
+
__version__ = "2.3.1"
|
|
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(
|
|
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
|
-
#
|
|
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(
|
|
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,
|
|
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"])
|
|
@@ -663,41 +683,45 @@ def export_lesson_pptx(
|
|
|
663
683
|
|
|
664
684
|
_add_footer(slide, slide_num[0])
|
|
665
685
|
|
|
666
|
-
# ── Vocabulary slide
|
|
667
|
-
#
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
#
|
|
677
|
-
if not
|
|
686
|
+
# ── Vocabulary slide ───────────────────────────────────────
|
|
687
|
+
# Prefer structured vocabulary from v2.3 model fields
|
|
688
|
+
vocab_pairs: list[tuple[str, str]] = []
|
|
689
|
+
if hasattr(lesson, "vocabulary") and lesson.vocabulary:
|
|
690
|
+
for vt in lesson.vocabulary:
|
|
691
|
+
term = getattr(vt, "term", "") if hasattr(vt, "term") else vt.get("term", "")
|
|
692
|
+
defn = getattr(vt, "definition", "") if hasattr(vt, "definition") else vt.get("definition", "")
|
|
693
|
+
if term and defn:
|
|
694
|
+
vocab_pairs.append((term, defn))
|
|
695
|
+
|
|
696
|
+
# Fallback: regex extraction from DI text
|
|
697
|
+
if not vocab_pairs:
|
|
698
|
+
di_text_raw = lesson.direct_instruction or ""
|
|
678
699
|
vocab_patterns = re.findall(
|
|
679
|
-
r'(
|
|
680
|
-
r'([A-Za-z][^\n]{15,200})',
|
|
700
|
+
r'\*\*([A-Z][^*]{2,30})\*\*\s*[-—:]+\s*([^*\n]{15,200})',
|
|
681
701
|
di_text_raw,
|
|
682
702
|
)
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
703
|
+
if not vocab_patterns:
|
|
704
|
+
vocab_patterns = re.findall(
|
|
705
|
+
r'(?:^|\n)\s*\*?\*?([A-Z][a-z]+(?:\s+[A-Za-z]+){0,3})\*?\*?\s*[-—:]+\s+'
|
|
706
|
+
r'([A-Za-z][^\n]{15,200})',
|
|
707
|
+
di_text_raw,
|
|
708
|
+
)
|
|
709
|
+
INSTRUCTIONAL_WORDS = {
|
|
710
|
+
"check", "ask", "call", "facilitate", "transition", "minutes",
|
|
711
|
+
"discuss", "display", "distribute", "brief", "move", "moved",
|
|
712
|
+
"students", "responses", "excellent", "turn", "now", "let",
|
|
713
|
+
"today", "good", "morning", "scholars", "friends", "class",
|
|
714
|
+
"next", "first", "take", "look", "read", "write", "complete",
|
|
715
|
+
}
|
|
716
|
+
vocab_pairs = [
|
|
717
|
+
(term.strip(), defn.strip()) for term, defn in vocab_patterns
|
|
718
|
+
if 1 <= len(term.split()) <= 4
|
|
719
|
+
and len(defn.split()) >= 3
|
|
720
|
+
and not any(w in defn.lower().split()[:3] for w in INSTRUCTIONAL_WORDS)
|
|
721
|
+
and not any(w in term.lower().split() for w in INSTRUCTIONAL_WORDS)
|
|
722
|
+
]
|
|
723
|
+
|
|
724
|
+
if vocab_pairs:
|
|
701
725
|
slide = _next_slide()
|
|
702
726
|
_white_bg(slide)
|
|
703
727
|
|
|
@@ -724,7 +748,7 @@ def export_lesson_pptx(
|
|
|
724
748
|
tf = tb.text_frame
|
|
725
749
|
tf.word_wrap = True
|
|
726
750
|
|
|
727
|
-
for idx, (term, definition) in enumerate(
|
|
751
|
+
for idx, (term, definition) in enumerate(vocab_pairs[:8]):
|
|
728
752
|
p = tf.paragraphs[0] if idx == 0 else tf.add_paragraph()
|
|
729
753
|
p.space_before = Pt(10)
|
|
730
754
|
p.line_spacing = Pt(36)
|
|
@@ -808,7 +832,11 @@ def export_lesson_pptx(
|
|
|
808
832
|
# SECTION DIVIDER: "Let's Practice Together"
|
|
809
833
|
# ═══════════════════════════════════════════════════════════════════
|
|
810
834
|
if lesson.guided_practice:
|
|
811
|
-
|
|
835
|
+
gp_min = lesson.time_estimates.get("guided_practice", 15)
|
|
836
|
+
_section_divider(
|
|
837
|
+
prs, slide_num, f"Let's Practice Together\n({gp_min} minutes)",
|
|
838
|
+
theme, slide_w, slide_h,
|
|
839
|
+
)
|
|
812
840
|
|
|
813
841
|
# ═══════════════════════════════════════════════════════════════════
|
|
814
842
|
# GUIDED PRACTICE -- "Your Turn" header
|
|
@@ -832,7 +860,16 @@ def export_lesson_pptx(
|
|
|
832
860
|
|
|
833
861
|
# No image on Guided Practice -- keep clean for readability
|
|
834
862
|
|
|
835
|
-
#
|
|
863
|
+
# Brief student-facing instructions on slide face (first 2-3 sentences)
|
|
864
|
+
gp_text = lesson.guided_practice
|
|
865
|
+
gp_summary = gp_text
|
|
866
|
+
if len(gp_text) > 250:
|
|
867
|
+
cutoff = gp_text[:250].rfind(". ")
|
|
868
|
+
if cutoff > 80:
|
|
869
|
+
gp_summary = gp_text[:cutoff + 1]
|
|
870
|
+
else:
|
|
871
|
+
gp_summary = gp_text[:250].rsplit(" ", 1)[0] + "..."
|
|
872
|
+
|
|
836
873
|
tb = slide.shapes.add_textbox(
|
|
837
874
|
Inches(0.8), Inches(1.8), slide_w - Inches(2.0), Inches(4.5),
|
|
838
875
|
)
|
|
@@ -841,9 +878,14 @@ def export_lesson_pptx(
|
|
|
841
878
|
p = tf.paragraphs[0]
|
|
842
879
|
p.line_spacing = Pt(34)
|
|
843
880
|
run = p.add_run()
|
|
844
|
-
run.text =
|
|
881
|
+
run.text = gp_summary
|
|
845
882
|
_set_text_props(run, 24, theme["text_dark"])
|
|
846
883
|
|
|
884
|
+
# Full guided practice in speaker notes
|
|
885
|
+
notes_slide = slide.notes_slide
|
|
886
|
+
notes_tf = notes_slide.notes_text_frame
|
|
887
|
+
notes_tf.text = gp_text
|
|
888
|
+
|
|
847
889
|
# Time estimate
|
|
848
890
|
minutes = lesson.time_estimates.get("guided_practice", 15)
|
|
849
891
|
tb_time = slide.shapes.add_textbox(
|
|
@@ -883,7 +925,16 @@ def export_lesson_pptx(
|
|
|
883
925
|
|
|
884
926
|
# No image on Independent Work -- keep clean for readability
|
|
885
927
|
|
|
886
|
-
#
|
|
928
|
+
# Brief student-facing instructions on slide face
|
|
929
|
+
iw_text = lesson.independent_work
|
|
930
|
+
iw_summary = iw_text
|
|
931
|
+
if len(iw_text) > 250:
|
|
932
|
+
cutoff = iw_text[:250].rfind(". ")
|
|
933
|
+
if cutoff > 80:
|
|
934
|
+
iw_summary = iw_text[:cutoff + 1]
|
|
935
|
+
else:
|
|
936
|
+
iw_summary = iw_text[:250].rsplit(" ", 1)[0] + "..."
|
|
937
|
+
|
|
887
938
|
tb = slide.shapes.add_textbox(
|
|
888
939
|
Inches(1.0), Inches(1.8), slide_w - Inches(2.0), Inches(4.5),
|
|
889
940
|
)
|
|
@@ -892,9 +943,14 @@ def export_lesson_pptx(
|
|
|
892
943
|
p = tf.paragraphs[0]
|
|
893
944
|
p.line_spacing = Pt(34)
|
|
894
945
|
run = p.add_run()
|
|
895
|
-
run.text =
|
|
946
|
+
run.text = iw_summary
|
|
896
947
|
_set_text_props(run, 24, theme["text_dark"])
|
|
897
948
|
|
|
949
|
+
# Full independent work in speaker notes
|
|
950
|
+
notes_slide = slide.notes_slide
|
|
951
|
+
notes_tf = notes_slide.notes_text_frame
|
|
952
|
+
notes_tf.text = iw_text
|
|
953
|
+
|
|
898
954
|
# Time estimate in corner
|
|
899
955
|
minutes = lesson.time_estimates.get("independent_work", 10)
|
|
900
956
|
_rounded_card(
|
|
@@ -919,7 +975,7 @@ def export_lesson_pptx(
|
|
|
919
975
|
# SECTION DIVIDER: "Show What You Know"
|
|
920
976
|
# ═══════════════════════════════════════════════════════════════════
|
|
921
977
|
if lesson.exit_ticket:
|
|
922
|
-
_section_divider(prs, slide_num, "Show What You Know", theme, slide_w, slide_h)
|
|
978
|
+
_section_divider(prs, slide_num, "Show What You Know\n(Exit Ticket)", theme, slide_w, slide_h)
|
|
923
979
|
|
|
924
980
|
# ═══════════════════════════════════════════════════════════════════
|
|
925
981
|
# EXIT TICKET -- distinctive assessment design
|
|
@@ -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", "
|
|
77
|
-
table.add_row("2", "
|
|
78
|
-
table.add_row("3", "
|
|
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(
|
|
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 == "
|
|
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"
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|