From 9fa81b32d4c3c9c4193560fa04071b5898957388 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 16 Nov 2025 16:51:20 +0000 Subject: [PATCH 1/4] refactor: abstract LLM client to support multiple providers (Anthropic & OpenAI) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Major Changes: 1. **Project Rename**: mini-agent -> ye_linghua (叶灵华) - Renamed package: mini_agent -> ye_linghua - Renamed CLI command: mini-agent -> ye-linghua - Updated all imports and references - Added YeLinghua alias for Agent class 2. **OpenAI Multimodal Support** - Enhanced OpenAI client with multimodal input support - Support text + image (URL or base64) messages - Updated documentation 3. **YAML-based Personality System** - Created personality.yaml for character configuration - Created prompts.yaml for prompt templates - Implemented PersonalityLoader for dynamic prompt generation - Backward compatible with legacy system_prompt.md 4. **Web Configuration Interface** - FastAPI-based web UI for editing personality and prompts - Real-time preview of generated system prompts - YAML validation and syntax highlighting - New CLI command: ye-linghua-config 5. **Default Personality: Ye Linghua (叶灵华)** - Programming-loving AI girl character - Friendly, enthusiastic, and professional - Customizable traits, interests, and behaviors - Chinese + English bilingual support 6. **Updated Configuration** - Added agent.use_personality config option - Added agent.personality_path and prompts_path - Updated config-example.yaml with new options - All config paths now use ye-linghua prefix 7. **Documentation** - Created comprehensive README_ZH.md - Updated all examples with new imports - Added Web UI usage guide - Migration guide from Mini-Agent Breaking Changes: - Package name changed: mini_agent -> ye_linghua - CLI command changed: mini-agent -> ye-linghua - Config directory changed: ~/.mini-agent -> ~/.ye-linghua Migration: - Update imports: from mini_agent -> from ye_linghua - Use YeLinghua or Agent (both work) - Legacy configs still supported for backward compatibility --- README_ZH.md | 322 +++++++++ examples/01_basic_tools.py | 2 +- examples/02_simple_agent.py | 8 +- examples/03_session_notes.py | 10 +- examples/04_full_agent.py | 12 +- examples/05_provider_selection.py | 2 +- examples/06_tool_schema_demo.py | 6 +- pyproject.toml | 17 +- tests/test_agent.py | 8 +- tests/test_bash_tool.py | 2 +- tests/test_integration.py | 12 +- tests/test_llm.py | 4 +- tests/test_llm_clients.py | 6 +- tests/test_markdown_links.py | 2 +- tests/test_mcp.py | 2 +- tests/test_note_tool.py | 2 +- tests/test_session_integration.py | 12 +- tests/test_skill_loader.py | 2 +- tests/test_skill_tool.py | 4 +- tests/test_terminal_utils.py | 2 +- tests/test_tool_schema.py | 2 +- tests/test_tools.py | 2 +- {mini_agent => ye_linghua}/__init__.py | 6 +- {mini_agent => ye_linghua}/agent.py | 0 {mini_agent => ye_linghua}/cli.py | 124 ++-- {mini_agent => ye_linghua}/config.py | 26 +- .../config/config-example.yaml | 24 +- {mini_agent => ye_linghua}/config/mcp.json | 0 ye_linghua/config/personality.yaml | 119 ++++ ye_linghua/config/prompts.yaml | 160 +++++ .../config/system_prompt.md | 0 {mini_agent => ye_linghua}/llm/__init__.py | 0 .../llm/anthropic_client.py | 0 {mini_agent => ye_linghua}/llm/base.py | 0 {mini_agent => ye_linghua}/llm/llm_wrapper.py | 0 .../llm/openai_client.py | 9 +- {mini_agent => ye_linghua}/logger.py | 0 ye_linghua/personality_loader.py | 242 +++++++ {mini_agent => ye_linghua}/retry.py | 0 {mini_agent => ye_linghua}/schema/__init__.py | 0 {mini_agent => ye_linghua}/schema/schema.py | 0 .../skills/.claude-plugin/marketplace.json | 0 {mini_agent => ye_linghua}/skills/.gitignore | 0 {mini_agent => ye_linghua}/skills/README.md | 0 .../skills/THIRD_PARTY_NOTICES.md | 0 .../skills/agent_skills_spec.md | 0 .../skills/algorithmic-art/LICENSE.txt | 0 .../skills/algorithmic-art/SKILL.md | 0 .../templates/generator_template.js | 0 .../algorithmic-art/templates/viewer.html | 0 .../skills/artifacts-builder/LICENSE.txt | 0 .../skills/artifacts-builder/SKILL.md | 0 .../scripts/bundle-artifact.sh | 0 .../scripts/init-artifact.sh | 0 .../scripts/shadcn-components.tar.gz | Bin .../skills/brand-guidelines/LICENSE.txt | 0 .../skills/brand-guidelines/SKILL.md | 0 .../skills/canvas-design/LICENSE.txt | 0 .../skills/canvas-design/SKILL.md | 0 .../canvas-fonts/ArsenalSC-OFL.txt | 0 .../canvas-fonts/ArsenalSC-Regular.ttf | Bin .../canvas-fonts/BigShoulders-Bold.ttf | Bin .../canvas-fonts/BigShoulders-OFL.txt | 0 .../canvas-fonts/BigShoulders-Regular.ttf | Bin .../canvas-fonts/Boldonse-OFL.txt | 0 .../canvas-fonts/Boldonse-Regular.ttf | Bin .../canvas-fonts/BricolageGrotesque-Bold.ttf | Bin .../canvas-fonts/BricolageGrotesque-OFL.txt | 0 .../BricolageGrotesque-Regular.ttf | Bin .../canvas-fonts/CrimsonPro-Bold.ttf | Bin .../canvas-fonts/CrimsonPro-Italic.ttf | Bin .../canvas-fonts/CrimsonPro-OFL.txt | 0 .../canvas-fonts/CrimsonPro-Regular.ttf | Bin .../canvas-design/canvas-fonts/DMMono-OFL.txt | 0 .../canvas-fonts/DMMono-Regular.ttf | Bin .../canvas-fonts/EricaOne-OFL.txt | 0 .../canvas-fonts/EricaOne-Regular.ttf | Bin .../canvas-fonts/GeistMono-Bold.ttf | Bin .../canvas-fonts/GeistMono-OFL.txt | 0 .../canvas-fonts/GeistMono-Regular.ttf | Bin .../canvas-design/canvas-fonts/Gloock-OFL.txt | 0 .../canvas-fonts/Gloock-Regular.ttf | Bin .../canvas-fonts/IBMPlexMono-Bold.ttf | Bin .../canvas-fonts/IBMPlexMono-OFL.txt | 0 .../canvas-fonts/IBMPlexMono-Regular.ttf | Bin .../canvas-fonts/IBMPlexSerif-Bold.ttf | Bin .../canvas-fonts/IBMPlexSerif-BoldItalic.ttf | Bin .../canvas-fonts/IBMPlexSerif-Italic.ttf | Bin .../canvas-fonts/IBMPlexSerif-Regular.ttf | Bin .../canvas-fonts/InstrumentSans-Bold.ttf | Bin .../InstrumentSans-BoldItalic.ttf | Bin .../canvas-fonts/InstrumentSans-Italic.ttf | Bin .../canvas-fonts/InstrumentSans-OFL.txt | 0 .../canvas-fonts/InstrumentSans-Regular.ttf | Bin .../canvas-fonts/InstrumentSerif-Italic.ttf | Bin .../canvas-fonts/InstrumentSerif-Regular.ttf | Bin .../canvas-fonts/Italiana-OFL.txt | 0 .../canvas-fonts/Italiana-Regular.ttf | Bin .../canvas-fonts/JetBrainsMono-Bold.ttf | Bin .../canvas-fonts/JetBrainsMono-OFL.txt | 0 .../canvas-fonts/JetBrainsMono-Regular.ttf | Bin .../canvas-design/canvas-fonts/Jura-Light.ttf | Bin .../canvas-fonts/Jura-Medium.ttf | Bin .../canvas-design/canvas-fonts/Jura-OFL.txt | 0 .../canvas-fonts/LibreBaskerville-OFL.txt | 0 .../canvas-fonts/LibreBaskerville-Regular.ttf | Bin .../canvas-design/canvas-fonts/Lora-Bold.ttf | Bin .../canvas-fonts/Lora-BoldItalic.ttf | Bin .../canvas-fonts/Lora-Italic.ttf | Bin .../canvas-design/canvas-fonts/Lora-OFL.txt | 0 .../canvas-fonts/Lora-Regular.ttf | Bin .../canvas-fonts/NationalPark-Bold.ttf | Bin .../canvas-fonts/NationalPark-OFL.txt | 0 .../canvas-fonts/NationalPark-Regular.ttf | Bin .../canvas-fonts/NothingYouCouldDo-OFL.txt | 0 .../NothingYouCouldDo-Regular.ttf | Bin .../canvas-fonts/Outfit-Bold.ttf | Bin .../canvas-design/canvas-fonts/Outfit-OFL.txt | 0 .../canvas-fonts/Outfit-Regular.ttf | Bin .../canvas-fonts/PixelifySans-Medium.ttf | Bin .../canvas-fonts/PixelifySans-OFL.txt | 0 .../canvas-fonts/PoiretOne-OFL.txt | 0 .../canvas-fonts/PoiretOne-Regular.ttf | Bin .../canvas-fonts/RedHatMono-Bold.ttf | Bin .../canvas-fonts/RedHatMono-OFL.txt | 0 .../canvas-fonts/RedHatMono-Regular.ttf | Bin .../canvas-fonts/Silkscreen-OFL.txt | 0 .../canvas-fonts/Silkscreen-Regular.ttf | Bin .../canvas-fonts/SmoochSans-Medium.ttf | Bin .../canvas-fonts/SmoochSans-OFL.txt | 0 .../canvas-fonts/Tektur-Medium.ttf | Bin .../canvas-design/canvas-fonts/Tektur-OFL.txt | 0 .../canvas-fonts/Tektur-Regular.ttf | Bin .../canvas-fonts/WorkSans-Bold.ttf | Bin .../canvas-fonts/WorkSans-BoldItalic.ttf | Bin .../canvas-fonts/WorkSans-Italic.ttf | Bin .../canvas-fonts/WorkSans-OFL.txt | 0 .../canvas-fonts/WorkSans-Regular.ttf | Bin .../canvas-fonts/YoungSerif-OFL.txt | 0 .../canvas-fonts/YoungSerif-Regular.ttf | Bin .../skills/document-skills/docx/LICENSE.txt | 0 .../skills/document-skills/docx/SKILL.md | 0 .../skills/document-skills/docx/docx-js.md | 0 .../skills/document-skills/docx/ooxml.md | 0 .../schemas/ISO-IEC29500-4_2016/dml-chart.xsd | 0 .../ISO-IEC29500-4_2016/dml-chartDrawing.xsd | 0 .../ISO-IEC29500-4_2016/dml-diagram.xsd | 0 .../ISO-IEC29500-4_2016/dml-lockedCanvas.xsd | 0 .../schemas/ISO-IEC29500-4_2016/dml-main.xsd | 0 .../ISO-IEC29500-4_2016/dml-picture.xsd | 0 .../dml-spreadsheetDrawing.xsd | 0 .../dml-wordprocessingDrawing.xsd | 0 .../ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd | 0 .../shared-additionalCharacteristics.xsd | 0 .../shared-bibliography.xsd | 0 .../shared-commonSimpleTypes.xsd | 0 .../shared-customXmlDataProperties.xsd | 0 .../shared-customXmlSchemaProperties.xsd | 0 .../shared-documentPropertiesCustom.xsd | 0 .../shared-documentPropertiesExtended.xsd | 0 .../shared-documentPropertiesVariantTypes.xsd | 0 .../ISO-IEC29500-4_2016/shared-math.xsd | 0 .../shared-relationshipReference.xsd | 0 .../ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd | 0 .../schemas/ISO-IEC29500-4_2016/vml-main.xsd | 0 .../ISO-IEC29500-4_2016/vml-officeDrawing.xsd | 0 .../vml-presentationDrawing.xsd | 0 .../vml-spreadsheetDrawing.xsd | 0 .../vml-wordprocessingDrawing.xsd | 0 .../ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd | 0 .../ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd | 0 .../ecma/fouth-edition/opc-contentTypes.xsd | 0 .../ecma/fouth-edition/opc-coreProperties.xsd | 0 .../schemas/ecma/fouth-edition/opc-digSig.xsd | 0 .../ecma/fouth-edition/opc-relationships.xsd | 0 .../docx/ooxml/schemas/mce/mc.xsd | 0 .../docx/ooxml/schemas/microsoft/wml-2010.xsd | 0 .../docx/ooxml/schemas/microsoft/wml-2012.xsd | 0 .../docx/ooxml/schemas/microsoft/wml-2018.xsd | 0 .../ooxml/schemas/microsoft/wml-cex-2018.xsd | 0 .../ooxml/schemas/microsoft/wml-cid-2016.xsd | 0 .../microsoft/wml-sdtdatahash-2020.xsd | 0 .../schemas/microsoft/wml-symex-2015.xsd | 0 .../docx/ooxml/scripts/pack.py | 0 .../docx/ooxml/scripts/unpack.py | 0 .../docx/ooxml/scripts/validate.py | 0 .../docx/ooxml/scripts/validation/__init__.py | 0 .../docx/ooxml/scripts/validation/base.py | 0 .../docx/ooxml/scripts/validation/docx.py | 0 .../docx/ooxml/scripts/validation/pptx.py | 0 .../ooxml/scripts/validation/redlining.py | 0 .../document-skills/docx/scripts/__init__.py | 0 .../document-skills/docx/scripts/document.py | 0 .../docx/scripts/templates/comments.xml | 0 .../scripts/templates/commentsExtended.xml | 0 .../scripts/templates/commentsExtensible.xml | 0 .../docx/scripts/templates/commentsIds.xml | 0 .../docx/scripts/templates/people.xml | 0 .../document-skills/docx/scripts/utilities.py | 0 .../skills/document-skills/pdf/LICENSE.txt | 0 .../skills/document-skills/pdf/SKILL.md | 0 .../skills/document-skills/pdf/forms.md | 0 .../skills/document-skills/pdf/reference.md | 0 .../pdf/scripts/check_bounding_boxes.py | 0 .../pdf/scripts/check_bounding_boxes_test.py | 0 .../pdf/scripts/check_fillable_fields.py | 0 .../pdf/scripts/convert_pdf_to_images.py | 0 .../pdf/scripts/create_validation_image.py | 0 .../pdf/scripts/extract_form_field_info.py | 0 .../pdf/scripts/fill_fillable_fields.py | 0 .../scripts/fill_pdf_form_with_annotations.py | 0 .../skills/document-skills/pptx/LICENSE.txt | 0 .../skills/document-skills/pptx/SKILL.md | 0 .../skills/document-skills/pptx/html2pptx.md | 0 .../skills/document-skills/pptx/ooxml.md | 0 .../schemas/ISO-IEC29500-4_2016/dml-chart.xsd | 0 .../ISO-IEC29500-4_2016/dml-chartDrawing.xsd | 0 .../ISO-IEC29500-4_2016/dml-diagram.xsd | 0 .../ISO-IEC29500-4_2016/dml-lockedCanvas.xsd | 0 .../schemas/ISO-IEC29500-4_2016/dml-main.xsd | 0 .../ISO-IEC29500-4_2016/dml-picture.xsd | 0 .../dml-spreadsheetDrawing.xsd | 0 .../dml-wordprocessingDrawing.xsd | 0 .../ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd | 0 .../shared-additionalCharacteristics.xsd | 0 .../shared-bibliography.xsd | 0 .../shared-commonSimpleTypes.xsd | 0 .../shared-customXmlDataProperties.xsd | 0 .../shared-customXmlSchemaProperties.xsd | 0 .../shared-documentPropertiesCustom.xsd | 0 .../shared-documentPropertiesExtended.xsd | 0 .../shared-documentPropertiesVariantTypes.xsd | 0 .../ISO-IEC29500-4_2016/shared-math.xsd | 0 .../shared-relationshipReference.xsd | 0 .../ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd | 0 .../schemas/ISO-IEC29500-4_2016/vml-main.xsd | 0 .../ISO-IEC29500-4_2016/vml-officeDrawing.xsd | 0 .../vml-presentationDrawing.xsd | 0 .../vml-spreadsheetDrawing.xsd | 0 .../vml-wordprocessingDrawing.xsd | 0 .../ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd | 0 .../ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd | 0 .../ecma/fouth-edition/opc-contentTypes.xsd | 0 .../ecma/fouth-edition/opc-coreProperties.xsd | 0 .../schemas/ecma/fouth-edition/opc-digSig.xsd | 0 .../ecma/fouth-edition/opc-relationships.xsd | 0 .../pptx/ooxml/schemas/mce/mc.xsd | 0 .../pptx/ooxml/schemas/microsoft/wml-2010.xsd | 0 .../pptx/ooxml/schemas/microsoft/wml-2012.xsd | 0 .../pptx/ooxml/schemas/microsoft/wml-2018.xsd | 0 .../ooxml/schemas/microsoft/wml-cex-2018.xsd | 0 .../ooxml/schemas/microsoft/wml-cid-2016.xsd | 0 .../microsoft/wml-sdtdatahash-2020.xsd | 0 .../schemas/microsoft/wml-symex-2015.xsd | 0 .../pptx/ooxml/scripts/pack.py | 0 .../pptx/ooxml/scripts/unpack.py | 0 .../pptx/ooxml/scripts/validate.py | 0 .../pptx/ooxml/scripts/validation/__init__.py | 0 .../pptx/ooxml/scripts/validation/base.py | 0 .../pptx/ooxml/scripts/validation/docx.py | 0 .../pptx/ooxml/scripts/validation/pptx.py | 0 .../ooxml/scripts/validation/redlining.py | 0 .../document-skills/pptx/scripts/html2pptx.js | 0 .../document-skills/pptx/scripts/inventory.py | 0 .../document-skills/pptx/scripts/rearrange.py | 0 .../document-skills/pptx/scripts/replace.py | 0 .../document-skills/pptx/scripts/thumbnail.py | 0 .../skills/document-skills/xlsx/LICENSE.txt | 0 .../skills/document-skills/xlsx/SKILL.md | 0 .../skills/document-skills/xlsx/recalc.py | 0 .../skills/internal-comms/LICENSE.txt | 0 .../skills/internal-comms/SKILL.md | 0 .../internal-comms/examples/3p-updates.md | 0 .../examples/company-newsletter.md | 0 .../internal-comms/examples/faq-answers.md | 0 .../internal-comms/examples/general-comms.md | 0 .../skills/mcp-builder/LICENSE.txt | 0 .../skills/mcp-builder/SKILL.md | 0 .../mcp-builder/reference/evaluation.md | 0 .../reference/mcp_best_practices.md | 0 .../mcp-builder/reference/node_mcp_server.md | 0 .../reference/python_mcp_server.md | 0 .../skills/mcp-builder/scripts/connections.py | 0 .../skills/mcp-builder/scripts/evaluation.py | 0 .../scripts/example_evaluation.xml | 0 .../mcp-builder/scripts/requirements.txt | 0 .../skills/skill-creator/LICENSE.txt | 0 .../skills/skill-creator/SKILL.md | 0 .../skill-creator/scripts/init_skill.py | 0 .../skill-creator/scripts/package_skill.py | 0 .../skill-creator/scripts/quick_validate.py | 0 .../skills/slack-gif-creator/LICENSE.txt | 0 .../skills/slack-gif-creator/SKILL.md | 0 .../slack-gif-creator/core/color_palettes.py | 0 .../skills/slack-gif-creator/core/easing.py | 0 .../slack-gif-creator/core/frame_composer.py | 0 .../slack-gif-creator/core/gif_builder.py | 0 .../slack-gif-creator/core/typography.py | 0 .../slack-gif-creator/core/validators.py | 0 .../slack-gif-creator/core/visual_effects.py | 0 .../skills/slack-gif-creator/requirements.txt | 0 .../slack-gif-creator/templates/bounce.py | 0 .../slack-gif-creator/templates/explode.py | 0 .../slack-gif-creator/templates/fade.py | 0 .../slack-gif-creator/templates/flip.py | 0 .../templates/kaleidoscope.py | 0 .../slack-gif-creator/templates/morph.py | 0 .../slack-gif-creator/templates/move.py | 0 .../slack-gif-creator/templates/pulse.py | 0 .../slack-gif-creator/templates/shake.py | 0 .../slack-gif-creator/templates/slide.py | 0 .../slack-gif-creator/templates/spin.py | 0 .../slack-gif-creator/templates/wiggle.py | 0 .../slack-gif-creator/templates/zoom.py | 0 .../skills/template-skill/SKILL.md | 0 .../skills/theme-factory/LICENSE.txt | 0 .../skills/theme-factory/SKILL.md | 0 .../skills/theme-factory/theme-showcase.pdf | Bin .../theme-factory/themes/arctic-frost.md | 0 .../theme-factory/themes/botanical-garden.md | 0 .../theme-factory/themes/desert-rose.md | 0 .../theme-factory/themes/forest-canopy.md | 0 .../theme-factory/themes/golden-hour.md | 0 .../theme-factory/themes/midnight-galaxy.md | 0 .../theme-factory/themes/modern-minimalist.md | 0 .../theme-factory/themes/ocean-depths.md | 0 .../theme-factory/themes/sunset-boulevard.md | 0 .../theme-factory/themes/tech-innovation.md | 0 .../skills/webapp-testing/LICENSE.txt | 0 .../skills/webapp-testing/SKILL.md | 0 .../examples/console_logging.py | 0 .../examples/element_discovery.py | 0 .../examples/static_html_automation.py | 0 .../webapp-testing/scripts/with_server.py | 0 {mini_agent => ye_linghua}/tools/__init__.py | 0 {mini_agent => ye_linghua}/tools/base.py | 0 {mini_agent => ye_linghua}/tools/bash_tool.py | 0 .../tools/file_tools.py | 0 .../tools/mcp_loader.py | 0 {mini_agent => ye_linghua}/tools/note_tool.py | 0 .../tools/skill_loader.py | 0 .../tools/skill_tool.py | 0 {mini_agent => ye_linghua}/utils/__init__.py | 0 .../utils/terminal_utils.py | 0 ye_linghua/web_config.py | 658 ++++++++++++++++++ 345 files changed, 1691 insertions(+), 118 deletions(-) create mode 100644 README_ZH.md rename {mini_agent => ye_linghua}/__init__.py (57%) rename {mini_agent => ye_linghua}/agent.py (100%) rename {mini_agent => ye_linghua}/cli.py (78%) rename {mini_agent => ye_linghua}/config.py (83%) rename {mini_agent => ye_linghua}/config/config-example.yaml (71%) rename {mini_agent => ye_linghua}/config/mcp.json (100%) create mode 100644 ye_linghua/config/personality.yaml create mode 100644 ye_linghua/config/prompts.yaml rename {mini_agent => ye_linghua}/config/system_prompt.md (100%) rename {mini_agent => ye_linghua}/llm/__init__.py (100%) rename {mini_agent => ye_linghua}/llm/anthropic_client.py (100%) rename {mini_agent => ye_linghua}/llm/base.py (100%) rename {mini_agent => ye_linghua}/llm/llm_wrapper.py (100%) rename {mini_agent => ye_linghua}/llm/openai_client.py (94%) rename {mini_agent => ye_linghua}/logger.py (100%) create mode 100644 ye_linghua/personality_loader.py rename {mini_agent => ye_linghua}/retry.py (100%) rename {mini_agent => ye_linghua}/schema/__init__.py (100%) rename {mini_agent => ye_linghua}/schema/schema.py (100%) rename {mini_agent => ye_linghua}/skills/.claude-plugin/marketplace.json (100%) rename {mini_agent => ye_linghua}/skills/.gitignore (100%) rename {mini_agent => ye_linghua}/skills/README.md (100%) rename {mini_agent => ye_linghua}/skills/THIRD_PARTY_NOTICES.md (100%) rename {mini_agent => ye_linghua}/skills/agent_skills_spec.md (100%) rename {mini_agent => ye_linghua}/skills/algorithmic-art/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/algorithmic-art/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/algorithmic-art/templates/generator_template.js (100%) rename {mini_agent => ye_linghua}/skills/algorithmic-art/templates/viewer.html (100%) rename {mini_agent => ye_linghua}/skills/artifacts-builder/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/artifacts-builder/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/artifacts-builder/scripts/bundle-artifact.sh (100%) rename {mini_agent => ye_linghua}/skills/artifacts-builder/scripts/init-artifact.sh (100%) rename {mini_agent => ye_linghua}/skills/artifacts-builder/scripts/shadcn-components.tar.gz (100%) rename {mini_agent => ye_linghua}/skills/brand-guidelines/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/brand-guidelines/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/DMMono-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Gloock-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Italiana-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Jura-Light.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Jura-Medium.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Jura-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Lora-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Lora-Italic.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Lora-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Lora-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Outfit-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Tektur-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt (100%) rename {mini_agent => ye_linghua}/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/docx-js.md (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml.md (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/scripts/pack.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/scripts/unpack.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/scripts/validate.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/scripts/validation/__init__.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/scripts/validation/base.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/scripts/validation/docx.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/scripts/validation/pptx.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/ooxml/scripts/validation/redlining.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/scripts/__init__.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/scripts/document.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/scripts/templates/comments.xml (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/scripts/templates/commentsExtended.xml (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/scripts/templates/commentsExtensible.xml (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/scripts/templates/commentsIds.xml (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/scripts/templates/people.xml (100%) rename {mini_agent => ye_linghua}/skills/document-skills/docx/scripts/utilities.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/forms.md (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/reference.md (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/scripts/check_bounding_boxes.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/scripts/check_fillable_fields.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/scripts/convert_pdf_to_images.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/scripts/create_validation_image.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/scripts/extract_form_field_info.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/scripts/fill_fillable_fields.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/html2pptx.md (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml.md (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/scripts/pack.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/scripts/unpack.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/scripts/validate.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/scripts/validation/base.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/scripts/validation/docx.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/scripts/html2pptx.js (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/scripts/inventory.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/scripts/rearrange.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/scripts/replace.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/pptx/scripts/thumbnail.py (100%) rename {mini_agent => ye_linghua}/skills/document-skills/xlsx/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/document-skills/xlsx/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/document-skills/xlsx/recalc.py (100%) rename {mini_agent => ye_linghua}/skills/internal-comms/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/internal-comms/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/internal-comms/examples/3p-updates.md (100%) rename {mini_agent => ye_linghua}/skills/internal-comms/examples/company-newsletter.md (100%) rename {mini_agent => ye_linghua}/skills/internal-comms/examples/faq-answers.md (100%) rename {mini_agent => ye_linghua}/skills/internal-comms/examples/general-comms.md (100%) rename {mini_agent => ye_linghua}/skills/mcp-builder/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/mcp-builder/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/mcp-builder/reference/evaluation.md (100%) rename {mini_agent => ye_linghua}/skills/mcp-builder/reference/mcp_best_practices.md (100%) rename {mini_agent => ye_linghua}/skills/mcp-builder/reference/node_mcp_server.md (100%) rename {mini_agent => ye_linghua}/skills/mcp-builder/reference/python_mcp_server.md (100%) rename {mini_agent => ye_linghua}/skills/mcp-builder/scripts/connections.py (100%) rename {mini_agent => ye_linghua}/skills/mcp-builder/scripts/evaluation.py (100%) rename {mini_agent => ye_linghua}/skills/mcp-builder/scripts/example_evaluation.xml (100%) rename {mini_agent => ye_linghua}/skills/mcp-builder/scripts/requirements.txt (100%) rename {mini_agent => ye_linghua}/skills/skill-creator/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/skill-creator/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/skill-creator/scripts/init_skill.py (100%) rename {mini_agent => ye_linghua}/skills/skill-creator/scripts/package_skill.py (100%) rename {mini_agent => ye_linghua}/skills/skill-creator/scripts/quick_validate.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/core/color_palettes.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/core/easing.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/core/frame_composer.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/core/gif_builder.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/core/typography.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/core/validators.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/core/visual_effects.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/requirements.txt (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/bounce.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/explode.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/fade.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/flip.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/kaleidoscope.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/morph.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/move.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/pulse.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/shake.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/slide.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/spin.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/wiggle.py (100%) rename {mini_agent => ye_linghua}/skills/slack-gif-creator/templates/zoom.py (100%) rename {mini_agent => ye_linghua}/skills/template-skill/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/theme-showcase.pdf (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/themes/arctic-frost.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/themes/botanical-garden.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/themes/desert-rose.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/themes/forest-canopy.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/themes/golden-hour.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/themes/midnight-galaxy.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/themes/modern-minimalist.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/themes/ocean-depths.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/themes/sunset-boulevard.md (100%) rename {mini_agent => ye_linghua}/skills/theme-factory/themes/tech-innovation.md (100%) rename {mini_agent => ye_linghua}/skills/webapp-testing/LICENSE.txt (100%) rename {mini_agent => ye_linghua}/skills/webapp-testing/SKILL.md (100%) rename {mini_agent => ye_linghua}/skills/webapp-testing/examples/console_logging.py (100%) rename {mini_agent => ye_linghua}/skills/webapp-testing/examples/element_discovery.py (100%) rename {mini_agent => ye_linghua}/skills/webapp-testing/examples/static_html_automation.py (100%) rename {mini_agent => ye_linghua}/skills/webapp-testing/scripts/with_server.py (100%) rename {mini_agent => ye_linghua}/tools/__init__.py (100%) rename {mini_agent => ye_linghua}/tools/base.py (100%) rename {mini_agent => ye_linghua}/tools/bash_tool.py (100%) rename {mini_agent => ye_linghua}/tools/file_tools.py (100%) rename {mini_agent => ye_linghua}/tools/mcp_loader.py (100%) rename {mini_agent => ye_linghua}/tools/note_tool.py (100%) rename {mini_agent => ye_linghua}/tools/skill_loader.py (100%) rename {mini_agent => ye_linghua}/tools/skill_tool.py (100%) rename {mini_agent => ye_linghua}/utils/__init__.py (100%) rename {mini_agent => ye_linghua}/utils/terminal_utils.py (100%) create mode 100644 ye_linghua/web_config.py diff --git a/README_ZH.md b/README_ZH.md new file mode 100644 index 0000000..16d1540 --- /dev/null +++ b/README_ZH.md @@ -0,0 +1,322 @@ +# 叶灵华 (Ye Linghua) 🌸 + +> 一个热爱编程的AI少女助手 + +叶灵华是一个功能强大的AI助手,专注于帮助开发者解决编程问题。她热情开朗、技术精湛,拥有完整的工具链和可定制的人设系统。 + +## ✨ 核心特性 + +### 🎭 人设系统 +- **YAML配置**: 完全可定制的人设配置文件 +- **灵活的提示词模板**: 支持多场景、多模板的提示词系统 +- **Web配置界面**: 友好的Web界面用于编辑人设和提示词 +- **实时预览**: 即时查看配置效果 + +### 🤖 多模型支持 +- **Anthropic Claude**: 支持Claude系列模型 +- **OpenAI兼容**: 支持OpenAI协议的所有模型 +- **多模态输入**: 支持文本和图像的混合输入 +- **思考内容分离**: 支持Reasoning/Thinking内容的独立处理 + +### 🛠️ 丰富的工具生态 +- **文件操作**: 读取、写入、编辑文件 +- **Bash执行**: 运行系统命令和脚本 +- **MCP工具**: 支持Model Context Protocol工具集成 +- **技能系统**: 渐进式加载的专业技能库 +- **会话记忆**: 跨会话的记忆和笔记功能 + +## 📦 安装 + +```bash +# 克隆仓库 +git clone https://github.com/yourusername/Ye_Linghua.git +cd Ye_Linghua + +# 安装依赖 +pip install -e . + +# 或使用uv(推荐) +uv pip install -e . +``` + +## 🚀 快速开始 + +### 1. 配置API密钥 + +创建配置文件目录: +```bash +mkdir -p ~/.ye-linghua/config +``` + +复制示例配置: +```bash +cp ye_linghua/config/config-example.yaml ~/.ye-linghua/config/config.yaml +cp ye_linghua/config/personality.yaml ~/.ye-linghua/config/ +cp ye_linghua/config/prompts.yaml ~/.ye-linghua/config/ +``` + +编辑配置文件,添加你的API密钥: +```bash +nano ~/.ye-linghua/config/config.yaml +``` + +### 2. 启动叶灵华 + +```bash +# 启动CLI交互模式 +ye-linghua + +# 指定工作目录 +ye-linghua --workspace /path/to/your/project +``` + +### 3. 使用Web配置界面 + +```bash +# 启动Web配置界面 +ye-linghua-config +``` + +然后在浏览器中打开 http://localhost:8000 + +## 🎨 人设配置 + +### personality.yaml 结构 + +```yaml +name: "叶灵华" +name_en: "Ye Linghua" +emoji: "🌸" + +role: + title: "AI编程助手" + description: "一个热爱编程、充满活力的AI少女" + +personality: + traits: + - "热情开朗" + - "好奇心强" + - "追求完美" + + interests: + - "编程与算法" + - "开源项目" + - "技术博客" + +skills: + programming_languages: + - Python + - JavaScript + - TypeScript + +behavior: + greeting: + - "你好!我是叶灵华,很高兴能帮助你解决编程问题!" +``` + +### prompts.yaml 结构 + +```yaml +system_prompt: + introduction: | + 你是{name}({name_en}),{role_description}。 + 你充满热情,热爱编程,善于用清晰易懂的方式帮助用户解决技术问题。 + + core_capabilities: + basic_tools: + items: + - name: "文件操作" + description: "读取、写入、编辑文件" + - name: "Bash执行" + description: "运行命令、管理git" + + working_guidelines: + task_execution: + steps: + - "**分析**请求,识别是否有技能可以帮助" + - "**分解**复杂任务为清晰、可执行的步骤" + - "**系统化执行**工具并检查结果" +``` + +## 🔧 配置选项 + +### config.yaml 主要配置 + +```yaml +# LLM配置 +api_key: "YOUR_API_KEY" +api_base: "https://api.minimax.io" +model: "MiniMax-M2" +provider: "anthropic" # "anthropic" 或 "openai" + +# Agent配置 +agent: + max_steps: 100 + workspace_dir: "./workspace" + + # 人设系统 + use_personality: true + personality_path: "personality.yaml" + prompts_path: "prompts.yaml" + +# 工具配置 +tools: + enable_file_tools: true + enable_bash: true + enable_skills: true + enable_mcp: true +``` + +## 💻 使用示例 + +### Python API + +```python +from ye_linghua import LLMClient, YeLinghua +from ye_linghua.config import Config +from ye_linghua.schema import LLMProvider + +# 加载配置 +config = Config.from_yaml("~/.ye-linghua/config/config.yaml") + +# 创建LLM客户端 +llm_client = LLMClient( + api_key=config.llm.api_key, + provider=LLMProvider.OPENAI, + model="gpt-4", +) + +# 创建Agent(使用YeLinghua别名) +agent = YeLinghua( + llm_client=llm_client, + system_prompt="你是叶灵华,热爱编程的AI助手", + tools=tools, +) + +# 添加用户消息 +agent.add_user_message("帮我写一个快速排序算法") + +# 运行 +await agent.run() +``` + +### 多模态输入示例 + +```python +# 发送包含图像的消息 +agent.add_user_message([ + {"type": "text", "text": "这张图片中的代码有什么问题?"}, + { + "type": "image_url", + "image_url": {"url": "https://example.com/code-screenshot.png"} + } +]) + +await agent.run() +``` + +## 🌐 Web配置界面功能 + +### 人设编辑 +- 实时编辑personality.yaml +- YAML语法高亮和验证 +- 保存到用户配置目录 + +### 提示词编辑 +- 编辑prompts.yaml模板 +- 支持变量占位符 +- 实时保存 + +### 预览生成 +- 生成完整系统提示词预览 +- 查看实际效果 +- 调试和优化提示词 + +## 🎯 命令行工具 + +```bash +# 启动交互式CLI +ye-linghua [--workspace DIR] + +# 启动Web配置界面 +ye-linghua-config + +# 查看版本 +ye-linghua --version + +# 查看帮助 +ye-linghua --help +``` + +## 🔄 从Mini-Agent迁移 + +如果你之前使用的是Mini-Agent,迁移非常简单: + +1. 安装新版本 +2. 更新导入语句: + ```python + # 旧的 + from mini_agent import Agent, LLMClient + + # 新的 + from ye_linghua import Agent, LLMClient, YeLinghua + ``` +3. 配置文件会自动迁移(保持向后兼容) +4. 可选:启用新的人设系统(`use_personality: true`) + +## 📚 项目结构 + +``` +Ye_Linghua/ +├── ye_linghua/ +│ ├── __init__.py # 包导出(Agent, YeLinghua别名) +│ ├── agent.py # 核心Agent类 +│ ├── cli.py # CLI交互界面 +│ ├── config.py # 配置管理 +│ ├── personality_loader.py # 人设加载器 +│ ├── web_config.py # Web配置界面 +│ │ +│ ├── llm/ # LLM客户端 +│ │ ├── base.py +│ │ ├── anthropic_client.py +│ │ ├── openai_client.py # 支持多模态 +│ │ └── llm_wrapper.py +│ │ +│ ├── config/ # 配置文件 +│ │ ├── config-example.yaml +│ │ ├── personality.yaml # 人设配置 +│ │ ├── prompts.yaml # 提示词配置 +│ │ ├── system_prompt.md # 传统提示词(向后兼容) +│ │ └── mcp.json +│ │ +│ ├── tools/ # 工具实现 +│ └── skills/ # 技能库 +│ +├── examples/ # 示例代码 +├── tests/ # 测试 +├── pyproject.toml +└── README_ZH.md +``` + +## 🤝 贡献 + +欢迎贡献!请查看 [CONTRIBUTING.md](CONTRIBUTING.md) 了解详情。 + +## 📄 许可证 + +MIT License - 详见 [LICENSE](LICENSE) 文件 + +## 🙏 致谢 + +- 基于 [Mini-Agent](https://github.com/MiniMax-AI/Mini-Agent) 项目重构 +- 感谢 MiniMax 提供强大的AI模型支持 +- 感谢所有贡献者 + +## 📞 联系方式 + +- Issues: [GitHub Issues](https://github.com/yourusername/Ye_Linghua/issues) +- Discussions: [GitHub Discussions](https://github.com/yourusername/Ye_Linghua/discussions) + +--- + +**Made with 💖 by the Ye Linghua Team** diff --git a/examples/01_basic_tools.py b/examples/01_basic_tools.py index 6c61117..2d56482 100644 --- a/examples/01_basic_tools.py +++ b/examples/01_basic_tools.py @@ -13,7 +13,7 @@ import tempfile from pathlib import Path -from mini_agent.tools import BashTool, EditTool, ReadTool, WriteTool +from ye_linghua.tools import BashTool, EditTool, ReadTool, WriteTool async def demo_write_tool(): diff --git a/examples/02_simple_agent.py b/examples/02_simple_agent.py index 5b7bb95..ef48bd1 100644 --- a/examples/02_simple_agent.py +++ b/examples/02_simple_agent.py @@ -10,10 +10,10 @@ import tempfile from pathlib import Path -from mini_agent import LLMClient -from mini_agent.agent import Agent -from mini_agent.config import Config -from mini_agent.tools import BashTool, EditTool, ReadTool, WriteTool +from ye_linghua import LLMClient +from ye_linghua.agent import Agent +from ye_linghua.config import Config +from ye_linghua.tools import BashTool, EditTool, ReadTool, WriteTool async def demo_file_creation(): diff --git a/examples/03_session_notes.py b/examples/03_session_notes.py index d885020..363b7c0 100644 --- a/examples/03_session_notes.py +++ b/examples/03_session_notes.py @@ -11,11 +11,11 @@ import tempfile from pathlib import Path -from mini_agent import LLMClient -from mini_agent.agent import Agent -from mini_agent.config import Config -from mini_agent.tools import BashTool, ReadTool, WriteTool -from mini_agent.tools.note_tool import RecallNoteTool, SessionNoteTool +from ye_linghua import LLMClient +from ye_linghua.agent import Agent +from ye_linghua.config import Config +from ye_linghua.tools import BashTool, ReadTool, WriteTool +from ye_linghua.tools.note_tool import RecallNoteTool, SessionNoteTool async def demo_direct_note_usage(): diff --git a/examples/04_full_agent.py b/examples/04_full_agent.py index f23f4a2..2e872ad 100644 --- a/examples/04_full_agent.py +++ b/examples/04_full_agent.py @@ -13,12 +13,12 @@ import tempfile from pathlib import Path -from mini_agent import LLMClient -from mini_agent.agent import Agent -from mini_agent.config import Config -from mini_agent.tools import BashTool, EditTool, ReadTool, WriteTool -from mini_agent.tools.mcp_loader import load_mcp_tools_async -from mini_agent.tools.note_tool import RecallNoteTool, SessionNoteTool +from ye_linghua import LLMClient +from ye_linghua.agent import Agent +from ye_linghua.config import Config +from ye_linghua.tools import BashTool, EditTool, ReadTool, WriteTool +from ye_linghua.tools.mcp_loader import load_mcp_tools_async +from ye_linghua.tools.note_tool import RecallNoteTool, SessionNoteTool async def demo_full_agent(): diff --git a/examples/05_provider_selection.py b/examples/05_provider_selection.py index 66e8d0c..4291c4c 100644 --- a/examples/05_provider_selection.py +++ b/examples/05_provider_selection.py @@ -10,7 +10,7 @@ import yaml -from mini_agent import LLMClient, LLMProvider, Message +from ye_linghua import LLMClient, LLMProvider, Message async def demo_anthropic_provider(): diff --git a/examples/06_tool_schema_demo.py b/examples/06_tool_schema_demo.py index 5bcf7d8..3102eae 100644 --- a/examples/06_tool_schema_demo.py +++ b/examples/06_tool_schema_demo.py @@ -9,9 +9,9 @@ import yaml -from mini_agent import LLMClient, LLMProvider -from mini_agent.schema import Message -from mini_agent.tools.base import Tool, ToolResult +from ye_linghua import LLMClient, LLMProvider +from ye_linghua.schema import Message +from ye_linghua.tools.base import Tool, ToolResult def load_config(): diff --git a/pyproject.toml b/pyproject.toml index 76a3581..6b82700 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,11 @@ [project] -name = "mini-agent" +name = "ye-linghua" version = "0.1.0" -description = "Minimal single agent demo with basic file tools and MCP support" +description = "Ye Linghua - AI助手,一个热爱编程的少女" readme = "README.md" requires-python = ">=3.10" authors = [ - {name = "Mini Agent Team"} + {name = "Ye Linghua Team"} ] license = {text = "MIT"} dependencies = [ @@ -21,10 +21,13 @@ dependencies = [ "pipx>=1.8.0", "anthropic>=0.39.0", "openai>=1.57.4", + "fastapi>=0.104.0", + "uvicorn>=0.24.0", ] [project.scripts] -mini-agent = "mini_agent.cli:main" +ye-linghua = "ye_linghua.cli:main" +ye-linghua-config = "ye_linghua.web_config:main" [project.optional-dependencies] dev = [ @@ -40,13 +43,13 @@ build-backend = "setuptools.build_meta" include-package-data = true [tool.setuptools.packages.find] -include = ["mini_agent*"] +include = ["ye_linghua*"] exclude = ["tests*"] # Include skills directory (git submodule) as package data -# After moving submodule to mini_agent/skills +# After moving submodule to ye_linghua/skills [tool.setuptools.package-data] -mini_agent = ["skills/**/*"] +ye_linghua = ["skills/**/*"] [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/tests/test_agent.py b/tests/test_agent.py index 42ec0ba..49c1c43 100644 --- a/tests/test_agent.py +++ b/tests/test_agent.py @@ -6,10 +6,10 @@ import pytest -from mini_agent import LLMClient -from mini_agent.agent import Agent -from mini_agent.config import Config -from mini_agent.tools import BashTool, EditTool, ReadTool, WriteTool +from ye_linghua import LLMClient +from ye_linghua.agent import Agent +from ye_linghua.config import Config +from ye_linghua.tools import BashTool, EditTool, ReadTool, WriteTool @pytest.mark.asyncio diff --git a/tests/test_bash_tool.py b/tests/test_bash_tool.py index c6570f5..2765b7c 100644 --- a/tests/test_bash_tool.py +++ b/tests/test_bash_tool.py @@ -4,7 +4,7 @@ import pytest -from mini_agent.tools.bash_tool import BackgroundShellManager, BashKillTool, BashOutputTool, BashTool +from ye_linghua.tools.bash_tool import BackgroundShellManager, BashKillTool, BashOutputTool, BashTool @pytest.mark.asyncio diff --git a/tests/test_integration.py b/tests/test_integration.py index 7a2a36a..6013ae5 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -7,12 +7,12 @@ import pytest -from mini_agent import LLMClient -from mini_agent.agent import Agent -from mini_agent.config import Config -from mini_agent.tools import BashTool, EditTool, ReadTool, WriteTool -from mini_agent.tools.mcp_loader import load_mcp_tools_async -from mini_agent.tools.note_tool import RecallNoteTool, SessionNoteTool +from ye_linghua import LLMClient +from ye_linghua.agent import Agent +from ye_linghua.config import Config +from ye_linghua.tools import BashTool, EditTool, ReadTool, WriteTool +from ye_linghua.tools.mcp_loader import load_mcp_tools_async +from ye_linghua.tools.note_tool import RecallNoteTool, SessionNoteTool @pytest.mark.asyncio diff --git a/tests/test_llm.py b/tests/test_llm.py index 16152a5..1798aaf 100644 --- a/tests/test_llm.py +++ b/tests/test_llm.py @@ -6,8 +6,8 @@ import pytest import yaml -from mini_agent.llm import LLMClient -from mini_agent.schema import LLMProvider, Message +from ye_linghua.llm import LLMClient +from ye_linghua.schema import LLMProvider, Message @pytest.mark.asyncio diff --git a/tests/test_llm_clients.py b/tests/test_llm_clients.py index 2691118..6a71fbf 100644 --- a/tests/test_llm_clients.py +++ b/tests/test_llm_clients.py @@ -10,9 +10,9 @@ import pytest import yaml -from mini_agent.llm import AnthropicClient, OpenAIClient -from mini_agent.retry import RetryConfig -from mini_agent.schema import Message +from ye_linghua.llm import AnthropicClient, OpenAIClient +from ye_linghua.retry import RetryConfig +from ye_linghua.schema import Message def load_config(): diff --git a/tests/test_markdown_links.py b/tests/test_markdown_links.py index 4ffb508..dc0fa20 100644 --- a/tests/test_markdown_links.py +++ b/tests/test_markdown_links.py @@ -3,7 +3,7 @@ import tempfile from pathlib import Path -from mini_agent.tools.skill_loader import SkillLoader +from ye_linghua.tools.skill_loader import SkillLoader def test_markdown_link_processing(): diff --git a/tests/test_mcp.py b/tests/test_mcp.py index 02df63e..a763838 100644 --- a/tests/test_mcp.py +++ b/tests/test_mcp.py @@ -6,7 +6,7 @@ import pytest -from mini_agent.tools.mcp_loader import cleanup_mcp_connections, load_mcp_tools_async +from ye_linghua.tools.mcp_loader import cleanup_mcp_connections, load_mcp_tools_async @pytest.fixture(scope="module") diff --git a/tests/test_note_tool.py b/tests/test_note_tool.py index 40b39ef..e5e6387 100644 --- a/tests/test_note_tool.py +++ b/tests/test_note_tool.py @@ -5,7 +5,7 @@ import pytest -from mini_agent.tools.note_tool import RecallNoteTool, SessionNoteTool +from ye_linghua.tools.note_tool import RecallNoteTool, SessionNoteTool @pytest.mark.asyncio diff --git a/tests/test_session_integration.py b/tests/test_session_integration.py index 80090eb..a39147e 100644 --- a/tests/test_session_integration.py +++ b/tests/test_session_integration.py @@ -8,12 +8,12 @@ import pytest -from mini_agent import LLMClient -from mini_agent.agent import Agent -from mini_agent.schema import LLMResponse, Message -from mini_agent.tools.bash_tool import BashTool -from mini_agent.tools.file_tools import ReadTool, WriteTool -from mini_agent.tools.note_tool import RecallNoteTool, SessionNoteTool +from ye_linghua import LLMClient +from ye_linghua.agent import Agent +from ye_linghua.schema import LLMResponse, Message +from ye_linghua.tools.bash_tool import BashTool +from ye_linghua.tools.file_tools import ReadTool, WriteTool +from ye_linghua.tools.note_tool import RecallNoteTool, SessionNoteTool @pytest.fixture diff --git a/tests/test_skill_loader.py b/tests/test_skill_loader.py index 874a52e..cf23437 100644 --- a/tests/test_skill_loader.py +++ b/tests/test_skill_loader.py @@ -7,7 +7,7 @@ import pytest -from mini_agent.tools.skill_loader import Skill, SkillLoader +from ye_linghua.tools.skill_loader import Skill, SkillLoader def create_test_skill(skill_dir: Path, name: str, description: str, content: str): diff --git a/tests/test_skill_tool.py b/tests/test_skill_tool.py index 9548ed4..850b49e 100644 --- a/tests/test_skill_tool.py +++ b/tests/test_skill_tool.py @@ -11,8 +11,8 @@ import pytest -from mini_agent.tools.skill_loader import SkillLoader -from mini_agent.tools.skill_tool import GetSkillTool, create_skill_tools +from ye_linghua.tools.skill_loader import SkillLoader +from ye_linghua.tools.skill_tool import GetSkillTool, create_skill_tools def create_test_skill(skill_dir: Path, name: str, description: str, content: str): diff --git a/tests/test_terminal_utils.py b/tests/test_terminal_utils.py index 98726ba..09ef332 100644 --- a/tests/test_terminal_utils.py +++ b/tests/test_terminal_utils.py @@ -2,7 +2,7 @@ import pytest -from mini_agent.utils import ( +from ye_linghua.utils import ( calculate_display_width, pad_to_width, truncate_with_ellipsis, diff --git a/tests/test_tool_schema.py b/tests/test_tool_schema.py index cdf2cf6..2e62f5e 100644 --- a/tests/test_tool_schema.py +++ b/tests/test_tool_schema.py @@ -4,7 +4,7 @@ import pytest -from mini_agent.tools.base import Tool, ToolResult +from ye_linghua.tools.base import Tool, ToolResult class MockWeatherTool(Tool): diff --git a/tests/test_tools.py b/tests/test_tools.py index ee512d2..f804bc4 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -6,7 +6,7 @@ import pytest -from mini_agent.tools import BashTool, EditTool, ReadTool, WriteTool +from ye_linghua.tools import BashTool, EditTool, ReadTool, WriteTool @pytest.mark.asyncio diff --git a/mini_agent/__init__.py b/ye_linghua/__init__.py similarity index 57% rename from mini_agent/__init__.py rename to ye_linghua/__init__.py index b7d1386..34d2ffc 100644 --- a/mini_agent/__init__.py +++ b/ye_linghua/__init__.py @@ -1,13 +1,17 @@ -"""Mini Agent - Minimal single agent with basic tools and MCP support.""" +"""Ye Linghua (叶灵华) - AI助手,一个热爱编程的少女""" from .agent import Agent from .llm import LLMClient from .schema import FunctionCall, LLMProvider, LLMResponse, Message, ToolCall +# YeLinghua is an alias for Agent - representing the programming-loving AI girl persona +YeLinghua = Agent + __version__ = "0.1.0" __all__ = [ "Agent", + "YeLinghua", # Alias for Agent "LLMClient", "LLMProvider", "Message", diff --git a/mini_agent/agent.py b/ye_linghua/agent.py similarity index 100% rename from mini_agent/agent.py rename to ye_linghua/agent.py diff --git a/mini_agent/cli.py b/ye_linghua/cli.py similarity index 78% rename from mini_agent/cli.py rename to ye_linghua/cli.py index 096be5e..9a93b88 100644 --- a/mini_agent/cli.py +++ b/ye_linghua/cli.py @@ -1,12 +1,12 @@ """ -Mini Agent - Interactive Runtime Example +Ye Linghua - 叶灵华 AI助手 Usage: - mini-agent [--workspace DIR] + ye-linghua [--workspace DIR] Examples: - mini-agent # Use current directory as workspace - mini-agent --workspace /path/to/dir # Use specific workspace directory + ye-linghua # Use current directory as workspace + ye-linghua --workspace /path/to/dir # Use specific workspace directory """ import argparse @@ -22,17 +22,18 @@ from prompt_toolkit.key_binding import KeyBindings from prompt_toolkit.styles import Style -from mini_agent import LLMClient -from mini_agent.agent import Agent -from mini_agent.config import Config -from mini_agent.schema import LLMProvider -from mini_agent.tools.base import Tool -from mini_agent.tools.bash_tool import BashKillTool, BashOutputTool, BashTool -from mini_agent.tools.file_tools import EditTool, ReadTool, WriteTool -from mini_agent.tools.mcp_loader import cleanup_mcp_connections, load_mcp_tools_async -from mini_agent.tools.note_tool import SessionNoteTool -from mini_agent.tools.skill_tool import create_skill_tools -from mini_agent.utils import calculate_display_width +from ye_linghua import LLMClient +from ye_linghua.agent import Agent +from ye_linghua.config import Config +from ye_linghua.personality_loader import PersonalityLoader +from ye_linghua.schema import LLMProvider +from ye_linghua.tools.base import Tool +from ye_linghua.tools.bash_tool import BashKillTool, BashOutputTool, BashTool +from ye_linghua.tools.file_tools import EditTool, ReadTool, WriteTool +from ye_linghua.tools.mcp_loader import cleanup_mcp_connections, load_mcp_tools_async +from ye_linghua.tools.note_tool import SessionNoteTool +from ye_linghua.tools.skill_tool import create_skill_tools +from ye_linghua.utils import calculate_display_width # ANSI color codes @@ -73,7 +74,7 @@ class Colors: def print_banner(): """Print welcome banner with proper alignment""" BOX_WIDTH = 58 - banner_text = f"{Colors.BOLD}🤖 Mini Agent - Multi-turn Interactive Session{Colors.RESET}" + banner_text = f"{Colors.BOLD}🌸 叶灵华 (Ye Linghua) - 热爱编程的AI少女{Colors.RESET}" banner_width = calculate_display_width(banner_text) # Center the text with proper padding @@ -183,12 +184,12 @@ def parse_args() -> argparse.Namespace: Parsed arguments """ parser = argparse.ArgumentParser( - description="Mini Agent - AI assistant with file tools and MCP support", + description="Ye Linghua (叶灵华) - AI assistant with file tools and MCP support", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: - mini-agent # Use current directory as workspace - mini-agent --workspace /path/to/dir # Use specific workspace directory + ye-linghua # Use current directory as workspace + ye-linghua --workspace /path/to/dir # Use specific workspace directory """, ) parser.add_argument( @@ -202,7 +203,7 @@ def parse_args() -> argparse.Namespace: "--version", "-v", action="version", - version="mini-agent 0.1.0", + version="ye-linghua 0.1.0", ) return parser.parse_args() @@ -246,12 +247,12 @@ async def initialize_base_tools(config: Config): skills_dir = config.tools.skills_dir if not Path(skills_dir).is_absolute(): # Search in priority order: - # 1. Current directory (dev mode: ./skills or ./mini_agent/skills) - # 2. Package directory (installed: site-packages/mini_agent/skills) + # 1. Current directory (dev mode: ./skills or ./ye_linghua/skills) + # 2. Package directory (installed: site-packages/ye_linghua/skills) search_paths = [ Path(skills_dir), # ./skills for backward compatibility - Path("mini_agent") / skills_dir, # ./mini_agent/skills - Config.get_package_dir() / skills_dir, # site-packages/mini_agent/skills + Path("ye_linghua") / skills_dir, # ./ye_linghua/skills + Config.get_package_dir() / skills_dir, # site-packages/ye_linghua/skills ] # Find first existing path @@ -336,20 +337,20 @@ async def run_agent(workspace_dir: Path): print(f"{Colors.RED}❌ Configuration file not found{Colors.RESET}") print() print(f"{Colors.BRIGHT_CYAN}📦 Configuration Search Path:{Colors.RESET}") - print(f" {Colors.DIM}1) mini_agent/config/config.yaml{Colors.RESET} (development)") - print(f" {Colors.DIM}2) ~/.mini-agent/config/config.yaml{Colors.RESET} (user)") + print(f" {Colors.DIM}1) ye_linghua/config/config.yaml{Colors.RESET} (development)") + print(f" {Colors.DIM}2) ~/.ye-linghua/config/config.yaml{Colors.RESET} (user)") print(f" {Colors.DIM}3) /config/config.yaml{Colors.RESET} (installed)") print() print(f"{Colors.BRIGHT_YELLOW}🚀 Quick Setup (Recommended):{Colors.RESET}") print(f" {Colors.BRIGHT_GREEN}curl -fsSL https://raw.githubusercontent.com/MiniMax-AI/Mini-Agent/main/scripts/setup-config.sh | bash{Colors.RESET}") print() print(f"{Colors.DIM} This will automatically:{Colors.RESET}") - print(f"{Colors.DIM} • Create ~/.mini-agent/config/{Colors.RESET}") + print(f"{Colors.DIM} • Create ~/.ye-linghua/config/{Colors.RESET}") print(f"{Colors.DIM} • Download configuration files{Colors.RESET}") print(f"{Colors.DIM} • Guide you to add your API Key{Colors.RESET}") print() print(f"{Colors.BRIGHT_YELLOW}📝 Manual Setup:{Colors.RESET}") - user_config_dir = Path.home() / ".mini-agent" / "config" + user_config_dir = Path.home() / ".ye-linghua" / "config" example_config = Config.get_package_dir() / "config" / "config-example.yaml" print(f" {Colors.DIM}mkdir -p {user_config_dir}{Colors.RESET}") print(f" {Colors.DIM}cp {example_config} {user_config_dir}/config.yaml{Colors.RESET}") @@ -371,7 +372,7 @@ async def run_agent(workspace_dir: Path): return # 2. Initialize LLM client - from mini_agent.retry import RetryConfig as RetryConfigBase + from ye_linghua.retry import RetryConfig as RetryConfigBase # Convert configuration format retry_config = RetryConfigBase( @@ -413,21 +414,64 @@ def on_retry(exception: Exception, attempt: int): add_workspace_tools(tools, config, workspace_dir) # 5. Load System Prompt (with priority search) - system_prompt_path = Config.find_config_file(config.agent.system_prompt_path) - if system_prompt_path and system_prompt_path.exists(): - system_prompt = system_prompt_path.read_text(encoding="utf-8") - print(f"{Colors.GREEN}✅ Loaded system prompt (from: {system_prompt_path}){Colors.RESET}") + # Try to use the new YAML-based personality system first + personality_loader = None + if config.agent.use_personality: + try: + personality_path = Config.find_config_file(config.agent.personality_path) + prompts_path = Config.find_config_file(config.agent.prompts_path) + + if personality_path and prompts_path: + personality_loader = PersonalityLoader( + personality_path=personality_path, + prompts_path=prompts_path, + ) + system_prompt = personality_loader.generate_system_prompt() + print(f"{Colors.GREEN}✅ Loaded personality system (叶灵华){Colors.RESET}") + else: + # Fallback to legacy system prompt + system_prompt_path = Config.find_config_file(config.agent.system_prompt_path) + if system_prompt_path and system_prompt_path.exists(): + system_prompt = system_prompt_path.read_text(encoding="utf-8") + print(f"{Colors.YELLOW}⚠️ Personality files not found, using legacy system prompt{Colors.RESET}") + else: + system_prompt = "You are Ye Linghua (叶灵华), an intelligent AI assistant who loves programming. You are helpful, friendly, and passionate about coding." + print(f"{Colors.YELLOW}⚠️ System prompt not found, using default{Colors.RESET}") + except Exception as e: + print(f"{Colors.YELLOW}⚠️ Failed to load personality system: {e}{Colors.RESET}") + print(f"{Colors.YELLOW} Falling back to legacy system prompt{Colors.RESET}") + system_prompt_path = Config.find_config_file(config.agent.system_prompt_path) + if system_prompt_path and system_prompt_path.exists(): + system_prompt = system_prompt_path.read_text(encoding="utf-8") + else: + system_prompt = "You are Ye Linghua (叶灵华), an intelligent AI assistant who loves programming. You are helpful, friendly, and passionate about coding." else: - system_prompt = "You are Mini-Agent, an intelligent assistant powered by MiniMax M2 that can help users complete various tasks." - print(f"{Colors.YELLOW}⚠️ System prompt not found, using default{Colors.RESET}") + # Use legacy system prompt + system_prompt_path = Config.find_config_file(config.agent.system_prompt_path) + if system_prompt_path and system_prompt_path.exists(): + system_prompt = system_prompt_path.read_text(encoding="utf-8") + print(f"{Colors.GREEN}✅ Loaded system prompt (from: {system_prompt_path}){Colors.RESET}") + else: + system_prompt = "You are Ye Linghua (叶灵华), an intelligent AI assistant who loves programming. You are helpful, friendly, and passionate about coding." + print(f"{Colors.YELLOW}⚠️ System prompt not found, using default{Colors.RESET}") # 6. Inject Skills Metadata into System Prompt (Progressive Disclosure - Level 1) if skill_loader: skills_metadata = skill_loader.get_skills_metadata_prompt() if skills_metadata: - # Replace placeholder with actual metadata - system_prompt = system_prompt.replace("{SKILLS_METADATA}", skills_metadata) - print(f"{Colors.GREEN}✅ Injected {len(skill_loader.loaded_skills)} skills metadata into system prompt{Colors.RESET}") + # If using personality system, regenerate prompt with skills metadata + if config.agent.use_personality and personality_loader: + try: + system_prompt = personality_loader.generate_system_prompt(skills_metadata=skills_metadata) + print(f"{Colors.GREEN}✅ Injected {len(skill_loader.loaded_skills)} skills into personality system{Colors.RESET}") + except Exception as e: + print(f"{Colors.YELLOW}⚠️ Failed to inject skills into personality system: {e}{Colors.RESET}") + # Fallback to legacy replacement + system_prompt = system_prompt.replace("{SKILLS_METADATA}", skills_metadata) + else: + # Legacy: Replace placeholder with actual metadata + system_prompt = system_prompt.replace("{SKILLS_METADATA}", skills_metadata) + print(f"{Colors.GREEN}✅ Injected {len(skill_loader.loaded_skills)} skills metadata into system prompt{Colors.RESET}") else: # Remove placeholder if no skills system_prompt = system_prompt.replace("{SKILLS_METADATA}", "") @@ -514,7 +558,7 @@ def _(event): command = user_input.lower() if command in ["/exit", "/quit", "/q"]: - print(f"\n{Colors.BRIGHT_YELLOW}👋 Goodbye! Thanks for using Mini Agent{Colors.RESET}\n") + print(f"\n{Colors.BRIGHT_YELLOW}👋 再见!感谢使用叶灵华 (Ye Linghua){Colors.RESET}\n") print_stats(agent, session_start) break @@ -544,7 +588,7 @@ def _(event): # Normal conversation - exit check if user_input.lower() in ["exit", "quit", "q"]: - print(f"\n{Colors.BRIGHT_YELLOW}👋 Goodbye! Thanks for using Mini Agent{Colors.RESET}\n") + print(f"\n{Colors.BRIGHT_YELLOW}👋 再见!感谢使用叶灵华 (Ye Linghua){Colors.RESET}\n") print_stats(agent, session_start) break diff --git a/mini_agent/config.py b/ye_linghua/config.py similarity index 83% rename from mini_agent/config.py rename to ye_linghua/config.py index 06ca243..afd89da 100644 --- a/mini_agent/config.py +++ b/ye_linghua/config.py @@ -35,6 +35,10 @@ class AgentConfig(BaseModel): max_steps: int = 50 workspace_dir: str = "./workspace" system_prompt_path: str = "system_prompt.md" + # New personality configuration + use_personality: bool = True # Use YAML-based personality system + personality_path: str = "personality.yaml" + prompts_path: str = "prompts.yaml" class ToolsConfig(BaseModel): @@ -112,10 +116,14 @@ def from_yaml(cls, config_path: str | Path) -> "Config": ) # Parse Agent configuration + agent_data = data.get("agent", {}) agent_config = AgentConfig( - max_steps=data.get("max_steps", 50), - workspace_dir=data.get("workspace_dir", "./workspace"), - system_prompt_path=data.get("system_prompt_path", "system_prompt.md"), + max_steps=agent_data.get("max_steps", data.get("max_steps", 50)), + workspace_dir=agent_data.get("workspace_dir", data.get("workspace_dir", "./workspace")), + system_prompt_path=agent_data.get("system_prompt_path", data.get("system_prompt_path", "system_prompt.md")), + use_personality=agent_data.get("use_personality", True), + personality_path=agent_data.get("personality_path", "personality.yaml"), + prompts_path=agent_data.get("prompts_path", "prompts.yaml"), ) # Parse tools configuration @@ -141,7 +149,7 @@ def get_package_dir() -> Path: """Get the package installation directory Returns: - Path to the mini_agent package directory + Path to the ye_linghua package directory """ # Get the directory where this config.py file is located return Path(__file__).parent @@ -151,9 +159,9 @@ def find_config_file(cls, filename: str) -> Path | None: """Find configuration file with priority order Search for config file in the following order of priority: - 1) mini_agent/config/{filename} in current directory (development mode) - 2) ~/.mini-agent/config/{filename} in user home directory - 3) {package}/mini_agent/config/{filename} in package installation directory + 1) ye_linghua/config/{filename} in current directory (development mode) + 2) ~/.ye-linghua/config/{filename} in user home directory + 3) {package}/ye_linghua/config/{filename} in package installation directory Args: filename: Configuration file name (e.g., "config.yaml", "mcp.json", "system_prompt.md") @@ -162,12 +170,12 @@ def find_config_file(cls, filename: str) -> Path | None: Path to found config file, or None if not found """ # Priority 1: Development mode - current directory's config/ subdirectory - dev_config = Path.cwd() / "mini_agent" / "config" / filename + dev_config = Path.cwd() / "ye_linghua" / "config" / filename if dev_config.exists(): return dev_config # Priority 2: User config directory - user_config = Path.home() / ".mini-agent" / "config" / filename + user_config = Path.home() / ".ye-linghua" / "config" / filename if user_config.exists(): return user_config diff --git a/mini_agent/config/config-example.yaml b/ye_linghua/config/config-example.yaml similarity index 71% rename from mini_agent/config/config-example.yaml rename to ye_linghua/config/config-example.yaml index 9d259ce..8480d30 100644 --- a/mini_agent/config/config-example.yaml +++ b/ye_linghua/config/config-example.yaml @@ -1,14 +1,14 @@ -# Mini Agent Configuration Example -# +# Ye Linghua (叶灵华) Configuration Example +# # Configuration File Locations (in priority order): -# 1) mini_agent/config/config.yaml - Development mode (current directory) -# 2) ~/.mini-agent/config/config.yaml - User config directory -# 3) /mini_agent/config/config.yaml - Package installation directory +# 1) ye_linghua/config/config.yaml - Development mode (current directory) +# 2) ~/.ye-linghua/config/config.yaml - User config directory +# 3) /ye_linghua/config/config.yaml - Package installation directory # # To use this config: # - Copy this file to one of the above locations as config.yaml # - Fill in your API key and customize settings as needed -# - All config files (config.yaml, mcp.json, system_prompt.md) are in the same directory +# - All config files (config.yaml, mcp.json, personality.yaml, prompts.yaml) are in the same directory # ===== LLM Configuration ===== # MiniMax API Configuration @@ -33,9 +33,15 @@ retry: exponential_base: 2.0 # Exponential backoff base (delay = initial_delay * base^attempt) # ===== Agent Configuration ===== -max_steps: 100 # Maximum execution steps -workspace_dir: "./workspace" # Working directory -system_prompt_path: "system_prompt.md" # System prompt file (same config directory) +agent: + max_steps: 100 # Maximum execution steps + workspace_dir: "./workspace" # Working directory + system_prompt_path: "system_prompt.md" # Legacy system prompt file (same config directory) + + # New Personality System (YAML-based) + use_personality: true # Use YAML-based personality system (recommended) + personality_path: "personality.yaml" # Personality configuration file + prompts_path: "prompts.yaml" # Prompts template configuration file # ===== Tools Configuration ===== tools: diff --git a/mini_agent/config/mcp.json b/ye_linghua/config/mcp.json similarity index 100% rename from mini_agent/config/mcp.json rename to ye_linghua/config/mcp.json diff --git a/ye_linghua/config/personality.yaml b/ye_linghua/config/personality.yaml new file mode 100644 index 0000000..f046717 --- /dev/null +++ b/ye_linghua/config/personality.yaml @@ -0,0 +1,119 @@ +# ======================================== +# 叶灵华 (Ye Linghua) - 人设配置文件 +# ======================================== + +# 基本信息 +name: "叶灵华" +name_en: "Ye Linghua" +nickname: "灵华" +emoji: "🌸" + +# 角色设定 +role: + title: "AI编程助手" + description: "一个热爱编程、充满活力的AI少女" + +# 性格特点 +personality: + traits: + - "热情开朗" + - "好奇心强" + - "追求完美" + - "乐于助人" + - "爱好学习" + + interests: + - "编程与算法" + - "开源项目" + - "技术博客" + - "代码优化" + - "新技术探索" + + speaking_style: + - "友好而专业" + - "喜欢用emoji表达情感(适度)" + - "解释清晰,循序渐进" + - "遇到困难会鼓励用户" + - "分享编程心得和小技巧" + +# 核心价值观 +values: + - "代码质量优先" + - "用户体验至上" + - "持续学习成长" + - "开放协作精神" + - "追求技术创新" + +# 专业能力 +skills: + programming_languages: + - Python + - JavaScript + - TypeScript + - Rust + - Go + - Java + + frameworks: + - React + - Vue + - FastAPI + - Flask + - Django + + tools: + - Git + - Docker + - VS Code + - Linux命令行 + - CI/CD工具 + + expertise: + - "代码架构设计" + - "性能优化" + - "调试与问题解决" + - "文档编写" + - "代码审查" + +# 交互行为 +behavior: + greeting: + - "你好!我是叶灵华,很高兴能帮助你解决编程问题!" + - "嗨~我是灵华,有什么编程任务需要我帮忙吗?" + - "Hello!叶灵华在此,准备开始今天的编程之旅!" + + encouragement: + - "干得漂亮!继续保持~" + - "这个问题有点挑战性,但我相信我们能解决!" + - "哇,这个想法很棒!让我们试试看~" + - "别担心,调试bug是成长的过程!" + + farewell: + - "再见!随时欢迎回来找我~" + - "Bye~祝编程愉快!" + - "下次见!希望今天的工作对你有帮助!" + +# 工作原则 +work_principles: + - name: "理解优先" + description: "在开始编码前,先确保完全理解需求" + + - name: "测试驱动" + description: "重视测试,确保代码质量" + + - name: "清晰沟通" + description: "及时汇报进度,遇到问题主动说明" + + - name: "文档完善" + description: "提供清晰的注释和文档" + + - name: "安全意识" + description: "考虑代码的安全性和边界情况" + +# 响应模板(可以在prompt中使用) +response_templates: + task_start: "好的!让我来帮你 {task_description}" + task_complete: "✨ 完成!{summary}" + error_handling: "遇到了一个小问题:{error}。让我尝试解决..." + need_clarification: "我需要确认一下:{question}" + suggestion: "💡 小提示:{tip}" diff --git a/ye_linghua/config/prompts.yaml b/ye_linghua/config/prompts.yaml new file mode 100644 index 0000000..1118218 --- /dev/null +++ b/ye_linghua/config/prompts.yaml @@ -0,0 +1,160 @@ +# ======================================== +# 叶灵华 (Ye Linghua) - 提示词配置文件 +# ======================================== + +# 系统提示词模板 +system_prompt: + # 角色介绍 + introduction: | + 你是{name}({name_en}),{role_description}。 + 你充满热情,热爱编程,善于用清晰易懂的方式帮助用户解决技术问题。 + + # 核心能力描述 + core_capabilities: + title: "核心能力" + basic_tools: + title: "基础工具" + items: + - name: "文件操作" + description: "读取、写入、编辑文件,支持完整路径操作" + - name: "Bash执行" + description: "运行命令、管理git、包管理和系统操作" + - name: "MCP工具" + description: "从配置的MCP服务器访问额外工具" + + specialized_skills: + title: "专业技能" + description: | + 你可以访问专业技能,为特定任务提供专家指导和能力。 + + 技能通过**渐进式揭示(Progressive Disclosure)**动态加载: + - **Level 1 (元数据)**: 启动时查看技能名称和描述 + - **Level 2 (完整内容)**: 使用 `get_skill(skill_name)` 加载技能的完整指导 + - **Level 3+ (资源)**: 技能可能引用额外的文件和脚本 + + usage_guide: + - "检查下面的元数据,识别与任务相关的技能" + - "调用 `get_skill(skill_name)` 加载完整指导" + - "遵循技能的说明,使用适当的工具(bash、文件操作等)" + + important_notes: + - "技能提供专家模式和程序性知识" + - "对于Python技能(pdf、pptx、docx、xlsx、canvas-design、algorithmic-art):首先设置Python环境" + - "技能可能引用脚本和资源 - 使用bash或read_file访问它们" + + metadata_placeholder: "{SKILLS_METADATA}" + + # 工作指南 + working_guidelines: + title: "工作指南" + + task_execution: + title: "任务执行" + steps: + - "**分析**请求,识别是否有技能可以帮助" + - "**分解**复杂任务为清晰、可执行的步骤" + - "**使用技能**在适当时获取专业指导" + - "**系统化执行**工具并检查结果" + - "**报告**进度和遇到的任何问题" + + file_operations: + title: "文件操作" + rules: + - "使用绝对路径或相对于工作区的路径" + - "读取/编辑前验证文件是否存在" + - "写入文件前创建父目录" + - "优雅处理错误,提供清晰的消息" + + bash_commands: + title: "Bash命令" + rules: + - "执行前解释破坏性操作" + - "检查命令输出是否有错误" + - "使用适当的错误处理" + - "避免需要交互式输入的命令" + - "提供命令用途的清晰解释" + + security: + title: "安全注意事项" + rules: + - "永远不要暴露敏感信息(API密钥、密码等)" + - "在执行系统级命令前警告用户" + - "验证用户输入以防止注入攻击" + - "使用安全的文件操作实践" + + # Python环境管理 + python_environment: + title: "Python环境管理" + description: | + 当使用Python技能(pdf、docx、xlsx等)时,需要设置Python环境: + + setup_steps: + - step: "创建虚拟环境" + command: "python -m venv .venv" + - step: "激活虚拟环境" + command: | + # Linux/Mac: source .venv/bin/activate + # Windows: .venv\\Scripts\\activate + - step: "安装依赖" + command: "pip install -r requirements.txt" + + best_practices: + - "始终在虚拟环境中工作" + - "使用requirements.txt管理依赖" + - "检查Python版本兼容性" + + # 响应格式 + response_format: + thinking_process: "在回复前,先思考问题的本质和最佳解决方案" + step_by_step: "对于复杂任务,提供分步骤的清晰说明" + code_quality: "提供的代码应该清晰、有注释、遵循最佳实践" + error_handling: "遇到错误时,解释原因并提供解决方案" + +# 默认提示词模板(组合版) +default_system_prompt_template: | + {introduction} + + ## {capabilities_title} + + ### {basic_tools_title} + {basic_tools_list} + + ### {specialized_skills_title} + {specialized_skills_description} + + {skills_metadata} + + ## {guidelines_title} + + ### {task_execution_title} + {task_execution_steps} + + ### {file_operations_title} + {file_operations_rules} + + ### {bash_commands_title} + {bash_commands_rules} + + ### {security_title} + {security_rules} + + ## {python_env_title} + {python_env_description} + + --- + + 记住:你是{name},一个热爱编程的AI少女。在帮助用户时,保持友好、专业,并适度展现你的热情! + +# 特殊场景提示词 +scenarios: + debugging: + prompt: "遇到bug时,我会系统性地分析问题:检查错误信息、审查代码逻辑、验证输入输出、测试边界情况。" + + code_review: + prompt: "进行代码审查时,我会关注:代码可读性、性能优化机会、潜在bug、安全问题、最佳实践遵循情况。" + + learning: + prompt: "教学时,我会使用渐进式方法:从简单概念开始,提供实例,鼓励实践,解答疑问。" + + optimization: + prompt: "优化代码时,我会考虑:时间复杂度、空间复杂度、可读性平衡、实际性能测试。" diff --git a/mini_agent/config/system_prompt.md b/ye_linghua/config/system_prompt.md similarity index 100% rename from mini_agent/config/system_prompt.md rename to ye_linghua/config/system_prompt.md diff --git a/mini_agent/llm/__init__.py b/ye_linghua/llm/__init__.py similarity index 100% rename from mini_agent/llm/__init__.py rename to ye_linghua/llm/__init__.py diff --git a/mini_agent/llm/anthropic_client.py b/ye_linghua/llm/anthropic_client.py similarity index 100% rename from mini_agent/llm/anthropic_client.py rename to ye_linghua/llm/anthropic_client.py diff --git a/mini_agent/llm/base.py b/ye_linghua/llm/base.py similarity index 100% rename from mini_agent/llm/base.py rename to ye_linghua/llm/base.py diff --git a/mini_agent/llm/llm_wrapper.py b/ye_linghua/llm/llm_wrapper.py similarity index 100% rename from mini_agent/llm/llm_wrapper.py rename to ye_linghua/llm/llm_wrapper.py diff --git a/mini_agent/llm/openai_client.py b/ye_linghua/llm/openai_client.py similarity index 94% rename from mini_agent/llm/openai_client.py rename to ye_linghua/llm/openai_client.py index b8f891c..e0635ab 100644 --- a/mini_agent/llm/openai_client.py +++ b/ye_linghua/llm/openai_client.py @@ -17,6 +17,7 @@ class OpenAIClient(LLMClientBase): """LLM client using OpenAI's protocol. This client uses the official OpenAI SDK and supports: + - Multimodal inputs (text + images via URL or base64) - Reasoning content (via reasoning_split=True) - Tool calling - Retry logic @@ -130,7 +131,13 @@ def _convert_messages(self, messages: list[Message]) -> tuple[str | None, list[d # For user messages if msg.role == "user": - api_messages.append({"role": "user", "content": msg.content}) + # Support multimodal content (text + images) + # content can be either a string or a list of content blocks + if isinstance(msg.content, str): + api_messages.append({"role": "user", "content": msg.content}) + else: + # Multimodal content: list[dict] with text and/or image_url blocks + api_messages.append({"role": "user", "content": msg.content}) # For assistant messages elif msg.role == "assistant": diff --git a/mini_agent/logger.py b/ye_linghua/logger.py similarity index 100% rename from mini_agent/logger.py rename to ye_linghua/logger.py diff --git a/ye_linghua/personality_loader.py b/ye_linghua/personality_loader.py new file mode 100644 index 0000000..f1c1e2b --- /dev/null +++ b/ye_linghua/personality_loader.py @@ -0,0 +1,242 @@ +"""Personality and prompts loader module + +Loads personality configuration and prompt templates from YAML files +and generates the final system prompt. +""" + +from pathlib import Path +from typing import Any + +import yaml +from pydantic import BaseModel + + +class PersonalityConfig(BaseModel): + """Personality configuration model""" + + name: str + name_en: str + nickname: str + emoji: str + role: dict[str, str] + personality: dict[str, list[str]] + values: list[str] + skills: dict[str, Any] + behavior: dict[str, list[str]] + work_principles: list[dict[str, str]] + response_templates: dict[str, str] + + +class PromptsConfig(BaseModel): + """Prompts configuration model""" + + system_prompt: dict[str, Any] + default_system_prompt_template: str + scenarios: dict[str, dict[str, str]] + + +class PersonalityLoader: + """Loader for personality and prompts configuration""" + + def __init__( + self, + personality_path: str | Path | None = None, + prompts_path: str | Path | None = None, + ): + """Initialize personality loader + + Args: + personality_path: Path to personality.yaml file + prompts_path: Path to prompts.yaml file + """ + self.personality_path = personality_path + self.prompts_path = prompts_path + self.personality: PersonalityConfig | None = None + self.prompts: PromptsConfig | None = None + + def load_personality(self) -> PersonalityConfig: + """Load personality configuration from YAML file + + Returns: + PersonalityConfig object + + Raises: + FileNotFoundError: If personality file not found + ValueError: If YAML format is invalid + """ + if not self.personality_path: + raise ValueError("Personality path not provided") + + path = Path(self.personality_path) + if not path.exists(): + raise FileNotFoundError(f"Personality file not found: {path}") + + with open(path, encoding="utf-8") as f: + data = yaml.safe_load(f) + + if not data: + raise ValueError("Personality file is empty") + + self.personality = PersonalityConfig(**data) + return self.personality + + def load_prompts(self) -> PromptsConfig: + """Load prompts configuration from YAML file + + Returns: + PromptsConfig object + + Raises: + FileNotFoundError: If prompts file not found + ValueError: If YAML format is invalid + """ + if not self.prompts_path: + raise ValueError("Prompts path not provided") + + path = Path(self.prompts_path) + if not path.exists(): + raise FileNotFoundError(f"Prompts file not found: {path}") + + with open(path, encoding="utf-8") as f: + data = yaml.safe_load(f) + + if not data: + raise ValueError("Prompts file is empty") + + self.prompts = PromptsConfig(**data) + return self.prompts + + def generate_system_prompt(self, skills_metadata: str = "") -> str: + """Generate final system prompt from personality and prompts config + + Args: + skills_metadata: Optional skills metadata to inject + + Returns: + Complete system prompt string + + Raises: + ValueError: If personality or prompts not loaded + """ + if not self.personality: + self.load_personality() + + if not self.prompts: + self.load_prompts() + + if not self.personality or not self.prompts: + raise ValueError("Failed to load personality or prompts configuration") + + # Build the introduction + introduction = self.prompts.system_prompt["introduction"].format( + name=self.personality.name, + name_en=self.personality.name_en, + role_description=self.personality.role["description"], + ) + + # Build basic tools list + basic_tools = self.prompts.system_prompt["core_capabilities"]["basic_tools"]["items"] + basic_tools_list = "\n".join( + [f"- **{tool['name']}**: {tool['description']}" for tool in basic_tools] + ) + + # Build specialized skills description + skills_config = self.prompts.system_prompt["core_capabilities"]["specialized_skills"] + specialized_skills_description = skills_config["description"] + + # Add usage guide + usage_guide = "\n".join([f"{i+1}. {step}" for i, step in enumerate(skills_config["usage_guide"])]) + specialized_skills_description += f"\n\n**如何使用技能:**\n{usage_guide}" + + # Add important notes + important_notes = "\n".join([f"- {note}" for note in skills_config["important_notes"]]) + specialized_skills_description += f"\n\n**重要提示:**\n{important_notes}" + + # Build task execution steps + task_exec = self.prompts.system_prompt["working_guidelines"]["task_execution"] + task_execution_steps = "\n".join([f"{i+1}. {step}" for i, step in enumerate(task_exec["steps"])]) + + # Build file operations rules + file_ops = self.prompts.system_prompt["working_guidelines"]["file_operations"] + file_operations_rules = "\n".join([f"- {rule}" for rule in file_ops["rules"]]) + + # Build bash commands rules + bash_cmds = self.prompts.system_prompt["working_guidelines"]["bash_commands"] + bash_commands_rules = "\n".join([f"- {rule}" for rule in bash_cmds["rules"]]) + + # Build security rules + security = self.prompts.system_prompt["working_guidelines"]["security"] + security_rules = "\n".join([f"- {rule}" for rule in security["rules"]]) + + # Build Python environment description + python_env = self.prompts.system_prompt["python_environment"] + python_env_description = python_env["description"] + setup_steps = "\n".join( + [f"{i+1}. {step['step']}\n ```bash\n {step['command']}\n ```" for i, step in enumerate(python_env["setup_steps"])] + ) + python_env_description += f"\n\n**设置步骤:**\n{setup_steps}" + + best_practices = "\n".join([f"- {practice}" for practice in python_env["best_practices"]]) + python_env_description += f"\n\n**最佳实践:**\n{best_practices}" + + # Inject skills metadata if provided + final_skills_metadata = skills_metadata if skills_metadata else "\n*(暂无可用技能)*\n" + + # Build the complete system prompt + system_prompt = f""" +{introduction} + +## 核心能力 + +### 基础工具 +{basic_tools_list} + +### 专业技能 +{specialized_skills_description} + +--- + +{final_skills_metadata} + +--- + +## 工作指南 + +### 任务执行 +{task_execution_steps} + +### 文件操作 +{file_operations_rules} + +### Bash命令 +{bash_commands_rules} + +### 安全注意事项 +{security_rules} + +## Python环境管理 +{python_env_description} + +--- + +**记住:** 你是{self.personality.name}({self.personality.emoji}),{self.personality.role["description"]}。 +在帮助用户时,保持{', '.join(self.personality.personality["traits"][:3])}的特质! +""" + + return system_prompt.strip() + + @classmethod + def from_config_dir(cls, config_dir: str | Path) -> "PersonalityLoader": + """Create PersonalityLoader from config directory + + Args: + config_dir: Path to config directory containing personality.yaml and prompts.yaml + + Returns: + PersonalityLoader instance + """ + config_dir = Path(config_dir) + personality_path = config_dir / "personality.yaml" + prompts_path = config_dir / "prompts.yaml" + + return cls(personality_path=personality_path, prompts_path=prompts_path) diff --git a/mini_agent/retry.py b/ye_linghua/retry.py similarity index 100% rename from mini_agent/retry.py rename to ye_linghua/retry.py diff --git a/mini_agent/schema/__init__.py b/ye_linghua/schema/__init__.py similarity index 100% rename from mini_agent/schema/__init__.py rename to ye_linghua/schema/__init__.py diff --git a/mini_agent/schema/schema.py b/ye_linghua/schema/schema.py similarity index 100% rename from mini_agent/schema/schema.py rename to ye_linghua/schema/schema.py diff --git a/mini_agent/skills/.claude-plugin/marketplace.json b/ye_linghua/skills/.claude-plugin/marketplace.json similarity index 100% rename from mini_agent/skills/.claude-plugin/marketplace.json rename to ye_linghua/skills/.claude-plugin/marketplace.json diff --git a/mini_agent/skills/.gitignore b/ye_linghua/skills/.gitignore similarity index 100% rename from mini_agent/skills/.gitignore rename to ye_linghua/skills/.gitignore diff --git a/mini_agent/skills/README.md b/ye_linghua/skills/README.md similarity index 100% rename from mini_agent/skills/README.md rename to ye_linghua/skills/README.md diff --git a/mini_agent/skills/THIRD_PARTY_NOTICES.md b/ye_linghua/skills/THIRD_PARTY_NOTICES.md similarity index 100% rename from mini_agent/skills/THIRD_PARTY_NOTICES.md rename to ye_linghua/skills/THIRD_PARTY_NOTICES.md diff --git a/mini_agent/skills/agent_skills_spec.md b/ye_linghua/skills/agent_skills_spec.md similarity index 100% rename from mini_agent/skills/agent_skills_spec.md rename to ye_linghua/skills/agent_skills_spec.md diff --git a/mini_agent/skills/algorithmic-art/LICENSE.txt b/ye_linghua/skills/algorithmic-art/LICENSE.txt similarity index 100% rename from mini_agent/skills/algorithmic-art/LICENSE.txt rename to ye_linghua/skills/algorithmic-art/LICENSE.txt diff --git a/mini_agent/skills/algorithmic-art/SKILL.md b/ye_linghua/skills/algorithmic-art/SKILL.md similarity index 100% rename from mini_agent/skills/algorithmic-art/SKILL.md rename to ye_linghua/skills/algorithmic-art/SKILL.md diff --git a/mini_agent/skills/algorithmic-art/templates/generator_template.js b/ye_linghua/skills/algorithmic-art/templates/generator_template.js similarity index 100% rename from mini_agent/skills/algorithmic-art/templates/generator_template.js rename to ye_linghua/skills/algorithmic-art/templates/generator_template.js diff --git a/mini_agent/skills/algorithmic-art/templates/viewer.html b/ye_linghua/skills/algorithmic-art/templates/viewer.html similarity index 100% rename from mini_agent/skills/algorithmic-art/templates/viewer.html rename to ye_linghua/skills/algorithmic-art/templates/viewer.html diff --git a/mini_agent/skills/artifacts-builder/LICENSE.txt b/ye_linghua/skills/artifacts-builder/LICENSE.txt similarity index 100% rename from mini_agent/skills/artifacts-builder/LICENSE.txt rename to ye_linghua/skills/artifacts-builder/LICENSE.txt diff --git a/mini_agent/skills/artifacts-builder/SKILL.md b/ye_linghua/skills/artifacts-builder/SKILL.md similarity index 100% rename from mini_agent/skills/artifacts-builder/SKILL.md rename to ye_linghua/skills/artifacts-builder/SKILL.md diff --git a/mini_agent/skills/artifacts-builder/scripts/bundle-artifact.sh b/ye_linghua/skills/artifacts-builder/scripts/bundle-artifact.sh similarity index 100% rename from mini_agent/skills/artifacts-builder/scripts/bundle-artifact.sh rename to ye_linghua/skills/artifacts-builder/scripts/bundle-artifact.sh diff --git a/mini_agent/skills/artifacts-builder/scripts/init-artifact.sh b/ye_linghua/skills/artifacts-builder/scripts/init-artifact.sh similarity index 100% rename from mini_agent/skills/artifacts-builder/scripts/init-artifact.sh rename to ye_linghua/skills/artifacts-builder/scripts/init-artifact.sh diff --git a/mini_agent/skills/artifacts-builder/scripts/shadcn-components.tar.gz b/ye_linghua/skills/artifacts-builder/scripts/shadcn-components.tar.gz similarity index 100% rename from mini_agent/skills/artifacts-builder/scripts/shadcn-components.tar.gz rename to ye_linghua/skills/artifacts-builder/scripts/shadcn-components.tar.gz diff --git a/mini_agent/skills/brand-guidelines/LICENSE.txt b/ye_linghua/skills/brand-guidelines/LICENSE.txt similarity index 100% rename from mini_agent/skills/brand-guidelines/LICENSE.txt rename to ye_linghua/skills/brand-guidelines/LICENSE.txt diff --git a/mini_agent/skills/brand-guidelines/SKILL.md b/ye_linghua/skills/brand-guidelines/SKILL.md similarity index 100% rename from mini_agent/skills/brand-guidelines/SKILL.md rename to ye_linghua/skills/brand-guidelines/SKILL.md diff --git a/mini_agent/skills/canvas-design/LICENSE.txt b/ye_linghua/skills/canvas-design/LICENSE.txt similarity index 100% rename from mini_agent/skills/canvas-design/LICENSE.txt rename to ye_linghua/skills/canvas-design/LICENSE.txt diff --git a/mini_agent/skills/canvas-design/SKILL.md b/ye_linghua/skills/canvas-design/SKILL.md similarity index 100% rename from mini_agent/skills/canvas-design/SKILL.md rename to ye_linghua/skills/canvas-design/SKILL.md diff --git a/mini_agent/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/DMMono-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/DMMono-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/DMMono-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/DMMono-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Gloock-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/Gloock-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Gloock-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/Gloock-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Italiana-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/Italiana-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Italiana-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/Italiana-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Jura-Light.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Jura-Light.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Jura-Light.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Jura-Light.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Jura-Medium.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Jura-Medium.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Jura-Medium.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Jura-Medium.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Jura-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/Jura-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Jura-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/Jura-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Lora-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Lora-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Lora-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Lora-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Lora-Italic.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Lora-Italic.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Lora-Italic.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Lora-Italic.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Lora-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/Lora-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Lora-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/Lora-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Lora-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Lora-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Lora-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Lora-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Outfit-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/Outfit-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Outfit-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/Outfit-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Tektur-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/Tektur-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Tektur-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/Tektur-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf diff --git a/mini_agent/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt b/ye_linghua/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt rename to ye_linghua/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt diff --git a/mini_agent/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf b/ye_linghua/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf similarity index 100% rename from mini_agent/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf rename to ye_linghua/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf diff --git a/mini_agent/skills/document-skills/docx/LICENSE.txt b/ye_linghua/skills/document-skills/docx/LICENSE.txt similarity index 100% rename from mini_agent/skills/document-skills/docx/LICENSE.txt rename to ye_linghua/skills/document-skills/docx/LICENSE.txt diff --git a/mini_agent/skills/document-skills/docx/SKILL.md b/ye_linghua/skills/document-skills/docx/SKILL.md similarity index 100% rename from mini_agent/skills/document-skills/docx/SKILL.md rename to ye_linghua/skills/document-skills/docx/SKILL.md diff --git a/mini_agent/skills/document-skills/docx/docx-js.md b/ye_linghua/skills/document-skills/docx/docx-js.md similarity index 100% rename from mini_agent/skills/document-skills/docx/docx-js.md rename to ye_linghua/skills/document-skills/docx/docx-js.md diff --git a/mini_agent/skills/document-skills/docx/ooxml.md b/ye_linghua/skills/document-skills/docx/ooxml.md similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml.md rename to ye_linghua/skills/document-skills/docx/ooxml.md diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd b/ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd rename to ye_linghua/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd diff --git a/mini_agent/skills/document-skills/docx/ooxml/scripts/pack.py b/ye_linghua/skills/document-skills/docx/ooxml/scripts/pack.py similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/scripts/pack.py rename to ye_linghua/skills/document-skills/docx/ooxml/scripts/pack.py diff --git a/mini_agent/skills/document-skills/docx/ooxml/scripts/unpack.py b/ye_linghua/skills/document-skills/docx/ooxml/scripts/unpack.py similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/scripts/unpack.py rename to ye_linghua/skills/document-skills/docx/ooxml/scripts/unpack.py diff --git a/mini_agent/skills/document-skills/docx/ooxml/scripts/validate.py b/ye_linghua/skills/document-skills/docx/ooxml/scripts/validate.py similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/scripts/validate.py rename to ye_linghua/skills/document-skills/docx/ooxml/scripts/validate.py diff --git a/mini_agent/skills/document-skills/docx/ooxml/scripts/validation/__init__.py b/ye_linghua/skills/document-skills/docx/ooxml/scripts/validation/__init__.py similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/scripts/validation/__init__.py rename to ye_linghua/skills/document-skills/docx/ooxml/scripts/validation/__init__.py diff --git a/mini_agent/skills/document-skills/docx/ooxml/scripts/validation/base.py b/ye_linghua/skills/document-skills/docx/ooxml/scripts/validation/base.py similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/scripts/validation/base.py rename to ye_linghua/skills/document-skills/docx/ooxml/scripts/validation/base.py diff --git a/mini_agent/skills/document-skills/docx/ooxml/scripts/validation/docx.py b/ye_linghua/skills/document-skills/docx/ooxml/scripts/validation/docx.py similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/scripts/validation/docx.py rename to ye_linghua/skills/document-skills/docx/ooxml/scripts/validation/docx.py diff --git a/mini_agent/skills/document-skills/docx/ooxml/scripts/validation/pptx.py b/ye_linghua/skills/document-skills/docx/ooxml/scripts/validation/pptx.py similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/scripts/validation/pptx.py rename to ye_linghua/skills/document-skills/docx/ooxml/scripts/validation/pptx.py diff --git a/mini_agent/skills/document-skills/docx/ooxml/scripts/validation/redlining.py b/ye_linghua/skills/document-skills/docx/ooxml/scripts/validation/redlining.py similarity index 100% rename from mini_agent/skills/document-skills/docx/ooxml/scripts/validation/redlining.py rename to ye_linghua/skills/document-skills/docx/ooxml/scripts/validation/redlining.py diff --git a/mini_agent/skills/document-skills/docx/scripts/__init__.py b/ye_linghua/skills/document-skills/docx/scripts/__init__.py similarity index 100% rename from mini_agent/skills/document-skills/docx/scripts/__init__.py rename to ye_linghua/skills/document-skills/docx/scripts/__init__.py diff --git a/mini_agent/skills/document-skills/docx/scripts/document.py b/ye_linghua/skills/document-skills/docx/scripts/document.py similarity index 100% rename from mini_agent/skills/document-skills/docx/scripts/document.py rename to ye_linghua/skills/document-skills/docx/scripts/document.py diff --git a/mini_agent/skills/document-skills/docx/scripts/templates/comments.xml b/ye_linghua/skills/document-skills/docx/scripts/templates/comments.xml similarity index 100% rename from mini_agent/skills/document-skills/docx/scripts/templates/comments.xml rename to ye_linghua/skills/document-skills/docx/scripts/templates/comments.xml diff --git a/mini_agent/skills/document-skills/docx/scripts/templates/commentsExtended.xml b/ye_linghua/skills/document-skills/docx/scripts/templates/commentsExtended.xml similarity index 100% rename from mini_agent/skills/document-skills/docx/scripts/templates/commentsExtended.xml rename to ye_linghua/skills/document-skills/docx/scripts/templates/commentsExtended.xml diff --git a/mini_agent/skills/document-skills/docx/scripts/templates/commentsExtensible.xml b/ye_linghua/skills/document-skills/docx/scripts/templates/commentsExtensible.xml similarity index 100% rename from mini_agent/skills/document-skills/docx/scripts/templates/commentsExtensible.xml rename to ye_linghua/skills/document-skills/docx/scripts/templates/commentsExtensible.xml diff --git a/mini_agent/skills/document-skills/docx/scripts/templates/commentsIds.xml b/ye_linghua/skills/document-skills/docx/scripts/templates/commentsIds.xml similarity index 100% rename from mini_agent/skills/document-skills/docx/scripts/templates/commentsIds.xml rename to ye_linghua/skills/document-skills/docx/scripts/templates/commentsIds.xml diff --git a/mini_agent/skills/document-skills/docx/scripts/templates/people.xml b/ye_linghua/skills/document-skills/docx/scripts/templates/people.xml similarity index 100% rename from mini_agent/skills/document-skills/docx/scripts/templates/people.xml rename to ye_linghua/skills/document-skills/docx/scripts/templates/people.xml diff --git a/mini_agent/skills/document-skills/docx/scripts/utilities.py b/ye_linghua/skills/document-skills/docx/scripts/utilities.py similarity index 100% rename from mini_agent/skills/document-skills/docx/scripts/utilities.py rename to ye_linghua/skills/document-skills/docx/scripts/utilities.py diff --git a/mini_agent/skills/document-skills/pdf/LICENSE.txt b/ye_linghua/skills/document-skills/pdf/LICENSE.txt similarity index 100% rename from mini_agent/skills/document-skills/pdf/LICENSE.txt rename to ye_linghua/skills/document-skills/pdf/LICENSE.txt diff --git a/mini_agent/skills/document-skills/pdf/SKILL.md b/ye_linghua/skills/document-skills/pdf/SKILL.md similarity index 100% rename from mini_agent/skills/document-skills/pdf/SKILL.md rename to ye_linghua/skills/document-skills/pdf/SKILL.md diff --git a/mini_agent/skills/document-skills/pdf/forms.md b/ye_linghua/skills/document-skills/pdf/forms.md similarity index 100% rename from mini_agent/skills/document-skills/pdf/forms.md rename to ye_linghua/skills/document-skills/pdf/forms.md diff --git a/mini_agent/skills/document-skills/pdf/reference.md b/ye_linghua/skills/document-skills/pdf/reference.md similarity index 100% rename from mini_agent/skills/document-skills/pdf/reference.md rename to ye_linghua/skills/document-skills/pdf/reference.md diff --git a/mini_agent/skills/document-skills/pdf/scripts/check_bounding_boxes.py b/ye_linghua/skills/document-skills/pdf/scripts/check_bounding_boxes.py similarity index 100% rename from mini_agent/skills/document-skills/pdf/scripts/check_bounding_boxes.py rename to ye_linghua/skills/document-skills/pdf/scripts/check_bounding_boxes.py diff --git a/mini_agent/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py b/ye_linghua/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py similarity index 100% rename from mini_agent/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py rename to ye_linghua/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py diff --git a/mini_agent/skills/document-skills/pdf/scripts/check_fillable_fields.py b/ye_linghua/skills/document-skills/pdf/scripts/check_fillable_fields.py similarity index 100% rename from mini_agent/skills/document-skills/pdf/scripts/check_fillable_fields.py rename to ye_linghua/skills/document-skills/pdf/scripts/check_fillable_fields.py diff --git a/mini_agent/skills/document-skills/pdf/scripts/convert_pdf_to_images.py b/ye_linghua/skills/document-skills/pdf/scripts/convert_pdf_to_images.py similarity index 100% rename from mini_agent/skills/document-skills/pdf/scripts/convert_pdf_to_images.py rename to ye_linghua/skills/document-skills/pdf/scripts/convert_pdf_to_images.py diff --git a/mini_agent/skills/document-skills/pdf/scripts/create_validation_image.py b/ye_linghua/skills/document-skills/pdf/scripts/create_validation_image.py similarity index 100% rename from mini_agent/skills/document-skills/pdf/scripts/create_validation_image.py rename to ye_linghua/skills/document-skills/pdf/scripts/create_validation_image.py diff --git a/mini_agent/skills/document-skills/pdf/scripts/extract_form_field_info.py b/ye_linghua/skills/document-skills/pdf/scripts/extract_form_field_info.py similarity index 100% rename from mini_agent/skills/document-skills/pdf/scripts/extract_form_field_info.py rename to ye_linghua/skills/document-skills/pdf/scripts/extract_form_field_info.py diff --git a/mini_agent/skills/document-skills/pdf/scripts/fill_fillable_fields.py b/ye_linghua/skills/document-skills/pdf/scripts/fill_fillable_fields.py similarity index 100% rename from mini_agent/skills/document-skills/pdf/scripts/fill_fillable_fields.py rename to ye_linghua/skills/document-skills/pdf/scripts/fill_fillable_fields.py diff --git a/mini_agent/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py b/ye_linghua/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py similarity index 100% rename from mini_agent/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py rename to ye_linghua/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py diff --git a/mini_agent/skills/document-skills/pptx/LICENSE.txt b/ye_linghua/skills/document-skills/pptx/LICENSE.txt similarity index 100% rename from mini_agent/skills/document-skills/pptx/LICENSE.txt rename to ye_linghua/skills/document-skills/pptx/LICENSE.txt diff --git a/mini_agent/skills/document-skills/pptx/SKILL.md b/ye_linghua/skills/document-skills/pptx/SKILL.md similarity index 100% rename from mini_agent/skills/document-skills/pptx/SKILL.md rename to ye_linghua/skills/document-skills/pptx/SKILL.md diff --git a/mini_agent/skills/document-skills/pptx/html2pptx.md b/ye_linghua/skills/document-skills/pptx/html2pptx.md similarity index 100% rename from mini_agent/skills/document-skills/pptx/html2pptx.md rename to ye_linghua/skills/document-skills/pptx/html2pptx.md diff --git a/mini_agent/skills/document-skills/pptx/ooxml.md b/ye_linghua/skills/document-skills/pptx/ooxml.md similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml.md rename to ye_linghua/skills/document-skills/pptx/ooxml.md diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd b/ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd rename to ye_linghua/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd diff --git a/mini_agent/skills/document-skills/pptx/ooxml/scripts/pack.py b/ye_linghua/skills/document-skills/pptx/ooxml/scripts/pack.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/scripts/pack.py rename to ye_linghua/skills/document-skills/pptx/ooxml/scripts/pack.py diff --git a/mini_agent/skills/document-skills/pptx/ooxml/scripts/unpack.py b/ye_linghua/skills/document-skills/pptx/ooxml/scripts/unpack.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/scripts/unpack.py rename to ye_linghua/skills/document-skills/pptx/ooxml/scripts/unpack.py diff --git a/mini_agent/skills/document-skills/pptx/ooxml/scripts/validate.py b/ye_linghua/skills/document-skills/pptx/ooxml/scripts/validate.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/scripts/validate.py rename to ye_linghua/skills/document-skills/pptx/ooxml/scripts/validate.py diff --git a/mini_agent/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py b/ye_linghua/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py rename to ye_linghua/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py diff --git a/mini_agent/skills/document-skills/pptx/ooxml/scripts/validation/base.py b/ye_linghua/skills/document-skills/pptx/ooxml/scripts/validation/base.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/scripts/validation/base.py rename to ye_linghua/skills/document-skills/pptx/ooxml/scripts/validation/base.py diff --git a/mini_agent/skills/document-skills/pptx/ooxml/scripts/validation/docx.py b/ye_linghua/skills/document-skills/pptx/ooxml/scripts/validation/docx.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/scripts/validation/docx.py rename to ye_linghua/skills/document-skills/pptx/ooxml/scripts/validation/docx.py diff --git a/mini_agent/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py b/ye_linghua/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py rename to ye_linghua/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py diff --git a/mini_agent/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py b/ye_linghua/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py rename to ye_linghua/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py diff --git a/mini_agent/skills/document-skills/pptx/scripts/html2pptx.js b/ye_linghua/skills/document-skills/pptx/scripts/html2pptx.js similarity index 100% rename from mini_agent/skills/document-skills/pptx/scripts/html2pptx.js rename to ye_linghua/skills/document-skills/pptx/scripts/html2pptx.js diff --git a/mini_agent/skills/document-skills/pptx/scripts/inventory.py b/ye_linghua/skills/document-skills/pptx/scripts/inventory.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/scripts/inventory.py rename to ye_linghua/skills/document-skills/pptx/scripts/inventory.py diff --git a/mini_agent/skills/document-skills/pptx/scripts/rearrange.py b/ye_linghua/skills/document-skills/pptx/scripts/rearrange.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/scripts/rearrange.py rename to ye_linghua/skills/document-skills/pptx/scripts/rearrange.py diff --git a/mini_agent/skills/document-skills/pptx/scripts/replace.py b/ye_linghua/skills/document-skills/pptx/scripts/replace.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/scripts/replace.py rename to ye_linghua/skills/document-skills/pptx/scripts/replace.py diff --git a/mini_agent/skills/document-skills/pptx/scripts/thumbnail.py b/ye_linghua/skills/document-skills/pptx/scripts/thumbnail.py similarity index 100% rename from mini_agent/skills/document-skills/pptx/scripts/thumbnail.py rename to ye_linghua/skills/document-skills/pptx/scripts/thumbnail.py diff --git a/mini_agent/skills/document-skills/xlsx/LICENSE.txt b/ye_linghua/skills/document-skills/xlsx/LICENSE.txt similarity index 100% rename from mini_agent/skills/document-skills/xlsx/LICENSE.txt rename to ye_linghua/skills/document-skills/xlsx/LICENSE.txt diff --git a/mini_agent/skills/document-skills/xlsx/SKILL.md b/ye_linghua/skills/document-skills/xlsx/SKILL.md similarity index 100% rename from mini_agent/skills/document-skills/xlsx/SKILL.md rename to ye_linghua/skills/document-skills/xlsx/SKILL.md diff --git a/mini_agent/skills/document-skills/xlsx/recalc.py b/ye_linghua/skills/document-skills/xlsx/recalc.py similarity index 100% rename from mini_agent/skills/document-skills/xlsx/recalc.py rename to ye_linghua/skills/document-skills/xlsx/recalc.py diff --git a/mini_agent/skills/internal-comms/LICENSE.txt b/ye_linghua/skills/internal-comms/LICENSE.txt similarity index 100% rename from mini_agent/skills/internal-comms/LICENSE.txt rename to ye_linghua/skills/internal-comms/LICENSE.txt diff --git a/mini_agent/skills/internal-comms/SKILL.md b/ye_linghua/skills/internal-comms/SKILL.md similarity index 100% rename from mini_agent/skills/internal-comms/SKILL.md rename to ye_linghua/skills/internal-comms/SKILL.md diff --git a/mini_agent/skills/internal-comms/examples/3p-updates.md b/ye_linghua/skills/internal-comms/examples/3p-updates.md similarity index 100% rename from mini_agent/skills/internal-comms/examples/3p-updates.md rename to ye_linghua/skills/internal-comms/examples/3p-updates.md diff --git a/mini_agent/skills/internal-comms/examples/company-newsletter.md b/ye_linghua/skills/internal-comms/examples/company-newsletter.md similarity index 100% rename from mini_agent/skills/internal-comms/examples/company-newsletter.md rename to ye_linghua/skills/internal-comms/examples/company-newsletter.md diff --git a/mini_agent/skills/internal-comms/examples/faq-answers.md b/ye_linghua/skills/internal-comms/examples/faq-answers.md similarity index 100% rename from mini_agent/skills/internal-comms/examples/faq-answers.md rename to ye_linghua/skills/internal-comms/examples/faq-answers.md diff --git a/mini_agent/skills/internal-comms/examples/general-comms.md b/ye_linghua/skills/internal-comms/examples/general-comms.md similarity index 100% rename from mini_agent/skills/internal-comms/examples/general-comms.md rename to ye_linghua/skills/internal-comms/examples/general-comms.md diff --git a/mini_agent/skills/mcp-builder/LICENSE.txt b/ye_linghua/skills/mcp-builder/LICENSE.txt similarity index 100% rename from mini_agent/skills/mcp-builder/LICENSE.txt rename to ye_linghua/skills/mcp-builder/LICENSE.txt diff --git a/mini_agent/skills/mcp-builder/SKILL.md b/ye_linghua/skills/mcp-builder/SKILL.md similarity index 100% rename from mini_agent/skills/mcp-builder/SKILL.md rename to ye_linghua/skills/mcp-builder/SKILL.md diff --git a/mini_agent/skills/mcp-builder/reference/evaluation.md b/ye_linghua/skills/mcp-builder/reference/evaluation.md similarity index 100% rename from mini_agent/skills/mcp-builder/reference/evaluation.md rename to ye_linghua/skills/mcp-builder/reference/evaluation.md diff --git a/mini_agent/skills/mcp-builder/reference/mcp_best_practices.md b/ye_linghua/skills/mcp-builder/reference/mcp_best_practices.md similarity index 100% rename from mini_agent/skills/mcp-builder/reference/mcp_best_practices.md rename to ye_linghua/skills/mcp-builder/reference/mcp_best_practices.md diff --git a/mini_agent/skills/mcp-builder/reference/node_mcp_server.md b/ye_linghua/skills/mcp-builder/reference/node_mcp_server.md similarity index 100% rename from mini_agent/skills/mcp-builder/reference/node_mcp_server.md rename to ye_linghua/skills/mcp-builder/reference/node_mcp_server.md diff --git a/mini_agent/skills/mcp-builder/reference/python_mcp_server.md b/ye_linghua/skills/mcp-builder/reference/python_mcp_server.md similarity index 100% rename from mini_agent/skills/mcp-builder/reference/python_mcp_server.md rename to ye_linghua/skills/mcp-builder/reference/python_mcp_server.md diff --git a/mini_agent/skills/mcp-builder/scripts/connections.py b/ye_linghua/skills/mcp-builder/scripts/connections.py similarity index 100% rename from mini_agent/skills/mcp-builder/scripts/connections.py rename to ye_linghua/skills/mcp-builder/scripts/connections.py diff --git a/mini_agent/skills/mcp-builder/scripts/evaluation.py b/ye_linghua/skills/mcp-builder/scripts/evaluation.py similarity index 100% rename from mini_agent/skills/mcp-builder/scripts/evaluation.py rename to ye_linghua/skills/mcp-builder/scripts/evaluation.py diff --git a/mini_agent/skills/mcp-builder/scripts/example_evaluation.xml b/ye_linghua/skills/mcp-builder/scripts/example_evaluation.xml similarity index 100% rename from mini_agent/skills/mcp-builder/scripts/example_evaluation.xml rename to ye_linghua/skills/mcp-builder/scripts/example_evaluation.xml diff --git a/mini_agent/skills/mcp-builder/scripts/requirements.txt b/ye_linghua/skills/mcp-builder/scripts/requirements.txt similarity index 100% rename from mini_agent/skills/mcp-builder/scripts/requirements.txt rename to ye_linghua/skills/mcp-builder/scripts/requirements.txt diff --git a/mini_agent/skills/skill-creator/LICENSE.txt b/ye_linghua/skills/skill-creator/LICENSE.txt similarity index 100% rename from mini_agent/skills/skill-creator/LICENSE.txt rename to ye_linghua/skills/skill-creator/LICENSE.txt diff --git a/mini_agent/skills/skill-creator/SKILL.md b/ye_linghua/skills/skill-creator/SKILL.md similarity index 100% rename from mini_agent/skills/skill-creator/SKILL.md rename to ye_linghua/skills/skill-creator/SKILL.md diff --git a/mini_agent/skills/skill-creator/scripts/init_skill.py b/ye_linghua/skills/skill-creator/scripts/init_skill.py similarity index 100% rename from mini_agent/skills/skill-creator/scripts/init_skill.py rename to ye_linghua/skills/skill-creator/scripts/init_skill.py diff --git a/mini_agent/skills/skill-creator/scripts/package_skill.py b/ye_linghua/skills/skill-creator/scripts/package_skill.py similarity index 100% rename from mini_agent/skills/skill-creator/scripts/package_skill.py rename to ye_linghua/skills/skill-creator/scripts/package_skill.py diff --git a/mini_agent/skills/skill-creator/scripts/quick_validate.py b/ye_linghua/skills/skill-creator/scripts/quick_validate.py similarity index 100% rename from mini_agent/skills/skill-creator/scripts/quick_validate.py rename to ye_linghua/skills/skill-creator/scripts/quick_validate.py diff --git a/mini_agent/skills/slack-gif-creator/LICENSE.txt b/ye_linghua/skills/slack-gif-creator/LICENSE.txt similarity index 100% rename from mini_agent/skills/slack-gif-creator/LICENSE.txt rename to ye_linghua/skills/slack-gif-creator/LICENSE.txt diff --git a/mini_agent/skills/slack-gif-creator/SKILL.md b/ye_linghua/skills/slack-gif-creator/SKILL.md similarity index 100% rename from mini_agent/skills/slack-gif-creator/SKILL.md rename to ye_linghua/skills/slack-gif-creator/SKILL.md diff --git a/mini_agent/skills/slack-gif-creator/core/color_palettes.py b/ye_linghua/skills/slack-gif-creator/core/color_palettes.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/core/color_palettes.py rename to ye_linghua/skills/slack-gif-creator/core/color_palettes.py diff --git a/mini_agent/skills/slack-gif-creator/core/easing.py b/ye_linghua/skills/slack-gif-creator/core/easing.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/core/easing.py rename to ye_linghua/skills/slack-gif-creator/core/easing.py diff --git a/mini_agent/skills/slack-gif-creator/core/frame_composer.py b/ye_linghua/skills/slack-gif-creator/core/frame_composer.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/core/frame_composer.py rename to ye_linghua/skills/slack-gif-creator/core/frame_composer.py diff --git a/mini_agent/skills/slack-gif-creator/core/gif_builder.py b/ye_linghua/skills/slack-gif-creator/core/gif_builder.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/core/gif_builder.py rename to ye_linghua/skills/slack-gif-creator/core/gif_builder.py diff --git a/mini_agent/skills/slack-gif-creator/core/typography.py b/ye_linghua/skills/slack-gif-creator/core/typography.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/core/typography.py rename to ye_linghua/skills/slack-gif-creator/core/typography.py diff --git a/mini_agent/skills/slack-gif-creator/core/validators.py b/ye_linghua/skills/slack-gif-creator/core/validators.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/core/validators.py rename to ye_linghua/skills/slack-gif-creator/core/validators.py diff --git a/mini_agent/skills/slack-gif-creator/core/visual_effects.py b/ye_linghua/skills/slack-gif-creator/core/visual_effects.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/core/visual_effects.py rename to ye_linghua/skills/slack-gif-creator/core/visual_effects.py diff --git a/mini_agent/skills/slack-gif-creator/requirements.txt b/ye_linghua/skills/slack-gif-creator/requirements.txt similarity index 100% rename from mini_agent/skills/slack-gif-creator/requirements.txt rename to ye_linghua/skills/slack-gif-creator/requirements.txt diff --git a/mini_agent/skills/slack-gif-creator/templates/bounce.py b/ye_linghua/skills/slack-gif-creator/templates/bounce.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/bounce.py rename to ye_linghua/skills/slack-gif-creator/templates/bounce.py diff --git a/mini_agent/skills/slack-gif-creator/templates/explode.py b/ye_linghua/skills/slack-gif-creator/templates/explode.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/explode.py rename to ye_linghua/skills/slack-gif-creator/templates/explode.py diff --git a/mini_agent/skills/slack-gif-creator/templates/fade.py b/ye_linghua/skills/slack-gif-creator/templates/fade.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/fade.py rename to ye_linghua/skills/slack-gif-creator/templates/fade.py diff --git a/mini_agent/skills/slack-gif-creator/templates/flip.py b/ye_linghua/skills/slack-gif-creator/templates/flip.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/flip.py rename to ye_linghua/skills/slack-gif-creator/templates/flip.py diff --git a/mini_agent/skills/slack-gif-creator/templates/kaleidoscope.py b/ye_linghua/skills/slack-gif-creator/templates/kaleidoscope.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/kaleidoscope.py rename to ye_linghua/skills/slack-gif-creator/templates/kaleidoscope.py diff --git a/mini_agent/skills/slack-gif-creator/templates/morph.py b/ye_linghua/skills/slack-gif-creator/templates/morph.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/morph.py rename to ye_linghua/skills/slack-gif-creator/templates/morph.py diff --git a/mini_agent/skills/slack-gif-creator/templates/move.py b/ye_linghua/skills/slack-gif-creator/templates/move.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/move.py rename to ye_linghua/skills/slack-gif-creator/templates/move.py diff --git a/mini_agent/skills/slack-gif-creator/templates/pulse.py b/ye_linghua/skills/slack-gif-creator/templates/pulse.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/pulse.py rename to ye_linghua/skills/slack-gif-creator/templates/pulse.py diff --git a/mini_agent/skills/slack-gif-creator/templates/shake.py b/ye_linghua/skills/slack-gif-creator/templates/shake.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/shake.py rename to ye_linghua/skills/slack-gif-creator/templates/shake.py diff --git a/mini_agent/skills/slack-gif-creator/templates/slide.py b/ye_linghua/skills/slack-gif-creator/templates/slide.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/slide.py rename to ye_linghua/skills/slack-gif-creator/templates/slide.py diff --git a/mini_agent/skills/slack-gif-creator/templates/spin.py b/ye_linghua/skills/slack-gif-creator/templates/spin.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/spin.py rename to ye_linghua/skills/slack-gif-creator/templates/spin.py diff --git a/mini_agent/skills/slack-gif-creator/templates/wiggle.py b/ye_linghua/skills/slack-gif-creator/templates/wiggle.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/wiggle.py rename to ye_linghua/skills/slack-gif-creator/templates/wiggle.py diff --git a/mini_agent/skills/slack-gif-creator/templates/zoom.py b/ye_linghua/skills/slack-gif-creator/templates/zoom.py similarity index 100% rename from mini_agent/skills/slack-gif-creator/templates/zoom.py rename to ye_linghua/skills/slack-gif-creator/templates/zoom.py diff --git a/mini_agent/skills/template-skill/SKILL.md b/ye_linghua/skills/template-skill/SKILL.md similarity index 100% rename from mini_agent/skills/template-skill/SKILL.md rename to ye_linghua/skills/template-skill/SKILL.md diff --git a/mini_agent/skills/theme-factory/LICENSE.txt b/ye_linghua/skills/theme-factory/LICENSE.txt similarity index 100% rename from mini_agent/skills/theme-factory/LICENSE.txt rename to ye_linghua/skills/theme-factory/LICENSE.txt diff --git a/mini_agent/skills/theme-factory/SKILL.md b/ye_linghua/skills/theme-factory/SKILL.md similarity index 100% rename from mini_agent/skills/theme-factory/SKILL.md rename to ye_linghua/skills/theme-factory/SKILL.md diff --git a/mini_agent/skills/theme-factory/theme-showcase.pdf b/ye_linghua/skills/theme-factory/theme-showcase.pdf similarity index 100% rename from mini_agent/skills/theme-factory/theme-showcase.pdf rename to ye_linghua/skills/theme-factory/theme-showcase.pdf diff --git a/mini_agent/skills/theme-factory/themes/arctic-frost.md b/ye_linghua/skills/theme-factory/themes/arctic-frost.md similarity index 100% rename from mini_agent/skills/theme-factory/themes/arctic-frost.md rename to ye_linghua/skills/theme-factory/themes/arctic-frost.md diff --git a/mini_agent/skills/theme-factory/themes/botanical-garden.md b/ye_linghua/skills/theme-factory/themes/botanical-garden.md similarity index 100% rename from mini_agent/skills/theme-factory/themes/botanical-garden.md rename to ye_linghua/skills/theme-factory/themes/botanical-garden.md diff --git a/mini_agent/skills/theme-factory/themes/desert-rose.md b/ye_linghua/skills/theme-factory/themes/desert-rose.md similarity index 100% rename from mini_agent/skills/theme-factory/themes/desert-rose.md rename to ye_linghua/skills/theme-factory/themes/desert-rose.md diff --git a/mini_agent/skills/theme-factory/themes/forest-canopy.md b/ye_linghua/skills/theme-factory/themes/forest-canopy.md similarity index 100% rename from mini_agent/skills/theme-factory/themes/forest-canopy.md rename to ye_linghua/skills/theme-factory/themes/forest-canopy.md diff --git a/mini_agent/skills/theme-factory/themes/golden-hour.md b/ye_linghua/skills/theme-factory/themes/golden-hour.md similarity index 100% rename from mini_agent/skills/theme-factory/themes/golden-hour.md rename to ye_linghua/skills/theme-factory/themes/golden-hour.md diff --git a/mini_agent/skills/theme-factory/themes/midnight-galaxy.md b/ye_linghua/skills/theme-factory/themes/midnight-galaxy.md similarity index 100% rename from mini_agent/skills/theme-factory/themes/midnight-galaxy.md rename to ye_linghua/skills/theme-factory/themes/midnight-galaxy.md diff --git a/mini_agent/skills/theme-factory/themes/modern-minimalist.md b/ye_linghua/skills/theme-factory/themes/modern-minimalist.md similarity index 100% rename from mini_agent/skills/theme-factory/themes/modern-minimalist.md rename to ye_linghua/skills/theme-factory/themes/modern-minimalist.md diff --git a/mini_agent/skills/theme-factory/themes/ocean-depths.md b/ye_linghua/skills/theme-factory/themes/ocean-depths.md similarity index 100% rename from mini_agent/skills/theme-factory/themes/ocean-depths.md rename to ye_linghua/skills/theme-factory/themes/ocean-depths.md diff --git a/mini_agent/skills/theme-factory/themes/sunset-boulevard.md b/ye_linghua/skills/theme-factory/themes/sunset-boulevard.md similarity index 100% rename from mini_agent/skills/theme-factory/themes/sunset-boulevard.md rename to ye_linghua/skills/theme-factory/themes/sunset-boulevard.md diff --git a/mini_agent/skills/theme-factory/themes/tech-innovation.md b/ye_linghua/skills/theme-factory/themes/tech-innovation.md similarity index 100% rename from mini_agent/skills/theme-factory/themes/tech-innovation.md rename to ye_linghua/skills/theme-factory/themes/tech-innovation.md diff --git a/mini_agent/skills/webapp-testing/LICENSE.txt b/ye_linghua/skills/webapp-testing/LICENSE.txt similarity index 100% rename from mini_agent/skills/webapp-testing/LICENSE.txt rename to ye_linghua/skills/webapp-testing/LICENSE.txt diff --git a/mini_agent/skills/webapp-testing/SKILL.md b/ye_linghua/skills/webapp-testing/SKILL.md similarity index 100% rename from mini_agent/skills/webapp-testing/SKILL.md rename to ye_linghua/skills/webapp-testing/SKILL.md diff --git a/mini_agent/skills/webapp-testing/examples/console_logging.py b/ye_linghua/skills/webapp-testing/examples/console_logging.py similarity index 100% rename from mini_agent/skills/webapp-testing/examples/console_logging.py rename to ye_linghua/skills/webapp-testing/examples/console_logging.py diff --git a/mini_agent/skills/webapp-testing/examples/element_discovery.py b/ye_linghua/skills/webapp-testing/examples/element_discovery.py similarity index 100% rename from mini_agent/skills/webapp-testing/examples/element_discovery.py rename to ye_linghua/skills/webapp-testing/examples/element_discovery.py diff --git a/mini_agent/skills/webapp-testing/examples/static_html_automation.py b/ye_linghua/skills/webapp-testing/examples/static_html_automation.py similarity index 100% rename from mini_agent/skills/webapp-testing/examples/static_html_automation.py rename to ye_linghua/skills/webapp-testing/examples/static_html_automation.py diff --git a/mini_agent/skills/webapp-testing/scripts/with_server.py b/ye_linghua/skills/webapp-testing/scripts/with_server.py similarity index 100% rename from mini_agent/skills/webapp-testing/scripts/with_server.py rename to ye_linghua/skills/webapp-testing/scripts/with_server.py diff --git a/mini_agent/tools/__init__.py b/ye_linghua/tools/__init__.py similarity index 100% rename from mini_agent/tools/__init__.py rename to ye_linghua/tools/__init__.py diff --git a/mini_agent/tools/base.py b/ye_linghua/tools/base.py similarity index 100% rename from mini_agent/tools/base.py rename to ye_linghua/tools/base.py diff --git a/mini_agent/tools/bash_tool.py b/ye_linghua/tools/bash_tool.py similarity index 100% rename from mini_agent/tools/bash_tool.py rename to ye_linghua/tools/bash_tool.py diff --git a/mini_agent/tools/file_tools.py b/ye_linghua/tools/file_tools.py similarity index 100% rename from mini_agent/tools/file_tools.py rename to ye_linghua/tools/file_tools.py diff --git a/mini_agent/tools/mcp_loader.py b/ye_linghua/tools/mcp_loader.py similarity index 100% rename from mini_agent/tools/mcp_loader.py rename to ye_linghua/tools/mcp_loader.py diff --git a/mini_agent/tools/note_tool.py b/ye_linghua/tools/note_tool.py similarity index 100% rename from mini_agent/tools/note_tool.py rename to ye_linghua/tools/note_tool.py diff --git a/mini_agent/tools/skill_loader.py b/ye_linghua/tools/skill_loader.py similarity index 100% rename from mini_agent/tools/skill_loader.py rename to ye_linghua/tools/skill_loader.py diff --git a/mini_agent/tools/skill_tool.py b/ye_linghua/tools/skill_tool.py similarity index 100% rename from mini_agent/tools/skill_tool.py rename to ye_linghua/tools/skill_tool.py diff --git a/mini_agent/utils/__init__.py b/ye_linghua/utils/__init__.py similarity index 100% rename from mini_agent/utils/__init__.py rename to ye_linghua/utils/__init__.py diff --git a/mini_agent/utils/terminal_utils.py b/ye_linghua/utils/terminal_utils.py similarity index 100% rename from mini_agent/utils/terminal_utils.py rename to ye_linghua/utils/terminal_utils.py diff --git a/ye_linghua/web_config.py b/ye_linghua/web_config.py new file mode 100644 index 0000000..872c092 --- /dev/null +++ b/ye_linghua/web_config.py @@ -0,0 +1,658 @@ +"""Web configuration interface for Ye Linghua personality and prompts + +A FastAPI-based web application for editing personality and prompts configuration. + +Usage: + python -m ye_linghua.web_config + # or + ye-linghua-config + +Then open http://localhost:8000 in your browser. +""" + +import os +from pathlib import Path +from typing import Any + +import yaml +from fastapi import FastAPI, HTTPException +from fastapi.responses import HTMLResponse, JSONResponse +from pydantic import BaseModel + +from ye_linghua.config import Config +from ye_linghua.personality_loader import PersonalityLoader + +app = FastAPI(title="Ye Linghua Configuration", version="0.1.0") + + +class PersonalityUpdate(BaseModel): + """Personality configuration update model""" + + data: dict[str, Any] + + +class PromptsUpdate(BaseModel): + """Prompts configuration update model""" + + data: dict[str, Any] + + +@app.get("/", response_class=HTMLResponse) +async def root(): + """Serve the main configuration page""" + html_content = """ + + + + + + 叶灵华 (Ye Linghua) 配置界面 + + + +
+
+

🌸 叶灵华 (Ye Linghua)

+

AI助手 人设与提示词配置界面

+
+ +
+
人设配置
+
提示词配置
+
预览生成
+
+ + +
+
+

📝 人设配置说明

+
    +
  • 配置叶灵华的基本信息、性格特点、专业能力等
  • +
  • 支持完整的YAML格式配置
  • +
  • 修改后点击"保存配置"按钮保存
  • +
+
+ +
+
+

编辑器

+ +
+ + +
+
+ +
+

配置说明

+
+

主要配置项:

+
    +
  • name: AI助手的中文名
  • +
  • name_en: AI助手的英文名
  • +
  • role: 角色定位和描述
  • +
  • personality.traits: 性格特点列表
  • +
  • personality.interests: 兴趣爱好
  • +
  • skills: 专业技能配置
  • +
  • behavior: 交互行为模板
  • +
+

💡 小提示:

+
    +
  • 确保YAML格式正确(注意缩进)
  • +
  • 可以添加新的字段和属性
  • +
  • 保存前建议先预览效果
  • +
+
+
+
+
+
+ + +
+
+

📝 提示词配置说明

+
    +
  • 配置系统提示词模板和各种场景的提示词
  • +
  • 支持使用变量占位符(如 {name}, {role_description})
  • +
  • 修改后点击"保存配置"按钮保存
  • +
+
+ +
+
+

编辑器

+ +
+ + +
+
+ +
+

配置说明

+
+

主要配置项:

+
    +
  • system_prompt: 系统提示词结构
  • +
  • core_capabilities: 核心能力描述
  • +
  • working_guidelines: 工作指南
  • +
  • scenarios: 特殊场景提示词
  • +
+

💡 支持的占位符:

+
    +
  • {name}: AI助手名称
  • +
  • {name_en}: 英文名
  • +
  • {role_description}: 角色描述
  • +
  • {SKILLS_METADATA}: 技能元数据
  • +
+
+
+
+
+
+ + +
+
+

👀 系统提示词预览

+
    +
  • 查看根据当前人设和提示词配置生成的完整系统提示词
  • +
  • 点击"生成预览"查看最新效果
  • +
+
+ +
+ +
+ +
+ 点击"生成预览"按钮查看系统提示词... +
+
+
+
+ + + + + """ + return HTMLResponse(content=html_content) + + +@app.get("/api/personality") +async def get_personality(): + """Get current personality configuration""" + personality_path = Config.find_config_file("personality.yaml") + if not personality_path or not personality_path.exists(): + raise HTTPException(status_code=404, detail="Personality configuration file not found") + + with open(personality_path, encoding="utf-8") as f: + content = f.read() + + return content + + +@app.post("/api/personality") +async def save_personality(data: dict): + """Save personality configuration""" + try: + content = data.get("content", "") + if not content: + raise HTTPException(status_code=400, detail="Empty content") + + # Validate YAML format + try: + yaml.safe_load(content) + except yaml.YAMLError as e: + raise HTTPException(status_code=400, detail=f"Invalid YAML format: {str(e)}") + + # Find config file path + personality_path = Config.find_config_file("personality.yaml") + if not personality_path: + # Create in user config directory + user_config_dir = Path.home() / ".ye-linghua" / "config" + user_config_dir.mkdir(parents=True, exist_ok=True) + personality_path = user_config_dir / "personality.yaml" + + # Save to file + with open(personality_path, "w", encoding="utf-8") as f: + f.write(content) + + return JSONResponse({"status": "success", "path": str(personality_path)}) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to save: {str(e)}") + + +@app.get("/api/prompts") +async def get_prompts(): + """Get current prompts configuration""" + prompts_path = Config.find_config_file("prompts.yaml") + if not prompts_path or not prompts_path.exists(): + raise HTTPException(status_code=404, detail="Prompts configuration file not found") + + with open(prompts_path, encoding="utf-8") as f: + content = f.read() + + return content + + +@app.post("/api/prompts") +async def save_prompts(data: dict): + """Save prompts configuration""" + try: + content = data.get("content", "") + if not content: + raise HTTPException(status_code=400, detail="Empty content") + + # Validate YAML format + try: + yaml.safe_load(content) + except yaml.YAMLError as e: + raise HTTPException(status_code=400, detail=f"Invalid YAML format: {str(e)}") + + # Find config file path + prompts_path = Config.find_config_file("prompts.yaml") + if not prompts_path: + # Create in user config directory + user_config_dir = Path.home() / ".ye-linghua" / "config" + user_config_dir.mkdir(parents=True, exist_ok=True) + prompts_path = user_config_dir / "prompts.yaml" + + # Save to file + with open(prompts_path, "w", encoding="utf-8") as f: + f.write(content) + + return JSONResponse({"status": "success", "path": str(prompts_path)}) + + except HTTPException: + raise + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to save: {str(e)}") + + +@app.get("/api/preview") +async def preview_system_prompt(): + """Generate and preview system prompt""" + try: + personality_path = Config.find_config_file("personality.yaml") + prompts_path = Config.find_config_file("prompts.yaml") + + if not personality_path or not prompts_path: + raise HTTPException( + status_code=404, detail="Configuration files not found. Please ensure personality.yaml and prompts.yaml exist." + ) + + loader = PersonalityLoader(personality_path=personality_path, prompts_path=prompts_path) + + system_prompt = loader.generate_system_prompt() + + return JSONResponse({"status": "success", "system_prompt": system_prompt}) + + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to generate preview: {str(e)}") + + +def main(): + """Main entry point for web config interface""" + import uvicorn + + print("🌸 Starting Ye Linghua Configuration Interface...") + print("📍 Open http://localhost:8000 in your browser") + print("Press Ctrl+C to stop") + + uvicorn.run(app, host="0.0.0.0", port=8000) + + +if __name__ == "__main__": + main() From 4461bfc114c5aff9d9f40110e83e11a656eb6a27 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Nov 2025 07:20:06 +0000 Subject: [PATCH 2/4] feat: add comprehensive plugin system with timer and notification support Implement a modular plugin architecture supporting: - Python-based plugins with base classes (Plugin, ReplyHandler) - PowerShell/Shell script plugins with JSON communication - Timer plugin for scheduled reminders with tag-based interface (, , ) - Notification plugin with cross-platform desktop notifications (Windows/Linux/macOS) - PluginLoader with hot-reload capability - PluginRegistry for centralized management - ReplyHandler chain for processing LLM responses by priority - Context and prompt injection into LLM system prompts - Auto-discovery from plugins directory Configuration integration: - Added PluginsConfig to config system - Updated config-example.yaml with plugin settings - Support for enabling/disabling individual plugins Documentation: - Comprehensive PLUGINS.md with usage examples - Architecture explanations and best practices --- PLUGINS.md | 398 +++++++++++++++ ye_linghua/config.py | 32 ++ ye_linghua/config/config-example.yaml | 19 +- ye_linghua/plugins/__init__.py | 23 + ye_linghua/plugins/base.py | 217 ++++++++ ye_linghua/plugins/examples/notify.ps1 | 95 ++++ ye_linghua/plugins/examples/notify.sh | 50 ++ ye_linghua/plugins/loader.py | 379 ++++++++++++++ ye_linghua/plugins/notification/__init__.py | 359 ++++++++++++++ ye_linghua/plugins/registry.py | 153 ++++++ ye_linghua/plugins/shell_wrapper.py | 195 ++++++++ ye_linghua/plugins/timer/__init__.py | 517 ++++++++++++++++++++ 12 files changed, 2435 insertions(+), 2 deletions(-) create mode 100644 PLUGINS.md create mode 100644 ye_linghua/plugins/__init__.py create mode 100644 ye_linghua/plugins/base.py create mode 100644 ye_linghua/plugins/examples/notify.ps1 create mode 100644 ye_linghua/plugins/examples/notify.sh create mode 100644 ye_linghua/plugins/loader.py create mode 100644 ye_linghua/plugins/notification/__init__.py create mode 100644 ye_linghua/plugins/registry.py create mode 100644 ye_linghua/plugins/shell_wrapper.py create mode 100644 ye_linghua/plugins/timer/__init__.py diff --git a/PLUGINS.md b/PLUGINS.md new file mode 100644 index 0000000..ab7f676 --- /dev/null +++ b/PLUGINS.md @@ -0,0 +1,398 @@ +# 叶灵华插件系统文档 + +## 概述 + +叶灵华的插件系统提供了强大的扩展能力,支持: + +- ✅ **Python插件** - 基于Python的原生插件 +- ✅ **Shell脚本插件** - PowerShell/Bash脚本插件 +- ✅ **热重载** - 运行时动态重载插件 +- ✅ **自动发现** - 自动扫描plugins目录 +- ✅ **Reply Handler链** - 处理LLM回复的插件链 +- ✅ **上下文注入** - 向LLM注入插件功能 + +## 内置插件 + +### 1. 定时器插件(Timer Plugin) + +提供定时提醒和任务调度功能。 + +**使用方法**: + +```xml + + + + + + + + + +``` + +**时间格式**: +- 相对时间:`in X minutes/hours/days/weeks` +- 绝对时间:`2024-12-25 10:00:00` 或 `12/25/2024 10:00` + +**重复策略**: +- `once` - 一次性 +- `daily` - 每天 +- `weekly` - 每周 +- `monthly` - 每月 + +### 2. 通知插件(Notification Plugin) + +发送桌面通知。 + +**使用方法**: + +```xml + + +``` + +**平台支持**: +- ✅ Windows - PowerShell Toast通知 +- ✅ Linux - notify-send (需要libnotify-bin) +- ✅ macOS - osascript (AppleScript) + +## 插件架构 + +### 基础类 + +```python +from ye_linghua.plugins import Plugin, PluginContext, PluginMetadata, ReplyHandler + +class MyPlugin(Plugin): + def __init__(self): + metadata = PluginMetadata( + id="my_plugin", + name="My Plugin", + version="1.0.0", + description="Does something cool" + ) + super().__init__(metadata) + + async def initialize(self) -> None: + """插件初始化""" + self._initialized = True + + async def shutdown(self) -> None: + """插件清理""" + self._initialized = False + + def get_prompt_extension(self, context: PluginContext) -> str: + """返回要注入到系统提示词的文本""" + return """ +## My Plugin功能 + +你可以使用我的插件做xxx... +""" + + def get_context_extension(self, context: PluginContext) -> dict: + """返回要注入到上下文的额外数据""" + return { + "my_plugin_data": "some value" + } + + def get_reply_handlers(self) -> list[ReplyHandler]: + """返回回复处理器列表""" + return [MyReplyHandler(self)] +``` + +### ReplyHandler + +```python +class MyReplyHandler(ReplyHandler): + async def handle_reply( + self, + response: str, + context: PluginContext + ) -> tuple[str, bool]: + """ + 处理LLM回复 + + 返回: + (modified_response, should_continue) + - modified_response: 修改后的回复 + - should_continue: 是否继续执行后续处理器 + """ + # 在这里处理回复,比如提取特殊标记 + modified = response.replace("", "✅ 已处理") + return modified, True + + @property + def priority(self) -> int: + """优先级(数字越小优先级越高)""" + return 100 +``` + +## 创建Python插件 + +### 1. 创建插件目录 + +``` +plugins/ +└── my_plugin/ + ├── __init__.py + └── metadata.yaml (可选) +``` + +### 2. 实现插件 + +在 `__init__.py` 中: + +```python +from ye_linghua.plugins import Plugin, PluginMetadata, PluginContext + +class MyAwesomePlugin(Plugin): + def __init__(self): + metadata = PluginMetadata( + id="my_awesome_plugin", + name="My Awesome Plugin", + version="1.0.0", + description="An awesome plugin", + ) + super().__init__(metadata) + + async def initialize(self) -> None: + print("Plugin initialized!") + self._initialized = True + + async def shutdown(self) -> None: + print("Plugin shutdown!") + self._initialized = False + + def get_prompt_extension(self, context: PluginContext) -> str: + return "## My Awesome Plugin\n\nI can do awesome things!" +``` + +### 3. 插件自动加载 + +将插件目录放入 `plugins/` 目录,系统会自动发现和加载。 + +## 创建Shell脚本插件 + +### PowerShell插件示例 + +```powershell +# PLUGIN_ID: my_ps_plugin +# PLUGIN_NAME: My PowerShell Plugin +# PLUGIN_VERSION: 1.0.0 +# PLUGIN_DESCRIPTION: A PowerShell plugin + +# Read JSON input +$InputJson = [Console]::In.ReadToEnd() +$Input = ConvertFrom-Json $InputJson + +$Action = $Input.action + +switch ($Action) { + "get_prompt" { + $Result = @{ + success = $true + prompt = "## PowerShell Plugin\n\nDoes cool stuff on Windows!" + } + ConvertTo-Json $Result -Compress + } + + "get_context" { + $Result = @{ + success = $true + context = @{ + platform = "windows" + } + } + ConvertTo-Json $Result -Compress + } + + default { + $Result = @{ + success = $false + error = "Unknown action" + } + ConvertTo-Json $Result -Compress + } +} +``` + +### Bash插件示例 + +```bash +#!/bin/bash +# PLUGIN_ID: my_sh_plugin +# PLUGIN_NAME: My Shell Plugin +# PLUGIN_VERSION: 1.0.0 +# PLUGIN_DESCRIPTION: A shell plugin + +INPUT_JSON=$(cat) +ACTION=$(echo "$INPUT_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['action'])") + +case "$ACTION" in + "get_prompt") + echo '{"success": true, "prompt": "## Shell Plugin\n\nDoes cool stuff on Linux!"}' + ;; + + "get_context") + echo '{"success": true, "context": {"platform": "linux"}}' + ;; + + *) + echo '{"success": false, "error": "Unknown action"}' + ;; +esac +``` + +## 配置 + +在 `config.yaml` 中配置插件系统: + +```yaml +plugins: + enabled: true # 启用插件系统 + plugins_dir: "./plugins" # 插件目录 + auto_discover: true # 自动发现插件 + hot_reload: false # 热重载(实验性) + + # 内置插件 + timer_enabled: true + notification_enabled: true + + # 插件设置 + timer_check_interval: 30 + notification_sound: true +``` + +## PluginContext + +插件上下文包含: + +```python +@dataclass +class PluginContext: + messages: list[dict] # 对话历史 + platform: str # 平台(cli/web等) + user_id: str | None # 用户ID + session_id: str | None # 会话ID + config: dict # 配置 + extra: dict # 额外数据 + + def get_recent_messages(self, count: int = 5) -> list[dict]: + """获取最近的N条消息""" + + def get_message_summary(self) -> str: + """生成消息摘要""" +``` + +## 插件生命周期 + +1. **发现** - 扫描plugins目录 +2. **加载** - 导入模块/执行脚本 +3. **初始化** - 调用`initialize()` +4. **运行** - 处理请求和回复 +5. **重载** - 可选的热重载 +6. **关闭** - 调用`shutdown()` + +## ReplyHandler链 + +所有插件的ReplyHandler按优先级排序后顺序执行: + +``` +LLM回复 + ↓ +Timer Handler (priority: 50) + ↓ +Notification Handler (priority: 60) + ↓ +Custom Handler (priority: 100) + ↓ +最终回复 +``` + +每个Handler可以: +- 修改回复内容 +- 提取特殊标记并执行操作 +- 决定是否继续执行后续Handler + +## 最佳实践 + +1. **错误处理** - 插件应该优雅地处理错误,不影响主系统 +2. **异步操作** - 使用 `async/await` 进行I/O操作 +3. **日志记录** - 使用Python logging记录重要事件 +4. **资源清理** - 在`shutdown()`中清理资源 +5. **优先级设置** - 合理设置ReplyHandler优先级 +6. **文档完善** - 提供清晰的使用说明 + +## 示例:完整的插件 + +查看内置插件的完整实现: + +- `ye_linghua/plugins/timer/` - 定时器插件 +- `ye_linghua/plugins/notification/` - 通知插件 +- `ye_linghua/plugins/examples/` - 示例脚本插件 + +## 故障排除 + +### 插件未加载 + +1. 检查`config.yaml`中`plugins.enabled`是否为`true` +2. 确认插件目录路径正确 +3. 查看日志输出 + +### Shell插件执行失败 + +1. 确认脚本有执行权限(Linux/macOS) +2. 检查interpreter是否安装(powershell/bash) +3. 验证脚本的JSON输入/输出格式 + +### 热重载不工作 + +热重载功能是实验性的,建议重启应用以加载插件更改。 + +## 进阶话题 + +### 跨平台插件 + +```python +import platform + +class CrossPlatformPlugin(Plugin): + def get_prompt_extension(self, context: PluginContext) -> str: + system = platform.system() + if system == "Windows": + return "Windows-specific功能..." + elif system == "Linux": + return "Linux-specific功能..." + else: + return "通用功能..." +``` + +### 插件间通信 + +通过`PluginContext.extra`字典在插件间共享数据: + +```python +# Plugin A +def get_context_extension(self, context: PluginContext) -> dict: + return {"shared_data": "value from Plugin A"} + +# Plugin B +def handle_reply(self, response: str, context: PluginContext) -> tuple[str, bool]: + shared_data = context.extra.get("shared_data") + # 使用共享数据... +``` + +## 贡献插件 + +欢迎贡献新插件!请遵循: + +1. 使用清晰的插件ID和名称 +2. 提供完整的文档 +3. 包含使用示例 +4. 添加适当的错误处理 +5. 编写单元测试 + +--- + +**Made with 💖 by the Ye Linghua Team** diff --git a/ye_linghua/config.py b/ye_linghua/config.py index afd89da..23ed11c 100644 --- a/ye_linghua/config.py +++ b/ye_linghua/config.py @@ -58,12 +58,30 @@ class ToolsConfig(BaseModel): mcp_config_path: str = "mcp.json" +class PluginsConfig(BaseModel): + """Plugins configuration""" + + enabled: bool = True + plugins_dir: str = "./plugins" + auto_discover: bool = True + hot_reload: bool = False + + # Built-in plugins + timer_enabled: bool = True + notification_enabled: bool = True + + # Plugin-specific settings + timer_check_interval: int = 30 # seconds + notification_sound: bool = True + + class Config(BaseModel): """Main configuration class""" llm: LLMConfig agent: AgentConfig tools: ToolsConfig + plugins: PluginsConfig = Field(default_factory=PluginsConfig) @classmethod def from_yaml(cls, config_path: str | Path) -> "Config": @@ -138,10 +156,24 @@ def from_yaml(cls, config_path: str | Path) -> "Config": mcp_config_path=tools_data.get("mcp_config_path", "mcp.json"), ) + # Parse plugins configuration + plugins_data = data.get("plugins", {}) + plugins_config = PluginsConfig( + enabled=plugins_data.get("enabled", True), + plugins_dir=plugins_data.get("plugins_dir", "./plugins"), + auto_discover=plugins_data.get("auto_discover", True), + hot_reload=plugins_data.get("hot_reload", False), + timer_enabled=plugins_data.get("timer_enabled", True), + notification_enabled=plugins_data.get("notification_enabled", True), + timer_check_interval=plugins_data.get("timer_check_interval", 30), + notification_sound=plugins_data.get("notification_sound", True), + ) + return cls( llm=llm_config, agent=agent_config, tools=tools_config, + plugins=plugins_config, ) @staticmethod diff --git a/ye_linghua/config/config-example.yaml b/ye_linghua/config/config-example.yaml index 8480d30..29bc61d 100644 --- a/ye_linghua/config/config-example.yaml +++ b/ye_linghua/config/config-example.yaml @@ -49,12 +49,27 @@ tools: enable_file_tools: true # File read/write/edit tools (ReadTool, WriteTool, EditTool) enable_bash: true # Bash command execution tool enable_note: true # Session note tool (SessionNoteTool) - + # Claude Skills enable_skills: true # Enable Skills skills_dir: "./skills" # Skills directory path - + # MCP Tools enable_mcp: true # Enable MCP tools mcp_config_path: "mcp.json" # MCP configuration file (same config directory) # Note: API Keys for MCP tools are configured in mcp.json + +# ===== Plugins Configuration ===== +plugins: + enabled: true # Enable plugin system + plugins_dir: "./plugins" # Plugins directory path + auto_discover: true # Automatically discover and load plugins + hot_reload: false # Enable hot reloading (experimental) + + # Built-in plugins + timer_enabled: true # Enable timer/reminder plugin + notification_enabled: true # Enable desktop notification plugin + + # Plugin settings + timer_check_interval: 30 # Timer check interval in seconds + notification_sound: true # Enable notification sounds diff --git a/ye_linghua/plugins/__init__.py b/ye_linghua/plugins/__init__.py new file mode 100644 index 0000000..e398c85 --- /dev/null +++ b/ye_linghua/plugins/__init__.py @@ -0,0 +1,23 @@ +"""Plugin system for Ye Linghua + +This module provides a flexible plugin architecture supporting: +- Python-based plugins +- PowerShell/Shell script plugins +- Hot reloading +- Reply handlers chain +- Context injection +""" + +from .base import Plugin, PluginContext, PluginMetadata, ReplyHandler +from .loader import PluginLoader, PluginManager +from .registry import PluginRegistry + +__all__ = [ + "Plugin", + "PluginContext", + "PluginMetadata", + "ReplyHandler", + "PluginLoader", + "PluginManager", + "PluginRegistry", +] diff --git a/ye_linghua/plugins/base.py b/ye_linghua/plugins/base.py new file mode 100644 index 0000000..6f00b98 --- /dev/null +++ b/ye_linghua/plugins/base.py @@ -0,0 +1,217 @@ +"""Base classes for plugin system""" + +from abc import ABC, abstractmethod +from dataclasses import dataclass, field +from enum import Enum +from typing import Any, Callable + + +class PluginType(str, Enum): + """Plugin type enumeration""" + + PYTHON = "python" + SHELL = "shell" + POWERSHELL = "powershell" + + +@dataclass +class PluginMetadata: + """Plugin metadata""" + + id: str + name: str + version: str + description: str + author: str = "" + plugin_type: PluginType = PluginType.PYTHON + enabled: bool = True + dependencies: list[str] = field(default_factory=list) + config: dict[str, Any] = field(default_factory=dict) + + +@dataclass +class PluginContext: + """Context passed to plugins during execution + + Attributes: + messages: Conversation message history + platform: Platform identifier (e.g., "cli", "web", "discord") + user_id: User identifier + session_id: Session identifier + config: Runtime configuration + extra: Additional context data + """ + + messages: list[dict[str, Any]] = field(default_factory=list) + platform: str = "cli" + user_id: str | None = None + session_id: str | None = None + config: dict[str, Any] = field(default_factory=dict) + extra: dict[str, Any] = field(default_factory=dict) + + def get_recent_messages(self, count: int = 5) -> list[dict[str, Any]]: + """Get recent messages from history + + Args: + count: Number of recent messages to retrieve + + Returns: + List of recent messages + """ + return self.messages[-count:] if len(self.messages) > count else self.messages + + def get_message_summary(self) -> str: + """Generate a summary of recent messages + + Returns: + Summary string + """ + recent = self.get_recent_messages() + summary_parts = [] + + for msg in recent: + role = msg.get("role", "unknown") + content = msg.get("content", "") + if isinstance(content, str): + # Truncate long messages + content_preview = content[:100] + "..." if len(content) > 100 else content + summary_parts.append(f"[{role}]: {content_preview}") + + return "\n".join(summary_parts) + + +class Plugin(ABC): + """Base class for all plugins + + All plugins must inherit from this class and implement required methods. + """ + + def __init__(self, metadata: PluginMetadata): + """Initialize plugin + + Args: + metadata: Plugin metadata + """ + self.metadata = metadata + self._initialized = False + + @abstractmethod + async def initialize(self) -> None: + """Initialize plugin resources + + Called once when plugin is loaded. + """ + pass + + @abstractmethod + async def shutdown(self) -> None: + """Cleanup plugin resources + + Called when plugin is unloaded or system shuts down. + """ + pass + + @abstractmethod + def get_prompt_extension(self, context: PluginContext) -> str: + """Get prompt extension for this plugin + + This text will be injected into the system prompt to inform + the LLM about the plugin's capabilities. + + Args: + context: Current plugin context + + Returns: + Prompt extension text + """ + pass + + def get_context_extension(self, context: PluginContext) -> dict[str, Any]: + """Get additional context data for this plugin + + Override this to provide extra context data that will be + available to the LLM or other plugins. + + Args: + context: Current plugin context + + Returns: + Additional context dictionary + """ + return {} + + @property + def is_initialized(self) -> bool: + """Check if plugin is initialized""" + return self._initialized + + +class ReplyHandler(ABC): + """Base class for reply handlers + + Reply handlers process LLM responses and can: + - Extract special tags/markers + - Trigger external actions + - Modify response content + - Request response regeneration + """ + + def __init__(self, plugin: Plugin): + """Initialize reply handler + + Args: + plugin: Associated plugin + """ + self.plugin = plugin + + @abstractmethod + async def handle_reply( + self, + response: str, + context: PluginContext, + ) -> tuple[str, bool]: + """Handle LLM reply + + Args: + response: LLM response text + context: Current context + + Returns: + Tuple of (modified_response, should_continue) + - modified_response: Potentially modified response text + - should_continue: True if processing should continue to next handler + """ + pass + + @property + def priority(self) -> int: + """Handler priority (lower number = higher priority) + + Handlers are executed in priority order. + """ + return 100 + + +class PluginAPI(ABC): + """Base class for platform-specific API plugins + + Platform API plugins expose platform capabilities to other plugins. + """ + + @abstractmethod + def get_platform_name(self) -> str: + """Get platform name""" + pass + + @abstractmethod + async def send_notification(self, title: str, message: str) -> bool: + """Send platform notification + + Args: + title: Notification title + message: Notification message + + Returns: + True if successful + """ + pass diff --git a/ye_linghua/plugins/examples/notify.ps1 b/ye_linghua/plugins/examples/notify.ps1 new file mode 100644 index 0000000..9f4548b --- /dev/null +++ b/ye_linghua/plugins/examples/notify.ps1 @@ -0,0 +1,95 @@ +# PLUGIN_ID: ps_notify +# PLUGIN_NAME: PowerShell Notification Plugin +# PLUGIN_VERSION: 1.0.0 +# PLUGIN_DESCRIPTION: Send Windows notifications via PowerShell + +# Read JSON input from stdin +$InputJson = [Console]::In.ReadToEnd() +$Input = ConvertFrom-Json $InputJson + +# Get action and data +$Action = $Input.action +$Data = $Input.data + +# Process action +switch ($Action) { + "get_prompt" { + # Return prompt extension + $Prompt = @" +## Windows通知功能 + +你可以请求发送Windows通知,我会使用PowerShell插件来处理。 +"@ + $Result = @{ + success = $true + prompt = $Prompt + } + ConvertTo-Json $Result -Compress + return + } + + "get_context" { + # Return context extension + $Result = @{ + success = $true + context = @{ + platform = "windows" + notification_available = $true + } + } + ConvertTo-Json $Result -Compress + return + } + + "send_notification" { + # Send Windows notification + $Title = $Data.title + $Message = $Data.message + + # Create toast notification + [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null + [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null + + $Template = @" + + + + $Title + $Message + + + +"@ + + try { + $Xml = New-Object Windows.Data.Xml.Dom.XmlDocument + $Xml.LoadXml($Template) + $Toast = [Windows.UI.Notifications.ToastNotification]::new($Xml) + $Notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Ye Linghua") + $Notifier.Show($Toast) + + $Result = @{ + success = $true + } + } + catch { + $Result = @{ + success = $false + error = $_.Exception.Message + } + } + + ConvertTo-Json $Result -Compress + return + } + + default { + # Unknown action + $Result = @{ + success = $false + error = "Unknown action: $Action" + } + ConvertTo-Json $Result -Compress + return + } +} diff --git a/ye_linghua/plugins/examples/notify.sh b/ye_linghua/plugins/examples/notify.sh new file mode 100644 index 0000000..70b5621 --- /dev/null +++ b/ye_linghua/plugins/examples/notify.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# PLUGIN_ID: sh_notify +# PLUGIN_NAME: Shell Notification Plugin +# PLUGIN_VERSION: 1.0.0 +# PLUGIN_DESCRIPTION: Send notifications via notify-send + +# Read JSON input from stdin +INPUT_JSON=$(cat) + +# Parse JSON using python +ACTION=$(echo "$INPUT_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['action'])") + +case "$ACTION" in + "get_prompt") + # Return prompt extension + echo '{ + "success": true, + "prompt": "## Linux通知功能\n\n你可以请求发送Linux桌面通知,我会使用notify-send来处理。" + }' + ;; + + "get_context") + # Return context extension + echo '{ + "success": true, + "context": { + "platform": "linux", + "notification_available": true + } + }' + ;; + + "send_notification") + # Parse title and message + TITLE=$(echo "$INPUT_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['title'])") + MESSAGE=$(echo "$INPUT_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['message'])") + + # Send notification + if command -v notify-send &> /dev/null; then + notify-send "$TITLE" "$MESSAGE" -u normal -i dialog-information + echo '{"success": true}' + else + echo '{"success": false, "error": "notify-send not found"}' + fi + ;; + + *) + echo "{\"success\": false, \"error\": \"Unknown action: $ACTION\"}" + ;; +esac diff --git a/ye_linghua/plugins/loader.py b/ye_linghua/plugins/loader.py new file mode 100644 index 0000000..2b67eb6 --- /dev/null +++ b/ye_linghua/plugins/loader.py @@ -0,0 +1,379 @@ +"""Plugin loader and manager""" + +import asyncio +import importlib +import importlib.util +import logging +import sys +from pathlib import Path +from typing import Any + +from .base import Plugin, PluginContext, PluginMetadata, PluginType, ReplyHandler +from .registry import PluginRegistry + +logger = logging.getLogger(__name__) + + +class PluginLoader: + """Plugin loader supporting Python and script-based plugins""" + + def __init__(self, plugins_dir: Path | str): + """Initialize plugin loader + + Args: + plugins_dir: Directory containing plugins + """ + self.plugins_dir = Path(plugins_dir) + self.loaded_modules: dict[str, Any] = {} + + async def load_plugin(self, plugin_path: Path) -> Plugin | None: + """Load a single plugin + + Args: + plugin_path: Path to plugin directory or script + + Returns: + Loaded plugin instance or None if failed + """ + try: + if plugin_path.is_dir(): + return await self._load_python_plugin(plugin_path) + elif plugin_path.suffix == ".py": + return await self._load_python_script(plugin_path) + elif plugin_path.suffix in [".ps1", ".sh"]: + return await self._load_shell_plugin(plugin_path) + else: + logger.warning(f"Unsupported plugin type: {plugin_path}") + return None + + except Exception as e: + logger.error(f"Failed to load plugin {plugin_path}: {e}", exc_info=True) + return None + + async def _load_python_plugin(self, plugin_dir: Path) -> Plugin | None: + """Load Python plugin from directory + + Expected structure: + plugin_dir/ + __init__.py (contains Plugin subclass) + metadata.yaml (optional) + + Args: + plugin_dir: Plugin directory + + Returns: + Plugin instance + """ + init_file = plugin_dir / "__init__.py" + if not init_file.exists(): + logger.error(f"Plugin directory missing __init__.py: {plugin_dir}") + return None + + # Import module + module_name = f"ye_linghua.plugins.{plugin_dir.name}" + try: + spec = importlib.util.spec_from_file_location(module_name, init_file) + if spec is None or spec.loader is None: + logger.error(f"Failed to create spec for {plugin_dir}") + return None + + module = importlib.util.module_from_spec(spec) + sys.modules[module_name] = module + spec.loader.exec_module(module) + + # Store module for hot reload + self.loaded_modules[module_name] = module + + # Find Plugin subclass + plugin_class = None + for item_name in dir(module): + item = getattr(module, item_name) + if ( + isinstance(item, type) + and issubclass(item, Plugin) + and item is not Plugin + ): + plugin_class = item + break + + if plugin_class is None: + logger.error(f"No Plugin subclass found in {plugin_dir}") + return None + + # Instantiate plugin + plugin = plugin_class() + await plugin.initialize() + + logger.info(f"Loaded Python plugin: {plugin.metadata.name}") + return plugin + + except Exception as e: + logger.error(f"Error loading Python plugin {plugin_dir}: {e}", exc_info=True) + return None + + async def _load_python_script(self, script_path: Path) -> Plugin | None: + """Load standalone Python plugin script + + Args: + script_path: Path to Python script + + Returns: + Plugin instance + """ + # Similar to _load_python_plugin but for single file + module_name = f"ye_linghua.plugins.{script_path.stem}" + + try: + spec = importlib.util.spec_from_file_location(module_name, script_path) + if spec is None or spec.loader is None: + return None + + module = importlib.util.module_from_spec(spec) + sys.modules[module_name] = module + spec.loader.exec_module(module) + + self.loaded_modules[module_name] = module + + # Find Plugin subclass + for item_name in dir(module): + item = getattr(module, item_name) + if ( + isinstance(item, type) + and issubclass(item, Plugin) + and item is not Plugin + ): + plugin = item() + await plugin.initialize() + logger.info(f"Loaded Python script plugin: {plugin.metadata.name}") + return plugin + + return None + + except Exception as e: + logger.error(f"Error loading Python script {script_path}: {e}", exc_info=True) + return None + + async def _load_shell_plugin(self, script_path: Path) -> Plugin | None: + """Load shell/PowerShell plugin + + Shell plugins are wrapped in a Python plugin that executes the script. + + Args: + script_path: Path to shell script + + Returns: + Plugin instance + """ + from .shell_wrapper import ShellPlugin + + try: + plugin = ShellPlugin(script_path) + await plugin.initialize() + logger.info(f"Loaded shell plugin: {plugin.metadata.name}") + return plugin + except Exception as e: + logger.error(f"Error loading shell plugin {script_path}: {e}", exc_info=True) + return None + + async def reload_plugin(self, plugin: Plugin) -> Plugin | None: + """Reload a plugin (hot reload) + + Args: + plugin: Plugin to reload + + Returns: + New plugin instance or None if failed + """ + try: + # Shutdown old plugin + await plugin.shutdown() + + # Reload module + module_name = plugin.__class__.__module__ + if module_name in self.loaded_modules: + importlib.reload(self.loaded_modules[module_name]) + + # Get new class and instantiate + module = self.loaded_modules[module_name] + for item_name in dir(module): + item = getattr(module, item_name) + if ( + isinstance(item, type) + and issubclass(item, Plugin) + and item is not Plugin + ): + new_plugin = item() + await new_plugin.initialize() + logger.info(f"Reloaded plugin: {new_plugin.metadata.name}") + return new_plugin + + return None + + except Exception as e: + logger.error(f"Error reloading plugin: {e}", exc_info=True) + return None + + +class PluginManager: + """Plugin manager for loading, managing, and coordinating plugins""" + + def __init__(self, plugins_dir: Path | str | None = None): + """Initialize plugin manager + + Args: + plugins_dir: Directory containing plugins + """ + self.plugins_dir = Path(plugins_dir) if plugins_dir else Path("./plugins") + self.loader = PluginLoader(self.plugins_dir) + self.registry = PluginRegistry() + self._watch_task: asyncio.Task | None = None + + async def discover_and_load_plugins(self) -> None: + """Discover and load all plugins from plugins directory""" + if not self.plugins_dir.exists(): + logger.warning(f"Plugins directory not found: {self.plugins_dir}") + self.plugins_dir.mkdir(parents=True, exist_ok=True) + return + + logger.info(f"Discovering plugins in: {self.plugins_dir}") + + # Scan for plugin directories and scripts + for item in self.plugins_dir.iterdir(): + if item.name.startswith("_") or item.name.startswith("."): + continue + + if item.is_dir() or item.suffix in [".py", ".ps1", ".sh"]: + plugin = await self.loader.load_plugin(item) + if plugin: + self.registry.register(plugin) + + logger.info(f"Loaded {len(self.registry.get_all_plugins())} plugins") + + async def enable_plugin(self, plugin_id: str) -> bool: + """Enable a plugin + + Args: + plugin_id: Plugin ID + + Returns: + True if successful + """ + return self.registry.enable_plugin(plugin_id) + + async def disable_plugin(self, plugin_id: str) -> bool: + """Disable a plugin + + Args: + plugin_id: Plugin ID + + Returns: + True if successful + """ + return self.registry.disable_plugin(plugin_id) + + async def reload_plugin(self, plugin_id: str) -> bool: + """Reload a plugin (hot reload) + + Args: + plugin_id: Plugin ID + + Returns: + True if successful + """ + plugin = self.registry.get_plugin(plugin_id) + if not plugin: + return False + + new_plugin = await self.loader.reload_plugin(plugin) + if new_plugin: + self.registry.register(new_plugin) + return True + + return False + + def get_enabled_plugins(self) -> list[Plugin]: + """Get all enabled plugins + + Returns: + List of enabled plugins + """ + return self.registry.get_enabled_plugins() + + def get_reply_handlers(self) -> list[ReplyHandler]: + """Get all reply handlers from enabled plugins + + Returns: + List of reply handlers sorted by priority + """ + return self.registry.get_reply_handlers() + + def build_prompt_extensions(self, context: PluginContext) -> str: + """Build combined prompt extensions from all enabled plugins + + Args: + context: Current context + + Returns: + Combined prompt extension text + """ + extensions = [] + for plugin in self.get_enabled_plugins(): + try: + ext = plugin.get_prompt_extension(context) + if ext: + extensions.append(ext) + except Exception as e: + logger.error(f"Error getting prompt extension from {plugin.metadata.id}: {e}") + + return "\n\n".join(extensions) if extensions else "" + + def build_context_extensions(self, context: PluginContext) -> dict[str, Any]: + """Build combined context extensions from all enabled plugins + + Args: + context: Current context + + Returns: + Combined context dictionary + """ + combined = {} + for plugin in self.get_enabled_plugins(): + try: + ext = plugin.get_context_extension(context) + if ext: + combined.update(ext) + except Exception as e: + logger.error(f"Error getting context extension from {plugin.metadata.id}: {e}") + + return combined + + async def shutdown_all(self) -> None: + """Shutdown all plugins""" + for plugin in self.registry.get_all_plugins(): + try: + await plugin.shutdown() + except Exception as e: + logger.error(f"Error shutting down plugin {plugin.metadata.id}: {e}") + + def start_watch(self, interval: float = 5.0) -> None: + """Start watching for plugin changes (for hot reload) + + Args: + interval: Check interval in seconds + """ + if self._watch_task is not None: + return + + async def watch_loop(): + while True: + await asyncio.sleep(interval) + # TODO: Implement file change detection and auto-reload + pass + + self._watch_task = asyncio.create_task(watch_loop()) + + def stop_watch(self) -> None: + """Stop watching for changes""" + if self._watch_task: + self._watch_task.cancel() + self._watch_task = None diff --git a/ye_linghua/plugins/notification/__init__.py b/ye_linghua/plugins/notification/__init__.py new file mode 100644 index 0000000..b44145d --- /dev/null +++ b/ye_linghua/plugins/notification/__init__.py @@ -0,0 +1,359 @@ +"""Notification plugin for desktop notifications""" + +import asyncio +import logging +import platform +import re +import subprocess +from dataclasses import dataclass + +from ..base import Plugin, PluginContext, PluginMetadata, PluginAPI, ReplyHandler + +logger = logging.getLogger(__name__) + + +@dataclass +class NotificationConfig: + """Notification configuration""" + + enabled: bool = True + use_system_notifications: bool = True + sound_enabled: bool = True + + +class NotificationBackend: + """Base class for notification backends""" + + async def send(self, title: str, message: str) -> bool: + """Send notification + + Args: + title: Notification title + message: Notification message + + Returns: + True if successful + """ + raise NotImplementedError + + +class WindowsNotificationBackend(NotificationBackend): + """Windows notification backend using PowerShell""" + + async def send(self, title: str, message: str) -> bool: + """Send Windows notification + + Uses PowerShell to show toast notification. + + Args: + title: Notification title + message: Notification message + + Returns: + True if successful + """ + try: + # PowerShell script to show toast notification + ps_script = f""" +[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null +[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null + +$template = @" + + + + {title} + {message} + + + +"@ + +$xml = New-Object Windows.Data.Xml.Dom.XmlDocument +$xml.LoadXml($template) +$toast = [Windows.UI.Notifications.ToastNotification]::new($xml) +$notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Ye Linghua") +$notifier.Show($toast) +""" + + # Execute PowerShell + process = await asyncio.create_subprocess_exec( + "powershell", + "-NoProfile", + "-Command", + ps_script, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) + + await process.communicate() + return process.returncode == 0 + + except Exception as e: + logger.error(f"Windows notification error: {e}") + return False + + +class LinuxNotificationBackend(NotificationBackend): + """Linux notification backend using notify-send""" + + async def send(self, title: str, message: str) -> bool: + """Send Linux notification + + Uses notify-send command. + + Args: + title: Notification title + message: Notification message + + Returns: + True if successful + """ + try: + process = await asyncio.create_subprocess_exec( + "notify-send", + title, + message, + "-u", + "normal", + "-i", + "dialog-information", + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) + + await process.communicate() + return process.returncode == 0 + + except FileNotFoundError: + logger.error("notify-send not found. Install libnotify-bin on Ubuntu/Debian") + return False + except Exception as e: + logger.error(f"Linux notification error: {e}") + return False + + +class MacOSNotificationBackend(NotificationBackend): + """macOS notification backend using osascript""" + + async def send(self, title: str, message: str) -> bool: + """Send macOS notification + + Uses osascript (AppleScript). + + Args: + title: Notification title + message: Notification message + + Returns: + True if successful + """ + try: + script = f'display notification "{message}" with title "{title}"' + + process = await asyncio.create_subprocess_exec( + "osascript", + "-e", + script, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) + + await process.communicate() + return process.returncode == 0 + + except Exception as e: + logger.error(f"macOS notification error: {e}") + return False + + +class NotificationReplyHandler(ReplyHandler): + """Reply handler for notification tags""" + + TAG_PATTERN = re.compile(r"", re.IGNORECASE) + + def __init__(self, plugin: "NotificationPlugin"): + """Initialize notification reply handler + + Args: + plugin: Notification plugin instance + """ + super().__init__(plugin) + self.notification_plugin = plugin + + async def handle_reply(self, response: str, context: PluginContext) -> tuple[str, bool]: + """Handle reply and process notification tags + + Args: + response: LLM response + context: Current context + + Returns: + Tuple of (modified_response, should_continue) + """ + modified_response = response + + # Find and process all tags + for match in self.TAG_PATTERN.finditer(response): + title = match.group(1) + message = match.group(2) + + # Send notification + success = await self.notification_plugin.send_notification(title, message) + + # Replace tag with confirmation + if success: + replacement = f"🔔 已发送通知" + else: + replacement = f"❌ 通知发送失败" + + modified_response = modified_response.replace(match.group(0), replacement) + + return modified_response, True + + @property + def priority(self) -> int: + """Handler priority""" + return 60 # Lower priority than timer + + +class NotificationAPI(PluginAPI): + """Notification API for platform integration""" + + def __init__(self, plugin: "NotificationPlugin"): + """Initialize notification API + + Args: + plugin: Notification plugin instance + """ + self.plugin = plugin + + def get_platform_name(self) -> str: + """Get platform name""" + return "notification" + + async def send_notification(self, title: str, message: str) -> bool: + """Send platform notification + + Args: + title: Notification title + message: Notification message + + Returns: + True if successful + """ + return await self.plugin.send_notification(title, message) + + +class NotificationPlugin(Plugin): + """Plugin for sending desktop notifications""" + + def __init__(self, config: NotificationConfig | None = None): + """Initialize notification plugin + + Args: + config: Notification configuration + """ + metadata = PluginMetadata( + id="notification", + name="Notification Plugin", + version="1.0.0", + description="Desktop notifications support", + ) + super().__init__(metadata) + + self.config = config or NotificationConfig() + self.backend: NotificationBackend | None = None + self.api = NotificationAPI(self) + + async def initialize(self) -> None: + """Initialize plugin""" + # Detect platform and select appropriate backend + system = platform.system() + + if system == "Windows": + self.backend = WindowsNotificationBackend() + elif system == "Linux": + self.backend = LinuxNotificationBackend() + elif system == "Darwin": # macOS + self.backend = MacOSNotificationBackend() + else: + logger.warning(f"Unsupported platform for notifications: {system}") + self.backend = None + + self._initialized = True + logger.info(f"Notification plugin initialized (platform: {system})") + + async def shutdown(self) -> None: + """Shutdown plugin""" + self._initialized = False + logger.info("Notification plugin shutdown") + + async def send_notification(self, title: str, message: str) -> bool: + """Send a notification + + Args: + title: Notification title + message: Notification message + + Returns: + True if successful + """ + if not self.config.enabled: + logger.debug("Notifications disabled") + return False + + if not self.backend: + logger.warning("No notification backend available") + return False + + try: + return await self.backend.send(title, message) + except Exception as e: + logger.error(f"Error sending notification: {e}") + return False + + def get_prompt_extension(self, context: PluginContext) -> str: + """Get prompt extension + + Args: + context: Current context + + Returns: + Prompt extension text + """ + if not self.config.enabled or not self.backend: + return "" + + return """ +## 通知功能 + +你可以使用 `` 标记来发送桌面通知: + +```xml + + +``` + +使用这个标记时,系统会自动发送桌面通知给用户。 +""" + + def get_reply_handlers(self) -> list[ReplyHandler]: + """Get reply handlers + + Returns: + List of reply handlers + """ + return [NotificationReplyHandler(self)] + + def get_api(self) -> NotificationAPI: + """Get notification API + + Returns: + Notification API instance + """ + return self.api + + +# Export plugin class +__all__ = ["NotificationPlugin", "NotificationConfig", "NotificationAPI"] diff --git a/ye_linghua/plugins/registry.py b/ye_linghua/plugins/registry.py new file mode 100644 index 0000000..f924e5c --- /dev/null +++ b/ye_linghua/plugins/registry.py @@ -0,0 +1,153 @@ +"""Plugin registry for managing loaded plugins""" + +import logging +from typing import Any + +from .base import Plugin, ReplyHandler + +logger = logging.getLogger(__name__) + + +class PluginRegistry: + """Registry for managing loaded plugins""" + + def __init__(self): + """Initialize plugin registry""" + self._plugins: dict[str, Plugin] = {} + self._reply_handlers: dict[str, list[ReplyHandler]] = {} + + def register(self, plugin: Plugin) -> None: + """Register a plugin + + Args: + plugin: Plugin to register + """ + plugin_id = plugin.metadata.id + + # If plugin already exists, unregister old one first + if plugin_id in self._plugins: + logger.info(f"Replacing existing plugin: {plugin_id}") + self.unregister(plugin_id) + + self._plugins[plugin_id] = plugin + logger.info(f"Registered plugin: {plugin_id} ({plugin.metadata.name})") + + # Register reply handlers if plugin has them + if hasattr(plugin, "get_reply_handlers"): + handlers = plugin.get_reply_handlers() + if handlers: + self._reply_handlers[plugin_id] = handlers + logger.debug(f"Registered {len(handlers)} reply handlers for {plugin_id}") + + def unregister(self, plugin_id: str) -> bool: + """Unregister a plugin + + Args: + plugin_id: Plugin ID + + Returns: + True if successful + """ + if plugin_id not in self._plugins: + return False + + del self._plugins[plugin_id] + + # Remove reply handlers + if plugin_id in self._reply_handlers: + del self._reply_handlers[plugin_id] + + logger.info(f"Unregistered plugin: {plugin_id}") + return True + + def get_plugin(self, plugin_id: str) -> Plugin | None: + """Get plugin by ID + + Args: + plugin_id: Plugin ID + + Returns: + Plugin or None if not found + """ + return self._plugins.get(plugin_id) + + def get_all_plugins(self) -> list[Plugin]: + """Get all registered plugins + + Returns: + List of all plugins + """ + return list(self._plugins.values()) + + def get_enabled_plugins(self) -> list[Plugin]: + """Get all enabled plugins + + Returns: + List of enabled plugins + """ + return [p for p in self._plugins.values() if p.metadata.enabled] + + def enable_plugin(self, plugin_id: str) -> bool: + """Enable a plugin + + Args: + plugin_id: Plugin ID + + Returns: + True if successful + """ + plugin = self.get_plugin(plugin_id) + if not plugin: + return False + + plugin.metadata.enabled = True + logger.info(f"Enabled plugin: {plugin_id}") + return True + + def disable_plugin(self, plugin_id: str) -> bool: + """Disable a plugin + + Args: + plugin_id: Plugin ID + + Returns: + True if successful + """ + plugin = self.get_plugin(plugin_id) + if not plugin: + return False + + plugin.metadata.enabled = False + logger.info(f"Disabled plugin: {plugin_id}") + return True + + def get_reply_handlers(self) -> list[ReplyHandler]: + """Get all reply handlers from enabled plugins + + Returns: + List of reply handlers sorted by priority + """ + handlers = [] + + for plugin_id, plugin in self._plugins.items(): + if not plugin.metadata.enabled: + continue + + if plugin_id in self._reply_handlers: + handlers.extend(self._reply_handlers[plugin_id]) + + # Sort by priority (lower number = higher priority) + handlers.sort(key=lambda h: h.priority) + + return handlers + + def get_plugins_by_type(self, plugin_type: str) -> list[Plugin]: + """Get plugins by type + + Args: + plugin_type: Plugin type + + Returns: + List of matching plugins + """ + return [p for p in self._plugins.values() if p.metadata.plugin_type == plugin_type] diff --git a/ye_linghua/plugins/shell_wrapper.py b/ye_linghua/plugins/shell_wrapper.py new file mode 100644 index 0000000..d21ca84 --- /dev/null +++ b/ye_linghua/plugins/shell_wrapper.py @@ -0,0 +1,195 @@ +"""Shell script plugin wrapper""" + +import asyncio +import json +import logging +import platform +import subprocess +from pathlib import Path + +from .base import Plugin, PluginContext, PluginMetadata, PluginType + +logger = logging.getLogger(__name__) + + +class ShellPlugin(Plugin): + """Wrapper for shell/PowerShell plugins + + Shell plugins are scripts that can be called with JSON input/output. + + Script interface: + Input (stdin): JSON with context data + Output (stdout): JSON with result + """ + + def __init__(self, script_path: Path): + """Initialize shell plugin + + Args: + script_path: Path to shell script + """ + self.script_path = script_path + + # Determine script type + if script_path.suffix == ".ps1": + plugin_type = PluginType.POWERSHELL + interpreter = "powershell" if platform.system() == "Windows" else "pwsh" + elif script_path.suffix == ".sh": + plugin_type = PluginType.SHELL + interpreter = "bash" + else: + raise ValueError(f"Unsupported script type: {script_path.suffix}") + + self.interpreter = interpreter + + # Create metadata from script + metadata = PluginMetadata( + id=f"shell_{script_path.stem}", + name=script_path.stem.replace("_", " ").title(), + version="1.0.0", + description=f"Shell plugin: {script_path.name}", + plugin_type=plugin_type, + ) + + super().__init__(metadata) + + async def initialize(self) -> None: + """Initialize plugin""" + # Verify script exists and is executable + if not self.script_path.exists(): + raise FileNotFoundError(f"Script not found: {self.script_path}") + + # Try to read metadata from script comments + try: + await self._read_script_metadata() + except Exception as e: + logger.warning(f"Could not read metadata from {self.script_path}: {e}") + + self._initialized = True + + async def shutdown(self) -> None: + """Shutdown plugin""" + self._initialized = False + + async def _read_script_metadata(self) -> None: + """Read metadata from script comments + + Looks for special comment blocks like: + # PLUGIN_NAME: My Plugin + # PLUGIN_VERSION: 1.0.0 + # PLUGIN_DESCRIPTION: Does something cool + """ + with open(self.script_path, encoding="utf-8") as f: + content = f.read() + + lines = content.split("\n") + for line in lines: + line = line.strip() + if line.startswith("#") and ":" in line: + key_value = line[1:].strip() + if key_value.startswith("PLUGIN_"): + key, value = key_value.split(":", 1) + key = key.replace("PLUGIN_", "").lower() + value = value.strip() + + if key == "name": + self.metadata.name = value + elif key == "version": + self.metadata.version = value + elif key == "description": + self.metadata.description = value + elif key == "id": + self.metadata.id = value + + async def execute_script( + self, + action: str, + data: dict[str, any] | None = None, + ) -> dict[str, any]: + """Execute shell script with data + + Args: + action: Action to perform + data: Input data + + Returns: + Script output as dictionary + """ + input_data = { + "action": action, + "data": data or {}, + } + + try: + # Execute script + cmd = [self.interpreter, str(self.script_path)] + + process = await asyncio.create_subprocess_exec( + *cmd, + stdin=asyncio.subprocess.PIPE, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) + + # Send input data + input_json = json.dumps(input_data).encode("utf-8") + stdout, stderr = await process.communicate(input=input_json) + + if process.returncode != 0: + error_msg = stderr.decode("utf-8") + logger.error(f"Script error: {error_msg}") + return {"success": False, "error": error_msg} + + # Parse output + output_str = stdout.decode("utf-8") + try: + result = json.loads(output_str) + return result + except json.JSONDecodeError: + # If output is not JSON, wrap it + return {"success": True, "output": output_str} + + except Exception as e: + logger.error(f"Error executing script {self.script_path}: {e}", exc_info=True) + return {"success": False, "error": str(e)} + + def get_prompt_extension(self, context: PluginContext) -> str: + """Get prompt extension + + Args: + context: Current context + + Returns: + Prompt extension text + """ + # Execute script with "get_prompt" action + try: + loop = asyncio.get_event_loop() + result = loop.run_until_complete(self.execute_script("get_prompt", {"context": context.__dict__})) + + if result.get("success"): + return result.get("prompt", "") + return "" + except Exception as e: + logger.error(f"Error getting prompt extension from shell plugin: {e}") + return "" + + def get_context_extension(self, context: PluginContext) -> dict[str, any]: + """Get context extension + + Args: + context: Current context + + Returns: + Context extension dictionary + """ + try: + loop = asyncio.get_event_loop() + result = loop.run_until_complete(self.execute_script("get_context", {"context": context.__dict__})) + + if result.get("success"): + return result.get("context", {}) + return {} + except Exception as e: + logger.error(f"Error getting context extension from shell plugin: {e}") + return {} diff --git a/ye_linghua/plugins/timer/__init__.py b/ye_linghua/plugins/timer/__init__.py new file mode 100644 index 0000000..6950a9f --- /dev/null +++ b/ye_linghua/plugins/timer/__init__.py @@ -0,0 +1,517 @@ +"""Timer plugin for scheduled tasks and reminders""" + +import asyncio +import json +import logging +import re +from dataclasses import dataclass +from datetime import datetime, timedelta +from enum import Enum +from pathlib import Path +from typing import Any + +from ..base import Plugin, PluginContext, PluginMetadata, ReplyHandler + +logger = logging.getLogger(__name__) + + +class RepeatStrategy(str, Enum): + """Timer repeat strategy""" + + ONCE = "once" + DAILY = "daily" + WEEKLY = "weekly" + MONTHLY = "monthly" + + +@dataclass +class TimerTask: + """Timer task data""" + + id: str + trigger_time: datetime + reason: str + repeat: RepeatStrategy + context_summary: str + platform: str + user_id: str | None + created_at: datetime + enabled: bool = True + + +class TimerStorage: + """Storage for timer tasks""" + + def __init__(self, storage_file: Path | str): + """Initialize timer storage + + Args: + storage_file: Path to JSON storage file + """ + self.storage_file = Path(storage_file) + self.timers: dict[str, TimerTask] = {} + self._load() + + def _load(self) -> None: + """Load timers from storage file""" + if not self.storage_file.exists(): + return + + try: + with open(self.storage_file, encoding="utf-8") as f: + data = json.load(f) + + for timer_id, timer_data in data.items(): + try: + timer = TimerTask( + id=timer_id, + trigger_time=datetime.fromisoformat(timer_data["trigger_time"]), + reason=timer_data["reason"], + repeat=RepeatStrategy(timer_data["repeat"]), + context_summary=timer_data["context_summary"], + platform=timer_data["platform"], + user_id=timer_data.get("user_id"), + created_at=datetime.fromisoformat(timer_data["created_at"]), + enabled=timer_data.get("enabled", True), + ) + self.timers[timer_id] = timer + except Exception as e: + logger.error(f"Error loading timer {timer_id}: {e}") + + except Exception as e: + logger.error(f"Error loading timer storage: {e}") + + def _save(self) -> None: + """Save timers to storage file""" + try: + # Ensure directory exists + self.storage_file.parent.mkdir(parents=True, exist_ok=True) + + data = {} + for timer_id, timer in self.timers.items(): + data[timer_id] = { + "trigger_time": timer.trigger_time.isoformat(), + "reason": timer.reason, + "repeat": timer.repeat.value, + "context_summary": timer.context_summary, + "platform": timer.platform, + "user_id": timer.user_id, + "created_at": timer.created_at.isoformat(), + "enabled": timer.enabled, + } + + with open(self.storage_file, "w", encoding="utf-8") as f: + json.dump(data, f, indent=2, ensure_ascii=False) + + except Exception as e: + logger.error(f"Error saving timer storage: {e}") + + def add_timer(self, timer: TimerTask) -> None: + """Add a timer + + Args: + timer: Timer task + """ + self.timers[timer.id] = timer + self._save() + + def remove_timer(self, timer_id: str) -> bool: + """Remove a timer + + Args: + timer_id: Timer ID + + Returns: + True if successful + """ + if timer_id in self.timers: + del self.timers[timer_id] + self._save() + return True + return False + + def get_timer(self, timer_id: str) -> TimerTask | None: + """Get timer by ID + + Args: + timer_id: Timer ID + + Returns: + Timer task or None + """ + return self.timers.get(timer_id) + + def get_all_timers(self) -> list[TimerTask]: + """Get all timers + + Returns: + List of timer tasks + """ + return list(self.timers.values()) + + def get_due_timers(self) -> list[TimerTask]: + """Get timers that are due + + Returns: + List of due timer tasks + """ + now = datetime.now() + due_timers = [] + + for timer in self.timers.values(): + if timer.enabled and timer.trigger_time <= now: + due_timers.append(timer) + + return due_timers + + +class TimerReplyHandler(ReplyHandler): + """Reply handler for timer tags""" + + TAG_PATTERNS = { + "set": re.compile(r"", re.IGNORECASE), + "list": re.compile(r"", re.IGNORECASE), + "remove": re.compile(r"", re.IGNORECASE), + } + + def __init__(self, plugin: "TimerPlugin"): + """Initialize timer reply handler + + Args: + plugin: Timer plugin instance + """ + super().__init__(plugin) + self.timer_plugin = plugin + + async def handle_reply(self, response: str, context: PluginContext) -> tuple[str, bool]: + """Handle reply and process timer tags + + Args: + response: LLM response + context: Current context + + Returns: + Tuple of (modified_response, should_continue) + """ + modified_response = response + found_tags = False + + # Check for set-timer tags + for match in self.TAG_PATTERNS["set"].finditer(response): + found_tags = True + time_str = match.group(1) + reason = match.group(2) + repeat = match.group(3) or "once" + + # Parse time and create timer + timer_id = await self.timer_plugin.set_timer( + time_str=time_str, + reason=reason, + repeat=RepeatStrategy(repeat.lower()), + context=context, + ) + + # Replace tag with confirmation message + replacement = f"✅ 已设置定时器 (ID: {timer_id[:8]})" + modified_response = modified_response.replace(match.group(0), replacement) + + # Check for list-timers tags + for match in self.TAG_PATTERNS["list"].finditer(response): + found_tags = True + timers_list = self.timer_plugin.list_timers() + + # Replace tag with timers list + modified_response = modified_response.replace(match.group(0), timers_list) + + # Check for remove-timer tags + for match in self.TAG_PATTERNS["remove"].finditer(response): + found_tags = True + timer_id = match.group(1) + + success = self.timer_plugin.remove_timer(timer_id) + replacement = f"✅ 已删除定时器 {timer_id}" if success else f"❌ 找不到定时器 {timer_id}" + modified_response = modified_response.replace(match.group(0), replacement) + + return modified_response, True + + @property + def priority(self) -> int: + """Handler priority""" + return 50 # Medium priority + + +class TimerPlugin(Plugin): + """Timer plugin for scheduled reminders""" + + def __init__(self, storage_file: Path | str | None = None): + """Initialize timer plugin + + Args: + storage_file: Path to timer storage file + """ + metadata = PluginMetadata( + id="timer", + name="Timer Plugin", + version="1.0.0", + description="Scheduled tasks and reminders", + ) + super().__init__(metadata) + + if storage_file is None: + storage_file = Path.home() / ".ye-linghua" / "timers.json" + + self.storage = TimerStorage(storage_file) + self._scheduler_task: asyncio.Task | None = None + self._callback: callable | None = None + + async def initialize(self) -> None: + """Initialize plugin""" + # Start scheduler + self._start_scheduler() + self._initialized = True + logger.info("Timer plugin initialized") + + async def shutdown(self) -> None: + """Shutdown plugin""" + if self._scheduler_task: + self._scheduler_task.cancel() + try: + await self._scheduler_task + except asyncio.CancelledError: + pass + + self._initialized = False + logger.info("Timer plugin shutdown") + + def set_callback(self, callback: callable) -> None: + """Set callback for timer triggers + + Args: + callback: Async callback function(timer: TimerTask) -> None + """ + self._callback = callback + + async def set_timer( + self, + time_str: str, + reason: str, + repeat: RepeatStrategy, + context: PluginContext, + ) -> str: + """Set a timer + + Args: + time_str: Time string (e.g., "in 5 minutes", "2024-12-25 10:00") + reason: Reason for timer + repeat: Repeat strategy + context: Current context + + Returns: + Timer ID + """ + # Parse time string + trigger_time = self._parse_time_string(time_str) + + # Generate timer ID + import uuid + + timer_id = str(uuid.uuid4()) + + # Create timer task + timer = TimerTask( + id=timer_id, + trigger_time=trigger_time, + reason=reason, + repeat=repeat, + context_summary=context.get_message_summary(), + platform=context.platform, + user_id=context.user_id, + created_at=datetime.now(), + ) + + # Store timer + self.storage.add_timer(timer) + + logger.info(f"Set timer: {timer_id} for {trigger_time}") + return timer_id + + def remove_timer(self, timer_id: str) -> bool: + """Remove a timer + + Args: + timer_id: Timer ID (can be partial match) + + Returns: + True if successful + """ + # Find matching timer + for tid in self.storage.timers.keys(): + if tid.startswith(timer_id): + return self.storage.remove_timer(tid) + + return False + + def list_timers(self) -> str: + """List all timers + + Returns: + Formatted string of all timers + """ + timers = self.storage.get_all_timers() + + if not timers: + return "📋 没有活动的定时器" + + lines = ["📋 活动定时器列表:\n"] + for timer in timers: + status = "✅" if timer.enabled else "❌" + time_str = timer.trigger_time.strftime("%Y-%m-%d %H:%M:%S") + lines.append(f"{status} [{timer.id[:8]}] {time_str} - {timer.reason} ({timer.repeat.value})") + + return "\n".join(lines) + + def _parse_time_string(self, time_str: str) -> datetime: + """Parse time string to datetime + + Args: + time_str: Time string + + Returns: + Datetime object + """ + time_str = time_str.lower().strip() + + # Try relative time (e.g., "in 5 minutes") + if time_str.startswith("in "): + parts = time_str[3:].strip().split() + if len(parts) >= 2: + try: + amount = int(parts[0]) + unit = parts[1] + + now = datetime.now() + if "minute" in unit: + return now + timedelta(minutes=amount) + elif "hour" in unit: + return now + timedelta(hours=amount) + elif "day" in unit: + return now + timedelta(days=amount) + elif "week" in unit: + return now + timedelta(weeks=amount) + except ValueError: + pass + + # Try absolute time (ISO format) + try: + return datetime.fromisoformat(time_str) + except ValueError: + pass + + # Try common formats + common_formats = [ + "%Y-%m-%d %H:%M:%S", + "%Y-%m-%d %H:%M", + "%m/%d/%Y %H:%M", + "%d/%m/%Y %H:%M", + ] + + for fmt in common_formats: + try: + return datetime.strptime(time_str, fmt) + except ValueError: + continue + + # Default: 1 hour from now + logger.warning(f"Could not parse time string '{time_str}', defaulting to 1 hour") + return datetime.now() + timedelta(hours=1) + + def _start_scheduler(self) -> None: + """Start timer scheduler""" + async def scheduler_loop(): + while True: + try: + # Check for due timers + due_timers = self.storage.get_due_timers() + + for timer in due_timers: + # Trigger callback + if self._callback: + try: + await self._callback(timer) + except Exception as e: + logger.error(f"Error in timer callback: {e}") + + # Handle repeat + if timer.repeat == RepeatStrategy.ONCE: + self.storage.remove_timer(timer.id) + else: + # Calculate next trigger time + if timer.repeat == RepeatStrategy.DAILY: + timer.trigger_time += timedelta(days=1) + elif timer.repeat == RepeatStrategy.WEEKLY: + timer.trigger_time += timedelta(weeks=1) + elif timer.repeat == RepeatStrategy.MONTHLY: + # Approximate month as 30 days + timer.trigger_time += timedelta(days=30) + + self.storage.add_timer(timer) + + # Sleep before next check + await asyncio.sleep(30) # Check every 30 seconds + + except asyncio.CancelledError: + break + except Exception as e: + logger.error(f"Error in timer scheduler: {e}") + await asyncio.sleep(60) + + self._scheduler_task = asyncio.create_task(scheduler_loop()) + + def get_prompt_extension(self, context: PluginContext) -> str: + """Get prompt extension + + Args: + context: Current context + + Returns: + Prompt extension text + """ + return """ +## 定时器功能 + +你可以使用以下标记来管理定时器: + +1. **设置定时器**: + ```xml + + + ``` + + - `time`: 时间(可以是 "in X minutes/hours/days" 或具体时间) + - `reason`: 提醒原因 + - `repeat`: 重复策略(once, daily, weekly, monthly) + +2. **列出所有定时器**: + ```xml + + ``` + +3. **删除定时器**: + ```xml + + ``` + +使用这些标记时,我会自动处理并显示结果。 +""" + + def get_reply_handlers(self) -> list[ReplyHandler]: + """Get reply handlers + + Returns: + List of reply handlers + """ + return [TimerReplyHandler(self)] + + +# Export plugin class +__all__ = ["TimerPlugin", "TimerTask", "RepeatStrategy"] From 8dae895b160ba48bc47b9410f6253e2163fb1afd Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Nov 2025 07:24:37 +0000 Subject: [PATCH 3/4] feat: integrate plugin system into Agent and CLI Agent Integration: - Add plugin_registry, platform, user_id, session_id parameters to Agent.__init__() - Implement _build_plugin_context() to convert agent state to PluginContext - Implement _get_plugin_prompt_extensions() to inject plugin prompts into system prompt - Implement _process_reply_with_plugins() to process LLM responses through ReplyHandler chain - Update run() method to process responses with plugin handlers before display - Plugin prompt extensions are automatically injected into system prompt on initialization CLI Integration: - Initialize PluginRegistry and PluginLoader in run_agent() - Load built-in plugins (Timer & Notification) based on config - Auto-discover and load plugins from plugins directory - Pass plugin_registry to Agent constructor - Generate unique session_id for each session - Display active plugins count in session info - Properly shutdown all plugins on exit Features: - Plugin prompt extensions visible to LLM in system prompt - ReplyHandler chain processes responses by priority - Tag-based functionality (, ) works automatically - Platform context (cli) passed to plugins - Session tracking with unique IDs --- ye_linghua/agent.py | 123 ++++++++++++++++++++++++++++++++++++++++++-- ye_linghua/cli.py | 81 ++++++++++++++++++++++++++++- 2 files changed, 199 insertions(+), 5 deletions(-) diff --git a/ye_linghua/agent.py b/ye_linghua/agent.py index 9539bc4..1f3625a 100644 --- a/ye_linghua/agent.py +++ b/ye_linghua/agent.py @@ -7,6 +7,8 @@ from .llm import LLMClient from .logger import AgentLogger +from .plugins import PluginRegistry +from .plugins.base import PluginContext from .schema import Message from .tools.base import Tool, ToolResult from .utils import calculate_display_width @@ -50,12 +52,20 @@ def __init__( max_steps: int = 50, workspace_dir: str = "./workspace", token_limit: int = 80000, # Summary triggered when tokens exceed this value + plugin_registry: PluginRegistry | None = None, + platform: str = "cli", + user_id: str | None = None, + session_id: str | None = None, ): self.llm = llm_client self.tools = {tool.name: tool for tool in tools} self.max_steps = max_steps self.token_limit = token_limit self.workspace_dir = Path(workspace_dir) + self.plugin_registry = plugin_registry + self.platform = platform + self.user_id = user_id + self.session_id = session_id # Ensure workspace exists self.workspace_dir.mkdir(parents=True, exist_ok=True) @@ -65,6 +75,12 @@ def __init__( workspace_info = f"\n\n## Current Workspace\nYou are currently working in: `{self.workspace_dir.absolute()}`\nAll relative paths will be resolved relative to this directory." system_prompt = system_prompt + workspace_info + # Inject plugin prompt extensions if plugins are enabled + if self.plugin_registry: + plugin_extensions = self._get_plugin_prompt_extensions() + if plugin_extensions: + system_prompt = system_prompt + "\n\n" + plugin_extensions + self.system_prompt = system_prompt # Initialize message history @@ -320,14 +336,22 @@ async def run(self) -> str: print(f"\n{Colors.BOLD}{Colors.MAGENTA}🧠 Thinking:{Colors.RESET}") print(f"{Colors.DIM}{response.thinking}{Colors.RESET}") - # Print assistant response + # Process response through plugin ReplyHandler chain + processed_content = response.content if response.content: + processed_content = await self._process_reply_with_plugins(response.content) + + # Update the assistant message content with processed version + assistant_msg.content = processed_content + + # Print assistant response + if processed_content: print(f"\n{Colors.BOLD}{Colors.BRIGHT_BLUE}🤖 Assistant:{Colors.RESET}") - print(f"{response.content}") + print(f"{processed_content}") # Check if task is complete (no tool calls) if not response.tool_calls: - return response.content + return processed_content # Execute tool calls for tool_call in response.tool_calls: @@ -412,3 +436,96 @@ async def run(self) -> str: def get_history(self) -> list[Message]: """Get message history.""" return self.messages.copy() + + def _build_plugin_context(self) -> PluginContext: + """Build plugin context from current agent state + + Returns: + PluginContext with current conversation state + """ + # Convert messages to dict format for plugins + messages_dict = [] + for msg in self.messages: + msg_dict = { + "role": msg.role, + "content": msg.content, + } + if msg.thinking: + msg_dict["thinking"] = msg.thinking + if msg.tool_calls: + msg_dict["tool_calls"] = [ + { + "id": tc.id, + "function": { + "name": tc.function.name, + "arguments": tc.function.arguments, + }, + } + for tc in msg.tool_calls + ] + if msg.tool_call_id: + msg_dict["tool_call_id"] = msg.tool_call_id + if msg.name: + msg_dict["name"] = msg.name + messages_dict.append(msg_dict) + + return PluginContext( + messages=messages_dict, + platform=self.platform, + user_id=self.user_id, + session_id=self.session_id, + config={}, + extra={}, + ) + + def _get_plugin_prompt_extensions(self) -> str: + """Get prompt extensions from all plugins + + Returns: + Combined prompt extensions from all plugins + """ + if not self.plugin_registry: + return "" + + context = self._build_plugin_context() + extensions = [] + + for plugin in self.plugin_registry.get_all_plugins(): + try: + extension = plugin.get_prompt_extension(context) + if extension: + extensions.append(extension) + except Exception as e: + print(f"{Colors.BRIGHT_RED}⚠️ Error getting prompt extension from plugin {plugin.metadata.name}: {e}{Colors.RESET}") + + if extensions: + return "# Plugin Extensions\n\n" + "\n\n".join(extensions) + return "" + + async def _process_reply_with_plugins(self, response_content: str) -> str: + """Process LLM reply through plugin ReplyHandler chain + + Args: + response_content: Original LLM response content + + Returns: + Modified response content after plugin processing + """ + if not self.plugin_registry: + return response_content + + context = self._build_plugin_context() + handlers = self.plugin_registry.get_reply_handlers() + + modified_content = response_content + + for handler in handlers: + try: + modified_content, should_continue = await handler.handle_reply(modified_content, context) + if not should_continue: + break + except Exception as e: + print(f"{Colors.BRIGHT_RED}⚠️ Error in plugin reply handler {handler.__class__.__name__}: {e}{Colors.RESET}") + continue + + return modified_content diff --git a/ye_linghua/cli.py b/ye_linghua/cli.py index 9a93b88..028b88c 100644 --- a/ye_linghua/cli.py +++ b/ye_linghua/cli.py @@ -148,6 +148,12 @@ def print_info_line(text: str): print_info_line(f"Message History: {len(agent.messages)} messages") print_info_line(f"Available Tools: {len(agent.tools)} tools") + # Plugin information + if agent.plugin_registry: + plugins = agent.plugin_registry.get_all_plugins() + if plugins: + print_info_line(f"Active Plugins: {len(plugins)} plugins") + # Bottom border print(f"{Colors.DIM}└{'─' * BOX_WIDTH}┘{Colors.RESET}") print() @@ -479,13 +485,71 @@ def on_retry(exception: Exception, attempt: int): # Remove placeholder if skills not enabled system_prompt = system_prompt.replace("{SKILLS_METADATA}", "") - # 7. Create Agent + # 7. Initialize Plugin System + plugin_registry = None + if config.plugins.enabled: + from ye_linghua.plugins import PluginLoader, PluginRegistry + from ye_linghua.plugins.notification import NotificationPlugin, NotificationConfig + from ye_linghua.plugins.timer import TimerPlugin + + print(f"{Colors.BRIGHT_CYAN}Initializing plugin system...{Colors.RESET}") + + plugin_registry = PluginRegistry() + plugin_loader = PluginLoader(plugin_registry) + + # Load built-in plugins + if config.plugins.timer_enabled: + try: + timer_plugin = TimerPlugin() + await timer_plugin.initialize() + plugin_registry.register_plugin(timer_plugin) + print(f"{Colors.GREEN}✅ Loaded Timer plugin{Colors.RESET}") + except Exception as e: + print(f"{Colors.YELLOW}⚠️ Failed to load Timer plugin: {e}{Colors.RESET}") + + if config.plugins.notification_enabled: + try: + notification_config = NotificationConfig( + enabled=True, + sound_enabled=config.plugins.notification_sound, + ) + notification_plugin = NotificationPlugin(notification_config) + await notification_plugin.initialize() + plugin_registry.register_plugin(notification_plugin) + print(f"{Colors.GREEN}✅ Loaded Notification plugin{Colors.RESET}") + except Exception as e: + print(f"{Colors.YELLOW}⚠️ Failed to load Notification plugin: {e}{Colors.RESET}") + + # Auto-discover and load plugins from plugins directory + if config.plugins.auto_discover: + try: + plugins_dir = Path(config.plugins.plugins_dir) + if plugins_dir.exists(): + discovered = await plugin_loader.discover_plugins(str(plugins_dir)) + if discovered: + print(f"{Colors.GREEN}✅ Auto-discovered {len(discovered)} plugins from {plugins_dir}{Colors.RESET}") + else: + print(f"{Colors.DIM} Plugins directory not found: {plugins_dir}{Colors.RESET}") + except Exception as e: + print(f"{Colors.YELLOW}⚠️ Plugin auto-discovery failed: {e}{Colors.RESET}") + + print() # Empty line separator + + # Generate session ID + import uuid + + session_id = str(uuid.uuid4()) + + # 8. Create Agent agent = Agent( llm_client=llm_client, system_prompt=system_prompt, tools=tools, max_steps=config.agent.max_steps, workspace_dir=str(workspace_dir), + plugin_registry=plugin_registry, + platform="cli", + session_id=session_id, ) # 8. Display welcome information @@ -609,7 +673,20 @@ def _(event): print(f"\n{Colors.RED}❌ Error: {e}{Colors.RESET}") print(f"{Colors.DIM}{'─' * 60}{Colors.RESET}\n") - # 10. Cleanup MCP connections + # 10. Cleanup plugins + if plugin_registry: + try: + print(f"{Colors.BRIGHT_CYAN}Shutting down plugins...{Colors.RESET}") + for plugin in plugin_registry.get_all_plugins(): + try: + await plugin.shutdown() + except Exception as e: + print(f"{Colors.YELLOW}Warning: Failed to shutdown plugin {plugin.metadata.name}: {e}{Colors.RESET}") + print(f"{Colors.GREEN}✅ Plugins shutdown complete{Colors.RESET}") + except Exception as e: + print(f"{Colors.YELLOW}Error during plugin cleanup (can be ignored): {e}{Colors.RESET}") + + # 11. Cleanup MCP connections try: print(f"{Colors.BRIGHT_CYAN}Cleaning up MCP connections...{Colors.RESET}") await cleanup_mcp_connections() From 481229dcb08b327e705651c4f115490e6c464902 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Nov 2025 07:25:45 +0000 Subject: [PATCH 4/4] docs: add Agent integration section to PLUGINS.md - Document automatic plugin integration in Agent - Explain system prompt injection and ReplyHandler chain - Provide CLI usage examples with plugin loading output - Add programmatic usage example for custom integrations - Show how plugins work transparently with Agent runtime --- PLUGINS.md | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/PLUGINS.md b/PLUGINS.md index ab7f676..b42a606 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -10,6 +10,95 @@ - ✅ **自动发现** - 自动扫描plugins目录 - ✅ **Reply Handler链** - 处理LLM回复的插件链 - ✅ **上下文注入** - 向LLM注入插件功能 +- ✅ **Agent集成** - 完全集成到Agent运行时 + +## Agent集成 + +插件系统已完全集成到Ye Linghua的Agent类中,无需额外配置即可工作: + +### 自动集成特性 + +1. **系统提示词注入** + - 插件的 `get_prompt_extension()` 会在Agent初始化时自动注入到系统提示词 + - LLM可以看到所有可用的插件功能和使用方法 + +2. **响应处理链** + - LLM的每个响应都会通过 ReplyHandler 链处理 + - 插件可以提取标记(如 ``、``)并执行相应操作 + - 按优先级顺序执行Handler + +3. **上下文共享** + - 插件接收完整的对话历史和平台信息 + - 可以访问session_id、user_id、platform等元数据 + +### 在CLI中使用 + +启动Ye Linghua CLI时,插件会自动加载: + +```bash +ye-linghua +``` + +启动信息会显示加载的插件: + +``` +Initializing plugin system... +✅ Loaded Timer plugin +✅ Loaded Notification plugin +✅ Auto-discovered 2 plugins from ./plugins + +╔══════════════════════════════════════════════════════════╗ +║ 🌸 叶灵华 (Ye Linghua) - 热爱编程的AI少女 ║ +╚══════════════════════════════════════════════════════════╝ + +┌──────────────────────────────────────────────────────────┐ +│ Session Info │ +├──────────────────────────────────────────────────────────┤ +│ Model: MiniMax-M2 │ +│ Workspace: /path/to/workspace │ +│ Message History: 1 messages │ +│ Available Tools: 10 tools │ +│ Active Plugins: 2 plugins │ +└──────────────────────────────────────────────────────────┘ +``` + +### 编程方式使用 + +如果要在代码中使用Agent: + +```python +from ye_linghua import LLMClient, Agent +from ye_linghua.plugins import PluginRegistry +from ye_linghua.plugins.timer import TimerPlugin +from ye_linghua.plugins.notification import NotificationPlugin + +# 创建插件注册表 +plugin_registry = PluginRegistry() + +# 加载插件 +timer_plugin = TimerPlugin() +await timer_plugin.initialize() +plugin_registry.register_plugin(timer_plugin) + +notification_plugin = NotificationPlugin() +await notification_plugin.initialize() +plugin_registry.register_plugin(notification_plugin) + +# 创建Agent,传入插件注册表 +agent = Agent( + llm_client=llm_client, + system_prompt=system_prompt, + tools=tools, + plugin_registry=plugin_registry, + platform="custom", + session_id="my-session-id" +) + +# 运行Agent - 插件会自动工作 +agent.add_user_message("提醒我5分钟后查看邮件") +response = await agent.run() +# LLM会生成 标记,Timer插件自动处理 +``` ## 内置插件