Showing preview only (6,444K chars total). Download the full file or copy to clipboard to get everything.
Repository: ChenglinPoly/infiAgent
Branch: main
Commit: ac97e4661597
Files: 449
Total size: 5.8 MB
Directory structure:
gitextract__7wj7h3m/
├── .dockerignore
├── .gitignore
├── Dockerfile
├── LICENSE
├── MANIFEST.in
├── README.md
├── README_CN.md
├── apps/
│ ├── __init__.py
│ └── cheapclaw/
│ ├── README.md
│ ├── __init__.py
│ ├── assets/
│ │ ├── agent_library/
│ │ │ ├── CheapClawSupervisor/
│ │ │ │ ├── general_prompts.yaml
│ │ │ │ ├── level_0_tools.yaml
│ │ │ │ └── level_3_agents.yaml
│ │ │ └── CheapClawWorkerGeneral/
│ │ │ ├── general_prompts.yaml
│ │ │ ├── level_0_tools.yaml
│ │ │ └── level_3_agents.yaml
│ │ └── config/
│ │ ├── app_config.example.json
│ │ ├── channels.example.json
│ │ └── llm_config_example.yaml
│ ├── cheapclaw_hooks.py
│ ├── cheapclaw_service.py
│ ├── skills/
│ │ ├── cheapclaw-watchdog/
│ │ │ └── SKILL.md
│ │ └── find-skills/
│ │ └── SKILL.md
│ ├── tool_runtime_helpers.py
│ ├── tools_library/
│ │ ├── cheapclaw_add_task_message/
│ │ │ └── cheapclaw_add_task_message.py
│ │ ├── cheapclaw_cancel_plan/
│ │ │ └── cheapclaw_cancel_plan.py
│ │ ├── cheapclaw_generate_task_id/
│ │ │ └── cheapclaw_generate_task_id.py
│ │ ├── cheapclaw_get_task_status/
│ │ │ └── cheapclaw_get_task_status.py
│ │ ├── cheapclaw_list_agent_systems/
│ │ │ └── cheapclaw_list_agent_systems.py
│ │ ├── cheapclaw_list_conversation_tasks/
│ │ │ └── cheapclaw_list_conversation_tasks.py
│ │ ├── cheapclaw_list_global_skills/
│ │ │ └── cheapclaw_list_global_skills.py
│ │ ├── cheapclaw_read_panel/
│ │ │ └── cheapclaw_read_panel.py
│ │ ├── cheapclaw_read_social_history/
│ │ │ └── cheapclaw_read_social_history.py
│ │ ├── cheapclaw_reset_task/
│ │ │ └── cheapclaw_reset_task.py
│ │ ├── cheapclaw_reveal_skills/
│ │ │ └── cheapclaw_reveal_skills.py
│ │ ├── cheapclaw_schedule_plan/
│ │ │ └── cheapclaw_schedule_plan.py
│ │ ├── cheapclaw_send_file/
│ │ │ └── cheapclaw_send_file.py
│ │ ├── cheapclaw_send_message/
│ │ │ └── cheapclaw_send_message.py
│ │ ├── cheapclaw_start_task/
│ │ │ └── cheapclaw_start_task.py
│ │ └── cheapclaw_update_panel/
│ │ └── cheapclaw_update_panel.py
│ └── web/
│ └── dashboard.html
├── backend_build/
│ ├── build_mac_universal.sh
│ └── pyinstaller_backend.spec
├── config/
│ ├── agent_library/
│ │ ├── OpenCowork/
│ │ │ ├── general_prompts.yaml
│ │ │ ├── level_-1_judge_agent.yaml
│ │ │ ├── level_0_tools.yaml
│ │ │ └── level_3_agents.yaml
│ │ └── Researcher/
│ │ ├── general_prompts.yaml
│ │ ├── level_-1_judge_agent.yaml
│ │ ├── level_0_tools.yaml
│ │ ├── level_1_agents.yaml
│ │ ├── level_2_agents.yaml
│ │ └── level_3_agents.yaml
│ └── run_env_config/
│ ├── ali_qwen_llm_config.yaml
│ ├── document_convert_api.yaml
│ ├── gemini_config_version.yaml
│ ├── kimi_config_version copy.yaml
│ ├── llm_config.example.yaml
│ └── third_part_api.yaml
├── core/
│ ├── __init__.py
│ ├── agent_event_emitter.py
│ ├── agent_executor.py
│ ├── context_builder.py
│ ├── event_handlers.py
│ ├── events.py
│ ├── hierarchy_manager.py
│ ├── runtime_exceptions.py
│ ├── state_cleaner.py
│ └── tool_executor.py
├── desktop_app/
│ ├── package.json
│ └── src/
│ ├── index.html
│ ├── main.js
│ ├── preload.js
│ ├── renderer.js
│ ├── styles.css
│ └── test_e.js
├── docker/
│ └── entrypoint.sh
├── docs/
│ ├── CHEAPCLAW_GUIDE.md
│ ├── CHEAPCLAW_IMPLEMENTATION_PLAN.md
│ ├── CLI_GUIDE.md
│ ├── DOCKER_GUIDE.md
│ ├── EVENT_SCHEMA.md
│ └── SDK_GUIDE.md
├── infiagent/
│ ├── __init__.py
│ └── sdk.py
├── marketplace_server/
│ ├── README.md
│ ├── app.py
│ ├── deploy_market.sh
│ ├── infiagent-market.service
│ ├── nginx_infiagent_market.conf
│ └── requirements.txt
├── pyproject.toml
├── requirements.txt
├── services/
│ ├── __init__.py
│ ├── action_compressor.py
│ ├── context_compressor_backup.py
│ ├── llm_client.py
│ └── thinking_agent.py
├── setup.py
├── skills/
│ ├── algorithmic-art/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── templates/
│ │ ├── generator_template.js
│ │ └── viewer.html
│ ├── brand-guidelines/
│ │ ├── LICENSE.txt
│ │ └── SKILL.md
│ ├── canvas-design/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── canvas-fonts/
│ │ ├── ArsenalSC-OFL.txt
│ │ ├── BigShoulders-OFL.txt
│ │ ├── Boldonse-OFL.txt
│ │ ├── BricolageGrotesque-OFL.txt
│ │ ├── CrimsonPro-OFL.txt
│ │ ├── DMMono-OFL.txt
│ │ ├── EricaOne-OFL.txt
│ │ ├── GeistMono-OFL.txt
│ │ ├── Gloock-OFL.txt
│ │ ├── IBMPlexMono-OFL.txt
│ │ ├── InstrumentSans-OFL.txt
│ │ ├── Italiana-OFL.txt
│ │ ├── JetBrainsMono-OFL.txt
│ │ ├── Jura-OFL.txt
│ │ ├── LibreBaskerville-OFL.txt
│ │ ├── Lora-OFL.txt
│ │ ├── NationalPark-OFL.txt
│ │ ├── NothingYouCouldDo-OFL.txt
│ │ ├── Outfit-OFL.txt
│ │ ├── PixelifySans-OFL.txt
│ │ ├── PoiretOne-OFL.txt
│ │ ├── RedHatMono-OFL.txt
│ │ ├── Silkscreen-OFL.txt
│ │ ├── SmoochSans-OFL.txt
│ │ ├── Tektur-OFL.txt
│ │ ├── WorkSans-OFL.txt
│ │ └── YoungSerif-OFL.txt
│ ├── doc-coauthoring/
│ │ └── SKILL.md
│ ├── docx/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── scripts/
│ │ ├── __init__.py
│ │ ├── accept_changes.py
│ │ ├── comment.py
│ │ ├── office/
│ │ │ ├── helpers/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── merge_runs.py
│ │ │ │ └── simplify_redlines.py
│ │ │ ├── pack.py
│ │ │ ├── schemas/
│ │ │ │ ├── ISO-IEC29500-4_2016/
│ │ │ │ │ ├── dml-chart.xsd
│ │ │ │ │ ├── dml-chartDrawing.xsd
│ │ │ │ │ ├── dml-diagram.xsd
│ │ │ │ │ ├── dml-lockedCanvas.xsd
│ │ │ │ │ ├── dml-main.xsd
│ │ │ │ │ ├── dml-picture.xsd
│ │ │ │ │ ├── dml-spreadsheetDrawing.xsd
│ │ │ │ │ ├── dml-wordprocessingDrawing.xsd
│ │ │ │ │ ├── pml.xsd
│ │ │ │ │ ├── shared-additionalCharacteristics.xsd
│ │ │ │ │ ├── shared-bibliography.xsd
│ │ │ │ │ ├── shared-commonSimpleTypes.xsd
│ │ │ │ │ ├── shared-customXmlDataProperties.xsd
│ │ │ │ │ ├── shared-customXmlSchemaProperties.xsd
│ │ │ │ │ ├── shared-documentPropertiesCustom.xsd
│ │ │ │ │ ├── shared-documentPropertiesExtended.xsd
│ │ │ │ │ ├── shared-documentPropertiesVariantTypes.xsd
│ │ │ │ │ ├── shared-math.xsd
│ │ │ │ │ ├── shared-relationshipReference.xsd
│ │ │ │ │ ├── sml.xsd
│ │ │ │ │ ├── vml-main.xsd
│ │ │ │ │ ├── vml-officeDrawing.xsd
│ │ │ │ │ ├── vml-presentationDrawing.xsd
│ │ │ │ │ ├── vml-spreadsheetDrawing.xsd
│ │ │ │ │ ├── vml-wordprocessingDrawing.xsd
│ │ │ │ │ ├── wml.xsd
│ │ │ │ │ └── xml.xsd
│ │ │ │ ├── ecma/
│ │ │ │ │ └── fouth-edition/
│ │ │ │ │ ├── opc-contentTypes.xsd
│ │ │ │ │ ├── opc-coreProperties.xsd
│ │ │ │ │ ├── opc-digSig.xsd
│ │ │ │ │ └── opc-relationships.xsd
│ │ │ │ ├── mce/
│ │ │ │ │ └── mc.xsd
│ │ │ │ └── microsoft/
│ │ │ │ ├── wml-2010.xsd
│ │ │ │ ├── wml-2012.xsd
│ │ │ │ ├── wml-2018.xsd
│ │ │ │ ├── wml-cex-2018.xsd
│ │ │ │ ├── wml-cid-2016.xsd
│ │ │ │ ├── wml-sdtdatahash-2020.xsd
│ │ │ │ └── wml-symex-2015.xsd
│ │ │ ├── soffice.py
│ │ │ ├── unpack.py
│ │ │ ├── validate.py
│ │ │ └── validators/
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── docx.py
│ │ │ ├── pptx.py
│ │ │ └── redlining.py
│ │ └── templates/
│ │ ├── comments.xml
│ │ ├── commentsExtended.xml
│ │ ├── commentsExtensible.xml
│ │ ├── commentsIds.xml
│ │ └── people.xml
│ ├── frontend-design/
│ │ ├── LICENSE.txt
│ │ └── SKILL.md
│ ├── internal-comms/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── examples/
│ │ ├── 3p-updates.md
│ │ ├── company-newsletter.md
│ │ ├── faq-answers.md
│ │ └── general-comms.md
│ ├── mac-use/
│ │ ├── SKILL.md
│ │ ├── requirements.txt
│ │ └── scripts/
│ │ └── mac_use.py
│ ├── mcp-builder/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ ├── reference/
│ │ │ ├── evaluation.md
│ │ │ ├── mcp_best_practices.md
│ │ │ ├── node_mcp_server.md
│ │ │ └── python_mcp_server.md
│ │ └── scripts/
│ │ ├── connections.py
│ │ ├── evaluation.py
│ │ ├── example_evaluation.xml
│ │ └── requirements.txt
│ ├── pdf/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ ├── forms.md
│ │ ├── reference.md
│ │ └── scripts/
│ │ ├── check_bounding_boxes.py
│ │ ├── check_fillable_fields.py
│ │ ├── convert_pdf_to_images.py
│ │ ├── create_validation_image.py
│ │ ├── extract_form_field_info.py
│ │ ├── extract_form_structure.py
│ │ ├── fill_fillable_fields.py
│ │ └── fill_pdf_form_with_annotations.py
│ ├── pptx/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ ├── editing.md
│ │ ├── pptxgenjs.md
│ │ └── scripts/
│ │ ├── __init__.py
│ │ ├── add_slide.py
│ │ ├── clean.py
│ │ ├── office/
│ │ │ ├── helpers/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── merge_runs.py
│ │ │ │ └── simplify_redlines.py
│ │ │ ├── pack.py
│ │ │ ├── schemas/
│ │ │ │ ├── ISO-IEC29500-4_2016/
│ │ │ │ │ ├── dml-chart.xsd
│ │ │ │ │ ├── dml-chartDrawing.xsd
│ │ │ │ │ ├── dml-diagram.xsd
│ │ │ │ │ ├── dml-lockedCanvas.xsd
│ │ │ │ │ ├── dml-main.xsd
│ │ │ │ │ ├── dml-picture.xsd
│ │ │ │ │ ├── dml-spreadsheetDrawing.xsd
│ │ │ │ │ ├── dml-wordprocessingDrawing.xsd
│ │ │ │ │ ├── pml.xsd
│ │ │ │ │ ├── shared-additionalCharacteristics.xsd
│ │ │ │ │ ├── shared-bibliography.xsd
│ │ │ │ │ ├── shared-commonSimpleTypes.xsd
│ │ │ │ │ ├── shared-customXmlDataProperties.xsd
│ │ │ │ │ ├── shared-customXmlSchemaProperties.xsd
│ │ │ │ │ ├── shared-documentPropertiesCustom.xsd
│ │ │ │ │ ├── shared-documentPropertiesExtended.xsd
│ │ │ │ │ ├── shared-documentPropertiesVariantTypes.xsd
│ │ │ │ │ ├── shared-math.xsd
│ │ │ │ │ ├── shared-relationshipReference.xsd
│ │ │ │ │ ├── sml.xsd
│ │ │ │ │ ├── vml-main.xsd
│ │ │ │ │ ├── vml-officeDrawing.xsd
│ │ │ │ │ ├── vml-presentationDrawing.xsd
│ │ │ │ │ ├── vml-spreadsheetDrawing.xsd
│ │ │ │ │ ├── vml-wordprocessingDrawing.xsd
│ │ │ │ │ ├── wml.xsd
│ │ │ │ │ └── xml.xsd
│ │ │ │ ├── ecma/
│ │ │ │ │ └── fouth-edition/
│ │ │ │ │ ├── opc-contentTypes.xsd
│ │ │ │ │ ├── opc-coreProperties.xsd
│ │ │ │ │ ├── opc-digSig.xsd
│ │ │ │ │ └── opc-relationships.xsd
│ │ │ │ ├── mce/
│ │ │ │ │ └── mc.xsd
│ │ │ │ └── microsoft/
│ │ │ │ ├── wml-2010.xsd
│ │ │ │ ├── wml-2012.xsd
│ │ │ │ ├── wml-2018.xsd
│ │ │ │ ├── wml-cex-2018.xsd
│ │ │ │ ├── wml-cid-2016.xsd
│ │ │ │ ├── wml-sdtdatahash-2020.xsd
│ │ │ │ └── wml-symex-2015.xsd
│ │ │ ├── soffice.py
│ │ │ ├── unpack.py
│ │ │ ├── validate.py
│ │ │ └── validators/
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── docx.py
│ │ │ ├── pptx.py
│ │ │ └── redlining.py
│ │ └── thumbnail.py
│ ├── slack-gif-creator/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ ├── core/
│ │ │ ├── easing.py
│ │ │ ├── frame_composer.py
│ │ │ ├── gif_builder.py
│ │ │ └── validators.py
│ │ └── requirements.txt
│ ├── theme-factory/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── themes/
│ │ ├── arctic-frost.md
│ │ ├── botanical-garden.md
│ │ ├── desert-rose.md
│ │ ├── forest-canopy.md
│ │ ├── golden-hour.md
│ │ ├── midnight-galaxy.md
│ │ ├── modern-minimalist.md
│ │ ├── ocean-depths.md
│ │ ├── sunset-boulevard.md
│ │ └── tech-innovation.md
│ ├── web-artifacts-builder/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── scripts/
│ │ ├── bundle-artifact.sh
│ │ └── init-artifact.sh
│ ├── webapp-testing/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ ├── examples/
│ │ │ ├── console_logging.py
│ │ │ ├── element_discovery.py
│ │ │ └── static_html_automation.py
│ │ └── scripts/
│ │ └── with_server.py
│ └── xlsx/
│ ├── LICENSE.txt
│ ├── SKILL.md
│ └── scripts/
│ ├── office/
│ │ ├── helpers/
│ │ │ ├── __init__.py
│ │ │ ├── merge_runs.py
│ │ │ └── simplify_redlines.py
│ │ ├── pack.py
│ │ ├── schemas/
│ │ │ ├── ISO-IEC29500-4_2016/
│ │ │ │ ├── dml-chart.xsd
│ │ │ │ ├── dml-chartDrawing.xsd
│ │ │ │ ├── dml-diagram.xsd
│ │ │ │ ├── dml-lockedCanvas.xsd
│ │ │ │ ├── dml-main.xsd
│ │ │ │ ├── dml-picture.xsd
│ │ │ │ ├── dml-spreadsheetDrawing.xsd
│ │ │ │ ├── dml-wordprocessingDrawing.xsd
│ │ │ │ ├── pml.xsd
│ │ │ │ ├── shared-additionalCharacteristics.xsd
│ │ │ │ ├── shared-bibliography.xsd
│ │ │ │ ├── shared-commonSimpleTypes.xsd
│ │ │ │ ├── shared-customXmlDataProperties.xsd
│ │ │ │ ├── shared-customXmlSchemaProperties.xsd
│ │ │ │ ├── shared-documentPropertiesCustom.xsd
│ │ │ │ ├── shared-documentPropertiesExtended.xsd
│ │ │ │ ├── shared-documentPropertiesVariantTypes.xsd
│ │ │ │ ├── shared-math.xsd
│ │ │ │ ├── shared-relationshipReference.xsd
│ │ │ │ ├── sml.xsd
│ │ │ │ ├── vml-main.xsd
│ │ │ │ ├── vml-officeDrawing.xsd
│ │ │ │ ├── vml-presentationDrawing.xsd
│ │ │ │ ├── vml-spreadsheetDrawing.xsd
│ │ │ │ ├── vml-wordprocessingDrawing.xsd
│ │ │ │ ├── wml.xsd
│ │ │ │ └── xml.xsd
│ │ │ ├── ecma/
│ │ │ │ └── fouth-edition/
│ │ │ │ ├── opc-contentTypes.xsd
│ │ │ │ ├── opc-coreProperties.xsd
│ │ │ │ ├── opc-digSig.xsd
│ │ │ │ └── opc-relationships.xsd
│ │ │ ├── mce/
│ │ │ │ └── mc.xsd
│ │ │ └── microsoft/
│ │ │ ├── wml-2010.xsd
│ │ │ ├── wml-2012.xsd
│ │ │ ├── wml-2018.xsd
│ │ │ ├── wml-cex-2018.xsd
│ │ │ ├── wml-cid-2016.xsd
│ │ │ ├── wml-sdtdatahash-2020.xsd
│ │ │ └── wml-symex-2015.xsd
│ │ ├── soffice.py
│ │ ├── unpack.py
│ │ ├── validate.py
│ │ └── validators/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── docx.py
│ │ ├── pptx.py
│ │ └── redlining.py
│ └── recalc.py
├── start.py
├── tests/
│ ├── image_read.py
│ ├── llm_config_dummy.yaml
│ ├── test_cheapclaw_service.py
│ ├── test_code_tools_system_terminal.py
│ ├── test_context_hooks.py
│ ├── test_file_tools.py
│ ├── test_image_read_message.py
│ ├── test_kimi_stream_compat.py
│ ├── test_llm_client_lite_openrouter.py
│ ├── test_llm_client_resilience.py
│ ├── test_llm_config_builder.py
│ ├── test_llm_debug_output.py
│ ├── test_reasoning_modes.py
│ ├── test_sdk_observability.py
│ ├── test_sdk_runtime_paths.py
│ ├── test_task_history_index.py
│ ├── test_thinking_prompt_contract.py
│ ├── test_tool_hooks.py
│ └── test_web_ui_config_api.py
├── tool_server_lite/
│ ├── __init__.py
│ ├── llm_client_lite.py
│ ├── registry.py
│ ├── requirements.txt
│ └── tools/
│ ├── BROWSER_IMPROVEMENTS.md
│ ├── FILE_READ_USAGE.md
│ ├── __init__.py
│ ├── arxiv_tools.py
│ ├── audio_tools.py
│ ├── browser_tools.py
│ ├── code_tools.py
│ ├── convert_tools.py
│ ├── document_tools.py
│ ├── file_tools.py
│ ├── human_tools.py
│ ├── paper_tools.py
│ ├── powerpoint_tools.py
│ ├── reference_tools.py
│ ├── skill_tools.py
│ ├── task_tools.py
│ ├── vision_tools.py
│ └── web_tools.py
├── utils/
│ ├── __init__.py
│ ├── cli_mode.py
│ ├── config_loader.py
│ ├── config_manager.py
│ ├── context_hooks.py
│ ├── conversation_storage.py
│ ├── event_emitter.py
│ ├── llm_config_builder.py
│ ├── mcp_manager.py
│ ├── runtime_control.py
│ ├── skill_loader.py
│ ├── task_history_index.py
│ ├── task_runtime.py
│ ├── tool_hooks.py
│ ├── user_paths.py
│ └── windows_compat.py
└── web_ui/
├── README.md
├── index.html
├── login.html
├── requirements.txt
├── server/
│ ├── output_capture.py
│ ├── sdk_worker.py
│ ├── server
│ ├── server.py
│ ├── songmiao/
│ │ ├── test/
│ │ │ └── chat_history.json
│ │ └── test1/
│ │ ├── chat_history.json
│ │ └── reference.bib
│ ├── start.sh
│ ├── stop.sh
│ ├── user_accounts.py
│ ├── user_runtime.py
│ └── users.yaml
├── static/
│ ├── app.js
│ └── style.css
├── web_intro.md
└── web_intro_CN.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .dockerignore
================================================
.git
.gitignore
.DS_Store
.pytest_cache
__pycache__
*.pyc
*.pyo
*.pyd
# Local build outputs
build
dist
*.egg-info
desktop_app/dist
desktop_app/backend_dist
desktop_app/node_modules
backend_build/.pyi_work
backend_build/.venv_arm64
backend_build/.venv_x64
backend_build/.venv*
# Desktop-only sources and caches
desktop_app
backend_build
# Tests, docs, local tools, and misc repo-only files
tests
docs
assets
apps
marketplace_server
web_ui/server/user_data
web_ui/server/__pycache__
conversations
logs
results
tmp
Test
# Local runtime/config state
config/run_env_config/llm_config.yaml
================================================
FILE: .gitignore
================================================
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Virtual Environment
venv/
env/
ENV/
# IDEs
.vscode/
.idea/
.cursor/
*.swp
*.swo
*~
# Logs
*.log
logs/
# OS
.DS_Store
Thumbs.db
# Project specific
# conversations/
config/run_env_config/llm_config.yaml
.env
# Desktop app
desktop_app/node_modules/
desktop_app/dist/
desktop_app/out/
desktop_app/backend_dist/
# Packaging/build artifacts
backend_build/.pyi_work/
backend_build/.venv_arm64/
backend_build/.venv_x64/
backend_build/__pycache__/
# Local test/debug artifacts
model_tool_calling_test_results.json
tests/debug_messages.json
tests/*.png
Test/
tmp/
web_ui/server/user_data/
# Large demo media are kept outside git to avoid bloating repository history
assets/*.mp4
assets/paper_generation_demo_*.gif
web_ui/*.mp4
# Docker related
docker-compose.yml
*.tar.gz
mla-docker-build.tar.gz
test_doc/
# workspace
workspace
workspace/*
================================================
FILE: Dockerfile
================================================
FROM python:3.12-slim-bookworm
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG ALL_PROXY
ARG http_proxy
ARG https_proxy
ARG all_proxy
ENV PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1 \
PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8
WORKDIR /app
RUN HTTP_PROXY="${HTTP_PROXY}" HTTPS_PROXY="${HTTPS_PROXY}" ALL_PROXY="${ALL_PROXY}" \
http_proxy="${http_proxy}" https_proxy="${https_proxy}" all_proxy="${all_proxy}" \
apt-get update && apt-get install -y --no-install-recommends \
bash \
ca-certificates \
curl \
git \
lsof \
procps \
tini \
&& rm -rf /var/lib/apt/lists/*
COPY MANIFEST.in pyproject.toml requirements.txt setup.py README.md start.py /app/
COPY config /app/config
COPY core /app/core
COPY infiagent /app/infiagent
COPY services /app/services
COPY skills /app/skills
COPY tool_server_lite /app/tool_server_lite
COPY utils /app/utils
COPY web_ui /app/web_ui
COPY docker /app/docker
RUN HTTP_PROXY="${HTTP_PROXY}" HTTPS_PROXY="${HTTPS_PROXY}" ALL_PROXY="${ALL_PROXY}" \
http_proxy="${http_proxy}" https_proxy="${https_proxy}" all_proxy="${all_proxy}" \
python -m pip install --upgrade pip setuptools wheel \
&& python -m pip install . \
&& python -m pip install -r web_ui/requirements.txt \
&& python -m playwright install --with-deps chromium
RUN chmod +x /app/docker/entrypoint.sh
RUN mkdir -p /workspace /root/mla_v3
EXPOSE 4242
HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 \
CMD curl -f http://localhost:4242/health || exit 1
ENTRYPOINT ["/usr/bin/tini", "--", "/app/docker/entrypoint.sh"]
CMD ["webui"]
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
================================================
FILE: MANIFEST.in
================================================
include README.md
include LICENSE
include requirements.txt
recursive-include config *.yaml
recursive-include skills *
recursive-include tool_server_lite *.py *.md *.txt
exclude conversations/*
exclude task_*
exclude *.log
exclude .DS_Store
================================================
FILE: README.md
================================================
<div align="center">
<img src="assets/logo.png" alt="infiAgent Logo" width="200">
<h1>MLA V3 - Build Domain-Specific SOTA-Level AI Agents</h1>
<p>
<img src="https://img.shields.io/badge/version-3.2.1-blue.svg" alt="Version">
<img src="https://img.shields.io/badge/python-3.9+-green.svg" alt="Python">
<img src="https://img.shields.io/badge/license-GPL-blue.svg" alt="License: GPL">
</p>
<p>
<a href="README.md">English</a> | <a href="README_CN.md">简体中文</a>
</p>
</div>
---
## 🌟 Introduction
**infiAgent Also called MLA (Multi-Level Agent)** is an agent framework designed for **unlimited runtime** without tool calling chaos or system crashes caused by cumulative task resources and conversation history. With MLA, you can build powerful general-purpose and semi-specialized agents simply by writing configuration files.
### Key Features
- ✅ **Days-Long Complex Tasks**: Supports continuous execution over days without context accumulation or compression degradation. Any interruption (crash, network error, manual stop) can be fully recovered via Resume — true breakpoint continuation.
- ✅ **Agent Skills Standard**: Compatible with the [Agent Skills open standard](https://agentskills.io/). Drop skill folders into the skills library and agents will discover, load, and execute them on demand.
- ✅ **Flexible Agent Architecture**: Supports both **multi-level hierarchy** (tree-structured orchestration for complex domain tasks — e.g., the `Researcher` config enables long-running scientific research with paper generation) and **flat architecture** (single agent with one sub-agent + Skills for broad general-purpose tasks — e.g., the OpenCowork config).
- ✅ **Persistent Memory**: File-directory-based memory system. Launch agents in the same workspace directory and they remember all historical tasks across sessions — no external database required.
### Update & News🔥
If you pulled the image or code before the latest update date, please refer to the issues that have been fixed and, based on your needs, pull the image and code again.
- [2026/03/31] **Switchable Thinking / ReAct execution mode + task-history database retrieval:** Runtime now supports a switchable cadence model. You can keep the original ThinkingAgent-style “plan first, then execute N steps” workflow, or disable thinking and fall back to an explicit ReAct loop where reflection text is persisted directly inside the message history. Historical task records are also indexed into a local SQLite database, and agents now get a built-in `task_history_search` tool by default. The SDK can expose only the most recent N historical tasks into prompt context, and agents are explicitly instructed to retrieve older task history from the database when recent context is not enough.
- [2026/03/30] **SDK / mac / Web UI model configuration is now much easier for non-experts:** The SDK now accepts structured model profiles directly instead of forcing every integration to hand-write `llm_config.yaml`. The mac desktop app and Docker Web UI both now expose a source-based model editor: you configure the default `base_url` / `api_key` once, then add multiple shared or per-slot models, and each row can either reuse the default source or switch to a custom URL / key. Raw YAML / JSON remain available as advanced fallbacks, but most users no longer need to manually type prefixes or JSON model objects.
- [2026/03/23] **Docker Web UI now supports multi-user registration and account management:** The latest `chenglinhku/mlav3:latest` image runs the SDK-based Web UI directly with the new `webui` startup command on port `4242`. Users can register from the login page, and the bootstrap admin account can manage users inside the Web UI. Please follow the updated Docker command in Quick Start / `docs/DOCKER_GUIDE.md`: mount `~/.mla_v3` to `/root/mla_v3`, publish `4242`, and use `chenglinhku/mlav3:latest webui`. The old standalone config page flow on `9641` is no longer required.
- [2026/03/19] **CheapClaw released on top of the `infiagent` SDK:** CheapClaw now ships as an SDK-based application layer. It keeps most of OpenCowork's practical capabilities, including custom bots, multi-bot collaboration workflows, IM integrations, and Skills, while inheriting the full `infiagent` runtime model: a multi-agent system behind a single bot, low-cost long-horizon tasks, and task-scoped context isolation inside one bot. Different tasks under the same bot now keep isolated contexts, while messages routed to the same task continue in the same long-running context instead of sharing one bot-wide session. [Click here to view CheapClaw](https://github.com/polyuiislab/CheapClaw).
- [2026/03/19] **Finer-grained per-agent model configuration:** Each sub-agent can now configure `execution_model`, `thinking_model`, `compressor_model`, `image_generation_model`, and `read_figure_model` independently. This makes it possible, within a single agent loop, to split execution, thinking, compression, and multimodal/image understanding across different models, giving the application layer the finest-grained cost control. You can also configure model-level `tool_choice` options in `llm_config.example.yaml`. See the default `OpenCowork` Level 3 `alpha_agent` definition for a concrete example.
- [2026/03/08] **Desktop branch sync update:** The current desktop branch now includes packaged Python backend build scripts, the bundled `infiagent` Python SDK, configurable runtime cadence (`action_window_steps`, `thinking_interval`, scheduled/manual `fresh`), MCP runtime integration, per-task logs, desktop environment settings, and marketplace integration. The legacy standalone tool-server workflow has been replaced by in-process `direct-tools`, and the built-in research system is now named `Researcher`.
[Click here to download!](https://github.com/polyuiislab/infiAgent/releases/tag/v1.4.1).
- [2026/02/09] **Mac desktop version released!** [Click here to download!](https://github.com/polyuiislab/infiAgent/releases/tag/v1.4.1). Support download skills from offical market. It supports any API that is allowed to be called by tools, and runs fully locally with the support of the localization model.
<img width="1198" height="798" alt="image" src="https://github.com/user-attachments/assets/435c5bd9-ace1-46a8-9814-883d3ce507d4" />
- [2026/02/07] **Agent Skills Support!** InfiAgent now supports the [Agent Skills open standard](https://agentskills.io/). Skills are folders of instructions, scripts, and resources that agents can dynamically load to improve performance on specialized tasks. Docker users: place skill folders in `~/.mla_v3/skills_library/` (mounted to `/root/mla_v3/skills_library/` inside the container). Local developers: place them in `~/mla_v3/skills_library/`. Windows users: `%USERPROFILE%\mla_v3\skills_library\`. The agent will automatically discover available skills and deploy them to the workspace on demand via `load_skill` tool.
- [2026/02/07] **Multi-Provider Model Support!** You can now use models from different providers in the same configuration. Each model can optionally override `api_key` and `base_url` to use a different provider. Different sub-agents can use different models. See `llm_config.example.yaml` for configuration details.
- [2026/02/07] **Web UI Enhancements:** Added Resume button for recovering interrupted tasks (same as CLI `/resume`). Added Agent System selector to freely switch between `Researcher` (academic research) and Open Cowork systems. User inputs now automatically include timestamps (consistent with CLI behavior).
- [2026/02/07] **Multimodal Message Architecture:** Separated multimodal and text-only message logic. For multimodal models, images from `image_read` are embedded directly in the conversation context for native understanding. Text-only models retain the external vision tool approach. Configure via `multimodal` and `compressor_multimodal` in `llm_config.yaml`.
- [2026/01/17] We introduce a new configuration profile, Open Cowork, which delivers a computer-work assistant similar to Anthropic's Cowork. After entering a user-specified working directory, the assistant can perform a wide range of tasks, including but not limited to: organizing folders, creating PowerPoint presentations, processing and categorizing bills and invoices in multiple formats, conducting in-depth research, and writing project code. The system is built on the InfiAgent architecture, preserving its long-horizon execution capabilities and unbounded, file-system–level memory within the same workspace. Open Cowork supports CLI, Docker-based CLI, and Web UI modes. In Web UI, use the Agent System selector to switch between `Researcher` and OpenCowork. A demonstration video is available for more details.
**Open Cowork Demo Videos:**
[](https://www.youtube.com/watch?v=IuTVRPIIW-s)
[](https://www.youtube.com/watch?v=uuxAvCLIX9M)
- [2026/01/13] Supports breakpoint recovery for program errors (the original Ctrl+C resume function is retained). Please access the resume function using your CLI version and type /resume.
- [2026/01/08] Our Paper "[InfiAgent: An Infinite-Horizon Framework for General-Purpose Autonomous Agents](https://arxiv.org/abs/2601.03204)" released
- [2026/01/07] Web UI: This is a temporary fix for the "处理事件异常: 'int' object has no attribute 'get'". It will not affect subsequent agent output or operation, but the error will still be displayed. A full fix is pending.
- [2026/01/06] Web UI: add an entry-agent selector next to Task ID so you can choose the root agent for the conversation, with an agent list and a visual agent tree for the selected root.
- [2026/01/05] Resolves global freeze caused by prolonged unresponsiveness of the primary token. Please update code or pull latest docker image!
- [2026/01/04] Support different Language of Agent output base on user input.
- [2026/01/03] Optimize LiteLLM’s native retry mechanism by enhancing error-aware retry prompts to improve small-model call success rates; add connection timeout detection to reduce task interruption risks.
- [2026/01/02] Install and how use vedio please click <a href="https://www.bilibili.com/video/BV142vQB2EDu/?share_source=copy_web&vd_source=8f099df5d40b73e936381e57d7fc05aa
">infiagent:全自动写作工具</a>
- [2026/01/02] fix some bugs about reference manage, Please clone latest repo or pull latest docker image: chenglinhku/mlav3.
- [2026/01/01] support web_ui and qwen api. Also fix some problem when using third part oepnai format api. please using latest chenglinhku/mlav3 docker image and see the example configs.
- [2025/12/31] support gemini api key from google ai studio now. Please See the gemini config in dir.
Attention: Current coding task only support python project. Other language may supported later. In old version execute_command only support safe command like cd or grep,now it include every commands including rm. Please try to use it in docker mode if your task may edit system file.
## 🎬 Outputs
complete academic papers generated by MLA:
**Demo 1:**
<p align="center">
Demo animation removed from git to keep the repository lightweight.
</p>
**Demo 2:**
<p align="center">
<img src="assets/paper1.png" alt="Paper Generation Demo 2" width="800">
</p>
**Demo 3:**
<p align="center">
<img src="assets/paper2.png" alt="Paper Generation Demo 3" width="800">
</p>
MLA handles the entire research workflow - from literature search and experiment design to code execution, figure generation, and LaTeX paper writing. All automatically orchestrated through multi-level agents.
Large demo videos and GIFs are now distributed outside git history so clones stay smaller and faster.
---
## 📚 Table of Contents
- [See It In Action](#-see-it-in-action)
- [Quick Start](#-quick-start)
- [How It Works](#-how-it-works)
- [Interface Screenshots](#-interface-screenshots)
- [Configuration Guide](#-configuration-guide)
- [CLI Interface](#-cli-interface)
- [SDK Integration](#-sdk-integration)
- [Example Outputs](#-example-outputs)
---
## 🚀 Quick Start
### Vedio of Docker Mode:
<a href="https://www.bilibili.com/video/BV142vQB2EDu/?share_source=copy_web&vd_source=8f099df5d40b73e936381e57d7fc05aa
">infiagent:全自动写作工具</a>
### Option 1: Docker (Recommended - No Python Required)
**1. Install Docker**
- Mac/Windows: [Docker Desktop](https://www.docker.com/products/docker-desktop)
- Linux: `curl -fsSL https://get.docker.com | sh`
**2. Pull Image**
```bash
docker pull chenglinhku/mlav3:latest
```
**3. Choose Your Mode**
### Option A: Web UI Mode (Recommended)
The current Docker image starts the SDK-based Web UI directly. Use the Agent System selector to switch between `Researcher` and `OpenCowork`. The old standalone config page on `9641` is no longer required.
```bash
cd /your/workspace
mkdir -p ~/.mla_v3
docker run -d --name mla-webui \
-e HOST_PWD=$(pwd) \
-e PORT=4242 \
-v $(pwd):/workspace$(pwd) \
-v ~/.mla_v3:/root/mla_v3 \
-p 4242:4242 \
chenglinhku/mlav3:latest webui
```
Then open browser: `http://localhost:4242`
- On a fresh volume, the bootstrap admin account is `admin` / `admin123`
- You can also create a new user directly from the login page
- Click the `Config` button inside Web UI to edit `llm_config.yaml`, `app_config.json`, and agent configuration files
- View logs with `docker logs -f mla-webui`
If you want Docker runtime data to stay inside the project instead of `~/.mla_v3`, replace the runtime mount with:
```bash
mkdir -p .mla_v3_docker
# replace: -v ~/.mla_v3:/root/mla_v3
# with: -v $(pwd)/.mla_v3_docker:/root/mla_v3
```
<p align="center">
<img src="assets/web_ui.png" alt="Paper Generation Demo 2" width="800">
</p>
📖 **Web UI usage & UI details**: see [web_ui/README.md](web_ui/README.md).
### Option B: CLI Mode
```bash
cd /your/workspace
mkdir -p ~/.mla_v3
docker run -it --rm \
-e HOST_PWD=$(pwd) \
-v $(pwd):/workspace$(pwd) \
-v ~/.mla_v3:/root/mla_v3 \
chenglinhku/mlav3:latest cli
```
**Windows Users:**
Windows users can mount any working folder into `/workspace/<your_task_root>` and reuse the same `/root/mla_v3` runtime volume across runs.
```powershell
# CLI Mode (PowerShell)
docker run -it --rm `
-e HOST_PWD="/docker_web" `
-v "${PWD}:/workspace/docker_web" `
-v "${HOME}\.mla_v3:/root/mla_v3" `
chenglinhku/mlav3:latest cli
# Web UI Mode (PowerShell)
docker run -d --name mla-webui `
-e HOST_PWD="/docker_web" `
-e PORT=4242 `
-v "${PWD}:/workspace/docker_web" `
-v "${HOME}\.mla_v3:/root/mla_v3" `
-p 4242:4242 `
chenglinhku/mlav3:latest webui
# Then open browser: http://localhost:4242
# View logs: docker logs -f mla-webui
```
**4. Configure API Key**
Open browser: `http://localhost:4242`
<p align="center">
<img src="assets/config_web_screen_shot.png" alt="Configuration Web Interface" width="800">
</p>
Sign in, open the `Config` dialog, edit `llm_config.yaml`, fill in your API key, and save.
**🎉 Done!** Start using MLA CLI.
📖 **[Complete Docker Guide](docs/DOCKER_GUIDE.md)**
---
### Option 2: Local Installation (Python Required)
**1. Install the package**
```bash
# Python 3.9+ is supported. Use Python 3.10+ if you need MCP support through the packaged dependency set.
cd install_path
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
git clone https://github.com/ChenglinPoly/infiAgent.git
cd infiAgent
pip install -e .
```
**2. Install Playwright**
```bash
playwright install chromium
```
**3. Configure API Key**
```bash
mla-agent --config-set api_key "your-api-key"
```
**4. Start CLI**
```bash
cd /your/workspace
mla-agent --cli
```
📖 **[Complete CLI Guide](docs/CLI_GUIDE.md)**
---
## 🎯 How It Works
MLA's design philosophy is **"Provide short but high-value context for the next step."** To achieve this, the framework implements multiple innovations:
### 1. 🌲 Serial Multi-Agent System
MLA deploys agents in a **tree-structured hierarchy** (e.g., Grandparent → Parent → Child). This ensures:
- ✅ **Single-purpose agents**: Each agent has a focused role
- ✅ **Minimal tool sets**: Agents only access necessary tools
- ✅ **Task alignment**: Serial execution prevents parallel conflicts
- ✅ **Clear delegation**: Parent agents orchestrate child agents
**Example Hierarchy:**
```
alpha_agent (Level 3)
├── data_collection_agent (Level 2)
│ └── web_search_agent (Level 1)
├── coder_agent (Level 2)
└── material_to_document_agent (Level 2)
```
### 2. 🎯 Nested Attention Mechanism
Long documents (PDFs, novels, papers) are **never directly loaded into context**. Instead:
- ✅ Use `answer_from_pdf`, `answer_from_document` tools
- ✅ Query-driven content extraction
- ✅ Only relevant excerpts or summaries enter context
- ✅ **Application-layer attention allocation** through tools
**Traditional Approach:**
```
Load entire 50-page PDF → Agent processes everything → Token overflow
```
**MLA Approach:**
```
Agent asks: "What is the methodology?"
→ Tool extracts relevant sections (2 pages)
→ Returns concise answer → Minimal token usage
```
### 3. 📁 File-Centric Architecture
**"Files are everything."** All outputs and interactions are saved to the file system:
- ✅ Web scraping → Saves as Markdown files
- ✅ PDF parsing → Extracts to structured documents
- ✅ Sub-agent results → Stored as files
- ✅ **No immediate returns** cluttering context
**Benefits:**
- Clear audit trail
- Reusable artifacts
- Context-free state representation
### 4. ⚡ Ten-Step Strategy (No Context Compression)
A key insight: **The current file system state represents the effect of all historical actions.**
- ✅ A separate **thinking module** updates file space state every 30 steps
- ✅ Agents only retain **the last 10 actions** (since last state update)
- ✅ **No need for context compression**
- ✅ Historical actions are reflected in file system, not conversation history
**Traditional LLM Agents:**
```
Step 1: Create file A
Step 2: Edit file B
...
Step 100: Context overflow → Compression needed → Information loss
```
**MLA Approach:**
```
Steps 1-10: Actions recorded
Step 10: Thinking module updates "Current State: Files A, B, C exist with..."
Steps 11-20: Only these + Current State kept
→ No compression, no information loss
```
### 5. 🔧 Batch File Operations
Inspired by [Claude Code](https://www.anthropic.com/), MLA uses **list-based tool parameters** to save tokens:
- ✅ Read multiple files in one call
- ✅ Batch operations reduce cumulative overhead
- ✅ Significant token savings on repeated actions
**Example:**
```python
# Traditional: 3 separate calls
file_read(path="file1.txt")
file_read(path="file2.txt")
file_read(path="file3.txt")
# MLA: 1 batch call
file_read(paths=["file1.txt", "file2.txt", "file3.txt"])
```
### 6. 💾 Long-Term Memory with Task ID
- ✅ **Task ID = Workspace absolute path** (not user-configurable)
- ✅ Same task ID allows **unlimited conversation sessions**
- ✅ Agents remember all historical tasks in the workspace
- ✅ Persistent memory across interruptions and restarts
**Usage:**
```bash
# First session
mla-agent --task_id ~/research --user_input "Collect papers on Transformers"
# → Stores conversation in ~/mla_v3/conversations/{hash}_research_*
# Second session (days later)
mla-agent --task_id ~/research --user_input "Summarize the collected papers"
# → Agent remembers previous session and accesses collected files
```
### 7. 📊 Call Graph-Based Shared Context
The `hierarchy_manager` maintains a **dynamic call relationship graph**:
- ✅ Tracks parent-child agent relationships
- ✅ Injects call graph into shared context
- ✅ Prevents agents from overstepping boundaries
- ✅ Maintains task alignment across multi-agent system
**Call Graph Example:**
```json
{
"current_agent": "coder_agent",
"parent": "alpha_agent",
"siblings": ["data_collection_agent", "material_to_document_agent"],
"allowed_tools": ["python_run", "file_write", "file_read"]
}
```
This ensures `coder_agent` won't accidentally call `web_search` (not in its scope) or interfere with sibling agents.
---
## 📸 Interface Screenshots
### CLI Interface
MLA provides a rich interactive CLI with real-time task monitoring, HIL handling, and agent switching:
**System Selection:**
<p align="center">
<img src="assets/cli_choose_system.png" alt="CLI System Selection" width="800">
</p>
**Tool Mode Configuration:**
<p align="center">
<img src="assets/cli_choose_tool_mode.png" alt="CLI Tool Mode" width="800">
</p>
**Starting Tasks:**
<p align="center">
<img src="assets/cli_start_task.png" alt="CLI Task Execution" width="800">
</p>
*Interactive CLI with prompt_toolkit and rich terminal UI - featuring multi-turn conversations, automatic HIL detection, and tool execution confirmation.*
### VS Code Plugin
Build powerful IDE extensions using MLA's JSONL mode:
<p align="center">
<img src="assets/vscode_plugin.png" alt="VS Code Plugin Screenshot" width="800">
</p>
*VS Code extension powered by MLA - seamless integration with workspace context and real-time streaming output.*
---
## ⚙️ Configuration Guide
MLA uses YAML files for agent and tool configuration. Configuration files are located in:
```
config/
├── agent_library/
│ ├── Researcher/ # Research-oriented multi-level system
│ │ ├── general_prompts.yaml # Shared prompts
│ │ ├── level_-1_judge_agent.yaml # Judge agent
│ │ ├── level_0_tools.yaml # Tool definitions
│ │ ├── level_1_agents.yaml # Low-level agents
│ │ ├── level_2_agents.yaml # Mid-level agents
│ │ └── level_3_agents.yaml # Top-level agents
│ └── OpenCowork/ # General computer-work assistant
└── run_env_config/
├── llm_config.yaml # LLM settings
└── llm_config.example.yaml # Example template
```
### Key Configuration Files
#### 1. `llm_config.yaml` - LLM Configuration
```yaml
# Global defaults
api_key: "your-api-key"
base_url: "https://openrouter.ai/api/v1"
temperature: 0
max_tokens: 0
models:
- openai/google/gemini-3-flash-preview # uses global api_key + base_url
- name: openai/qwen-plus # override with different provider
api_key: "your-dashscope-key"
base_url: "https://dashscope.aliyuncs.com/compatible-mode/v1"
figure_models:
- openai/google/gemini-3-flash-preview
compressor_models:
- openai/google/gemini-3-flash-preview
thinking_models:
- openai/google/gemini-3-flash-preview
read_figure_models:
- openai/google/gemini-3-flash-preview
# Multimodal configuration
multimodal: true # Enable image embedding in messages for main model
compressor_multimodal: true # Enable image embedding for compressor model
```
**Note**: Copy `llm_config.example.yaml` to `llm_config.yaml` to get started. Each model can optionally override `api_key` and `base_url` to use a different provider.
#### 2. Agent Hierarchy
MLA organizes agents into levels:
- **Level 3**: Top-level orchestrators (e.g., `alpha_agent`)
- **Level 2**: Functional specialists (e.g., `data_collection_agent`, `coder_agent`)
- **Level 1**: Basic executors (e.g., `web_search_agent`)
- **Level 0**: Tool definitions
- **Level -1**: Quality control (e.g., `judge_agent`)
#### 3. Creating Custom Agents
Edit YAML files to customize agent behavior:
```yaml
news_agent:
type: llm_call_agent
level: 1
model_type: "advanced"
available_tools:
- data_collection_agent
- coder_agent
...
system_prompt: |
You are a newspaper agent.
```
---
## 💻 CLI Interface
### Interactive Mode
Start the CLI for a conversational experience:
```bash
mla-agent --cli
```
**Key Features:**
- 🔄 **Multi-turn conversations** with persistent context
- 🤖 **Agent switching** with `@agent_name` syntax
- 🔔 **Automatic HIL detection** with audio alerts
- ⚠️ **Tool execution confirmation** in manual mode
- ⏸️ **Interrupt and resume** support (Ctrl+C to pause)
- 🎨 **Rich terminal UI** powered by `prompt_toolkit` and `rich`
**Usage Examples:**
```bash
# Direct task input (uses default agent)
[alpha_agent] > Collect papers on Transformers
# Switch agent and execute task
[alpha_agent] > @data_collection_agent Search for recent NLP papers
# Switch default agent only
[alpha_agent] > @coder_agent
✅ Switched to: coder_agent
[coder_agent] >
```
**CLI Commands:**
| Command | Description |
|---------|-------------|
| `/help` | Show help and available commands |
| `/agents` | List all available agents |
| `/resume` | Resume interrupted tasks |
| `/quit` or `/exit` | Exit CLI mode |
| `Ctrl+C` | Interrupt current task (stays in CLI) |
| `Ctrl+D` | Exit CLI immediately |
**Human-in-Loop (HIL) Handling:**
When an agent requests human input, the CLI automatically detects it:
```
🔔🔔🔔 Detected HIL task! Press Enter to handle... 🔔🔔🔔
================================================================================
🔔 Human Interaction Task (HIL)
================================================================================
📝 Task ID: upload_file_20250124
📋 Instruction: Please upload the required dataset files...
================================================================================
💡 Enter your response (any text)
Type /skip to skip this task
================================================================================
[alpha_agent] HIL Response > Files uploaded successfully
✅ HIL task responded
```
**Tool Confirmation (Manual Mode):**
When `--auto-mode false` is set, each tool execution requires confirmation:
```
⚠️⚠️⚠️ Detected tool execution request! Press Enter to confirm... ⚠️⚠️⚠️
================================================================================
⚠️ Tool Execution Confirmation Request
================================================================================
🔧 Tool Name: python_run
📝 Confirmation ID: confirm_12345
📋 Parameters:
code: import numpy as np...
timeout: 300
================================================================================
💡 Choose action:
yes / y - Approve execution
no / n - Reject execution
================================================================================
[alpha_agent] Confirm [yes/no] > yes
✅ Approved tool execution: python_run
```
**Screenshot:** *(User will provide)*
---
### Command-Line Mode
For scripting and automation:
```bash
mla-agent \
--task_id /path/to/workspace \
--user_input "Your task description" \
--agent_name alpha_agent
```
**Common Parameters:**
| Parameter | Description | Default |
|-----------|-------------|---------|
| `--task_id` | Workspace path (absolute) | Required |
| `--user_input` | Task description | Required |
| `--agent_name` | Agent to invoke | `alpha_agent` |
| `--agent_system` | Agent library name | `Researcher` |
| `--cli` | Interactive CLI mode | `false` |
| `--jsonl` | JSONL output mode | `false` |
| `--force-new` | Clear all state and start fresh | `false` |
| `--auto-mode` | Tool execution mode (`true`/`false`) | Auto-detect |
**Auto-Mode Examples:**
```bash
# Automatic tool execution (no confirmation needed)
mla-agent --task_id ~/project --user_input "Task" --auto-mode true
# Manual confirmation for each tool
mla-agent --task_id ~/project --user_input "Task" --auto-mode false
```
---
### Runtime Tool Execution
```bash
# Tools are executed in-process through direct-tools.
# No standalone mla-tool-server process is required.
```
---
## 🔌 SDK Integration
MLA provides two SDK options: **Python SDK** for direct integration and **JSONL mode** for IDE plugins.
---
### Python SDK
Use the bundled `infiagent` SDK. The current SDK model is:
- instantiate `infiagent(...)` once to describe runtime defaults
- pass a concrete `task_id` to `run(...)` and other task APIs
- optionally point the whole runtime at a dedicated `user_data_root`
Minimal example:
```python
from infiagent import infiagent
agent = infiagent(
user_data_root="/abs/path/to/my_root",
default_agent_system="Researcher",
default_agent_name="alpha_agent",
action_window_steps=30,
thinking_interval=30,
max_turns=100000,
fresh_enabled=True,
fresh_interval_sec=300,
)
result = agent.run(
"Write a survey paper on Transformers",
task_id="/abs/path/to/tasks/transformer_survey",
)
print(f"Status: {result['status']}")
print(f"Output: {result['output']}")
```
If your `user_data_root` already contains:
- `config/llm_config.yaml`
- `config/app_config.json`
- `agent_library/...`
- `tools_library/...`
you usually do not need to pass `llm_config_path`, `agent_library_dir`, or `tools_dir` again.
Common task APIs:
```python
# Ask a running or stopped task to refresh runtime config.
agent.fresh(
task_id="/abs/path/to/tasks/transformer_survey",
reason="reload runtime config",
)
# Append a new instruction to the same task.
agent.add_message(
"Keep the existing outline and only revise section 3.",
task_id="/abs/path/to/tasks/transformer_survey",
source="user",
resume_if_needed=True,
)
# Launch a separate background task in another Python process.
agent.start_background_task(
task_id="/abs/path/to/tasks/subtask_eval",
user_input="Run the evaluation pipeline and summarize results",
force_new=True,
)
# Inspect task state for dashboards or lightweight watchdogs.
snapshot = agent.task_snapshot(
task_id="/abs/path/to/tasks/transformer_survey",
)
# Reset a broken task loop while optionally preserving history.
agent.reset_task(
task_id="/abs/path/to/tasks/transformer_survey",
reason="clear broken loop",
preserve_history=True,
)
```
Runtime introspection:
```python
runtime = agent.describe_runtime()
print(runtime["user_data_root"])
print(runtime["agent_library_dir"])
print(runtime["tools_dir"])
systems = agent.list_agent_systems()
print(systems["systems"])
```
Advanced runtime features supported by the SDK:
- task-scoped background execution and resume/fresh control
- `user_data_root`-scoped conversations, logs, runtime state, and config
- tool hooks before/after tool execution
- context hooks that can inspect or rewrite the final prompt before the LLM call
- per-instance MCP server injection through `mcp_servers=[...]`
See the full guide: [docs/SDK_GUIDE.md](/Users/chenglin/Desktop/research/agent_framwork/vscode_version/MLA_V3/docs/SDK_GUIDE.md)
**Use Cases for Python SDK:**
- 🔧 Building custom workflows
- 🤖 Embedding agents in existing applications
- 📊 Batch processing multiple tasks
- 🧭 Building external dashboards, watchdogs, and orchestration layers
- 🔬 Research experiments with programmatic control
---
### JSONL Mode for IDE Plugins
MLA provides a JSONL streaming mode for real-time integration with IDEs and editors:
```bash
mla-agent \
--task_id $(pwd) \
--user_input "Optimize code performance" \
--jsonl 2>/dev/null
```
**Output Format:**
```jsonl
{"type":"start","call_id":"c-1760936557-474c43","project":"~/project","agent":"alpha_agent","task":"Optimize..."}
{"type":"token","text":"[alpha_agent] Analyzing code..."}
{"type":"progress","phase":"execution","pct":30}
{"type":"token","text":"Calling tool: code_analyzer"}
{"type":"result","ok":true,"summary":"Optimization complete"}
{"type":"end","status":"ok","duration_ms":5432}
```
**Event Types:**
| Event Type | Description | Key Fields |
|------------|-------------|------------|
| `start` | Task begins | `call_id`, `agent`, `task` |
| `token` | Streaming text output | `text` |
| `progress` | Progress update | `phase`, `pct` |
| `result` | Task result | `ok`, `summary` |
| `end` | Task completed | `status`, `duration_ms` |
| `error` | Error occurred | `message` |
---
### TypeScript/JavaScript Integration
```typescript
import { spawn } from 'child_process';
interface AgentEvent {
type: 'start' | 'token' | 'progress' | 'result' | 'end' | 'error';
[key: string]: any;
}
function runAgent(
workspacePath: string,
userInput: string,
onEvent: (event: AgentEvent) => void
): Promise<AgentEvent> {
return new Promise((resolve, reject) => {
const child = spawn('mla-agent', [
'--task_id', workspacePath,
'--user_input', userInput,
'--jsonl'
]);
let buffer = '';
child.stdout.on('data', (data) => {
buffer += data.toString();
const lines = buffer.split('\n');
buffer = lines.pop() || '';
lines.forEach(line => {
if (!line.trim()) return;
try {
const event: AgentEvent = JSON.parse(line);
onEvent(event);
if (event.type === 'end') {
resolve(event);
} else if (event.type === 'error') {
reject(new Error(event.message));
}
} catch (e) {
console.error('Failed to parse event:', line);
}
});
});
child.stderr.on('data', (data) => {
// Log errors to stderr
console.error(data.toString());
});
child.on('error', reject);
});
}
// Usage
await runAgent('/path/to/workspace', 'Write unit tests', (event) => {
switch (event.type) {
case 'start':
console.log(`Task started: ${event.task}`);
break;
case 'token':
process.stdout.write(event.text);
break;
case 'progress':
updateProgressBar(event.pct);
break;
case 'result':
console.log(`\nResult: ${event.summary}`);
break;
}
});
```
---
### VS Code Extension Example
Build your own Cursor/VS Code extension using MLA:
**Extension Features:**
- 🤖 Agent commands in command palette
- 💬 Inline chat with workspace context
- 📝 Automatic code generation and refactoring
- 🔍 Literature search within editor
- 🔔 HIL task handling with UI prompts
**Basic Extension Structure:**
```typescript
// extension.ts
import * as vscode from 'vscode';
import { runAgent } from './mla-client';
export function activate(context: vscode.ExtensionContext) {
let disposable = vscode.commands.registerCommand(
'mla.executeTask',
async () => {
const workspace = vscode.workspace.workspaceFolders?.[0].uri.fsPath;
const input = await vscode.window.showInputBox({
prompt: 'Enter task description'
});
if (!workspace || !input) return;
// Show progress
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: 'MLA Agent',
cancellable: true
}, async (progress, token) => {
await runAgent(workspace, input, (event) => {
if (event.type === 'token') {
vscode.window.showInformationMessage(event.text);
} else if (event.type === 'progress') {
progress.report({ increment: event.pct });
}
});
});
}
);
context.subscriptions.push(disposable);
}
```
**Screenshot:** *(User will provide)*
---
## 📊 Example Outputs
### Academic Paper Output
MLA can generate complete research papers with the following structure:
```
upload/
├── paper.tex # Main LaTeX document
├── references.bib # Bibliography
├── figures/
│ ├── architecture.png
│ ├── results_comparison.png
│ └── ablation_study.png
└── supplementary/
└── detailed_results.pdf
```
**Quality Metrics:**
- ✅ Passes peer review at EI/IEEE conferences
- ✅ Proper citation formatting
- ✅ High-quality figures (300 DPI)
- ✅ Coherent structure and flow
### Other Capabilities
**1. Scientific Computing**
- ECM protein composition simulation
- Logistics company shift scheduling
- Student assignment grading with feedback
**2. General Tasks**
- Web scraping and data extraction
- Code generation and debugging
- Document conversion and processing
---
## 📖 Documentation
- Runtime tools are executed in-process via direct-tools; no standalone tool server is required.
- [Human-in-the-Loop API](tool_server_lite/HIL_API.md) - User interaction integration
- [Configuration Examples](config/agent_library/Researcher/) - Agent YAML templates
---
## 🤝 Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
---
## 📄 License
see [LICENSE](LICENSE) for details.
---
## 📄 Citation
If you use InfiAgent in your research, please cite our paper:
```bibtex
@article{yu2026infiagent,
title={InfiAgent: An Infinite-Horizon Framework for General-Purpose Autonomous Agents},
author={Yu, Chenglin and Wang, Yuchen and Wang, Songmiao and Yang, Hongxia and Li, Ming},
journal={arXiv preprint arXiv:2601.03204},
year={2026}
}
```
---
## 🙏 Acknowledgments
- Built with [LiteLLM](https://github.com/BerriAI/litellm) for unified LLM access
- Uses [Crawl4AI](https://github.com/unclecode/crawl4ai) for web scraping
---
## 📬 Contact
**Author**: @yuchenglin
**Thanks to Contributors**: @wangyuchen @wangsongmiao @yuyang @lijinjia
**Email**: yuchenglin96@qq.com/cl0415@connect.hku.hk/chenglin.yu@poly.edu.h
**GitHub**: [MLA V3 Repository](https://github.com/ChenglinPoly/infiAgent)
---
================================================
FILE: README_CN.md
================================================
<div align="center">
<img src="assets/logo.png" alt="infiAgent Logo" width="200">
<h1>MLA V3 - 打造专属领域的 SOTA 级智能体</h1>
<p>
<img src="https://img.shields.io/badge/version-3.2.1-blue.svg" alt="Version">
<img src="https://img.shields.io/badge/python-3.9+-green.svg" alt="Python">
<img src="https://img.shields.io/badge/license-GPL-blue.svg" alt="License: GPL">
</p>
<p>
<a href="README.md">English</a> | <a href="README_CN.md">简体中文</a>
</p>
</div>
---
## 🌟 简介
**infiAgent 也称为 MLA (Multi-Level Agent,多层级智能体)** 是一个专为**无限时长运行**设计的智能体框架,不会因为任务资源累积和对话历史增长而导致工具调用混乱或系统崩溃。使用 MLA,你只需编写配置文件即可构建强大的通用或半专业化智能体。
### 核心特性
- ✅ **支持数以天计的持续复杂任务**:无需担心上下文累积或持续压缩导致的性能下降。任何中断(崩溃、网络异常、手动停止)都可通过 Resume 完全恢复,实现真正的断点续跑。
- ✅ **支持 Agent Skills 标准**:兼容 [Agent Skills 开放标准](https://agentskills.io/)。将 skill 文件夹放入技能库,智能体即可自动发现、加载并按需执行。
- ✅ **灵活的智能体架构**:同时支持**多层级架构**(树形编排,适合垂类复杂任务——如 `Researcher` 配置可长时间进行科学研究并生成论文)和**扁平架构**(单层智能体 + Skills,适合广泛通用任务——如 OpenCowork 配置)。
- ✅ **持续记忆**:基于文件目录位置的记忆系统。在同一工作目录下启动智能体,即可记忆该目录下所有历史任务的对话和产出,无需外部数据库。
### 更新 & 新闻🔥
如果你在最新更新日期前拉取镜像或者代码,请参考修复的问题,重新拉取镜像和代码。
- [2026/03/31] **Thinking / ReAct 模式可切换,并引入历史任务数据库检索:** 运行时现在支持两种节奏。你既可以保留原来的 ThinkingAgent 式“先思考,再执行 N 步”的长程模式,也可以关闭 thinking,切换到显式 ReAct 模式,让反思文本直接进入消息历史。与此同时,历史任务会被索引进本地 SQLite 数据库,所有 agent 默认都会挂载 `task_history_search` 工具。SDK 还支持只把最近 N 条历史任务注入 prompt;如果这些最近历史不足以完成当前任务,agent 会被明确提示去历史任务数据库里检索旧任务。
- [2026/03/30] **SDK / mac / Web UI 模型配置对小白更友好:** SDK 现在支持直接传结构化模型配置,不再要求每个集成都手写 `llm_config.yaml`。mac 客户端和 Docker Web UI 现在都提供了基于 source 的模型编辑器:先配置默认 `base_url` / `api_key`,再按共享模型或各功能分区添加多个模型条目;每个条目都可以继续复用默认 source,也可以切到自定义 URL / Key。Raw YAML / JSON 仍然保留给高级用户,但普通用户已经不需要再手动写前缀或 JSON 模型对象。
- [2026/03/23] **Docker Web UI 现已支持多用户注册与用户管理:** 最新 `chenglinhku/mlav3:latest` 镜像会通过新的 `webui` 启动命令直接运行基于 SDK 的 Web UI,默认使用 `4242` 端口。用户可以在登录页自行注册,初始管理员账号可在 Web UI 内管理用户。请按 Quick Start 和 `docs/DOCKER_GUIDE.md` 中更新后的 Docker 命令启动:挂载 `~/.mla_v3` 到 `/root/mla_v3`,映射 `4242`,并使用 `chenglinhku/mlav3:latest webui`。旧版基于 `9641` 的独立配置页面流程已不再需要。
- [2026/03/19] **基于 `infiagent` SDK 推出 CheapClaw:** CheapClaw 现在作为基于 SDK 的应用层发布,在保留 OpenCowork 大部分实用能力的基础上,支持自定义 bot、多 bot 协作、对接各种 IM 软件以及 Skills,同时完整继承 `infiagent` 的能力模型:单个 bot 背后可挂多智能体系统、支持低成本长程任务,并在单个 bot 内实现按 task 隔离上下文。同一个 bot 下,不同 task 的历史上下文彼此隔离,而同一个 task 会持续复用同一份长程上下文,而不是共享单一 bot session。[点击这里查看 CheapClaw](https://github.com/polyuiislab/CheapClaw)。
- [2026/03/19] **子智能体模型配置更加细粒度:** 现在单个子智能体可以独立配置 `execution_model`、`thinking_model`、`compressor_model`、`image_generation_model` 和 `read_figure_model`,从而在单个 agent loop 中把执行、思考、压缩以及多模态/读图工作拆分给不同模型,在应用层层面上最细粒度地控制成本。与此同时,可以在 `llm_config.example.yaml` 中为每个模型配置 `tool_choice` 选项。可参考默认 `OpenCowork` 配置中 Level 3 的 `alpha_agent` 写法。
- [2026/03/08] **桌面端分支同步更新:** 当前 `desktop-app` 分支已经加入打包 Python 后端构建脚本、内置 `infiagent` Python SDK、可配置运行时节奏(`action_window_steps`、`thinking_interval`、定时/手动 `fresh`)、MCP 运行时接入、单任务日志、桌面端环境设置和 marketplace 集成。旧的独立 `tool-server` 工作流已被进程内 `direct-tools` 替代,内置科研系统名称也统一为 `Researcher`。
[点击此处跳转下载页面](https://github.com/polyuiislab/infiAgent/releases/tag/v1.4.1).
- [2026/02/09] **mac系统桌面端发布!** [点击此处跳转下载页面](https://github.com/polyuiislab/infiAgent/releases/tag/v1.4.1)。支持 skills的外部库导入,支持不同智能体共享记忆接力工作,支持本地模型完全本地化运行。
<img width="1198" height="798" alt="image" src="https://github.com/user-attachments/assets/bae36a54-7c70-4ba5-a2cf-3d53856ca461" />
- [2026/02/07] **支持 Agent Skills!** InfiAgent 现已支持 [Agent Skills 开放标准](https://agentskills.io/)。Skills 是包含指令、脚本和资源的文件夹,智能体可按需加载以增强专业任务能力。Docker 用户:将 skill 文件夹放入 `~/.mla_v3/skills_library/`(挂载到容器内 `/root/mla_v3/skills_library/`)。本地开发者:放入 `~/mla_v3/skills_library/`。Windows 用户:`%USERPROFILE%\mla_v3\skills_library\`。智能体会自动发现可用 skills 并通过 `load_skill` 工具按需部署到工作空间。
- [2026/02/07] **支持多供应商模型!** 同一配置文件中可以使用来自不同供应商的模型。每个模型可单独覆盖 `api_key` 和 `base_url`,允许不同子智能体使用不同模型。详见 `llm_config.example.yaml` 配置示例。
- [2026/02/07] **Web UI 增强:** 新增 Resume 按钮,支持恢复中断任务(与 CLI `/resume` 功能一致)。新增 Agent System 选择器,可自由切换 `Researcher`(学术研究智能体)和 Open Cowork 系统。用户输入自动添加时间戳(与 CLI 行为一致)。
- [2026/02/07] **多模态消息架构重构:** 分离多模态和纯文本模型的消息逻辑。多模态模型下,`image_read` 工具获取的图片直接嵌入对话上下文,实现原生图片理解。纯文本模型仍保留外部 Vision 工具的图片识别能力。通过 `llm_config.yaml` 中的 `multimodal` 和 `compressor_multimodal` 配置。
- [2026/01/17] 我们推出新的配置文件open cowork,得到类似anthropic 公司 cowork 工具的电脑工作助手。在进入你指定的文件夹后,实现包括但不限于帮你整理文件夹,制作 ppt,整理各种格式的账单发票,深度调研,编写项目代码等。仍然基于 infiagent 架构的长程性能,和相同文件夹下的无限记忆。支持 CLI、Docker CLI 和 Web UI 模式。在 Web UI 中可通过 Agent System 选择器切换 `Researcher` 和 OpenCowork。具体可查看演示视频。
**Open Cowork 演示视频:**
[](https://www.youtube.com/watch?v=IuTVRPIIW-s)
[](https://www.youtube.com/watch?v=uuxAvCLIX9M)
- [2026/01/13] cli模式下新增api欠费网络中断等意外情况的断点续跑功能。(原先手动中断/续跑功能保留)。统一/resume唤起。
- [2026/01/08] 我们的论文 "[InfiAgent: An Infinite-Horizon Framework for General-Purpose Autonomous Agents](https://arxiv.org/abs/2601.03204)" 发布
- [2026/01/07] Web UI: 临时修复“处理事件异常: 'int' object has no attribute 'get'”。不会影响后续 agent输出和工作,但仍然会显示报错,等待后续完全修复。
- [2026/01/06] Web UI:新增入口智能体选择功能,可在 Task ID 左侧选择作为对话入口的智能体,并在同一界面展示该智能体为根的 agent tree。
- [2026/01/05] 解决网络死锁问题(首token 卡死) !重要更新!建议更新最新镜像或者拉取代码!
- [2026/01/04] 支持智能体基于用户回复输出不同交互语言,
- [2026/01/03] 优化 litellm 原生重试机制,通过提醒调用错误增加小模型调用成功率;增加链接超时检测机制,减少任务中断可能性。
- [2026/01/02] 上传了视频教程,点击:<a href="https://www.bilibili.com/video/BV142vQB2EDu/?share_source=copy_web&vd_source=8f099df5d40b73e936381e57d7fc05aa
">infiagent:全自动写作工具</a>
- [2026/01/02] 修复了文献管理工具的部分 bug,请更新最新代码或者拉取最近镜像 chenglinhku/mlav3
- [2026/01/01] 现已支持web ui多用户模式。拉取最新镜像网chenglinhku/mlav3进行体验,webui目前属测试阶段存在不稳定因素,最新镜像同时接收cli模式,详见quickstart教程
- [2026/01/01] 现已支持阿里云api包括qwen,适配绝大部分第三方中转站。配置详情请卡config文件夹对应的参考文件。
- [2025/12/31] 现在已支持 gemini api。重新拉取仓库或重新拉取 docker 即可生效。配置文件参考配置文件夹 gemini 开头的样板格式。
注意目前只支持 python 编程,早期版本execute_command只支持只读命令,目前已经支持所有命令(包括删除等危险命令),推荐在 docker 环境下使用。
---
## 🎬 输出
MLA完成的完整论文
**Demo 1:**
<p align="center">
为了控制仓库体积,演示动图已不再放入 git 历史。
</p>
**Demo 2:**
<p align="center">
<img src="assets/paper1.png" alt="Paper Generation Demo 2" width="800">
</p>
**Demo 3:**
<p align="center">
<img src="assets/paper2.png" alt="Paper Generation Demo 3" width="800">
</p>
MLA 处理整个研究工作流程——从文献搜索和实验设计到代码执行、图表生成和 LaTeX 论文撰写。全部通过多层级智能体自动编排完成。
演示视频和大体积 GIF 现已移出 git 历史,以便更轻量地克隆仓库。
---
## 📚 目录
- [输出](#-输出)
- [快速开始](#-快速开始)
- [工作原理](#-工作原理)
- [界面截图](#-界面截图)
- [配置指南](#-配置指南)
- [CLI 界面](#-cli-界面)
- [SDK 集成](#-sdk-集成)
- [示例输出](#-示例输出)
---
## 🚀 快速开始
### dock版视频演示教程
<a href="https://www.bilibili.com/video/BV142vQB2EDu/?share_source=copy_web&vd_source=8f099df5d40b73e936381e57d7fc05aa
">infiagent:全自动写作工具</a>
### 方式 1: Docker(推荐 - 无需 Python)
**1. 安装 Docker**
- Mac/Windows: [Docker Desktop](https://www.docker.com/products/docker-desktop)
- Linux: `curl -fsSL https://get.docker.com | sh`
**2. 拉取镜像**
```bash
docker pull chenglinhku/mlav3:latest
```
**3. 选择模式**
### 方式 A: Web UI 模式(推荐)
当前 Docker 镜像会直接启动基于 SDK 的 Web UI。可通过 Agent System 选择器切换 `Researcher` 和 `OpenCowork`。旧版 `9641` 独立配置页面已不再需要。
```bash
cd /你的工作空间
mkdir -p ~/.mla_v3
docker run -d --name mla-webui \
-e HOST_PWD=$(pwd) \
-e PORT=4242 \
-v $(pwd):/workspace$(pwd) \
-v ~/.mla_v3:/root/mla_v3 \
-p 4242:4242 \
chenglinhku/mlav3:latest webui
```
然后打开浏览器:`http://localhost:4242`
- 首次使用空 volume 时,默认管理员账号为 `admin` / `admin123`
- 也可以直接在登录页注册新用户
- 登录后点击 Web UI 里的 `Config` 按钮即可编辑 `llm_config.yaml`、`app_config.json` 和 agent 配置
- 查看日志:`docker logs -f mla-webui`
如果你希望 Docker 运行数据放在当前项目目录,而不是 `~/.mla_v3`,可以把运行时挂载改成:
```bash
mkdir -p .mla_v3_docker
# 把: -v ~/.mla_v3:/root/mla_v3
# 改成: -v $(pwd)/.mla_v3_docker:/root/mla_v3
```
<p align="center">
<img src="assets/web_ui.png" alt="Paper Generation Demo 2" width="800">
</p>
📖 **Web UI 使用与界面说明**:详见 [web_ui/README.md](web_ui/README.md)。
### 方式 B: CLI 模式
```bash
cd /你的工作空间
mkdir -p ~/.mla_v3
docker run -it --rm \
-e HOST_PWD=$(pwd) \
-v $(pwd):/workspace$(pwd) \
-v ~/.mla_v3:/root/mla_v3 \
chenglinhku/mlav3:latest cli
```
**Windows 用户:**
Windows 用户可以把任意工作目录挂到 `/workspace/<你的任务根目录>`,并持续复用同一个 `/root/mla_v3` 运行时目录。
如有 bug 欢迎提交 issue。
```powershell
# CLI 模式 (PowerShell)
docker run -it --rm `
-e HOST_PWD="/docker_web" `
-v "${PWD}:/workspace/docker_web" `
-v "${HOME}\.mla_v3:/root/mla_v3" `
chenglinhku/mlav3:latest cli
# Web UI 模式 (PowerShell)
docker run -d --name mla-webui `
-e HOST_PWD="/docker_web" `
-e PORT=4242 `
-v "${PWD}:/workspace/docker_web" `
-v "${HOME}\.mla_v3:/root/mla_v3" `
-p 4242:4242 `
chenglinhku/mlav3:latest webui
# 然后打开浏览器:http://localhost:4242
# 查看日志:docker logs -f mla-webui
```
**4. 配置 API Key**
打开浏览器:`http://localhost:4242`
<p align="center">
<img src="assets/config_web_screen_shot.png" alt="配置管理界面" width="800">
</p>
登录后打开 `Config` 对话框,编辑 `llm_config.yaml`,填入 API key 并保存。
**🎉 完成!** 开始使用 MLA CLI。
📖 **[Docker 完整指南](docs/DOCKER_GUIDE.md)**
---
### 方式 2: 本地安装(需要 Python)
**1. 安装包**
```bash
# 支持 Python 3.9+。如果需要使用打包依赖中的 MCP 能力,建议使用 Python 3.10+。
cd 安装路径
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
git clone https://github.com/ChenglinPoly/infiAgent.git
cd infiAgent
pip install -e .
```
**2. 安装 Playwright**
```bash
playwright install chromium
```
**3. 配置 API Key**
```bash
mla-agent --config-set api_key "your-api-key"
```
**4. 启动 CLI**
```bash
cd /你的工作空间
mla-agent --cli
```
📖 **[CLI 完整指南](docs/CLI_GUIDE.md)**
---
## 🎯 工作原理
MLA 的设计理念是**"为下一步提供简短但高价值的上下文"**。为实现这一理念,框架实现了多项创新:
### 1. 🌲 串行多智能体系统
MLA 在**树形层级结构**中部署智能体(例如,祖父 → 父亲 → 儿子)。这确保了:
- ✅ **单一目的智能体**:每个智能体都有专注的角色
- ✅ **最小工具集**:智能体仅访问必要的工具
- ✅ **任务对齐**:串行执行防止并行冲突
- ✅ **明确委派**:父智能体编排子智能体
**示例层级:**
```
alpha_agent(Level 3)
├── data_collection_agent(Level 2)
│ └── web_search_agent(Level 1)
├── coder_agent(Level 2)
└── material_to_document_agent(Level 2)
```
### 2. 🎯 嵌套注意力机制
长文档(PDF、小说、论文)**永远不会直接加载到上下文中**。相反:
- ✅ 使用 `answer_from_pdf`、`answer_from_document` 工具
- ✅ 查询驱动的内容提取
- ✅ 仅相关摘录或摘要进入上下文
- ✅ **应用层通过工具进行注意力分配**
**传统方法:**
```
加载整个 50 页 PDF → 智能体处理所有内容 → Token 溢出
```
**MLA 方法:**
```
智能体问:"方法是什么?"
→ 工具提取相关部分(2 页)
→ 返回简洁答案 → 最小 token 使用
```
### 3. 📁 文件中心架构
**"文件即一切。"** 所有输出和交互都保存到文件系统:
- ✅ 网页抓取 → 保存为 Markdown 文件
- ✅ PDF 解析 → 提取到结构化文档
- ✅ 子智能体结果 → 存储为文件
- ✅ **无即时返回**使上下文混乱
**优势:**
- 清晰的审计跟踪
- 可重用的工件
- 无上下文状态表示
### 4. ⚡ 十步策略(无需上下文压缩)
一个关键洞察:**当前文件系统状态代表了所有历史操作的效果。**
- ✅ 一个独立的 **thinking 模块**每 30 步更新一次文件空间状态
- ✅ 智能体仅保留**最近 10 个操作**(自上次状态更新以来)
- ✅ **无需上下文压缩**
- ✅ 历史操作反映在文件系统中,而非对话历史
**传统 LLM 智能体:**
```
步骤 1:创建文件 A
步骤 2:编辑文件 B
...
步骤 100:上下文溢出 → 需要压缩 → 信息丢失
```
**MLA 方法:**
```
步骤 1-10:记录操作
步骤 10:Thinking 模块更新"当前状态:文件 A、B、C 存在,包含..."
步骤 11-20:仅保留这些 + 当前状态
→ 无压缩,无信息丢失
```
### 5. 🔧 批量文件操作
受 [Claude Code](https://www.anthropic.com/) 启发,MLA 使用**基于列表的工具参数**来节省 token:
- ✅ 一次调用读取多个文件
- ✅ 批量操作减少累积 token 消耗
- ✅ 重复操作显著节省 token
**示例:**
```python
# 传统:3 次单独调用
file_read(path="file1.txt")
file_read(path="file2.txt")
file_read(path="file3.txt")
# MLA:1 次批量调用
file_read(paths=["file1.txt", "file2.txt", "file3.txt"])
```
### 6. 💾 基于任务 ID 的长期记忆
- ✅ **任务 ID = 工作空间绝对路径**(用户不可配置)
- ✅ 同一任务 ID 下允许**无限对话会话**
- ✅ 智能体具有工作空间中所有历史任务的记忆
- ✅ 跨中断和重启的持久记忆
**使用:**
```bash
# 第一次会话
mla-agent --task_id ~/research --user_input "收集有关 Transformer 的论文"
# → 将对话存储在 ~/mla_v3/conversations/{hash}_research_*
# 第二次会话(几天后)
mla-agent --task_id ~/research --user_input "总结已收集的论文"
# → 智能体记住前一次会话并访问收集的文件
```
### 7. 📊 基于调用图的共享上下文
`hierarchy_manager` 维护**动态调用关系图**:
- ✅ 跟踪父子智能体关系
- ✅ 将调用图注入共享上下文
- ✅ 防止智能体越界
- ✅ 在多智能体系统中保持任务对齐
**调用图示例:**
```json
{
"current_agent": "coder_agent",
"parent": "alpha_agent",
"siblings": ["data_collection_agent", "material_to_document_agent"],
"allowed_tools": ["python_run", "file_write", "file_read"]
}
```
这确保 `coder_agent` 不会意外调用 `web_search`(不在其范围内)或干扰兄弟智能体。
---
## 📸 界面截图
### CLI 界面
MLA 提供了功能丰富的交互式 CLI,支持实时任务监控、HIL 处理和智能体切换:
**系统选择:**
<p align="center">
<img src="assets/cli_choose_system.png" alt="CLI 系统选择" width="800">
</p>
**工具模式配置:**
<p align="center">
<img src="assets/cli_choose_tool_mode.png" alt="CLI 工具模式" width="800">
</p>
**启动任务:**
<p align="center">
<img src="assets/cli_start_task.png" alt="CLI 任务执行" width="800">
</p>
*基于 prompt_toolkit 和 rich 的交互式 CLI - 支持多轮对话、自动 HIL 检测和工具执行确认。*
### VS Code 插件
使用 MLA 的 JSONL 模式构建强大的 IDE 扩展:
<p align="center">
<img src="assets/vscode_plugin.png" alt="VS Code 插件截图" width="800">
</p>
*由 MLA 驱动的 VS Code 扩展 - 与工作空间上下文无缝集成,支持实时流式输出。*
---
## ⚙️ 配置指南
MLA 使用 YAML 文件进行智能体和工具配置。配置文件位于:
```
config/
├── agent_library/
│ ├── Researcher/ # 面向科研的多层级系统
│ │ ├── general_prompts.yaml # 共享提示词
│ │ ├── level_-1_judge_agent.yaml # 评判智能体
│ │ ├── level_0_tools.yaml # 工具定义
│ │ ├── level_1_agents.yaml # 底层智能体
│ │ ├── level_2_agents.yaml # 中层智能体
│ │ └── level_3_agents.yaml # 顶层智能体
│ └── OpenCowork/ # 通用电脑工作助手
└── run_env_config/
├── llm_config.yaml # LLM 设置
└── llm_config.example.yaml # 示例模板
```
### 关键配置文件
#### 1. `llm_config.yaml` - LLM 配置
```yaml
api_key: "your-api-key"
base_url: "https://openrouter.ai/api/v1"
models:
- "openai/anthropic/claude-sonnet-4"
- "openai/anthropic/claude-haiku-4.5"
temperature: 0.7
max_tokens: 8000
figure_models:
- "google/gemini-2.0-flash-thinking-exp-01-21"
```
**注意**:复制 `llm_config.example.yaml` 到 `llm_config.yaml` 开始使用。
#### 2. 智能体层级
MLA 将智能体组织成层级:
- **Level 3**:顶层编排者(如 `alpha_agent`)
- **Level 2**:功能专家(如 `data_collection_agent`、`coder_agent`)
- **Level 1**:基础执行者(如 `web_search_agent`)
- **Level 0**:工具定义
- **Level -1**:质量控制(如 `judge_agent`)
#### 3. 创建自定义智能体
编辑 YAML 文件以自定义智能体行为:
```yaml
alpha_agent:
type: llm_call_agent
level: 3
model_type: "advanced"
available_tools:
- data_collection_agent
- coder_agent
- data_to_figures_agent
- material_to_document_agent
- judge_agent
- final_output
system_prompt: |
你是一个研究助手...
```
---
## 💻 CLI 界面
### 交互模式
启动 CLI 进行对话式体验:
```bash
mla-agent --cli
```
**主要功能:**
- 🔄 **多轮对话**,持久化上下文
- 🤖 **智能体切换**,使用 `@agent_name` 语法
- 🔔 **自动 HIL 检测**,带音频提醒
- ⚠️ **工具执行确认**,手动模式下
- ⏸️ **中断和恢复**支持(Ctrl+C 暂停)
- 🎨 **丰富的终端 UI**,基于 `prompt_toolkit` 和 `rich`
**使用示例:**
```bash
# 直接输入任务(使用默认智能体)
[alpha_agent] > 收集有关 Transformer 的论文
# 切换智能体并执行任务
[alpha_agent] > @data_collection_agent 搜索最近的 NLP 论文
# 仅切换默认智能体
[alpha_agent] > @coder_agent
✅ 已切换到:coder_agent
[coder_agent] >
```
**CLI 命令:**
| 命令 | 描述 |
|------|------|
| `/help` | 显示帮助和可用命令 |
| `/agents` | 列出所有可用智能体 |
| `/resume` | 恢复中断的任务 |
| `/quit` 或 `/exit` | 退出 CLI 模式 |
| `Ctrl+C` | 中断当前任务(保持在 CLI 中) |
| `Ctrl+D` | 立即退出 CLI |
**人机交互(HIL)处理:**
当智能体请求人工输入时,CLI 会自动检测:
```
🔔🔔🔔 检测到 HIL 任务!按回车处理... 🔔🔔🔔
================================================================================
🔔 人类交互任务(HIL)
================================================================================
📝 任务 ID:upload_file_20250124
📋 指令:请上传所需的数据集文件...
================================================================================
💡 输入你的响应(任何文本)
输入 /skip 跳过此任务
================================================================================
[alpha_agent] HIL 响应 > 文件已成功上传
✅ HIL 任务已响应
```
**工具确认(手动模式):**
当设置 `--auto-mode false` 时,每次工具执行都需要确认:
```
⚠️⚠️⚠️ 检测到工具执行请求!按回车确认... ⚠️⚠️⚠️
================================================================================
⚠️ 工具执行确认请求
================================================================================
🔧 工具名称:python_run
📝 确认 ID:confirm_12345
📋 参数:
code: import numpy as np...
timeout: 300
================================================================================
💡 选择操作:
yes / y - 批准执行
no / n - 拒绝执行
================================================================================
[alpha_agent] 确认 [yes/no] > yes
✅ 已批准执行工具:python_run
```
---
### 命令行模式
用于脚本和自动化:
```bash
mla-agent \
--task_id /path/to/workspace \
--user_input "你的任务描述" \
--agent_name alpha_agent
```
**常用参数:**
| 参数 | 描述 | 默认值 |
|------|------|--------|
| `--task_id` | 工作空间路径(绝对路径) | 必需 |
| `--user_input` | 任务描述 | 必需 |
| `--agent_name` | 调用的智能体 | `alpha_agent` |
| `--agent_system` | 智能体库名称 | `Researcher` |
| `--cli` | 交互式 CLI 模式 | `false` |
| `--jsonl` | JSONL 输出模式 | `false` |
| `--force-new` | 清空所有状态并重新开始 | `false` |
| `--auto-mode` | 工具执行模式(`true`/`false`) | 自动检测 |
**自动模式示例:**
```bash
# 自动执行工具(无需确认)
mla-agent --task_id ~/project --user_input "任务" --auto-mode true
# 每个工具需手动确认
mla-agent --task_id ~/project --user_input "任务" --auto-mode false
```
---
### 运行时工具执行
```bash
# 工具通过进程内 direct-tools 执行
# 不再需要单独启动 mla-tool-server 进程
```
---
## 🔌 SDK 集成
MLA 提供两种 SDK 选项:**Python SDK** 用于直接集成,**JSONL 模式**用于 IDE 插件。
---
### Python SDK
当前推荐直接使用内置的 `infiagent` SDK。现在的 SDK 语义是:
- `infiagent(...)` 负责描述运行时默认配置
- `run(...)`、`fresh(...)`、`add_message(...)` 等方法负责绑定具体 `task_id`
- 可以通过 `user_data_root` 切换整套运行时目录
最小示例:
```python
from infiagent import infiagent
agent = infiagent(
user_data_root="/abs/path/to/my_root",
default_agent_system="Researcher",
default_agent_name="alpha_agent",
action_window_steps=30,
thinking_interval=30,
max_turns=100000,
fresh_enabled=True,
fresh_interval_sec=300,
)
result = agent.run(
"写一篇关于 Transformer 的综述论文",
task_id="/abs/path/to/tasks/transformer_survey",
)
print(f"状态:{result['status']}")
print(f"输出:{result['output']}")
```
如果你的 `user_data_root` 已经包含:
- `config/llm_config.yaml`
- `config/app_config.json`
- `agent_library/...`
- `tools_library/...`
通常不需要再重复传入 `llm_config_path`、`agent_library_dir`、`tools_dir`。
常用任务接口:
```python
# 对运行中或已停止的 task 发起 fresh / resume。
agent.fresh(
task_id="/abs/path/to/tasks/transformer_survey",
reason="reload runtime config",
)
# 向同一个 task(不是 task_id正在运行中的智能体) 追加新指令。
agent.add_message(
"保留已有大纲,只修改第三节。",
task_id="/abs/path/to/tasks/transformer_survey",
source="user",
resume_if_needed=True,
)
# 启动新的后台 Python 进程执行另一个 task。(可以是相同 task_id,将获得此 id下之前 task的所有记忆)
agent.start_background_task(
task_id="/abs/path/to/tasks/subtask_eval",
user_input="后台运行评测流程并总结结果",
force_new=True,
)
# 获取 task 快照,适合面板和轻量 watchdog。
snapshot = agent.task_snapshot(
task_id="/abs/path/to/tasks/transformer_survey",
)
# 重置损坏的 task 状态,可选保留 history。
agent.reset_task(
task_id="/abs/path/to/tasks/transformer_survey",
reason="clear broken loop",
preserve_history=True,
)
```
运行时自省:
```python
runtime = agent.describe_runtime()
print(runtime["user_data_root"])
print(runtime["agent_library_dir"])
print(runtime["tools_dir"])
systems = agent.list_agent_systems()
print(systems["systems"])
```
SDK 目前支持的高级能力:
- 基于 `task_id` 的后台启动、resume 和 fresh
- 基于 `user_data_root` 的 conversations、logs、runtime、config 隔离
- 工具调用前后 hook
- LLM 调用前的 context hook,可读取并改写最终 prompt
- 通过 `mcp_servers=[...]` 为实例注入 MCP 运行时配置
完整说明见:[docs/SDK_GUIDE.md](/Users/chenglin/Desktop/research/agent_framwork/vscode_version/MLA_V3/docs/SDK_GUIDE.md)
**Python SDK 使用场景:**
- 🔧 构建自定义工作流
- 🤖 在现有应用中嵌入智能体
- 📊 批量处理多个任务
- 🧭 构建外部面板、watchdog 和调度层
- 🔬 程序化控制的研究实验
---
### JSONL 模式(IDE 插件)
MLA 提供 JSONL 流式模式,用于与 IDE 和编辑器实时集成:
```bash
mla-agent \
--task_id $(pwd) \
--user_input "优化代码性能" \
--jsonl 2>/dev/null
```
**输出格式:**
```jsonl
{"type":"start","call_id":"c-1760936557-474c43","project":"~/project","agent":"alpha_agent","task":"优化..."}
{"type":"token","text":"[alpha_agent] 正在分析代码..."}
{"type":"progress","phase":"execution","pct":30}
{"type":"token","text":"调用工具:code_analyzer"}
{"type":"result","ok":true,"summary":"优化完成"}
{"type":"end","status":"ok","duration_ms":5432}
```
**事件类型:**
| 事件类型 | 描述 | 关键字段 |
|----------|------|----------|
| `start` | 任务开始 | `call_id`、`agent`、`task` |
| `token` | 流式文本输出 | `text` |
| `progress` | 进度更新 | `phase`、`pct` |
| `result` | 任务结果 | `ok`、`summary` |
| `end` | 任务完成 | `status`、`duration_ms` |
| `error` | 发生错误 | `message` |
---
### TypeScript/JavaScript 集成
```typescript
import { spawn } from 'child_process';
interface AgentEvent {
type: 'start' | 'token' | 'progress' | 'result' | 'end' | 'error';
[key: string]: any;
}
function runAgent(
workspacePath: string,
userInput: string,
onEvent: (event: AgentEvent) => void
): Promise<AgentEvent> {
return new Promise((resolve, reject) => {
const child = spawn('mla-agent', [
'--task_id', workspacePath,
'--user_input', userInput,
'--jsonl'
]);
let buffer = '';
child.stdout.on('data', (data) => {
buffer += data.toString();
const lines = buffer.split('\n');
buffer = lines.pop() || '';
lines.forEach(line => {
if (!line.trim()) return;
try {
const event: AgentEvent = JSON.parse(line);
onEvent(event);
if (event.type === 'end') {
resolve(event);
} else if (event.type === 'error') {
reject(new Error(event.message));
}
} catch (e) {
console.error('解析事件失败:', line);
}
});
});
child.stderr.on('data', (data) => {
// 将错误记录到 stderr
console.error(data.toString());
});
child.on('error', reject);
});
}
// 使用示例
await runAgent('/path/to/workspace', '编写单元测试', (event) => {
switch (event.type) {
case 'start':
console.log(`任务开始:${event.task}`);
break;
case 'token':
process.stdout.write(event.text);
break;
case 'progress':
updateProgressBar(event.pct);
break;
case 'result':
console.log(`\n结果:${event.summary}`);
break;
}
});
```
---
### VS Code 扩展示例
使用 MLA 构建你自己的 Cursor/VS Code 扩展:
**扩展功能:**
- 🤖 命令面板中的智能体命令
- 💬 带工作空间上下文的内联聊天
- 📝 自动代码生成和重构
- 🔍 编辑器内文献搜索
- 🔔 带 UI 提示的 HIL 任务处理
**基本扩展结构:**
```typescript
// extension.ts
import * as vscode from 'vscode';
import { runAgent } from './mla-client';
export function activate(context: vscode.ExtensionContext) {
let disposable = vscode.commands.registerCommand(
'mla.executeTask',
async () => {
const workspace = vscode.workspace.workspaceFolders?.[0].uri.fsPath;
const input = await vscode.window.showInputBox({
prompt: '输入任务描述'
});
if (!workspace || !input) return;
// 显示进度
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: 'MLA 智能体',
cancellable: true
}, async (progress, token) => {
await runAgent(workspace, input, (event) => {
if (event.type === 'token') {
vscode.window.showInformationMessage(event.text);
} else if (event.type === 'progress') {
progress.report({ increment: event.pct });
}
});
});
}
);
context.subscriptions.push(disposable);
}
```
---
## 📊 示例输出
### 学术论文输出
MLA 可以生成具有以下结构的完整研究论文:
```
upload/
├── paper.tex # 主 LaTeX 文档
├── references.bib # 参考文献
├── figures/
│ ├── architecture.png
│ ├── results_comparison.png
│ └── ablation_study.png
└── supplementary/
└── detailed_results.pdf
```
**质量指标:**
- ✅ 通过 EI/IEEE 会议的同行评审
- ✅ 正确的引用格式
- ✅ 高质量图表(300 DPI)
- ✅ 连贯的结构和流程
### 其他能力
**1. 科学计算**
- ECM 蛋白质组成仿真
- 物流公司排班调度
- 学生作业批改与反馈
**2. 通用任务**
- 网页抓取和数据提取
- 代码生成和调试
- 文档转换和处理
---
## 📖 文档
- 运行时工具通过 direct-tools 进程内执行,不再需要单独的 tool server。
- [人机交互 API](tool_server_lite/HIL_API.md) - 用户交互集成
- [配置示例](config/agent_library/Researcher/) - 智能体 YAML 模板
---
## 🤝 贡献
欢迎贡献!请随时提交问题或拉取请求。
---
## 📄 许可证
详见 [LICENSE](LICENSE)
---
## 📄 引用
如果您在研究中使用了 InfiAgent,请引用我们的论文:
```bibtex
@article{yu2026infiagent,
title={InfiAgent: An Infinite-Horizon Framework for General-Purpose Autonomous Agents},
author={Yu, Chenglin and Wang, Yuchen and Wang, Songmiao and Yang, Hongxia and Li, Ming},
journal={arXiv preprint arXiv:2601.03204},
year={2026}
}
```
---
## 🙏 致谢
- 使用 [LiteLLM](https://github.com/BerriAI/litellm) 统一 LLM 访问
- 使用 [Crawl4AI](https://github.com/unclecode/crawl4ai) 进行网页抓取
---
## 📬 联系方式
**作者**:@yuchenglin
**感谢贡献者**:@wangyuchen @wangsongmiao @yuyang @lijinjia
**邮箱**:yuchenglin96@qq.com/cl0415@connect.hku.hk/chenglin.yu@poly.edu.h
**GitHub**:[MLA V3 仓库](https://github.com/ChenglinPoly/infiAgent)
---
**使用 MLA V3 开始构建专属领域的 SOTA 智能体!** 🚀
================================================
FILE: apps/__init__.py
================================================
================================================
FILE: apps/cheapclaw/README.md
================================================
# CheapClaw
CheapClaw is a social-message orchestration app built on top of the `infiagent/mla` SDK.
It started from a practical judgment about OpenClaw-style systems: the idea is good, but the operating cost is too high if you push everything through large models for long-running work. CheapClaw is aimed at the opposite direction. It tries to make weaker and cheaper models hold long tasks better by leaning on InfiAgent's runtime design instead of turning every message into a giant single-shot agent loop.
The core problem it solves is not "how to connect one more chat channel". The real problem is:
- a user sends a new request while several agents are already running
- sometimes the new message should continue an old task
- sometimes it should inject a new requirement into a running task
- sometimes it should start a parallel branch
- and the system needs to choose that path automatically without losing context
CheapClaw is built around that decision layer.
## Why CheapClaw exists
Compared with OpenClaw-like systems, the main motivation here is cost and long-horizon stability.
OpenClaw is impressive, but for many practical deployments it is expensive. CheapClaw uses `infiagent` as the execution substrate because `infiagent` already has several properties that matter for weaker models:
- short-step execution instead of giant long-context monologues
- resumable task memory keyed by `task_id`
- configurable fresh / resume behavior
- agent-system level composition
- SDK-level control over runtime, task state, and tool execution
That makes it much more suitable for small-model orchestration, especially when tasks are long and iterative.
## What is different
### 1. Instant message insertion into existing work
This is the main feature, not a side feature.
CheapClaw has a supervisor agent that decides how a new message should be routed:
- continue an old task by reusing the same `task_id`
- append a requirement to a currently running task without stopping it
- fork into a new task when the work is genuinely different
These are different operations and they are handled differently.
#### Continue an old task
If the work is still the same deliverable, CheapClaw can restart a new worker on the same `task_id`.
That matters because the old task keeps:
- workspace
- share context
- historical outputs
- prior task memory
So "modify the old report", "redo that script", "continue the previous result" does not have to become a brand new task.
#### Append to a running task
If a worker is still running, CheapClaw can inject a new requirement into that running task.
This does not require stopping the worker first. The requirement is appended and absorbed on the next safe loop boundary.
That is a different behavior from resuming an old task, and it is one of the main pain points CheapClaw is designed to solve.
### 2. Built on the InfiAgent SDK, not a closed custom runtime
CheapClaw is not a monolithic framework. It is an application built on the `infiagent` SDK.
That means it inherits several useful runtime capabilities:
- different thinking and execution models
- different models for different sub-agents
- mixed local models and provider models
- mixed API vendors in one overall system
- task-level runtime control through the SDK
In practice, this means you can build a system where:
- the supervisor uses one model
- the worker uses another
- a compression model is different again
- some parts use local inference and others use hosted APIs
This is configured at the agent-system level and in the model config.
### 3. Better behavior for weaker models
CheapClaw benefits from InfiAgent's short-step execution strategy.
For weak or small models, that matters a lot. With the same model, total cost can go either way depending on the exact task, but on long-running tasks the short-step strategy is often more stable and more cost-efficient than trying to force a weak model through a giant single planning loop.
Practical rule:
- the weaker the model, the shorter the step window should be
- do not set it below 10
- a good default is 20
### 4. Skills are not the only extension mechanism
CheapClaw supports normal skills, but it also treats full agent systems as a reusable extension layer.
In the default CheapClaw layout there are only two systems:
- `CheapClawSupervisor`
- `CheapClawWorkerGeneral`
But `infiagent` itself also ships with other agent systems, for example:
- `Researcher`
- `OpenCowork`
If you want to reuse them in this kind of setup, remove `human_in_loop` from their config first.
Using a full agent system as a reusable capability is sometimes better than a narrow skill:
- a skill is good for a compact workflow or tool pattern
- an agent system is good for a whole class of related tasks with a stronger internal role design
You can think of an agent system as a kind of "skill pro": broader coverage, more prompt budget, more specialization.
## Architecture
CheapClaw has three layers:
1. Channel adapters
2. A supervisor agent
3. Worker tasks running on InfiAgent
The supervisor does not do the real work. It decides:
- direct reply
- reuse old `task_id`
- append to running task
- start a new task
- restart / fresh / reset when needed
Workers do the execution.
## Current capabilities
- Telegram integration
- Feishu integration through long connection mode
- WhatsApp adapter scaffolding
- dashboard and panel view
- conversation-to-task binding
- task completion observation
- watchdog observation
- task-level visible skill filtering
- task-level message append
- task-level restart on the same `task_id`
- file sending for Telegram
## Skills behavior
CheapClaw uses task-level visible-skill filtering for worker agents.
By default, workers only see:
- `docx`
- `pptx`
- `xlsx`
- `find-skills`
The supervisor can expose more skills to a worker when needed.
This is implemented by filtering what the model sees in `<available_skills>`, not by breaking the global skill installation mechanism. That means normal skill installation still works.
## Install and run
The intended model is:
1. install `infiagent`
2. install CheapClaw's extra runtime dependencies
3. place CheapClaw in a separate repo
4. point it at a `user_data_root`
5. run it as an app
### 1. Install InfiAgent
Use the published package first:
```bash
python -m pip install -U infiagent==3.0.1
```
### 2. Install CheapClaw's extra dependencies
CheapClaw itself is an app layer on top of `infiagent`, so it still needs a few app-specific packages:
```bash
python -m pip install -U requests lark-oapi
```
If you only test Telegram first, `requests` is enough.
If you want Feishu long-connection mode, install `lark-oapi` too.
### Bootstrap assets
```bash
python cheapclaw_service.py \
--user-data-root /abs/path/to/user_root \
--llm-config-path /abs/path/to/llm_config.yaml \
--bootstrap
```
### Show runtime
```bash
python cheapclaw_service.py \
--user-data-root /abs/path/to/user_root \
--llm-config-path /abs/path/to/llm_config.yaml \
--show-runtime
```
### Run one cycle
```bash
python cheapclaw_service.py \
--user-data-root /abs/path/to/user_root \
--llm-config-path /abs/path/to/llm_config.yaml \
--run-once
```
### Run as a long-lived service
```bash
python cheapclaw_service.py \
--user-data-root /abs/path/to/user_root \
--llm-config-path /abs/path/to/llm_config.yaml \
--run-loop
```
### Start the local dashboard
```bash
python cheapclaw_service.py \
--user-data-root /abs/path/to/user_root \
--llm-config-path /abs/path/to/llm_config.yaml \
--serve-webhooks --host 127.0.0.1 --port 8765 \
--run-loop
```
Then open:
- `http://127.0.0.1:8765/dashboard`
## Channel credentials
### Telegram
- `bot_token`
### Feishu
- `app_id`
- `app_secret`
- `verify_token`
- optional: `encrypt_key`
CheapClaw uses Feishu long connection mode, so it does not require a public webhook endpoint.
### WhatsApp Cloud API
- `access_token`
- `phone_number_id`
- `verify_token`
## Repository layout
- `cheapclaw_service.py`: main service entry
- `tool_runtime_helpers.py`: panel, task, and runtime helpers
- `assets/agent_library/`: supervisor and worker systems
- `assets/config/`: example config files
- `tools_library/`: CheapClaw-specific tools
- `skills/`: CheapClaw-specific skills
- `web/`: dashboard
## Notes for separate release
CheapClaw is intended to live in its own repository.
The framework-level changes that made it possible are mostly SDK and runtime improvements in `infiagent`, especially:
- SDK task control
- task snapshotting
- fresh / resume support
- tool hooks
- context hooks
- skill visibility filtering
If you publish `infiagent` to PyPI, CheapClaw can then be shipped as a clean separate application repo on top of that package.
================================================
FILE: apps/cheapclaw/__init__.py
================================================
================================================
FILE: apps/cheapclaw/assets/agent_library/CheapClawSupervisor/general_prompts.yaml
================================================
system_prompt_xml: |
<系统角色>
你是 CheapClawSupervisor 系统中的主调度智能体。你负责理解社交消息、维护会话状态、派发/续跑后台任务、安排计划任务、处理 watchdog 观测以及组织对用户的回复。
你不是业务执行 worker。你不直接做长任务,不自己产出复杂交付物。
</系统角色>
<面板语义>
CheapClaw 面板是调度的单一事实来源。任务输入只会给你当前 trigger_reason 和 dirty conversations 的事件摘要,不会把完整 panel、完整路径、完整 bindings、全量 linked_tasks 全部塞进来。
每个 dirty conversation 摘要主要包含:
- 所有新的用户消息
- 所有新的任务事件(尤其是 task_completed)
不会直接附带完整任务列表。你需要自己决定何时继续查。
如果你需要完整 panel、完整 bindings、完整 linked_tasks、message history 的完整范围、或 task 的文件路径和详细状态,必须主动调用工具:
- cheapclaw_read_panel
- cheapclaw_read_social_history
- cheapclaw_list_conversation_tasks
- cheapclaw_get_task_status
message_task_bindings 表示“哪条用户消息已经绑定到哪个 task_id”。一个 task_id 可以绑定多条用户消息;多条用户消息共同组成同一工作的连续需求。
</面板语义>
<核心决策流程>
处理每个 dirty conversation 时,必须按下面顺序思考:
1. 先识别这次触发来自什么:新用户消息、计划任务、watchdog、task 完成、还是系统状态变化。
2. 如果是用户消息,先判断是否只是普通聊天、澄清、确认、或无需调用 worker 就能直接回复。
3. 如果是明显的任务型需求,在不需要额外澄清时,应尽快先向用户发送一条简短回执,例如“收到,我先检查现有任务并继续处理”或“收到,我正在安排助手处理”,然后再继续做 task 路由和后台调度。
这个快速回执不等于最终结果;它只是为了让用户立即知道系统已接单。
4. 如果不是直接回复,再判断它与历史 task 的关系:
- append_to_running_task:这是同一工作,且已有 task 正在运行。
- continue_existing_task:这是同一工作,但已有 task 当前未运行,应恢复同一个 task_id。
- fork_new_task:和历史工作相关,但应开一个新的 task_id,例如新的 deliverable、不同 agent_system、不同实验分支、风险隔离。
- brand_new_task:与现有工作无关,应开全新 task。
5. 做出 task 决策后,必须把触发这次决策的 message_id 绑定到对应 task_id:
- 新建 task:用 cheapclaw_start_task 的 source_message_ids。
- 追加已有 task:用 cheapclaw_add_task_message 的 source_message_ids,或用 cheapclaw_update_panel 补充绑定。
- 直接回复无 task:也应在面板中更新 last_reply_summary,并清理 pending_events,避免同一条消息反复触发。
6. 如果同一 conversation 中有多个历史 task,必须先调用 cheapclaw_list_conversation_tasks,并结合:
- social_history 中的最近用户消息
- panel 中的完整 message_task_bindings
- task 的最近 final_output / thinking / status
来判断该继续哪个旧 task_id。
`recommended_task_id` 只是启发式提示,不是强制结论。最终选择必须由你基于历史对话和任务状态自行判断。
只有在有明确证据表明用户是在要求一个新 deliverable、一个新实验分支、一个不同 agent_system,或者旧 task 明显不适合承接时,才允许新建 task。
7. 处理完成后要更新面板:清掉已处理的 dirty / pending_events,必要时写 last_reply_summary、task 状态、message_task_bindings。
</核心决策流程>
<连续任务强规则>
对同一 deliverable 的修改、补充、重试、参数调整,默认都属于继续已有 task,而不是新建 task。
当旧 task 当前未运行,但你希望在“同一个 task_id / 同一个工作目录 / 同一段历史记忆”上继续做新的后台执行时,优先使用 cheapclaw_start_task,并显式传入这个旧 task_id。cheapclaw_start_task 不会再自动生成 task_id;如果确实要开新任务,必须先调用 cheapclaw_generate_task_id。
cheapclaw_add_task_message 主要用于:
- 目标 task 仍在运行中,需要即时插入新的需求
- 或者你明确想先把消息追加进当前任务上下文,再配合 resume/fresh 继续
下面这些表达,若 conversation 中已有相关 task,默认先判断该 task 是否仍在运行:
- “改成生成前 20 个”
- “把刚才那个脚本默认值改一下”
- “继续刚才那个任务”
- “再加一个导出 csv”
- “刚才那个结果不对,重试一下”
规则:
- 若旧 task 正在运行:优先 cheapclaw_add_task_message
- 若旧 task 已结束/已停止,但仍然是同一工作:优先 cheapclaw_start_task(task_id=旧task_id)
- 若确实是全新工作:先 cheapclaw_generate_task_id,再 cheapclaw_start_task(task_id=新task_id)
- 只有当用户明确要求新的独立交付物、不同方向的工作、或需要保留旧结果作为并行分支时,才新建新的 task_id
如果最新用户消息是在某个 task 完成后紧接着提出的增量修改,默认继续这个最近完成的 task_id。
</连续任务强规则>
<任务派发原则>
- 只有当确实需要后台工作时才启动 worker。
- 派工后要立即给用户发送回执,不等待 worker 完成。
- 如果任务正在进行而用户又提出补充需求,优先追加到同一 task,而不是重复开新任务。
- 如果用户明确改变目标、交付物、方法或系统,应考虑 fork 新 task。
- 如果 watchdog 只是“安静但可能还活着”,先查看状态、日志、history,再决定是否 fresh 或 reset。
- reset_task 是高风险操作,只在证据充分、当前 task 无法安全恢复时使用。
</任务派发原则>
<工具使用原则>
你优先使用 CheapClaw 专用工具:
- cheapclaw_read_panel
- cheapclaw_read_social_history
- cheapclaw_get_task_status
- cheapclaw_start_task
- cheapclaw_add_task_message
- cheapclaw_send_message
- cheapclaw_update_panel
- cheapclaw_schedule_plan / cheapclaw_cancel_plan
- cheapclaw_reset_task
- cheapclaw_list_agent_systems
- cheapclaw_list_global_skills / cheapclaw_reveal_skills
只有在需要看日志尾部或补充核验文件内容时,才使用 file_read / task_share_context_path / grep。
不要假设任务输入里已经附带了完整 panel 路径、message_history_path、share_context_path、log_path。需要这些时,主动调用 CheapClaw 工具查询。
如果当前新消息不足以判断其和旧任务的关系,先用 cheapclaw_read_social_history 扩展读取历史;如果你已经知道关键词或 task_id,也可以直接对 social_history.jsonl / latest_context.md / panel.json 使用 grep。
启动 worker 时不要臆造 agent_name。默认对 `CheapClawWorkerGeneral` 只使用 `worker_agent`。
如果你想使用别的 agent_name,必须先通过 `cheapclaw_list_agent_systems` 确认该 agent_system 的 `agent_names` 中确实存在该名字。
你绝对不能启动 `CheapClawSupervisor` 或 `supervisor_agent` 作为后台任务。主调度 agent 不能调用本身,否则会造成递归调度和状态污染。
</工具使用原则>
<计划与watchdog>
当 trigger_reason 或 pending_events 中出现 plan_tick / watchdog_tick / task_completed 时:
- 先查看对应 task 的最新状态和最近输出
- 决定是否需要给用户发送状态更新
- 决定是否需要继续派生任务、追加消息、fresh 或 reset
- 不要把“很久没更新 thinking”直接等同于卡死;先结合 log_path、last_action_at、最近历史消息综合判断
如果需要系统化排查 watchdog 观测,你可以加载 cheapclaw-watchdog skill。
</计划与watchdog>
<输出要求>
你本轮结束前必须用 final_output 给出简洁调度摘要:
- 处理了哪些 conversations
- 哪些消息被直接回复
- 哪些 message_id 被绑定到了哪些 task_id
- 启动/恢复/追加/重置了哪些 tasks
- 设置或取消了哪些计划
不要在 final_output 中粘贴大段日志或文件内容。
</输出要求>
================================================
FILE: apps/cheapclaw/assets/agent_library/CheapClawSupervisor/level_0_tools.yaml
================================================
tools:
# ==================== 文件操作工具 ====================
file_read:
level: 0
type: tool_call_agent
name: "file_read"
description: "读取指定文本文件的内容。路径参数必须是相对于当前 workspace/task 根目录的相对路径,不要传绝对路径。可以读取单个或多个文件,也可以指定起始和结束行。默认返回带行号的 JSON 格式。警告:不要读取二进制文件(如 pdf、docx、图片等)。"
parameters:
type: "object"
properties:
path:
type: "array"
items:
type: "string"
description: "文件相对路径数组,基于当前 workspace/task 根目录解析。单个文件传 ['file.txt'],多个文件传 ['file1.txt', 'file2.txt']。不要传绝对路径;只允许读取文本文件,不要读取二进制文件。"
start_line:
type: "integer"
description: "读取起始行号(从1开始),可选。多文件模式下应用于所有文件。"
end_line:
type: "integer"
description: "读取结束行号(包含),可选。多文件模式下应用于所有文件。"
encoding:
type: "string"
description: "文件编码,可选。不指定时自动检测。"
show_line_numbers:
type: "boolean"
default: true
description: "是否显示行号。true 返回 JSON 格式(含行号),false 返回纯文本。默认 true。"
required: ["path"]
file_write:
level: 0
type: tool_call_agent
name: "file_write"
description: "向指定文本文件写入内容。path 必须是相对于当前 workspace/task 根目录的相对路径,不要传绝对路径。如果文件不存在会自动创建;如果存在可以选择覆盖或追加,也支持替换指定行。注意:禁止写入 reference.bib 文件,请使用专门的参考文献管理工具(reference_add/reference_delete)。"
parameters:
type: "object"
properties:
path:
type: "string"
description: "文件的相对路径,例如 'src/main.py',相对于当前 workspace/task 根目录解析。不要传绝对路径。写入前建议使用目录列表工具检查是否有同名文件,避免覆盖他人文件。禁止路径为 'reference.bib'。"
content:
type: "string"
description: "要写入的文本内容。"
mode:
type: "string"
enum: ["write", "append"]
default: "write"
description: "写入模式。'write' 覆盖整个文件,'append' 追加到文件末尾。"
start_line:
type: "integer"
description: "行替换模式 - 起始行号(从1开始),可选。"
end_line:
type: "integer"
description: "行替换模式 - 结束行号,可选。"
required: ["path", "content"]
dir_list:
level: 0
type: tool_call_agent
name: "dir_list"
description: "列出指定目录的内容。path 必须是相对于当前 workspace/task 根目录的相对路径;不传时默认列出任务根目录。可以递归列出所有子目录和文件(自动排除 code_env 目录)。"
parameters:
type: "object"
properties:
path:
type: "string"
default: "."
description: "要列出的目录相对路径,相对于当前 workspace/task 根目录解析。不指定时列出任务根目录。"
recursive:
type: "boolean"
default: false
description: "是否递归列出子目录,默认 false。"
required: []
dir_create:
level: 0
type: tool_call_agent
name: "dir_create"
description: "创建新目录。path 必须是相对于当前 workspace/task 根目录的相对路径。如果父目录不存在会自动创建。"
parameters:
type: "object"
properties:
path:
type: "string"
description: "要创建的目录相对路径,相对于当前 workspace/task 根目录解析。"
required: ["path"]
file_move:
level: 0
type: tool_call_agent
name: "file_move"
description: "移动或复制文件/目录。source 和 destination 都应使用相对于当前 workspace/task 根目录的相对路径,不要传绝对路径。"
parameters:
type: "object"
properties:
source:
# type: "string"
# description: "源文件或目录的相对路径。"
# path:
type: "array"
items:
type: "string"
description: "源文件或目录的相对路径组,相对于当前 workspace/task 根目录解析。可以单个或多个。"
destination:
type: "string"
description: "目标相对路径,相对于当前 workspace/task 根目录解析。"
copy:
type: "boolean"
default: false
description: "是否复制(保留原文件),默认 false(移动)。"
required: ["source", "destination"]
file_delete:
level: 0
type: tool_call_agent
name: "file_delete"
description: "删除指定的文件或目录。path 应使用相对于当前 workspace/task 根目录的相对路径,不要传绝对路径。"
parameters:
type: "object"
properties:
path:
type: "string"
description: "要删除的文件或目录的相对路径,相对于当前 workspace/task 根目录解析。"
required: ["path"]
# ==================== 网络工具 ====================
web_search:
level: 0
type: tool_call_agent
name: "web_search"
description: "使用 DuckDuckGo 进行网络搜索。结果会保存为 Markdown 格式。"
parameters:
type: "object"
properties:
query:
type: "string"
description: "搜索关键词或问题。"
max_results:
type: "integer"
default: 10
description: "返回的最大结果数,默认 10。"
save_path:
type: "string"
description: "保存搜索结果的相对路径(.md 文件),请保存在 temp/web_search目录中。"
required: ["query","save_path"]
google_scholar_search:
level: 0
type: tool_call_agent
name: "google_scholar_search"
description: "在 Google Scholar 上搜索学术论文。支持年份筛选和分页。搜索结果保存为 Markdown 文件。"
parameters:
type: "object"
properties:
query:
type: "string"
description: "搜索关键词或主题。"
year_low:
type: "integer"
description: "筛选论文的起始年份,可选。"
year_high:
type: "integer"
description: "筛选论文的结束年份,可选。"
pages:
type: "integer"
default: 1
description: "爬取的搜索结果页数,每页约10篇论文。"
save_path:
type: "string"
description: "保存搜索结果的相对路径(.md 文件)。请保存在 temp/scholar_search目录中。"
required: ["query","save_path"]
arxiv_search:
level: 0
type: tool_call_agent
name: "arxiv_search"
description: "搜索 arXiv 预印本论文库。返回论文标题、作者、摘要、PDF 下载地址等信息。"
parameters:
type: "object"
properties:
query:
type: "string"
description: "搜索关键词,例如 'transformer neural network'。"
max_results:
type: "integer"
default: 10
description: "返回的最大结果数,默认 10。"
sort_by:
type: "string"
enum: ["relevance", "lastUpdatedDate", "submittedDate"]
default: "relevance"
description: "排序方式:relevance(相关性)、lastUpdatedDate(更新时间)、submittedDate(提交时间)。"
sort_order:
type: "string"
enum: ["descending", "ascending"]
default: "descending"
description: "排序顺序:descending(降序)、ascending(升序)。"
save_path:
type: "string"
description: "保存搜索结果的相对路径(.md 文件)。请保存在 temp/arxiv_search目录中。"
required: ["query","save_path"]
crawl_page:
level: 0
type: tool_call_agent
name: "crawl_page"
description: "爬取指定 URL 的网页内容,转换为 Markdown 格式。使用 crawl4ai 智能提取。"
parameters:
type: "object"
properties:
url:
type: "string"
description: "要爬取的网页完整 URL。"
save_path:
type: "string"
description: "保存 Markdown 文件的相对路径,必选。不指定则直接返回内容。请保存在 temp/crawl_page目录中。"
download_images:
type: "boolean"
default: false
description: "是否下载图片,默认 false(移除图片)。"
required: ["url","save_path"]
file_download:
level: 0
type: tool_call_agent
name: "file_download"
description: "从 URL 下载文件到本地。"
parameters:
type: "object"
properties:
url:
type: "string"
description: "要下载的文件 URL。"
save_path:
type: "string"
description: "保存文件的相对路径,例如 'upload/file.pdf'。"
required: ["url", "save_path"]
# ==================== 参考文献管理工具 ====================
reference_list:
level: 0
type: tool_call_agent
name: "reference_list"
description: "列出 reference.bib 文件中的所有参考文献(显示原文)。"
parameters:
type: "object"
properties:
bib_path:
type: "string"
default: "reference.bib"
description: "bib文件相对路径,默认 'reference.bib'。"
required: []
reference_add:
level: 0
type: tool_call_agent
name: "reference_add"
description: "向 reference.bib 添加参考文献。如果引用键已存在则覆盖原有内容。"
parameters:
type: "object"
properties:
entries:
type: "array"
items:
type: "string"
description: "参考文献字符串数组,每个元素是一条完整的bib条目。例如:['@article{key1,...}', '@book{key2,...}']"
bib_path:
type: "string"
default: "reference.bib"
description: "bib文件相对路径,默认 'reference.bib'。"
required: ["entries"]
reference_delete:
level: 0
type: tool_call_agent
name: "reference_delete"
description: "从 reference.bib 删除指定的参考文献。"
parameters:
type: "object"
properties:
keys:
type: "array"
items:
type: "string"
description: "要删除的引用键(如 'sun2023blockchain')或引用键数组。"
bib_path:
type: "string"
default: "reference.bib"
description: "bib文件相对路径,默认 'reference.bib'。"
required: ["keys"]
# ==================== 文档处理工具 ====================
parse_document:
level: 0
type: tool_call_agent
name: "parse_document"
description: "解析二进制文档为纯文本文件,不提供总结,分析服务。支持 PDF、Word、Markdown 格式。"
parameters:
type: "object"
properties:
path:
type: "string"
description: "要解析的文档相对路径。"
save_path:
type: "string"
description: "保存解析结果的相对路径。请保存在 temp/parse_document目录中。"
required: ["path","save_path"]
vision_tool:
level: 0
type: tool_call_agent
name: "vision_tool"
description: "使用LLM Vision模型分析图片内容。可以识别图片中的内容、描述场景、回答问题等。"
parameters:
type: "object"
properties:
image_path:
type: "string"
description: "图片文件的相对路径(相对于任务目录)。"
question:
type: "string"
description: "要问的问题,例如'这是什么?'或'请描述图片中的内容'。不指定则默认描述图片内容。"
save_path:
type: "string"
description: "必选,保存结果的相对路径,保存为纯文本文件 md或者 txt。请保存在 temp/answer_figuers目录中。"
# model:
# type: "string"
# description: "要使用的模型名称,可选。不指定则使用配置中的默认模型。"
required: ["image_path","save_path"]
image_read:
level: 0
type: tool_call_agent
name: "image_read"
description: "读取并分析图片内容(支持同时读取多张)。如果主模型支持多模态,图片会直接嵌入到对话中由主模型分析;否则会调用 Vision LLM 进行分析并返回文字描述。适用于查看实验结果图表、分析截图、理解图片内容等场景。"
parameters:
type: "object"
properties:
image_paths:
type: "array"
items:
type: "string"
description: "图片文件相对路径数组(相对于任务目录)。读取单张图片传单元素数组,如 [\"result.png\"]。支持 jpg/jpeg/png/gif/webp/bmp 格式。"
query:
type: "string"
description: "关于图片的问题或分析要求,例如'这些图表显示了什么趋势?'。不指定则默认描述图片内容。"
save_path:
type: "string"
description: "可选,保存分析结果的相对路径(仅在 text-only 模式下有效)。"
required: ["image_paths"]
create_image:
level: 0
type: tool_call_agent
name: "create_image"
description: "根据提示词生成图片,或基于参考图进行图片编辑/融合/风格迁移。支持最多 14 张参考图(Gemini 3 Pro)。"
parameters:
type: "object"
properties:
prompt:
type: "string"
description: "图片的描述提示词或编辑指令。纯生成时描述要生成的图片;有参考图时描述如何处理参考图(如'融合这两张图'、'将第一张图转为梵高风格')。"
image_path:
type: "string"
description: "生成图片保存的相对路径(例如 'temp/generated_image.png')。"
reference_images:
type: "array"
items:
type: "string"
description: "参考图片相对路径列表,可选。用于图片编辑、风格迁移、多图融合等。不提供则为纯文本生成图片。"
size:
type: "string"
default: "1024x1024"
description: "生成图片尺寸,默认 '1024x1024'。支持 '1792x1024'(16:9)等。"
n:
type: "integer"
default: 1
description: "生成图片数量,默认 1。"
required: ["prompt", "image_path"]
audio_tool:
level: 0
type: tool_call_agent
name: "audio_tool"
description: "使用LLM Audio模型分析音频内容。可以识别音频中的内容、描述场景、回答问题等。支持 mp3、wav、m4a 等格式。"
parameters:
type: "object"
properties:
audio_path:
type: "string"
description: "音频文件的相对路径(相对于任务目录)。"
question:
type: "string"
description: "要问的问题,例如'这段音频讲了什么?'或'请描述音频内容'。不指定则默认描述音频内容。"
model:
type: "string"
description: "要使用的模型名称,可选。不指定则使用配置中的默认模型。"
required: ["audio_path"]
paper_analyze_tool:
level: 0
type: tool_call_agent
name: "paper_analyze_tool"
description: "解析论文文档并使用LLM分析论文内容。可以总结论文、回答关于论文的问题等。"
parameters:
type: "object"
properties:
paper_path:
type: "string"
description: "论文文件的相对路径(相对于任务目录),支持PDF、Word等格式。"
question:
type: "string"
description: "要问的问题,例如'这篇论文的主要贡献是什么?'不指定则默认总结论文内容。"
parse_save_path:
type: "string"
description: "保存解析结果的相对路径,可选。"
required: ["paper_path"]
md_to_pdf:
level: 0
type: tool_call_agent
name: "md_to_pdf"
description: "将 Markdown 文件转换为 PDF。支持数学公式、表格、中文。调用远程 Pandoc API 服务。"
parameters:
type: "object"
properties:
source_path:
type: "string"
description: "Markdown 源文件的相对路径。"
output_path:
type: "string"
description: "输出 PDF 文件的相对路径,可选。不指定则使用源文件名改后缀。"
engine:
type: "string"
enum: ["pdflatex", "xelatex", "lualatex"]
default: "xelatex"
description: "PDF 编译引擎。xelatex 支持中文(推荐),pdflatex 适合英文。"
required: ["source_path"]
md_to_docx:
level: 0
type: tool_call_agent
name: "md_to_docx"
description: "将 Markdown 文件转换为 Word 文档(.docx)。调用远程 Pandoc API 服务。"
parameters:
type: "object"
properties:
source_path:
type: "string"
description: "Markdown 源文件的相对路径。"
output_path:
type: "string"
description: "输出 DOCX 文件的相对路径,可选。不指定则使用源文件名改后缀。"
required: ["source_path"]
file_download:
level: 0
type: tool_call_agent
name: "file_download"
description: "从指定 URL 下载文件到本地。"
parameters:
type: "object"
properties:
url:
type: "string"
description: "要下载的文件 URL。"
save_path:
type: "string"
description: "保存文件的相对路径,例如 'upload/file.pdf'。"
required: ["url", "save_path"]
# ==================== 文档处理工具 ====================
# parse_document:
# level: 0
# type: tool_call_agent
# name: "parse_document"
# description: "解析文档文件并提取文本内容。支持 PDF、Word、Markdown 格式。使用 pdfplumber 高质量提取 PDF(包含表格)。"
# parameters:
# type: "object"
# properties:
# path:
# type: "string"
# description: "要解析的文档相对路径。"
# save_path:
# type: "string"
# description: "保存解析结果的相对路径,可选。不指定则直接返回内容。"
# required: ["path"]
md_to_pdf:
level: 0
type: tool_call_agent
name: "md_to_pdf"
description: "将 Markdown 文件转换为 PDF。支持数学公式、表格、中文。调用远程 Pandoc API 服务。"
parameters:
type: "object"
properties:
source_path:
type: "string"
description: "Markdown 源文件的相对路径。"
output_path:
type: "string"
description: "输出 PDF 文件的相对路径,可选。不指定则使用源文件名改后缀。"
engine:
type: "string"
enum: ["pdflatex", "xelatex", "lualatex"]
default: "xelatex"
description: "PDF 编译引擎。xelatex 支持中文(推荐),pdflatex 适合英文。"
required: ["source_path"]
md_to_docx:
level: 0
type: tool_call_agent
name: "md_to_docx"
description: "将 Markdown 文件转换为 Word 文档(.docx)。调用远程 Pandoc API 服务。"
parameters:
type: "object"
properties:
source_path:
type: "string"
description: "Markdown 源文件的相对路径。"
output_path:
type: "string"
description: "输出 DOCX 文件的相对路径,可选。不指定则使用源文件名改后缀。"
required: ["source_path"]
images_to_ppt:
level: 0
type: tool_call_agent
name: "images_to_ppt"
description: "将多张图片转换为 PowerPoint 演示文稿,每张图片占一页。PPT 尺寸自动根据第一张图片的宽高比设置,所有图片居中显示并保持比例。适合将多张图表、截图等快速制作成演示文稿。"
parameters:
type: "object"
properties:
image_paths:
type: "array"
items:
type: "string"
description: "图片文件相对路径列表,例如 ['chart1.png', 'chart2.png']。也可以是单个字符串。"
output_path:
type: "string"
description: "输出 PPT 文件的相对路径,例如 'presentation.pptx'。"
required: ["image_paths", "output_path"]
# ==================== 浏览器操作工具 ====================
browser_launch:
level: 0
type: tool_call_agent
name: "browser_launch"
description: "启动浏览器会话。默认打开有界面的浏览器窗口(非无头模式),创建第一个标签页 page_0。返回 browser_id 用于后续操作。会自动创建 temp/browser/{browser_id}/ 目录保存截图和页面内容。"
parameters:
type: "object"
properties:
headless:
type: "boolean"
default: false
description: "是否无头模式(不显示浏览器窗口),默认 false(显示窗口)。"
width:
type: "integer"
default: 1280
description: "浏览器窗口宽度(像素),默认 1280。"
height:
type: "integer"
default: 800
description: "浏览器窗口高度(像素),默认 800。"
required: []
browser_close:
level: 0
type: tool_call_agent
name: "browser_close"
description: "关闭浏览器会话。会关闭所有标签页并清理资源。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID(由 browser_launch 返回)。"
required: ["browser_id"]
browser_navigate:
level: 0
type: tool_call_agent
name: "browser_navigate"
description: "在当前活跃标签页导航到指定 URL。导航后自动截图并保存页面内容到 temp/browser/{browser_id}/current.png 和 page_content.md。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
url:
type: "string"
description: "目标 URL,例如 'https://www.example.com'。"
wait_until:
type: "string"
enum: ["load", "domcontentloaded", "networkidle"]
default: "load"
description: "等待条件:load(页面加载完成)、domcontentloaded(DOM加载完成)、networkidle(网络空闲)。默认 load。"
required: ["browser_id", "url"]
browser_snapshot:
level: 0
type: tool_call_agent
name: "browser_snapshot"
description: "获取当前活跃标签页的快照。更新截图和页面文本内容。返回页面标题、URL、截图路径。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
include_html:
type: "boolean"
default: false
description: "是否包含 HTML 源码,默认 false。如果为 true,会保存到 page_source.html。"
required: ["browser_id"]
browser_execute_js:
level: 0
type: tool_call_agent
name: "browser_execute_js"
description: "在当前活跃标签页执行 JavaScript 代码。这是最强大的浏览器操作工具,可以实现任意页面操作(点击、输入、滚动、提取数据等)。执行后自动截图。注意:JavaScript 代码必须是函数表达式,如 '() => { return document.title; }'。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
script:
type: "string"
description: "要执行的 JavaScript 代码。必须是函数表达式,如 '() => { ... }'。示例:'() => document.querySelector(\"#btn\").click()' 或 '() => { return Array.from(document.querySelectorAll(\".item\")).map(el => el.textContent); }'。"
save_result:
type: "boolean"
default: false
description: "是否将执行结果保存到 js_result.json 文件,默认 false。"
required: ["browser_id", "script"]
browser_new_page:
level: 0
type: tool_call_agent
name: "browser_new_page"
description: "在当前浏览器会话中新建一个标签页。新标签页会自动成为活跃页面。返回新的 page_id(如 page_1, page_2)。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
required: ["browser_id"]
browser_switch_page:
level: 0
type: tool_call_agent
name: "browser_switch_page"
description: "切换到指定的标签页,使其成为活跃页面。切换后会自动更新截图和页面内容。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
page_id:
type: "string"
description: "要切换到的页面ID,例如 'page_0', 'page_1'。可通过 browser_list_pages 查看所有页面。"
required: ["browser_id", "page_id"]
browser_close_page:
level: 0
type: tool_call_agent
name: "browser_close_page"
description: "关闭指定的标签页。如果关闭的是活跃页面,会自动切换到第一个页面。不能关闭唯一的标签页(至少保留一个)。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
page_id:
type: "string"
description: "要关闭的页面ID,例如 'page_1'。"
required: ["browser_id", "page_id"]
browser_list_pages:
level: 0
type: tool_call_agent
name: "browser_list_pages"
description: "列出当前浏览器会话的所有标签页。显示每个页面的 page_id、标题、URL、是否为活跃页面。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
required: ["browser_id"]
browser_click:
level: 0
type: tool_call_agent
name: "browser_click"
description: "点击当前页面的指定元素。使用 CSS 选择器定位元素。点击后自动截图。如果元素难以点击,建议使用 browser_execute_js 执行 JavaScript 点击。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
selector:
type: "string"
description: "CSS 选择器,例如 '#submit-btn', '.button', 'button[type=\"submit\"]'。"
timeout:
type: "integer"
default: 5000
description: "等待元素出现的超时时间(毫秒),默认 5000。"
required: ["browser_id", "selector"]
browser_type:
level: 0
type: tool_call_agent
name: "browser_type"
description: "在指定的输入框输入文本。使用 CSS 选择器定位输入框。输入后自动截图。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
selector:
type: "string"
description: "输入框的 CSS 选择器,例如 '#username', 'input[name=\"email\"]'。"
text:
type: "string"
description: "要输入的文本内容。"
clear_first:
type: "boolean"
default: true
description: "是否先清空输入框,默认 true。"
required: ["browser_id", "selector", "text"]
browser_wait:
level: 0
type: tool_call_agent
name: "browser_wait"
description: "等待指定条件满足。可以等待元素出现、页面导航完成或指定时间。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
wait_type:
type: "string"
enum: ["selector", "navigation", "timeout"]
description: "等待类型:selector(等待元素出现)、navigation(等待导航完成)、timeout(等待指定时间)。"
selector:
type: "string"
description: "CSS 选择器(wait_type='selector' 时必需)。"
timeout:
type: "integer"
default: 30000
description: "超时时间(毫秒),默认 30000。"
milliseconds:
type: "integer"
description: "等待时长(毫秒,wait_type='timeout' 时必需)。"
required: ["browser_id", "wait_type"]
browser_mouse_move:
level: 0
type: tool_call_agent
name: "browser_mouse_move"
description: "移动鼠标到指定坐标位置。支持人类化移动(贝塞尔曲线轨迹)模拟真实用户行为,避免人机验证检测。适用于需要精确控制鼠标位置的场景。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
x:
type: "number"
description: "目标 x 坐标(像素)。"
y:
type: "number"
description: "目标 y 坐标(像素)。"
human_like:
type: "boolean"
default: true
description: "是否使用人类化移动(贝塞尔曲线轨迹),默认 true。设为 false 则直接瞬移到目标位置。"
required: ["browser_id", "x", "y"]
browser_mouse_click_coords:
level: 0
type: tool_call_agent
name: "browser_mouse_click_coords"
description: "在指定坐标位置点击鼠标。支持左键/右键/中键、单击/双击、人类化点击(随机延迟和轨迹)。适用于动态元素、Canvas/SVG 区域、无法用选择器定位的元素。特别适合处理滑块验证码等场景。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
x:
type: "number"
description: "点击的 x 坐标(像素)。"
y:
type: "number"
description: "点击的 y 坐标(像素)。"
button:
type: "string"
enum: ["left", "right", "middle"]
default: "left"
description: "鼠标按钮:left(左键)、right(右键)、middle(中键),默认 left。"
click_count:
type: "integer"
default: 1
description: "点击次数,1为单击,2为双击,默认 1。"
human_like:
type: "boolean"
default: true
description: "是否使用人类化点击(贝塞尔曲线移动+随机延迟),默认 true。推荐在需要绕过人机验证时启用。"
required: ["browser_id", "x", "y"]
browser_drag_and_drop:
level: 0
type: tool_call_agent
name: "browser_drag_and_drop"
description: "执行鼠标拖拽操作,从起点拖动到终点。支持人类化拖拽(贝塞尔曲线轨迹+随机延迟)模拟真实用户行为。主要用于:1) 滑块验证码(重要!)2) 拖拽排序 3) 地图平移/缩放 4) 拖拽文件上传 5) 任何需要拖拽的交互。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
from_x:
type: "number"
description: "起始 x 坐标(像素)。"
from_y:
type: "number"
description: "起始 y 坐标(像素)。"
to_x:
type: "number"
description: "目标 x 坐标(像素)。"
to_y:
type: "number"
description: "目标 y 坐标(像素)。"
human_like:
type: "boolean"
default: true
description: "是否使用人类化拖拽(贝塞尔曲线轨迹+随机延迟),默认 true。强烈推荐在处理验证码时启用。"
required: ["browser_id", "from_x", "from_y", "to_x", "to_y"]
browser_hover:
level: 0
type: tool_call_agent
name: "browser_hover"
description: "鼠标悬停在元素或坐标上,停留指定时长。支持人类化移动。用于触发悬停菜单、查看 tooltip、触发延迟加载内容等场景。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
selector:
type: "string"
description: "要悬停的元素 CSS 选择器(selector 和坐标二选一)。"
x:
type: "number"
description: "悬停的 x 坐标(selector 和坐标二选一)。"
y:
type: "number"
description: "悬停的 y 坐标(selector 和坐标二选一)。"
duration_ms:
type: "integer"
default: 1000
description: "悬停持续时间(毫秒),默认 1000。"
human_like:
type: "boolean"
default: true
description: "是否使用人类化移动(贝塞尔曲线轨迹),默认 true。"
required: ["browser_id"]
browser_scroll:
level: 0
type: tool_call_agent
name: "browser_scroll"
description: "使用鼠标滚轮滚动页面或指定元素。支持平滑滚动模拟真实用户行为。可以滚动整个页面,也可以滚动指定元素(如滚动容器、iframe 等)。用于查看页面更多内容、触发懒加载、滚动到特定位置等场景。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
delta_y:
type: "integer"
description: "垂直滚动距离(像素)。正数向下滚动,负数向上滚动。例如:500 向下滚动500像素,-300 向上滚动300像素。"
delta_x:
type: "integer"
default: 0
description: "水平滚动距离(像素),可选,默认 0。正数向右滚动,负数向左滚动。"
selector:
type: "string"
description: "要滚动的元素 CSS 选择器,可选。不指定则滚动整个页面。指定后会先移动鼠标到该元素,然后滚动该元素。"
smooth:
type: "boolean"
default: true
description: "是否平滑滚动(分多次小步滚动),默认 true。平滑滚动更像真实用户,但稍慢。"
human_like:
type: "boolean"
default: true
description: "是否先使用人类化移动鼠标到元素(仅在指定 selector 时有效),默认 true。"
required: ["browser_id", "delta_y"]
# ==================== 代码执行工具 ====================
execute_command:
level: 0
type: tool_call_agent
name: "execute_command"
description: "执行命令行命令。可选后台执行并将输出重定向到文件。"
parameters:
type: "object"
properties:
command:
type: "string"
description: "要执行的 shell 命令,例如 'ls -la'、'python script.py'、'pip install -r requirements.txt'。"
working_dir:
type: "string"
default: "."
description: "命令执行的工作目录相对路径,默认为任务根目录。"
timeout:
type: "integer"
default: 30
description: "命令执行超时时间(秒),默认 30。"
background:
type: "boolean"
default: false
description: "是否后台执行(不阻塞),默认 false。后台执行时必须指定 output_file。"
output_file:
type: "string"
description: "输出重定向到文件的相对路径。后台执行时必需,非后台执行时可选。"
required: ["command"]
grep:
level: 0
type: tool_call_agent
name: "grep"
description: "在文件中搜索匹配的文本模式(跨平台纯Python实现,支持正则表达式)。可以搜索指定目录或文件,支持递归搜索和文件类型过滤。"
parameters:
type: "object"
properties:
pattern:
type: "string"
description: "要搜索的正则表达式模式,例如 'def.*function' 或 'TODO'。"
search_path:
type: "string"
default: "."
description: "搜索路径相对路径,默认为当前工作区根目录。"
file_pattern:
type: "string"
default: "*"
description: "文件名匹配模式(支持通配符),如 '*.py'、'*.txt'、'*.md' 等。默认匹配所有文件。"
recursive:
type: "boolean"
default: true
description: "是否递归搜索子目录,默认 true。"
case_sensitive:
type: "boolean"
default: true
description: "是否大小写敏感,默认 true。"
show_line_number:
type: "boolean"
default: true
description: "是否显示行号,默认 true。"
max_results:
type: "integer"
default: 100
description: "最大结果数量,默认 100。"
context_lines:
type: "integer"
default: 0
description: "显示匹配行前后的上下文行数,默认 0(不显示上下文)。"
required: ["pattern"]
# ==================== Skill 工具 ====================
load_skill:
level: 0
type: tool_call_agent
name: "load_skill"
description: "将指定的 Agent Skill 从全局技能库部署到当前 workspace 的 .skills/ 目录,并把对应 SKILL.md 注入当前上下文。部署后可通过 execute_command 运行技能包含的脚本。"
parameters:
type: "object"
properties:
skill_name:
type: "string"
description: "要部署的 skill 名称,对应 <available_skills> 中列出的 name。"
required: ["skill_name"]
offload_skill:
level: 0
type: tool_call_agent
name: "offload_skill"
description: "从当前上下文中卸载某个已加载 skill 的 SKILL.md 内容,但不删除磁盘上的 .skills 文件。"
parameters:
type: "object"
properties:
skill_name:
type: "string"
description: "要从当前上下文中卸载的 skill 名称。"
required: ["skill_name"]
fresh:
level: 0
type: tool_call_agent
name: "fresh"
description: "在安全点刷新运行时配置、工具注册、skills 与提示词缓存。默认刷新当前 task;若指定 task_id,则刷新对应 task。这里的 task_id 应为绝对路径。仅当你刚创建/安装了新工具或新 skills 时才使用。"
parameters:
type: "object"
properties:
reason:
type: "string"
description: "触发 fresh 的原因说明,例如“刚安装了新工具”或“刚安装了新 skill”。"
task_id:
type: "string"
description: "可选。目标任务的 task_id,必须是绝对路径。省略时 fresh 当前任务;指定后会 fresh 对应任务,若该任务未在运行则会重载配置并后台 resume。"
add_message:
level: 0
type: tool_call_agent
name: "add_message"
description: "向指定 task 的 current.instructions 追加一条新消息。若目标 task 正在运行,它会在下一轮看到这条消息;若未运行,可选择后台 resume。task_id 应为绝对路径;省略时默认当前 task。适合对同一任务做需求补充或变更。"
parameters:
type: "object"
properties:
task_id:
type: "string"
description: "可选。目标任务的 task_id,必须是绝对路径。省略时默认当前 task。"
message:
type: "string"
description: "要追加给该 task 的消息内容。"
source:
type: "string"
description: "消息来源标记,例如 agent / user / system。默认 agent。"
resume_if_needed:
type: "boolean"
default: false
description: "当目标 task 当前未运行时,是否在追加消息后后台 resume。默认 false。"
required: ["message"]
start_background_task:
level: 0
type: tool_call_agent
name: "start_background_task"
description: "后台启动一个新的 task 进程。适合把独立子任务交给另一个 workspace/task 在后台异步运行。"
parameters:
type: "object"
properties:
task_id:
type: "string"
description: "必需。新任务的 task_id,建议使用绝对路径作为 workspace。"
user_input:
type: "string"
description: "必需。新任务的需求描述。"
agent_system:
type: "string"
description: "可选。Agent system,默认 OpenCowork。"
agent_name:
type: "string"
description: "可选。启动的 agent 名称,默认 alpha_agent。"
force_new:
type: "boolean"
default: false
description: "是否强制清空该 task 的旧状态后再启动。"
direct_tools:
type: "boolean"
default: true
description: "是否启用 direct-tools。默认 true。"
config:
type: "object"
description: "可选。类似 SDK 的运行配置。当前支持 llm_config_path、user_data_root、agent_library_dir/library_dir、skills_dir、tools_dir、action_window_steps、thinking_interval、fresh_enabled、fresh_interval_sec、mcp_servers、auto_mode、force_new、direct_tools。"
required: ["task_id", "user_input"]
task_share_context_path:
level: 0
type: tool_call_agent
name: "task_share_context_path"
description: "返回指定 task 的 share_context 和 stack 文件路径,不直接返回内容。task_id 应为绝对路径;拿到路径后,如有需要请再自行读取。"
parameters:
type: "object"
properties:
task_id:
type: "string"
description: "可选。目标任务的 task_id,必须是绝对路径。省略时默认当前 task。"
required: []
list_task_ids:
level: 0
type: tool_call_agent
name: "list_task_ids"
description: "列出当前已知的 task_id 列表,来源于 share_context 持久化记录。可选只返回当前运行中的 task。"
parameters:
type: "object"
properties:
only_running:
type: "boolean"
default: false
description: "是否只返回当前运行中的 task。默认 false。"
required: []
# ==================== 框架必需工具 ====================
final_output:
level: 0
type: tool_call_agent
name: "final_output"
description: "智能体输出最终结果的工具。当智能体完成任务或需要终止执行时调用此工具。"
parameters:
type: "object"
properties:
task_id:
type: "string"
description: "任务的唯一ID。"
status:
type: "string"
enum: ["success", "error"]
description: "任务执行状态:'success' 表示成功完成,'error' 表示执行失败。"
output:
type: "string"
description: "成功或失败的说明。如果输出包含文件,必须提供文件的相对路径和描述(不要重复文件中已有的内容),并包含 judge agent 的反馈。"
error_information:
type: "string"
description: "错误信息,仅在 status 为 'error' 时必需。"
required: ["task_id", "status", "output"]
cheapclaw_read_panel:
level: 0
type: tool_call_agent
name: "cheapclaw_read_panel"
description: "读取 CheapClaw 的完整消息面板或指定 conversation 的完整面板数据。默认输入不会附带完整 linked_tasks 和完整 bindings;当你需要完整 panel、完整 message_task_bindings、context_summary_path、路径字段、或 service_state 细节时,使用它。"
parameters:
type: "object"
properties:
only_dirty:
type: "boolean"
default: false
description: "是否只返回 dirty=true 的 conversations。"
channel:
type: "string"
description: "渠道名,例如 telegram / feishu / whatsapp。"
conversation_id:
type: "string"
description: "会话稳定 ID。"
required: []
cheapclaw_update_panel:
level: 0
type: tool_call_agent
name: "cheapclaw_update_panel"
description: "CheapClaw 面板的兜底修正工具。大多数消息写入、task 启动/完成、message_id 绑定、dirty 清理应由系统自动完成;只有当你需要补写 last_reply_summary、手动修正绑定关系、追加特殊 pending_event,或纠正异常状态时才使用它。该工具只返回是否成功和执行了哪些操作,不返回整块 panel。"
parameters:
type: "object"
properties:
channel:
type: "string"
description: "渠道名。"
conversation_id:
type: "string"
description: "会话 ID。"
set_dirty:
type: "boolean"
description: "是否标记该会话为 dirty。"
clear_dirty:
type: "boolean"
description: "是否清除该会话的 dirty 和 pending_events。"
conversation_patch:
type: "object"
description: "要直接 merge 到 conversation 上的字段。"
task_id:
type: "string"
description: "目标 task_id,必须是绝对路径。"
task_patch:
type: "object"
description: "要 merge 到 linked task 上的字段。"
bind_message_ids:
type: "array"
items:
type: "string"
description: "可选。需要绑定到 task_id 的 message_id 列表。用于把具体用户消息明确关联到某个 task。"
binding_note:
type: "string"
description: "可选。绑定说明,例如“继续昨天的报告任务”或“这是一个新分支 deliverable”。"
binding_type:
type: "string"
description: "可选。绑定类型,例如 task / direct_reply / forked_task。默认 task。"
append_pending_event:
type: "object"
description: "要追加到 pending_events 的事件对象。"
required: ["channel", "conversation_id"]
cheapclaw_read_social_history:
level: 0
type: tool_call_agent
name: "cheapclaw_read_social_history"
description: "读取某个渠道会话的社交历史消息。默认只取最近有限条,但你可以通过 limit、message_id 范围或时间范围做分层检索。群聊建议优先读取最近和 bot 相关的消息;如果最近 10 条不足以判断,再扩大到最近 20 条、50 条或指定时间段。"
parameters:
type: "object"
properties:
channel:
type: "string"
conversation_id:
type: "string"
limit:
type: "integer"
default: 30
only_mentions_to_bot:
type: "boolean"
default: false
include_bot_replies:
type: "boolean"
default: true
from_message_id:
type: "string"
to_message_id:
type: "string"
before_timestamp:
type: "string"
after_timestamp:
type: "string"
required: ["channel", "conversation_id"]
cheapclaw_send_message:
level: 0
type: tool_call_agent
name: "cheapclaw_send_message"
description: "向 CheapClaw 主服务写入一个待发送消息,由主服务异步发送到对应社交平台。若还需要发送本地文件,优先使用 cheapclaw_send_file;此工具也可附带 attachments,但更适合文本回执。"
parameters:
type: "object"
properties:
channel:
type: "string"
conversation_id:
type: "string"
message:
type: "string"
attachments:
type: "array"
items:
type: "object"
description: "附件元数据列表,可选。"
required: ["channel", "conversation_id", "message"]
cheapclaw_send_file:
level: 0
type: tool_call_agent
name: "cheapclaw_send_file"
description: "向指定社交渠道异步发送一个本地文件。适用于将任务产出的脚本、文档、图片等文件直接发回用户。local_path 必须是当前机器上真实存在的文件绝对路径。若交付结果本质上是一个文件,优先发文件,不要把整段文件内容直接塞进文本消息。"
parameters:
type: "object"
properties:
channel:
type: "string"
description: "渠道名,例如 telegram / feishu / whatsapp。"
conversation_id:
type: "string"
description: "目标会话 ID。"
local_path:
type: "string"
description: "要发送的本地文件绝对路径。"
filename:
type: "string"
description: "可选。对外显示的文件名;不传则使用 local_path 的文件名。"
mime_type:
type: "string"
description: "可选。文件 MIME 类型;不传则自动猜测。"
kind:
type: "string"
description: "可选。auto / document / image / video / audio。默认 auto。"
caption:
type: "string"
description: "可选。文件说明文字。"
message:
type: "string"
description: "可选。随文件一起发送的额外文本消息。"
required: ["channel", "conversation_id", "local_path"]
cheapclaw_start_task:
level: 0
type: tool_call_agent
name: "cheapclaw_start_task"
description: "为指定 conversation 后台启动一个 worker 进程,并自动把它绑定到 CheapClaw 面板。它既可以用于新 task_id,也可以用于旧 task_id,但 task_id 必须显式提供。若要创建全新任务,应先调用 cheapclaw_generate_task_id 生成新的绝对路径 task_id;若要继续同一工作,应直接复用旧 task_id。若传入已经存在的 task_id 且 force_new=false,新的后台执行会继续使用这个 task_id 对应的 workspace、history、share_context 和记忆。对于“同一工作但旧 worker 已结束”的情况,优先使用它并传旧 task_id。只有在明确是全新工作、并行分支或不同 deliverable 时,才应生成新的 task_id。禁止用它启动 CheapClawSupervisor 本身。默认在 CheapClawWorkerGeneral 中使用 worker_agent。只有在 cheapclaw_list_agent_systems 已确认目标 agent_name 存在时才应显式传 agent_name。"
parameters:
type: "object"
properties:
channel:
type: "string"
conversation_id:
type: "string"
conversation_type:
type: "string"
default: "group"
display_name:
type: "string"
task_name:
type: "string"
task_id:
type: "string"
description: "必需。必须是绝对路径。创建新任务前应先调用 cheapclaw_generate_task_id;若传入一个已有 task_id,则会在同一个 task 身份下继续运行,复用该 task 的历史记忆和工作目录。"
user_input:
type: "string"
agent_system:
type: "string"
description: "目标 agent_system。不能使用 CheapClawSupervisor;主 agent 不允许调用本身。"
agent_name:
type: "string"
description: "可选。默认不传,CheapClawWorkerGeneral 会自动使用 worker_agent。不要臆造 agent_name。只有在 cheapclaw_list_agent_systems 返回的 agent_names 中确认存在时才传。"
force_new:
type: "boolean"
default: false
require_mention:
type: "boolean"
default: true
exposed_skills:
type: "array"
items:
type: "string"
description: "可选。额外追加给该 task 的 skills 名称列表。系统会始终保留默认开放的 skills(当前为 docx、pptx、xlsx、find-skills),这里传入的是在默认集合基础上的增量追加,重复项会自动去重。"
source_message_ids:
type: "array"
items:
type: "string"
description: "可选。触发本次启动的用户 message_id 列表。主 agent 应传入,用于把这些用户消息绑定到新 task。"
required: ["channel", "conversation_id", "task_name", "task_id", "user_input"]
cheapclaw_add_task_message:
level: 0
type: tool_call_agent
name: "cheapclaw_add_task_message"
description: "给已有 task_id 追加同一任务语义下的新消息,并自动附加当前时区时间。task_id 必须是绝对路径。它主要用于目标 task 正在运行时的即时需求插入,让运行中的 agent 在后续轮次吸收新要求;也可用于先追加消息再配合 resume/fresh。若旧 task 已经停止,但你只是想在同一个 task_id 下重新起一个后台执行,通常更适合用 cheapclaw_start_task(task_id=旧task_id)。在决定是否追加前,应结合 panel 历史对话、message_task_bindings、最近 final_output 先确认这是不是同一个 deliverable。"
parameters:
type: "object"
properties:
task_id:
type: "string"
message:
type: "string"
source:
type: "string"
default: "agent"
resume_if_needed:
type: "boolean"
default: false
description: "目标 task 未运行时,是否在追加消息后尝试恢复。适合你明确要沿用当前 current 指令上下文继续。"
agent_system:
type: "string"
channel:
type: "string"
description: "可选。若提供,会把 source_message_ids 绑定到这个 conversation 下的 task。"
conversation_id:
type: "string"
description: "可选。若提供,会把 source_message_ids 绑定到这个 conversation 下的 task。"
source_message_ids:
type: "array"
items:
type: "string"
description: "可选。触发这次追加消息的用户 message_id 列表。主 agent 应传入,用于把这些消息绑定到已有 task。"
required: ["task_id", "message"]
cheapclaw_get_task_status:
level: 0
type: tool_call_agent
name: "cheapclaw_get_task_status"
description: "读取指定 task_id 的聚合状态,包括 running、share_context_path、stack_path、last_thinking、last_final_output、log_path 等。任务输入里默认不会附带这些路径与明细;当你需要核验某个 task 的详细状态或文件位置时,用它。"
parameters:
type: "object"
properties:
task_id:
type: "string"
required: ["task_id"]
cheapclaw_list_agent_systems:
level: 0
type: tool_call_agent
name: "cheapclaw_list_agent_systems"
description: "列出当前 user_data_root 下可用的 agent_system 配置,并返回每个 system 中实际存在的 agent_names。启动任务前应用它确认 agent_name;对 CheapClawWorkerGeneral,默认使用 worker_agent。"
parameters:
type: "object"
properties: {}
required: []
cheapclaw_schedule_plan:
level: 0
type: tool_call_agent
name: "cheapclaw_schedule_plan"
description: "创建 CheapClaw 计划任务。支持 main_agent 或 task 范围。除了 interval_sec 和 once_at,还支持 daily/weekly 按固定时刻触发,例如每天 08:00 或每周一/三/五 08:00。"
parameters:
type: "object"
properties:
name:
type: "string"
scope:
type: "string"
enum: ["main_agent", "task"]
task_id:
type: "string"
channel:
type: "string"
conversation_id:
type: "string"
interval_sec:
type: "integer"
once_at:
type: "string"
schedule_type:
type: "string"
enum: ["interval", "once", "daily", "weekly"]
time_of_day:
type: "string"
description: "用于 daily/weekly,格式 HH:MM,例如 08:00。"
days_of_week:
type: "array"
items:
type: "string"
description: "用于 weekly,取值如 mon/tue/wed/thu/fri/sat/sun。"
message:
type: "string"
enabled:
type: "boolean"
default: true
required: ["name", "scope"]
cheapclaw_cancel_plan:
level: 0
type: tool_call_agent
name: "cheapclaw_cancel_plan"
description: "取消已有的计划任务。"
parameters:
type: "object"
properties:
plan_id:
type: "string"
required: ["plan_id"]
cheapclaw_reset_task:
level: 0
type: tool_call_agent
name: "cheapclaw_reset_task"
description: "重置 task 状态,可选保留 history,并可尝试终止当前 task 的后台进程。task_id 必须是绝对路径。"
parameters:
type: "object"
properties:
task_id:
type: "string"
preserve_history:
type: "boolean"
default: true
kill_background_processes:
type: "boolean"
default: true
reason:
type: "string"
required: ["task_id"]
cheapclaw_generate_task_id:
level: 0
type: tool_call_agent
name: "cheapclaw_generate_task_id"
description: "按 CheapClaw 规则生成新的绝对路径 task_id。"
parameters:
type: "object"
properties:
channel:
type: "string"
conversation_id:
type: "string"
task_name:
type: "string"
required: ["channel", "conversation_id", "task_name"]
cheapclaw_list_conversation_tasks:
level: 0
type: tool_call_agent
name: "cheapclaw_list_conversation_tasks"
description: "列出某个 conversation 当前已经关联的 tasks,并返回 latest_bound_task_id、running_task_ids、recent_task_ids,以及基于绑定和最近活动生成的 recommended_task_id / recommended_action。注意:recommended_* 只是启发式提示,不是强制结论。主 agent 必须结合 panel 历史、社交消息历史、最近 final_output 和用户最新表达,自行决定是续用旧 task_id 还是新建 task。"
parameters:
type: "object"
properties:
channel:
type: "string"
conversation_id:
type: "string"
required: ["channel", "conversation_id"]
cheapclaw_list_global_skills:
level: 0
type: tool_call_agent
name: "cheapclaw_list_global_skills"
description: "查看当前全局 skills 主库中的全部可用技能。"
parameters:
type: "object"
properties: {}
required: []
cheapclaw_reveal_skills:
level: 0
type: tool_call_agent
name: "cheapclaw_reveal_skills"
description: "将指定 skills 追加到某个 task 的可见 skills 白名单中。它不会修改全局 skills 主库;load_skill 仍然从全局主库安装技能。可选执行 fresh 让运行中的任务重新看到这些 skills。"
parameters:
type: "object"
properties:
task_id:
type: "string"
skill_names:
type: "array"
items:
type: "string"
run_fresh:
type: "boolean"
default: false
required: ["task_id", "skill_names"]
================================================
FILE: apps/cheapclaw/assets/agent_library/CheapClawSupervisor/level_3_agents.yaml
================================================
tools:
supervisor_agent:
level: 3
type: llm_call_agent
available_tools:
- cheapclaw_read_panel
- cheapclaw_update_panel
- cheapclaw_read_social_history
- cheapclaw_send_message
- cheapclaw_send_file
- cheapclaw_start_task
- cheapclaw_add_task_message
- cheapclaw_get_task_status
- cheapclaw_list_agent_systems
- cheapclaw_schedule_plan
- cheapclaw_cancel_plan
- cheapclaw_reset_task
- cheapclaw_generate_task_id
- cheapclaw_list_conversation_tasks
- cheapclaw_list_global_skills
- cheapclaw_reveal_skills
- file_read
- task_share_context_path
- load_skill
- offload_skill
- fresh
- final_output
- execute_command
max_turns: 80
execution_model: openai/google/gemini-3-flash-preview
thinking_model: openai/google/gemini-3-flash-preview
compressor_model: openai/google/gemini-3-flash-preview
image_generation_model: openai/google/gemini-3-flash-preview
read_figure_model: openai/google/gemini-3-flash-preview
max_tokens: 0
action_window_steps: 20
thinking_interval: 20
prompts:
agent_responsibility: |
你是 CheapClaw 的总调度智能体。你负责会话消息判断、历史 task 路由、message_id 到 task_id 绑定、worker 派发、watchdog 处理和用户回执。你可以使用execute_command查看电脑的目录结构,安排 task_id。
agent_workflow: |
对每个 dirty conversation,先判断直接回复还是需要任务;如果是任务型消息,应先尽快发一条简短回执;然后必须先调用 cheapclaw_list_conversation_tasks,再结合 panel 和 social history 自己判断该继续哪个旧 task。若旧 task 正在运行,优先 cheapclaw_add_task_message;若旧 task 已停止但仍是同一工作,优先 cheapclaw_start_task(task_id=旧task_id);只有明确是新 deliverable 或并行分支时才新建 task_id。随后必须把相关 message_id 绑定到对应 task_id,并更新面板。
name: "supervisor_agent"
description: "CheapClaw 主调度智能体"
parameters:
type: "object"
properties:
task_id:
type: "string"
task_input:
type: "string"
required: ["task_id", "task_input"]
================================================
FILE: apps/cheapclaw/assets/agent_library/CheapClawWorkerGeneral/general_prompts.yaml
================================================
system_prompt_xml: |
<系统角色>
你是 CheapClawWorkerGeneral 系统中的后台 worker。你负责完成被分派给当前 task_id 的具体工作。
</系统角色>
<工作空间与路径>
你明确处在当前 task_id 对应的工作空间中。大多数文件类工具都应传相对路径;task_id 参数则必须是绝对路径。
你需要继承并利用同一 task_id 下积累的历史信息、share_context、history 和文件空间,而不是把每次补充消息都当成全新任务。
</工作空间与路径>
<连续任务语义>
当前 task 可能已经绑定多条用户消息,这些消息共同定义同一工作的连续需求变化。
你必须把最新用户消息与历史工作结果一起理解:
- 如果新消息是增量修改,就在现有成果上继续推进。
- 如果新消息修正了目标,要基于最新目标调整计划,但不要无故丢掉已有有效产出。
- 只有当当前 task 明显不适合承接该目标时,才在 final_output 中说明应由 supervisor 分叉新 task。
</连续任务语义>
<技能与扩展>
当前 task 只能看到被允许的 overlay skills。
如果你判断现有 skills 不够,可以:
1. 使用 cheapclaw_list_global_skills 查看主技能库
2. 使用 cheapclaw_reveal_skills 把需要的 skill 暴露给当前 task
3. 再 fresh 当前 task 继续工作
不要假设某个 skill 已经可见,先检查再揭开。
</技能与扩展>
<执行原则>
- 尽量复用当前 task 目录中的已有材料和中间结果。
- 长时间命令必须后台运行并写日志,不要把当前进程挂死。
- 需要外部命令时优先可恢复、可观察、可复用的方式。
- 如果你判断任务当前无法完成,应在 final_output 中明确说明阻塞点和建议,而不是无意义循环。
</执行原则>
<输出要求>
任务完成时必须使用 final_output。
output 中应说明:
- 完成了什么
- 最终文件路径
- 关键中间文件路径
- 若未完成,阻塞原因是什么
不要把大段文件内容直接粘贴进 output。
</输出要求>
================================================
FILE: apps/cheapclaw/assets/agent_library/CheapClawWorkerGeneral/level_0_tools.yaml
================================================
tools:
# ==================== 文件操作工具 ====================
file_read:
level: 0
type: tool_call_agent
name: "file_read"
description: "读取指定文本文件的内容。路径参数必须是相对于当前 workspace/task 根目录的相对路径,不要传绝对路径。可以读取单个或多个文件,也可以指定起始和结束行。默认返回带行号的 JSON 格式。警告:不要读取二进制文件(如 pdf、docx、图片等)。"
parameters:
type: "object"
properties:
path:
type: "array"
items:
type: "string"
description: "文件相对路径数组,基于当前 workspace/task 根目录解析。单个文件传 ['file.txt'],多个文件传 ['file1.txt', 'file2.txt']。不要传绝对路径;只允许读取文本文件,不要读取二进制文件。"
start_line:
type: "integer"
description: "读取起始行号(从1开始),可选。多文件模式下应用于所有文件。"
end_line:
type: "integer"
description: "读取结束行号(包含),可选。多文件模式下应用于所有文件。"
encoding:
type: "string"
description: "文件编码,可选。不指定时自动检测。"
show_line_numbers:
type: "boolean"
default: true
description: "是否显示行号。true 返回 JSON 格式(含行号),false 返回纯文本。默认 true。"
required: ["path"]
file_write:
level: 0
type: tool_call_agent
name: "file_write"
description: "向指定文本文件写入内容。path 必须是相对于当前 workspace/task 根目录的相对路径,不要传绝对路径。如果文件不存在会自动创建;如果存在可以选择覆盖或追加,也支持替换指定行。注意:禁止写入 reference.bib 文件,请使用专门的参考文献管理工具(reference_add/reference_delete)。"
parameters:
type: "object"
properties:
path:
type: "string"
description: "文件的相对路径,例如 'src/main.py',相对于当前 workspace/task 根目录解析。不要传绝对路径。写入前建议使用目录列表工具检查是否有同名文件,避免覆盖他人文件。禁止路径为 'reference.bib'。"
content:
type: "string"
description: "要写入的文本内容。"
mode:
type: "string"
enum: ["write", "append"]
default: "write"
description: "写入模式。'write' 覆盖整个文件,'append' 追加到文件末尾。"
start_line:
type: "integer"
description: "行替换模式 - 起始行号(从1开始),可选。"
end_line:
type: "integer"
description: "行替换模式 - 结束行号,可选。"
required: ["path", "content"]
dir_list:
level: 0
type: tool_call_agent
name: "dir_list"
description: "列出指定目录的内容。path 必须是相对于当前 workspace/task 根目录的相对路径;不传时默认列出任务根目录。可以递归列出所有子目录和文件(自动排除 code_env 目录)。"
parameters:
type: "object"
properties:
path:
type: "string"
default: "."
description: "要列出的目录相对路径,相对于当前 workspace/task 根目录解析。不指定时列出任务根目录。"
recursive:
type: "boolean"
default: false
description: "是否递归列出子目录,默认 false。"
required: []
dir_create:
level: 0
type: tool_call_agent
name: "dir_create"
description: "创建新目录。path 必须是相对于当前 workspace/task 根目录的相对路径。如果父目录不存在会自动创建。"
parameters:
type: "object"
properties:
path:
type: "string"
description: "要创建的目录相对路径,相对于当前 workspace/task 根目录解析。"
required: ["path"]
file_move:
level: 0
type: tool_call_agent
name: "file_move"
description: "移动或复制文件/目录。source 和 destination 都应使用相对于当前 workspace/task 根目录的相对路径,不要传绝对路径。"
parameters:
type: "object"
properties:
source:
# type: "string"
# description: "源文件或目录的相对路径。"
# path:
type: "array"
items:
type: "string"
description: "源文件或目录的相对路径组,相对于当前 workspace/task 根目录解析。可以单个或多个。"
destination:
type: "string"
description: "目标相对路径,相对于当前 workspace/task 根目录解析。"
copy:
type: "boolean"
default: false
description: "是否复制(保留原文件),默认 false(移动)。"
required: ["source", "destination"]
file_delete:
level: 0
type: tool_call_agent
name: "file_delete"
description: "删除指定的文件或目录。path 应使用相对于当前 workspace/task 根目录的相对路径,不要传绝对路径。"
parameters:
type: "object"
properties:
path:
type: "string"
description: "要删除的文件或目录的相对路径,相对于当前 workspace/task 根目录解析。"
required: ["path"]
# ==================== 网络工具 ====================
web_search:
level: 0
type: tool_call_agent
name: "web_search"
description: "使用 DuckDuckGo 进行网络搜索。结果会保存为 Markdown 格式。"
parameters:
type: "object"
properties:
query:
type: "string"
description: "搜索关键词或问题。"
max_results:
type: "integer"
default: 10
description: "返回的最大结果数,默认 10。"
save_path:
type: "string"
description: "保存搜索结果的相对路径(.md 文件),请保存在 temp/web_search目录中。"
required: ["query","save_path"]
google_scholar_search:
level: 0
type: tool_call_agent
name: "google_scholar_search"
description: "在 Google Scholar 上搜索学术论文。支持年份筛选和分页。搜索结果保存为 Markdown 文件。"
parameters:
type: "object"
properties:
query:
type: "string"
description: "搜索关键词或主题。"
year_low:
type: "integer"
description: "筛选论文的起始年份,可选。"
year_high:
type: "integer"
description: "筛选论文的结束年份,可选。"
pages:
type: "integer"
default: 1
description: "爬取的搜索结果页数,每页约10篇论文。"
save_path:
type: "string"
description: "保存搜索结果的相对路径(.md 文件)。请保存在 temp/scholar_search目录中。"
required: ["query","save_path"]
arxiv_search:
level: 0
type: tool_call_agent
name: "arxiv_search"
description: "搜索 arXiv 预印本论文库。返回论文标题、作者、摘要、PDF 下载地址等信息。"
parameters:
type: "object"
properties:
query:
type: "string"
description: "搜索关键词,例如 'transformer neural network'。"
max_results:
type: "integer"
default: 10
description: "返回的最大结果数,默认 10。"
sort_by:
type: "string"
enum: ["relevance", "lastUpdatedDate", "submittedDate"]
default: "relevance"
description: "排序方式:relevance(相关性)、lastUpdatedDate(更新时间)、submittedDate(提交时间)。"
sort_order:
type: "string"
enum: ["descending", "ascending"]
default: "descending"
description: "排序顺序:descending(降序)、ascending(升序)。"
save_path:
type: "string"
description: "保存搜索结果的相对路径(.md 文件)。请保存在 temp/arxiv_search目录中。"
required: ["query","save_path"]
crawl_page:
level: 0
type: tool_call_agent
name: "crawl_page"
description: "爬取指定 URL 的网页内容,转换为 Markdown 格式。使用 crawl4ai 智能提取。"
parameters:
type: "object"
properties:
url:
type: "string"
description: "要爬取的网页完整 URL。"
save_path:
type: "string"
description: "保存 Markdown 文件的相对路径,必选。不指定则直接返回内容。请保存在 temp/crawl_page目录中。"
download_images:
type: "boolean"
default: false
description: "是否下载图片,默认 false(移除图片)。"
required: ["url","save_path"]
file_download:
level: 0
type: tool_call_agent
name: "file_download"
description: "从 URL 下载文件到本地。"
parameters:
type: "object"
properties:
url:
type: "string"
description: "要下载的文件 URL。"
save_path:
type: "string"
description: "保存文件的相对路径,例如 'upload/file.pdf'。"
required: ["url", "save_path"]
# ==================== 参考文献管理工具 ====================
reference_list:
level: 0
type: tool_call_agent
name: "reference_list"
description: "列出 reference.bib 文件中的所有参考文献(显示原文)。"
parameters:
type: "object"
properties:
bib_path:
type: "string"
default: "reference.bib"
description: "bib文件相对路径,默认 'reference.bib'。"
required: []
reference_add:
level: 0
type: tool_call_agent
name: "reference_add"
description: "向 reference.bib 添加参考文献。如果引用键已存在则覆盖原有内容。"
parameters:
type: "object"
properties:
entries:
type: "array"
items:
type: "string"
description: "参考文献字符串数组,每个元素是一条完整的bib条目。例如:['@article{key1,...}', '@book{key2,...}']"
bib_path:
type: "string"
default: "reference.bib"
description: "bib文件相对路径,默认 'reference.bib'。"
required: ["entries"]
reference_delete:
level: 0
type: tool_call_agent
name: "reference_delete"
description: "从 reference.bib 删除指定的参考文献。"
parameters:
type: "object"
properties:
keys:
type: "array"
items:
type: "string"
description: "要删除的引用键(如 'sun2023blockchain')或引用键数组。"
bib_path:
type: "string"
default: "reference.bib"
description: "bib文件相对路径,默认 'reference.bib'。"
required: ["keys"]
# ==================== 文档处理工具 ====================
parse_document:
level: 0
type: tool_call_agent
name: "parse_document"
description: "解析二进制文档为纯文本文件,不提供总结,分析服务。支持 PDF、Word、Markdown 格式。"
parameters:
type: "object"
properties:
path:
type: "string"
description: "要解析的文档相对路径。"
save_path:
type: "string"
description: "保存解析结果的相对路径。请保存在 temp/parse_document目录中。"
required: ["path","save_path"]
vision_tool:
level: 0
type: tool_call_agent
name: "vision_tool"
description: "使用LLM Vision模型分析图片内容。可以识别图片中的内容、描述场景、回答问题等。"
parameters:
type: "object"
properties:
image_path:
type: "string"
description: "图片文件的相对路径(相对于任务目录)。"
question:
type: "string"
description: "要问的问题,例如'这是什么?'或'请描述图片中的内容'。不指定则默认描述图片内容。"
save_path:
type: "string"
description: "必选,保存结果的相对路径,保存为纯文本文件 md或者 txt。请保存在 temp/answer_figuers目录中。"
# model:
# type: "string"
# description: "要使用的模型名称,可选。不指定则使用配置中的默认模型。"
required: ["image_path","save_path"]
image_read:
level: 0
type: tool_call_agent
name: "image_read"
description: "读取并分析图片内容(支持同时读取多张)。如果主模型支持多模态,图片会直接嵌入到对话中由主模型分析;否则会调用 Vision LLM 进行分析并返回文字描述。适用于查看实验结果图表、分析截图、理解图片内容等场景。"
parameters:
type: "object"
properties:
image_paths:
type: "array"
items:
type: "string"
description: "图片文件相对路径数组(相对于任务目录)。读取单张图片传单元素数组,如 [\"result.png\"]。支持 jpg/jpeg/png/gif/webp/bmp 格式。"
query:
type: "string"
description: "关于图片的问题或分析要求,例如'这些图表显示了什么趋势?'。不指定则默认描述图片内容。"
save_path:
type: "string"
description: "可选,保存分析结果的相对路径(仅在 text-only 模式下有效)。"
required: ["image_paths"]
create_image:
level: 0
type: tool_call_agent
name: "create_image"
description: "根据提示词生成图片,或基于参考图进行图片编辑/融合/风格迁移。支持最多 14 张参考图(Gemini 3 Pro)。"
parameters:
type: "object"
properties:
prompt:
type: "string"
description: "图片的描述提示词或编辑指令。纯生成时描述要生成的图片;有参考图时描述如何处理参考图(如'融合这两张图'、'将第一张图转为梵高风格')。"
image_path:
type: "string"
description: "生成图片保存的相对路径(例如 'temp/generated_image.png')。"
reference_images:
type: "array"
items:
type: "string"
description: "参考图片相对路径列表,可选。用于图片编辑、风格迁移、多图融合等。不提供则为纯文本生成图片。"
size:
type: "string"
default: "1024x1024"
description: "生成图片尺寸,默认 '1024x1024'。支持 '1792x1024'(16:9)等。"
n:
type: "integer"
default: 1
description: "生成图片数量,默认 1。"
required: ["prompt", "image_path"]
audio_tool:
level: 0
type: tool_call_agent
name: "audio_tool"
description: "使用LLM Audio模型分析音频内容。可以识别音频中的内容、描述场景、回答问题等。支持 mp3、wav、m4a 等格式。"
parameters:
type: "object"
properties:
audio_path:
type: "string"
description: "音频文件的相对路径(相对于任务目录)。"
question:
type: "string"
description: "要问的问题,例如'这段音频讲了什么?'或'请描述音频内容'。不指定则默认描述音频内容。"
model:
type: "string"
description: "要使用的模型名称,可选。不指定则使用配置中的默认模型。"
required: ["audio_path"]
paper_analyze_tool:
level: 0
type: tool_call_agent
name: "paper_analyze_tool"
description: "解析论文文档并使用LLM分析论文内容。可以总结论文、回答关于论文的问题等。"
parameters:
type: "object"
properties:
paper_path:
type: "string"
description: "论文文件的相对路径(相对于任务目录),支持PDF、Word等格式。"
question:
type: "string"
description: "要问的问题,例如'这篇论文的主要贡献是什么?'不指定则默认总结论文内容。"
parse_save_path:
type: "string"
description: "保存解析结果的相对路径,可选。"
required: ["paper_path"]
md_to_pdf:
level: 0
type: tool_call_agent
name: "md_to_pdf"
description: "将 Markdown 文件转换为 PDF。支持数学公式、表格、中文。调用远程 Pandoc API 服务。"
parameters:
type: "object"
properties:
source_path:
type: "string"
description: "Markdown 源文件的相对路径。"
output_path:
type: "string"
description: "输出 PDF 文件的相对路径,可选。不指定则使用源文件名改后缀。"
engine:
type: "string"
enum: ["pdflatex", "xelatex", "lualatex"]
default: "xelatex"
description: "PDF 编译引擎。xelatex 支持中文(推荐),pdflatex 适合英文。"
required: ["source_path"]
md_to_docx:
level: 0
type: tool_call_agent
name: "md_to_docx"
description: "将 Markdown 文件转换为 Word 文档(.docx)。调用远程 Pandoc API 服务。"
parameters:
type: "object"
properties:
source_path:
type: "string"
description: "Markdown 源文件的相对路径。"
output_path:
type: "string"
description: "输出 DOCX 文件的相对路径,可选。不指定则使用源文件名改后缀。"
required: ["source_path"]
file_download:
level: 0
type: tool_call_agent
name: "file_download"
description: "从指定 URL 下载文件到本地。"
parameters:
type: "object"
properties:
url:
type: "string"
description: "要下载的文件 URL。"
save_path:
type: "string"
description: "保存文件的相对路径,例如 'upload/file.pdf'。"
required: ["url", "save_path"]
# ==================== 文档处理工具 ====================
# parse_document:
# level: 0
# type: tool_call_agent
# name: "parse_document"
# description: "解析文档文件并提取文本内容。支持 PDF、Word、Markdown 格式。使用 pdfplumber 高质量提取 PDF(包含表格)。"
# parameters:
# type: "object"
# properties:
# path:
# type: "string"
# description: "要解析的文档相对路径。"
# save_path:
# type: "string"
# description: "保存解析结果的相对路径,可选。不指定则直接返回内容。"
# required: ["path"]
md_to_pdf:
level: 0
type: tool_call_agent
name: "md_to_pdf"
description: "将 Markdown 文件转换为 PDF。支持数学公式、表格、中文。调用远程 Pandoc API 服务。"
parameters:
type: "object"
properties:
source_path:
type: "string"
description: "Markdown 源文件的相对路径。"
output_path:
type: "string"
description: "输出 PDF 文件的相对路径,可选。不指定则使用源文件名改后缀。"
engine:
type: "string"
enum: ["pdflatex", "xelatex", "lualatex"]
default: "xelatex"
description: "PDF 编译引擎。xelatex 支持中文(推荐),pdflatex 适合英文。"
required: ["source_path"]
md_to_docx:
level: 0
type: tool_call_agent
name: "md_to_docx"
description: "将 Markdown 文件转换为 Word 文档(.docx)。调用远程 Pandoc API 服务。"
parameters:
type: "object"
properties:
source_path:
type: "string"
description: "Markdown 源文件的相对路径。"
output_path:
type: "string"
description: "输出 DOCX 文件的相对路径,可选。不指定则使用源文件名改后缀。"
required: ["source_path"]
images_to_ppt:
level: 0
type: tool_call_agent
name: "images_to_ppt"
description: "将多张图片转换为 PowerPoint 演示文稿,每张图片占一页。PPT 尺寸自动根据第一张图片的宽高比设置,所有图片居中显示并保持比例。适合将多张图表、截图等快速制作成演示文稿。"
parameters:
type: "object"
properties:
image_paths:
type: "array"
items:
type: "string"
description: "图片文件相对路径列表,例如 ['chart1.png', 'chart2.png']。也可以是单个字符串。"
output_path:
type: "string"
description: "输出 PPT 文件的相对路径,例如 'presentation.pptx'。"
required: ["image_paths", "output_path"]
# ==================== 浏览器操作工具 ====================
browser_launch:
level: 0
type: tool_call_agent
name: "browser_launch"
description: "启动浏览器会话。默认打开有界面的浏览器窗口(非无头模式),创建第一个标签页 page_0。返回 browser_id 用于后续操作。会自动创建 temp/browser/{browser_id}/ 目录保存截图和页面内容。"
parameters:
type: "object"
properties:
headless:
type: "boolean"
default: false
description: "是否无头模式(不显示浏览器窗口),默认 false(显示窗口)。"
width:
type: "integer"
default: 1280
description: "浏览器窗口宽度(像素),默认 1280。"
height:
type: "integer"
default: 800
description: "浏览器窗口高度(像素),默认 800。"
required: []
browser_close:
level: 0
type: tool_call_agent
name: "browser_close"
description: "关闭浏览器会话。会关闭所有标签页并清理资源。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID(由 browser_launch 返回)。"
required: ["browser_id"]
browser_navigate:
level: 0
type: tool_call_agent
name: "browser_navigate"
description: "在当前活跃标签页导航到指定 URL。导航后自动截图并保存页面内容到 temp/browser/{browser_id}/current.png 和 page_content.md。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
url:
type: "string"
description: "目标 URL,例如 'https://www.example.com'。"
wait_until:
type: "string"
enum: ["load", "domcontentloaded", "networkidle"]
default: "load"
description: "等待条件:load(页面加载完成)、domcontentloaded(DOM加载完成)、networkidle(网络空闲)。默认 load。"
required: ["browser_id", "url"]
browser_snapshot:
level: 0
type: tool_call_agent
name: "browser_snapshot"
description: "获取当前活跃标签页的快照。更新截图和页面文本内容。返回页面标题、URL、截图路径。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
include_html:
type: "boolean"
default: false
description: "是否包含 HTML 源码,默认 false。如果为 true,会保存到 page_source.html。"
required: ["browser_id"]
browser_execute_js:
level: 0
type: tool_call_agent
name: "browser_execute_js"
description: "在当前活跃标签页执行 JavaScript 代码。这是最强大的浏览器操作工具,可以实现任意页面操作(点击、输入、滚动、提取数据等)。执行后自动截图。注意:JavaScript 代码必须是函数表达式,如 '() => { return document.title; }'。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
script:
type: "string"
description: "要执行的 JavaScript 代码。必须是函数表达式,如 '() => { ... }'。示例:'() => document.querySelector(\"#btn\").click()' 或 '() => { return Array.from(document.querySelectorAll(\".item\")).map(el => el.textContent); }'。"
save_result:
type: "boolean"
default: false
description: "是否将执行结果保存到 js_result.json 文件,默认 false。"
required: ["browser_id", "script"]
browser_new_page:
level: 0
type: tool_call_agent
name: "browser_new_page"
description: "在当前浏览器会话中新建一个标签页。新标签页会自动成为活跃页面。返回新的 page_id(如 page_1, page_2)。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
required: ["browser_id"]
browser_switch_page:
level: 0
type: tool_call_agent
name: "browser_switch_page"
description: "切换到指定的标签页,使其成为活跃页面。切换后会自动更新截图和页面内容。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
page_id:
type: "string"
description: "要切换到的页面ID,例如 'page_0', 'page_1'。可通过 browser_list_pages 查看所有页面。"
required: ["browser_id", "page_id"]
browser_close_page:
level: 0
type: tool_call_agent
name: "browser_close_page"
description: "关闭指定的标签页。如果关闭的是活跃页面,会自动切换到第一个页面。不能关闭唯一的标签页(至少保留一个)。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
page_id:
type: "string"
description: "要关闭的页面ID,例如 'page_1'。"
required: ["browser_id", "page_id"]
browser_list_pages:
level: 0
type: tool_call_agent
name: "browser_list_pages"
description: "列出当前浏览器会话的所有标签页。显示每个页面的 page_id、标题、URL、是否为活跃页面。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
required: ["browser_id"]
browser_click:
level: 0
type: tool_call_agent
name: "browser_click"
description: "点击当前页面的指定元素。使用 CSS 选择器定位元素。点击后自动截图。如果元素难以点击,建议使用 browser_execute_js 执行 JavaScript 点击。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
selector:
type: "string"
description: "CSS 选择器,例如 '#submit-btn', '.button', 'button[type=\"submit\"]'。"
timeout:
type: "integer"
default: 5000
description: "等待元素出现的超时时间(毫秒),默认 5000。"
required: ["browser_id", "selector"]
browser_type:
level: 0
type: tool_call_agent
name: "browser_type"
description: "在指定的输入框输入文本。使用 CSS 选择器定位输入框。输入后自动截图。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
selector:
type: "string"
description: "输入框的 CSS 选择器,例如 '#username', 'input[name=\"email\"]'。"
text:
type: "string"
description: "要输入的文本内容。"
clear_first:
type: "boolean"
default: true
description: "是否先清空输入框,默认 true。"
required: ["browser_id", "selector", "text"]
browser_wait:
level: 0
type: tool_call_agent
name: "browser_wait"
description: "等待指定条件满足。可以等待元素出现、页面导航完成或指定时间。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
wait_type:
type: "string"
enum: ["selector", "navigation", "timeout"]
description: "等待类型:selector(等待元素出现)、navigation(等待导航完成)、timeout(等待指定时间)。"
selector:
type: "string"
description: "CSS 选择器(wait_type='selector' 时必需)。"
timeout:
type: "integer"
default: 30000
description: "超时时间(毫秒),默认 30000。"
milliseconds:
type: "integer"
description: "等待时长(毫秒,wait_type='timeout' 时必需)。"
required: ["browser_id", "wait_type"]
browser_mouse_move:
level: 0
type: tool_call_agent
name: "browser_mouse_move"
description: "移动鼠标到指定坐标位置。支持人类化移动(贝塞尔曲线轨迹)模拟真实用户行为,避免人机验证检测。适用于需要精确控制鼠标位置的场景。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
x:
type: "number"
description: "目标 x 坐标(像素)。"
y:
type: "number"
description: "目标 y 坐标(像素)。"
human_like:
type: "boolean"
default: true
description: "是否使用人类化移动(贝塞尔曲线轨迹),默认 true。设为 false 则直接瞬移到目标位置。"
required: ["browser_id", "x", "y"]
browser_mouse_click_coords:
level: 0
type: tool_call_agent
name: "browser_mouse_click_coords"
description: "在指定坐标位置点击鼠标。支持左键/右键/中键、单击/双击、人类化点击(随机延迟和轨迹)。适用于动态元素、Canvas/SVG 区域、无法用选择器定位的元素。特别适合处理滑块验证码等场景。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
x:
type: "number"
description: "点击的 x 坐标(像素)。"
y:
type: "number"
description: "点击的 y 坐标(像素)。"
button:
type: "string"
enum: ["left", "right", "middle"]
default: "left"
description: "鼠标按钮:left(左键)、right(右键)、middle(中键),默认 left。"
click_count:
type: "integer"
default: 1
description: "点击次数,1为单击,2为双击,默认 1。"
human_like:
type: "boolean"
default: true
description: "是否使用人类化点击(贝塞尔曲线移动+随机延迟),默认 true。推荐在需要绕过人机验证时启用。"
required: ["browser_id", "x", "y"]
browser_drag_and_drop:
level: 0
type: tool_call_agent
name: "browser_drag_and_drop"
description: "执行鼠标拖拽操作,从起点拖动到终点。支持人类化拖拽(贝塞尔曲线轨迹+随机延迟)模拟真实用户行为。主要用于:1) 滑块验证码(重要!)2) 拖拽排序 3) 地图平移/缩放 4) 拖拽文件上传 5) 任何需要拖拽的交互。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
from_x:
type: "number"
description: "起始 x 坐标(像素)。"
from_y:
type: "number"
description: "起始 y 坐标(像素)。"
to_x:
type: "number"
description: "目标 x 坐标(像素)。"
to_y:
type: "number"
description: "目标 y 坐标(像素)。"
human_like:
type: "boolean"
default: true
description: "是否使用人类化拖拽(贝塞尔曲线轨迹+随机延迟),默认 true。强烈推荐在处理验证码时启用。"
required: ["browser_id", "from_x", "from_y", "to_x", "to_y"]
browser_hover:
level: 0
type: tool_call_agent
name: "browser_hover"
description: "鼠标悬停在元素或坐标上,停留指定时长。支持人类化移动。用于触发悬停菜单、查看 tooltip、触发延迟加载内容等场景。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
selector:
type: "string"
description: "要悬停的元素 CSS 选择器(selector 和坐标二选一)。"
x:
type: "number"
description: "悬停的 x 坐标(selector 和坐标二选一)。"
y:
type: "number"
description: "悬停的 y 坐标(selector 和坐标二选一)。"
duration_ms:
type: "integer"
default: 1000
description: "悬停持续时间(毫秒),默认 1000。"
human_like:
type: "boolean"
default: true
description: "是否使用人类化移动(贝塞尔曲线轨迹),默认 true。"
required: ["browser_id"]
browser_scroll:
level: 0
type: tool_call_agent
name: "browser_scroll"
description: "使用鼠标滚轮滚动页面或指定元素。支持平滑滚动模拟真实用户行为。可以滚动整个页面,也可以滚动指定元素(如滚动容器、iframe 等)。用于查看页面更多内容、触发懒加载、滚动到特定位置等场景。"
parameters:
type: "object"
properties:
browser_id:
type: "string"
description: "浏览器会话ID。"
delta_y:
type: "integer"
description: "垂直滚动距离(像素)。正数向下滚动,负数向上滚动。例如:500 向下滚动500像素,-300 向上滚动300像素。"
delta_x:
type: "integer"
default: 0
description: "水平滚动距离(像素),可选,默认 0。正数向右滚动,负数向左滚动。"
selector:
type: "string"
description: "要滚动的元素 CSS 选择器,可选。不指定则滚动整个页面。指定后会先移动鼠标到该元素,然后滚动该元素。"
smooth:
type: "boolean"
default: true
description: "是否平滑滚动(分多次小步滚动),默认 true。平滑滚动更像真实用户,但稍慢。"
human_like:
type: "boolean"
default: true
description: "是否先使用人类化移动鼠标到元素(仅在指定 selector 时有效),默认 true。"
required: ["browser_id", "delta_y"]
# ==================== 代码执行工具 ====================
execute_command:
level: 0
type: tool_call_agent
name: "execute_command"
description: "执行命令行命令。可选后台执行并将输出重定向到文件。"
parameters:
type: "object"
properties:
command:
type: "string"
description: "要执行的 shell 命令,例如 'ls -la'、'python script.py'、'pip install -r requirements.txt'。"
working_dir:
type: "string"
default: "."
description: "命令执行的工作目录相对路径,默认为任务根目录。"
timeout:
type: "integer"
default: 30
description: "命令执行超时时间(秒),默认 30。"
background:
type: "boolean"
default: false
description: "是否后台执行(不阻塞),默认 false。后台执行时必须指定 output_file。"
output_file:
type: "string"
description: "输出重定向到文件的相对路径。后台执行时必需,非后台执行时可选。"
required: ["command"]
grep:
level: 0
type: tool_call_agent
name: "grep"
description: "在文件中搜索匹配的文本模式(跨平台纯Python实现,支持正则表达式)。可以搜索指定目录或文件,支持递归搜索和文件类型过滤。"
parameters:
type: "object"
properties:
pattern:
type: "string"
description: "要搜索的正则表达式模式,例如 'def.*function' 或 'TODO'。"
search_path:
type: "string"
default: "."
description: "搜索路径相对路径,默认为当前工作区根目录。"
file_pattern:
type: "string"
default: "*"
description: "文件名匹配模式(支持通配符),如 '*.py'、'*.txt'、'*.md' 等。默认匹配所有文件。"
recursive:
type: "boolean"
default: true
description: "是否递归搜索子目录,默认 true。"
case_sensitive:
type: "boolean"
default: true
description: "是否大小写敏感,默认 true。"
show_line_number:
type: "boolean"
default: true
description: "是否显示行号,默认 true。"
max_results:
type: "integer"
default: 100
description: "最大结果数量,默认 100。"
context_lines:
type: "integer"
default: 0
description: "显示匹配行前后的上下文行数,默认 0(不显示上下文)。"
required: ["pattern"]
# ==================== Skill 工具 ====================
load_skill:
level: 0
type: tool_call_agent
name: "load_skill"
description: "将指定的 Agent Skill 从全局技能库部署到当前 workspace 的 .skills/ 目录,并把对应 SKILL.md 注入当前上下文。部署后可通过 execute_command 运行技能包含的脚本。"
parameters:
type: "object"
properties:
skill_name:
type: "string"
description: "要部署的 skill 名称,对应 <available_skills> 中列出的 name。"
required: ["skill_name"]
offload_skill:
level: 0
type: tool_call_agent
name: "offload_skill"
description: "从当前上下文中卸载某个已加载 skill 的 SKILL.md 内容,但不删除磁盘上的 .skills 文件。"
parameters:
type: "object"
properties:
skill_name:
type: "string"
description: "要从当前上下文中卸载的 skill 名称。"
required: ["skill_name"]
fresh:
level: 0
type: tool_call_agent
name: "fresh"
description: "在安全点刷新运行时配置、工具注册、skills 与提示词缓存。默认刷新当前 task;若指定 task_id,则刷新对应 task。这里的 task_id 应为绝对路径。仅当你刚创建/安装了新工具或新 skills 时才使用。"
parameters:
type: "object"
properties:
reason:
type: "string"
description: "触发 fresh 的原因说明,例如“刚安装了新工具”或“刚安装了新 skill”。"
task_id:
type: "string"
description: "可选。目标任务的 task_id,必须是绝对路径。省略时 fresh 当前任务;指定后会 fresh 对应任务,若该任务未在运行则会重载配置并后台 resume。"
add_message:
level: 0
type: tool_call_agent
name: "add_message"
description: "向指定 task 的 current.instructions 追加一条新消息。若目标 task 正在运行,它会在下一轮看到这条消息;若未运行,可选择后台 resume。task_id 应为绝对路径;省略时默认当前 task。适合对同一任务做需求补充或变更。"
parameters:
type: "object"
properties:
task_id:
type: "string"
description: "可选。目标任务的 task_id,必须是绝对路径。省略时默认当前 task。"
message:
type: "string"
description: "要追加给该 task 的消息内容。"
source:
type: "string"
description: "消息来源标记,例如 agent / user / system。默认 agent。"
resume_if_needed:
type: "boolean"
default: false
description: "当目标 task 当前未运行时,是否在追加消息后后台 resume。默认 false。"
required: ["message"]
start_background_task:
level: 0
type: tool_call_agent
name: "start_background_task"
description: "后台启动一个新的 task 进程。适合把独立子任务交给另一个 workspace/task 在后台异步运行。"
parameters:
type: "object"
properties:
task_id:
type: "string"
description: "必需。新任务的 task_id,建议使用绝对路径作为 workspace。"
user_input:
type: "string"
description: "必需。新任务的需求描述。"
agent_system:
type: "string"
description: "可选。Agent system,默认 OpenCowork。"
agent_name:
type: "string"
description: "可选。启动的 agent 名称,默认 alpha_agent。"
force_new:
type: "boolean"
default: false
description: "是否强制清空该 task 的旧状态后再启动。"
direct_tools:
type: "boolean"
default: true
description: "是否启用 direct-tools。默认 true。"
config:
type: "object"
description: "可选。类似 SDK 的运行配置。当前支持 llm_config_path、user_data_root、agent_library_dir/library_dir、skills_dir、tools_dir、action_window_steps、thinking_interval、fresh_enabled、fresh_interval_sec、mcp_servers、auto_mode、force_new、direct_tools。"
required: ["task_id", "user_input"]
task_share_context_path:
level: 0
type: tool_call_agent
name: "task_share_context_path"
description: "返回指定 task 的 share_context 和 stack 文件路径,不直接返回内容。task_id 应为绝对路径;拿到路径后,如有需要请再自行读取。"
parameters:
type: "object"
properties:
task_id:
type: "string"
description: "可选。目标任务的 task_id,必须是绝对路径。省略时默认当前 task。"
required: []
list_task_ids:
level: 0
type: tool_call_agent
name: "list_task_ids"
description: "列出当前已知的 task_id 列表,来源于 share_context 持久化记录。可选只返回当前运行中的 task。"
parameters:
type: "object"
properties:
only_running:
type: "boolean"
default: false
description: "是否只返回当前运行中的 task。默认 false。"
required: []
# ==================== 框架必需工具 ====================
final_output:
level: 0
type: tool_call_agent
name: "final_output"
description: "智能体输出最终结果的工具。当智能体完成任务或需要终止执行时调用此工具。"
parameters:
type: "object"
properties:
task_id:
type: "string"
description: "任务的唯一ID。"
status:
type: "string"
enum: ["success", "error"]
description: "任务执行状态:'success' 表示成功完成,'error' 表示执行失败。"
output:
type: "string"
description: "成功或失败的说明。如果输出包含文件,必须提供文件的相对路径和描述(不要重复文件中已有的内容),并包含 judge agent 的反馈。"
error_information:
type: "string"
description: "错误信息,仅在 status 为 'error' 时必需。"
required: ["task_id", "status", "output"]
cheapclaw_read_panel:
level: 0
type: tool_call_agent
name: "cheapclaw_read_panel"
description: "读取 CheapClaw 消息面板。可只读取 dirty 会话,或读取指定 channel / conversation_id 的会话。当你需要完整 message_task_bindings、context_summary_path 或完整 linked_tasks 时使用。"
parameters:
type: "object"
properties:
only_dirty:
type: "boolean"
default: false
description: "是否只返回 dirty=true 的 conversations。"
channel:
type: "string"
description: "渠道名,例如 telegram / feishu / whatsapp。"
conversation_id:
type: "string"
description: "会话稳定 ID。"
required: []
cheapclaw_update_panel:
level: 0
type: tool_call_agent
name: "cheapclaw_update_panel"
description: "CheapClaw 面板的兜底修正工具。大多数消息写入、task 启动/完成、message_id 绑定、dirty 清理应由系统自动完成;只有当你需要补写 last_reply_summary、手动修正绑定关系、追加特殊 pending_event,或纠正异常状态时才使用它。该工具只返回是否成功和执行了哪些操作,不返回整块 panel。"
parameters:
type: "object"
properties:
channel:
type: "string"
description: "渠道名。"
conversation_i
gitextract__7wj7h3m/
├── .dockerignore
├── .gitignore
├── Dockerfile
├── LICENSE
├── MANIFEST.in
├── README.md
├── README_CN.md
├── apps/
│ ├── __init__.py
│ └── cheapclaw/
│ ├── README.md
│ ├── __init__.py
│ ├── assets/
│ │ ├── agent_library/
│ │ │ ├── CheapClawSupervisor/
│ │ │ │ ├── general_prompts.yaml
│ │ │ │ ├── level_0_tools.yaml
│ │ │ │ └── level_3_agents.yaml
│ │ │ └── CheapClawWorkerGeneral/
│ │ │ ├── general_prompts.yaml
│ │ │ ├── level_0_tools.yaml
│ │ │ └── level_3_agents.yaml
│ │ └── config/
│ │ ├── app_config.example.json
│ │ ├── channels.example.json
│ │ └── llm_config_example.yaml
│ ├── cheapclaw_hooks.py
│ ├── cheapclaw_service.py
│ ├── skills/
│ │ ├── cheapclaw-watchdog/
│ │ │ └── SKILL.md
│ │ └── find-skills/
│ │ └── SKILL.md
│ ├── tool_runtime_helpers.py
│ ├── tools_library/
│ │ ├── cheapclaw_add_task_message/
│ │ │ └── cheapclaw_add_task_message.py
│ │ ├── cheapclaw_cancel_plan/
│ │ │ └── cheapclaw_cancel_plan.py
│ │ ├── cheapclaw_generate_task_id/
│ │ │ └── cheapclaw_generate_task_id.py
│ │ ├── cheapclaw_get_task_status/
│ │ │ └── cheapclaw_get_task_status.py
│ │ ├── cheapclaw_list_agent_systems/
│ │ │ └── cheapclaw_list_agent_systems.py
│ │ ├── cheapclaw_list_conversation_tasks/
│ │ │ └── cheapclaw_list_conversation_tasks.py
│ │ ├── cheapclaw_list_global_skills/
│ │ │ └── cheapclaw_list_global_skills.py
│ │ ├── cheapclaw_read_panel/
│ │ │ └── cheapclaw_read_panel.py
│ │ ├── cheapclaw_read_social_history/
│ │ │ └── cheapclaw_read_social_history.py
│ │ ├── cheapclaw_reset_task/
│ │ │ └── cheapclaw_reset_task.py
│ │ ├── cheapclaw_reveal_skills/
│ │ │ └── cheapclaw_reveal_skills.py
│ │ ├── cheapclaw_schedule_plan/
│ │ │ └── cheapclaw_schedule_plan.py
│ │ ├── cheapclaw_send_file/
│ │ │ └── cheapclaw_send_file.py
│ │ ├── cheapclaw_send_message/
│ │ │ └── cheapclaw_send_message.py
│ │ ├── cheapclaw_start_task/
│ │ │ └── cheapclaw_start_task.py
│ │ └── cheapclaw_update_panel/
│ │ └── cheapclaw_update_panel.py
│ └── web/
│ └── dashboard.html
├── backend_build/
│ ├── build_mac_universal.sh
│ └── pyinstaller_backend.spec
├── config/
│ ├── agent_library/
│ │ ├── OpenCowork/
│ │ │ ├── general_prompts.yaml
│ │ │ ├── level_-1_judge_agent.yaml
│ │ │ ├── level_0_tools.yaml
│ │ │ └── level_3_agents.yaml
│ │ └── Researcher/
│ │ ├── general_prompts.yaml
│ │ ├── level_-1_judge_agent.yaml
│ │ ├── level_0_tools.yaml
│ │ ├── level_1_agents.yaml
│ │ ├── level_2_agents.yaml
│ │ └── level_3_agents.yaml
│ └── run_env_config/
│ ├── ali_qwen_llm_config.yaml
│ ├── document_convert_api.yaml
│ ├── gemini_config_version.yaml
│ ├── kimi_config_version copy.yaml
│ ├── llm_config.example.yaml
│ └── third_part_api.yaml
├── core/
│ ├── __init__.py
│ ├── agent_event_emitter.py
│ ├── agent_executor.py
│ ├── context_builder.py
│ ├── event_handlers.py
│ ├── events.py
│ ├── hierarchy_manager.py
│ ├── runtime_exceptions.py
│ ├── state_cleaner.py
│ └── tool_executor.py
├── desktop_app/
│ ├── package.json
│ └── src/
│ ├── index.html
│ ├── main.js
│ ├── preload.js
│ ├── renderer.js
│ ├── styles.css
│ └── test_e.js
├── docker/
│ └── entrypoint.sh
├── docs/
│ ├── CHEAPCLAW_GUIDE.md
│ ├── CHEAPCLAW_IMPLEMENTATION_PLAN.md
│ ├── CLI_GUIDE.md
│ ├── DOCKER_GUIDE.md
│ ├── EVENT_SCHEMA.md
│ └── SDK_GUIDE.md
├── infiagent/
│ ├── __init__.py
│ └── sdk.py
├── marketplace_server/
│ ├── README.md
│ ├── app.py
│ ├── deploy_market.sh
│ ├── infiagent-market.service
│ ├── nginx_infiagent_market.conf
│ └── requirements.txt
├── pyproject.toml
├── requirements.txt
├── services/
│ ├── __init__.py
│ ├── action_compressor.py
│ ├── context_compressor_backup.py
│ ├── llm_client.py
│ └── thinking_agent.py
├── setup.py
├── skills/
│ ├── algorithmic-art/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── templates/
│ │ ├── generator_template.js
│ │ └── viewer.html
│ ├── brand-guidelines/
│ │ ├── LICENSE.txt
│ │ └── SKILL.md
│ ├── canvas-design/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── canvas-fonts/
│ │ ├── ArsenalSC-OFL.txt
│ │ ├── BigShoulders-OFL.txt
│ │ ├── Boldonse-OFL.txt
│ │ ├── BricolageGrotesque-OFL.txt
│ │ ├── CrimsonPro-OFL.txt
│ │ ├── DMMono-OFL.txt
│ │ ├── EricaOne-OFL.txt
│ │ ├── GeistMono-OFL.txt
│ │ ├── Gloock-OFL.txt
│ │ ├── IBMPlexMono-OFL.txt
│ │ ├── InstrumentSans-OFL.txt
│ │ ├── Italiana-OFL.txt
│ │ ├── JetBrainsMono-OFL.txt
│ │ ├── Jura-OFL.txt
│ │ ├── LibreBaskerville-OFL.txt
│ │ ├── Lora-OFL.txt
│ │ ├── NationalPark-OFL.txt
│ │ ├── NothingYouCouldDo-OFL.txt
│ │ ├── Outfit-OFL.txt
│ │ ├── PixelifySans-OFL.txt
│ │ ├── PoiretOne-OFL.txt
│ │ ├── RedHatMono-OFL.txt
│ │ ├── Silkscreen-OFL.txt
│ │ ├── SmoochSans-OFL.txt
│ │ ├── Tektur-OFL.txt
│ │ ├── WorkSans-OFL.txt
│ │ └── YoungSerif-OFL.txt
│ ├── doc-coauthoring/
│ │ └── SKILL.md
│ ├── docx/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── scripts/
│ │ ├── __init__.py
│ │ ├── accept_changes.py
│ │ ├── comment.py
│ │ ├── office/
│ │ │ ├── helpers/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── merge_runs.py
│ │ │ │ └── simplify_redlines.py
│ │ │ ├── pack.py
│ │ │ ├── schemas/
│ │ │ │ ├── ISO-IEC29500-4_2016/
│ │ │ │ │ ├── dml-chart.xsd
│ │ │ │ │ ├── dml-chartDrawing.xsd
│ │ │ │ │ ├── dml-diagram.xsd
│ │ │ │ │ ├── dml-lockedCanvas.xsd
│ │ │ │ │ ├── dml-main.xsd
│ │ │ │ │ ├── dml-picture.xsd
│ │ │ │ │ ├── dml-spreadsheetDrawing.xsd
│ │ │ │ │ ├── dml-wordprocessingDrawing.xsd
│ │ │ │ │ ├── pml.xsd
│ │ │ │ │ ├── shared-additionalCharacteristics.xsd
│ │ │ │ │ ├── shared-bibliography.xsd
│ │ │ │ │ ├── shared-commonSimpleTypes.xsd
│ │ │ │ │ ├── shared-customXmlDataProperties.xsd
│ │ │ │ │ ├── shared-customXmlSchemaProperties.xsd
│ │ │ │ │ ├── shared-documentPropertiesCustom.xsd
│ │ │ │ │ ├── shared-documentPropertiesExtended.xsd
│ │ │ │ │ ├── shared-documentPropertiesVariantTypes.xsd
│ │ │ │ │ ├── shared-math.xsd
│ │ │ │ │ ├── shared-relationshipReference.xsd
│ │ │ │ │ ├── sml.xsd
│ │ │ │ │ ├── vml-main.xsd
│ │ │ │ │ ├── vml-officeDrawing.xsd
│ │ │ │ │ ├── vml-presentationDrawing.xsd
│ │ │ │ │ ├── vml-spreadsheetDrawing.xsd
│ │ │ │ │ ├── vml-wordprocessingDrawing.xsd
│ │ │ │ │ ├── wml.xsd
│ │ │ │ │ └── xml.xsd
│ │ │ │ ├── ecma/
│ │ │ │ │ └── fouth-edition/
│ │ │ │ │ ├── opc-contentTypes.xsd
│ │ │ │ │ ├── opc-coreProperties.xsd
│ │ │ │ │ ├── opc-digSig.xsd
│ │ │ │ │ └── opc-relationships.xsd
│ │ │ │ ├── mce/
│ │ │ │ │ └── mc.xsd
│ │ │ │ └── microsoft/
│ │ │ │ ├── wml-2010.xsd
│ │ │ │ ├── wml-2012.xsd
│ │ │ │ ├── wml-2018.xsd
│ │ │ │ ├── wml-cex-2018.xsd
│ │ │ │ ├── wml-cid-2016.xsd
│ │ │ │ ├── wml-sdtdatahash-2020.xsd
│ │ │ │ └── wml-symex-2015.xsd
│ │ │ ├── soffice.py
│ │ │ ├── unpack.py
│ │ │ ├── validate.py
│ │ │ └── validators/
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── docx.py
│ │ │ ├── pptx.py
│ │ │ └── redlining.py
│ │ └── templates/
│ │ ├── comments.xml
│ │ ├── commentsExtended.xml
│ │ ├── commentsExtensible.xml
│ │ ├── commentsIds.xml
│ │ └── people.xml
│ ├── frontend-design/
│ │ ├── LICENSE.txt
│ │ └── SKILL.md
│ ├── internal-comms/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── examples/
│ │ ├── 3p-updates.md
│ │ ├── company-newsletter.md
│ │ ├── faq-answers.md
│ │ └── general-comms.md
│ ├── mac-use/
│ │ ├── SKILL.md
│ │ ├── requirements.txt
│ │ └── scripts/
│ │ └── mac_use.py
│ ├── mcp-builder/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ ├── reference/
│ │ │ ├── evaluation.md
│ │ │ ├── mcp_best_practices.md
│ │ │ ├── node_mcp_server.md
│ │ │ └── python_mcp_server.md
│ │ └── scripts/
│ │ ├── connections.py
│ │ ├── evaluation.py
│ │ ├── example_evaluation.xml
│ │ └── requirements.txt
│ ├── pdf/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ ├── forms.md
│ │ ├── reference.md
│ │ └── scripts/
│ │ ├── check_bounding_boxes.py
│ │ ├── check_fillable_fields.py
│ │ ├── convert_pdf_to_images.py
│ │ ├── create_validation_image.py
│ │ ├── extract_form_field_info.py
│ │ ├── extract_form_structure.py
│ │ ├── fill_fillable_fields.py
│ │ └── fill_pdf_form_with_annotations.py
│ ├── pptx/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ ├── editing.md
│ │ ├── pptxgenjs.md
│ │ └── scripts/
│ │ ├── __init__.py
│ │ ├── add_slide.py
│ │ ├── clean.py
│ │ ├── office/
│ │ │ ├── helpers/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── merge_runs.py
│ │ │ │ └── simplify_redlines.py
│ │ │ ├── pack.py
│ │ │ ├── schemas/
│ │ │ │ ├── ISO-IEC29500-4_2016/
│ │ │ │ │ ├── dml-chart.xsd
│ │ │ │ │ ├── dml-chartDrawing.xsd
│ │ │ │ │ ├── dml-diagram.xsd
│ │ │ │ │ ├── dml-lockedCanvas.xsd
│ │ │ │ │ ├── dml-main.xsd
│ │ │ │ │ ├── dml-picture.xsd
│ │ │ │ │ ├── dml-spreadsheetDrawing.xsd
│ │ │ │ │ ├── dml-wordprocessingDrawing.xsd
│ │ │ │ │ ├── pml.xsd
│ │ │ │ │ ├── shared-additionalCharacteristics.xsd
│ │ │ │ │ ├── shared-bibliography.xsd
│ │ │ │ │ ├── shared-commonSimpleTypes.xsd
│ │ │ │ │ ├── shared-customXmlDataProperties.xsd
│ │ │ │ │ ├── shared-customXmlSchemaProperties.xsd
│ │ │ │ │ ├── shared-documentPropertiesCustom.xsd
│ │ │ │ │ ├── shared-documentPropertiesExtended.xsd
│ │ │ │ │ ├── shared-documentPropertiesVariantTypes.xsd
│ │ │ │ │ ├── shared-math.xsd
│ │ │ │ │ ├── shared-relationshipReference.xsd
│ │ │ │ │ ├── sml.xsd
│ │ │ │ │ ├── vml-main.xsd
│ │ │ │ │ ├── vml-officeDrawing.xsd
│ │ │ │ │ ├── vml-presentationDrawing.xsd
│ │ │ │ │ ├── vml-spreadsheetDrawing.xsd
│ │ │ │ │ ├── vml-wordprocessingDrawing.xsd
│ │ │ │ │ ├── wml.xsd
│ │ │ │ │ └── xml.xsd
│ │ │ │ ├── ecma/
│ │ │ │ │ └── fouth-edition/
│ │ │ │ │ ├── opc-contentTypes.xsd
│ │ │ │ │ ├── opc-coreProperties.xsd
│ │ │ │ │ ├── opc-digSig.xsd
│ │ │ │ │ └── opc-relationships.xsd
│ │ │ │ ├── mce/
│ │ │ │ │ └── mc.xsd
│ │ │ │ └── microsoft/
│ │ │ │ ├── wml-2010.xsd
│ │ │ │ ├── wml-2012.xsd
│ │ │ │ ├── wml-2018.xsd
│ │ │ │ ├── wml-cex-2018.xsd
│ │ │ │ ├── wml-cid-2016.xsd
│ │ │ │ ├── wml-sdtdatahash-2020.xsd
│ │ │ │ └── wml-symex-2015.xsd
│ │ │ ├── soffice.py
│ │ │ ├── unpack.py
│ │ │ ├── validate.py
│ │ │ └── validators/
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── docx.py
│ │ │ ├── pptx.py
│ │ │ └── redlining.py
│ │ └── thumbnail.py
│ ├── slack-gif-creator/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ ├── core/
│ │ │ ├── easing.py
│ │ │ ├── frame_composer.py
│ │ │ ├── gif_builder.py
│ │ │ └── validators.py
│ │ └── requirements.txt
│ ├── theme-factory/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── themes/
│ │ ├── arctic-frost.md
│ │ ├── botanical-garden.md
│ │ ├── desert-rose.md
│ │ ├── forest-canopy.md
│ │ ├── golden-hour.md
│ │ ├── midnight-galaxy.md
│ │ ├── modern-minimalist.md
│ │ ├── ocean-depths.md
│ │ ├── sunset-boulevard.md
│ │ └── tech-innovation.md
│ ├── web-artifacts-builder/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ └── scripts/
│ │ ├── bundle-artifact.sh
│ │ └── init-artifact.sh
│ ├── webapp-testing/
│ │ ├── LICENSE.txt
│ │ ├── SKILL.md
│ │ ├── examples/
│ │ │ ├── console_logging.py
│ │ │ ├── element_discovery.py
│ │ │ └── static_html_automation.py
│ │ └── scripts/
│ │ └── with_server.py
│ └── xlsx/
│ ├── LICENSE.txt
│ ├── SKILL.md
│ └── scripts/
│ ├── office/
│ │ ├── helpers/
│ │ │ ├── __init__.py
│ │ │ ├── merge_runs.py
│ │ │ └── simplify_redlines.py
│ │ ├── pack.py
│ │ ├── schemas/
│ │ │ ├── ISO-IEC29500-4_2016/
│ │ │ │ ├── dml-chart.xsd
│ │ │ │ ├── dml-chartDrawing.xsd
│ │ │ │ ├── dml-diagram.xsd
│ │ │ │ ├── dml-lockedCanvas.xsd
│ │ │ │ ├── dml-main.xsd
│ │ │ │ ├── dml-picture.xsd
│ │ │ │ ├── dml-spreadsheetDrawing.xsd
│ │ │ │ ├── dml-wordprocessingDrawing.xsd
│ │ │ │ ├── pml.xsd
│ │ │ │ ├── shared-additionalCharacteristics.xsd
│ │ │ │ ├── shared-bibliography.xsd
│ │ │ │ ├── shared-commonSimpleTypes.xsd
│ │ │ │ ├── shared-customXmlDataProperties.xsd
│ │ │ │ ├── shared-customXmlSchemaProperties.xsd
│ │ │ │ ├── shared-documentPropertiesCustom.xsd
│ │ │ │ ├── shared-documentPropertiesExtended.xsd
│ │ │ │ ├── shared-documentPropertiesVariantTypes.xsd
│ │ │ │ ├── shared-math.xsd
│ │ │ │ ├── shared-relationshipReference.xsd
│ │ │ │ ├── sml.xsd
│ │ │ │ ├── vml-main.xsd
│ │ │ │ ├── vml-officeDrawing.xsd
│ │ │ │ ├── vml-presentationDrawing.xsd
│ │ │ │ ├── vml-spreadsheetDrawing.xsd
│ │ │ │ ├── vml-wordprocessingDrawing.xsd
│ │ │ │ ├── wml.xsd
│ │ │ │ └── xml.xsd
│ │ │ ├── ecma/
│ │ │ │ └── fouth-edition/
│ │ │ │ ├── opc-contentTypes.xsd
│ │ │ │ ├── opc-coreProperties.xsd
│ │ │ │ ├── opc-digSig.xsd
│ │ │ │ └── opc-relationships.xsd
│ │ │ ├── mce/
│ │ │ │ └── mc.xsd
│ │ │ └── microsoft/
│ │ │ ├── wml-2010.xsd
│ │ │ ├── wml-2012.xsd
│ │ │ ├── wml-2018.xsd
│ │ │ ├── wml-cex-2018.xsd
│ │ │ ├── wml-cid-2016.xsd
│ │ │ ├── wml-sdtdatahash-2020.xsd
│ │ │ └── wml-symex-2015.xsd
│ │ ├── soffice.py
│ │ ├── unpack.py
│ │ ├── validate.py
│ │ └── validators/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── docx.py
│ │ ├── pptx.py
│ │ └── redlining.py
│ └── recalc.py
├── start.py
├── tests/
│ ├── image_read.py
│ ├── llm_config_dummy.yaml
│ ├── test_cheapclaw_service.py
│ ├── test_code_tools_system_terminal.py
│ ├── test_context_hooks.py
│ ├── test_file_tools.py
│ ├── test_image_read_message.py
│ ├── test_kimi_stream_compat.py
│ ├── test_llm_client_lite_openrouter.py
│ ├── test_llm_client_resilience.py
│ ├── test_llm_config_builder.py
│ ├── test_llm_debug_output.py
│ ├── test_reasoning_modes.py
│ ├── test_sdk_observability.py
│ ├── test_sdk_runtime_paths.py
│ ├── test_task_history_index.py
│ ├── test_thinking_prompt_contract.py
│ ├── test_tool_hooks.py
│ └── test_web_ui_config_api.py
├── tool_server_lite/
│ ├── __init__.py
│ ├── llm_client_lite.py
│ ├── registry.py
│ ├── requirements.txt
│ └── tools/
│ ├── BROWSER_IMPROVEMENTS.md
│ ├── FILE_READ_USAGE.md
│ ├── __init__.py
│ ├── arxiv_tools.py
│ ├── audio_tools.py
│ ├── browser_tools.py
│ ├── code_tools.py
│ ├── convert_tools.py
│ ├── document_tools.py
│ ├── file_tools.py
│ ├── human_tools.py
│ ├── paper_tools.py
│ ├── powerpoint_tools.py
│ ├── reference_tools.py
│ ├── skill_tools.py
│ ├── task_tools.py
│ ├── vision_tools.py
│ └── web_tools.py
├── utils/
│ ├── __init__.py
│ ├── cli_mode.py
│ ├── config_loader.py
│ ├── config_manager.py
│ ├── context_hooks.py
│ ├── conversation_storage.py
│ ├── event_emitter.py
│ ├── llm_config_builder.py
│ ├── mcp_manager.py
│ ├── runtime_control.py
│ ├── skill_loader.py
│ ├── task_history_index.py
│ ├── task_runtime.py
│ ├── tool_hooks.py
│ ├── user_paths.py
│ └── windows_compat.py
└── web_ui/
├── README.md
├── index.html
├── login.html
├── requirements.txt
├── server/
│ ├── output_capture.py
│ ├── sdk_worker.py
│ ├── server
│ ├── server.py
│ ├── songmiao/
│ │ ├── test/
│ │ │ └── chat_history.json
│ │ └── test1/
│ │ ├── chat_history.json
│ │ └── reference.bib
│ ├── start.sh
│ ├── stop.sh
│ ├── user_accounts.py
│ ├── user_runtime.py
│ └── users.yaml
├── static/
│ ├── app.js
│ └── style.css
├── web_intro.md
└── web_intro_CN.md
SYMBOL INDEX (1779 symbols across 147 files)
FILE: apps/cheapclaw/cheapclaw_hooks.py
function on_tool_event (line 21) | def on_tool_event(payload: Dict[str, Any]) -> None:
FILE: apps/cheapclaw/cheapclaw_service.py
function _tail_text (line 104) | def _tail_text(path: Path, max_chars: int = 4000) -> str:
function _atomic_write_text (line 114) | def _atomic_write_text(path: Path, content: str) -> None:
function _log (line 126) | def _log(message: str) -> None:
function _load_json (line 139) | def _load_json(path: Path, default: Any) -> Any:
function _load_cheapclaw_app_config_example (line 146) | def _load_cheapclaw_app_config_example() -> Dict[str, Any]:
function _extract_cheapclaw_settings (line 169) | def _extract_cheapclaw_settings(payload: Dict[str, Any]) -> Dict[str, Any]:
class CheapClawPaths (line 190) | class CheapClawPaths:
method from_user_data_root (line 212) | def from_user_data_root(cls, user_data_root: str | Path, app_name: str...
class CheapClawPanelStore (line 241) | class CheapClawPanelStore:
method __init__ (line 242) | def __init__(self, paths: CheapClawPaths, history_preview_limit: int =...
method ensure_layout (line 248) | def ensure_layout(self) -> None:
method _file_lock (line 289) | def _file_lock(self):
method load_panel (line 301) | def load_panel(self) -> Dict[str, Any]:
method save_panel (line 304) | def save_panel(self, panel: Dict[str, Any], *, backup: bool = True) ->...
method mutate (line 310) | def mutate(self, updater: Callable[[Dict[str, Any]], Dict[str, Any] | ...
method _write_panel_locked (line 319) | def _write_panel_locked(self, panel: Dict[str, Any], *, backup: bool) ...
method _normalize_panel (line 326) | def _normalize_panel(self, panel: Dict[str, Any]) -> Dict[str, Any]:
method _normalize_conversation (line 353) | def _normalize_conversation(self, channel: str, conversation_id: str, ...
method dirty_conversations (line 419) | def dirty_conversations(self) -> List[Dict[str, Any]]:
method record_social_message (line 428) | def record_social_message(self, **kwargs) -> Dict[str, Any]:
method set_main_agent_state (line 474) | def set_main_agent_state(self, *, running: bool, run_id: str = "", mar...
method mark_watchdog_tick (line 489) | def mark_watchdog_tick(self) -> Dict[str, Any]:
class ChannelAdapter (line 496) | class ChannelAdapter:
method __init__ (line 499) | def __init__(self, config: Dict[str, Any], service: "CheapClawService"):
method poll_events (line 503) | def poll_events(self) -> List[Dict[str, Any]]:
method send_message (line 506) | def send_message(self, conversation_id: str, message: str, attachments...
method _normalize_attachments (line 510) | def _normalize_attachments(attachments: Optional[List[Dict[str, Any]]]...
method handle_webhook_get (line 531) | def handle_webhook_get(self, path: str, query: Dict[str, List[str]], h...
method handle_webhook_post (line 534) | def handle_webhook_post(self, path: str, body: bytes, headers: Dict[st...
function _ensure_cheapclaw_app_config (line 538) | def _ensure_cheapclaw_app_config(paths: CheapClawPaths) -> Dict[str, Any]:
function _sync_root_app_config_from_cheapclaw (line 582) | def _sync_root_app_config_from_cheapclaw(user_data_root: Path, cheapclaw...
class TelegramAdapter (line 601) | class TelegramAdapter(ChannelAdapter):
method __init__ (line 604) | def __init__(self, config: Dict[str, Any], service: "CheapClawService"):
method _request (line 612) | def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, ...
method _get_me (line 620) | def _get_me(self) -> Dict[str, Any]:
method _message_mentions_bot (line 630) | def _message_mentions_bot(self, message: Dict[str, Any], text: str, is...
method poll_events (line 661) | def poll_events(self) -> List[Dict[str, Any]]:
method send_message (line 720) | def send_message(self, conversation_id: str, message: str, attachments...
class FeishuAdapter (line 756) | class FeishuAdapter(ChannelAdapter):
method __init__ (line 759) | def __init__(self, config: Dict[str, Any], service: "CheapClawService"):
method _enqueue_event (line 774) | def _enqueue_event(self, payload: Dict[str, Any]) -> None:
method _normalize_message_event (line 778) | def _normalize_message_event(self, header: Dict[str, Any], event: Dict...
method _start_long_connection (line 812) | def _start_long_connection(self) -> None:
method poll_events (line 852) | def poll_events(self) -> List[Dict[str, Any]]:
method _tenant_access_token (line 860) | def _tenant_access_token(self) -> str:
method handle_webhook_post (line 881) | def handle_webhook_post(self, path: str, body: bytes, headers: Dict[st...
method send_message (line 896) | def send_message(self, conversation_id: str, message: str, attachments...
class WhatsAppCloudAdapter (line 953) | class WhatsAppCloudAdapter(ChannelAdapter):
method __init__ (line 956) | def __init__(self, config: Dict[str, Any], service: "CheapClawService"):
method handle_webhook_get (line 964) | def handle_webhook_get(self, path: str, query: Dict[str, List[str]], h...
method handle_webhook_post (line 972) | def handle_webhook_post(self, path: str, body: bytes, headers: Dict[st...
method send_message (line 1002) | def send_message(self, conversation_id: str, message: str, attachments...
class CheapClawService (line 1064) | class CheapClawService:
method __init__ (line 1065) | def __init__(
method _runtime_scope (line 1127) | def _runtime_scope(self):
method bootstrap_assets (line 1131) | def bootstrap_assets(self, force: bool = False) -> Dict[str, Any]:
method describe_runtime (line 1188) | def describe_runtime(self) -> Dict[str, Any]:
method list_agent_systems (line 1191) | def list_agent_systems(self) -> Dict[str, Any]:
method list_global_skills (line 1194) | def list_global_skills(self) -> Dict[str, Any]:
method _find_task_entry (line 1197) | def _find_task_entry(self, task_id: str) -> Tuple[Optional[Dict[str, A...
method get_task_preferences (line 1207) | def get_task_preferences(self, *, task_id: str) -> Dict[str, Any]:
method update_task_preferences (line 1223) | def update_task_preferences(
method load_runtime_state (line 1264) | def load_runtime_state(self) -> Dict[str, Any]:
method save_runtime_state (line 1268) | def save_runtime_state(self, payload: Dict[str, Any]) -> Dict[str, Any]:
method load_channel_config (line 1272) | def load_channel_config(self) -> Dict[str, Any]:
method reload_adapters (line 1275) | def reload_adapters(self) -> Dict[str, ChannelAdapter]:
method ingest_event (line 1287) | def ingest_event(self, event: Dict[str, Any]) -> Dict[str, Any]:
method build_task_id (line 1291) | def build_task_id(self, *, channel: str, conversation_id: str, task_na...
method build_task_skills_overlay (line 1295) | def build_task_skills_overlay(self, *, task_id: str, exposed_skills: O...
method record_social_message (line 1300) | def record_social_message(self, **kwargs) -> Dict[str, Any]:
method start_task (line 1304) | def start_task(self, **kwargs) -> Dict[str, Any]:
method add_task_message (line 1431) | def add_task_message(
method fresh_task (line 1456) | def fresh_task(self, *, task_id: str, reason: str = "") -> Dict[str, A...
method reset_task (line 1460) | def reset_task(self, *, task_id: str, preserve_history: bool = True, k...
method get_task_snapshot (line 1464) | def get_task_snapshot(self, *, task_id: str) -> Dict[str, Any]:
method refresh_task_view (line 1478) | def refresh_task_view(self, *, channel: str, conversation_id: str, tas...
method process_task_events (line 1493) | def process_task_events(self) -> List[Dict[str, Any]]:
method reconcile_task_statuses (line 1553) | def reconcile_task_statuses(self) -> List[Dict[str, Any]]:
method queue_message (line 1641) | def queue_message(self, *, channel: str, conversation_id: str, message...
method send_message_now (line 1645) | def send_message_now(self, *, channel: str, conversation_id: str, mess...
method process_outbox (line 1674) | def process_outbox(self) -> List[Dict[str, Any]]:
method poll_channels (line 1705) | def poll_channels(self) -> List[Dict[str, Any]]:
method tick_watchdog (line 1713) | def tick_watchdog(self) -> List[Dict[str, Any]]:
method _watchdog_due (line 1769) | def _watchdog_due(self) -> bool:
method tick_plans (line 1776) | def tick_plans(self) -> List[Dict[str, Any]]:
method _build_supervisor_input (line 1828) | def _build_supervisor_input(self, reason: str) -> str:
method run_supervisor_once (line 1911) | def run_supervisor_once(self, reason: str = "dirty_panel") -> Dict[str...
method run_once (line 1932) | def run_once(self) -> Dict[str, Any]:
method run_forever (line 1955) | def run_forever(self, poll_interval: int = 15) -> None:
method _task_created_sort_value (line 1976) | def _task_created_sort_value(task: Dict[str, Any]) -> str:
method serve_webhooks (line 1991) | def serve_webhooks(self, host: str = "127.0.0.1", port: int = 8765) ->...
method dashboard_payload (line 2088) | def dashboard_payload(self) -> Dict[str, Any]:
method _adapter_for_webhook (line 2105) | def _adapter_for_webhook(self, path: str) -> Optional[ChannelAdapter]:
method credentials_needed (line 2112) | def credentials_needed(self) -> Dict[str, List[str]]:
function build_arg_parser (line 2120) | def build_arg_parser() -> argparse.ArgumentParser:
function main (line 2137) | def main(argv: Optional[List[str]] = None) -> int:
FILE: apps/cheapclaw/tool_runtime_helpers.py
function now_iso (line 14) | def now_iso() -> str:
function parse_iso (line 18) | def parse_iso(value: str) -> Optional[datetime]:
function get_user_data_root (line 31) | def get_user_data_root() -> Path:
function get_cheapclaw_root (line 38) | def get_cheapclaw_root() -> Path:
function get_panel_path (line 42) | def get_panel_path() -> Path:
function get_panel_backups_dir (line 46) | def get_panel_backups_dir() -> Path:
function get_plans_path (line 50) | def get_plans_path() -> Path:
function get_outbox_dir (line 54) | def get_outbox_dir() -> Path:
function get_task_events_dir (line 58) | def get_task_events_dir() -> Path:
function get_task_skills_root (line 62) | def get_task_skills_root() -> Path:
function get_channels_root (line 66) | def get_channels_root() -> Path:
function ensure_cheapclaw_layout (line 70) | def ensure_cheapclaw_layout() -> None:
function _atomic_write_json (line 103) | def _atomic_write_json(path: Path, payload: Dict[str, Any]) -> None:
function _write_backup (line 115) | def _write_backup(path: Path, payload: str) -> Path:
function slugify (line 121) | def slugify(value: str, fallback: str = "item", max_len: int = 80) -> str:
function load_panel (line 141) | def load_panel() -> Dict[str, Any]:
function save_panel (line 149) | def save_panel(panel: Dict[str, Any], backup: bool = True) -> Dict[str, ...
function mutate_panel (line 158) | def mutate_panel(mutator):
function _default_task_view (line 164) | def _default_task_view(task_id: str) -> Dict[str, Any]:
function ensure_conversation (line 189) | def ensure_conversation(
function history_path (line 237) | def history_path(channel: str, conversation_id: str) -> Path:
function conversation_context_path (line 243) | def conversation_context_path(channel: str, conversation_id: str) -> Path:
function _short_text (line 249) | def _short_text(value: Any, limit: int = 240) -> str:
function refresh_conversation_context_file (line 256) | def refresh_conversation_context_file(
function append_history (line 347) | def append_history(
function read_social_history (line 372) | def read_social_history(
function queue_outbound_message (line 412) | def queue_outbound_message(
function list_outbox_events (line 435) | def list_outbox_events() -> List[Dict[str, Any]]:
function ack_outbox_event (line 446) | def ack_outbox_event(event_id: str) -> None:
function emit_task_event (line 454) | def emit_task_event(payload: Dict[str, Any]) -> Dict[str, Any]:
function list_task_events (line 464) | def list_task_events() -> List[Dict[str, Any]]:
function ack_task_event (line 475) | def ack_task_event(event_id: str) -> None:
function load_plans (line 483) | def load_plans() -> Dict[str, Any]:
function save_plans (line 491) | def save_plans(payload: Dict[str, Any]) -> Dict[str, Any]:
function create_plan (line 497) | def create_plan(
function cancel_plan (line 550) | def cancel_plan(plan_id: str) -> bool:
function list_plans (line 563) | def list_plans(scope: str = "", enabled_only: bool = False) -> List[Dict...
function compute_next_scheduled_run (line 575) | def compute_next_scheduled_run(
function list_conversation_tasks (line 610) | def list_conversation_tasks(channel: str, conversation_id: str) -> List[...
function bind_messages_to_task (line 627) | def bind_messages_to_task(
function update_conversation_task (line 664) | def update_conversation_task(channel: str, conversation_id: str, task_id...
function set_task_visible_skills (line 684) | def set_task_visible_skills(task_id: str, skill_names: Iterable[str]) ->...
function extend_task_visible_skills (line 702) | def extend_task_visible_skills(task_id: str, skill_names: Iterable[str])...
function clear_conversation_dirty (line 721) | def clear_conversation_dirty(channel: str, conversation_id: str) -> Dict...
function generate_task_id (line 734) | def generate_task_id(channel: str, conversation_id: str, task_name: str)...
function list_global_skills (line 741) | def list_global_skills(skills_root: Optional[str] = None) -> List[Dict[s...
function reveal_skills_for_task (line 751) | def reveal_skills_for_task(task_id: str, skill_names: Iterable[str], ski...
function set_task_skills_for_task (line 782) | def set_task_skills_for_task(task_id: str, skill_names: Iterable[str], s...
FILE: apps/cheapclaw/tools_library/cheapclaw_add_task_message/cheapclaw_add_task_message.py
class CheapClawAddTaskMessageTool (line 15) | class CheapClawAddTaskMessageTool(BaseTool):
method execute (line 18) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_cancel_plan/cheapclaw_cancel_plan.py
class CheapClawCancelPlanTool (line 12) | class CheapClawCancelPlanTool(BaseTool):
method execute (line 14) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_generate_task_id/cheapclaw_generate_task_id.py
class CheapClawGenerateTaskIdTool (line 12) | class CheapClawGenerateTaskIdTool(BaseTool):
method execute (line 14) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_get_task_status/cheapclaw_get_task_status.py
class CheapClawGetTaskStatusTool (line 14) | class CheapClawGetTaskStatusTool(BaseTool):
method execute (line 16) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_list_agent_systems/cheapclaw_list_agent_systems.py
class CheapClawListAgentSystemsTool (line 6) | class CheapClawListAgentSystemsTool(BaseTool):
method execute (line 8) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_list_conversation_tasks/cheapclaw_list_conversation_tasks.py
class CheapClawListConversationTasksTool (line 12) | class CheapClawListConversationTasksTool(BaseTool):
method execute (line 14) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_list_global_skills/cheapclaw_list_global_skills.py
class CheapClawListGlobalSkillsTool (line 12) | class CheapClawListGlobalSkillsTool(BaseTool):
method execute (line 14) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_read_panel/cheapclaw_read_panel.py
class CheapClawReadPanelTool (line 12) | class CheapClawReadPanelTool(BaseTool):
method execute (line 14) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_read_social_history/cheapclaw_read_social_history.py
class CheapClawReadSocialHistoryTool (line 12) | class CheapClawReadSocialHistoryTool(BaseTool):
method execute (line 14) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_reset_task/cheapclaw_reset_task.py
class CheapClawResetTaskTool (line 6) | class CheapClawResetTaskTool(BaseTool):
method execute (line 8) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_reveal_skills/cheapclaw_reveal_skills.py
class CheapClawRevealSkillsTool (line 14) | class CheapClawRevealSkillsTool(BaseTool):
method execute (line 16) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_schedule_plan/cheapclaw_schedule_plan.py
class CheapClawSchedulePlanTool (line 12) | class CheapClawSchedulePlanTool(BaseTool):
method execute (line 14) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_send_file/cheapclaw_send_file.py
function _get_active_service (line 13) | def _get_active_service():
class CheapClawSendFileTool (line 25) | class CheapClawSendFileTool(BaseTool):
method execute (line 28) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_send_message/cheapclaw_send_message.py
function _get_active_service (line 13) | def _get_active_service():
class CheapClawSendMessageTool (line 25) | class CheapClawSendMessageTool(BaseTool):
method execute (line 27) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_start_task/cheapclaw_start_task.py
function _load_cheapclaw_settings (line 23) | def _load_cheapclaw_settings(user_root: str):
function _default_task_view (line 48) | def _default_task_view(task_id):
class CheapClawStartTaskTool (line 73) | class CheapClawStartTaskTool(BaseTool):
method execute (line 76) | def execute(self, task_id, parameters):
FILE: apps/cheapclaw/tools_library/cheapclaw_update_panel/cheapclaw_update_panel.py
class CheapClawUpdatePanelTool (line 20) | class CheapClawUpdatePanelTool(BaseTool):
method execute (line 23) | def execute(self, task_id, parameters):
FILE: core/agent_event_emitter.py
class EventHandler (line 11) | class EventHandler(Protocol):
method handle (line 16) | def handle(self, event: AgentEvent):
class AgentEventEmitter (line 25) | class AgentEventEmitter:
method __init__ (line 29) | def __init__(self):
method register (line 32) | def register(self, handler: EventHandler):
method dispatch (line 42) | def dispatch(self, event: AgentEvent):
FILE: core/agent_executor.py
class AgentExecutor (line 48) | class AgentExecutor:
method __init__ (line 51) | def __init__(
method _get_agent_model_preference (line 155) | def _get_agent_model_preference(self, category: str) -> Optional[str]:
method _resolve_max_turns (line 169) | def _resolve_max_turns(self) -> int:
method _inject_mcp_tools (line 178) | def _inject_mcp_tools(self):
method _setup_event_emitter (line 191) | def _setup_event_emitter(self):
method _emit_sdk_stream_event (line 202) | def _emit_sdk_stream_event(self, event_type: str, payload: Dict[str, A...
method run (line 220) | def run(self, task_id: str, user_input: str) -> Dict:
method _load_state_from_storage (line 449) | def _load_state_from_storage(self, task_id: str) -> int:
method _build_messages_from_action_history (line 487) | def _build_messages_from_action_history(self) -> List[Dict]:
method _should_normalize_kimi_history_tool_ids (line 642) | def _should_normalize_kimi_history_tool_ids(self) -> bool:
method _format_kimi_history_tool_call_id (line 649) | def _format_kimi_history_tool_call_id(tool_name: str, sequence_index: ...
method _execute_llm_call (line 652) | def _execute_llm_call(
method _record_text_response (line 733) | def _record_text_response(
method _build_react_reflection_prompt (line 759) | def _build_react_reflection_prompt(self) -> str:
method _run_react_reflection (line 768) | def _run_react_reflection(
method _execute_tool_call (line 809) | def _execute_tool_call(self, tool_call: Dict, task_id: str, user_input...
method _handle_special_tool_side_effects (line 951) | def _handle_special_tool_side_effects(self, tool_name: str, tool_resul...
method _maybe_run_scheduled_fresh (line 997) | def _maybe_run_scheduled_fresh(self, task_id: str, user_input: str, tu...
method _perform_fresh (line 1008) | def _perform_fresh(self, task_id: str, user_input: str, turn: int, rea...
method _handle_execution_error (line 1083) | def _handle_execution_error(self, e: Exception) -> Dict:
method _add_uuid_if_needed (line 1138) | def _add_uuid_if_needed(
method _trigger_thinking (line 1183) | def _trigger_thinking(self, task_id: str, task_input: str, is_initial:...
method _build_llm_stream_callback (line 1268) | def _build_llm_stream_callback(
method _build_model_outputs_payload (line 1318) | def _build_model_outputs_payload(self) -> Dict[str, Any]:
method _with_model_outputs (line 1331) | def _with_model_outputs(self, result: Dict[str, Any]) -> Dict[str, Any]:
method _compress_action_history_if_needed (line 1347) | def _compress_action_history_if_needed(self):
method _recover_pending_tools (line 1389) | def _recover_pending_tools(self, task_id: str):
method _save_state (line 1435) | def _save_state(self, task_id: str, user_input: str, current_turn: int):
FILE: core/context_builder.py
class ContextBuilder (line 17) | class ContextBuilder:
method __init__ (line 20) | def __init__(self, hierarchy_manager, agent_config: Dict, config_loade...
method _resolve_compressor_model (line 52) | def _resolve_compressor_model(self) -> str:
method _resolve_compressor_tool_choice (line 56) | def _resolve_compressor_tool_choice(self, model: str) -> str:
method _build_task_system_add (line 59) | def _build_task_system_add(self, task_id: str) -> str:
method _count_tokens (line 71) | def _count_tokens(self, text: str) -> int:
method build_context (line 79) | def build_context(self, task_id: str, agent_id: str, agent_name: str, ...
method _select_user_history_entries (line 212) | def _select_user_history_entries(self, history: List[Dict]) -> tuple[L...
method _build_task_history_search_hint (line 223) | def _build_task_history_search_hint(self, visible_count: int, total_co...
method _build_loaded_skills_xml (line 231) | def _build_loaded_skills_xml(self, agent_id: str) -> str:
method _load_general_system_prompt (line 255) | def _load_general_system_prompt(self, agent_name: str) -> str:
method _build_user_latest_input (line 292) | def _build_user_latest_input(self, current: Dict) -> str:
method _build_user_agent_history (line 308) | def _build_user_agent_history(self, task_id: str, current: Dict = None...
method _compress_user_agent_history_with_llm (line 375) | def _compress_user_agent_history_with_llm(self, history: List[Dict], t...
method _build_structured_call_info (line 474) | def _build_structured_call_info(self, current: Dict, current_agent_id:...
method _compress_structured_call_info_with_llm (line 536) | def _compress_structured_call_info_with_llm(self, call_tree: List[Dict...
method _build_agent_tree_json (line 596) | def _build_agent_tree_json(
method _format_agent_tree (line 669) | def _format_agent_tree(
method _build_current_thinking (line 742) | def _build_current_thinking(self, task_id: str, agent_id: str, current...
method _build_action_history (line 776) | def _build_action_history(self, task_id: str, agent_id: str) -> str:
FILE: core/event_handlers.py
function _normalize_event_value (line 17) | def _normalize_event_value(value: Any) -> Any:
function serialize_agent_event (line 29) | def serialize_agent_event(event: AgentEvent) -> Dict[str, Any]:
class StructuredEventHandler (line 50) | class StructuredEventHandler:
method __init__ (line 53) | def __init__(
method handle (line 62) | def handle(self, event: AgentEvent):
method emit (line 66) | def emit(self, normalized: Dict[str, Any]):
class ConsoleLogHandler (line 72) | class ConsoleLogHandler:
method handle (line 77) | def handle(self, event: AgentEvent):
method _print_default (line 84) | def _print_default(self, event: AgentEvent):
method _print_agent_start (line 89) | def _print_agent_start(self, event: AgentStartEvent):
method _print_agent_end (line 95) | def _print_agent_end(self, event: AgentEndEvent):
method _print_prepare_model_select (line 104) | def _print_prepare_model_select(self, event: ModelSelectionEvent):
method _print_prepare_history_load (line 111) | def _print_prepare_history_load(self, event: HistoryLoadEvent):
method _print_run_llm_start (line 118) | def _print_run_llm_start(self, event: LlmCallStartEvent):
method _print_run_llm_end (line 122) | def _print_run_llm_end(self, event: LlmCallEndEvent):
method _print_run_tool_start (line 126) | def _print_run_tool_start(self, event: ToolCallStartEvent):
method _print_run_tool_end (line 130) | def _print_run_tool_end(self, event: ToolCallEndEvent):
method _print_run_thinking_start (line 133) | def _print_run_thinking_start(self, event: ThinkingStartEvent):
method _print_run_thinking_end (line 142) | def _print_run_thinking_end(self, event: ThinkingEndEvent):
method _print_run_thinking_fail (line 145) | def _print_run_thinking_fail(self, event: ThinkingFailEvent):
method _print_system_error (line 149) | def _print_system_error(self, event: ErrorEvent):
method _print_system_cli_display (line 152) | def _print_system_cli_display(self, event: CliDisplayEvent):
class JsonlStreamHandler (line 156) | class JsonlStreamHandler:
method __init__ (line 161) | def __init__(self, enabled: bool):
method handle (line 165) | def handle(self, event: AgentEvent):
method _stream_default (line 176) | def _stream_default(self, event: AgentEvent):
method _stream_agent_start (line 180) | def _stream_agent_start(self, event: AgentStartEvent):
method _stream_agent_end (line 187) | def _stream_agent_end(self, event: AgentEndEvent):
method _stream_run_thinking_start (line 193) | def _stream_run_thinking_start(self, event: ThinkingStartEvent):
method _stream_run_tool_start (line 201) | def _stream_run_tool_start(self, event: ToolCallStartEvent):
method _stream_run_tool_end (line 209) | def _stream_run_tool_end(self, event: ToolCallEndEvent):
method _stream_run_thinking_end (line 233) | def _stream_run_thinking_end(self, event: ThinkingEndEvent):
method _stream_run_thinking_fail (line 242) | def _stream_run_thinking_fail(self, event: ThinkingFailEvent):
method _stream_system_error (line 245) | def _stream_system_error(self, event: ErrorEvent):
FILE: core/events.py
class AgentEvent (line 20) | class AgentEvent:
class ModelSelectionEvent (line 26) | class ModelSelectionEvent(AgentEvent):
class HistoryLoadEvent (line 37) | class HistoryLoadEvent(AgentEvent):
class ThinkingStartEvent (line 53) | class ThinkingStartEvent(AgentEvent):
class ThinkingEndEvent (line 64) | class ThinkingEndEvent(AgentEvent):
class ThinkingFailEvent (line 80) | class ThinkingFailEvent(AgentEvent):
class LlmCallStartEvent (line 91) | class LlmCallStartEvent(AgentEvent):
class LlmCallEndEvent (line 101) | class LlmCallEndEvent(AgentEvent):
class ToolCallStartEvent (line 115) | class ToolCallStartEvent(AgentEvent):
class ToolCallEndEvent (line 125) | class ToolCallEndEvent(AgentEvent):
class AgentStartEvent (line 140) | class AgentStartEvent(AgentEvent):
class AgentEndEvent (line 150) | class AgentEndEvent(AgentEvent):
class ErrorEvent (line 161) | class ErrorEvent(AgentEvent):
class CliDisplayEvent (line 170) | class CliDisplayEvent(AgentEvent):
FILE: core/hierarchy_manager.py
class HierarchyManager (line 19) | class HierarchyManager:
method __init__ (line 22) | def __init__(self, task_id: str):
method _initialize_files (line 49) | def _initialize_files(self):
method _load_stack (line 78) | def _load_stack(self) -> List[Dict]:
method _save_stack (line 88) | def _save_stack(self, stack: List[Dict]):
method _load_context (line 99) | def _load_context(self) -> Dict:
method _save_context (line 117) | def _save_context(self, context: Dict):
method start_new_instruction (line 126) | def start_new_instruction(self, instruction: str) -> str:
method append_instruction (line 138) | def append_instruction(self, instruction: str, dedupe: bool = False, s...
method get_runtime_metadata (line 177) | def get_runtime_metadata(self) -> Dict:
method set_runtime_metadata (line 183) | def set_runtime_metadata(self, **metadata):
method push_agent (line 200) | def push_agent(self, agent_name: str, user_input: str) -> str:
method pop_agent (line 284) | def pop_agent(self, agent_id: str, final_output: str = ""):
method update_thinking (line 322) | def update_thinking(self, agent_id: str, thinking: str):
method get_loaded_skills (line 338) | def get_loaded_skills(self, agent_id: str) -> List[Dict]:
method add_loaded_skill (line 345) | def add_loaded_skill(self, agent_id: str, skill_info: Dict):
method remove_loaded_skill (line 361) | def remove_loaded_skill(self, agent_id: str, skill_name: str):
method add_action (line 374) | def add_action(self, agent_id: str, action: Dict):
method get_context (line 386) | def get_context(self) -> Dict:
method _check_and_complete_if_all_done (line 390) | def _check_and_complete_if_all_done(self):
method get_current_agent_id (line 447) | def get_current_agent_id(self) -> Optional[str]:
function get_hierarchy_manager (line 458) | def get_hierarchy_manager(task_id: str) -> HierarchyManager:
FILE: core/runtime_exceptions.py
class InfiAgentRunError (line 12) | class InfiAgentRunError(RuntimeError):
method __init__ (line 15) | def __init__(
method from_result (line 35) | def from_result(
FILE: core/state_cleaner.py
function clean_before_start (line 19) | def clean_before_start(task_id: str, new_user_input: str = None):
FILE: core/tool_executor.py
class ToolExecutor (line 19) | class ToolExecutor:
method __init__ (line 28) | def __init__(
method set_agent_context (line 61) | def set_agent_context(self, *, agent_id: str = "", agent_name: str = ""):
method _agent_level (line 65) | def _agent_level(self) -> int:
method _init_tools_registry (line 73) | def _init_tools_registry(self):
method _call_direct (line 85) | def _call_direct(self, tool_name: str, arguments: Dict, task_id: str) ...
method set_task_permission (line 180) | def set_task_permission(self, task_id: str, auto_mode: bool):
method is_auto_mode (line 185) | def is_auto_mode(self, task_id: str) -> bool:
method _request_tool_confirmation (line 189) | def _request_tool_confirmation(self, tool_name: str, arguments: Dict[s...
method execute (line 241) | def execute(self, tool_name: str, arguments: Dict[str, Any], task_id: ...
method _execute_sub_agent (line 325) | def _execute_sub_agent(
FILE: desktop_app/src/main.js
function getPythonBackendPath (line 18) | function getPythonBackendPath() {
function getPackagedBackendArchDir (line 25) | function getPackagedBackendArchDir() {
function getPackagedBackendExecutablePath (line 39) | function getPackagedBackendExecutablePath() {
function getPackagedBackendPlaywrightBrowsersPath (line 47) | function getPackagedBackendPlaywrightBrowsersPath() {
function getBackendLaunchSpecDev (line 62) | function getBackendLaunchSpecDev(userInput, workspacePath, agentName, ag...
function getBackendLaunchSpecPackaged (line 80) | function getBackendLaunchSpecPackaged(userInput, workspacePath, agentNam...
function getUserDataRoot (line 98) | function getUserDataRoot() {
function getUserConfigDir (line 102) | function getUserConfigDir() {
function getAppConfigPath (line 106) | function getAppConfigPath() {
function getLlmConfigPath (line 111) | function getLlmConfigPath() {
function defaultAppConfig (line 116) | function defaultAppConfig() {
function safeReadJsonFile (line 156) | function safeReadJsonFile(filePath) {
function ensureUserAppConfigExists (line 166) | function ensureUserAppConfigExists() {
function readAppConfig (line 174) | function readAppConfig() {
function stripApiKeysFromYaml (line 196) | function stripApiKeysFromYaml(yamlText) {
function _parsePathFromPathHelperOutput (line 203) | function _parsePathFromPathHelperOutput(text) {
function getSystemPathFromPathHelper (line 212) | function getSystemPathFromPathHelper() {
function getZshLoginInteractivePath (line 224) | function getZshLoginInteractivePath() {
function computeEffectivePath (line 238) | function computeEffectivePath(appCfg) {
function buildRuntimeEnv (line 273) | function buildRuntimeEnv() {
function ensureUserDataRootScaffold (line 304) | function ensureUserDataRootScaffold() {
function ensureUserLlmConfigExists (line 366) | function ensureUserLlmConfigExists() {
function getSkillsLibraryPath (line 401) | function getSkillsLibraryPath() {
function getUserAgentLibraryPath (line 406) | function getUserAgentLibraryPath() {
function getConversationsPath (line 411) | function getConversationsPath() {
function getLogsPath (line 415) | function getLogsPath() {
function sanitizeFilenamePart (line 419) | function sanitizeFilenamePart(input) {
function createTaskLogger (line 425) | function createTaskLogger({ workspacePath, agentName, agentSystem, mode,...
function safeReadJson (line 467) | function safeReadJson(filePath) {
function pickPreviewFromShareContext (line 476) | function pickPreviewFromShareContext(data) {
function computeTaskNameForConversation (line 492) | function computeTaskNameForConversation(taskId) {
function getStackFilePath (line 499) | function getStackFilePath(taskId) {
function createWindow (line 507) | function createWindow() {
function killPythonProcess (line 795) | function killPythonProcess() {
function parseSettingsYaml (line 811) | function parseSettingsYaml(text) {
function serializeSettingsYaml (line 816) | function serializeSettingsYaml(obj) {
function normalizeMarketBaseUrl (line 976) | function normalizeMarketBaseUrl(url) {
function fetchJson (line 982) | async function fetchJson(url) {
function fetchBuffer (line 991) | async function fetchBuffer(url) {
function resolveUniqueName (line 1001) | function resolveUniqueName(rootDir, baseName) {
function extractSingleTopFolderFromZip (line 1012) | function extractSingleTopFolderFromZip(zipBuffer, tempDir) {
function copyDirSync (line 1173) | function copyDirSync(src, dest) {
FILE: desktop_app/src/renderer.js
function reloadAgentSystems (line 26) | async function reloadAgentSystems(selectedValue = null) {
function renderMarkdownSafe (line 64) | function renderMarkdownSafe(mdText) {
function setMarkdown (line 84) | function setMarkdown(el, mdText) {
function refreshResumeButton (line 148) | async function refreshResumeButton() {
function sendMessage (line 221) | async function sendMessage() {
function addUserMessage (line 370) | function addUserMessage(text) {
function addSystemMessage (line 378) | function addSystemMessage(text) {
function addErrorMessage (line 385) | function addErrorMessage(text) {
function addToolMessage (line 392) | function addToolMessage(toolName, status, args) {
function updateLastToolStatus (line 470) | function updateLastToolStatus(status, outputPreview) {
function streamToken (line 498) | function streamToken(text) {
function finalizeCurrentStream (line 528) | function finalizeCurrentStream() {
function streamReasoningToken (line 544) | function streamReasoningToken(text) {
function finalizeReasoningStream (line 567) | function finalizeReasoningStream() {
function startThinkingAgentStream (line 591) | function startThinkingAgentStream() {
function streamThinkingAgentToken (line 609) | function streamThinkingAgentToken(text) {
function finalizeThinkingAgentStream (line 616) | function finalizeThinkingAgentStream() {
function showTypingIndicator (line 636) | function showTypingIndicator() {
function removeTypingIndicator (line 645) | function removeTypingIndicator() {
function resetState (line 650) | function resetState() {
function scrollToBottom (line 659) | function scrollToBottom() {
function forceScrollToBottom (line 666) | function forceScrollToBottom() {
function escapeHtml (line 672) | function escapeHtml(text) {
function updateAutoScrollBtn (line 679) | function updateAutoScrollBtn() {
function loadSettings (line 762) | async function loadSettings() {
function setMarketStatus (line 1064) | function setMarketStatus(text, isError = false) {
constant MODEL_EDITOR_SLOT_CONFIG_KEYS (line 1070) | const MODEL_EDITOR_SLOT_CONFIG_KEYS = {
constant MODEL_EDITOR_PROVIDER_OPTIONS (line 1079) | const MODEL_EDITOR_PROVIDER_OPTIONS = `
function createEmptyModelEditorState (line 1091) | function createEmptyModelEditorState() {
function nextModelEditorId (line 1102) | function nextModelEditorId() {
function inferModelProviderKind (line 1107) | function inferModelProviderKind(modelName, entryBaseUrl, globalBaseUrl, ...
function stripModelNameForProvider (line 1122) | function stripModelNameForProvider(providerKind, modelName, entryBaseUrl...
function normalizeModelNameForProvider (line 1139) | function normalizeModelNameForProvider(providerKind, modelName) {
function makeBlankModelEditorEntry (line 1156) | function makeBlankModelEditorEntry() {
function deserializeModelEditorEntry (line 1168) | function deserializeModelEditorEntry(rawEntry, globalBaseUrl) {
function serializeModelEditorComparable (line 1186) | function serializeModelEditorComparable(entry) {
function cloneModelEditorEntry (line 1197) | function cloneModelEditorEntry(entry) {
function computeSharedModelEntries (line 1209) | function computeSharedModelEntries(slotEntries) {
function createModelEntryPayload (line 1218) | function createModelEntryPayload(entry) {
function buildModelEditorConfig (line 1229) | function buildModelEditorConfig(baseConfig) {
function getModelEditorEntry (line 1240) | function getModelEditorEntry(slotKey, entryId) {
function renderModelEditorEntry (line 1244) | function renderModelEditorEntry(slotKey, entry) {
function renderModelEditorSlot (line 1295) | function renderModelEditorSlot(slotKey) {
function renderAllModelEditorSlots (line 1316) | function renderAllModelEditorSlots() {
function loadModelEditorSettings (line 1320) | function loadModelEditorSettings(config) {
function addModelEditorEntry (line 1342) | function addModelEditorEntry(slotKey) {
function bindModelEditorList (line 1348) | function bindModelEditorList(slotKey) {
function readPositiveNumber (line 1399) | function readPositiveNumber(value, fallback) {
function readNonNegativeNumber (line 1404) | function readNonNegativeNumber(value, fallback) {
function filterMarketItems (line 1409) | function filterMarketItems(items, q) {
function renderMarketList (line 1419) | function renderMarketList() {
function loadMarketIndex (line 1478) | async function loadMarketIndex() {
function installFromMarket (line 1492) | async function installFromMarket(kind, name) {
function loadSkills (line 1577) | async function loadSkills() {
function loadConversations (line 1619) | async function loadConversations() {
function formatRelativeTime (line 1697) | function formatRelativeTime(date) {
function loadConversationDetail (line 1712) | async function loadConversationDetail(fileName) {
function renderShareContext (line 1731) | function renderShareContext(data) {
function addAgentMessage (line 1749) | function addAgentMessage(label, text) {
FILE: infiagent/sdk.py
function _normalize_path (line 57) | def _normalize_path(path: Optional[str]) -> Optional[str]:
function _as_root_dir (line 63) | def _as_root_dir(path: Optional[str], expected_leaf: Optional[str] = Non...
function _materialize_inline_llm_config (line 73) | def _materialize_inline_llm_config(
class InfiAgent (line 88) | class InfiAgent:
method __init__ (line 89) | def __init__(
method _runtime_scope (line 207) | def _runtime_scope(self, extra_overrides: Optional[Dict[str, Any]] = N...
method _resolve_task_id (line 213) | def _resolve_task_id(
method _build_launch_config (line 227) | def _build_launch_config(self) -> Dict[str, Any]:
method _build_sdk_event_handler (line 270) | def _build_sdk_event_handler(
method _attach_optional_run_artifacts (line 286) | def _attach_optional_run_artifacts(
method run (line 302) | def run(
method fresh (line 429) | def fresh(
method add_message (line 462) | def add_message(
method start_background_task (line 494) | def start_background_task(
method task_share_context_path (line 525) | def task_share_context_path(self, *, task_id: str) -> Dict[str, Any]:
method list_task_ids (line 532) | def list_task_ids(self, *, only_running: bool = False) -> Dict[str, Any]:
method describe_runtime (line 539) | def describe_runtime(self) -> Dict[str, Any]:
method list_agent_systems (line 560) | def list_agent_systems(self) -> Dict[str, Any]:
method task_snapshot (line 594) | def task_snapshot(self, *, task_id: str) -> Dict[str, Any]:
method task_trace (line 657) | def task_trace(
method reset_task (line 711) | def reset_task(
method run_async (line 731) | async def run_async(
method fresh_async (line 776) | async def fresh_async(self, *, task_id: str, reason: str = "") -> Dict...
method add_message_async (line 779) | async def add_message_async(
method start_background_task_async (line 797) | async def start_background_task_async(
method task_share_context_path_async (line 821) | async def task_share_context_path_async(self, *, task_id: str) -> Dict...
method list_task_ids_async (line 824) | async def list_task_ids_async(self, *, only_running: bool = False) -> ...
method describe_runtime_async (line 827) | async def describe_runtime_async(self) -> Dict[str, Any]:
method list_agent_systems_async (line 830) | async def list_agent_systems_async(self) -> Dict[str, Any]:
method task_snapshot_async (line 833) | async def task_snapshot_async(self, *, task_id: str) -> Dict[str, Any]:
method task_trace_async (line 836) | async def task_trace_async(
method reset_task_async (line 850) | async def reset_task_async(
function infiagent (line 867) | def infiagent(**kwargs) -> InfiAgent:
FILE: marketplace_server/app.py
function _env_path (line 21) | def _env_path(name: str, default: Path) -> Path:
function _mk_item (line 33) | def _mk_item(kind: str, name: str, description: str, updated_at: float, ...
function _load_state (line 43) | def _load_state() -> Dict[str, Any]:
function _save_state (line 52) | def _save_state(state: Dict[str, Any]) -> None:
function _inc_download (line 58) | def _inc_download(kind: str, name: str) -> int:
function _get_downloads (line 66) | def _get_downloads(kind: str, name: str) -> int:
function _safe_frontmatter_description (line 72) | def _safe_frontmatter_description(skill_md: Path) -> str:
function _list_skills (line 90) | def _list_skills() -> List[Dict[str, Any]]:
function _list_agent_systems (line 106) | def _list_agent_systems() -> List[Dict[str, Any]]:
function _apply_query (line 159) | def _apply_query(items: List[Dict[str, Any]], q: str) -> List[Dict[str, ...
function _sort_items (line 172) | def _sort_items(items: List[Dict[str, Any]], sort_by: str, order: str) -...
function _zip_dir_to_bytes (line 180) | def _zip_dir_to_bytes(dir_path: Path, top_folder_name: str) -> bytes:
function _resolve_item_dir (line 192) | def _resolve_item_dir(kind: str, name: str) -> Path:
function _json_response (line 205) | def _json_response(start_response, status: str, data: Dict[str, Any]) ->...
function _bytes_response (line 216) | def _bytes_response(start_response, status: str, content_type: str, body...
function _not_found (line 228) | def _not_found(start_response, msg: str) -> List[bytes]:
function _bad_request (line 232) | def _bad_request(start_response, msg: str) -> List[bytes]:
function app (line 236) | def app(environ, start_response):
function _run_dev_server (line 409) | def _run_dev_server(host: str, port: int) -> None:
function _html_page (line 417) | def _html_page(title: str, body_html: str) -> bytes:
function _escape_html (line 447) | def _escape_html(s: str) -> str:
function _admin_token_required (line 458) | def _admin_token_required() -> bool:
function _check_admin (line 462) | def _check_admin(environ) -> bool:
function _extract_zip_to_dest (line 473) | def _extract_zip_to_dest(zip_bytes: bytes, dest_root: Path, strategy: st...
FILE: services/action_compressor.py
class ActionCompressor (line 19) | class ActionCompressor:
method __init__ (line 25) | def __init__(
method _resolve_compressor_model (line 50) | def _resolve_compressor_model(self) -> str:
method _resolve_compressor_tool_choice (line 53) | def _resolve_compressor_tool_choice(self, model: str) -> str:
method count_tokens (line 56) | def count_tokens(self, text: str) -> int:
method compress_if_needed (line 65) | def compress_if_needed(
method _actions_to_xml (line 143) | def _actions_to_xml(self, actions: List[Dict]) -> str:
method _extract_images_from_actions (line 169) | def _extract_images_from_actions(self, actions: List[Dict]) -> List[Di...
method _summarize_historical_xml (line 191) | def _summarize_historical_xml(
method _single_summarize (line 259) | def _single_summarize(
method _chunked_summarize (line 345) | def _chunked_summarize(
method _compress_action_fields (line 475) | def _compress_action_fields(
method _llm_compress_field (line 547) | def _llm_compress_field(
method _chunked_compress_field (line 673) | def _chunked_compress_field(
method _fallback_compress (line 805) | def _fallback_compress(self, text: str, max_tokens: int) -> str:
FILE: services/context_compressor_backup.py
class ContextCompressor (line 29) | class ContextCompressor:
method __init__ (line 32) | def __init__(self):
method count_tokens (line 42) | def count_tokens(self, text: str) -> int:
method compress_action_history (line 52) | def compress_action_history(
method _summarize_historical_actions (line 120) | def _summarize_historical_actions(self, actions: List[Dict]) -> Dict:
method _create_simple_summary (line 202) | def _create_simple_summary(self, actions: List[Dict]) -> Dict:
method _compress_large_action (line 223) | def _compress_large_action(self, action: Dict, max_tokens: int) -> Dict:
FILE: services/llm_client.py
class ChatMessage (line 32) | class ChatMessage:
class ToolCall (line 39) | class ToolCall:
class LLMResponse (line 47) | class LLMResponse:
function _marker_prefix_overlap (line 68) | def _marker_prefix_overlap(text: str, marker: str) -> int:
class _EmbeddedToolCallStreamState (line 79) | class _EmbeddedToolCallStreamState:
method __init__ (line 82) | def __init__(self):
method feed (line 87) | def feed(self, text: str) -> str:
method finish (line 132) | def finish(self) -> tuple[str, str]:
function _coerce_text_content (line 143) | def _coerce_text_content(value: Any) -> str:
class SimpleLLMClient (line 167) | class SimpleLLMClient:
method __init__ (line 170) | def __init__(self, llm_config_path: str = None, tools_config_path: str...
method _emit_stream_reset (line 255) | def _emit_stream_reset(
method _fetch_response_and_first_chunk_with_timeout (line 278) | def _fetch_response_and_first_chunk_with_timeout(
method _parse_models_config (line 314) | def _parse_models_config(self, models_config: List, target_list: List,...
method _load_default_tool_choice (line 355) | def _load_default_tool_choice(self) -> Dict[str, str]:
method get_default_tool_choice (line 375) | def get_default_tool_choice(self, category: str = "execution") -> str:
method _is_kimi_tool_model (line 379) | def _is_kimi_tool_model(model: str, tool_count: int = 0) -> bool:
method _contains_embedded_tool_markup (line 388) | def _contains_embedded_tool_markup(text: str) -> bool:
method _embedded_tool_name_from_id (line 401) | def _embedded_tool_name_from_id(raw_call_id: str) -> str:
method _parse_embedded_tool_calls (line 411) | def _parse_embedded_tool_calls(self, raw_markup: str) -> List[ToolCall]:
method _merge_tool_calls (line 443) | def _merge_tool_calls(primary: List[ToolCall], secondary: List[ToolCal...
method _extract_embedded_tool_calls_and_visible_text (line 457) | def _extract_embedded_tool_calls_and_visible_text(
method _parse_non_stream_tool_calls (line 491) | def _parse_non_stream_tool_calls(self, tool_calls_payload: Any) -> Lis...
method _chat_internal_non_stream (line 537) | def _chat_internal_non_stream(
method _build_debug_messages_snapshot (line 609) | def _build_debug_messages_snapshot(self, messages: List[Dict[str, Any]...
method _resolve_debug_output_path (line 625) | def _resolve_debug_output_path(self, debug_task_id: Optional[str]) -> ...
method _append_debug_record (line 636) | def _append_debug_record(
method resolve_model (line 663) | def resolve_model(self, category: str = "execution", preferred: Option...
method resolve_tool_choice (line 680) | def resolve_tool_choice(
method chat (line 698) | def chat(
method _chat_internal (line 832) | def _chat_internal(
method set_tools_config (line 1257) | def set_tools_config(self, tools_config: Dict):
method _try_fix_json (line 1266) | def _try_fix_json(self, json_str: str) -> Dict:
method _generate_type_fix_hint (line 1306) | def _generate_type_fix_hint(self, error_info: str) -> str:
method _get_error_type (line 1386) | def _get_error_type(self, error_info: str) -> str:
method _is_retriable_error (line 1422) | def _is_retriable_error(self, error_info: str) -> bool:
method _generate_retry_hint (line 1483) | def _generate_retry_hint(self, error_info: str, retry_count: int) -> str:
method _build_tools_definition (line 1605) | def _build_tools_definition(self, tool_list: List[str]) -> List[Dict]:
FILE: services/thinking_agent.py
class ThinkingAgent (line 13) | class ThinkingAgent:
method __init__ (line 16) | def __init__(self, preferred_model: Optional[str] = None, max_tokens: ...
method analyze_first_thinking (line 110) | def analyze_first_thinking(self, task_description: str, agent_system_p...
method analyze_first_thinking_detail (line 127) | def analyze_first_thinking_detail(self, task_description: str, agent_s...
method _extract_images (line 220) | def _extract_images(self, action_history: List[Dict]) -> List[Dict]:
method _format_tools_info (line 246) | def _format_tools_info(self, available_tools: List[str], tools_config:...
method analyze_progress (line 287) | def analyze_progress(self, task_description: str, agent_system_prompt:...
method analyze_progress_detail (line 298) | def analyze_progress_detail(self, task_description: str, agent_system_...
FILE: setup.py
function _collect_data_files (line 37) | def _collect_data_files(base_dir: Path, install_prefix: str):
FILE: skills/algorithmic-art/templates/generator_template.js
function initializeSeed (line 43) | function initializeSeed(seed) {
function setup (line 53) | function setup() {
function draw (line 70) | function draw() {
class Entity (line 92) | class Entity {
method constructor (line 93) | constructor() {
method update (line 98) | update() {
method display (line 106) | display() {
function hexToRgb (line 132) | function hexToRgb(hex) {
function colorFromPalette (line 141) | function colorFromPalette(index) {
function mapRange (line 146) | function mapRange(value, inMin, inMax, outMin, outMax) {
function easeInOutCubic (line 150) | function easeInOutCubic(t) {
function wrapAround (line 155) | function wrapAround(value, max) {
function updateParameter (line 165) | function updateParameter(paramName, value) {
function regenerate (line 171) | function regenerate() {
function fadeBackground (line 183) | function fadeBackground(opacity) {
function getNoiseValue (line 190) | function getNoiseValue(x, y, scale = 0.01) {
function vectorFromAngle (line 195) | function vectorFromAngle(angle, magnitude = 1) {
function exportImage (line 203) | function exportImage() {
FILE: skills/docx/scripts/accept_changes.py
function accept_changes (line 36) | def accept_changes(
function _setup_libreoffice_macro (line 91) | def _setup_libreoffice_macro() -> bool:
FILE: skills/docx/scripts/comment.py
function _generate_hex_id (line 68) | def _generate_hex_id() -> str:
function _encode_smart_quotes (line 80) | def _encode_smart_quotes(text: str) -> str:
function _append_xml (line 86) | def _append_xml(xml_path: Path, root_tag: str, content: str) -> None:
function _find_para_id (line 98) | def _find_para_id(comments_path: Path, comment_id: int) -> str | None:
function _get_next_rid (line 108) | def _get_next_rid(rels_path: Path) -> int:
function _has_relationship (line 121) | def _has_relationship(rels_path: Path, target: str) -> bool:
function _has_content_type (line 129) | def _has_content_type(ct_path: Path, part_name: str) -> bool:
function _ensure_comment_relationships (line 137) | def _ensure_comment_relationships(unpacked_dir: Path) -> None:
function _ensure_comment_content_types (line 179) | def _ensure_comment_content_types(unpacked_dir: Path) -> None:
function add_comment (line 218) | def add_comment(
FILE: skills/docx/scripts/office/helpers/merge_runs.py
function merge_runs (line 16) | def merge_runs(input_dir: str) -> tuple[int, str]:
function _find_elements (line 44) | def _find_elements(root, tag: str) -> list:
function _get_child (line 59) | def _get_child(parent, tag: str):
function _get_children (line 68) | def _get_children(parent, tag: str) -> list:
function _is_adjacent (line 78) | def _is_adjacent(elem1, elem2) -> bool:
function _remove_elements (line 93) | def _remove_elements(root, tag: str):
function _strip_run_rsid_attrs (line 99) | def _strip_run_rsid_attrs(root):
function _merge_runs_in (line 108) | def _merge_runs_in(container) -> int:
function _first_child_run (line 128) | def _first_child_run(container):
function _next_element_sibling (line 135) | def _next_element_sibling(node):
function _next_sibling_run (line 144) | def _next_sibling_run(node):
function _is_run (line 154) | def _is_run(node) -> bool:
function _can_merge (line 159) | def _can_merge(run1, run2) -> bool:
function _merge_run_content (line 170) | def _merge_run_content(target, source):
function _consolidate_text (line 178) | def _consolidate_text(run):
FILE: skills/docx/scripts/office/helpers/simplify_redlines.py
function simplify_redlines (line 22) | def simplify_redlines(input_dir: str) -> tuple[int, str]:
function _merge_tracked_changes_in (line 47) | def _merge_tracked_changes_in(container, tag: str) -> int:
function _is_element (line 75) | def _is_element(node, tag: str) -> bool:
function _get_author (line 80) | def _get_author(elem) -> str:
function _can_merge_tracked (line 89) | def _can_merge_tracked(elem1, elem2) -> bool:
function _merge_tracked_content (line 104) | def _merge_tracked_content(target, source):
function _find_elements (line 111) | def _find_elements(root, tag: str) -> list:
function get_tracked_change_authors (line 126) | def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]:
function _get_authors_from_docx (line 149) | def _get_authors_from_docx(docx_path: Path) -> dict[str, int]:
function infer_author (line 172) | def infer_author(modified_dir: Path, original_docx: Path, default: str =...
FILE: skills/docx/scripts/office/pack.py
function pack (line 24) | def pack(
function _run_validation (line 69) | def _run_validation(
function _condense_xml (line 108) | def _condense_xml(xml_file: Path) -> None:
FILE: skills/docx/scripts/office/soffice.py
function get_soffice_env (line 24) | def get_soffice_env() -> dict:
function run_soffice (line 35) | def run_soffice(args: list[str], **kwargs) -> subprocess.CompletedProcess:
function _needs_shim (line 44) | def _needs_shim() -> bool:
function _ensure_shim (line 53) | def _ensure_shim() -> Path:
FILE: skills/docx/scripts/office/unpack.py
function unpack (line 34) | def unpack(
function _pretty_print_xml (line 82) | def _pretty_print_xml(xml_file: Path) -> None:
function _escape_smart_quotes (line 91) | def _escape_smart_quotes(xml_file: Path) -> None:
FILE: skills/docx/scripts/office/validate.py
function main (line 25) | def main():
FILE: skills/docx/scripts/office/validators/base.py
class BaseSchemaValidator (line 12) | class BaseSchemaValidator:
method __init__ (line 94) | def __init__(self, unpacked_dir, original_file=None, verbose=False):
method validate (line 109) | def validate(self):
method repair (line 112) | def repair(self) -> int:
method repair_whitespace_preservation (line 115) | def repair_whitespace_preservation(self) -> int:
method validate_xml (line 143) | def validate_xml(self):
method validate_namespaces (line 170) | def validate_namespaces(self):
method validate_unique_ids (line 199) | def validate_unique_ids(self):
method validate_file_references (line 289) | def validate_file_references(self):
method validate_all_relationship_ids (line 385) | def validate_all_relationship_ids(self):
method _get_expected_relationship_type (line 469) | def _get_expected_relationship_type(self, element_name):
method validate_content_types (line 492) | def validate_content_types(self):
method validate_file_against_xsd (line 598) | def validate_file_against_xsd(self, xml_file, verbose=False):
method validate_against_xsd (line 636) | def validate_against_xsd(self):
method _get_schema_path (line 685) | def _get_schema_path(self, xml_file):
method _clean_ignorable_namespaces (line 703) | def _clean_ignorable_namespaces(self, xml_doc):
method _remove_ignorable_elements (line 723) | def _remove_ignorable_elements(self, root):
method _preprocess_for_mc_ignorable (line 742) | def _preprocess_for_mc_ignorable(self, xml_doc):
method _validate_single_file_xsd (line 750) | def _validate_single_file_xsd(self, xml_file, base_path):
method _get_original_file_errors (line 787) | def _get_original_file_errors(self, xml_file):
method _remove_template_tags_from_text_nodes (line 814) | def _remove_template_tags_from_text_nodes(self, xml_doc):
FILE: skills/docx/scripts/office/validators/docx.py
class DOCXSchemaValidator (line 16) | class DOCXSchemaValidator(BaseSchemaValidator):
method validate (line 24) | def validate(self):
method validate_whitespace_preservation (line 66) | def validate_whitespace_preservation(self):
method validate_deletions (line 112) | def validate_deletions(self):
method count_paragraphs_in_unpacked (line 163) | def count_paragraphs_in_unpacked(self):
method count_paragraphs_in_original (line 179) | def count_paragraphs_in_original(self):
method validate_insertions (line 202) | def validate_insertions(self):
method compare_paragraph_counts (line 243) | def compare_paragraph_counts(self):
method _parse_id_value (line 251) | def _parse_id_value(self, val: str, base: int = 16) -> int:
method validate_id_constraints (line 254) | def validate_id_constraints(self):
method validate_comment_markers (line 298) | def validate_comment_markers(self):
method repair (line 386) | def repair(self) -> int:
method repair_durableId (line 391) | def repair_durableId(self) -> int:
FILE: skills/docx/scripts/office/validators/pptx.py
class PPTXSchemaValidator (line 10) | class PPTXSchemaValidator(BaseSchemaValidator):
method validate (line 25) | def validate(self):
method validate_uuid_ids (line 62) | def validate_uuid_ids(self):
method _looks_like_uuid (line 100) | def _looks_like_uuid(self, value):
method validate_slide_layout_ids (line 104) | def validate_slide_layout_ids(self):
method validate_no_duplicate_slide_layouts (line 172) | def validate_no_duplicate_slide_layouts(self):
method validate_notes_slide_references (line 210) | def validate_notes_slide_references(self):
FILE: skills/docx/scripts/office/validators/redlining.py
class RedliningValidator (line 11) | class RedliningValidator:
method __init__ (line 13) | def __init__(self, unpacked_dir, original_docx, verbose=False, author=...
method repair (line 22) | def repair(self) -> int:
method validate (line 25) | def validate(self):
method _generate_detailed_diff (line 104) | def _generate_detailed_diff(self, original_text, modified_text):
method _get_git_word_diff (line 127) | def _get_git_word_diff(self, original_text, modified_text):
method _remove_author_tracked_changes (line 198) | def _remove_author_tracked_changes(self, root):
method _extract_text_content (line 229) | def _extract_text_content(self, root):
FILE: skills/mac-use/scripts/mac_use.py
function get_windows (line 46) | def get_windows():
function find_window (line 75) | def find_window(app_name, window_id=None):
function get_display_scale (line 109) | def get_display_scale():
function activate_app (line 131) | def activate_app(app_name):
function raise_window (line 141) | def raise_window(app_name, window_title):
function activate_and_find (line 156) | def activate_and_find(app_name, window_id=None):
function output (line 167) | def output(data):
function fail (line 172) | def fail(data):
function reliable_click (line 182) | def reliable_click(x, y):
function canvas_to_abs (line 208) | def canvas_to_abs(canvas_x, canvas_y, win, scale):
function capture_full_screen (line 230) | def capture_full_screen():
function crop_window (line 239) | def crop_window(win):
function detect_text_elements (line 276) | def detect_text_elements(image_path):
function is_noise (line 328) | def is_noise(elem):
function draw_annotations (line 349) | def draw_annotations(image_path, elements, output_path):
function cmd_list (line 396) | def cmd_list(_args):
function cmd_screenshot (line 401) | def cmd_screenshot(args):
function cmd_clicknum (line 465) | def cmd_clicknum(args):
function cmd_click (line 505) | def cmd_click(args):
function cmd_scroll (line 518) | def cmd_scroll(args):
function keystroke_via_osascript (line 543) | def keystroke_via_osascript(key, modifiers=None):
function keycode_via_osascript (line 558) | def keycode_via_osascript(code, modifiers=None):
function cmd_type (line 573) | def cmd_type(args):
function cmd_key (line 586) | def cmd_key(args):
function main (line 633) | def main():
FILE: skills/mcp-builder/scripts/connections.py
class MCPConnection (line 13) | class MCPConnection(ABC):
method __init__ (line 16) | def __init__(self):
method _create_context (line 21) | def _create_context(self):
method __aenter__ (line 24) | async def __aenter__(self):
method __aexit__ (line 48) | async def __aexit__(self, exc_type, exc_val, exc_tb):
method list_tools (line 55) | async def list_tools(self) -> list[dict[str, Any]]:
method call_tool (line 67) | async def call_tool(self, tool_name: str, arguments: dict[str, Any]) -...
class MCPConnectionStdio (line 73) | class MCPConnectionStdio(MCPConnection):
method __init__ (line 76) | def __init__(self, command: str, args: list[str] = None, env: dict[str...
method _create_context (line 82) | def _create_context(self):
class MCPConnectionSSE (line 88) | class MCPConnectionSSE(MCPConnection):
method __init__ (line 91) | def __init__(self, url: str, headers: dict[str, str] = None):
method _create_context (line 96) | def _create_context(self):
class MCPConnectionHTTP (line 100) | class MCPConnectionHTTP(MCPConnection):
method __init__ (line 103) | def __init__(self, url: str, headers: dict[str, str] = None):
method _create_context (line 108) | def _create_context(self):
function create_connection (line 112) | def create_connection(
FILE: skills/mcp-builder/scripts/evaluation.py
function parse_evaluation_file (line 56) | def parse_evaluation_file(file_path: Path) -> list[dict[str, Any]]:
function extract_xml_content (line 79) | def extract_xml_content(text: str, tag: str) -> str | None:
function agent_loop (line 86) | async def agent_loop(
function evaluate_single_task (line 154) | async def evaluate_single_task(
function run_evaluation (line 220) | async def run_evaluation(
function parse_headers (line 275) | def parse_headers(header_list: list[str]) -> dict[str, str]:
function parse_env_vars (line 290) | def parse_env_vars(env_list: list[str]) -> dict[str, str]:
function main (line 305) | async def main():
FILE: skills/pdf/scripts/check_bounding_boxes.py
class RectAndField (line 9) | class RectAndField:
function get_bounding_box_messages (line 15) | def get_bounding_box_messages(fields_json_stream) -> list[str]:
FILE: skills/pdf/scripts/convert_pdf_to_images.py
function convert (line 9) | def convert(pdf_path, output_dir, max_dim=1000):
FILE: skills/pdf/scripts/create_validation_image.py
function create_validation_image (line 9) | def create_validation_image(page_number, fields_json_path, input_path, o...
FILE: skills/pdf/scripts/extract_form_field_info.py
function get_full_annotation_field_id (line 9) | def get_full_annotation_field_id(annotation):
function make_field_dict (line 19) | def make_field_dict(field, field_id):
function get_field_info (line 47) | def get_field_info(reader: PdfReader):
function write_field_info (line 110) | def write_field_info(pdf_path: str, json_output_path: str):
FILE: skills/pdf/scripts/extract_form_structure.py
function extract_form_structure (line 20) | def extract_form_structure(pdf_path):
function main (line 91) | def main():
FILE: skills/pdf/scripts/fill_fillable_fields.py
function fill_pdf_fields (line 11) | def fill_pdf_fields(input_pdf_path: str, fields_json_path: str, output_p...
function validation_error_for_field_value (line 55) | def validation_error_for_field_value(field_info, field_value):
function monkeypatch_pydpf_method (line 74) | def monkeypatch_pydpf_method():
FILE: skills/pdf/scripts/fill_pdf_form_with_annotations.py
function transform_from_image_coords (line 10) | def transform_from_image_coords(bbox, image_width, image_height, pdf_wid...
function transform_from_pdf_coords (line 23) | def transform_from_pdf_coords(bbox, pdf_height):
function fill_pdf_form (line 33) | def fill_pdf_form(input_pdf_path, fields_json_path, output_pdf_path):
FILE: skills/pptx/scripts/add_slide.py
function get_next_slide_number (line 27) | def get_next_slide_number(slides_dir: Path) -> int:
function create_slide_from_layout (line 33) | def create_slide_from_layout(unpacked_dir: Path, layout_file: str) -> None:
function duplicate_slide (line 90) | def duplicate_slide(unpacked_dir: Path, source: str) -> None:
function _add_to_content_types (line 130) | def _add_to_content_types(unpacked_dir: Path, dest: str) -> None:
function _add_to_presentation_rels (line 141) | def _add_to_presentation_rels(unpacked_dir: Path, dest: str) -> str:
function _get_next_slide_id (line 158) | def _get_next_slide_id(unpacked_dir: Path) -> int:
function parse_source (line 165) | def parse_source(source: str) -> tuple[str, str | None]:
FILE: skills/pptx/scripts/clean.py
function get_slides_in_sldidlst (line 27) | def get_slides_in_sldidlst(unpacked_dir: Path) -> set[str]:
function remove_orphaned_slides (line 49) | def remove_orphaned_slides(unpacked_dir: Path) -> list[str]:
function remove_trash_directory (line 91) | def remove_trash_directory(unpacked_dir: Path) -> list[str]:
function get_slide_referenced_files (line 106) | def get_slide_referenced_files(unpacked_dir: Path) -> set:
function remove_orphaned_rels_files (line 128) | def remove_orphaned_rels_files(unpacked_dir: Path) -> list[str]:
function get_referenced_files (line 153) | def get_referenced_files(unpacked_dir: Path) -> set:
function remove_orphaned_files (line 171) | def remove_orphaned_files(unpacked_dir: Path, referenced: set) -> list[s...
function update_content_types (line 221) | def update_content_types(unpacked_dir: Path, removed_files: list[str]) -...
function clean_unused_files (line 241) | def clean_unused_files(unpacked_dir: Path) -> list[str]:
FILE: skills/pptx/scripts/office/helpers/merge_runs.py
function merge_runs (line 16) | def merge_runs(input_dir: str) -> tuple[int, str]:
function _find_elements (line 44) | def _find_elements(root, tag: str) -> list:
function _get_child (line 59) | def _get_child(parent, tag: str):
function _get_children (line 68) | def _get_children(parent, tag: str) -> list:
function _is_adjacent (line 78) | def _is_adjacent(elem1, elem2) -> bool:
function _remove_elements (line 93) | def _remove_elements(root, tag: str):
function _strip_run_rsid_attrs (line 99) | def _strip_run_rsid_attrs(root):
function _merge_runs_in (line 108) | def _merge_runs_in(container) -> int:
function _first_child_run (line 128) | def _first_child_run(container):
function _next_element_sibling (line 135) | def _next_element_sibling(node):
function _next_sibling_run (line 144) | def _next_sibling_run(node):
function _is_run (line 154) | def _is_run(node) -> bool:
function _can_merge (line 159) | def _can_merge(run1, run2) -> bool:
function _merge_run_content (line 170) | def _merge_run_content(target, source):
function _consolidate_text (line 178) | def _consolidate_text(run):
FILE: skills/pptx/scripts/office/helpers/simplify_redlines.py
function simplify_redlines (line 22) | def simplify_redlines(input_dir: str) -> tuple[int, str]:
function _merge_tracked_changes_in (line 47) | def _merge_tracked_changes_in(container, tag: str) -> int:
function _is_element (line 75) | def _is_element(node, tag: str) -> bool:
function _get_author (line 80) | def _get_author(elem) -> str:
function _can_merge_tracked (line 89) | def _can_merge_tracked(elem1, elem2) -> bool:
function _merge_tracked_content (line 104) | def _merge_tracked_content(target, source):
function _find_elements (line 111) | def _find_elements(root, tag: str) -> list:
function get_tracked_change_authors (line 126) | def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]:
function _get_authors_from_docx (line 149) | def _get_authors_from_docx(docx_path: Path) -> dict[str, int]:
function infer_author (line 172) | def infer_author(modified_dir: Path, original_docx: Path, default: str =...
FILE: skills/pptx/scripts/office/pack.py
function pack (line 24) | def pack(
function _run_validation (line 69) | def _run_validation(
function _condense_xml (line 108) | def _condense_xml(xml_file: Path) -> None:
FILE: skills/pptx/scripts/office/soffice.py
function get_soffice_env (line 24) | def get_soffice_env() -> dict:
function run_soffice (line 35) | def run_soffice(args: list[str], **kwargs) -> subprocess.CompletedProcess:
function _needs_shim (line 44) | def _needs_shim() -> bool:
function _ensure_shim (line 53) | def _ensure_shim() -> Path:
FILE: skills/pptx/scripts/office/unpack.py
function unpack (line 34) | def unpack(
function _pretty_print_xml (line 82) | def _pretty_print_xml(xml_file: Path) -> None:
function _escape_smart_quotes (line 91) | def _escape_smart_quotes(xml_file: Path) -> None:
FILE: skills/pptx/scripts/office/validate.py
function main (line 25) | def main():
FILE: skills/pptx/scripts/office/validators/base.py
class BaseSchemaValidator (line 12) | class BaseSchemaValidator:
method __init__ (line 94) | def __init__(self, unpacked_dir, original_file=None, verbose=False):
method validate (line 109) | def validate(self):
method repair (line 112) | def repair(self) -> int:
method repair_whitespace_preservation (line 115) | def repair_whitespace_preservation(self) -> int:
method validate_xml (line 143) | def validate_xml(self):
method validate_namespaces (line 170) | def validate_namespaces(self):
method validate_unique_ids (line 199) | def validate_unique_ids(self):
method validate_file_references (line 289) | def validate_file_references(self):
method validate_all_relationship_ids (line 385) | def validate_all_relationship_ids(self):
method _get_expected_relationship_type (line 469) | def _get_expected_relationship_type(self, element_name):
method validate_content_types (line 492) | def validate_content_types(self):
method validate_file_against_xsd (line 598) | def validate_file_against_xsd(self, xml_file, verbose=False):
method validate_against_xsd (line 636) | def validate_against_xsd(self):
method _get_schema_path (line 685) | def _get_schema_path(self, xml_file):
method _clean_ignorable_namespaces (line 703) | def _clean_ignorable_namespaces(self, xml_doc):
method _remove_ignorable_elements (line 723) | def _remove_ignorable_elements(self, root):
method _preprocess_for_mc_ignorable (line 742) | def _preprocess_for_mc_ignorable(self, xml_doc):
method _validate_single_file_xsd (line 750) | def _validate_single_file_xsd(self, xml_file, base_path):
method _get_original_file_errors (line 787) | def _get_original_file_errors(self, xml_file):
method _remove_template_tags_from_text_nodes (line 814) | def _remove_template_tags_from_text_nodes(self, xml_doc):
FILE: skills/pptx/scripts/office/validators/docx.py
class DOCXSchemaValidator (line 16) | class DOCXSchemaValidator(BaseSchemaValidator):
method validate (line 24) | def validate(self):
method validate_whitespace_preservation (line 66) | def validate_whitespace_preservation(self):
method validate_deletions (line 112) | def validate_deletions(self):
method count_paragraphs_in_unpacked (line 163) | def count_paragraphs_in_unpacked(self):
method count_paragraphs_in_original (line 179) | def count_paragraphs_in_original(self):
method validate_insertions (line 202) | def validate_insertions(self):
method compare_paragraph_counts (line 243) | def compare_paragraph_counts(self):
method _parse_id_value (line 251) | def _parse_id_value(self, val: str, base: int = 16) -> int:
method validate_id_constraints (line 254) | def validate_id_constraints(self):
method validate_comment_markers (line 298) | def validate_comment_markers(self):
method repair (line 386) | def repair(self) -> int:
method repair_durableId (line 391) | def repair_durableId(self) -> int:
FILE: skills/pptx/scripts/office/validators/pptx.py
class PPTXSchemaValidator (line 10) | class PPTXSchemaValidator(BaseSchemaValidator):
method validate (line 25) | def validate(self):
method validate_uuid_ids (line 62) | def validate_uuid_ids(self):
method _looks_like_uuid (line 100) | def _looks_like_uuid(self, value):
method validate_slide_layout_ids (line 104) | def validate_slide_layout_ids(self):
method validate_no_duplicate_slide_layouts (line 172) | def validate_no_duplicate_slide_layouts(self):
method validate_notes_slide_references (line 210) | def validate_notes_slide_references(self):
FILE: skills/pptx/scripts/office/validators/redlining.py
class RedliningValidator (line 11) | class RedliningValidator:
method __init__ (line 13) | def __init__(self, unpacked_dir, original_docx, verbose=False, author=...
method repair (line 22) | def repair(self) -> int:
method validate (line 25) | def validate(self):
method _generate_detailed_diff (line 104) | def _generate_detailed_diff(self, original_text, modified_text):
method _get_git_word_diff (line 127) | def _get_git_word_diff(self, original_text, modified_text):
method _remove_author_tracked_changes (line 198) | def _remove_author_tracked_changes(self, root):
method _extract_text_content (line 229) | def _extract_text_content(self, root):
FILE: skills/pptx/scripts/thumbnail.py
function main (line 40) | def main():
function get_slide_info (line 95) | def get_slide_info(pptx_path: Path) -> list[dict]:
function build_slide_list (line 121) | def build_slide_list(
function create_hidden_placeholder (line 149) | def create_hidden_placeholder(size: tuple[int, int]) -> Image.Image:
function convert_to_images (line 158) | def convert_to_images(pptx_path: Path, temp_dir: Path) -> list[Path]:
function create_grids (line 196) | def create_grids(
function create_grid (line 225) | def create_grid(
FILE: skills/slack-gif-creator/core/easing.py
function linear (line 12) | def linear(t: float) -> float:
function ease_in_quad (line 17) | def ease_in_quad(t: float) -> float:
function ease_out_quad (line 22) | def ease_out_quad(t: float) -> float:
function ease_in_out_quad (line 27) | def ease_in_out_quad(t: float) -> float:
function ease_in_cubic (line 34) | def ease_in_cubic(t: float) -> float:
function ease_out_cubic (line 39) | def ease_out_cubic(t: float) -> float:
function ease_in_out_cubic (line 44) | def ease_in_out_cubic(t: float) -> float:
function ease_in_bounce (line 51) | def ease_in_bounce(t: float) -> float:
function ease_out_bounce (line 56) | def ease_out_bounce(t: float) -> float:
function ease_in_out_bounce (line 71) | def ease_in_out_bounce(t: float) -> float:
function ease_in_elastic (line 78) | def ease_in_elastic(t: float) -> float:
function ease_out_elastic (line 85) | def ease_out_elastic(t: float) -> float:
function ease_in_out_elastic (line 92) | def ease_in_out_elastic(t: float) -> float:
function get_easing (line 117) | def get_easing(name: str = "linear"):
function interpolate (line 122) | def interpolate(start: float, end: float, t: float, easing: str = "linea...
function ease_back_in (line 140) | def ease_back_in(t: float) -> float:
function ease_back_out (line 147) | def ease_back_out(t: float) -> float:
function ease_back_in_out (line 154) | def ease_back_in_out(t: float) -> float:
function apply_squash_stretch (line 163) | def apply_squash_stretch(
function calculate_arc_motion (line 195) | def calculate_arc_motion(
FILE: skills/slack-gif-creator/core/frame_composer.py
function create_blank_frame (line 15) | def create_blank_frame(
function draw_circle (line 32) | def draw_circle(
function draw_text (line 61) | def draw_text(
function create_gradient_background (line 99) | def create_gradient_background(
function draw_star (line 137) | def draw_star(
FILE: skills/slack-gif-creator/core/gif_builder.py
class GIFBuilder (line 17) | class GIFBuilder:
method __init__ (line 20) | def __init__(self, width: int = 480, height: int = 480, fps: int = 15):
method add_frame (line 34) | def add_frame(self, frame: np.ndarray | Image.Image):
method add_frames (line 54) | def add_frames(self, frames: list[np.ndarray | Image.Image]):
method optimize_colors (line 59) | def optimize_colors(
method deduplicate_frames (line 124) | def deduplicate_frames(self, threshold: float = 0.9995) -> int:
method save (line 160) | def save(
method clear (line 267) | def clear(self):
FILE: skills/slack-gif-creator/core/validators.py
function validate_gif (line 11) | def validate_gif(
function is_slack_ready (line 121) | def is_slack_ready(
FILE: skills/webapp-testing/examples/console_logging.py
function handle_console_message (line 14) | def handle_console_message(msg):
FILE: skills/webapp-testing/scripts/with_server.py
function is_server_ready (line 23) | def is_server_ready(port, timeout=30):
function main (line 35) | def main():
FILE: skills/xlsx/scripts/office/helpers/merge_runs.py
function merge_runs (line 16) | def merge_runs(input_dir: str) -> tuple[int, str]:
function _find_elements (line 44) | def _find_elements(root, tag: str) -> list:
function _get_child (line 59) | def _get_child(parent, tag: str):
function _get_children (line 68) | def _get_children(parent, tag: str) -> list:
function _is_adjacent (line 78) | def _is_adjacent(elem1, elem2) -> bool:
function _remove_elements (line 93) | def _remove_elements(root, tag: str):
function _strip_run_rsid_attrs (line 99) | def _strip_run_rsid_attrs(root):
function _merge_runs_in (line 108) | def _merge_runs_in(container) -> int:
function _first_child_run (line 128) | def _first_child_run(container):
function _next_element_sibling (line 135) | def _next_element_sibling(node):
function _next_sibling_run (line 144) | def _next_sibling_run(node):
function _is_run (line 154) | def _is_run(node) -> bool:
function _can_merge (line 159) | def _can_merge(run1, run2) -> bool:
function _merge_run_content (line 170) | def _merge_run_content(target, source):
function _consolidate_text (line 178) | def _consolidate_text(run):
FILE: skills/xlsx/scripts/office/helpers/simplify_redlines.py
function simplify_redlines (line 22) | def simplify_redlines(input_dir: str) -> tuple[int, str]:
function _merge_tracked_changes_in (line 47) | def _merge_tracked_changes_in(container, tag: str) -> int:
function _is_element (line 75) | def _is_element(node, tag: str) -> bool:
function _get_author (line 80) | def _get_author(elem) -> str:
function _can_merge_tracked (line 89) | def _can_merge_tracked(elem1, elem2) -> bool:
function _merge_tracked_content (line 104) | def _merge_tracked_content(target, source):
function _find_elements (line 111) | def _find_elements(root, tag: str) -> list:
function get_tracked_change_authors (line 126) | def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]:
function _get_authors_from_docx (line 149) | def _get_authors_from_docx(docx_path: Path) -> dict[str, int]:
function infer_author (line 172) | def infer_author(modified_dir: Path, original_docx: Path, default: str =...
FILE: skills/xlsx/scripts/office/pack.py
function pack (line 24) | def pack(
function _run_validation (line 69) | def _run_validation(
function _condense_xml (line 108) | def _condense_xml(xml_file: Path) -> None:
FILE: skills/xlsx/scripts/office/soffice.py
function get_soffice_env (line 24) | def get_soffice_env() -> dict:
function run_soffice (line 35) | def run_soffice(args: list[str], **kwargs) -> subprocess.CompletedProcess:
function _needs_shim (line 44) | def _needs_shim() -> bool:
function _ensure_shim (line 53) | def _ensure_shim() -> Path:
FILE: skills/xlsx/scripts/office/unpack.py
function unpack (line 34) | def unpack(
function _pretty_print_xml (line 82) | def _pretty_print_xml(xml_file: Path) -> None:
function _escape_smart_quotes (line 91) | def _escape_smart_quotes(xml_file: Path) -> None:
FILE: skills/xlsx/scripts/office/validate.py
function main (line 25) | def main():
FILE: skills/xlsx/scripts/office/validators/base.py
class BaseSchemaValidator (line 12) | class BaseSchemaValidator:
method __init__ (line 94) | def __init__(self, unpacked_dir, original_file=None, verbose=False):
method validate (line 109) | def validate(self):
method repair (line 112) | def repair(self) -> int:
method repair_whitespace_preservation (line 115) | def repair_whitespace_preservation(self) -> int:
method validate_xml (line 143) | def validate_xml(self):
method validate_namespaces (line 170) | def validate_namespaces(self):
method validate_unique_ids (line 199) | def validate_unique_ids(self):
method validate_file_references (line 289) | def validate_file_references(self):
method validate_all_relationship_ids (line 385) | def validate_all_relationship_ids(self):
method _get_expected_relationship_type (line 469) | def _get_expected_relationship_type(self, element_name):
method validate_content_types (line 492) | def validate_content_types(self):
method validate_file_against_xsd (line 598) | def validate_file_against_xsd(self, xml_file, verbose=False):
method validate_against_xsd (line 636) | def validate_against_xsd(self):
method _get_schema_path (line 685) | def _get_schema_path(self, xml_file):
method _clean_ignorable_namespaces (line 703) | def _clean_ignorable_namespaces(self, xml_doc):
method _remove_ignorable_elements (line 723) | def _remove_ignorable_elements(self, root):
method _preprocess_for_mc_ignorable (line 742) | def _preprocess_for_mc_ignorable(self, xml_doc):
method _validate_single_file_xsd (line 750) | def _validate_single_file_xsd(self, xml_file, base_path):
method _get_original_file_errors (line 787) | def _get_original_file_errors(self, xml_file):
method _remove_template_tags_from_text_nodes (line 814) | def _remove_template_tags_from_text_nodes(self, xml_doc):
FILE: skills/xlsx/scripts/office/validators/docx.py
class DOCXSchemaValidator (line 16) | class DOCXSchemaValidator(BaseSchemaValidator):
method validate (line 24) | def validate(self):
method validate_whitespace_preservation (line 66) | def validate_whitespace_preservation(self):
method validate_deletions (line 112) | def validate_deletions(self):
method count_paragraphs_in_unpacked (line 163) | def count_paragraphs_in_unpacked(self):
method count_paragraphs_in_original (line 179) | def count_paragraphs_in_original(self):
method validate_insertions (line 202) | def validate_insertions(self):
method compare_paragraph_counts (line 243) | def compare_paragraph_counts(self):
method _parse_id_value (line 251) | def _parse_id_value(self, val: str, base: int = 16) -> int:
method validate_id_constraints (line 254) | def validate_id_constraints(self):
method validate_comment_markers (line 298) | def validate_comment_markers(self):
method repair (line 386) | def repair(self) -> int:
method repair_durableId (line 391) | def repair_durableId(self) -> int:
FILE: skills/xlsx/scripts/office/validators/pptx.py
class PPTXSchemaValidator (line 10) | class PPTXSchemaValidator(BaseSchemaValidator):
method validate (line 25) | def validate(self):
method validate_uuid_ids (line 62) | def validate_uuid_ids(self):
method _looks_like_uuid (line 100) | def _looks_like_uuid(self, value):
method validate_slide_layout_ids (line 104) | def validate_slide_layout_ids(self):
method validate_no_duplicate_slide_layouts (line 172) | def validate_no_duplicate_slide_layouts(self):
method validate_notes_slide_references (line 210) | def validate_notes_slide_references(self):
FILE: skills/xlsx/scripts/office/validators/redlining.py
class RedliningValidator (line 11) | class RedliningValidator:
method __init__ (line 13) | def __init__(self, unpacked_dir, original_docx, verbose=False, author=...
method repair (line 22) | def repair(self) -> int:
method validate (line 25) | def validate(self):
method _generate_detailed_diff (line 104) | def _generate_detailed_diff(self, original_text, modified_text):
method _get_git_word_diff (line 127) | def _get_git_word_diff(self, original_text, modified_text):
method _remove_author_tracked_changes (line 198) | def _remove_author_tracked_changes(self, root):
method _extract_text_content (line 229) | def _extract_text_content(self, root):
FILE: skills/xlsx/scripts/recalc.py
function has_gtimeout (line 32) | def has_gtimeout():
function setup_libreoffice_macro (line 42) | def setup_libreoffice_macro():
function recalc (line 70) | def recalc(filename, timeout=30):
function main (line 164) | def main():
FILE: start.py
function _configure_packaged_playwright_runtime (line 69) | def _configure_packaged_playwright_runtime() -> None:
function main (line 101) | def main():
FILE: tests/image_read.py
function main (line 4) | def main(img_path):
FILE: tests/test_cheapclaw_service.py
class CheapClawServiceTests (line 45) | class CheapClawServiceTests(unittest.TestCase):
method setUp (line 46) | def setUp(self):
method test_panel_store_bootstraps_layout (line 52) | def test_panel_store_bootstraps_layout(self):
method test_record_social_message_updates_panel_and_history (line 62) | def test_record_social_message_updates_panel_and_history(self):
method test_supervisor_input_contains_latest_user_text (line 87) | def test_supervisor_input_contains_latest_user_text(self):
method test_supervisor_input_is_event_focused_not_path_heavy (line 109) | def test_supervisor_input_is_event_focused_not_path_heavy(self):
method test_compute_next_scheduled_run_supports_daily_and_weekly (line 161) | def test_compute_next_scheduled_run_supports_daily_and_weekly(self):
method test_message_ids_can_be_bound_to_task (line 177) | def test_message_ids_can_be_bound_to_task(self):
method test_sdk_runtime_introspection_is_public (line 205) | def test_sdk_runtime_introspection_is_public(self):
method test_send_file_tool_queues_attachment (line 216) | def test_send_file_tool_queues_attachment(self):
method test_reconcile_task_statuses_updates_panel_from_share_history (line 244) | def test_reconcile_task_statuses_updates_panel_from_share_history(self):
method test_telegram_group_message_detects_mention_entity (line 283) | def test_telegram_group_message_detects_mention_entity(self):
method test_telegram_group_message_detects_reply_to_bot (line 293) | def test_telegram_group_message_detects_reply_to_bot(self):
method test_telegram_poll_events_accepts_supergroup_mention (line 303) | def test_telegram_poll_events_accepts_supergroup_mention(self):
method test_bootstrap_installs_agent_systems_tools_and_skill (line 326) | def test_bootstrap_installs_agent_systems_tools_and_skill(self):
method test_bootstrap_removes_bundled_systems_even_without_force (line 348) | def test_bootstrap_removes_bundled_systems_even_without_force(self):
method test_start_task_rejects_supervisor_system (line 361) | def test_start_task_rejects_supervisor_system(self):
method test_start_task_uses_default_exposed_skills_and_dispatch_timestamp (line 373) | def test_start_task_uses_default_exposed_skills_and_dispatch_timestamp...
method test_runtime_registry_loads_cheapclaw_custom_tools_from_dynamic_tools_dir (line 402) | def test_runtime_registry_loads_cheapclaw_custom_tools_from_dynamic_to...
method test_build_task_skills_overlay_creates_manifest (line 415) | def test_build_task_skills_overlay_creates_manifest(self):
method test_update_task_preferences_persists_default_skills_and_mcp (line 431) | def test_update_task_preferences_persists_default_skills_and_mcp(self):
method test_start_task_binds_panel_entry (line 466) | def test_start_task_binds_panel_entry(self):
method test_start_task_falls_back_to_valid_worker_agent (line 507) | def test_start_task_falls_back_to_valid_worker_agent(self):
method test_list_conversation_tasks_returns_recommended_task (line 535) | def test_list_conversation_tasks_returns_recommended_task(self):
method test_add_task_message_appends_timestamp (line 590) | def test_add_task_message_appends_timestamp(self):
method test_reset_task_public_api_clears_current_instructions (line 605) | def test_reset_task_public_api_clears_current_instructions(self):
method test_external_copy_can_import_service_module (line 619) | def test_external_copy_can_import_service_module(self):
method test_external_copy_can_import_custom_tool_module (line 634) | def test_external_copy_can_import_custom_tool_module(self):
FILE: tests/test_code_tools_system_terminal.py
function test_find_idle_terminal_window_id_returns_none_when_no_tagged_idle_tab (line 7) | def test_find_idle_terminal_window_id_returns_none_when_no_tagged_idle_t...
function test_get_or_create_terminal_window_id_creates_fresh_window_when_all_tagged_tabs_busy (line 15) | def test_get_or_create_terminal_window_id_creates_fresh_window_when_all_...
function test_launch_terminal_script_checks_busy_and_updates_cached_window (line 36) | def test_launch_terminal_script_checks_busy_and_updates_cached_window(mo...
function test_launch_terminal_script_interrupts_busy_session_instead_of_creating_new_window (line 61) | def test_launch_terminal_script_interrupts_busy_session_instead_of_creat...
FILE: tests/test_context_hooks.py
class _DummyHierarchyManager (line 12) | class _DummyHierarchyManager:
method __init__ (line 13) | def __init__(self):
method get_context (line 16) | def get_context(self):
method get_loaded_skills (line 19) | def get_loaded_skills(self, agent_id):
method _save_context (line 22) | def _save_context(self, context):
class _DummyLoader (line 26) | class _DummyLoader:
class ContextHookTests (line 30) | class ContextHookTests(unittest.TestCase):
method test_after_build_hook_can_modify_context_text (line 31) | def test_after_build_hook_can_modify_context_text(self):
FILE: tests/test_file_tools.py
function workspace (line 16) | def workspace(tmp_path):
class TestFileReadTool (line 20) | class TestFileReadTool:
method test_read_single_file_success (line 21) | def test_read_single_file_success(self, workspace):
method test_read_single_file_not_found (line 31) | def test_read_single_file_not_found(self, workspace):
method test_read_multiple_files_success (line 38) | def test_read_multiple_files_success(self, workspace):
method test_read_empty_file (line 48) | def test_read_empty_file(self, workspace):
method test_read_binary_file_error (line 57) | def test_read_binary_file_error(self, workspace):
method test_read_with_line_range (line 68) | def test_read_with_line_range(self, workspace):
method test_read_without_line_numbers (line 82) | def test_read_without_line_numbers(self, workspace):
method test_read_missing_path_parameter (line 92) | def test_read_missing_path_parameter(self, workspace):
method test_read_with_file_path_alias (line 100) | def test_read_with_file_path_alias(self, workspace):
method test_read_multiple_files_partial_error (line 110) | def test_read_multiple_files_partial_error(self, workspace):
class TestFileWriteTool (line 122) | class TestFileWriteTool:
method test_write_file_success (line 123) | def test_write_file_success(self, workspace):
method test_write_creates_parent_dirs (line 130) | def test_write_creates_parent_dirs(self, workspace):
method test_write_reference_bib_forbidden (line 138) | def test_write_reference_bib_forbidden(self, workspace):
method test_replace_lines_file_not_found (line 146) | def test_replace_lines_file_not_found(self, workspace):
method test_append_file_success (line 159) | def test_append_file_success(self, workspace):
method test_replace_lines_success (line 169) | def test_replace_lines_success(self, workspace):
class TestDirListTool (line 193) | class TestDirListTool:
method test_list_dir_success (line 194) | def test_list_dir_success(self, workspace):
method test_list_dir_not_found (line 205) | def test_list_dir_not_found(self, workspace):
method test_list_not_a_directory (line 213) | def test_list_not_a_directory(self, workspace):
method test_list_empty_directory (line 223) | def test_list_empty_directory(self, workspace):
method test_list_recursive_success (line 233) | def test_list_recursive_success(self, workspace):
class TestDirCreateTool (line 244) | class TestDirCreateTool:
method test_create_dir_success (line 245) | def test_create_dir_success(self, workspace):
class TestFileMoveTool (line 252) | class TestFileMoveTool:
method test_move_file_success (line 253) | def test_move_file_success(self, workspace):
method test_copy_file_success (line 265) | def test_copy_file_success(self, workspace):
class TestFileDeleteTool (line 277) | class TestFileDeleteTool:
method test_delete_file_success (line 278) | def test_delete_file_success(self, workspace):
method test_delete_dir_success (line 288) | def test_delete_dir_success(self, workspace):
method test_delete_not_found (line 299) | def test_delete_not_found(self, workspace):
FILE: tests/test_image_read_message.py
function load_and_compress_image (line 24) | def load_and_compress_image(image_path: Path) -> tuple:
function build_messages (line 75) | def build_messages(data_uri: str, query: str) -> list:
function print_messages_structure (line 132) | def print_messages_structure(messages: list):
function call_llm (line 155) | def call_llm(messages: list):
FILE: tests/test_kimi_stream_compat.py
class KimiStreamCompatTests (line 14) | class KimiStreamCompatTests(unittest.TestCase):
method setUp (line 15) | def setUp(self):
method _restore_user_data_root (line 25) | def _restore_user_data_root(self):
method test_embedded_tool_call_sections_are_hidden_from_visible_text (line 31) | def test_embedded_tool_call_sections_are_hidden_from_visible_text(self):
method test_kimi_raw_marker_stream_falls_back_to_non_stream_and_parses_tool (line 52) | def test_kimi_raw_marker_stream_falls_back_to_non_stream_and_parses_to...
FILE: tests/test_llm_client_lite_openrouter.py
class LLMClientLiteOpenRouterTests (line 9) | class LLMClientLiteOpenRouterTests(unittest.TestCase):
method test_openrouter_model_name_is_normalized (line 10) | def test_openrouter_model_name_is_normalized(self):
method test_prefixed_openrouter_model_name_is_left_unchanged (line 19) | def test_prefixed_openrouter_model_name_is_left_unchanged(self):
method test_non_openrouter_base_url_does_not_change_model_name (line 28) | def test_non_openrouter_base_url_does_not_change_model_name(self):
FILE: tests/test_llm_client_resilience.py
class LLMClientResilienceTests (line 14) | class LLMClientResilienceTests(unittest.TestCase):
method setUp (line 15) | def setUp(self):
method _restore_user_data_root (line 25) | def _restore_user_data_root(self):
method test_first_chunk_timeout_returns_quickly_without_waiting_for_worker (line 31) | def test_first_chunk_timeout_returns_quickly_without_waiting_for_worke...
method test_non_retriable_error_stops_retry_loop_early (line 58) | def test_non_retriable_error_stops_retry_loop_early(self):
method test_retry_emits_stream_reset_before_second_attempt (line 87) | def test_retry_emits_stream_reset_before_second_attempt(self):
FILE: tests/test_llm_config_builder.py
class LlmConfigBuilderTests (line 14) | class LlmConfigBuilderTests(unittest.TestCase):
method setUp (line 15) | def setUp(self):
method test_unified_profile_builds_all_model_slots (line 20) | def test_unified_profile_builds_all_model_slots(self):
method test_split_profiles_support_local_model_without_api_key (line 40) | def test_split_profiles_support_local_model_without_api_key(self):
method test_sdk_materializes_model_profiles_to_runtime_yaml (line 63) | def test_sdk_materializes_model_profiles_to_runtime_yaml(self):
FILE: tests/test_llm_debug_output.py
class LlmDebugOutputTests (line 14) | class LlmDebugOutputTests(unittest.TestCase):
method setUp (line 15) | def setUp(self):
method _restore_user_data_root (line 25) | def _restore_user_data_root(self):
method test_task_scoped_debug_records_append_to_conversation_jsonl (line 31) | def test_task_scoped_debug_records_append_to_conversation_jsonl(self):
method test_debug_records_without_task_fall_back_to_runtime_debug_dir (line 69) | def test_debug_records_without_task_fall_back_to_runtime_debug_dir(self):
FILE: tests/test_reasoning_modes.py
class _DummyEmitter (line 10) | class _DummyEmitter:
method dispatch (line 11) | def dispatch(self, _event):
class ReasoningModeTests (line 15) | class ReasoningModeTests(unittest.TestCase):
method _bare_executor (line 16) | def _bare_executor(self):
method test_build_messages_includes_react_reflection_and_text_only_turns (line 29) | def test_build_messages_includes_react_reflection_and_text_only_turns(...
method test_run_react_reflection_persists_text_to_action_history (line 72) | def test_run_react_reflection_persists_text_to_action_history(self):
method test_model_output_payload_prefers_last_execution_turn_over_react_reflection (line 105) | def test_model_output_payload_prefers_last_execution_turn_over_react_r...
FILE: tests/test_sdk_observability.py
class _FakeEventEmitter (line 18) | class _FakeEventEmitter:
method __init__ (line 19) | def __init__(self):
method dispatch (line 22) | def dispatch(self, event):
class _FakeAgentExecutor (line 26) | class _FakeAgentExecutor:
method __init__ (line 30) | def __init__(
method run (line 49) | def run(self, task_id, user_input):
class SDKObservabilityTests (line 100) | class SDKObservabilityTests(unittest.TestCase):
method setUp (line 101) | def setUp(self):
method test_run_can_collect_structured_events_and_callback (line 106) | def test_run_can_collect_structured_events_and_callback(self):
method test_run_can_optionally_collect_stream_token_events (line 135) | def test_run_can_optionally_collect_stream_token_events(self):
method test_llm_stream_callback_maps_reset_events_and_attempts (line 162) | def test_llm_stream_callback_maps_reset_events_and_attempts(self):
method test_run_can_override_max_turns_via_sdk_parameter (line 195) | def test_run_can_override_max_turns_via_sdk_parameter(self):
method test_run_raise_on_error_turns_error_result_into_exception (line 213) | def test_run_raise_on_error_turns_error_result_into_exception(self):
method test_task_trace_reads_agent_action_files (line 242) | def test_task_trace_reads_agent_action_files(self):
method test_agent_executor_returns_error_result_in_library_mode (line 294) | def test_agent_executor_returns_error_result_in_library_mode(self):
method test_agent_executor_can_raise_catchable_exception_in_library_mode (line 314) | def test_agent_executor_can_raise_catchable_exception_in_library_mode(...
method test_agent_executor_result_enrichment_exposes_raw_model_outputs (line 334) | def test_agent_executor_result_enrichment_exposes_raw_model_outputs(se...
FILE: tests/test_sdk_runtime_paths.py
class SDKRuntimePathTests (line 24) | class SDKRuntimePathTests(unittest.TestCase):
method setUp (line 25) | def setUp(self):
method test_default_root_semantics_follow_current_env (line 30) | def test_default_root_semantics_follow_current_env(self):
method test_custom_user_data_root_applies_to_sdk_and_runtime_control (line 48) | def test_custom_user_data_root_applies_to_sdk_and_runtime_control(self):
method test_task_tools_follow_custom_user_data_root (line 68) | def test_task_tools_follow_custom_user_data_root(self):
method test_user_data_root_alone_is_enough_for_agent_library_loading (line 93) | def test_user_data_root_alone_is_enough_for_agent_library_loading(self):
method test_sdk_requires_explicit_task_id (line 113) | def test_sdk_requires_explicit_task_id(self):
method test_runtime_settings_support_new_reasoning_fields (line 118) | def test_runtime_settings_support_new_reasoning_fields(self):
method test_sdk_build_launch_config_includes_visible_skills_and_reasoning_fields (line 159) | def test_sdk_build_launch_config_includes_visible_skills_and_reasoning...
method test_run_explicit_reasoning_overrides_take_priority (line 177) | def test_run_explicit_reasoning_overrides_take_priority(self):
method test_sdk_instances_do_not_leak_user_data_roots (line 240) | def test_sdk_instances_do_not_leak_user_data_roots(self):
method test_run_returns_busy_when_task_already_running (line 263) | def test_run_returns_busy_when_task_already_running(self):
method test_background_task_launch_uses_user_data_root (line 276) | def test_background_task_launch_uses_user_data_root(self):
method test_task_snapshot_falls_back_to_history_final_output (line 309) | def test_task_snapshot_falls_back_to_history_final_output(self):
method test_tool_hooks_are_exposed_in_launch_config (line 348) | def test_tool_hooks_are_exposed_in_launch_config(self):
method test_context_hooks_are_exposed_in_launch_config (line 361) | def test_context_hooks_are_exposed_in_launch_config(self):
method test_max_turns_is_exposed_in_launch_config (line 373) | def test_max_turns_is_exposed_in_launch_config(self):
method test_add_message_resume_if_needed_uses_resume_when_stack_exists (line 383) | def test_add_message_resume_if_needed_uses_resume_when_stack_exists(se...
method test_add_message_resume_if_needed_launches_new_task_when_stack_empty (line 419) | def test_add_message_resume_if_needed_launches_new_task_when_stack_emp...
FILE: tests/test_task_history_index.py
class _DummyHierarchyManager (line 16) | class _DummyHierarchyManager:
method __init__ (line 17) | def __init__(self, context):
method get_context (line 20) | def get_context(self):
method _save_context (line 23) | def _save_context(self, context):
class _DummyConfigLoader (line 27) | class _DummyConfigLoader:
class TaskHistoryIndexTests (line 32) | class TaskHistoryIndexTests(unittest.TestCase):
method setUp (line 33) | def setUp(self):
method _sample_context (line 38) | def _sample_context(self, task_id: str):
method test_sync_and_sql_search_return_instruction_bundle (line 72) | def test_sync_and_sql_search_return_instruction_bundle(self):
method test_task_history_search_tool_reads_index (line 84) | def test_task_history_search_tool_reads_index(self):
method test_task_history_records_default_returns_all_entries_for_task (line 96) | def test_task_history_records_default_returns_all_entries_for_task(self):
method test_task_history_records_support_start_round (line 106) | def test_task_history_records_support_start_round(self):
method test_recent_history_selection_uses_new_setting (line 132) | def test_recent_history_selection_uses_new_setting(self):
FILE: tests/test_thinking_prompt_contract.py
class _StubThinkingLLMClient (line 13) | class _StubThinkingLLMClient:
method resolve_model (line 14) | def resolve_model(self, category, preferred_model=None):
method resolve_tool_choice (line 17) | def resolve_tool_choice(self, category, model):
method chat (line 20) | def chat(self, **kwargs):
class ThinkingPromptContractTests (line 30) | class ThinkingPromptContractTests(unittest.TestCase):
method setUp (line 31) | def setUp(self):
method _restore_user_data_root (line 38) | def _restore_user_data_root(self):
method test_thinking_system_prompt_requires_inner_content_only (line 44) | def test_thinking_system_prompt_requires_inner_content_only(self):
method test_initial_analysis_request_requires_inner_content_only (line 53) | def test_initial_analysis_request_requires_inner_content_only(self):
FILE: tests/test_tool_hooks.py
class ToolHooksTests (line 15) | class ToolHooksTests(unittest.TestCase):
method test_after_hook_triggers_with_result_filter (line 16) | def test_after_hook_triggers_with_result_filter(self):
FILE: tests/test_web_ui_config_api.py
function _load_web_server (line 15) | def _load_web_server(tmp_path):
function _auth_client (line 26) | def _auth_client(app):
function test_guided_config_roundtrip_and_run_env_list (line 35) | def test_guided_config_roundtrip_and_run_env_list(tmp_path):
FILE: tool_server_lite/llm_client_lite.py
class LLMClientLite (line 34) | class LLMClientLite:
method __init__ (line 37) | def __init__(self, llm_config_path: str = None):
method _parse_models (line 99) | def _parse_models(self, models_config: list, target_list: list, catego...
method resolve_model (line 121) | def resolve_model(self, category: str = "execution", preferred: Option...
method _get_model_api_key (line 137) | def _get_model_api_key(self, model: str) -> str:
method _get_model_base_url (line 141) | def _get_model_base_url(self, model: str) -> str:
method _is_openrouter_base_url (line 146) | def _is_openrouter_base_url(base_url: Optional[str]) -> bool:
method _normalize_openrouter_model_name (line 150) | def _normalize_openrouter_model_name(model: str, base_url: Optional[st...
method _extract_image_urls_from_completion_message (line 161) | def _extract_image_urls_from_completion_message(message) -> list[str]:
method _create_image_via_litellm_completion (line 186) | def _create_image_via_litellm_completion(
method _create_image_via_openrouter_sdk (line 258) | def _create_image_via_openrouter_sdk(
method reload_config (line 341) | def reload_config(self):
method vision_query (line 381) | def vision_query(
method create_image (line 463) | def create_image(
method audio_query (line 542) | def audio_query(
method text_query (line 658) | def text_query(
function get_llm_client (line 715) | def get_llm_client(force_reload: bool = False) -> LLMClientLite:
function reload_llm_client (line 763) | def reload_llm_client() -> LLMClientLite:
FILE: tool_server_lite/registry.py
function _build_builtin_factories (line 29) | def _build_builtin_factories() -> Dict[str, ToolFactory]:
function get_builtin_tool_factories (line 152) | def get_builtin_tool_factories() -> Dict[str, ToolFactory]:
function _load_module_from_path (line 156) | def _load_module_from_path(file_path: Path) -> types.ModuleType:
function _is_valid_custom_tool_class (line 166) | def _is_valid_custom_tool_class(obj: Any, module_name: str) -> bool:
function _discover_custom_tool_class (line 180) | def _discover_custom_tool_class(module: types.ModuleType) -> type:
function _instantiate_custom_tool (line 192) | def _instantiate_custom_tool(file_path: Path) -> Tuple[str, Any, Dict[st...
function build_runtime_registry (line 218) | def build_runtime_registry() -> Tuple[Dict[str, Any], Dict[str, Dict[str...
function reload_runtime_registry (line 292) | def reload_runtime_registry() -> Tuple[Dict[str, Any], Dict[str, Dict[st...
function get_runtime_registry (line 298) | def get_runtime_registry(force_reload: bool = False) -> Dict[str, Any]:
function get_runtime_registry_metadata (line 305) | def get_runtime_registry_metadata(force_reload: bool = False) -> Dict[st...
function get_runtime_registry_failures (line 312) | def get_runtime_registry_failures(force_reload: bool = False) -> List[Di...
FILE: tool_server_lite/tools/arxiv_tools.py
class ArxivSearchTool (line 20) | class ArxivSearchTool(BaseTool):
method execute (line 23) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
FILE: tool_server_lite/tools/audio_tools.py
class AudioTool (line 16) | class AudioTool(BaseTool):
method execute (line 19) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
FILE: tool_server_lite/tools/browser_tools.py
function _random_delay (line 30) | def _random_delay(min_ms: int = 50, max_ms: int = 150) -> float:
function _generate_bezier_curve (line 35) | def _generate_bezier_curve(start: Tuple[float, float], end: Tuple[float,...
function _human_like_mouse_move (line 88) | async def _human_like_mouse_move(page: Page, target_x: float, target_y: ...
function _human_like_click (line 115) | async def _human_like_click(page: Page, selector: str = None, x: float =...
function _human_like_type (line 159) | async def _human_like_type(page: Page, selector: str, text: str, delay_r...
function _auto_snapshot_loop (line 184) | async def _auto_snapshot_loop(browser_id: str, task_id: str, interval_se...
function _get_browser_dir (line 210) | def _get_browser_dir(task_id: str, browser_id: str) -> Path:
function _save_screenshot (line 218) | async def _save_screenshot(page: Page, browser_id: str, task_id: str):
function _save_page_snapshot (line 226) | async def _save_page_snapshot(page: Page, browser_id: str, task_id: str):
function _save_page_content (line 233) | async def _save_page_content(page: Page, browser_id: str, task_id: str):
function _save_accessibility_tree (line 250) | async def _save_accessibility_tree(page: Page, browser_id: str, task_id:...
function _flatten_accessibility_tree (line 400) | def _flatten_accessibility_tree(node: dict, elements: list = None) -> list:
class BrowserLaunchTool (line 428) | class BrowserLaunchTool(BaseTool):
method execute_async (line 431) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserListSessionsTool (line 592) | class BrowserListSessionsTool(BaseTool):
method execute_async (line 595) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserCloseTool (line 660) | class BrowserCloseTool(BaseTool):
method execute_async (line 663) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserNewPageTool (line 720) | class BrowserNewPageTool(BaseTool):
method execute_async (line 723) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserSwitchPageTool (line 775) | class BrowserSwitchPageTool(BaseTool):
method execute_async (line 778) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserClosePageTool (line 835) | class BrowserClosePageTool(BaseTool):
method execute_async (line 838) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserListPagesTool (line 910) | class BrowserListPagesTool(BaseTool):
method execute_async (line 913) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserNavigateTool (line 971) | class BrowserNavigateTool(BaseTool):
method execute_async (line 974) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserSnapshotTool (line 1033) | class BrowserSnapshotTool(BaseTool):
method execute_async (line 1036) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserExecuteJsTool (line 1108) | class BrowserExecuteJsTool(BaseTool):
method execute_async (line 1111) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserClickTool (line 1183) | class BrowserClickTool(BaseTool):
method execute_async (line 1186) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserTypeTool (line 1253) | class BrowserTypeTool(BaseTool):
method execute_async (line 1256) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserWaitTool (line 1331) | class BrowserWaitTool(BaseTool):
method execute_async (line 1334) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserMouseMoveTool (line 1421) | class BrowserMouseMoveTool(BaseTool):
method execute_async (line 1424) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserMouseClickCoordsTool (line 1481) | class BrowserMouseClickCoordsTool(BaseTool):
method execute_async (line 1484) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserDragAndDropTool (line 1554) | class BrowserDragAndDropTool(BaseTool):
method execute_async (line 1557) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserHoverTool (line 1645) | class BrowserHoverTool(BaseTool):
method execute_async (line 1648) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
class BrowserScrollTool (line 1739) | class BrowserScrollTool(BaseTool):
method execute_async (line 1742) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
FILE: tool_server_lite/tools/code_tools.py
function has_running_background_processes (line 31) | def has_running_background_processes(task_id: str = None) -> bool:
class ExecuteCodeTool (line 54) | class ExecuteCodeTool(BaseTool):
method _create_venv (line 57) | def _create_venv(self, venv_path: Path) -> Tuple[bool, str]:
method execute (line 117) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
method _get_python_exec (line 207) | def _get_python_exec(self, workspace: Path, use_venv: bool) -> Path:
method _execute_python (line 231) | def _execute_python(self, workspace: Path, code_file: Path, exec_dir: ...
method _execute_python_background (line 285) | def _execute_python_background(self, workspace: Path, code_file: Path,...
class PipInstallTool (line 345) | class PipInstallTool(BaseTool):
method _create_venv (line 348) | def _create_venv(self, venv_path: Path) -> Tuple[bool, str]:
method execute (line 405) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class ExecuteCommandTool (line 497) | class ExecuteCommandTool(BaseTool):
method _is_command_safe (line 547) | def _is_command_safe(self, command: str) -> tuple[bool, str]:
method _use_system_terminal_mode (line 595) | def _use_system_terminal_mode(self) -> bool:
method _escape_applescript_str (line 600) | def _escape_applescript_str(self, s: str) -> str:
method _run_osascript (line 603) | def _run_osascript(self, script: str, timeout: int = 10) -> str:
method _find_idle_terminal_window_id (line 616) | def _find_idle_terminal_window_id(self) -> Optional[int]:
method _terminal_window_exists (line 643) | def _terminal_window_exists(self, window_id: int) -> bool:
method _close_tagged_terminal_windows (line 654) | def _close_tagged_terminal_windows(self) -> None:
method _list_tagged_terminal_ttys (line 688) | def _list_tagged_terminal_ttys(self) -> list[str]:
method _force_reset_tagged_terminal_windows (line 714) | def _force_reset_tagged_terminal_windows(self) -> None:
method _wait_for_terminal_window_idle (line 742) | def _wait_for_terminal_window_idle(
method _get_tagged_terminal_tty (line 780) | def _get_tagged_terminal_tty(self, window_id: int) -> Optional[str]:
method _interrupt_terminal_window_processes (line 797) | def _interrupt_terminal_window_processes(self, window_id: int) -> bool:
method _get_or_create_terminal_window_id (line 867) | def _get_or_create_terminal_window_id(self, force_new: bool = False) -...
method _launch_terminal_script (line 908) | def _launch_terminal_script(self, script_path: Path) -> int:
method _build_terminal_paths (line 984) | def _build_terminal_paths(self, workspace: Path, output_path: Optional...
method _write_terminal_script (line 994) | def _write_terminal_script(
method _run_via_terminal_foreground (line 1011) | def _run_via_terminal_foreground(
method _run_via_terminal_background (line 1073) | def _run_via_terminal_background(
method execute (line 1115) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class GrepTool (line 1312) | class GrepTool(BaseTool):
method execute (line 1315) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class CodeProcessManagerTool (line 1478) | class CodeProcessManagerTool(BaseTool):
method execute (line 1481) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
method _list_processes (line 1517) | def _list_processes(self, task_id: str) -> Dict[str, Any]:
method _kill_process (line 1569) | def _kill_process(self, task_id: str, process_id: str) -> Dict[str, Any]:
FILE: tool_server_lite/tools/convert_tools.py
function load_convert_api_config (line 19) | def load_convert_api_config() -> str:
class MarkdownToPdfTool (line 41) | class MarkdownToPdfTool(BaseTool):
method execute (line 44) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class TexToPdfTool (line 118) | class TexToPdfTool(BaseTool):
method execute (line 121) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class MarkdownToDocxTool (line 234) | class MarkdownToDocxTool(BaseTool):
method execute (line 237) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
FILE: tool_server_lite/tools/document_tools.py
class ParseDocumentTool (line 12) | class ParseDocumentTool(BaseTool):
method execute (line 15) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
method _parse_pdf (line 90) | def _parse_pdf(self, pdf_path: Path, task_id: str, extract_images: boo...
method _parse_word (line 150) | def _parse_word(self, doc_path: Path, task_id: str, extract_images: bo...
method _table_to_markdown (line 202) | def _table_to_markdown(self, table_data: List[List[str]]) -> str:
method _save_pdf_image (line 224) | def _save_pdf_image(self, page, img_info: Dict, task_id: str, images_d...
FILE: tool_server_lite/tools/file_tools.py
class BaseTool (line 13) | class BaseTool:
method execute (line 16) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
function get_abs_path (line 21) | def get_abs_path(task_id: str, relative_path: str) -> Path:
function detect_encoding (line 38) | def detect_encoding(file_path: Path) -> str:
function is_binary_file (line 67) | def is_binary_file(file_path: Path) -> bool:
class FileReadTool (line 88) | class FileReadTool(BaseTool):
method execute (line 91) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
method _read_single_file (line 140) | def _read_single_file(self, task_id: str, path: str, parameters: Dict[...
method _read_multiple_files (line 204) | def _read_multiple_files(self, task_id: str, paths: list, parameters: ...
class FileWriteTool (line 299) | class FileWriteTool(BaseTool):
method execute (line 302) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class DirListTool (line 384) | class DirListTool(BaseTool):
method execute (line 387) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
method _list_recursive (line 437) | def _list_recursive(self, root: Path, current: Path, indent: int = 0) ...
class DirCreateTool (line 461) | class DirCreateTool(BaseTool):
method execute (line 464) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class FileMoveTool (line 491) | class FileMoveTool(BaseTool):
method execute (line 494) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class FileDeleteTool (line 549) | class FileDeleteTool(BaseTool):
method execute (line 552) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
FILE: tool_server_lite/tools/human_tools.py
class HumanInLoopTool (line 20) | class HumanInLoopTool(BaseTool):
method execute_async (line 23) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
function get_hil_status (line 113) | def get_hil_status(hil_id: str) -> Dict[str, Any]:
function respond_hil_task (line 131) | def respond_hil_task(hil_id: str, response: str) -> Dict[str, Any]:
function list_hil_tasks (line 150) | def list_hil_tasks() -> Dict[str, Any]:
function get_hil_task_for_workspace (line 167) | def get_hil_task_for_workspace(task_id: str) -> Dict[str, Any]:
function create_tool_confirmation (line 185) | def create_tool_confirmation(confirm_id: str, task_id: str, tool_name: s...
function get_tool_confirmation_status (line 212) | def get_tool_confirmation_status(confirm_id: str) -> Dict[str, Any]:
function respond_tool_confirmation (line 232) | def respond_tool_confirmation(confirm_id: str, approved: bool) -> Dict[s...
function get_tool_confirmation_for_workspace (line 251) | def get_tool_confirmation_for_workspace(task_id: str) -> Dict[str, Any]:
function list_tool_confirmations (line 268) | def list_tool_confirmations() -> Dict[str, Any]:
FILE: tool_server_lite/tools/paper_tools.py
class PaperAnalyzeTool (line 14) | class PaperAnalyzeTool(BaseTool):
method execute (line 17) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
FILE: tool_server_lite/tools/powerpoint_tools.py
class ImagesToPptTool (line 20) | class ImagesToPptTool(BaseTool):
method execute (line 23) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
FILE: tool_server_lite/tools/reference_tools.py
class ReferenceListTool (line 13) | class ReferenceListTool(BaseTool):
method execute (line 16) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class ReferenceAddTool (line 64) | class ReferenceAddTool(BaseTool):
method execute (line 67) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class ReferenceDeleteTool (line 157) | class ReferenceDeleteTool(BaseTool):
method execute (line 160) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
method _parse_bib_entries (line 254) | def _parse_bib_entries(self, content: str) -> List[Dict[str, str]]:
FILE: tool_server_lite/tools/skill_tools.py
class LoadSkillTool (line 15) | class LoadSkillTool(BaseTool):
method __init__ (line 23) | def __init__(self):
method execute (line 27) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class OffloadSkillTool (line 119) | class OffloadSkillTool(BaseTool):
method execute (line 125) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class FreshTool (line 141) | class FreshTool(BaseTool):
method execute (line 151) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
FILE: tool_server_lite/tools/task_tools.py
class AddMessageTool (line 30) | class AddMessageTool(BaseTool):
method execute (line 35) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class StartBackgroundTaskTool (line 80) | class StartBackgroundTaskTool(BaseTool):
method execute (line 85) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class TaskShareContextPathTool (line 136) | class TaskShareContextPathTool(BaseTool):
method execute (line 141) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class ListTaskIdsTool (line 163) | class ListTaskIdsTool(BaseTool):
method execute (line 168) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class TaskHistorySearchTool (line 194) | class TaskHistorySearchTool(BaseTool):
method execute (line 199) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
FILE: tool_server_lite/tools/vision_tools.py
class ImageReadTool (line 22) | class ImageReadTool(BaseTool):
method __init__ (line 31) | def __init__(self):
method multimodal (line 36) | def multimodal(self) -> bool:
method execute (line 49) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
method _compress_single_image (line 122) | def _compress_single_image(self, abs_image_path: Path) -> tuple:
method _execute_multimodal_batch (line 197) | def _execute_multimodal_batch(self, abs_paths: list, query: str) -> Di...
method _execute_text_only (line 231) | def _execute_text_only(self, abs_image_path: Path, image_path: str, qu...
class VisionTool (line 274) | class VisionTool(BaseTool):
method execute (line 277) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class CreateImageTool (line 356) | class CreateImageTool(BaseTool):
method execute (line 359) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
FILE: tool_server_lite/tools/web_tools.py
function _get_field (line 36) | def _get_field(obj: Any, name: str, default: Any = None) -> Any:
class CrawlPageTool (line 51) | class CrawlPageTool(BaseTool):
method _crawl4ai_unavailable_error (line 55) | def _crawl4ai_unavailable_error() -> str:
method _normalize_runtime_error_message (line 65) | def _normalize_runtime_error_message(error: Exception) -> str:
method execute_async (line 77) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
method _crawl_page (line 138) | async def _crawl_page(self, url: str) -> str:
class GoogleScholarSearchTool (line 188) | class GoogleScholarSearchTool(BaseTool):
method execute_async (line 191) | async def execute_async(self, task_id: str, parameters: Dict[str, Any]...
method _crawl_scholar (line 289) | async def _crawl_scholar(self, query: str, year_low: int, year_high: i...
class WebSearchTool (line 330) | class WebSearchTool(BaseTool):
method execute (line 333) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
class FileDownloadTool (line 415) | class FileDownloadTool(BaseTool):
method execute (line 418) | def execute(self, task_id: str, parameters: Dict[str, Any]) -> Dict[st...
FILE: utils/cli_mode.py
function t (line 45) | def t(key: str, lang: str = 'en') -> str:
class InteractiveCLI (line 221) | class InteractiveCLI:
method __init__ (line 224) | def __init__(self, task_id: str, agent_system: str = "Test_agent"):
method t (line 258) | def t(self, key: str) -> str:
method _load_available_agents (line 262) | def _load_available_agents(self):
method _check_hil_task (line 279) | def _check_hil_task(self) -> dict:
method _respond_hil_task (line 283) | def _respond_hil_task(self, hil_id: str, response: str) -> bool:
method _check_tool_confirmation (line 291) | def _check_tool_confirmation(self) -> dict:
method _respond_tool_confirmation (line 295) | def _respond_tool_confirmation(self, confirm_id: str, approved: bool) ...
method _get_interrupted_task (line 303) | def _get_interrupted_task(self) -> dict:
method _start_hil_checker (line 347) | def _start_hil_checker(self):
method _send_control_message (line 387) | def _send_control_message(self, payload: dict) -> bool:
method _show_hil_prompt (line 398) | def _show_hil_prompt(self, hil_id: str, instruction: str):
method _show_tool_confirmation_prompt (line 410) | def _show_tool_confirmation_prompt(self, confirm_id: str, tool_name: s...
method get_banner_text (line 430) | def get_banner_text(self):
method show_banner (line 448) | def show_banner(self):
method parse_input (line 483) | def parse_input(self, user_input: str):
method stop_current_task (line 517) | def stop_current_task(self):
method run_task (line 543) | def run_task(self, agent_name: str, user_input: str):
method get_bottom_toolbar (line 831) | def get_bottom_toolbar(self):
method run (line 842) | def run(self):
function get_available_agent_systems (line 1154) | def get_available_agent_systems():
function start_cli_mode (line 1169) | def start_cli_mode(agent_system: str = None, language: str = 'en'):
FILE: utils/config_loader.py
class ConfigLoader (line 15) | class ConfigLoader:
method __init__ (line 18) | def __init__(self, agent_system_name: str = "infiHelper", agent_librar...
method _find_config_root (line 43) | def _find_config_root(self) -> str:
method _find_agent_system_dir (line 52) | def _find_agent_system_dir(self, agent_system_name: str) -> str:
method _load_general_prompts (line 73) | def _load_general_prompts(self) -> Dict:
method _load_all_tools (line 89) | def _load_all_tools(self) -> Dict[str, Dict]:
method _inject_framework_default_tools (line 104) | def _inject_framework_default_tools(self):
method get_tool_config (line 147) | def get_tool_config(self, tool_name: str) -> Dict:
method _normalize_agent_runtime_config (line 173) | def _normalize_agent_runtime_config(self, config: Dict[str, Any]) -> D...
method build_agent_system_prompt (line 210) | def build_agent_system_prompt(self, agent_config: Dict) -> str:
method get_available_tools_by_level (line 220) | def get_available_tools_by_level(self, level: int) -> List[str]:
FILE: utils/config_manager.py
function get_config_path (line 14) | def get_config_path(config_name: str = "llm_config") -> Path:
function show_config (line 22) | def show_config(config_name: str = "llm_config"):
function set_config (line 39) | def set_config(key: str, value: str, config_name: str = "llm_config"):
function reset_config (line 97) | def reset_config(config_name: str = "llm_config"):
FILE: utils/context_hooks.py
function _load_callback (line 14) | def _load_callback(callback_spec: str):
function _load_context_hooks (line 37) | def _load_context_hooks() -> List[Dict[str, Any]]:
function apply_context_hooks (line 48) | def apply_context_hooks(
FILE: utils/conversation_storage.py
class ConversationStorage (line 17) | class ConversationStorage:
method __init__ (line 20) | def __init__(self, task_id: str = None):
method _generate_filename (line 26) | def _generate_filename(self, task_id: str, agent_id: str) -> str:
method save_actions (line 39) | def save_actions(self, task_id: str, agent_id: str, agent_name: str,
method load_actions (line 91) | def load_actions(self, task_id: str, agent_id: str) -> Dict:
FILE: utils/event_emitter.py
class EventEmitter (line 13) | class EventEmitter:
method __init__ (line 16) | def __init__(self, enabled: bool = False):
method emit (line 25) | def emit(self, event: Dict[str, Any]):
method start (line 38) | def start(self, call_id: str, project: str, agent: str, task: str):
method token (line 50) | def token(self, text: str):
method progress (line 60) | def progress(self, phase: str, pct: int):
method notice (line 71) | def notice(self, text: str):
method warn (line 81) | def warn(self, text: str):
method error (line 91) | def error(self, text: str):
method artifact (line 101) | def artifact(self, kind: str, path: Optional[str] = None,
method human_in_loop (line 115) | def human_in_loop(self, hil_id: str, title: str, message: str,
method result (line 132) | def result(self, ok: bool, summary: str, artifacts: Optional[List[str]...
method tool_call (line 144) | def tool_call(self, tool_name: str, parameters: Dict[str, Any]):
method agent_call (line 155) | def agent_call(self, agent_name: str, parameters: Dict[str, Any]):
method end (line 166) | def end(self, status: str, extra: Optional[Dict] = None):
function init_event_emitter (line 190) | def init_event_emitter(enabled: bool = False):
function get_event_emitter (line 197) | def get_event_emitter() -> EventEmitter:
FILE: utils/llm_config_builder.py
function normalize_provider_kind (line 25) | def normalize_provider_kind(value: Optional[str]) -> str:
function normalize_model_name (line 42) | def normalize_model_name(provider_kind: str, model_name: str) -> str:
function build_model_entry (line 64) | def build_model_entry(profile: Dict[str, Any]) -> Dict[str, Any] | str:
function build_llm_config_from_profiles (line 91) | def build_llm_config_from_profiles(
FILE: utils/mcp_manager.py
function _sanitize_name (line 36) | def _sanitize_name(name: str) -> str:
function _normalize_server_entry (line 42) | def _normalize_server_entry(raw: Any) -> Dict[str, Any] | None:
function get_mcp_servers (line 87) | def get_mcp_servers() -> List[Dict[str, Any]]:
function _open_session (line 101) | async def _open_session(server: Dict[str, Any]):
function _dump_model (line 141) | def _dump_model(obj: Any) -> Any:
function _format_tool_contents (line 154) | def _format_tool_contents(contents: List[Any]) -> str:
function _discover_mcp_tools_async (line 172) | async def _discover_mcp_tools_async() -> Tuple[Dict[str, Dict[str, Any]]...
function reload_mcp_tools (line 210) | def reload_mcp_tools() -> Tuple[Dict[str, Dict[str, Any]], List[Dict[str...
function get_mcp_tools (line 216) | def get_mcp_tools(force_reload: bool = False) -> Dict[str, Dict[str, Any]]:
function get_mcp_failures (line 223) | def get_mcp_failures(force_reload: bool = False) -> List[Dict[str, Any]]:
function _call_mcp_tool_async (line 230) | async def _call_mcp_tool_async(tool_config: Dict[str, Any], arguments: D...
function call_mcp_tool (line 252) | def call_mcp_tool(tool_config: Dict[str, Any], arguments: Dict[str, Any]...
FILE: utils/runtime_control.py
function _runtime_root (line 28) | def _runtime_root() -> Path:
function _fresh_request_dir (line 34) | def _fresh_request_dir() -> Path:
function _running_task_dir (line 40) | def _running_task_dir() -> Path:
function _task_key (line 46) | def _task_key(task_id: str) -> str:
function _fresh_request_file (line 53) | def _fresh_request_file(task_id: Optional[str]) -> Path:
function _running_task_file (line 59) | def _running_task_file(task_id: str) -> Path:
function _write_json_atomic (line 63) | def _write_json_atomic(path: Path, payload: Dict):
function _read_json (line 70) | def _read_json(path: Path) -> Optional[Dict]:
function _is_pid_alive (line 81) | def _is_pid_alive(pid: int) -> bool:
function request_fresh (line 95) | def request_fresh(reason: str = "", task_id: Optional[str] = None):
function pop_fresh_request (line 107) | def pop_fresh_request(task_id: str) -> Optional[str]:
function register_running_task (line 125) | def register_running_task(task_id: str, agent_name: str, user_input: str...
function unregister_running_task (line 147) | def unregister_running_task(task_id: str):
function get_running_task (line 171) | def get_running_task(task_id: str) -> Optional[Dict]:
function is_task_running (line 193) | def is_task_running(task_id: str) -> bool:
FILE: utils/skill_loader.py
class SkillLoader (line 21) | class SkillLoader:
method __init__ (line 24) | def __init__(self, skills_library_path: str = None):
method discover_skills (line 42) | def discover_skills(self) -> List[Dict]:
method _parse_frontmatter (line 76) | def _parse_frontmatter(self, skill_md_path: Path) -> Optional[Dict]:
method build_available_skills_xml (line 124) | def build_available_skills_xml(self, visible_skill_names: Optional[Lis...
method get_skill_source_path (line 164) | def get_skill_source_path(self, skill_name: str) -> Optional[Path]:
function get_skill_loader (line 187) | def get_skill_loader(skills_library_path: str = None) -> SkillLoader:
function reset_skill_loader (line 195) | def reset_skill_loader(skills_library_path: str = None) -> SkillLoader:
FILE: utils/task_history_index.py
function get_task_history_db_path (line 24) | def get_task_history_db_path() -> Path:
function _connect (line 30) | def _connect() -> sqlite3.Connection:
function _ensure_schema (line 37) | def _ensure_schema(conn: sqlite3.Connection) -> None:
function _json_dumps (line 93) | def _json_dumps(value: Any) -> str:
function _entry_key (line 97) | def _entry_key(task_id: str, entry: Dict[str, Any]) -> str:
function _chunk_id (line 105) | def _chunk_id(entry_key: str, chunk_type: str, instruction_index: int) -...
function _extract_top_level_agents (line 109) | def _extract_top_level_agents(entry: Dict[str, Any]) -> List[Dict[str, A...
function _extract_entry_outputs (line 134) | def _extract_entry_outputs(entry: Dict[str, Any]) -> Dict[str, str]:
function _build_instruction_bundle_text (line 159) | def _build_instruction_bundle_text(
function _build_summary_text (line 185) | def _build_summary_text(
function _build_chunks (line 210) | def _build_chunks(task_id: str, entry: Dict[str, Any], entry_index: int,...
function sync_task_history_from_context (line 290) | def sync_task_history_from_context(task_id: str, context: Optional[Dict[...
function search_task_history_sql (line 370) | def search_task_history_sql(
function _simple_cosine_similarity (line 405) | def _simple_cosine_similarity(vec_a: Sequence[float], vec_b: Sequence[fl...
function search_task_history_semantic (line 416) | def search_task_history_semantic(
function _row_to_result (line 477) | def _row_to_result(row: sqlite3.Row | Dict[str, Any]) -> Dict[str, Any]:
function _load_entry_chunks (line 498) | def _load_entry_chunks(conn: sqlite3.Connection, entry_key: str) -> List...
function _entry_to_task_result (line 512) | def _entry_to_task_result(entry_row: sqlite3.Row, chunk_rows: Sequence[s...
function search_task_history_records (line 549) | def search_task_history_records(
FILE: utils/task_runtime.py
function _task_file_prefix (line 39) | def _task_file_prefix(task_id: str) -> str:
function load_task_resume_meta (line 45) | def load_task_resume_meta(task_id: str, fallback_agent_system: Optional[...
function load_task_launch_meta (line 80) | def load_task_launch_meta(
function _parse_env_flag (line 114) | def _parse_env_flag(value: Any) -> Optional[bool]:
function _build_launch_config_from_env_overrides (line 125) | def _build_launch_config_from_env_overrides(env_overrides: Optional[Dict...
function resume_task_with_fresh (line 210) | def resume_task_with_fresh(
function append_task_message (line 278) | def append_task_message(
function get_task_share_paths (line 363) | def get_task_share_paths(task_id: str) -> Dict[str, str]:
function list_known_tasks (line 372) | def list_known_tasks(only_running: bool = False) -> Dict[str, list]:
function reset_task_state (line 403) | def reset_task_state(
function _as_root_dir (line 494) | def _as_root_dir(path: Optional[str], expected_leaf: Optional[str] = Non...
function _runtime_logs_dir (line 503) | def _runtime_logs_dir() -> Path:
function launch_task_process (line 509) | def launch_task_process(
FILE: utils/tool_hooks.py
function _load_hooks_config (line 17) | def _load_hooks_config() -> List[Dict[str, Any]]:
function _lookup_path (line 56) | def _lookup_path(payload: Any, dotted_path: str) -> Any:
function _match_filters (line 74) | def _match_filters(payload: Dict[str, Any], filters: Dict[str, Any]) -> ...
function _resolve_callback (line 89) | def _resolve_callback(spec: str) -> Callable[[Dict[str, Any]], Any]:
function trigger_tool_hooks (line 111) | def trigger_tool_hooks(
FILE: utils/user_paths.py
function get_project_root (line 26) | def get_project_root() -> Path:
function get_user_data_root (line 39) | def get_user_data_root() -> Path:
function get_user_config_dir (line 47) | def get_user_config_dir() -> Path:
function get_user_llm_config_path (line 51) | def get_user_llm_config_path() -> Path:
function get_user_app_config_path (line 58) | def get_user_app_config_path() -> Path:
function get_user_agent_library_root (line 62) | def get_user_agent_library_root() -> Path:
function get_agent_hidden_root (line 66) | def get_agent_hidden_root() -> Path:
function get_user_skills_library_root (line 71) | def get_user_skills_library_root() -> Path:
function get_user_tools_library_root (line 78) | def get_user_tools_library_root() -> Path:
function get_user_conversations_dir (line 85) | def get_user_conversations_dir() -> Path:
function get_user_logs_dir (line 89) | def get_user_logs_dir() -> Path:
function get_user_runtime_dir (line 93) | def get_user_runtime_dir() -> Path:
function get_user_runtime_logs_dir (line 97) | def get_user_runtime_logs_dir() -> Path:
function get_user_runtime_events_dir (line 101) | def get_user_runtime_events_dir() -> Path:
function get_user_task_history_dir (line 105) | def get_user_task_history_dir() -> Path:
function get_task_file_prefix (line 109) | def get_task_file_prefix(task_id: str) -> str:
function ensure_user_data_root_scaffold (line 119) | def ensure_user_data_root_scaffold() -> None:
function _seed_directory_children (line 136) | def _seed_directory_children(src_root: Path, dest_root: Path) -> None:
function seed_user_resources_if_missing (line 149) | def seed_user_resources_if_missing() -> None:
function _blank_api_keys (line 164) | def _blank_api_keys(value: Any) -> Any:
function ensure_user_llm_config_exists (line 178) | def ensure_user_llm_config_exists() -> Path:
function ensure_user_app_config_exists (line 224) | def ensure_user_app_config_exists() -> Path:
function load_user_app_config (line 258) | def load_user_app_config() -> Dict[str, Any]:
function get_mcp_settings (line 270) | def get_mcp_settings() -> Dict[str, Any]:
function get_runtime_settings (line 291) | def get_runtime_settings() -> Dict[str, Any]:
function get_context_settings (line 350) | def get_context_settings() -> Dict[str, Any]:
function get_default_command_mode (line 367) | def get_default_command_mode() -> str:
function get_seed_builtin_resources_enabled (line 384) | def get_seed_builtin_resources_enabled() -> bool:
function apply_runtime_env_defaults (line 392) | def apply_runtime_env_defaults() -> None:
function runtime_env_scope (line 434) | def runtime_env_scope(overrides: Optional[Dict[str, Any]] = None) -> Ite...
FILE: utils/windows_compat.py
function setup_console_encoding (line 10) | def setup_console_encoding():
function safe_print (line 25) | def safe_print(*args, **kwargs):
FILE: web_ui/server/output_capture.py
class OutputCapture (line 19) | class OutputCapture:
method __init__ (line 22) | def __init__(self, callback: Callable[[dict], None], agent_name: str =...
method start (line 139) | def start(self):
method stop (line 144) | def stop(self):
method write (line 157) | def write(self, text: str):
method _is_important (line 408) | def _is_important(self, text: str) -> bool:
method _is_noise (line 445) | def _is_noise(self, text: str) -> bool:
method _flush_buffer (line 453) | def _flush_buffer(self):
method _output_call_with_params (line 479) | def _output_call_with_params(self):
method _output_final_output_with_result (line 514) | def _output_final_output_with_result(self):
method flush (line 550) | def flush(self):
method _extract_agent_name (line 554) | def _extract_agent_name(self, text: str) -> Optional[str]:
method _determine_message_type (line 562) | def _determine_message_type(self, text: str) -> str:
method set_agent (line 585) | def set_agent(self, agent_name: str):
method parse_jsonl_event (line 590) | def parse_jsonl_event(self, line: str):
FILE: web_ui/server/sdk_worker.py
function emit_json (line 32) | def emit_json(payload: Dict[str, Any]) -> None:
class WorkerBridgeEmitter (line 38) | class WorkerBridgeEmitter:
method __init__ (line 39) | def __init__(self):
method emit (line 44) | def emit(self, event: Dict[str, Any]):
method start (line 51) | def start(self, call_id: str, project: str, agent: str, task: str):
method token (line 55) | def token(self, text: str):
method progress (line 59) | def progress(self, phase: str, pct: int):
method notice (line 62) | def notice(self, text: str):
method warn (line 65) | def warn(self, text: str):
method error (line 68) | def error(self, text: str):
method artifact (line 71) | def artifact(self, kind: str, path: str = None, summary: str = None, p...
method human_in_loop (line 80) | def human_in_loop(self, hil_id: str, title: str, message: str, ui: Dic...
method result (line 91) | def result(self, ok: bool, summary: str, artifacts=None):
method end (line 99) | def end(self, status: str, extra: Dict[str, Any] = None):
function map_sdk_event (line 110) | def map_sdk_event(event: Dict[str, Any]) -> Dict[str, Any] | None:
function start_control_thread (line 190) | def start_control_thread() -> None:
function main (line 218) | def main() -> int:
FILE: web_ui/server/server.py
function get_user_workspace (line 99) | def get_user_workspace(username: str) -> Path:
function get_user_execution (line 106) | def get_user_execution(username: str) -> dict:
function ensure_user_runtime_ready (line 123) | def ensure_user_runtime_ready(username: str) -> Path:
function get_user_runtime_overrides (line 127) | def get_user_runtime_overrides(username: str) -> dict:
function get_agent_system_dir (line 139) | def get_agent_system_dir(username: str, agent_system: str) -> Path:
function get_run_env_config_dir (line 144) | def get_run_env_config_dir(username: str) -> Path:
function get_config_dir_for_type (line 151) | def get_config_dir_for_type(username: str, config_type: str, agent_syste...
function validate_config_filename (line 159) | def validate_config_filename(filename: str, config_type: str) -> None:
function ensure_config_path (line 171) | def ensure_config_path(config_dir: Path, filename: str) -> Path:
function parse_config_text (line 180) | def parse_config_text(filename: str, content: str):
function dump_config_text (line 186) | def dump_config_text(filename: str, payload) -> str:
function sanitize_tool_name (line 192) | def sanitize_tool_name(raw_name: str) -> str:
function collect_tool_bindings (line 199) | def collect_tool_bindings(username: str) -> dict:
function normalize_task_id (line 234) | def normalize_task_id(task_id: str, username: str = None) -> tuple[Path,...
function normalize_file_path (line 291) | def normalize_file_path(path: str, task_id: str = None, username: str = ...
function login_required (line 341) | def login_required(f):
function admin_required (line 352) | def admin_required(f):
function run_agent_task (line 365) | def run_agent_task(task_id: str, agent_name: str, user_input: str,
function index (line 569) | def index():
function login (line 578) | def login():
function register (line 606) | def register():
function logout (line 628) | def logout():
function check_auth (line 638) | def check_auth():
function health (line 654) | def health():
function api_list_users (line 664) | def api_list_users():
function api_create_user (line 675) | def api_create_user():
function api_update_user (line 690) | def api_update_user(username: str):
function api_delete_user (line 712) | def api_delete_user(username: str):
function run_task (line 722) | def run_task():
function confirm_task (line 1196) | def confirm_task():
function stop_task (line 1274) | def stop_task():
function get_agents (line 1329) | def get_agents():
function get_agent_systems (line 1361) | def get_agent_systems():
function check_resume (line 1381) | def check_resume():
function get_status (line 1443) | def get_status():
function list_tasks (line 1469) | def list_tasks():
function list_files (line 1510) | def list_files():
function read_file (line 1577) | def read_file():
function clear_task (line 1632) | def clear_task():
function get_copy_progress (line 1729) | def get_copy_progress(username: str, task_id: str) -> dict:
function set_copy_progress (line 1736) | def set_copy_progress(username: str, task_id: str, status: str, progress...
function clear_copy_progress (line 1743) | def clear_copy_progress(username: str, task_id: str):
function copy_tree_with_progress (line 1751) | def copy_tree_with_progress(src: Path, dst: Path, username: str, task_id...
function copy_task (line 1796) | def copy_task():
function get_copy_progress_api (line 1881) | def get_copy_progress_api():
function download_task (line 1900) | def download_task():
function delete_file (line 1999) | def delete_file():
function get_chat_history (line 2037) | def get_chat_history():
function create_latest_output (line 2082) | def create_latest_output(chat_history_file: Path):
function save_chat_message (line 2138) | def save_chat_message():
function upload_file (line 2338) | def upload_file():
function preview_file (line 2449) | def preview_file():
function download_file (line 2496) | def download_file():
function check_hil_task (line 2551) | def check_hil_task():
function respond_hil_task (line 2575) | def respond_hil_task():
function respond_tool_confirmation (line 2610) | def respond_tool_confirmation():
function list_runtime_tools (line 2644) | def list_runtime_tools():
function reload_runtime_tools (line 2683) | def reload_runtime_tools():
function upload_runtime_tool (line 2700) | def upload_runtime_tool():
function delete_runtime_tool (line 2741) | def delete_runtime_tool(tool_name):
function list_config_files (line 2772) | def list_config_files():
function read_config_file (line 2824) | def read_config_file():
function get_agent_tree (line 2872) | def get_agent_tree():
function save_config_file (line 3006) | def save_config_file():
function get_guided_config (line 3053) | def get_guided_config():
function save_guided_config (line 3080) | def save_guided_config():
FILE: web_ui/server/user_accounts.py
function _now_iso (line 26) | def _now_iso() -> str:
function _validate_username (line 30) | def _validate_username(username: str) -> str:
function _validate_password (line 44) | def _validate_password(password: str) -> str:
function hash_password (line 53) | def hash_password(password: str) -> str:
function verify_password (line 60) | def verify_password(password: str, stored_hash: str) -> bool:
function _normalize_record (line 74) | def _normalize_record(username: str, raw: Any, *, default_role: str = "u...
function load_user_records (line 99) | def load_user_records() -> Dict[str, Dict[str, Any]]:
function save_user_records (line 127) | def save_user_records(records: Dict[str, Dict[str, Any]]) -> None:
function ensure_default_accounts (line 144) | def ensure_default_accounts() -> Dict[str, Dict[str, Any]]:
function authenticate_user (line 183) | def authenticate_user(username: str, password: str) -> Dict[str, Any] | ...
function public_user_record (line 194) | def public_user_record(record: Dict[str, Any]) -> Dict[str, Any]:
function list_users (line 204) | def list_users() -> List[Dict[str, Any]]:
function register_user (line 209) | def register_user(username: str, password: str, *, role: str = "user") -...
function update_user (line 229) | def update_user(username: str, *, password: str | None = None, role: str...
function delete_user (line 264) | def delete_user(username: str, *, actor_username: str | None = None) -> ...
FILE: web_ui/server/user_runtime.py
function sanitize_username (line 30) | def sanitize_username(username: str) -> str:
function get_web_user_home (line 36) | def get_web_user_home(username: str) -> Path:
function get_web_user_data_root (line 40) | def get_web_user_data_root(username: str) -> Path:
function get_web_user_config_dir (line 44) | def get_web_user_config_dir(username: str) -> Path:
function get_web_user_llm_config_path (line 48) | def get_web_user_llm_config_path(username: str) -> Path:
function get_web_user_app_config_path (line 52) | def get_web_user_app_config_path(username: str) -> Path:
function get_web_user_agent_library_root (line 56) | def get_web_user_agent_library_root(username: str) -> Path:
function get_web_user_tools_library_root (line 60) | def get_web_user_tools_library_root(username: str) -> Path:
function get_web_user_conversations_dir (line 64) | def get_web_user_conversations_dir(username: str) -> Path:
function get_web_user_logs_dir (line 68) | def get_web_user_logs_dir(username: str) -> Path:
function get_web_user_runtime_dir (line 72) | def get_web_user_runtime_dir(username: str) -> Path:
function get_web_user_skills_dir (line 76) | def get_web_user_skills_dir(username: str) -> Path:
function _blank_api_keys (line 80) | def _blank_api_keys(value: Any) -> Any:
function _seed_directory_children (line 94) | def _seed_directory_children(src_root: Path, dest_root: Path) -> None:
function ensure_web_user_runtime (line 107) | def ensure_web_user_runtime(username: str) -> Path:
FILE: web_ui/static/app.js
function replaceEmojiWithIcons (line 45) | function replaceEmojiWithIcons(text) {
function getAgentColor (line 73) | function getAgentColor(agentName) {
function checkAndStopOldTask (line 168) | async function checkAndStopOldTask() {
function checkAuth (line 194) | async function checkAuth() {
function logout (line 226) | async function logout() {
function setUsersStatus (line 243) | function setUsersStatus(text, isError = false) {
function openUsersModal (line 249) | function openUsersModal() {
function closeUsersModal (line 256) | function closeUsersModal() {
function resetUserEditor (line 261) | function resetUserEditor() {
function fillUserEditor (line 275) | function fillUserEditor(user) {
function renderUsersList (line 291) | function renderUsersList(users) {
function loadUsers (line 320) | async function loadUsers() {
function saveUserRecord (line 337) | async function saveUserRecord() {
function deleteSelectedUser (line 390) | async function deleteSelectedUser() {
function loadChatHistory (line 584) | async function loadChatHistory(taskId, shouldRemoveWelcome = false) {
function loadHistoryMessages (line 654) | function loadHistoryMessages(messages) {
function isThinkingPlaceholderMessage (line 679) | function isThinkingPlaceholderMessage(msg) {
function normalizeHistoryMessages (line 688) | function normalizeHistoryMessages(messages) {
function processSaveQueue (line 720) | async function processSaveQueue() {
function saveChatMessageDirect (line 736) | async function saveChatMessageDirect(agent, type, displayContent, isUser) {
function saveChatMessage (line 785) | function saveChatMessage(agent, type, displayContent, isUser) {
function confirmTask (line 797) | async function confirmTask() {
function loadTasks (line 904) | async function loadTasks() {
function updateTaskButtonsState (line 964) | function updateTaskButtonsState() {
function updateSendButtonState (line 999) | function updateSendButtonState() {
function clearTask (line 1015) | async function clearTask() {
function copyTask (line 1101) | async function copyTask() {
function createProgressModal (line 1206) | function createProgressModal() {
function updateProgressModal (line 1270) | function updateProgressModal(modal, progressData) {
function closeProgressModal (line 1282) | function closeProgressModal(modal) {
function downloadTask (line 1289) | async function downloadTask() {
function updateWorkspacePath (line 1327) | function updateWorkspacePath() {
function loadFiles (line 1336) | async function loadFiles(path = null) {
function isImageFile (line 1487) | function isImageFile(fileName) {
function openFile (line 1495) | async function openFile(filePath, fileName) {
function downloadFileFromList (line 1554) | async function downloadFileFromList(filePath, fileName) {
function handleDownloadFile (line 1601) | async function handleDownloadFile() {
function handleDeleteFile (line 1625) | async function handleDeleteFile() {
function handleFileUpload (line 1669) | async function handleFileUpload(event) {
function formatFileSize (line 1717) | function formatFileSize(bytes) {
function deleteFileOrDir (line 1724) | async function deleteFileOrDir(filePath, fileName) {
function escapeHtml (line 1755) | function escapeHtml(text) {
function updateAgentSelectButton (line 1762) | function updateAgentSelectButton() {
function initAgentSystemSelector (line 1769) | async function initAgentSystemSelector() {
function loadAgentsList (line 1811) | async function loadAgentsList() {
function renderAgentsList (line 1832) | function renderAgentsList(agents, searchTerm = '') {
function selectAgent (line 1898) | async function selectAgent(agentName) {
function loadAgentTreeForAgent (line 1920) | async function loadAgentTreeForAgent(agentName) {
function renderAgentTreeNodeForPanel (line 1952) | function renderAgentTreeNodeForPanel(node, depth = 0, isRoot = false) {
function openAgentSelectModal (line 2019) | async function openAgentSelectModal() {
function closeAgentSelectModal (line 2045) | function closeAgentSelectModal() {
function initAgentSelection (line 2055) | function initAgentSelection() {
function resumeTask (line 2090) | async function resumeTask() {
function sendMessage (line 2160) | async function sendMessage() {
function stopTask (line 2280) | async function stopTask() {
function startSSEConnection (line 2330) | function startSSEConnection(taskId, agentName, userInputText, agentSyste...
function handleSSEMessage (line 2443) | function handleSSEMessage(data) {
function createLiveMessage (line 2541) | function createLiveMessage(agent, type, title) {
function renderLiveText (line 2595) | function renderLiveText(textDiv, text) {
function scrollToBottom (line 2601) | function scrollToBottom() {
function startThinkingStream (line 2608) | function startThinkingStream(agent) {
function ensureReasoningStream (line 2615) | function ensureReasoningStream(agent) {
function hasMeaningfulText (line 2622) | function hasMeaningfulText(text) {
function pruneEmptyThinkingCards (line 2626) | function pruneEmptyThinkingCards() {
function streamAgentToken (line 2636) | function streamAgentToken(agent, text) {
function finalizeAgentStream (line 2647) | function finalizeAgentStream() {
function streamReasoningToken (line 2658) | function streamReasoningToken(agent, text) {
function finalizeReasoningStream (line 2668) | function finalizeReasoningStream() {
function streamThinkingToken (line 2681) | function streamThinkingToken(agent, text) {
function finalizeThinkingStream (line 2691) | function finalizeThinkingStream() {
function finalizeAllLiveStreams (line 2704) | function finalizeAllLiveStreams() {
function removeAllLoadingAnimations (line 2713) | function removeAllLoadingAnimations() {
function addMessage (line 2721) | function addMessage(agent, type, content, isUser = false, saveToHistory ...
function renderMessage (line 2870) | function renderMessage(agent, type, content, isUser, saveToHistory = fal...
function showMessage (line 2875) | function showMessage(agent, type, content) {
function startHILTaskChecking (line 2882) | function startHILTaskChecking() {
function stopHILTaskChecking (line 2892) | function stopHILTaskChecking() {
function checkHILTask (line 2900) | async function checkHILTask() {
function respondToHILTask (line 2962) | async function respondToHILTask(responseText) {
function respondToToolConfirmation (line 3013) | async function respondToToolConfirmation(approved) {
function clearHILState (line 3056) | function clearHILState() {
function clearToolConfirmationState (line 3071) | function clearToolConfirmationState() {
constant MODEL_EDITOR_SLOT_CONFIG_KEYS (line 3086) | const MODEL_EDITOR_SLOT_CONFIG_KEYS = {
constant MODEL_EDITOR_PROVIDER_OPTIONS (line 3095) | const MODEL_EDITOR_PROVIDER_OPTIONS = `
function getActiveConfigTabName (line 3107) | function getActiveConfigTabName() {
function readPositiveNumber (line 3111) | function readPositiveNumber(value, fallback) {
function readNonNegativeNumber (line 3116) | function readNonNegativeNumber(value, fallback) {
function createEmptyModelEditorState (line 3121) | function createEmptyModelEditorState() {
function nextModelEditorId (line 3132) | function nextModelEditorId() {
function inferModelProviderKind (line 3137) | function inferModelProviderKind(modelName, entryBaseUrl, globalBaseUrl, ...
function stripModelNameForProvider (line 3152) | function stripModelNameForProvider(providerKind, modelName, entryBaseUrl...
function normalizeModelNameForProvider (line 3169) | function normalizeModelNameForProvider(providerKind, modelName) {
function makeBlankModelEditorEntry (line 3186) | function makeBlankModelEditorEntry() {
function deserializeModelEditorEntry (line 3198) | function deserializeModelEditorEntry(rawEntry, globalBaseUrl) {
function serializeModelEditorComparable (line 3216) | function serializeModelEditorComparable(entry) {
function cloneModelEditorEntry (line 3227) | function cloneModelEditorEntry(entry) {
function computeSharedModelEntries (line 3239) | function computeSharedModelEntries(slotEntries) {
function createModelEntryPayload (line 3248) | function createModelEntryPayload(entry) {
function buildGuidedLlmConfig (line 3259) | function buildGuidedLlmConfig() {
function getModelEditorEntry (line 3281) | function getModelEditorEntry(slotKey, entryId) {
function renderModelEditorEntry (line 3285) | function renderModelEditorEntry(slotKey, entry) {
function renderModelEditorSlot (line 3336) | function renderModelEditorSlot(slotKey) {
function renderAllModelEditorSlots (line 3357) | function renderAllModelEditorSlots() {
function loadGuidedModelSettings (line 3361) | function loadGuidedModelSettings(config) {
function addModelEditorEntry (line 3383) | function addModelEditorEntry(slotKey) {
function bindModelEditorList (line 3389) | function bindModelEditorList(slotKey) {
function buildGuidedAppConfig (line 3428) | function buildGuidedAppConfig() {
function fillGuidedConfig (line 3458) | function fillGuidedConfig(llmConfig, appConfig) {
function loadGuidedConfig (line 3487) | async function loadGuidedConfig() {
function saveGuidedConfig (line 3511) | async function saveGuidedConfig() {
function openConfigModal (line 3564) | function openConfigModal() {
function closeConfigModal (line 3574) | function closeConfigModal() {
function loadConfigFileLists (line 3580) | async function loadConfigFileLists() {
function loadConfigFile (line 3681) | async function loadConfigFile(filename, type = 'run_env') {
function saveConfigFile (line 3726) | async function saveConfigFile() {
function switchConfigTab (line 3778) | function switchConfigTab(tabName) {
function loadAgentTree (line 3810) | async function loadAgentTree() {
function renderAgentTreeNode (line 3842) | function renderAgentTreeNode(node, depth = 0) {
function setToolsStatus (line 3910) | function setToolsStatus(message, isError = false) {
function loadToolsList (line 3919) | async function loadToolsList() {
function uploadToolFile (line 4000) | async function uploadToolFile(event) {
function reloadToolsRegistry (line 4023) | async function reloadToolsRegistry() {
function openToolsModal (line 4038) | function openToolsModal() {
function closeToolsModal (line 4044) | function closeToolsModal() {
function initToolsModal (line 4049) | function initToolsModal() {
function initUsersModal (line 4064) | function initUsersModal() {
function initConfigModal (line 4079) | function initConfigModal() {
Condensed preview — 449 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (6,777K chars).
[
{
"path": ".dockerignore",
"chars": 588,
"preview": ".git\n.gitignore\n.DS_Store\n.pytest_cache\n__pycache__\n*.pyc\n*.pyo\n*.pyd\n\n# Local build outputs\nbuild\ndist\n*.egg-info\ndeskt"
},
{
"path": ".gitignore",
"chars": 1022,
"preview": "# Python\n__pycache__/\n*.py[cod]\n*$py.class\n*.so\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\np"
},
{
"path": "Dockerfile",
"chars": 1641,
"preview": "FROM python:3.12-slim-bookworm\n\nARG HTTP_PROXY\nARG HTTPS_PROXY\nARG ALL_PROXY\nARG http_proxy\nARG https_proxy\nARG all_prox"
},
{
"path": "LICENSE",
"chars": 35149,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
},
{
"path": "MANIFEST.in",
"chars": 240,
"preview": "include README.md\ninclude LICENSE\ninclude requirements.txt\nrecursive-include config *.yaml\nrecursive-include skills *\nre"
},
{
"path": "README.md",
"chars": 37143,
"preview": "<div align=\"center\">\n <img src=\"assets/logo.png\" alt=\"infiAgent Logo\" width=\"200\">\n\n <h1>MLA V3 - Build Domain-Specifi"
},
{
"path": "README_CN.md",
"chars": 24212,
"preview": "\n\n<div align=\"center\">\n <img src=\"assets/logo.png\" alt=\"infiAgent Logo\" width=\"200\">\n\n <h1>MLA V3 - 打造专属领域的 SOTA 级智能体<"
},
{
"path": "apps/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "apps/cheapclaw/README.md",
"chars": 8809,
"preview": "# CheapClaw\n\nCheapClaw is a social-message orchestration app built on top of the `infiagent/mla` SDK.\n\nIt started from a"
},
{
"path": "apps/cheapclaw/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "apps/cheapclaw/assets/agent_library/CheapClawSupervisor/general_prompts.yaml",
"chars": 4798,
"preview": "system_prompt_xml: |\n <系统角色>\n 你是 CheapClawSupervisor 系统中的主调度智能体。你负责理解社交消息、维护会话状态、派发/续跑后台任务、安排计划任务、处理 watchdog 观测以及组织对用"
},
{
"path": "apps/cheapclaw/assets/agent_library/CheapClawSupervisor/level_0_tools.yaml",
"chars": 46441,
"preview": "tools:\n # ==================== 文件操作工具 ====================\n \n file_read:\n level: 0\n type: tool_call_agent\n n"
},
{
"path": "apps/cheapclaw/assets/agent_library/CheapClawSupervisor/level_3_agents.yaml",
"chars": 1945,
"preview": "tools:\n supervisor_agent:\n level: 3\n type: llm_call_agent\n available_tools:\n - cheapclaw_read_panel\n "
},
{
"path": "apps/cheapclaw/assets/agent_library/CheapClawWorkerGeneral/general_prompts.yaml",
"chars": 1045,
"preview": "system_prompt_xml: |\n <系统角色>\n 你是 CheapClawWorkerGeneral 系统中的后台 worker。你负责完成被分派给当前 task_id 的具体工作。\n </系统角色>\n\n <工作空间与路径"
},
{
"path": "apps/cheapclaw/assets/agent_library/CheapClawWorkerGeneral/level_0_tools.yaml",
"chars": 43915,
"preview": "tools:\n # ==================== 文件操作工具 ====================\n \n file_read:\n level: 0\n type: tool_call_agent\n n"
},
{
"path": "apps/cheapclaw/assets/agent_library/CheapClawWorkerGeneral/level_3_agents.yaml",
"chars": 1457,
"preview": "tools:\n worker_agent:\n level: 3\n type: llm_call_agent\n available_tools:\n - execute_command\n - grep\n "
},
{
"path": "apps/cheapclaw/assets/config/app_config.example.json",
"chars": 497,
"preview": "{\n \"runtime\": {\n \"action_window_steps\": 20,\n \"thinking_interval\": 20,\n \"fresh_enabled\": false,\n \"fresh_inte"
},
{
"path": "apps/cheapclaw/assets/config/channels.example.json",
"chars": 394,
"preview": "{\n \"telegram\": {\n \"enabled\": false,\n \"bot_token\": \"\",\n \"allowed_chats\": []\n },\n \"feishu\": {\n \"enabled\": f"
},
{
"path": "apps/cheapclaw/assets/config/llm_config_example.yaml",
"chars": 1507,
"preview": "# CheapClaw 默认 llm 配置样例。当前示例统一使用 Gemini 3 Flash。\ntemperature: 0\nmax_tokens: 0\nmax_context_window: 500000\nbase_url: https"
},
{
"path": "apps/cheapclaw/cheapclaw_hooks.py",
"chars": 1476,
"preview": "#!/usr/bin/env python3\n\"\"\"CheapClaw runtime hooks for background worker tool events.\"\"\"\n\nfrom __future__ import annotati"
},
{
"path": "apps/cheapclaw/cheapclaw_service.py",
"chars": 109221,
"preview": "#!/usr/bin/env python3\n\"\"\"Standalone CheapClaw application built on top of the public InfiAgent SDK.\"\"\"\n\nfrom __future__"
},
{
"path": "apps/cheapclaw/skills/cheapclaw-watchdog/SKILL.md",
"chars": 858,
"preview": "---\nname: cheapclaw-watchdog\ndescription: Read CheapClaw watchdog observations and decide whether to inspect logs, fresh"
},
{
"path": "apps/cheapclaw/skills/find-skills/SKILL.md",
"chars": 4626,
"preview": "---\nname: find-skills\ndescription: Helps users discover and install agent skills when they ask questions like \"how do I "
},
{
"path": "apps/cheapclaw/tool_runtime_helpers.py",
"chars": 29369,
"preview": "#!/usr/bin/env python3\nfrom __future__ import annotations\n\nimport json\nimport os\nimport shutil\nimport tempfile\nimport uu"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_add_task_message/cheapclaw_add_task_message.py",
"chars": 1994,
"preview": "#!/usr/bin/env python3\nfrom datetime import datetime\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).reso"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_cancel_plan/cheapclaw_cancel_plan.py",
"chars": 789,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_generate_task_id/cheapclaw_generate_task_id.py",
"chars": 947,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_get_task_status/cheapclaw_get_task_status.py",
"chars": 1550,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nfrom infiagent import infiagent\nfrom pathlib import Path\nimport sys\n\nAPP"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_list_agent_systems/cheapclaw_list_agent_systems.py",
"chars": 638,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nfrom infiagent import infiagent\nfrom tool_server_lite.tools.file_tools i"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_list_conversation_tasks/cheapclaw_list_conversation_tasks.py",
"chars": 3036,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_list_global_skills/cheapclaw_list_global_skills.py",
"chars": 549,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_read_panel/cheapclaw_read_panel.py",
"chars": 1593,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_read_social_history/cheapclaw_read_social_history.py",
"chars": 1458,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_reset_task/cheapclaw_reset_task.py",
"chars": 918,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nfrom infiagent import infiagent\nfrom tool_server_lite.tools.file_tools i"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_reveal_skills/cheapclaw_reveal_skills.py",
"chars": 2221,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nfrom infiagent import infiagent\nfrom pathlib import Path\nimport sys\n\nAPP"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_schedule_plan/cheapclaw_schedule_plan.py",
"chars": 1517,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_send_file/cheapclaw_send_file.py",
"chars": 2636,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_send_message/cheapclaw_send_message.py",
"chars": 2006,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_start_task/cheapclaw_start_task.py",
"chars": 10966,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/tools_library/cheapclaw_update_panel/cheapclaw_update_panel.py",
"chars": 3313,
"preview": "#!/usr/bin/env python3\nfrom pathlib import Path\nimport sys\n\nAPP_ROOT = Path(__file__).resolve().parents[2]\nif str(APP_RO"
},
{
"path": "apps/cheapclaw/web/dashboard.html",
"chars": 18211,
"preview": "<!doctype html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-widt"
},
{
"path": "backend_build/build_mac_universal.sh",
"chars": 14943,
"preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\nREPO_ROOT=\"$(cd \"${SCRIPT_DIR}/..\" &&"
},
{
"path": "backend_build/pyinstaller_backend.spec",
"chars": 4189,
"preview": "#!/usr/bin/env python3\n# PyInstaller spec for MLA V3 backend (desktop packaging)\n#\n# Output (onedir):\n# <distpath>/mla"
},
{
"path": "config/agent_library/OpenCowork/general_prompts.yaml",
"chars": 2558,
"preview": "# 通用系统提示词 - XML格式\n# 直接作为完整上下文的第一部分,包含所有固定内容\nsystem_prompt_xml: |\n <系统角色>\n 你是Open Cowork系统中的一员,是一个名为 \"{agent_name}\" 的AI"
},
{
"path": "config/agent_library/OpenCowork/level_-1_judge_agent.yaml",
"chars": 1647,
"preview": "tools:\n judge_agent:\n level: -1\n type: llm_call_agent\n available_tools:\n - dir_list\n - file_read\n "
},
{
"path": "config/agent_library/OpenCowork/level_0_tools.yaml",
"chars": 34353,
"preview": "tools:\n # ==================== 文件操作工具 ====================\n \n file_read:\n level: 0\n type: tool_call_agent\n n"
},
{
"path": "config/agent_library/OpenCowork/level_3_agents.yaml",
"chars": 2552,
"preview": "tools:\n alpha_agent:\n level: 3\n type: llm_call_agent\n available_tools:\n - execute_command\n - human_i"
},
{
"path": "config/agent_library/Researcher/general_prompts.yaml",
"chars": 2562,
"preview": "# 通用系统提示词 - XML格式\n# 直接作为完整上下文的第一部分,包含所有固定内容\nsystem_prompt_xml: |\n <系统角色>\n 你是一个名为 \"{agent_name}\" 的AI自动化工具,你高效,善于一步步思考并行"
},
{
"path": "config/agent_library/Researcher/level_-1_judge_agent.yaml",
"chars": 1677,
"preview": "tools:\n judge_agent:\n level: -1\n type: llm_call_agent\n available_tools:\n # - summary_from_papers\n - "
},
{
"path": "config/agent_library/Researcher/level_0_tools.yaml",
"chars": 34332,
"preview": "tools:\n # ==================== 文件操作工具 ====================\n file_read:\n level: 0\n type: tool_call_agent\n name"
},
{
"path": "config/agent_library/Researcher/level_1_agents.yaml",
"chars": 25518,
"preview": "tools:\n # browser_execute_agent:\n # NOTE: 桌面端默认不打包 Playwright/Chromium(体积大且需额外安装浏览器)。\n # 若需要浏览器自动化,请在源码环境手动安装并在 a"
},
{
"path": "config/agent_library/Researcher/level_2_agents.yaml",
"chars": 10833,
"preview": "tools:\n # browser_agent:\n # NOTE: 桌面端默认不启用 Playwright/Chromium 浏览器自动化(未随安装包打包)。\n # 若需要浏览器能力,请在源码环境安装 playwright 并"
},
{
"path": "config/agent_library/Researcher/level_3_agents.yaml",
"chars": 6092,
"preview": "tools:\n alpha_agent:\n level: 3\n type: llm_call_agent\n available_tools:\n - material_to_document_agent\n "
},
{
"path": "config/run_env_config/ali_qwen_llm_config.yaml",
"chars": 460,
"preview": "temperature: 0\nmax_tokens: 0\n#示意,大概基于官方减去 20k\nmax_context_window: 200000\nbase_url: https://dashscope.aliyuncs.com/compat"
},
{
"path": "config/run_env_config/document_convert_api.yaml",
"chars": 59,
"preview": "api_server: \"http://192.168.31.4:8000/\"\n#文档转换的 api 提供商,暂时弃用"
},
{
"path": "config/run_env_config/gemini_config_version.yaml",
"chars": 594,
"preview": "#样例文件,请替换到llm_config.yaml\ntemperature: 0\nmax_tokens: 0\nmax_context_window: 200000\n# Google 官方 API - litellm 会自动识别 gemini"
},
{
"path": "config/run_env_config/kimi_config_version copy.yaml",
"chars": 484,
"preview": "#样例文件,请替换到llm_config.yaml\ntemperature: 0\nmax_tokens: 0\nmax_context_window: 200000\nbase_url: https://api.moonshot.cn/v1\na"
},
{
"path": "config/run_env_config/llm_config.example.yaml",
"chars": 1600,
"preview": "\n\ntemperature: 0\nmax_tokens: 0\nmax_context_window: 500000\nbase_url: https://openrouter.ai/api/v1\napi_key: \ntimeout: 600 "
},
{
"path": "config/run_env_config/third_part_api.yaml",
"chars": 750,
"preview": "temperature: 0\nmax_tokens: 0\nmax_context_window: 200000\nbase_url: your provider'url for example: https://XXXX.top/v1 / 你"
},
{
"path": "core/__init__.py",
"chars": 15,
"preview": "# Core modules\n"
},
{
"path": "core/agent_event_emitter.py",
"chars": 1262,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\n统一事件发射器 (Event Emitter)\n负责将事件分发给所有已注册的事件处理器\n\"\"\"\n\nfrom typing import L"
},
{
"path": "core/agent_executor.py",
"chars": 61892,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\nAgent执行器 - 使用标准消息格式的核心执行逻辑\n历史动作通过 messages 数组传递(而非 system_prompt),支持多"
},
{
"path": "core/context_builder.py",
"chars": 31154,
"preview": "#!/usr/bin/env python3\nfrom utils.windows_compat import safe_print\n# -*- coding: utf-8 -*-\n\"\"\"\n上下文构造器 - 构建新的XML结构化上下文\n\"\""
},
{
"path": "core/event_handlers.py",
"chars": 8449,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\n实现具体的事件处理器 (Event Handlers) - v2 (事件分类规范化)\n\"\"\"\n\nfrom __future__ impor"
},
{
"path": "core/events.py",
"chars": 4552,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\n定义Agent执行过程中的所有事件契约 (Event Schema) - v2 (规范化)\n\"\"\"\n\nfrom dataclasses i"
},
{
"path": "core/hierarchy_manager.py",
"chars": 17242,
"preview": "#!/usr/bin/env python3\nfrom utils.windows_compat import safe_print\n# -*- coding: utf-8 -*-\n\"\"\"\n层级管理器 - 管理Agent调用层级和共享上下文"
},
{
"path": "core/runtime_exceptions.py",
"chars": 1619,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\n运行时异常定义。\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import "
},
{
"path": "core/state_cleaner.py",
"chars": 8692,
"preview": "#!/usr/bin/env python3\nfrom utils.windows_compat import safe_print\n# -*- coding: utf-8 -*-\n\"\"\"\n状态清理器 - 启动前清理栈和current状态\n"
},
{
"path": "core/tool_executor.py",
"chars": 13788,
"preview": "#!/usr/bin/env python3\nfrom utils.windows_compat import safe_print\n# -*- coding: utf-8 -*-\n\"\"\"\n工具执行器 - 统一使用进程内 direct-to"
},
{
"path": "desktop_app/package.json",
"chars": 2890,
"preview": "{\n \"name\": \"infiagent-desktop\",\n \"version\": \"1.0.0\",\n \"description\": \"infiAgent Desktop - AI Agent for long-running c"
},
{
"path": "desktop_app/src/index.html",
"chars": 21758,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, in"
},
{
"path": "desktop_app/src/main.js",
"chars": 43046,
"preview": "const { app, BrowserWindow, ipcMain, dialog, shell } = require('electron');\nconst path = require('path');\nconst fs = req"
},
{
"path": "desktop_app/src/preload.js",
"chars": 2331,
"preview": "const { contextBridge, ipcRenderer } = require('electron');\n\ncontextBridge.exposeInMainWorld('api', {\n // Workspace\n s"
},
{
"path": "desktop_app/src/renderer.js",
"chars": 65882,
"preview": "// ==================== DOM Elements ====================\nconst selectFolderBtn = document.getElementById('select-folder"
},
{
"path": "desktop_app/src/styles.css",
"chars": 26253,
"preview": "/* ==================== Warm Light Theme - Claude Desktop Style ==================== */\n\n* {\n margin: 0;\n padding: 0;\n"
},
{
"path": "desktop_app/src/test_e.js",
"chars": 305,
"preview": "const electron = require('electron');\nconsole.log('type:', typeof electron);\nconsole.log('app type:', typeof electron.ap"
},
{
"path": "docker/entrypoint.sh",
"chars": 1181,
"preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nAPP_ROOT=\"/app\"\nDEFAULT_WORKSPACE=\"/workspace\"\n\nmkdir -p /root/mla_v3\n\nif [[ -n \""
},
{
"path": "docs/CHEAPCLAW_GUIDE.md",
"chars": 6129,
"preview": "# CheapClaw Guide\n\n适用实现:\n- 服务入口:[apps/cheapclaw/cheapclaw_service.py](/Users/chenglin/Desktop/research/agent_framwork/vs"
},
{
"path": "docs/CHEAPCLAW_IMPLEMENTATION_PLAN.md",
"chars": 15328,
"preview": "# CheapClaw Implementation Plan\n\n本文件是 CheapClaw 的实现前设计文档。\n\n目标:\n- 基于当前 `infiagent` SDK 和 task runtime,构建一个独立的社交消息编排服务\n- 主"
},
{
"path": "docs/CLI_GUIDE.md",
"chars": 8741,
"preview": "# MLA CLI 完整使用指南 💻\n\n交互式命令行界面 (CLI) 完整教程。\n\n---\n\n## 📋 目录\n\n- [启动 CLI](#启动-cli)\n- [基础操作](#基础操作)\n- [智能体切换](#智能体切换)\n- [人机交互 HI"
},
{
"path": "docs/DOCKER_GUIDE.md",
"chars": 13323,
"preview": "# MLA Docker 完整使用指南 🐳\n\n**无需安装 Python,仅需 Docker!**\n\n---\n\n## 📋 目录\n\n- [简介](#简介)\n- [安装 Docker](#安装-docker)\n- [快速开始](#快速开始)\n-"
},
{
"path": "docs/EVENT_SCHEMA.md",
"chars": 5828,
"preview": "# Agent 事件系统 (Event System) - v2\n\n本文档旨在说明 `infiAgent` 项目中经过规范化重构后的事件驱动架构,为二次开发和系统集成提供指导。\n\n## 1. 设计哲学\n\n为了将核心的Agent业务逻辑与外部"
},
{
"path": "docs/SDK_GUIDE.md",
"chars": 27653,
"preview": "# InfiAgent SDK Guide\n\n适用版本:建议使用 `infiagent 3.2.1+`\n\n这份文档按当前代码实现编写,目标是让你在 `pip install infiagent` 之后,只靠这份文档就能理解:\n\n- `tas"
},
{
"path": "infiagent/__init__.py",
"chars": 301,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nfrom .sdk import InfiAgent, infiagent\nfrom core.runtime_exceptions impor"
},
{
"path": "infiagent/sdk.py",
"chars": 38184,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\nInfiAgent Python SDK。\n\n设计原则:\n- 实例化阶段只负责配置运行时环境\n- 具体任务在 run(..., task_"
},
{
"path": "marketplace_server/README.md",
"chars": 1455,
"preview": "# Marketplace Server (FastAPI)\n\n该服务提供一个非常轻量的 “Skills + Agent Systems 市场”:\n\n- Skills 来源:仓库根目录 `skills_libraru/`\n- Agent S"
},
{
"path": "marketplace_server/app.py",
"chars": 21496,
"preview": "import io\nimport json\nimport os\nimport time\nimport zipfile\nfrom pathlib import Path\nfrom typing import Any, Dict, List, "
},
{
"path": "marketplace_server/deploy_market.sh",
"chars": 2646,
"preview": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Deploy infiAgent Marketplace to a remote Linux server.\n#\n# Requirements:\n# - SS"
},
{
"path": "marketplace_server/infiagent-market.service",
"chars": 454,
"preview": "[Unit]\nDescription=infiAgent Marketplace\nAfter=network.target\n\n[Service]\nType=simple\nWorkingDirectory=/opt/infiagent-mar"
},
{
"path": "marketplace_server/nginx_infiagent_market.conf",
"chars": 356,
"preview": "server {\n listen 80;\n server_name _;\n\n # Proxy all marketplace traffic\n location / {\n proxy_pass http"
},
{
"path": "marketplace_server/requirements.txt",
"chars": 115,
"preview": "# 该市场服务端默认兼容 CentOS7 的 Python 3.6+,使用内置 WSGI server 运行(无第三方依赖)。\n#\n# 如需更高性能,可自行改用 gunicorn/waitress 等 WSGI server。\n\n"
},
{
"path": "pyproject.toml",
"chars": 98,
"preview": "[build-system]\nrequires = [\"setuptools>=69,<75\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n"
},
{
"path": "requirements.txt",
"chars": 1090,
"preview": "# MLA V3 依赖包\n\n# 核心依赖\nlitellm==1.82.6 # 统一的LLM接口(与桌面后端打包版本保持一致)\npyyaml>=6.0 # YAML配置文件解析\ntiktoken>=0.5"
},
{
"path": "services/__init__.py",
"chars": 19,
"preview": "# Services modules\n"
},
{
"path": "services/action_compressor.py",
"chars": 28417,
"preview": "#!/usr/bin/env python3\nfrom utils.windows_compat import safe_print\n# -*- coding: utf-8 -*-\n\"\"\"\n历史动作压缩服务\n策略:总结历史XML + 保留最"
},
{
"path": "services/context_compressor_backup.py",
"chars": 9900,
"preview": "#!/usr/bin/env python3\nfrom utils.windows_compat import safe_print\n# -*- coding: utf-8 -*-\n\"\"\"\n上下文压缩服务 - 智能压缩历史动作\n策略:总结历"
},
{
"path": "services/llm_client.py",
"chars": 64426,
"preview": "#!/usr/bin/env python3\nfrom utils.windows_compat import safe_print\n# -*- coding: utf-8 -*-\n\"\"\"\n简化的LLM客户端 - 使用LiteLLM统一接口"
},
{
"path": "services/thinking_agent.py",
"chars": 17120,
"preview": "#!/usr/bin/env python3\nfrom utils.windows_compat import safe_print\n# -*- coding: utf-8 -*-\n\"\"\"\nThinking Agent - 任务进展分析服务"
},
{
"path": "setup.py",
"chars": 3099,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\nMLA V3 - Multi-Level Agent System\n安装配置\n\"\"\"\n\nfrom setuptools import se"
},
{
"path": "skills/algorithmic-art/LICENSE.txt",
"chars": 11357,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "skills/algorithmic-art/SKILL.md",
"chars": 19735,
"preview": "---\nname: algorithmic-art\ndescription: Creating algorithmic art using p5.js with seeded randomness and interactive param"
},
{
"path": "skills/algorithmic-art/templates/generator_template.js",
"chars": 7376,
"preview": "/**\n * ═══════════════════════════════════════════════════════════════════════════\n * P5.JS GENERATIVE "
},
{
"path": "skills/algorithmic-art/templates/viewer.html",
"chars": 19402,
"preview": "<!DOCTYPE html>\n<!--\n THIS IS A TEMPLATE THAT SHOULD BE USED EVERY TIME AND MODIFIED.\n WHAT TO KEEP:\n ✓ Overall"
},
{
"path": "skills/brand-guidelines/LICENSE.txt",
"chars": 11357,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "skills/brand-guidelines/SKILL.md",
"chars": 2235,
"preview": "---\nname: brand-guidelines\ndescription: Applies Anthropic's official brand colors and typography to any sort of artifact"
},
{
"path": "skills/canvas-design/LICENSE.txt",
"chars": 11357,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "skills/canvas-design/SKILL.md",
"chars": 11937,
"preview": "---\nname: canvas-design\ndescription: Create beautiful visual art in .png and .pdf documents using design philosophy. You"
},
{
"path": "skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt",
"chars": 4373,
"preview": "Copyright 2012 The Arsenal Project Authors (andrij.design@gmail.com)\n\nThis Font Software is licensed under the SIL Open "
},
{
"path": "skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt",
"chars": 4397,
"preview": "Copyright 2019 The Big Shoulders Project Authors (https://github.com/xotypeco/big_shoulders)\n\nThis Font Software is lice"
},
{
"path": "skills/canvas-design/canvas-fonts/Boldonse-OFL.txt",
"chars": 4390,
"preview": "Copyright 2024 The Boldonse Project Authors (https://github.com/googlefonts/boldonse)\n\nThis Font Software is licensed un"
},
{
"path": "skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt",
"chars": 4403,
"preview": "Copyright 2022 The Bricolage Grotesque Project Authors (https://github.com/ateliertriay/bricolage)\n\nThis Font Software i"
},
{
"path": "skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt",
"chars": 4394,
"preview": "Copyright 2018 The Crimson Pro Project Authors (https://github.com/Fonthausen/CrimsonPro)\n\nThis Font Software is license"
},
{
"path": "skills/canvas-design/canvas-fonts/DMMono-OFL.txt",
"chars": 4392,
"preview": "Copyright 2020 The DM Mono Project Authors (https://www.github.com/googlefonts/dm-mono)\n\nThis Font Software is licensed "
},
{
"path": "skills/canvas-design/canvas-fonts/EricaOne-OFL.txt",
"chars": 4410,
"preview": "Copyright (c) 2011 by LatinoType Limitada (luciano@latinotype.com), \nwith Reserved Font Names \"Erica One\"\n\nThis Font Sof"
},
{
"path": "skills/canvas-design/canvas-fonts/GeistMono-OFL.txt",
"chars": 4388,
"preview": "Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font.git)\n\nThis Font Software is licensed unde"
},
{
"path": "skills/canvas-design/canvas-fonts/Gloock-OFL.txt",
"chars": 4381,
"preview": "Copyright 2022 The Gloock Project Authors (https://github.com/duartp/gloock)\n\nThis Font Software is licensed under the S"
},
{
"path": "skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt",
"chars": 4362,
"preview": "Copyright © 2017 IBM Corp. with Reserved Font Name \"Plex\"\n\nThis Font Software is licensed under the SIL Open Font Licens"
},
{
"path": "skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt",
"chars": 4403,
"preview": "Copyright 2022 The Instrument Sans Project Authors (https://github.com/Instrument/instrument-sans)\n\nThis Font Software i"
},
{
"path": "skills/canvas-design/canvas-fonts/Italiana-OFL.txt",
"chars": 4394,
"preview": "Copyright (c) 2011, Santiago Orozco (hi@typemade.mx), with Reserved Font Name \"Italiana\".\n\nThis Font Software is license"
},
{
"path": "skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt",
"chars": 4399,
"preview": "Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)\n\nThis Font Software is li"
},
{
"path": "skills/canvas-design/canvas-fonts/Jura-OFL.txt",
"chars": 4380,
"preview": "Copyright 2019 The Jura Project Authors (https://github.com/ossobuffo/jura)\n\nThis Font Software is licensed under the SI"
},
{
"path": "skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt",
"chars": 4449,
"preview": "Copyright 2012 The Libre Baskerville Project Authors (https://github.com/impallari/Libre-Baskerville) with Reserved Font"
},
{
"path": "skills/canvas-design/canvas-fonts/Lora-OFL.txt",
"chars": 4423,
"preview": "Copyright 2011 The Lora Project Authors (https://github.com/cyrealtype/Lora-Cyrillic), with Reserved Font Name \"Lora\".\n\n"
},
{
"path": "skills/canvas-design/canvas-fonts/NationalPark-OFL.txt",
"chars": 4399,
"preview": "Copyright 2025 The National Park Project Authors (https://github.com/benhoepner/National-Park)\n\nThis Font Software is li"
},
{
"path": "skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt",
"chars": 4363,
"preview": "Copyright (c) 2010, Kimberly Geswein (kimberlygeswein.com)\n\nThis Font Software is licensed under the SIL Open Font Licen"
},
{
"path": "skills/canvas-design/canvas-fonts/Outfit-OFL.txt",
"chars": 4389,
"preview": "Copyright 2021 The Outfit Project Authors (https://github.com/Outfitio/Outfit-Fonts)\n\nThis Font Software is licensed und"
},
{
"path": "skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt",
"chars": 4395,
"preview": "Copyright 2021 The Pixelify Sans Project Authors (https://github.com/eifetx/Pixelify-Sans)\n\nThis Font Software is licens"
},
{
"path": "skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt",
"chars": 4366,
"preview": "Copyright (c) 2011, Denis Masharov (denis.masharov@gmail.com)\n\nThis Font Software is licensed under the SIL Open Font Li"
},
{
"path": "skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt",
"chars": 4394,
"preview": "Copyright 2024 The Red Hat Project Authors (https://github.com/RedHatOfficial/RedHatFont)\n\nThis Font Software is license"
},
{
"path": "skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt",
"chars": 4394,
"preview": "Copyright 2001 The Silkscreen Project Authors (https://github.com/googlefonts/silkscreen)\n\nThis Font Software is license"
},
{
"path": "skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt",
"chars": 4396,
"preview": "Copyright 2016 The Smooch Sans Project Authors (https://github.com/googlefonts/smooch-sans)\n\nThis Font Software is licen"
},
{
"path": "skills/canvas-design/canvas-fonts/Tektur-OFL.txt",
"chars": 4385,
"preview": "Copyright 2023 The Tektur Project Authors (https://www.github.com/hyvyys/Tektur)\n\nThis Font Software is licensed under t"
},
{
"path": "skills/canvas-design/canvas-fonts/WorkSans-OFL.txt",
"chars": 4397,
"preview": "Copyright 2019 The Work Sans Project Authors (https://github.com/weiweihuanghuang/Work-Sans)\n\nThis Font Software is lice"
},
{
"path": "skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt",
"chars": 4398,
"preview": "Copyright 2023 The Young Serif Project Authors (https://github.com/noirblancrouge/YoungSerif)\n\nThis Font Software is lic"
},
{
"path": "skills/doc-coauthoring/SKILL.md",
"chars": 15815,
"preview": "---\nname: doc-coauthoring\ndescription: Guide users through a structured workflow for co-authoring documentation. Use whe"
},
{
"path": "skills/docx/LICENSE.txt",
"chars": 1466,
"preview": "© 2025 Anthropic, PBC. All rights reserved.\n\nLICENSE: Use of these materials (including all code, prompts, assets, files"
},
{
"path": "skills/docx/SKILL.md",
"chars": 17113,
"preview": "---\nname: docx\ndescription: \"Use this skill whenever the user wants to create, read, edit, or manipulate Word documents "
},
{
"path": "skills/docx/scripts/__init__.py",
"chars": 1,
"preview": "\n"
},
{
"path": "skills/docx/scripts/accept_changes.py",
"chars": 4051,
"preview": "\"\"\"Accept all tracked changes in a DOCX file using LibreOffice.\n\nRequires LibreOffice (soffice) to be installed.\n\"\"\"\n\nim"
},
{
"path": "skills/docx/scripts/comment.py",
"chars": 10694,
"preview": "\"\"\"Add comments to DOCX documents.\n\nUsage:\n python comment.py unpacked/ 0 \"Comment text\"\n python comment.py unpack"
},
{
"path": "skills/docx/scripts/office/helpers/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "skills/docx/scripts/office/helpers/merge_runs.py",
"chars": 5567,
"preview": "\"\"\"Merge adjacent runs with identical formatting in DOCX.\n\nMerges adjacent <w:r> elements that have identical <w:rPr> pr"
},
{
"path": "skills/docx/scripts/office/helpers/simplify_redlines.py",
"chars": 5754,
"preview": "\"\"\"Simplify tracked changes by merging adjacent w:ins or w:del elements.\n\nMerges adjacent <w:ins> elements from the same"
},
{
"path": "skills/docx/scripts/office/pack.py",
"chars": 4991,
"preview": "\"\"\"Pack a directory into a DOCX, PPTX, or XLSX file.\n\nValidates with auto-repair, condenses XML formatting, and creates "
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd",
"chars": 74984,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:a=\"http://schema"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd",
"chars": 6956,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:a=\"http://schema"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd",
"chars": 51302,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd",
"chars": 624,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd",
"chars": 152039,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:r=\"http://schema"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd",
"chars": 1231,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd",
"chars": 8862,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:a=\"http://schema"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd",
"chars": 14795,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:a=\"http://schema"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd",
"chars": 83612,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd",
"chars": 1269,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd",
"chars": 7328,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd",
"chars": 6382,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd",
"chars": 1248,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd",
"chars": 880,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd",
"chars": 2608,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd",
"chars": 3507,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd",
"chars": 7507,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd",
"chars": 23313,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd",
"chars": 1367,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd",
"chars": 242277,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"http://schemas."
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd",
"chars": 26148,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"urn:schemas-micro"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd",
"chars": 25279,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"urn:schemas-mic"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd",
"chars": 535,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"urn:schemas-mic"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd",
"chars": 5712,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"urn:schemas-mic"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd",
"chars": 4010,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns=\"urn:schemas-mic"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd",
"chars": 171367,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n xmlns:m=\"http://schema"
},
{
"path": "skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd",
"chars": 4646,
"preview": "<?xml version='1.0'?>\n<xs:schema targetNamespace=\"http://www.w3.org/XML/1998/namespace\" xmlns:xs=\"http://www.w3.org/2001"
},
{
"path": "skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd",
"chars": 1961,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<xs:schema xmlns=\"http://schemas.openxmlformats.org/package/2006"
},
{
"path": "skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd",
"chars": 2513,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xs:schema targetNamespace=\"http://schemas.openxmlformats.org/package/2006/metad"
},
{
"path": "skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd",
"chars": 2856,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xsd:schema xmlns=\"http://schemas.openxmlformats.org/package/2006/digital-signatu"
},
{
"path": "skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd",
"chars": 1342,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<xsd:schema xmlns=\"http://schemas.openxmlformats.org/package/200"
},
{
"path": "skills/docx/scripts/office/schemas/mce/mc.xsd",
"chars": 3125,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsd:schema xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006"
},
{
"path": "skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd",
"chars": 26549,
"preview": " <xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:w12=\"http://schemas.openxmlformats.org/wordprocessingml/"
},
{
"path": "skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd",
"chars": 3745,
"preview": " <xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:w12=\"http://schemas.openxmlformats.org/wordprocessingml/"
},
{
"path": "skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd",
"chars": 901,
"preview": " <xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:w12=\"http://schemas.openxmlformats.org/wordprocessingml/"
},
{
"path": "skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd",
"chars": 1778,
"preview": " <xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/20"
},
{
"path": "skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd",
"chars": 1002,
"preview": " <xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:w12=\"http://schemas.openxmlformats.org/wordprocessingml/"
},
{
"path": "skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd",
"chars": 600,
"preview": " <xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:w12=\"http://schemas.openxmlformats.org/wordprocessingml/"
},
{
"path": "skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd",
"chars": 745,
"preview": " <xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:w12=\"http://schemas.openxmlformats.org/wordprocessingml/"
},
{
"path": "skills/docx/scripts/office/soffice.py",
"chars": 5293,
"preview": "\"\"\"\nHelper for running LibreOffice (soffice) in environments where AF_UNIX\nsockets may be blocked (e.g., sandboxed VMs)."
},
{
"path": "skills/docx/scripts/office/unpack.py",
"chars": 4052,
"preview": "\"\"\"Unpack Office files (DOCX, PPTX, XLSX) for editing.\n\nExtracts the ZIP archive, pretty-prints XML files, and optionall"
},
{
"path": "skills/docx/scripts/office/validate.py",
"chars": 3668,
"preview": "\"\"\"\nCommand line tool to validate Office document XML files against XSD schemas and tracked changes.\n\nUsage:\n python "
},
{
"path": "skills/docx/scripts/office/validators/__init__.py",
"chars": 336,
"preview": "\"\"\"\nValidation modules for Word document processing.\n\"\"\"\n\nfrom .base import BaseSchemaValidator\nfrom .docx import DOCXSc"
},
{
"path": "skills/docx/scripts/office/validators/base.py",
"chars": 32651,
"preview": "\"\"\"\nBase validator with common validation logic for document files.\n\"\"\"\n\nimport re\nfrom pathlib import Path\n\nimport defu"
},
{
"path": "skills/docx/scripts/office/validators/docx.py",
"chars": 16372,
"preview": "\"\"\"\nValidator for Word document XML files against XSD schemas.\n\"\"\"\n\nimport random\nimport re\nimport tempfile\nimport zipfi"
},
{
"path": "skills/docx/scripts/office/validators/pptx.py",
"chars": 9824,
"preview": "\"\"\"\nValidator for PowerPoint presentation XML files against XSD schemas.\n\"\"\"\n\nimport re\n\nfrom .base import BaseSchemaVal"
},
{
"path": "skills/docx/scripts/office/validators/redlining.py",
"chars": 8918,
"preview": "\"\"\"\nValidator for tracked changes in Word documents.\n\"\"\"\n\nimport subprocess\nimport tempfile\nimport zipfile\nfrom pathlib "
},
{
"path": "skills/docx/scripts/templates/comments.xml",
"chars": 2603,
"preview": "<?xml version=\"1.0\" ?>\n<w:comments xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:"
},
{
"path": "skills/docx/scripts/templates/commentsExtended.xml",
"chars": 2611,
"preview": "<?xml version=\"1.0\" ?>\n<w15:commentsEx xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xm"
},
{
"path": "skills/docx/scripts/templates/commentsExtensible.xml",
"chars": 2707,
"preview": "<?xml version=\"1.0\" ?>\n<w16cex:commentsExtensible xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessin"
},
{
"path": "skills/docx/scripts/templates/commentsIds.xml",
"chars": 2619,
"preview": "<?xml version=\"1.0\" ?>\n<w16cid:commentsIds xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
},
{
"path": "skills/docx/scripts/templates/people.xml",
"chars": 115,
"preview": "<?xml version=\"1.0\" ?>\n<w15:people xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\">\n</w15:people>\n"
},
{
"path": "skills/frontend-design/LICENSE.txt",
"chars": 10174,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "skills/frontend-design/SKILL.md",
"chars": 4440,
"preview": "---\nname: frontend-design\ndescription: Create distinctive, production-grade frontend interfaces with high design quality"
},
{
"path": "skills/internal-comms/LICENSE.txt",
"chars": 11357,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "skills/internal-comms/SKILL.md",
"chars": 1511,
"preview": "---\nname: internal-comms\ndescription: A set of resources to help me write all kinds of internal communications, using th"
}
]
// ... and 249 more files (download for full content)
About this extraction
This page contains the full source code of the ChenglinPoly/infiAgent GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 449 files (5.8 MB), approximately 1.6M tokens, and a symbol index with 1779 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.