clawed 2.3.3__tar.gz → 2.3.4__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.3 → clawed-2.3.4}/PKG-INFO +1 -1
- {clawed-2.3.3 → clawed-2.3.4}/clawed/__init__.py +1 -1
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/prompt.py +5 -1
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/generate_lesson_bundle.py +4 -1
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/ingest_materials.py +57 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/generate.py +28 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/handlers/ingest.py +48 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/models.py +27 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/slide_images.py +26 -14
- {clawed-2.3.3 → clawed-2.3.4}/clawed/sub_packet.py +7 -0
- {clawed-2.3.3 → clawed-2.3.4}/pyproject.toml +1 -1
- {clawed-2.3.3 → clawed-2.3.4}/.gitignore +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/LICENSE +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/README.md +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/__main__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/_legacy_gateway.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/approvals.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/autonomy.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/context.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/core.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/custom_tools.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/drive/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/drive/auth.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/drive/client.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/fake_llm.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/loop.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/memory/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/memory/curriculum.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/memory/curriculum_kb.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/memory/embeddings.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/memory/episodes.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/memory/identity.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/memory/loader.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/memory/preferences.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/planner.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/scheduler.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/base.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/configure_profile.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/curriculum_map.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/drive_create_doc.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/drive_create_slides.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/drive_list.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/drive_organize.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/drive_read.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/drive_upload.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/export_document.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/gap_analysis.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/generate_assessment.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/generate_lesson.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/generate_materials.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/generate_unit.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/parent_comm.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/read_heartbeat.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/read_workspace.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/request_approval.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/schedule_task.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/search_lessons.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/search_my_materials.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/search_standards.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/student_insights.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/sub_packet.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/switch_model.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/agent_core/tools/update_soul.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/analytics.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/deps.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/chat.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/export.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/feedback.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/gateway_chat.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/generate.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/ingest.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/lessons.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/school.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/settings.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/routes/tools.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/server.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/static/app.js +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/static/style.css +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/static/widget.js +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/templates/analytics.html +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/templates/base.html +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/templates/dashboard.html +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/templates/generate.html +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/templates/index.html +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/templates/lesson.html +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/templates/profile.html +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/templates/settings.html +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/templates/stats.html +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/api/templates/students.html +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/assessment.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/asset_registry.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/auth/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/auth/google_auth.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/bot_state.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/chat.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/cli.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/cli_chat.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/_helpers.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/bot.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/config.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/config_llm.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/config_profile.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/export.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/generate_assessment.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/generate_unit.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/queue.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/schedule_cmd.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/sub.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/commands/workspace_cmd.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/config.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/corpus.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/curriculum_map.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/database.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/demo/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/demo/demo_assessment.json +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/demo/demo_lesson_science_g6.json +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/demo/demo_lesson_social_studies_g8.json +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/demo/demo_unit_plan.json +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/differentiation.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/doc_export.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/drive.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/evaluation.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/export_docx.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/export_handout.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/export_markdown.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/export_pdf.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/export_pptx.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/export_templates.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/export_theme.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/exporter.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/feedback.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/formats/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/formats/flipchart.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/formats/notebook.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/formats/xbk.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/gateway.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/gateway_response.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/generation.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/handlers/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/handlers/export.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/handlers/feedback.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/handlers/gaps.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/handlers/generate.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/handlers/misc.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/handlers/onboard.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/handlers/schedule.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/handlers/standards.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/improver.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/ingestor.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/io.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/lesson.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/llm.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/materials.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/mcp_server.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/memory_engine.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/model_router.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/onboarding.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/openclaw_plugin.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/parent_comm.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/persona.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/persona_evolution.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/planner.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/504_accommodations.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/admin_lesson_plan.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/assessment.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/curriculum_gaps.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/dbq_assessment.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/differentiation.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/formative_assessment.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/iep_modification.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/lesson_plan.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/pacing_guide.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/parent_note.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/persona_extract.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/quiz.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/rubric.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/student_packet.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/sub_packet.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/summative_assessment.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/tiered_assignments.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/unit_plan.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/worksheet.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/prompts/year_map.txt +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/quality.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/reading_report.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/router.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/sanitize.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/scheduler.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/school.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/search.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/art.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/base.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/computer_science.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/ela.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/foreign_language.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/history.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/library.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/math.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/music.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/physical_education.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/science.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/social_studies.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/skills/special_education.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/standards.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/state.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/state_standards.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/student_bot.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/student_cli.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/student_telegram_bot.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/task_queue.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/templates_lib.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/tools.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/transports/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/transports/cli.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/transports/openclaw.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/transports/student_telegram.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/transports/telegram.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/transports/web.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/tui.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/tui_chat.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/voice.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/voice_check.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/clawed/workspace.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/eduagent/__init__.py +0 -0
- {clawed-2.3.3 → clawed-2.3.4}/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.4
|
|
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.4"
|
|
21
21
|
__author__ = "Jon Maccarello & Claw-ED contributors"
|
|
22
22
|
__description__ = "Personal AI teaching agent. Learns your voice, works while you sleep."
|
|
23
23
|
|
|
@@ -91,7 +91,11 @@ def build_system_prompt(
|
|
|
91
91
|
" 'Building your lesson package now — plan, handout, and slides coming up.'\n"
|
|
92
92
|
"The teacher should always know you're working, not stuck.\n"
|
|
93
93
|
"1. Read SOUL.md to know your voice and values\n"
|
|
94
|
-
"2.
|
|
94
|
+
"2. **MANDATORY: Before calling generate_lesson_bundle, ALWAYS call "
|
|
95
|
+
"search_my_materials first** with the lesson topic. This is non-negotiable. "
|
|
96
|
+
"The teacher has uploaded materials — if you skip this step, you will "
|
|
97
|
+
"generate generic content instead of building on their prior work. "
|
|
98
|
+
"Tell the teacher what you found before generating.\n"
|
|
95
99
|
"3. Generate complete packages (lesson plan + student handout + slideshow) "
|
|
96
100
|
"using generate_lesson_bundle\n"
|
|
97
101
|
"4. Never ask 'want me to create materials?' -- just create them\n"
|
|
@@ -22,7 +22,10 @@ class GenerateLessonBundleTool:
|
|
|
22
22
|
"description": (
|
|
23
23
|
"Generate a COMPLETE teaching package for a topic: "
|
|
24
24
|
"a lesson plan (DOCX), a student handout (DOCX), and "
|
|
25
|
-
"a slideshow (PPTX). All three files are created at once."
|
|
25
|
+
"a slideshow (PPTX). All three files are created at once. "
|
|
26
|
+
"IMPORTANT: Always call search_my_materials FIRST to find "
|
|
27
|
+
"the teacher's existing materials on this topic before "
|
|
28
|
+
"calling this tool."
|
|
26
29
|
),
|
|
27
30
|
"parameters": {
|
|
28
31
|
"type": "object",
|
|
@@ -65,7 +65,31 @@ class IngestMaterialsTool:
|
|
|
65
65
|
from clawed.persona import extract_persona, save_persona
|
|
66
66
|
|
|
67
67
|
persona = await extract_persona(docs, context.config)
|
|
68
|
+
# Override LLM-inferred name with configured teacher name
|
|
69
|
+
try:
|
|
70
|
+
if context.config and context.config.teacher_profile and context.config.teacher_profile.name:
|
|
71
|
+
persona.name = f"{context.config.teacher_profile.name} Teaching Persona"
|
|
72
|
+
except Exception:
|
|
73
|
+
pass
|
|
74
|
+
try:
|
|
75
|
+
_id_path = Path.home() / ".eduagent" / "workspace" / "identity.md"
|
|
76
|
+
if _id_path.exists():
|
|
77
|
+
import re as _re
|
|
78
|
+
_id_content = _id_path.read_text(encoding="utf-8")
|
|
79
|
+
_name_match = _re.match(r"^#\s+(.+)", _id_content)
|
|
80
|
+
if _name_match:
|
|
81
|
+
_tname = _name_match.group(1).strip()
|
|
82
|
+
if _tname and _tname != "Teacher":
|
|
83
|
+
persona.name = f"{_tname} Teaching Persona"
|
|
84
|
+
except Exception:
|
|
85
|
+
pass
|
|
68
86
|
save_persona(persona, Path.home() / ".eduagent")
|
|
87
|
+
# Track persona changes for evolution
|
|
88
|
+
try:
|
|
89
|
+
from clawed.persona_evolution import record_ingestion_changes
|
|
90
|
+
record_ingestion_changes(old_persona=None, new_persona=persona)
|
|
91
|
+
except Exception:
|
|
92
|
+
pass
|
|
69
93
|
except Exception:
|
|
70
94
|
pass
|
|
71
95
|
|
|
@@ -129,6 +153,39 @@ class IngestMaterialsTool:
|
|
|
129
153
|
except Exception as e:
|
|
130
154
|
logger.debug("KB indexing failed: %s", e)
|
|
131
155
|
|
|
156
|
+
# Register assets for file-level search
|
|
157
|
+
try:
|
|
158
|
+
from clawed.asset_registry import AssetRegistry
|
|
159
|
+
registry = AssetRegistry()
|
|
160
|
+
asset_count = 0
|
|
161
|
+
for doc in docs:
|
|
162
|
+
doc_type_val = (
|
|
163
|
+
doc.doc_type.value
|
|
164
|
+
if hasattr(doc.doc_type, "value")
|
|
165
|
+
else str(doc.doc_type)
|
|
166
|
+
)
|
|
167
|
+
extraction = None
|
|
168
|
+
if doc.source_path:
|
|
169
|
+
try:
|
|
170
|
+
from clawed.ingestor import extract_rich
|
|
171
|
+
extraction = extract_rich(Path(doc.source_path))
|
|
172
|
+
except Exception:
|
|
173
|
+
pass
|
|
174
|
+
aid = registry.register_asset(
|
|
175
|
+
teacher_id=context.teacher_id,
|
|
176
|
+
source_path=doc.source_path or "",
|
|
177
|
+
title=doc.title,
|
|
178
|
+
doc_type=doc_type_val,
|
|
179
|
+
text=doc.content,
|
|
180
|
+
extraction=extraction,
|
|
181
|
+
)
|
|
182
|
+
if aid:
|
|
183
|
+
asset_count += 1
|
|
184
|
+
if asset_count:
|
|
185
|
+
summary += f" ({asset_count} files catalogued for search)"
|
|
186
|
+
except Exception as e:
|
|
187
|
+
logger.debug("Asset registration failed: %s", e)
|
|
188
|
+
|
|
132
189
|
# Update SOUL.md with what we learned
|
|
133
190
|
try:
|
|
134
191
|
soul_path = Path.home() / ".eduagent" / "workspace" / "SOUL.md"
|
|
@@ -130,8 +130,36 @@ def ingest(
|
|
|
130
130
|
persona = _run_async(extract_persona(documents))
|
|
131
131
|
progress.update(task, description="Persona extracted!")
|
|
132
132
|
|
|
133
|
+
# Override LLM-inferred name with configured teacher name
|
|
134
|
+
try:
|
|
135
|
+
cfg = AppConfig.load()
|
|
136
|
+
if cfg.teacher_profile and cfg.teacher_profile.name:
|
|
137
|
+
persona.name = f"{cfg.teacher_profile.name} Teaching Persona"
|
|
138
|
+
except Exception:
|
|
139
|
+
pass
|
|
140
|
+
# Also check identity.md
|
|
141
|
+
try:
|
|
142
|
+
identity_path = Path.home() / ".eduagent" / "workspace" / "identity.md"
|
|
143
|
+
if identity_path.exists():
|
|
144
|
+
import re
|
|
145
|
+
content = identity_path.read_text(encoding="utf-8")
|
|
146
|
+
name_match = re.match(r"^#\s+(.+)", content)
|
|
147
|
+
if name_match:
|
|
148
|
+
teacher_name = name_match.group(1).strip()
|
|
149
|
+
if teacher_name and teacher_name != "Teacher":
|
|
150
|
+
persona.name = f"{teacher_name} Teaching Persona"
|
|
151
|
+
except Exception:
|
|
152
|
+
pass
|
|
153
|
+
|
|
133
154
|
out = save_persona(persona, _output_dir())
|
|
134
155
|
|
|
156
|
+
# Track persona changes for evolution
|
|
157
|
+
try:
|
|
158
|
+
from clawed.persona_evolution import record_ingestion_changes
|
|
159
|
+
record_ingestion_changes(old_persona=None, new_persona=persona)
|
|
160
|
+
except Exception:
|
|
161
|
+
pass
|
|
162
|
+
|
|
135
163
|
# Index documents into curriculum knowledge base for KB search
|
|
136
164
|
kb_msg = ""
|
|
137
165
|
try:
|
|
@@ -60,6 +60,25 @@ class IngestHandler:
|
|
|
60
60
|
try:
|
|
61
61
|
from clawed.models import AppConfig
|
|
62
62
|
persona = await extract_persona(documents, AppConfig.load())
|
|
63
|
+
# Override LLM-inferred name with configured teacher name
|
|
64
|
+
try:
|
|
65
|
+
config = AppConfig.load()
|
|
66
|
+
if config.teacher_profile and config.teacher_profile.name:
|
|
67
|
+
persona.name = f"{config.teacher_profile.name} Teaching Persona"
|
|
68
|
+
except Exception:
|
|
69
|
+
pass
|
|
70
|
+
try:
|
|
71
|
+
_id_path = Path.home() / ".eduagent" / "workspace" / "identity.md"
|
|
72
|
+
if _id_path.exists():
|
|
73
|
+
import re as _re
|
|
74
|
+
_id_content = _id_path.read_text(encoding="utf-8")
|
|
75
|
+
_name_match = _re.match(r"^#\s+(.+)", _id_content)
|
|
76
|
+
if _name_match:
|
|
77
|
+
_tname = _name_match.group(1).strip()
|
|
78
|
+
if _tname and _tname != "Teacher":
|
|
79
|
+
persona.name = f"{_tname} Teaching Persona"
|
|
80
|
+
except Exception:
|
|
81
|
+
pass
|
|
63
82
|
from clawed.persona import save_persona
|
|
64
83
|
save_persona(persona, Path.home() / ".eduagent")
|
|
65
84
|
style_info = f"\nLearned teaching style: {persona.teaching_style}"
|
|
@@ -97,6 +116,35 @@ class IngestHandler:
|
|
|
97
116
|
except Exception as e:
|
|
98
117
|
logger.debug("KB indexing skipped: %s", e)
|
|
99
118
|
|
|
119
|
+
# Register assets (files, images, YouTube links) for search
|
|
120
|
+
try:
|
|
121
|
+
from clawed.asset_registry import AssetRegistry
|
|
122
|
+
registry = AssetRegistry()
|
|
123
|
+
asset_count = 0
|
|
124
|
+
for doc in documents:
|
|
125
|
+
doc_type_val = doc.doc_type.value if hasattr(doc.doc_type, "value") else str(doc.doc_type)
|
|
126
|
+
extraction = None
|
|
127
|
+
if doc.source_path:
|
|
128
|
+
try:
|
|
129
|
+
from clawed.ingestor import extract_rich
|
|
130
|
+
extraction = extract_rich(Path(doc.source_path))
|
|
131
|
+
except Exception:
|
|
132
|
+
pass
|
|
133
|
+
aid = registry.register_asset(
|
|
134
|
+
teacher_id=teacher_id,
|
|
135
|
+
source_path=doc.source_path or "",
|
|
136
|
+
title=doc.title,
|
|
137
|
+
doc_type=doc_type_val,
|
|
138
|
+
text=doc.content,
|
|
139
|
+
extraction=extraction,
|
|
140
|
+
)
|
|
141
|
+
if aid:
|
|
142
|
+
asset_count += 1
|
|
143
|
+
if asset_count:
|
|
144
|
+
kb_info += f" ({asset_count} files catalogued with images and links)"
|
|
145
|
+
except Exception as e:
|
|
146
|
+
logger.debug("Asset registration skipped: %s", e)
|
|
147
|
+
|
|
100
148
|
return GatewayResponse(
|
|
101
149
|
text=f"Ingested {len(documents)} document(s).{style_info}{kb_info}"
|
|
102
150
|
)
|
|
@@ -488,6 +488,15 @@ class WorksheetItem(BaseModel):
|
|
|
488
488
|
answer_key: str = ""
|
|
489
489
|
point_value: int = 1
|
|
490
490
|
|
|
491
|
+
@field_validator("point_value", mode="before")
|
|
492
|
+
@classmethod
|
|
493
|
+
def _coerce_point_value(cls, v):
|
|
494
|
+
if isinstance(v, str):
|
|
495
|
+
import re
|
|
496
|
+
match = re.match(r"(\d+)", v.strip())
|
|
497
|
+
return int(match.group(1)) if match else 1
|
|
498
|
+
return v
|
|
499
|
+
|
|
491
500
|
|
|
492
501
|
class AssessmentQuestion(BaseModel):
|
|
493
502
|
"""A single assessment question."""
|
|
@@ -499,6 +508,15 @@ class AssessmentQuestion(BaseModel):
|
|
|
499
508
|
correct_answer: str = ""
|
|
500
509
|
point_value: int = 1
|
|
501
510
|
|
|
511
|
+
@field_validator("point_value", mode="before")
|
|
512
|
+
@classmethod
|
|
513
|
+
def _coerce_point_value(cls, v):
|
|
514
|
+
if isinstance(v, str):
|
|
515
|
+
import re
|
|
516
|
+
match = re.match(r"(\d+)", v.strip())
|
|
517
|
+
return int(match.group(1)) if match else 1
|
|
518
|
+
return v
|
|
519
|
+
|
|
502
520
|
|
|
503
521
|
class RubricCriterion(BaseModel):
|
|
504
522
|
"""A single rubric criterion with levels."""
|
|
@@ -674,6 +692,15 @@ class SummativeQuestion(BaseModel):
|
|
|
674
692
|
point_value: int = 1
|
|
675
693
|
standard_aligned: str = ""
|
|
676
694
|
|
|
695
|
+
@field_validator("point_value", mode="before")
|
|
696
|
+
@classmethod
|
|
697
|
+
def _coerce_point_value(cls, v):
|
|
698
|
+
if isinstance(v, str):
|
|
699
|
+
import re
|
|
700
|
+
match = re.match(r"(\d+)", v.strip())
|
|
701
|
+
return int(match.group(1)) if match else 1
|
|
702
|
+
return v
|
|
703
|
+
|
|
677
704
|
|
|
678
705
|
class SummativeAssessment(BaseModel):
|
|
679
706
|
"""Unit test — mix of MC, short answer, DBQ/essay aligned to all unit objectives."""
|
|
@@ -253,16 +253,17 @@ def _select_sources(subject: str, topic: str = "") -> list[str]:
|
|
|
253
253
|
|
|
254
254
|
Returns an ordered list of source identifiers to try.
|
|
255
255
|
Teacher's own images are always checked first.
|
|
256
|
+
Only uses academic sources (LOC, Wikimedia). No stock photos.
|
|
256
257
|
"""
|
|
257
258
|
subject_lower = subject.strip().lower()
|
|
258
259
|
if any(s in subject_lower for s in ("history", "social", "civics", "government")):
|
|
259
|
-
return ["teacher_files", "loc", "wikimedia"
|
|
260
|
+
return ["teacher_files", "loc", "wikimedia"]
|
|
260
261
|
elif any(s in subject_lower for s in ("science", "biology", "chemistry", "physics")):
|
|
261
|
-
return ["teacher_files", "wikimedia", "loc"
|
|
262
|
+
return ["teacher_files", "wikimedia", "loc"]
|
|
262
263
|
elif any(s in subject_lower for s in ("art", "music")):
|
|
263
|
-
return ["teacher_files", "wikimedia", "loc"
|
|
264
|
+
return ["teacher_files", "wikimedia", "loc"]
|
|
264
265
|
else:
|
|
265
|
-
return ["teacher_files", "loc", "wikimedia"
|
|
266
|
+
return ["teacher_files", "loc", "wikimedia"]
|
|
266
267
|
|
|
267
268
|
|
|
268
269
|
# ── Cache helpers ────────────────────────────────────────────────────
|
|
@@ -497,14 +498,25 @@ async def _fetch_teacher_image(
|
|
|
497
498
|
|
|
498
499
|
with sqlite3.connect(db_path) as conn:
|
|
499
500
|
conn.row_factory = sqlite3.Row
|
|
500
|
-
#
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
501
|
+
# Pre-filter by topic keywords in SQL for efficiency
|
|
502
|
+
if keywords:
|
|
503
|
+
like_clauses = " OR ".join(
|
|
504
|
+
"(lower(ai.context_text) LIKE '%' || ? || '%' OR lower(a.title) LIKE '%' || ? || '%')"
|
|
505
|
+
for _ in keywords[:5]
|
|
506
|
+
)
|
|
507
|
+
params = []
|
|
508
|
+
for kw in keywords[:5]:
|
|
509
|
+
params.extend([kw, kw])
|
|
510
|
+
rows = conn.execute(
|
|
511
|
+
f"SELECT ai.image_path, ai.context_text, a.title "
|
|
512
|
+
f"FROM asset_images ai "
|
|
513
|
+
f"JOIN assets a ON ai.asset_id = a.id "
|
|
514
|
+
f"WHERE ai.image_path != '' AND ({like_clauses}) "
|
|
515
|
+
f"LIMIT 100",
|
|
516
|
+
params,
|
|
517
|
+
).fetchall()
|
|
518
|
+
else:
|
|
519
|
+
rows = []
|
|
508
520
|
|
|
509
521
|
best_path: Optional[str] = None
|
|
510
522
|
best_score = 0
|
|
@@ -540,8 +552,8 @@ async def _fetch_teacher_image(
|
|
|
540
552
|
best_score = score
|
|
541
553
|
best_path = row["image_path"]
|
|
542
554
|
|
|
543
|
-
# Require minimum score of
|
|
544
|
-
if best_path and best_score >=
|
|
555
|
+
# Require minimum score of 6 (exact phrase match or 3+ keyword hits)
|
|
556
|
+
if best_path and best_score >= 6 and Path(best_path).exists():
|
|
545
557
|
logger.info("Using teacher's own image for '%s' -> %s", query, best_path)
|
|
546
558
|
return Path(best_path)
|
|
547
559
|
except Exception as e:
|
|
@@ -43,6 +43,13 @@ class SubPacket(BaseModel):
|
|
|
43
43
|
closing_notes: str = ""
|
|
44
44
|
generated_at: datetime = Field(default_factory=datetime.now)
|
|
45
45
|
|
|
46
|
+
@field_validator("student_notes", mode="before")
|
|
47
|
+
@classmethod
|
|
48
|
+
def _coerce_student_notes(cls, v):
|
|
49
|
+
if isinstance(v, list):
|
|
50
|
+
return "\n".join(str(item) for item in v)
|
|
51
|
+
return v
|
|
52
|
+
|
|
46
53
|
@field_validator("emergency_info", mode="before")
|
|
47
54
|
@classmethod
|
|
48
55
|
def coerce_emergency_info(cls, v):
|
|
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
|