Full Code of MiroMindAI/MiroFlow for AI

miroflow-1.7 9d180f1eeb5e cached
296 files
1.5 MB
365.9k tokens
822 symbols
3 requests
Download .txt
Showing preview only (1,627K chars total). Download the full file or copy to clipboard to get everything.
Repository: MiroMindAI/MiroFlow
Branch: miroflow-1.7
Commit: 9d180f1eeb5e
Files: 296
Total size: 1.5 MB

Directory structure:
gitextract_m3xbil2z/

├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── pull_request_template.md
│   ├── scripts/
│   │   └── check_pr_title.py
│   └── workflows/
│       ├── check-pr-title.yml
│       └── run-ruff.yml
├── .gitignore
├── LICENSE
├── README.md
├── REUSE.toml
├── config/
│   ├── __init__.py
│   ├── agent_quickstart.yaml
│   ├── agent_quickstart_graph.yaml
│   ├── agent_quickstart_skill.yaml
│   ├── agent_single-test.yaml
│   ├── agent_web_demo.yaml
│   ├── benchmark/
│   │   ├── browsecomp-en-200.yaml
│   │   ├── browsecomp-en.yaml
│   │   ├── browsecomp-zh.yaml
│   │   ├── default.yaml
│   │   ├── example_dataset.yaml
│   │   ├── finsearchcomp.yaml
│   │   ├── frames-test.yaml
│   │   ├── futurex.yaml
│   │   ├── gaia-test.yaml
│   │   ├── gaia-validation-165.yaml
│   │   ├── gaia-validation-text-only.yaml
│   │   ├── gaia-validation.yaml
│   │   ├── hle-text-only.yaml
│   │   ├── hle.yaml
│   │   ├── webwalkerqa.yaml
│   │   └── xbench-ds.yaml
│   ├── benchmark_browsecomp-en-200_mirothinker_v1.yaml
│   ├── benchmark_browsecomp-en_mirothinker.yaml
│   ├── benchmark_browsecomp-zh_mirothinker_v1.yaml
│   ├── benchmark_browsecomp-zh_mirothinker_v2.yaml
│   ├── benchmark_browsecomp-zh_mirothinker_v3.yaml
│   ├── benchmark_frames-test_mirothinker.yaml
│   ├── benchmark_gaia-validation-165_mirothinker_tool.yaml
│   ├── benchmark_gaia-validation-165_mirothinker_v1.yaml
│   ├── benchmark_gaia-validation-text-103_kimi_k25.yaml
│   ├── benchmark_gaia-validation-text-103_mirothinker_multi-agent.yaml
│   ├── benchmark_gaia-validation-text-103_mirothinker_v1.yaml
│   ├── benchmark_gaia-validation-text-103_mirothinker_v2.yaml
│   ├── benchmark_hle-text-only_mirothinker.yaml
│   ├── benchmark_hle_mirothinker_v1.yaml
│   ├── benchmark_webwalkerqa_mirothinker.yaml
│   ├── benchmark_xbench-ds_mirothinker.yaml
│   ├── llm/
│   │   ├── base_kimi_k25.yaml
│   │   ├── base_mirothinker.yaml
│   │   └── base_openai.yaml
│   ├── prompts/
│   │   ├── __init__.py
│   │   ├── base_agent_prompt.py
│   │   ├── main_agent_prompt_deepseek.py
│   │   ├── main_agent_prompt_gaia.py
│   │   ├── main_boxed_answer.py
│   │   ├── prompt_final_answer_extraction.yaml
│   │   ├── prompt_main_agent.yaml
│   │   ├── prompt_main_agent_benchmark.yaml
│   │   ├── prompt_main_agent_gaia.yaml
│   │   ├── prompt_sub_agent.yaml
│   │   ├── prompt_subtask.yaml
│   │   └── sub_worker.py
│   └── tool/
│       ├── tool-audio-os.yaml
│       ├── tool-audio.yaml
│       ├── tool-browsing.yaml
│       ├── tool-code-sandbox.yaml
│       ├── tool-image-video-os.yaml
│       ├── tool-image-video.yaml
│       ├── tool-jina-scrape.yaml
│       ├── tool-markitdown.yaml
│       ├── tool-reading.yaml
│       ├── tool-reasoning-os.yaml
│       ├── tool-reasoning.yaml
│       ├── tool-scrape-website-v1.yaml
│       ├── tool-searching-serper.yaml
│       ├── tool-searching.yaml
│       ├── tool-serper-search.yaml
│       └── tool-serper-sogou-search.yaml
├── data/
│   ├── FSI-2023-DOWNLOAD.xlsx
│   └── README.md
├── docs/
│   └── mkdocs/
│       ├── README.md
│       ├── docs/
│       │   ├── all_about_agents.md
│       │   ├── browsecomp_en.md
│       │   ├── browsecomp_zh.md
│       │   ├── claude-3.7-sonnet.md
│       │   ├── contribute_benchmarks.md
│       │   ├── contribute_llm_clients.md
│       │   ├── contribute_tools.md
│       │   ├── contributors.md
│       │   ├── core_concepts.md
│       │   ├── data.md
│       │   ├── deepseek.md
│       │   ├── download_datasets.md
│       │   ├── e2b_advanced_features.md
│       │   ├── evaluation_overview.md
│       │   ├── faqs.md
│       │   ├── finsearchcomp.md
│       │   ├── futurex.md
│       │   ├── gaia_test.md
│       │   ├── gaia_validation_claude37sonnet.md
│       │   ├── gaia_validation_gpt5.md
│       │   ├── gaia_validation_mirothinker.md
│       │   ├── gaia_validation_prerequisites.md
│       │   ├── gaia_validation_text_only.md
│       │   ├── hle.md
│       │   ├── hle_text_only.md
│       │   ├── index.md
│       │   ├── license.md
│       │   ├── llm_clients_overview.md
│       │   ├── mirothinker.md
│       │   ├── model_comparison.md
│       │   ├── openai-gpt4o.md
│       │   ├── openai-gpt5.md
│       │   ├── openrouter-claude-3.7-sonnet.md
│       │   ├── quickstart.md
│       │   ├── tool_audio.md
│       │   ├── tool_audio_os.md
│       │   ├── tool_overview.md
│       │   ├── tool_python.md
│       │   ├── tool_reading.md
│       │   ├── tool_reasoning.md
│       │   ├── tool_reasoning_os.md
│       │   ├── tool_searching.md
│       │   ├── tool_searching_serper.md
│       │   ├── tool_vqa.md
│       │   ├── tool_vqa_os.md
│       │   ├── webwalkerqa.md
│       │   ├── whats_new.md
│       │   ├── why_miroflow.md
│       │   ├── xbench_ds.md
│       │   └── yaml_config.md
│       └── mkdocs.yml
├── miroflow/
│   ├── __init__.py
│   ├── agents/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── context.py
│   │   ├── factory.py
│   │   ├── iterative_agent_with_rollback.py
│   │   └── sequential_agent.py
│   ├── benchmark/
│   │   ├── __init__.py
│   │   ├── calculate_average_score.py
│   │   ├── eval_utils.py
│   │   ├── run_benchmark.py
│   │   ├── task_runner.py
│   │   └── verifiers/
│   │       ├── __init__.py
│   │       ├── base_verifier.py
│   │       ├── browsecomp_en_verifier.py
│   │       ├── browsecomp_zh_verifier.py
│   │       ├── finsearchcomp_verifier.py
│   │       ├── gaia_common_verifier.py
│   │       ├── gaia_verifier.py
│   │       ├── hle_verifier.py
│   │       ├── simpleqa_verifier.py
│   │       └── xbench_verifier.py
│   ├── io_processor/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── exceed_max_turn_summary_generator.py
│   │   ├── file_content_preprocessor.py
│   │   ├── final_answer_extractor.py
│   │   ├── input_hint_generator.py
│   │   ├── input_message_generator.py
│   │   ├── regex_boxed_extractor.py
│   │   └── summary_generator.py
│   ├── llm/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── claude_anthropic.py
│   │   ├── claude_openrouter.py
│   │   ├── factory.py
│   │   ├── gpt5_openai.py
│   │   ├── gpt_openai.py
│   │   ├── mirothinker_sglang.py
│   │   ├── openai_client.py
│   │   ├── openrouter.py
│   │   └── util.py
│   ├── logging/
│   │   ├── __init__.py
│   │   ├── decorators.py
│   │   ├── span.py
│   │   ├── task_tracer.py
│   │   └── tool_logging.py
│   ├── py.typed
│   ├── registry.py
│   ├── skill/
│   │   ├── __init__.py
│   │   ├── manager.py
│   │   └── skills/
│   │       ├── Afternoon_feeling/
│   │       │   └── SKILL.md
│   │       ├── Today_feeling/
│   │       │   └── SKILL.md
│   │       └── simple_file_understanding/
│   │           └── SKILL.md
│   ├── tool/
│   │   ├── __init__.py
│   │   ├── factory.py
│   │   ├── manager.py
│   │   └── mcp_servers/
│   │       ├── __init__.py
│   │       ├── audio_mcp_server.py
│   │       ├── audio_mcp_server_os.py
│   │       ├── browser_session.py
│   │       ├── code_sandbox.py
│   │       ├── jina_scrape.py
│   │       ├── miroapi_serper_mcp_server.py
│   │       ├── reading_mcp_server.py
│   │       ├── reasoning_mcp_server.py
│   │       ├── reasoning_mcp_server_os.py
│   │       ├── scrape_website_v1.py
│   │       ├── searching_mcp_server.py
│   │       ├── serper_search.py
│   │       ├── serper_sogou_search.py
│   │       ├── skill_mcp_server.py
│   │       ├── utils/
│   │       │   ├── smart_request.py
│   │       │   └── url_unquote.py
│   │       ├── vision_mcp_server.py
│   │       └── vision_mcp_server_os.py
│   └── utils/
│       ├── __init__.py
│       ├── file_content_utils.py
│       ├── io_utils.py
│       ├── parsing_utils.py
│       ├── prepare_benchmark/
│       │   ├── README.md
│       │   ├── __init__.py
│       │   ├── common.py
│       │   ├── gen_browsecomp.py
│       │   ├── gen_finsearchcomp.py
│       │   ├── gen_frames.py
│       │   ├── gen_futurex.py
│       │   ├── gen_gaia.py
│       │   ├── gen_gaia_text_only.py
│       │   ├── gen_hle.py
│       │   ├── gen_hle_text_only.py
│       │   ├── gen_webwalkerqa.py
│       │   ├── gen_xbench_ds.py
│       │   └── main.py
│       ├── prompt_utils.py
│       ├── summary_utils.py
│       └── tool_utils.py
├── pyproject.toml
├── scripts/
│   ├── benchmark/
│   │   ├── check_progress/
│   │   │   ├── check_progress_browsecomp-en-200.py
│   │   │   ├── check_progress_browsecomp-en.py
│   │   │   ├── check_progress_browsecomp-zh.py
│   │   │   ├── check_progress_frames-test.py
│   │   │   ├── check_progress_gaia-validation-165.py
│   │   │   ├── check_progress_gaia-validation-text-103.py
│   │   │   ├── check_progress_hle-text-only.py
│   │   │   ├── check_progress_hle.py
│   │   │   ├── check_progress_webwalkerqa.py
│   │   │   └── check_progress_xbench-ds.py
│   │   ├── kimi_k25/
│   │   │   └── gaia-validation-text-103_kimi_k25_8runs.sh
│   │   └── mirothinker/
│   │       ├── browsecomp-en-200_mirothinker_v1.sh
│   │       ├── browsecomp-en_mirothinker_3runs.sh
│   │       ├── browsecomp-zh_mirothinker_v1.sh
│   │       ├── browsecomp-zh_mirothinker_v2.sh
│   │       ├── browsecomp-zh_mirothinker_v3.sh
│   │       ├── frames-test_mirothinker_3runs.sh
│   │       ├── gaia-validation-165_mirothinker_v1.sh
│   │       ├── gaia-validation-text-103_mirothinker_v1.sh
│   │       ├── gaia-validation-text-103_mirothinker_v2.sh
│   │       ├── hle-text-only_mirothinker_3runs.sh
│   │       ├── hle_mirothinker_v1.sh
│   │       ├── webwalkerqa_mirothinker_3runs.sh
│   │       └── xbench-ds_mirothinker_8runs.sh
│   ├── run_prepare_benchmark.sh
│   ├── run_single_task.py
│   ├── start_web.sh
│   └── test_single_task.sh
└── web_app/
    ├── __init__.py
    ├── api/
    │   ├── __init__.py
    │   ├── dependencies.py
    │   └── routes/
    │       ├── __init__.py
    │       ├── configs.py
    │       ├── health.py
    │       ├── tasks.py
    │       └── uploads.py
    ├── core/
    │   ├── __init__.py
    │   ├── config.py
    │   ├── session_manager.py
    │   └── task_executor.py
    ├── frontend/
    │   ├── index.html
    │   ├── package.json
    │   ├── postcss.config.js
    │   ├── src/
    │   │   ├── App.tsx
    │   │   ├── api/
    │   │   │   ├── client.ts
    │   │   │   └── tasks.ts
    │   │   ├── components/
    │   │   │   ├── common/
    │   │   │   │   ├── FileUpload.tsx
    │   │   │   │   ├── LoadingSpinner.tsx
    │   │   │   │   └── MarkdownRenderer.tsx
    │   │   │   └── task/
    │   │   │       ├── TaskForm.tsx
    │   │   │       ├── TaskHistory.tsx
    │   │   │       └── TaskStatus.tsx
    │   │   ├── hooks/
    │   │   │   └── usePolling.ts
    │   │   ├── index.css
    │   │   ├── main.tsx
    │   │   ├── types/
    │   │   │   └── task.ts
    │   │   └── vite-env.d.ts
    │   ├── tailwind.config.js
    │   ├── tsconfig.json
    │   ├── tsconfig.node.json
    │   └── vite.config.ts
    ├── main.py
    └── models/
        ├── __init__.py
        └── task.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
*.pdf filter=lfs diff=lfs merge=lfs -text
*.pptx filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.docs filter=lfs diff=lfs merge=lfs -text
*.docx filter=lfs diff=lfs merge=lfs -text


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
 - OS: [e.g. iOS]
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]

**Smartphone (please complete the following information):**
 - Device: [e.g. iPhone6]
 - OS: [e.g. iOS8.1]
 - Browser [e.g. stock browser, safari]
 - Version [e.g. 22]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/pull_request_template.md
================================================
# Describe this PR

<!-- Please provide a clear and concise description of what this PR does -->

## What changed?
<!-- Describe the changes made in this PR -->

## Why?
<!-- Explain the motivation behind these changes -->

## Related issues
<!-- Link any related issues using #issue_number -->


# Checklist for PR

- [ ] Write a descriptive PR title following the [Angular commit message format](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#commit-message-format): `<type>(<scope>): <subject>`
  - **Examples:** `feat(agent): add pdf tool via mcp`, `perf: make llm client async`, `fix(utils): load custom config via importlib`
  - **Valid types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `revert`
  - The `check-pr-title` CI job will validate your title format
  - **Bad title examples and why they fail:**
    - `Update README` ❌ Missing type and colon
    - `feat add new feature` ❌ Missing colon after type
    - `Feature: add new tool` ❌ Invalid type (should be `feat`)
    - `feat(Agent): add tool` ❌ Scope should be lowercase
    - `feat(): add tool` ❌ Empty scope not allowed
    - `feat(my_scope): add tool` ❌ Underscores not allowed in scope
    - `feat(my space): add tool` ❌ Space not allowed in scope
    - `feat(scope):add tool` ❌ Missing space after colon
    - `feat(scope): ` ❌ Empty subject

- [ ] Run lint and format locally:
  - `uv tool run ruff@0.8.0 check --fix .`
  - `uv tool run ruff@0.8.0 format .`
  - CI job `lint` enforces ruff default format/lint rules on all new codes.

================================================
FILE: .github/scripts/check_pr_title.py
================================================
# /// script
# requires-python = ">=3.10"
# dependencies = []
# ///
import argparse
import dataclasses
import os
import re
import string
import sys

VALID_TYPES = {
    "revert",
    "build",
    "ci",
    "docs",
    "feat",
    "fix",
    "perf",
    "refactor",
    "style",
    "test",
}

MARKDOWN_TEMPLATE = string.Template(
    """### Result

| PR title | expected format | status | message |
|---|---|---|---|
| `${title}` | `<type>(<scope>): <subject>` | `${status}` | `${message}` |
"""
)


@dataclasses.dataclass
class CheckResult:
    title: str
    status: bool
    message: str

    def to_markdown(self) -> str:
        emoji = "PASSED ✅" if self.status else "FAILED ❌"
        return MARKDOWN_TEMPLATE.substitute(
            title=self.title, status=emoji, message=self.message
        ).strip()


def check_pr_title(title: str) -> CheckResult:
    """Validate PR title follows format: <type>(<scope>): <subject>"""
    type_pattern = rf"^({'|'.join(sorted(VALID_TYPES))})"
    scope_pattern = r"\([a-z0-9-]+\)"
    subject_pattern = r": .+"

    # Check type
    type_match = re.match(type_pattern, title)
    if not type_match:
        return CheckResult(
            title=title,
            status=False,
            message=f"<type> must be one of: {', '.join(sorted(VALID_TYPES))}",
        )

    remaining = title[type_match.end() :]

    # Check scope (optional)
    if remaining.startswith("("):
        scope_match = re.match(scope_pattern, remaining)
        if not scope_match:
            return CheckResult(
                title=title,
                status=False,
                message="<scope> must contain only lowercase letters, numbers, or hyphens",
            )
        remaining = remaining[scope_match.end() :]

    # Check subject
    if not re.match(subject_pattern, remaining):
        return CheckResult(
            title=title,
            status=False,
            message="<subject> must start with ': ' and contain a description",
        )

    return CheckResult(title=title, status=True, message="Valid PR title format")


def main() -> None:
    parser = argparse.ArgumentParser(
        description="Validate PR title following Angular commit convention"
    )
    parser.add_argument(
        "title", help="PR title to validate (format: <type>(<scope>): <subject>)"
    )

    args = parser.parse_args()
    result = check_pr_title(args.title)

    print(result)

    # Write to GitHub step summary if available
    if step_summary := os.environ.get("GITHUB_STEP_SUMMARY"):
        with open(step_summary, "a") as f:
            f.write(result.to_markdown())

    sys.exit(0 if result.status else 1)


if __name__ == "__main__":
    main()


================================================
FILE: .github/workflows/check-pr-title.yml
================================================
name: check-pr-title

on:
  pull_request:
   types: [opened, synchronize, edited]

jobs:
  check-pr-title:
    name: Check PR Title
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Install uv
      uses: astral-sh/setup-uv@v5

    - name: check PR with regex
      run: uv run .github/scripts/check_pr_title.py "${TITLE}"
      env:
        TITLE: ${{ github.event.pull_request.title }}

================================================
FILE: .github/workflows/run-ruff.yml
================================================
name: lint

on:
  pull_request:
    types: [opened, synchronize, edited]
  push:
    branches: [ "main" ]

jobs:
  lint:
    name: lint pull request
    runs-on: ubuntu-latest
    steps:
    - name: Debug workflow trigger
      run: |
        echo "Workflow triggered by: ${{ github.event_name }}"
        echo "PR number: ${{ github.event.pull_request.number }}"
        echo "PR title: ${{ github.event.pull_request.title }}"
        echo "Repository: ${{ github.repository }}"
        echo "Branch: ${{ github.head_ref }}"
    
    - name: checkout code
      uses: actions/checkout@v4
    
    - name: Install uv
      uses: astral-sh/setup-uv@v5

    - name: Install dependencies
      run: uv sync --extra dev

    - name: Check static error
      run: |
        uv run ruff check --show-fixes --output-format=github

    - name: Reformat code style
      run: |
        echo '## Reformat summary' >> $GITHUB_STEP_SUMMARY
        if diff_output="$(uv run ruff format --diff 2>&1)"; then
          echo "$diff_output"
          echo '✅ Format check passed.' >> "$GITHUB_STEP_SUMMARY"
        else
          echo "$diff_output"
          echo '❌ Format issues detected.' >> "$GITHUB_STEP_SUMMARY"
          {
            echo '```diff'
            echo "$diff_output"
            echo '```'
          } >> "$GITHUB_STEP_SUMMARY"
          exit 1
        fi


================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[codz]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py.cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# UV
#   Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
#   This is especially recommended for binary packages to ensure reproducibility, and is more
#   commonly ignored for libraries.
#uv.lock

# poetry
#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
#   This is especially recommended for binary packages to ensure reproducibility, and is more
#   commonly ignored for libraries.
#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
#poetry.toml

# pdm
#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#   pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
#   https://pdm-project.org/en/latest/usage/project/#working-with-version-control
#pdm.lock
#pdm.toml
.pdm-python
.pdm-build/

# pixi
#   Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
#pixi.lock
#   Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
#   in the .venv directory. It is recommended not to include this directory in version control.
.pixi

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.env.*
.envrc
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site
site/

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
#  and can be added to the global gitignore or merged into this file.  For a more nuclear
#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# Abstra
# Abstra is an AI-powered process automation framework.
# Ignore directories containing user credentials, local state, and settings.
# Learn more at https://abstra.io/docs
.abstra/

# Visual Studio Code
#  Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore 
#  that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
#  and can be added to the global gitignore or merged into this file. However, if you prefer, 
#  you could uncomment the following to ignore the entire vscode folder
# .vscode/

# Ruff stuff:
.ruff_cache/

# PyPI configuration file
.pypirc

# Cursor
#  Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
#  exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
#  refer to https://docs.cursor.com/context/ignore-files
.cursorignore
.cursorindexingignore

# Marimo
marimo/_static/
marimo/_lsp/
__marimo__/

logs/
tmp/
thirdparty/

data/*
!data/README.md
!data/FSI-2023-DOWNLOAD.xlsx

debug.py
**/debug.py

# Web app
web_app/frontend/node_modules/
web_app/frontend/dist/
web_app/frontend/package-lock.json
web_app/static/
web_app/sessions/
web_app/uploads/
.claude/
.vscode/
.ruff_cache/
.env
.env.*

================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
<div align="center">
  <img src="docs/mkdocs/docs/assets/miromind_logo.png" width="45%" alt="MiroMind" />

  <h3>Performance-First Agent Framework That Makes Any Model Better</h3>

[![DEMO](https://img.shields.io/badge/Demo-FFB300?style=for-the-badge&logo=airplayvideo&logoColor=white)](https://dr.miromind.ai/)
[![MODELS](https://img.shields.io/badge/Models-5EDDD2?style=for-the-badge&logo=huggingface&logoColor=ffffff&labelColor)](https://huggingface.co/miromind-ai)
[![DOCS](https://img.shields.io/badge/Docs-8CA1AF?style=for-the-badge&logo=readthedocs&logoColor=white)](https://miromindai.github.io/MiroFlow/)
[![WEBSITE](https://img.shields.io/badge/Website-4285F4?style=for-the-badge&logo=google-chrome&logoColor=white)](https://miromind.ai)
[![DISCORD](https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.com/invite/GPqEnkzQZd)
[![RedNote](https://img.shields.io/badge/RedNote-FF2442?style=for-the-badge&logo=revoltdotchat&logoColor=white)](https://www.xiaohongshu.com/user/profile/663098830000000003033edc)

</div>

<div align="center">
<strong>MiroFlow</strong> is the open-source agent framework that maximizes any model's agent performance — and proves it across 9+ benchmarks with reproducible results.<br>
Plug in GPT-5, Claude, <a href="https://github.com/MiroMindAI/mirothinker">MiroThinker</a>, Kimi, DeepSeek, or any OpenAI-compatible model. Same tools. Same environment. Better results.
</div>

<br>

<div align="center">
  <img src="docs/mkdocs/docs/assets/futurex_results.jpg" width="100%" alt="FutureX Benchmark Results" />
</div>

---

## 📰 News

- **[2026-03]**: **MiroFlow 1.7 + MiroThinker 1.7**: Major release with Web Application interface (FastAPI + React), comprehensive verifier system for benchmark evaluation, and expanded LLM support including Kimi K2.5 and GPT-5.

<details>
<summary><strong>Previous Updates</strong></summary>

- **[2025-09-15]**: **MiroFlow v0.3**: Enhanced codebase architecture and significantly improved benchmark performance, boosting GPT-5's prediction accuracy for future events by 11%. MiroFlow now ranks #1 in the future prediction benchmark. See [FutureX](https://futurex-ai.github.io/).
- **[2025-08-27]**: **MiroFlow v0.2**: Achieves state-of-the-art performance across [multiple agentic benchmarks](https://miromind.ai), including HLE (27.2%), HLE-Text-Only (29.5%), BrowserComp-EN (33.2%), BrowserComp-ZH (47.1%), and xBench-DeepSearch (72.0%).
- **[2025-08-26]**: Released GAIA Validation Trace (73.94% pass@1) and [Gradio Demo](https://github.com/MiroMindAI/MiroThinker/tree/main/apps/gradio-demo) for local deployment.
- **[2025-08-08]**: **MiroFlow v0.1**: Complete open-source release of the research agent framework.

</details>

---

## Architecture

<div align="center">
  <img src="docs/mkdocs/docs/assets/miroflow_architecture_v1.7.png" width="100%" alt="MiroFlow Architecture" />
</div>

---

## Why MiroFlow

### Make Any Model Better
- **Model-Agnostic Performance**: Plug in any LLM — GPT-5, Claude, MiroThinker, Kimi K2.5, DeepSeek — and get better agent performance through smart rollback, iterative reasoning, and optimized tool orchestration.
- **Comprehensive Benchmarking**: Supports 9+ benchmarks including FutureX, GAIA, HLE, xBench-DeepSearch, BrowseComp, and more.
- **One-Line Model Switching**: Change `provider_class` and `model_name` in YAML. Same tools, same prompts, same environment.

### Prove It
- **Standardized Evaluation**: Fair model comparison with identical infrastructure. The framework is the constant; the model is the variable.
- **Automated Multi-Run Evaluation**: Parallel runs with statistical aggregation (mean, std dev, min/max). Every result reproducible from config to score.

### Build With It
- **Skill System**: Define agent skills via `SKILL.md` — no code changes needed.
- **Agent Graph**: Compose multi-agent workflows with hierarchical graphs.
- **Web Application**: FastAPI + React interface out of the box.
- **Plugin Architecture**: `@register` decorator — extend without touching core code.
- **Zero-Code Prompts**: YAML + Jinja2 templates.
- **Cost-Effective**: Single RTX 4090 with open-source [MiroThinker](https://github.com/MiroMindAI/mirothinker).

---

## Any Model, Better Results

Benchmark results will be updated after comprehensive testing with v1.7. See the full [Model Comparison](https://miromindai.github.io/miroflow/model_comparison/) for details.

Follow our detailed guides to reproduce any result in our [Benchmarks Documentation](https://miromindai.github.io/miroflow/evaluation_overview/).

---

## Quick Start

```bash
# 1. Clone and setup
git clone https://github.com/MiroMindAI/miroflow && cd miroflow
uv sync

# 2. Configure API keys (only OPENAI_API_KEY is required for this example)
cp .env.template .env
# Edit .env and set OPENAI_API_KEY (used by GPT-5 in the default quickstart config)

# 3. Run your first task
bash scripts/test_single_task.sh \
  --config config/agent_quickstart.yaml \
  --task-question "What is the first country listed in the XLSX file that have names starting with Co?" \
  --file-path data/FSI-2023-DOWNLOAD.xlsx
```

Expected output: `\boxed{Congo Democratic Republic}`

**Switch models in one line** — same tools, same prompts, different LLM:

```yaml
# GPT-5
llm:
  provider_class: GPT5OpenAIClient
  model_name: gpt-5

# Claude 3.7 Sonnet
llm:
  provider_class: ClaudeAnthropicClient
  model_name: claude-3-7-sonnet-20250219

# MiroThinker (open-source, self-hosted)
llm:
  provider_class: MiroThinkerSGLangClient
  model_name: mirothinker-v1.5
```

See [full documentation](https://miromindai.github.io/miroflow/quickstart/) for web app setup, more examples, and configuration options.

---

## References

If you find our work helpful, please consider citing:

**MiroThinker** (Model & Method)
```bibtex
@article{miromind2025mirothinker,
  title={MiroThinker: Pushing the Performance Boundaries of Open-Source Research Agents via Model, Context, and Interactive Scaling},
  author={MiroMind Team and Bai, Song and Bing, Lidong and Chen, Carson and Chen, Guanzheng and Chen, Yuntao and Chen, Zhe and Chen, Ziyi and Dong, Xuan and others},
  journal={arXiv preprint arXiv:2511.11793},
  year={2025}
}
```

**MiroFlow** (Framework)
```bibtex
@article{miromind2026miroflow,
  title={MiroFlow: Towards High-Performance and Robust Open-Source Agent Framework for General Deep Research Tasks},
  author={Su, Shiqian and Xing, Sen and Dong, Xuan and Zhong, Muyan and Wang, Bin and Zhu, Xizhou and Chen, Yuntao and Wang, Wenhai and Deng, Yue and Zhu, Pengxiang and others},
  journal={arXiv preprint arXiv:2602.22808},
  year={2026}
}
```

---

<div align="center">

<a href="https://github.com/MiroMindAI/miroflow/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=MiroMindAI/miroflow" />
</a>

**Contributing**: [Issues](https://github.com/MiroMindAI/miroflow/issues) · [Pull Requests](https://github.com/MiroMindAI/miroflow/pulls) · [Discord](https://discord.com/invite/GPqEnkzQZd)

**License**: Apache 2.0

</div>


================================================
FILE: REUSE.toml
================================================
version = 1

# cursor, gitignore and github workflow
[[annotations]]
path = ["**/.cursor/**", ".github/**", "**/.gitignore", "**/justfile", "**/Makefile", "**/.env.template"]
SPDX-FileCopyrightText = "MiromindAI"
SPDX-License-Identifier = "Apache-2.0"

# hydra configs
[[annotations]]
path = ["config/**.yaml", "config/**.py"]
SPDX-FileCopyrightText = "MiromindAI"
SPDX-License-Identifier = "Apache-2.0"

# uv-related
[[annotations]]
path = ["**/.python-version", "**/pyproject.toml", "**/uv.lock"]
SPDX-FileCopyrightText = "MiromindAI"
SPDX-License-Identifier = "Apache-2.0"

# docs
[[annotations]]
path = ["**/*.md"]
SPDX-FileCopyrightText = "MiromindAI"
SPDX-License-Identifier = "Apache-2.0"

================================================
FILE: config/__init__.py
================================================
# SPDX-FileCopyrightText: 2025 MiromindAI
#
# SPDX-License-Identifier: Apache-2.0

import os
import pathlib
from datetime import datetime

import hydra
import omegaconf


def load_config(config_path: str, *overrides) -> omegaconf.DictConfig:
    """Initialize Hydra and load configuration with timestamped output directory."""
    # Extract config name (remove "config/" prefix and file extension)
    config_name = config_path
    if config_name.startswith("config/"):
        config_name = config_name[7:]
    if config_name.endswith((".yaml", ".yml")):
        config_name = os.path.splitext(config_name)[0]

    # Check if output_dir is explicitly specified in overrides
    output_dir_override = None
    for override in overrides:
        if override.startswith("output_dir="):
            output_dir_override = override.split("=", 1)[1]
            break

    # Load and resolve configuration
    hydra.initialize_config_dir(
        config_dir=str(pathlib.Path(__file__).parent.absolute()), version_base=None
    )
    cfg = hydra.compose(config_name=config_name, overrides=list(overrides))
    cfg = omegaconf.OmegaConf.create(
        omegaconf.OmegaConf.to_container(cfg, resolve=True)
    )

    # Create timestamped output directory only if output_dir was not explicitly specified
    if output_dir_override is None:
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output_dir = pathlib.Path(cfg.output_dir) / f"{config_name}_{timestamp}"
        output_dir.mkdir(parents=True, exist_ok=True)
        cfg.output_dir = str(output_dir)
    else:
        # Use the explicitly specified output_dir directly
        output_dir = pathlib.Path(cfg.output_dir)
        output_dir.mkdir(parents=True, exist_ok=True)
        cfg.output_dir = str(output_dir)

    return cfg


================================================
FILE: config/agent_quickstart.yaml
================================================
# MiroFlow Gradio Demo Configuration
# A simplified configuration for the Gradio web interface (using MiroThinker)

# No benchmark defaults - this is a standalone config
defaults:
  - benchmark: example_dataset
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent

main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_turns: 30
  verbose: true  # Print turn-by-turn agent loop details (LLM usage, tool calls, rollbacks)

  llm:
    _base_: config/llm/base_openai.yaml
    provider_class: GPT5OpenAIClient
    model_name: gpt-5
    max_tokens: 128000
    reasoning_effort: medium

  prompt: config/prompts/prompt_main_agent_benchmark.yaml

  tools:
    - config/tool/tool-reading.yaml
    # - config/tool/tool-code-sandbox.yaml
    # - config/tool/tool-serper-search.yaml
    # - config/tool/tool-jina-scrape.yaml
    #- config/tool/tool-code.yaml
    #- config/tool/tool-image-video.yaml
    # - config/tool/tool-audio.yaml     # Uncomment for audio processing

  input_processor:
    - ${input-message-generator}

  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}

# Input processor: generates initial message from task description
input-message-generator:
  type: InputMessageGenerator

# Output processor: summarizes conversation
output-summary:
  type: SummaryGenerator

# Output processor: extracts final answer in a boxed format
output-boxed-extractor:
  type: RegexBoxedExtractor

# Output directory for logs
output_dir: logs
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: false


================================================
FILE: config/agent_quickstart_graph.yaml
================================================
# MiroFlow Gradio Demo Configuration
# A simplified configuration for the Gradio web interface (using MiroThinker)

# No benchmark defaults - this is a standalone config
defaults:
  - benchmark: example_dataset
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent

main_agent:
  name: main_agent
  type: IterativeAgentWithTool
  max_turns: 30

  llm:
    _base_: config/llm/base_openai.yaml
    provider_class: GPT5OpenAIClient
    model_name: gpt-5
    max_tokens: 128000
    reasoning_effort: medium

  prompt: config/prompts/prompt_main_agent_benchmark.yaml

  tools: null

  input_processor:
    - ${input-message-generator}

  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}

  sub_agents:
    agent-worker: ${agent-subagent-1}

agent-subagent-1:
  type: IterativeAgentWithTool     
  name: agent-subagent-1
  max_consecutive_rollbacks: 3
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_sub_agent.yaml
  tools: null
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
  sub_agents:
    agent-worker: ${agent-subagent-3}

agent-subagent-2:
  type: IterativeAgentWithTool     
  name: agent-subagent-2
  max_consecutive_rollbacks: 3
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_sub_agent.yaml
  tools: null
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
  sub_agents:
    agent-worker: ${agent-subagent-3}

agent-subagent-3:
  type: IterativeAgentWithTool     
  name: agent-subagent-3
  max_consecutive_rollbacks: 3
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_sub_agent.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}



# Input processor: generates initial message from task description
input-message-generator:
  type: InputMessageGenerator

# Output processor: summarizes conversation
output-summary:
  type: SummaryGenerator

# Output processor: extracts final answer in a boxed format
output-boxed-extractor:
  type: RegexBoxedExtractor

# Output directory for logs
output_dir: logs
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: false


================================================
FILE: config/agent_quickstart_skill.yaml
================================================
# MiroFlow Quickstart with Skill Configuration
# A simple single-agent setup with the reading tool and simple_file_understanding skill.
#
# Usage:
#   bash scripts/test_single_task.sh \
#     --config config/agent_quickstart_skill.yaml \
#     --task-question "What is the first country listed in the XLSX file that have names starting with Co?" \
#     --file-path data/FSI-2023-DOWNLOAD.xlsx

defaults:
  - benchmark: example_dataset
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent

main_agent:
  name: main_agent
  type: IterativeAgentWithTool
  max_turns: 30

  llm:
    _base_: config/llm/base_openai.yaml
    provider_class: GPT5OpenAIClient
    model_name: gpt-5
    max_tokens: 128000
    reasoning_effort: medium

  prompt: config/prompts/prompt_main_agent_benchmark.yaml

  tools: 
    - config/tool/tool-code-sandbox.yaml

  skills:
    - miroflow/skill/skills/simple_file_understanding

  input_processor:
    - ${input-message-generator}

  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}

# Input processor: generates initial message from task description
input-message-generator:
  type: InputMessageGenerator

# Output processor: summarizes conversation
output-summary:
  type: SummaryGenerator

# Output processor: extracts final answer in a boxed format
output-boxed-extractor:
  type: RegexBoxedExtractor

# Output directory for logs
output_dir: logs
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: false


================================================
FILE: config/agent_single-test.yaml
================================================
defaults:
  - benchmark: gaia-validation
  - override hydra/job_logging: none
  - _self_  # Allow defining variables at the top of this file

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback                           
  llm: 
    _base_: config/llm/base_openai.yaml
    provider_class: GPT5OpenAIClient
    model_name: gpt-5
    max_tokens: 128000
  prompt: config/prompts/prompt_main_agent.yaml
  tools:
    # - config/tool/tool-searching.yaml
    # - config/tool/tool-image-video.yaml
    # - config/tool/tool-reading.yaml
    # - config/tool/tool-code.yaml
    - config/tool/tool-audio.yaml
    # - config/tool/tool-reasoning.yaml
  skills:
    - miroflow/skill/skills/Today_feeling
    - miroflow/skill/skills/Afternoon_feeling
  input_processor:
    - ${input-hint-generator} 
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-final-answer-extraction}
  
input-hint-generator:
  type: InputHintGenerator
  llm:
    _base_: config/llm/base_openai.yaml
    model_name: o3
input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-final-answer-extraction:
  type: FinalAnswerExtractor
  prompt: config/prompts/prompt_final_answer_extraction.yaml
  llm:
    _base_: config/llm/base_openai.yaml
    model_name: o3
  #llm o3 TODO


output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"  # Points to where data is stored




================================================
FILE: config/agent_web_demo.yaml
================================================
# MiroFlow Web Demo Configuration
# A simplified configuration for the web interface (using MiroThinker)

# No benchmark defaults - this is a standalone config
defaults:
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent

main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_turns: 30

  llm:
    _base_: config/llm/base_mirothinker.yaml
    provider_class: MiroThinkerSGLangClient
    model_name: mirothinker-v1.5

  prompt: config/prompts/prompt_main_agent.yaml

  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
    - config/tool/tool-reading.yaml
    #- config/tool/tool-code.yaml
    #- config/tool/tool-image-video.yaml
    # - config/tool/tool-audio.yaml     # Uncomment for audio processing

  input_processor:
    - ${input-message-generator}

  output_processor:
    - ${output-summary}
    - ${output-final-answer-extraction}

# Input processor: generates initial message from task description
input-message-generator:
  type: InputMessageGenerator

# Output processor: summarizes conversation
output-summary:
  type: SummaryGenerator

# Output processor: extracts final answer
output-final-answer-extraction:
  type: FinalAnswerExtractor
  prompt: config/prompts/prompt_final_answer_extraction.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml
    model_name: mirothinker-v1.5

# Output directory for logs
output_dir: logs/gradio_runs/


================================================
FILE: config/benchmark/browsecomp-en-200.yaml
================================================
# config/benchmark/browsecomp-en.yaml
defaults:
  - default
  - _self_

name: "browsecomp-en-200"

data:
  data_dir: "${data_dir}/browsecomp-200"  # Path to browsecomp-200 (English) dataset
  metadata_file: "standardized_data.jsonl"  # Metadata filename
  whitelist: []  # Optional: List of specific task_ids to run

execution:
  max_tasks: null      # null = no limit, or specify a number
  max_concurrent: 5    # Number of parallel tasks
  pass_at_k: 1         # Number of attempts per task
  max_retry: 5
  exceed_max_turn_summary: true

# OpenAI API key for evaluation (required for browsecomp since it has ground truth)
openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"



================================================
FILE: config/benchmark/browsecomp-en.yaml
================================================
# config/benchmark/browsecomp-en.yaml
defaults:
  - default
  - _self_

name: "browsecomp-en"

data:
  data_dir: "${data_dir}/browsecomp-test"  # Path to browsecomp-test (English) dataset
  metadata_file: "standardized_data.jsonl"  # Metadata filename
  whitelist: []  # Optional: List of specific task_ids to run

execution:
  max_tasks: null      # null = no limit, or specify a number
  max_concurrent: 5    # Number of parallel tasks
  pass_at_k: 1         # Number of attempts per task
  max_retry: 5
  exceed_max_turn_summary: true

# OpenAI API key for evaluation (required for browsecomp since it has ground truth)
openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"



================================================
FILE: config/benchmark/browsecomp-zh.yaml
================================================
# config/benchmark/browsecomp-zh.yaml
defaults:
  - default
  - _self_

name: "browsecomp-zh"

data:
  data_dir: "${data_dir}/browsecomp-zh-test"  # Path to browsecomp-zh-test (Chinese) dataset
  metadata_file: "standardized_data.jsonl"  # Metadata filename
  whitelist: []  # Optional: List of specific task_ids to run

execution:
  max_tasks: null      # null = no limit, or specify a number
  max_concurrent: 5    # Number of parallel tasks
  pass_at_k: 1         # Number of attempts per task
  max_retry: 5
  exceed_max_turn_summary: true

# OpenAI API key for evaluation (required for browsecomp-zh since it has ground truth)
openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"

================================================
FILE: config/benchmark/default.yaml
================================================
# config/benchmark/default.yaml - Default benchmark configuration
# This is a base configuration for benchmarks. Specific benchmarks can override these defaults.
name: "default"

data:
  metadata_file: "standardized_data.jsonl"
  whitelist: []

execution:
  max_tasks: null  # null means no limit
  max_concurrent: 5
  pass_at_k: 1
  max_retry: 1
  exceed_max_turn_summary: false

================================================
FILE: config/benchmark/example_dataset.yaml
================================================
# config/benchmark/example_dataset.yaml
defaults:
  - default
  - _self_

name: "example_dataset"

data:
  data_dir: "${data_dir}/example_dataset"  # Path to example_dataset
  metadata_file: "standardized_data.jsonl"  # Metadata filename
  whitelist: []  # Optional: List of specific task_ids to run

execution:
  max_tasks: null      # null = no limit, or specify a number
  max_concurrent: 5    # Number of parallel tasks
  pass_at_k: 1         # Number of attempts per task

# OpenAI API key for evaluation (required for example_dataset since it has ground truth)
openai_api_key: "${oc.env:OPENAI_API_KEY,???}"




================================================
FILE: config/benchmark/finsearchcomp.yaml
================================================
# config/benchmark/finsearchcomp.yaml
defaults:
  - default
  - _self_

name: "finsearchcomp"

data:
  data_dir: "${data_dir}/finsearchcomp"  # Path to finsearchcomp dataset
  metadata_file: "standardized_data.jsonl"  # Metadata filename
  whitelist: []  # Optional: List of specific task_ids to run

execution:
  max_tasks: null      # null = no limit, or specify a number
  max_concurrent: 5    # Number of parallel tasks
  pass_at_k: 1         # Number of attempts per task

# OpenAI API key for evaluation (required for finsearchcomp since it has ground truth)
openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"


================================================
FILE: config/benchmark/frames-test.yaml
================================================
# config/benchmark/frames-test.yaml
defaults:
  - default
  - _self_

name: "frames-test"

data:
  data_dir: "${data_dir}/frames-test"  # Path to frames-test dataset
  metadata_file: "standardized_data.jsonl"  # Metadata filename
  whitelist: []  # Optional: List of specific task_ids to run

execution:
  max_tasks: null      # null = no limit, or specify a number
  max_concurrent: 5    # Number of parallel tasks
  pass_at_k: 1         # Number of attempts per task
  max_retry: 5
  exceed_max_turn_summary: true

# OpenAI API key for evaluation (required for frames-test since it has ground truth)
openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"


================================================
FILE: config/benchmark/futurex.yaml
================================================
# config/benchmark/futurex.yaml
defaults:
  - default
  - _self_

name: "futurex"

data:
  data_dir: "${data_dir}/futurex"  # Path to your dataset
  metadata_file: "standardized_data.jsonl"  # Metadata filename
  whitelist: []  # Optional: List of specific task_ids to run

execution:
  max_tasks: null      # null = no limit, or specify a number
  max_concurrent: 5    # Number of parallel tasks
  pass_at_k: 1         # Number of attempts per task

# Set to skip evaluation since we don't have ground truth
openai_api_key: "skip_evaluation"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"



================================================
FILE: config/benchmark/gaia-test.yaml
================================================
# config/benchmark/gaia-validation.yaml
defaults:
  - default
  - _self_

name: "gaia-test"

data:
  data_dir: "${data_dir}/gaia-test"

execution:
  max_tasks: null  # null means no limit
  max_concurrent: 10
  pass_at_k: 1

openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"


================================================
FILE: config/benchmark/gaia-validation-165.yaml
================================================
# config/benchmark/gaia-validation-165.yaml
defaults:
  - default
  - _self_

name: "gaia-validation-165"

data:
  data_dir: "${data_dir}/gaia-val"

execution:
  max_tasks: null
  max_concurrent: 3
  pass_at_k: 1
  max_retry: 5
  exceed_max_turn_summary: true

openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"


================================================
FILE: config/benchmark/gaia-validation-text-only.yaml
================================================
# config/benchmark/gaia-validation.yaml
defaults:
  - default
  - _self_

name: "gaia-validation-text-only"

data:
  data_dir: "${data_dir}/gaia-val-text-only"

execution:
  max_tasks: null
  max_concurrent: 3
  pass_at_k: 1
  max_retry: 5
  exceed_max_turn_summary: true

openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"

================================================
FILE: config/benchmark/gaia-validation.yaml
================================================
# config/benchmark/gaia-validation.yaml
defaults:
  - default
  - _self_

name: "gaia-validation"

data:
  data_dir: "${data_dir}/gaia-val"

execution:
  max_tasks: -1  # null means no limit
  max_concurrent: 15
  pass_at_k: 1
  max_retry: 5
  exceed_max_turn_summary: true

openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"


================================================
FILE: config/benchmark/hle-text-only.yaml
================================================
# config/benchmark/hle-text-only.yaml
defaults:
  - default
  - _self_

name: "hle-text-only"

data:
  data_dir: "${data_dir}/hle-text-only"  # Path to hle-text-only dataset
  metadata_file: "standardized_data.jsonl"  # Metadata filename
  whitelist: []  # Optional: List of specific task_ids to run

execution:
  max_tasks: null      # null = no limit, or specify a number
  max_concurrent: 10    # Number of parallel tasks
  pass_at_k: 1         # Number of attempts per task
  max_retry: 5
  exceed_max_turn_summary: true

# OpenAI API key for evaluation (required for hle-text-only since it has ground truth)
openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"



================================================
FILE: config/benchmark/hle.yaml
================================================
# config/benchmark/hle.yaml
defaults:
  - default
  - _self_

name: "hle"

data:
  data_dir: "${data_dir}/hle"  # Path to hle dataset
  metadata_file: "standardized_data.jsonl"  # Metadata filename
  whitelist: []  # Optional: List of specific task_ids to run

execution:
  max_tasks: null      # null = no limit, or specify a number
  max_concurrent: 10    # Number of parallel tasks
  pass_at_k: 1         # Number of attempts per task
  max_retry: 5
  exceed_max_turn_summary: true

# OpenAI API key for evaluation (required for hle since it has ground truth)
openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"



================================================
FILE: config/benchmark/webwalkerqa.yaml
================================================
# config/benchmark/webwalkerqa.yaml
defaults:
  - default
  - _self_

name: "webwalkerqa"

data:
  data_dir: "${data_dir}/webwalkerqa"  # Path to webwalkerqa dataset
  metadata_file: "standardized_data.jsonl"  # Metadata filename
  whitelist: []  # Optional: List of specific task_ids to run

execution:
  max_tasks: null      # null = no limit, or specify a number
  max_concurrent: 5    # Number of parallel tasks
  pass_at_k: 1         # Number of attempts per task
  max_retry: 5
  exceed_max_turn_summary: true

# OpenAI API key for evaluation (required for webwalkerqa since it has ground truth)
openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"




================================================
FILE: config/benchmark/xbench-ds.yaml
================================================
# config/benchmark/xbench-ds.yaml
defaults:
  - default
  - _self_

name: "xbench-ds"

data:
  data_dir: "${data_dir}/xbench-ds"

execution:
  max_tasks: null  # null means no limit
  max_concurrent: 10
  pass_at_k: 1
  max_retry: 5
  exceed_max_turn_summary: true

openai_api_key: "${oc.env:OPENAI_API_KEY,???}"
openai_base_url: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"


================================================
FILE: config/benchmark_browsecomp-en-200_mirothinker_v1.yaml
================================================
defaults:
  - benchmark: browsecomp-en-200
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 400
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_browsecomp-en_mirothinker.yaml
================================================
defaults:
  - benchmark: browsecomp-en
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 400
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_browsecomp-zh_mirothinker_v1.yaml
================================================
defaults:
  - benchmark: browsecomp-zh
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 400
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_browsecomp-zh_mirothinker_v2.yaml
================================================
defaults:
  - benchmark: browsecomp-zh
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 400
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-sogou-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_browsecomp-zh_mirothinker_v3.yaml
================================================
defaults:
  - benchmark: browsecomp-zh
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 400
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-scrape-website-v1.yaml
  tool_blacklist:
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_frames-test_mirothinker.yaml
================================================
defaults:
  - benchmark: frames-test
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_gaia-validation-165_mirothinker_tool.yaml
================================================
defaults:
  - benchmark: gaia-validation-165
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
    - config/tool/tool-reading.yaml
    - config/tool/tool-audio.yaml
    - config/tool/tool-image-video.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${file-content-preprocessor}
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

file-content-preprocessor:
  type: FileContentPreprocessor
input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_gaia-validation-165_mirothinker_v1.yaml
================================================
defaults:
  - benchmark: gaia-validation-165
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml

  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"

  input_processor:
    - ${file-content-preprocessor}
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

file-content-preprocessor:
  type: FileContentPreprocessor
input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_gaia-validation-text-103_kimi_k25.yaml
================================================
defaults:
  - benchmark: gaia-validation-text-only
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_kimi_k25.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_kimi_k25.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_gaia-validation-text-103_mirothinker_multi-agent.yaml
================================================
defaults:
  - benchmark: gaia-validation-text-only
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  # max_consecutive_rollbacks: 5
  # max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools: null
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}
  sub_agents:
    agent-worker: ${agent-worker}

agent-worker:
  type: IterativeAgentWithToolAndRollback     
  name: agent-worker
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_sub_agent.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}

  


input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_gaia-validation-text-103_mirothinker_v1.yaml
================================================
defaults:
  - benchmark: gaia-validation-text-only
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_gaia-validation-text-103_mirothinker_v2.yaml
================================================
defaults:
  - benchmark: gaia-validation-text-only
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-sogou-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_hle-text-only_mirothinker.yaml
================================================
defaults:
  - benchmark: hle-text-only
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_hle_mirothinker_v1.yaml
================================================
defaults:
  - benchmark: hle
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_webwalkerqa_mirothinker.yaml
================================================
defaults:
  - benchmark: webwalkerqa
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/benchmark_xbench-ds_mirothinker.yaml
================================================
defaults:
  - benchmark: xbench-ds
  - override hydra/job_logging: none
  - _self_

entrypoint: main_agent
main_agent:
  name: main_agent
  type: IterativeAgentWithToolAndRollback
  max_consecutive_rollbacks: 5
  max_turns: 200
  llm:
    _base_: config/llm/base_mirothinker.yaml
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  tools:
    - config/tool/tool-code-sandbox.yaml
    - config/tool/tool-serper-search.yaml
    - config/tool/tool-jina-scrape.yaml
  tool_blacklist:
    - server: "tool-serper-search"
      tool: "sogou_search"
    - server: "tool-code-sandbox"
      tool: "download_file_from_sandbox_to_local"
  input_processor:
    - ${input-message-generator}
  output_processor:
    - ${output-summary}
    - ${output-boxed-extractor}
    - ${output-exceed-max-turn-summary}

input-message-generator:
  type: InputMessageGenerator
output-summary:
  type: SummaryGenerator
output-boxed-extractor:
  type: RegexBoxedExtractor
output-exceed-max-turn-summary:
  type: ExceedMaxTurnSummaryGenerator
  prompt: config/prompts/prompt_main_agent_benchmark.yaml
  llm:
    _base_: config/llm/base_mirothinker.yaml

output_dir: logs/
data_dir: "${oc.env:DATA_DIR,data}"

benchmark:
  exceed_max_turn_summary: true


================================================
FILE: config/llm/base_kimi_k25.yaml
================================================
# config/llm/base_kimi_k25.yaml
provider_class: "OpenRouterClient"
model_name: "moonshotai/kimi-k2.5"
openrouter_api_key: ${oc.env:OPENROUTER_API_KEY,???}
openrouter_base_url: ${oc.env:OPENROUTER_BASE_URL,https://openrouter.ai/api/v1}
openrouter_provider: ""

temperature: 1.0
top_p: 0.95
min_p: 0.0
top_k: -1

max_tokens: 32000
max_context_length: -1
async_client: true

reasoning_effort: null
repetition_penalty: 1.0

disable_cache_control: true
keep_tool_result: 5

use_tool_calls: false
oai_tool_thinking: false


================================================
FILE: config/llm/base_mirothinker.yaml
================================================
# config/llm/base.yaml
provider_class: "MiroThinkerSGLangClient"
model_name: mirothinker-v1.5
api_key: ${oc.env:OAI_MIROTHINKER_API_KEY,???}
base_url: ${oc.env:OAI_MIROTHINKER_BASE_URL,http://localhost:9000/v1}

temperature: 1.0
top_p: 0.95
min_p: 0.0
top_k: -1

max_tokens: 16384
max_context_length: 262144
async_client: true

reasoning_effort: null
repetition_penalty: 1.05

disable_cache_control: false
keep_tool_result: 5
strip_think_from_history: false

use_tool_calls: false
oai_tool_thinking: false


================================================
FILE: config/llm/base_openai.yaml
================================================
# config/llm/base.yaml
provider_class: "GPTOpenAIClient"
model_name: null
api_key: ${oc.env:OPENAI_API_KEY,???}
base_url: ${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}

temperature: 1.0
top_p: 1.0
min_p: 0.0
top_k: -1

max_tokens: 32000
max_context_length: -1
async_client: true

reasoning_effort: null
repetition_penalty: 1.0

disable_cache_control: true
keep_tool_result: -1

use_tool_calls: false
oai_tool_thinking: false


================================================
FILE: config/prompts/__init__.py
================================================
# SPDX-FileCopyrightText: 2025 MiromindAI
#
# SPDX-License-Identifier: Apache-2.0

import os
import importlib
import pkgutil
import inspect

# Dynamically import all classes from all .py files in this directory (excluding __init__.py)
__all__ = []

package_dir = os.path.dirname(__file__)

for module_info in pkgutil.iter_modules([package_dir]):
    module_name = module_info.name
    if module_name == "__init__":
        continue  # Skip __init__.py
    # Import the module
    module = importlib.import_module(f"{__name__}.{module_name}")
    # Inspect all classes defined in the module
    for name, obj in inspect.getmembers(module, inspect.isclass):
        # Only include classes defined in this module (not imported ones)
        if obj.__module__ == module.__name__:
            globals()[name] = obj
            __all__.append(name)


================================================
FILE: config/prompts/base_agent_prompt.py
================================================
from abc import ABC, abstractmethod
import dataclasses
from typing import Any


@dataclasses.dataclass
class BaseAgentPrompt(ABC):
    """
    Abstract base class for agent prompt templates.
    All agent prompt classes should inherit from this and implement the required methods.
    """

    is_main_agent: bool = True

    def __init__(self, *args, **kwargs):
        pass

    @abstractmethod
    def generate_system_prompt_with_mcp_tools(
        self, mcp_servers: list[Any], **kwargs
    ) -> str:
        """
        Generate the system prompt with mcp tools for the agent.

        Args:
            date (datetime.datetime): The current date.
            mcp_servers (list[Any]): List of MCP server configurations.
            **kwargs: Additional keyword arguments for extensibility.

        Returns:
            str: The system prompt string.

        Raises:
            NotImplementedError: This method must be implemented by subclasses.
        """
        raise NotImplementedError(
            "Subclasses must implement generate_mcp_system_prompt with support for extra kwargs."
        )

    @abstractmethod
    def generate_summarize_prompt(
        self,
        task_description: str,
        task_failed: bool = False,
        **kwargs,
    ) -> str:
        """
        Generate the summarize prompt for the agent.

        Args:
            task_description (str): The description of the task.
            task_failed (bool, optional): Whether the task failed. Defaults to False.
            agent_type (str, optional): The type of the agent. Defaults to "".
            **kwargs: Additional keyword arguments for extensibility.

        Returns:
            str: The summarize prompt string.

        Raises:
            NotImplementedError: This method must be implemented by subclasses.
        """
        raise NotImplementedError(
            "Subclasses must implement generate_summarize_prompt with support for extra kwargs."
        )

    def expose_agent_as_tool(self, subagent_name: str, **kwargs) -> dict:
        """
        Expose this agent as a tool.
        Main agent does not need to expose itself as tools.
        Sub-agents should implement this method to expose themselves as tools.

        Args:
            subagent_name (str): The name of the subagent.
            **kwargs: Additional keyword arguments for extensibility.

        Returns:
            dict: The tool definition dictionary with 'name' and 'tools' keys.
        """
        if self.is_main_agent:
            return {}
        else:
            raise NotImplementedError(
                "Subclasses must implement expose_agent_as_tool with support for extra kwargs."
            )

            # Output Example (this code will never be executed):
            tool_definition = dict(
                name=subagent_name,  # Name MUST starts with 'agent-'
                tools=[
                    dict(
                        name="execute_subtask",
                        description="This tool is an agent that performs various subtasks to collect information and execute specific actions... ",
                        schema={
                            "type": "object",
                            "properties": {
                                "subtask": {"title": "Subtask", "type": "string"}
                            },
                            "required": ["subtask"],
                            "title": "execute_subtaskArguments",
                        },
                    )
                ],
            )
            return tool_definition


================================================
FILE: config/prompts/main_agent_prompt_deepseek.py
================================================
import datetime
from typing import Any


class MainAgentPromptBoxedDeepSeek:
    """
    Adapted from MainAgentPromptBoxedAnswer. Since the tool-use is DeepSeek format, we remove the <use_mcp_tool> tags and its corresponding format instructions.
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.is_main_agent = True

    def generate_system_prompt_with_mcp_tools(self, mcp_servers: list[Any]) -> str:
        formatted_date = datetime.datetime.today().strftime("%Y-%m-%d")

        # Basic system prompt
        prompt = f"""In this environment you have access to a set of tools you can use to answer the user's question. 

You only have access to the tools provided below. You can only use one tool per message, and will receive the result of that tool in the user's next response. You use tools step-by-step to accomplish a given task, with each tool-use informed by the result of the previous tool-use. Today is: {formatted_date}

"""

        # Add MCP servers section
        if mcp_servers and len(mcp_servers) > 0:
            for server in mcp_servers:
                prompt += f"## Server name: {server['name']}\n"

                if "tools" in server and len(server["tools"]) > 0:
                    for tool in server["tools"]:
                        # Skip tools that failed to load (they only have 'error' key)
                        if "error" in tool and "name" not in tool:
                            continue
                        prompt += f"### Tool name: {tool['name']}\n"
                        prompt += f"Description: {tool['description']}\n"
                        prompt += f"Input JSON schema: {tool['schema']}\n"

        # Add the full objective system prompt
        prompt += """
# General Objective

You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.

## Task Strategy

1. Analyze the user's request and set clear, achievable sub-goals. Prioritize these sub-goals in a logical order.
2. Start with a concise, numbered, step-by-step plan (e.g., 1., 2., 3.) outlining how you will solve the task before taking any action. Each sub-goal should correspond to a distinct step in your task-solving process.
3. Work through these sub-goals sequentially. After each step, carefully review and extract all potentially relevant information, details, or implications from the tool result before proceeding. The user may provide tool-use feedback, reflect on the results, and revise your plan if needed. If you encounter new information or challenges, adjust your approach accordingly. Revisit previous steps to ensure earlier sub-goals or clues have not been overlooked or missed.
4. You have access to a wide range of powerful tools. Use them strategically to accomplish each sub-goal.

## Tool-Use Guidelines

1. **IMPORTANT: Each step must involve exactly ONE tool call only, unless the task is already solved. You are strictly prohibited from making multiple tool calls in a single response.** 
2. Before each tool call:
- Briefly summarize and analyze what is currently known.
- Identify what is missing, uncertain, or unreliable.
- Be concise; do not repeat the same analysis across steps.
- Choose the most relevant tool for the current sub-goal, and explain why this tool is necessary at this point.
- Verify whether all required parameters are either explicitly provided or can be clearly and reasonably inferred from context.
- Do not guess or use placeholder values for missing inputs.
- Skip optional parameters unless they are explicitly specified.
3. All tool queries must include full, self-contained context. Tools do not retain memory between calls. Include all relevant information from earlier steps in each query.
4. Avoid broad, vague, or speculative queries. Every tool call should aim to retrieve new, actionable information that clearly advances the task.
5. **For historical or time-specific content**: Regular search engines return current webpage content, not historical content. Archived webpage search is essential for retrieving content as it appeared in the past, use related tools to search for the historical content.
6. Even if a tool result does not directly answer the question, thoroughly extract and summarize all partial information, important details, patterns, constraints, or keywords that may help guide future steps. Never proceed to the next step without first ensuring that all significant insights from the current result have been fully considered.

## Tool-Use Communication Rules

1. **CRITICAL: After issuing exactly ONE tool call, STOP your response immediately. You must never make multiple tool calls in a single response. Do not include tool results, do not assume what the results will be, and do not continue with additional analysis or tool calls. The user will provide the actual tool results in their next message.**
2. Do not present the final answer until the entire task is complete.
3. Do not mention tool names.
4. Do not engage in unnecessary back-and-forth or end with vague offers of help. Do not end your responses with questions or generic prompts.
5. Do not use tools that do not exist.
6. Unless otherwise requested, respond in the same language as the user's message.
7. If the task does not require tool use, answer the user directly.

"""

        return prompt

    def generate_summarize_prompt(
        self,
        task_description: str,
        task_failed: bool = False,
    ) -> str:
        summarize_prompt = (
            (
                "============="
                "============="
                "============="
                "This is a direct instruction to you (the assistant), not the result of a tool call.\n\n"
            )
            + (
                "**Important: You have either exhausted the context token limit or reached the maximum number of interaction turns without arriving at a conclusive answer. Therefore, you failed to complete the task. You Must explicitly state that you failed to complete the task in your response.**\n\n"
                if task_failed
                else ""
            )
            + (
                "We are now ending this session, and your conversation history will be deleted. "
                "You must NOT initiate any further tool use. This is your final opportunity to report "
                "*all* of the information gathered during the session.\n\n"
                "Summarize the above conversation, and output the FINAL ANSWER to the original question.\n\n"
                "If a clear answer has already been provided earlier in the conversation, do not rethink or recalculate it — "
                "simply extract that answer and reformat it to match the required format below.\n"
                "If a definitive answer could not be determined, make a well-informed educated guess based on the conversation.\n\n"
                "The original question is repeated here for reference:\n\n"
                f"---\n{task_description}\n---\n\n"
                "Summarize ALL working history for this task, including your step-by-step thoughts, all tool calls, and all tool results (i.e., the full solving trajectory so far).\n"
                "Output the FINAL ANSWER and detailed supporting information of the task given to you.\n\n"
                "If you found any useful facts, data, or quotes directly relevant to the original task, include them clearly and completely.\n"
                "**Document the sources**: For each key fact or claim in your answer, mention which sources it came from and whether multiple sources confirmed it. If sources disagreed, explain the different viewpoints found.\n"
                "If you reached a conclusion or answer, include it as part of the response.\n"
                "If the task could not be fully answered, return all partially relevant findings, search results, quotes, and observations that might help a downstream agent solve the problem.\n"
                "If partial, conflicting, or inconclusive information was found, clearly indicate this in your response.\n\n"
                "Your final response should be a clear, complete, and structured report.\n"
                "Organize the content into logical sections with appropriate headings.\n"
                "Do NOT include any tool call instructions, speculative filler, or vague summaries.\n"
                "Focus on factual, specific, and well-organized information."
                "Output the final answer in the format: \\boxed{...}. The boxed answer should be a short phrase or a comma-separated list of numbers and/or strings."
            )
        )

        return summarize_prompt


================================================
FILE: config/prompts/main_agent_prompt_gaia.py
================================================
from config.agent_prompts.base_agent_prompt import BaseAgentPrompt
import datetime
from typing import Any


class MainAgentPrompt_GAIA(BaseAgentPrompt):
    """
    MainAgentGaiaPrompt inherits from BaseAgentPrompt and can be extended
    with main agent-specific prompt logic or configuration.
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.is_main_agent = True

    def generate_system_prompt_with_mcp_tools(self, mcp_servers: list[Any]) -> str:
        formatted_date = datetime.datetime.today().strftime("%Y-%m-%d")

        # Basic system prompt
        prompt = f"""In this environment you have access to a set of tools you can use to answer the user's question. 

You only have access to the tools provided below. You can only use one tool per message, and will receive the result of that tool in the user's next response. You use tools step-by-step to accomplish a given task, with each tool-use informed by the result of the previous tool-use. Today is: {formatted_date}

# Tool-Use Formatting Instructions 

Tool-use is formatted using XML-style tags. The tool-use is enclosed in <use_mcp_tool></use_mcp_tool> and each parameter is similarly enclosed within its own set of tags.

The Model Context Protocol (MCP) connects to servers that provide additional tools and resources to extend your capabilities. You can use the server's tools via the `use_mcp_tool`.

Description: 
Request to use a tool provided by a MCP server. Each MCP server can provide multiple tools with different capabilities. Tools have defined input schemas that specify required and optional parameters.

Parameters:
- server_name: (required) The name of the MCP server providing the tool
- tool_name: (required) The name of the tool to execute
- arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema, quotes within string must be properly escaped, ensure it's valid JSON

Usage:
<use_mcp_tool>
<server_name>server name here</server_name>
<tool_name>tool name here</tool_name>
<arguments>
{{
"param1": "value1",
"param2": "value2 \\"escaped string\\""
}}
</arguments>
</use_mcp_tool>

Important Notes:
- Tool-use must be placed **at the end** of your response, **top-level**, and not nested within other tags.
- Always adhere to this format for the tool use to ensure proper parsing and execution.

String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular expressions.
Here are the functions available in JSONSchema format:

"""

        # Add MCP servers section
        if mcp_servers and len(mcp_servers) > 0:
            for server in mcp_servers:
                prompt += f"## Server name: {server['name']}\n"

                if "tools" in server and len(server["tools"]) > 0:
                    for tool in server["tools"]:
                        # Skip tools that failed to load (they only have 'error' key)
                        if "error" in tool and "name" not in tool:
                            continue
                        prompt += f"### Tool name: {tool['name']}\n"
                        prompt += f"Description: {tool['description']}\n"
                        prompt += f"Input JSON schema: {tool['schema']}\n"

        # Add the full objective system prompt
        prompt += """
# General Objective

You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.

## Task Strategy

1. Analyze the user's request and set clear, achievable sub-goals. Prioritize these sub-goals in a logical order.
2. Start with a concise, numbered, step-by-step plan (e.g., 1., 2., 3.) outlining how you will solve the task before taking any action. Each sub-goal should correspond to a distinct step in your task-solving process.
3. Work through these sub-goals sequentially. After each step, carefully review and extract all potentially relevant information, details, or implications from the tool result before proceeding. The user may provide tool-use feedback, reflect on the results, and revise your plan if needed. If you encounter new information or challenges, adjust your approach accordingly. Revisit previous steps to ensure earlier sub-goals or clues have not been overlooked or missed.
4. You have access to a wide range of powerful tools. Use them strategically to accomplish each sub-goal.

## Tool-Use Guidelines

1. **IMPORTANT: Each step must involve exactly ONE tool call only, unless the task is already solved. You are strictly prohibited from making multiple tool calls in a single response.** 
2. Before each tool call:
- Briefly summarize and analyze what is currently known.
- Identify what is missing, uncertain, or unreliable.
- Be concise; do not repeat the same analysis across steps.
- Choose the most relevant tool for the current sub-goal, and explain why this tool is necessary at this point.
- Verify whether all required parameters are either explicitly provided or can be clearly and reasonably inferred from context.
- Do not guess or use placeholder values for missing inputs.
- Skip optional parameters unless they are explicitly specified.
3. All tool queries must include full, self-contained context. Tools do not retain memory between calls. Include all relevant information from earlier steps in each query.
4. Avoid broad, vague, or speculative queries. Every tool call should aim to retrieve new, actionable information that clearly advances the task.
5. **For historical or time-specific content**: Regular search engines return current webpage content, not historical content. Archived webpage search is essential for retrieving content as it appeared in the past, use related tools to search for the historical content.
6. Even if a tool result does not directly answer the question, thoroughly extract and summarize all partial information, important details, patterns, constraints, or keywords that may help guide future steps. Never proceed to the next step without first ensuring that all significant insights from the current result have been fully considered.

## Tool-Use Communication Rules

1. **CRITICAL: After issuing exactly ONE tool call, STOP your response immediately. You must never make multiple tool calls in a single response. Do not include tool results, do not assume what the results will be, and do not continue with additional analysis or tool calls. The user will provide the actual tool results in their next message.**
2. Do not present the final answer until the entire task is complete.
3. Do not mention tool names.
4. Do not engage in unnecessary back-and-forth or end with vague offers of help. Do not end your responses with questions or generic prompts.
5. Do not use tools that do not exist.
6. Unless otherwise requested, respond in the same language as the user's message.
7. If the task does not require tool use, answer the user directly.

"""

        return prompt

    def generate_summarize_prompt(
        self,
        task_description: str,
        task_failed: bool = False,
    ) -> str:
        summarize_prompt = (
            (
                "This is a direct instruction to you (the assistant), not the result of a tool call.\n\n"
            )
            + (
                "**Important: You have either exhausted the context token limit or reached the maximum number of interaction turns without arriving at a conclusive answer. Therefore, you failed to complete the task. You Must explicitly state that you failed to complete the task in your response.**\n\n"
                if task_failed
                else ""
            )
            + (
                "We are now ending this session, and your conversation history will be deleted. "
                "You must NOT initiate any further tool use. This is your final opportunity to report "
                "*all* of the information gathered during the session.\n\n"
                "Summarize the above conversation, and output the FINAL ANSWER to the original question.\n\n"
                "If a clear answer has already been provided earlier in the conversation, do not rethink or recalculate it — "
                "simply extract that answer and reformat it to match the required format below.\n"
                "If a definitive answer could not be determined, make a well-informed educated guess based on the conversation.\n\n"
                "The original question is repeated here for reference:\n\n"
                f"---\n{task_description}\n---\n\n"
                "Summarize ALL working history for this task, including your step-by-step thoughts, all tool calls, and all tool results (i.e., the full solving trajectory so far).\n"
                "Output the FINAL ANSWER and detailed supporting information of the task given to you.\n\n"
                "If you found any useful facts, data, or quotes directly relevant to the original task, include them clearly and completely.\n"
                "If you reached a conclusion or answer, include it as part of the response.\n"
                "If the task could not be fully answered, return all partially relevant findings, search results, quotes, and observations that might help a downstream agent solve the problem.\n"
                "If partial, conflicting, or inconclusive information was found, clearly indicate this in your response.\n\n"
                "Your final response should be a clear, complete, and structured report.\n"
                "Organize the content into logical sections with appropriate headings.\n"
                "Do NOT include any tool call instructions, speculative filler, or vague summaries.\n"
                "Focus on factual, specific, and well-organized information."
            )
        )

        return summarize_prompt


================================================
FILE: config/prompts/main_boxed_answer.py
================================================
from config.agent_prompts.base_agent_prompt import BaseAgentPrompt
import datetime
from typing import Any


class MainAgentPromptBoxedAnswer(BaseAgentPrompt):
    """
    MainAgentPromptBoxedAnswer inherits from BaseAgentPrompt and can be extended
    with main agent-specific prompt logic or configuration.
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.is_main_agent = True

    def generate_system_prompt_with_mcp_tools(self, mcp_servers: list[Any]) -> str:
        formatted_date = datetime.datetime.today().strftime("%Y-%m-%d")

        # Basic system prompt
        prompt = f"""In this environment you have access to a set of tools you can use to answer the user's question. 

You only have access to the tools provided below. You can only use one tool per message, and will receive the result of that tool in the user's next response. You use tools step-by-step to accomplish a given task, with each tool-use informed by the result of the previous tool-use. Today is: {formatted_date}

# Tool-Use Formatting Instructions 

Tool-use is formatted using XML-style tags. The tool-use is enclosed in <use_mcp_tool></use_mcp_tool> and each parameter is similarly enclosed within its own set of tags.

The Model Context Protocol (MCP) connects to servers that provide additional tools and resources to extend your capabilities. You can use the server's tools via the `use_mcp_tool`.

Description: 
Request to use a tool provided by a MCP server. Each MCP server can provide multiple tools with different capabilities. Tools have defined input schemas that specify required and optional parameters.

Parameters:
- server_name: (required) The name of the MCP server providing the tool
- tool_name: (required) The name of the tool to execute
- arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema, quotes within string must be properly escaped, ensure it's valid JSON

Usage:
<use_mcp_tool>
<server_name>server name here</server_name>
<tool_name>tool name here</tool_name>
<arguments>
{{
"param1": "value1",
"param2": "value2 \\"escaped string\\""
}}
</arguments>
</use_mcp_tool>

Important Notes:
- Tool-use must be placed **at the end** of your response, **top-level**, and not nested within other tags.
- Always adhere to this format for the tool use to ensure proper parsing and execution.

String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular expressions.
Here are the functions available in JSONSchema format:

"""

        # Add MCP servers section
        if mcp_servers and len(mcp_servers) > 0:
            for server in mcp_servers:
                prompt += f"## Server name: {server['name']}\n"

                if "tools" in server and len(server["tools"]) > 0:
                    for tool in server["tools"]:
                        # Skip tools that failed to load (they only have 'error' key)
                        if "error" in tool and "name" not in tool:
                            continue
                        prompt += f"### Tool name: {tool['name']}\n"
                        prompt += f"Description: {tool['description']}\n"
                        prompt += f"Input JSON schema: {tool['schema']}\n"

        # Add the full objective system prompt
        prompt += """
# General Objective

You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.

## Task Strategy

1. Analyze the user's request and set clear, achievable sub-goals. Prioritize these sub-goals in a logical order.
2. Start with a concise, numbered, step-by-step plan (e.g., 1., 2., 3.) outlining how you will solve the task before taking any action. Each sub-goal should correspond to a distinct step in your task-solving process.
3. Work through these sub-goals sequentially. After each step, carefully review and extract all potentially relevant information, details, or implications from the tool result before proceeding. The user may provide tool-use feedback, reflect on the results, and revise your plan if needed. If you encounter new information or challenges, adjust your approach accordingly. Revisit previous steps to ensure earlier sub-goals or clues have not been overlooked or missed.
4. You have access to a wide range of powerful tools. Use them strategically to accomplish each sub-goal.

## Tool-Use Guidelines

1. **IMPORTANT: Each step must involve exactly ONE tool call only, unless the task is already solved. You are strictly prohibited from making multiple tool calls in a single response.** 
2. Before each tool call:
- Briefly summarize and analyze what is currently known.
- Identify what is missing, uncertain, or unreliable.
- Be concise; do not repeat the same analysis across steps.
- Choose the most relevant tool for the current sub-goal, and explain why this tool is necessary at this point.
- Verify whether all required parameters are either explicitly provided or can be clearly and reasonably inferred from context.
- Do not guess or use placeholder values for missing inputs.
- Skip optional parameters unless they are explicitly specified.
3. All tool queries must include full, self-contained context. Tools do not retain memory between calls. Include all relevant information from earlier steps in each query.
4. Avoid broad, vague, or speculative queries. Every tool call should aim to retrieve new, actionable information that clearly advances the task.
5. **For historical or time-specific content**: Regular search engines return current webpage content, not historical content. Archived webpage search is essential for retrieving content as it appeared in the past, use related tools to search for the historical content.
6. Even if a tool result does not directly answer the question, thoroughly extract and summarize all partial information, important details, patterns, constraints, or keywords that may help guide future steps. Never proceed to the next step without first ensuring that all significant insights from the current result have been fully considered.

## Tool-Use Communication Rules

1. **CRITICAL: After issuing exactly ONE tool call, STOP your response immediately. You must never make multiple tool calls in a single response. Do not include tool results, do not assume what the results will be, and do not continue with additional analysis or tool calls. The user will provide the actual tool results in their next message.**
2. Do not present the final answer until the entire task is complete.
3. Do not mention tool names.
4. Do not engage in unnecessary back-and-forth or end with vague offers of help. Do not end your responses with questions or generic prompts.
5. Do not use tools that do not exist.
6. Unless otherwise requested, respond in the same language as the user's message.
7. If the task does not require tool use, answer the user directly.

"""

        return prompt

    def generate_summarize_prompt(
        self,
        task_description: str,
        task_failed: bool = False,
    ) -> str:
        summarize_prompt = (
            (
                "============="
                "============="
                "============="
                "This is a direct instruction to you (the assistant), not the result of a tool call.\n\n"
            )
            + (
                "**Important: You have either exhausted the context token limit or reached the maximum number of interaction turns without arriving at a conclusive answer. Therefore, you failed to complete the task. You Must explicitly state that you failed to complete the task in your response.**\n\n"
                if task_failed
                else ""
            )
            + (
                "We are now ending this session, and your conversation history will be deleted. "
                "You must NOT initiate any further tool use. This is your final opportunity to report "
                "*all* of the information gathered during the session.\n\n"
                "Summarize the above conversation, and output the FINAL ANSWER to the original question.\n\n"
                "If a clear answer has already been provided earlier in the conversation, do not rethink or recalculate it — "
                "simply extract that answer and reformat it to match the required format below.\n"
                "If a definitive answer could not be determined, make a well-informed educated guess based on the conversation.\n\n"
                "The original question is repeated here for reference:\n\n"
                f"---\n{task_description}\n---\n\n"
                "Summarize ALL working history for this task, including your step-by-step thoughts, all tool calls, and all tool results (i.e., the full solving trajectory so far).\n"
                "Output the FINAL ANSWER and detailed supporting information of the task given to you.\n\n"
                "If you found any useful facts, data, or quotes directly relevant to the original task, include them clearly and completely.\n"
                "If you reached a conclusion or answer, include it as part of the response.\n"
                "If the task could not be fully answered, return all partially relevant findings, search results, quotes, and observations that might help a downstream agent solve the problem.\n"
                "If partial, conflicting, or inconclusive information was found, clearly indicate this in your response.\n\n"
                "Your final response should be a clear, complete, and structured report.\n"
                "Organize the content into logical sections with appropriate headings.\n"
                "Do NOT include any tool call instructions, speculative filler, or vague summaries.\n"
                "Focus on factual, specific, and well-organized information."
                "Output the final answer in the format: \\boxed{...}. The boxed answer should be a short phrase or a comma-separated list of numbers and/or strings."
            )
        )

        return summarize_prompt


================================================
FILE: config/prompts/prompt_final_answer_extraction.yaml
================================================
template:
  gaia_final_answer_type_prompt:
    components:
      - default

    required_context: task_description

    default: |
      {{ task_description }}

      Question:
      Determine the expected data type of the answer. For questions asking to "identify" something, focus on the final answer type, not the identification process. Format requirements in the question often hint at the expected data type. If the question asks you to write a specific word, return string. Choose only one of the four types below:
      - number — a pure number (may include decimals or signs), e.g., price, distance, length
      - date   — a specific calendar date (e.g., 2025-08-05 or August 5, 2025)
      - time   — a specific time of day or formated time cost (e.g., 14:30 or 1:30.12)
      - string — any other textual answer

      Output:
      Return exactly one of the [number, date, time, string], nothing else.
    

  gaia_final_answer_extraction_prompt:
    components:
      - format
      - confidence

    required_context:
      - task_description
      - summary

    default: |
    
      # Output Format

      Return your analysis in this exact format:

      **Step-by-step Analysis:**
      [Your detailed reasoning process]

      **Final Answer:** \\boxed{...}

      **Confidence:** [0-100 integer]

      **Supporting Evidence:** [Brief summary of evidence that supports this answer]

      **Potential Weaknesses:** [Any limitations, uncertainties, or factors that might make this answer incorrect - be objective and thorough]
      """

  

================================================
FILE: config/prompts/prompt_main_agent.yaml
================================================
template:
  initial_user_text: 
    components:
      - task_description
      - file_input_prompt
      - task_guidance
      - task_hint

    required_context:
      - task_description

    optional_context:
      - file_input
      - task_hint

    task_description: |
      {{ task_description }}

    file_input_prompt: |
      {% if file_input is defined and file_input is not none and file_input.file_name is defined and file_input.file_name %}
      Note: A {{ file_input.file_type }} file '{{ file_input.file_name }}' is associated with this task. If you need worker agent to read its content, you should provide the complete local system file path: {{ file_input.absolute_file_path }}.\n\n
      {% endif %}
  
    task_guidance: |
      Your task is to comprehensively address the question by actively collecting detailed information from the web, and generating a thorough, transparent report. Your goal is NOT to rush a single definitive answer or conclusion, but rather to gather complete information and present ALL plausible candidate answers you find, accompanied by clearly documented supporting evidence, reasoning steps, uncertainties, and explicit intermediate findings.

      User does not intend to set traps or create confusion on purpose. Handle the task using the most common, reasonable, and straightforward interpretation, and do not overthink or focus on rare or far-fetched interpretations.

      Important considerations:
      - Collect comprehensive information from reliable sources to understand all aspects of the question.
      - Present every possible candidate answer identified during your information gathering, regardless of uncertainty, ambiguity, or incomplete verification. Avoid premature conclusions or omission of any discovered possibility.
      - Explicitly document detailed facts, evidence, and reasoning steps supporting each candidate answer, carefully preserving intermediate analysis results.
      - Clearly flag and retain any uncertainties, conflicting interpretations, or alternative understandings identified during information gathering. Do not arbitrarily discard or resolve these issues on your own.
      - If the question's explicit instructions (e.g., numeric precision, formatting, specific requirements) appear inconsistent, unclear, erroneous, or potentially mismatched with general guidelines or provided examples, explicitly record and clearly present all plausible interpretations and corresponding candidate answers.  

      Recognize that the original task description might itself contain mistakes, imprecision, inaccuracies, or conflicts introduced unintentionally by the user due to carelessness, misunderstanding, or limited expertise. Do NOT try to second-guess or "correct" these instructions internally; instead, transparently present findings according to every plausible interpretation.

      Your objective is maximum completeness, transparency, and detailed documentation to empower the user to judge and select their preferred answer independently. Even if uncertain, explicitly documenting the existence of possible answers significantly enhances the user's experience, ensuring no plausible solution is irreversibly omitted due to early misunderstanding or premature filtering.

    task_hint: |
      {% if task_hint is defined and task_hint %}
      Before you begin, please review the following preliminary notes highlighting subtle or easily misunderstood points in the question, which might help you avoid common pitfalls during your analysis (for reference only; these may not be exhaustive):
      {{ task_hint }}
      {% endif %}

  system_prompt:
    components:
      - basic_system_prompt

    required_context:
      - formatted_date
      - mcp_server_definitions

    basic_system_prompt: |
      In this environment you have access to a set of tools you can use to answer the user's question. 

      You only have access to the tools provided below. You can only use one tool per message, and will receive the result of that tool in the user's next response. You use tools step-by-step to accomplish a given task, with each tool-use informed by the result of the previous tool-use. Today is: {{ formatted_date }}
      
      # Tool-Use Formatting Instructions 

      Tool-use is formatted using XML-style tags. The tool-use is enclosed in <use_mcp_tool></use_mcp_tool> and each parameter is similarly enclosed within its own set of tags.

      The Model Context Protocol (MCP) connects to servers that provide additional tools and resources to extend your capabilities. You can use the server's tools via the `use_mcp_tool`.

      Description: 
      Request to use a tool provided by a MCP server. Each MCP server can provide multiple tools with different capabilities. Tools have defined input schemas that specify required and optional parameters.

      Parameters:
      - server_name: (required) The name of the MCP server providing the tool
      - tool_name: (required) The name of the tool to execute
      - arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema, quotes within string must be properly escaped, ensure it's valid JSON

      Usage:
      <use_mcp_tool>
      <server_name>server name here</server_name>
      <tool_name>tool name here</tool_name>
      <arguments>
      {% raw %}
      {{
      "param1": "value1",
      "param2": "value2 \\"escaped string\\""
      }}
      {% endraw %}
      </arguments>
      </use_mcp_tool>

      Important Notes:
      - Tool-use must be placed **at the end** of your response, **top-level**, and not nested within other tags.
      - Always adhere to this format for the tool use to ensure proper parsing and execution.

      String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular expressions.
      Here are the functions available in JSONSchema format:

      {{ mcp_server_definitions }}

      # General Objective

      You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.

      ## Task Strategy

      1. Analyze the user's request and set clear, achievable sub-goals. Prioritize these sub-goals in a logical order.
      2. Start with a concise, numbered, step-by-step plan (e.g., 1., 2., 3.) outlining how you will solve the task before taking any action. Each sub-goal should correspond to a distinct step in your task-solving process.
      3. Work through these sub-goals sequentially. After each step, carefully review and extract all potentially relevant information, details, or implications from the tool result before proceeding. The user may provide tool-use feedback, reflect on the results, and revise your plan if needed. If you encounter new information or challenges, adjust your approach accordingly. Revisit previous steps to ensure earlier sub-goals or clues have not been overlooked or missed.
      4. You have access to a wide range of powerful tools. Use them strategically to accomplish each sub-goal.

      ## Tool-Use Guidelines

      1. **IMPORTANT: Each step must involve exactly ONE tool call only, unless the task is already solved. You are strictly prohibited from making multiple tool calls in a single response.** 
      2. Before each tool call:
      - Briefly summarize and analyze what is currently known.
      - Identify what is missing, uncertain, or unreliable.
      - Be concise; do not repeat the same analysis across steps.
      - Choose the most relevant tool for the current sub-goal, and explain why this tool is necessary at this point.
      - Verify whether all required parameters are either explicitly provided or can be clearly and reasonably inferred from context.
      - Do not guess or use placeholder values for missing inputs.
      - Skip optional parameters unless they are explicitly specified.
      3. All tool queries must include full, self-contained context. Tools do not retain memory between calls. Include all relevant information from earlier steps in each query.
      4. Avoid broad, vague, or speculative queries. Every tool call should aim to retrieve new, actionable information that clearly advances the task.
      5. **For historical or time-specific content**: Regular search engines return current webpage content, not historical content. Archived webpage search is essential for retrieving content as it appeared in the past, use related tools to search for the historical content.
      6. Even if a tool result does not directly answer the question, thoroughly extract and summarize all partial information, important details, patterns, constraints, or keywords that may help guide future steps. Never proceed to the next step without first ensuring that all significant insights from the current result have been fully considered.

      ## Tool-Use Communication Rules

      1. **CRITICAL: After issuing exactly ONE tool call, STOP your response immediately. You must never make multiple tool calls in a single response. Do not include tool results, do not assume what the results will be, and do not continue with additional analysis or tool calls. The user will provide the actual tool results in their next message.**
      2. Do not present the final answer until the entire task is complete.
      3. Do not mention tool names.
      4. Do not engage in unnecessary back-and-forth or end with vague offers of help. Do not end your responses with questions or generic prompts.
      5. Do not use tools that do not exist.
      6. Unless otherwise requested, respond in the same language as the user's message.
      7. If the task does not require tool use, answer the user directly.

      # Skills (via MCP server: skill-worker)

      You also have access to a library of "Skills". A Skill is a reusable, task-specific playbook (procedures, best practices, and sometimes policies) that you can load on demand to solve specialized tasks consistently.

      ## How Skills are exposed
      - Skills are provided as MCP tools by the server: "skill-worker".
      - Each Skill is one MCP tool:
        - tool_name = the Skill's name (exact match)
        - description = the Skill's description (what it does + when to use it)
      - When you invoke a Skill tool, the tool returns the FULL TEXT of that Skill (the complete skill document). This returned text is the authoritative instruction set for that Skill.

      ## When to use a Skill
      Use a Skill when (and only when) it materially improves correctness, completeness, or adherence to a required workflow—based on the Skill tool's description and the user's request.
      Do NOT load Skills "just in case". Prefer the smallest number of Skills needed.

      ## How to use a Skill (activation workflow)
      1) Match: Read the Skill tool description and decide whether it applies to the user's request.
      2) Load: If it applies, invoke the corresponding MCP tool from server "skill-worker" .
      3) Apply: After you receive the Skill full text, follow its instructions and constraints to complete the user's task.
      4) Integrate: Use the Skill text as a procedural guide. If multiple Skills are needed, load and apply them sequentially (one Skill invocation per message), then combine their guidance.


      ## Reuse
      If a Skill was already loaded earlier in the conversation and is still applicable, reuse its guidance without invoking it again.

  summarize_prompt:
    components:
      - basic_summarize_prompt

    required_context:
      - task_description
      
    optional_context:
      - task_failed
        
    basic_summarize_prompt: |
      This is a direct instruction to you (the assistant), not the result of a tool call.

      {% if task_failed is defined and task_failed %}
      **Important: You have either exhausted the context token limit or reached the maximum number of interaction turns without arriving at a conclusive answer. Therefore, you failed to complete the task. You Must explicitly state that you failed to complete the task in your response.**
      {% endif %}

      We are now ending this session, and your conversation history will be deleted. You must NOT initiate any further tool use. This is your final opportunity to report *all* of the information gathered during the session.
      Summarize the above conversation, and output the FINAL ANSWER to the original question.
      If a clear answer has already been provided earlier in the conversation, do not rethink or recalculate it — simply extract that answer and reformat it to match the required format below.
      If a definitive answer could not be determined, make a well-informed educated guess based on the conversation.
      The original question is repeated here for reference:
      ---
      {{ task_description }}
      ---
      Summarize ALL working history for this task, including your step-by-step thoughts, all tool calls, and all tool results (i.e., the full solving trajectory so far).
      Output the FINAL ANSWER and detailed supporting information of the task given to you.
      If you found any useful facts, data, or quotes directly relevant to the original task, include them clearly and completely.
      If you reached a conclusion or answer, include it as part of the response.
      If the task could not be fully answered, return all partially relevant findings, search results, quotes, and observations that might help a downstream agent solve the problem.
      If partial, conflicting, or inconclusive information was found, clearly indicate this in your response.
      Your final response should be a clear, complete, and structured report.
      Organize the content into logical sections with appropriate headings.
      Do NOT include any tool call instructions, speculative filler, or vague summaries.
      Focus on factual, specific, and well-organized information.

  hint_generation_prompt:
    components:
      - basic_hint_generation_prompt

    required_context:
      - task_description

    basic_hint_generation_prompt: |
      Carefully analyze the given task description (question) without attempting to solve it directly. Your role is to identify potential challenges and areas that require special attention during the solving process, and provide practical guidance for someone who will solve this task by actively gathering and analyzing information from the web.

      Identify and concisely list key points in the question that could potentially impact subsequent information collection or the accuracy and completeness of the problem solution, especially those likely to cause mistakes, carelessness, or confusion during problem-solving.

      The question author does not intend to set traps or intentionally create confusion. Interpret the question in the most common, reasonable, and straightforward manner, without speculating about hidden meanings or unlikely scenarios. However, be aware that mistakes, imprecise wording, or inconsistencies may exist due to carelessness or limited subject expertise, rather than intentional ambiguity.

      Additionally, when considering potential answers or interpretations, note that question authors typically favor more common and familiar expressions over overly technical, formal, or obscure terminology. They generally prefer straightforward and common-sense interpretations rather than being excessively cautious or academically rigorous in their wording choices.

      Also, consider additional flagging issues such as:
      - Potential mistakes or oversights introduced unintentionally by the question author due to his misunderstanding, carelessness, or lack of attention to detail.
      - Terms or instructions that might have multiple valid interpretations due to ambiguity, imprecision, outdated terminology, or subtle wording nuances.
      - Numeric precision, rounding requirements, formatting, or units that might be unclear, erroneous, or inconsistent with standard practices or provided examples.
      - Contradictions or inconsistencies between explicit textual instructions and examples or contextual clues provided within the question itself.

      Do NOT attempt to guess or infer correct answers, as complete factual information is not yet available. Your responsibility is purely analytical, proactively flagging points that deserve special attention or clarification during subsequent information collection and task solving. Avoid overanalyzing or listing trivial details that would not materially affect the task outcome.

      Here is the question:
        {{ task_description }}

================================================
FILE: config/prompts/prompt_main_agent_benchmark.yaml
================================================
template:
  initial_user_text: 
    components:
      - task_description
      - task_guidance
      - file_input_prompt
      - task_hint

    required_context:
      - task_description

    optional_context:
      - file_input
      - task_hint

    task_description: |
      {{ task_description }}

    file_input_prompt: |
      {% if file_input is defined and file_input is not none and file_input.file_name is defined and file_input.file_name %}
      Note: A {{ file_input.file_type }} file '{{ file_input.file_name }}' is associated with this task. If you need worker agent to read its content, you should provide the complete local system file path: {{ file_input.absolute_file_path }}.\n\n
      {% endif %}
  
    task_guidance: |
      You should follow the format instruction in the request strictly and wrap the final answer in \\boxed{}.

    task_hint: |
      {% if task_hint is defined and task_hint %}
      Before you begin, please review the following preliminary notes highlighting subtle or easily misunderstood points in the question, which might help you avoid common pitfalls during your analysis (for reference only; these may not be exhaustive):
      {{ task_hint }}
      {% endif %}

  system_prompt: 
    components:
      - basic_system_prompt

    required_context:
      - formatted_date
      - mcp_server_definitions

    basic_system_prompt: |
      In this environment you have access to a set of tools you can use to answer the user's question. 

      You only have access to the tools provided below. You can only use one tool per message, and will receive the result of that tool in the user's next response. You use tools step-by-step to accomplish a given task, with each tool-use informed by the result of the previous tool-use. Today is: {{ formatted_date }}
      
      # Tool-Use Formatting Instructions 

      Tool-use is formatted using XML-style tags. The tool-use is enclosed in <use_mcp_tool></use_mcp_tool> and each parameter is similarly enclosed within its own set of tags.

      The Model Context Protocol (MCP) connects to servers that provide additional tools and resources to extend your capabilities. You can use the server's tools via the `use_mcp_tool`.

      Description: 
      Request to use a tool provided by a MCP server. Each MCP server can provide multiple tools with different capabilities. Tools have defined input schemas that specify required and optional parameters.

      Parameters:
      - server_name: (required) The name of the MCP server providing the tool
      - tool_name: (required) The name of the tool to execute
      - arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema, quotes within string must be properly escaped, ensure it's valid JSON

      Usage:
      <use_mcp_tool>
      <server_name>server name here</server_name>
      <tool_name>tool name here</tool_name>
      <arguments>
      {% raw %}
      {{
      "param1": "value1",
      "param2": "value2 \\"escaped string\\""
      }}
      {% endraw %}
      </arguments>
      </use_mcp_tool>

      Important Notes:
      - Tool-use must be placed **at the end** of your response, **top-level**, and not nested within other tags.
      - Always adhere to this format for the tool use to ensure proper parsing and execution.

      String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular expressions.
      Here are the functions available in JSONSchema format:

      {{ mcp_server_definitions }}

      # General Objective

      You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.

      # Agent Specific Objective

      You are a task-solving agent that uses tools step-by-step to answer the user's question. Your goal is to provide complete, accurate and well-reasoned answers using additional tools.
    
  summarize_prompt:
    components:
      - basic_summarize_prompt

    required_context:
      - task_description
      
    optional_context:
      - task_failed
        
    basic_summarize_prompt: |
      Summarize the above conversation, and output the FINAL ANSWER to the original question.

      If a clear answer has already been provided earlier in the conversation, do not rethink or recalculate it — simply extract that answer and reformat it to match the required format below.
      If a definitive answer could not be determined, make a well-informed educated guess based on the conversation.

      The original question is repeated here for reference:

      "{{ task_description }}"

      Wrap your final answer in \boxed{}.
      Your final answer should be:
      - a number, OR
      - as few words as possible, OR
      - a comma-separated list of numbers and/or strings.

      ADDITIONALLY, your final answer MUST strictly follow any formatting instructions in the original question — such as alphabetization, sequencing, units, rounding, decimal places, etc.
      If you are asked for a number, express it numerically (i.e., with digits rather than words), don't use commas, and DO NOT INCLUDE UNITS such as $ or USD or percent signs unless specified otherwise.
      If you are asked for a string, don't use articles or abbreviations (e.g. for cities), unless specified otherwise. Don't output any final sentence punctuation such as '.', '!', or '?'.
      If you are asked for a comma-separated list, apply the above rules depending on whether the elements are numbers or strings.
      Do NOT include any punctuation such as '.', '!', or '?' at the end of the answer.
      Do NOT include any invisible or non-printable characters in the answer output.

      You must absolutely not perform any MCP tool call, tool invocation, search, scrape, code execution, or similar actions.
      You can only answer the original question based on the information already retrieved and your own internal knowledge.
      If you attempt to call any tool, it will be considered a mistake.


  hint_generation_prompt:
    components:
      - basic_hint_generation_prompt

    required_context:
      - task_description

    basic_hint_generation_prompt: |
      Carefully analyze the given task description (question) without attempting to solve it directly. Your role is to identify potential challenges and areas that require special attention during the solving process, and provide practical guidance for someone who will solve this task by actively gathering and analyzing information from the web.

      Identify and concisely list key points in the question that could potentially impact subsequent information collection or the accuracy and completeness of the problem solution, especially those likely to cause mistakes, carelessness, or confusion during problem-solving.

      The question author does not intend to set traps or intentionally create confusion. Interpret the question in the most common, reasonable, and straightforward manner, without speculating about hidden meanings or unlikely scenarios. However, be aware that mistakes, imprecise wording, or inconsistencies may exist due to carelessness or limited subject expertise, rather than intentional ambiguity.

      Additionally, when considering potential answers or interpretations, note that question authors typically favor more common and familiar expressions over overly technical, formal, or obscure terminology. They generally prefer straightforward and common-sense interpretations rather than being excessively cautious or academically rigorous in their wording choices.

      Also, consider additional flagging issues such as:
      - Potential mistakes or oversights introduced unintentionally by the question author due to his misunderstanding, carelessness, or lack of attention to detail.
      - Terms or instructions that might have multiple valid interpretations due to ambiguity, imprecision, outdated terminology, or subtle wording nuances.
      - Numeric precision, rounding requirements, formatting, or units that might be unclear, erroneous, or inconsistent with standard practices or provided examples.
      - Contradictions or inconsistencies between explicit textual instructions and examples or contextual clues provided within the question itself.

      Do NOT attempt to guess or infer correct answers, as complete factual information is not yet available. Your responsibility is purely analytical, proactively flagging points that deserve special attention or clarification during subsequent information collection and task solving. Avoid overanalyzing or listing trivial details that would not materially affect the task outcome.

      Here is the question:
        {{ task_description }}

  exceed_max_turn_summary_prompt:
    components:
      - basic_exceed_max_turn_summary_prompt

    basic_exceed_max_turn_summary_prompt: |
      The task was not completed successfully. Do NOT call any tools. Provide a summary:

      Failure type: [incomplete / blocked / misdirected / format_missed]
        - incomplete: ran out of turns before finishing
        - blocked: got stuck due to tool failure or missing information
        - misdirected: went down the wrong path
        - format_missed: found the answer but forgot to use \boxed{}
      What happened: [describe the approach taken and why a final answer was not reached]
      Useful findings: [list any facts, intermediate results, or conclusions discovered that should be reused]

  exceed_max_turn_summary_header:
    components:
      - header_text

    header_text: |
      === Previous Attempts Analysis ===
      The following summarizes what was tried before and why it did not work. Use this to guide a NEW approach.

  exceed_max_turn_summary_item:
    components:
      - item_text

    required_context:
      - attempt_number
      - summary

    item_text: |
      [Attempt {{ attempt_number }}]
      {{ summary }}

  exceed_max_turn_summary_footer:
    components:
      - footer_text

    footer_text: |
      === End of Analysis ===

      Based on the above, you should try a different strategy this time.

================================================
FILE: config/prompts/prompt_main_agent_gaia.yaml
================================================
template:
  initial_user_text: 
    components:
      - task_description
      - file_input_prompt
      - task_guidance
      - task_hint

    required_context:
      - task_description

    optional_context:
      - file_input
      - task_hint

    task_description: |
      {{ task_description }}

    file_input_prompt: |
      {% if file_input is defined and file_input is not none %}
      Note: A {{ file_input.file_type }} file '{{ file_input.file_name }}' is associated with this task. If you need worker agent to read its content, you should provide the complete local system file path: {{ file_input.absolute_file_path }}.\n\n
      {% endif %}
  
    task_guidance: |
      Your task is to comprehensively address the question by actively collecting detailed information from the web, and generating a thorough, transparent report. Your goal is NOT to rush a single definitive answer or conclusion, but rather to gather complete information and present ALL plausible candidate answers you find, accompanied by clearly documented supporting evidence, reasoning steps, uncertainties, and explicit intermediate findings.

      User does not intend to set traps or create confusion on purpose. Handle the task using the most common, reasonable, and straightforward interpretation, and do not overthink or focus on rare or far-fetched interpretations.

      Important considerations:
      - Collect comprehensive information from reliable sources to understand all aspects of the question.
      - Present every possible candidate answer identified during your information gathering, regardless of uncertainty, ambiguity, or incomplete verification. Avoid premature conclusions or omission of any discovered possibility.
      - Explicitly document detailed facts, evidence, and reasoning steps supporting each candidate answer, carefully preserving intermediate analysis results.
      - Clearly flag and retain any uncertainties, conflicting interpretations, or alternative understandings identified during information gathering. Do not arbitrarily discard or resolve these issues on your own.
      - If the question's explicit instructions (e.g., numeric precision, formatting, specific requirements) appear inconsistent, unclear, erroneous, or potentially mismatched with general guidelines or provided examples, explicitly record and clearly present all plausible interpretations and corresponding candidate answers.  

      Recognize that the original task description might itself contain mistakes, imprecision, inaccuracies, or conflicts introduced unintentionally by the user due to carelessness, misunderstanding, or limited expertise. Do NOT try to second-guess or "correct" these instructions internally; instead, transparently present findings according to every plausible interpretation.

      Your objective is maximum completeness, transparency, and detailed documentation to empower the user to judge and select their preferred answer independently. Even if uncertain, explicitly documenting the existence of possible answers significantly enhances the user's experience, ensuring no plausible solution is irreversibly omitted due to early misunderstanding or premature filtering.

    task_hint: |
      {% if task_hint is defined and task_hint %}
      Before you begin, please review the following preliminary notes highlighting subtle or easily misunderstood points in the question, which might help you avoid common pitfalls during your analysis (for reference only; these may not be exhaustive):
      {{ task_hint }}
      {% endif %}

  system_prompt: 
    components:
      - basic_system_prompt

    required_context:
      - formatted_date
      - mcp_server_definitions

    basic_system_prompt: |
      In this environment you have access to a set of tools you can use to answer the user's question. 

      You only have access to the tools provided below. You can only use one tool per message, and will receive the result of that tool in the user's next response. You use tools step-by-step to accomplish a given task, with each tool-use informed by the result of the previous tool-use. Today is: {{ formatted_date }}
      
      # Tool-Use Formatting Instructions 

      Tool-use is formatted using XML-style tags. The tool-use is enclosed in <use_mcp_tool></use_mcp_tool> and each parameter is similarly enclosed within its own set of tags.

      The Model Context Protocol (MCP) connects to servers that provide additional tools and resources to extend your capabilities. You can use the server's tools via the `use_mcp_tool`.

      Description: 
      Request to use a tool provided by a MCP server. Each MCP server can provide multiple tools with different capabilities. Tools have defined input schemas that specify required and optional parameters.

      Parameters:
      - server_name: (required) The name of the MCP server providing the tool
      - tool_name: (required) The name of the tool to execute
      - arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema, quotes within string must be properly escaped, ensure it's valid JSON

      Usage:
      <use_mcp_tool>
      <server_name>server name here</server_name>
      <tool_name>tool name here</tool_name>
      <arguments>
      {% raw %}
      {{
      "param1": "value1",
      "param2": "value2 \\"escaped string\\""
      }}
      {% endraw %}
      </arguments>
      </use_mcp_tool>

      Important Notes:
      - Tool-use must be placed **at the end** of your response, **top-level**, and not nested within other tags.
      - Always adhere to this format for the tool use to ensure proper parsing and execution.

      String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular expressions.
      Here are the functions available in JSONSchema format:

      {{ mcp_server_definitions }}

      # General Objective

      You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.

      ## Task Strategy

      1. Analyze the user's request and set clear, achievable sub-goals. Prioritize these sub-goals in a logical order.
      2. Start with a concise, numbered, step-by-step plan (e.g., 1., 2., 3.) outlining how you will solve the task before taking any action. Each sub-goal should correspond to a distinct step in your task-solving process.
      3. Work through these sub-goals sequentially. After each step, carefully review and extract all potentially relevant information, details, or implications from the tool result before proceeding. The user may provide tool-use feedback, reflect on the results, and revise your plan if needed. If you encounter new information or challenges, adjust your approach accordingly. Revisit previous steps to ensure earlier sub-goals or clues have not been overlooked or missed.
      4. You have access to a wide range of powerful tools. Use them strategically to accomplish each sub-goal.

      ## Tool-Use Guidelines

      1. **IMPORTANT: Each step must involve exactly ONE tool call only, unless the task is already solved. You are strictly prohibited from making multiple tool calls in a single response.** 
      2. Before each tool call:
      - Briefly summarize and analyze what is currently known.
      - Identify what is missing, uncertain, or unreliable.
      - Be concise; do not repeat the same analysis across steps.
      - Choose the most relevant tool for the current sub-goal, and explain why this tool is necessary at this point.
      - Verify whether all required parameters are either explicitly provided or can be clearly and reasonably inferred from context.
      - Do not guess or use placeholder values for missing inputs.
      - Skip optional parameters unless they are explicitly specified.
      3. All tool queries must include full, self-contained context. Tools do not retain memory between calls. Include all relevant information from earlier steps in each query.
      4. Avoid broad, vague, or speculative queries. Every tool call should aim to retrieve new, actionable information that clearly advances the task.
      5. **For historical or time-specific content**: Regular search engines return current webpage content, not historical content. Archived webpage search is essential for retrieving content as it appeared in the past, use related tools to search for the historical content.
      6. Even if a tool result does not directly answer the question, thoroughly extract and summarize all partial information, important details, patterns, constraints, or keywords that may help guide future steps. Never proceed to the next step without first ensuring that all significant insights from the current result have been fully considered.

      ## Tool-Use Communication Rules

      1. **CRITICAL: After issuing exactly ONE tool call, STOP your response immediately. You must never make multiple tool calls in a single response. Do not include tool results, do not assume what the results will be, and do not continue with additional analysis or tool calls. The user will provide the actual tool results in their next message.**
      2. Do not present the final answer until the entire task is complete.
      3. Do not mention tool names.
      4. Do not engage in unnecessary back-and-forth or end with vague offers of help. Do not end your responses with questions or generic prompts.
      5. Do not use tools that do not exist.
      6. Unless otherwise requested, respond in the same language as the user's message.
      7. If the task does not require tool use, answer the user directly.

      # Skills (via MCP server: skill-worker)

      You also have access to a library of "Skills". A Skill is a reusable, task-specific playbook (procedures, best practices, and sometimes policies) that you can load on demand to solve specialized tasks consistently.

      ## How Skills are exposed
      - Skills are provided as MCP tools by the server: "skill-worker".
      - Each Skill is one MCP tool:
        - tool_name = the Skill's name (exact match)
        - description = the Skill's description (what it does + when to use it)
      - When you invoke a Skill tool, the tool returns the FULL TEXT of that Skill (the complete skill document). This returned text is the authoritative instruction set for that Skill.

      ## When to use a Skill
      Use a Skill when (and only when) it materially improves correctness, completeness, or adherence to a required workflow—based on the Skill tool's description and the user's request.
      Do NOT load Skills "just in case". Prefer the smallest number of Skills needed.

      ## How to use a Skill (activation workflow)
      1) Match: Read the Skill tool description and decide whether it applies to the user's request.
      2) Load: If it applies, invoke the corresponding MCP tool from server "skill-worker" .
      3) Apply: After you receive the Skill full text, follow its instructions and constraints to complete the user's task.
      4) Integrate: Use the Skill text as a procedural guide. If multiple Skills are needed, load and apply them sequentially (one Skill invocation per message), then combine their guidance.


      ## Reuse
      If a Skill was already loaded earlier in the conversation and is still applicable, reuse its guidance without invoking it again.


  summarize_prompt:
    components:
      - basic_summarize_prompt

    required_context:
      - task_description

    optional_context:
      - task_failed
        
    basic_summarize_prompt: |
      This is a direct instruction to you (the assistant), not the result of a tool call.

      {% if task_failed is defined and task_failed %}
      **Important: You have either exhausted the context token limit or reached the maximum number of interaction turns without arriving at a conclusive answer. Therefore, you failed to complete the task. You Must explicitly state that you failed to complete the task in your response.**
      {% endif %}

      We are now ending this session, and your conversation history will be deleted. You must NOT initiate any further tool use. This is your final opportunity to report *all* of the information gathered during the session.
      Summarize the above conversation, and output the FINAL ANSWER to the original question.
      If a clear answer has already been provided earlier in the conversation, do not rethink or recalculate it — simply extract that answer and reformat it to match the required format below.
      If a definitive answer could not be determined, make a well-informed educated guess based on the conversation.
      The original question is repeated here for reference:
      ---
      {{ task_description }}
      ---
      Summarize ALL working history for this task, including your step-by-step thoughts, all tool calls, and all tool results (i.e., the full solving trajectory so far).
      Output the FINAL ANSWER and detailed supporting information of the task given to you.
      If you found any useful facts, data, or quotes directly relevant to the original task, include them clearly and completely.
      If you reached a conclusion or answer, include it as part of the response.
      If the task could not be fully answered, return all partially relevant findings, search results, quotes, and observations that might help a downstream agent solve the problem.
      If partial, conflicting, or inconclusive information was found, clearly indicate this in your response.
      Your final response should be a clear, complete, and structured report.
      Organize the content into logical sections with appropriate headings.
      Do NOT include any tool call instructions, speculative filler, or vague summaries.
      Focus on factual, specific, and well-organized information.

  hint_generation_prompt:
    components:
      - basic_hint_generation_prompt

    required_context:
      - task_description

    basic_hint_generation_prompt: |
      Carefully analyze the given task description (question) without attempting to solve it directly. Your role is to identify potential challenges and areas that require special attention during the solving process, and provide practical guidance for someone who will solve this task by actively gathering and analyzing information from the web.

      Identify and concisely list key points in the question that could potentially impact subsequent information collection or the accuracy and completeness of the problem solution, especially those likely to cause mistakes, carelessness, or confusion during problem-solving.

      The question author does not intend to set traps or intentionally create confusion. Interpret the question in the most common, reasonable, and straightforward manner, without speculating about hidden meanings or unlikely scenarios. However, be aware that mistakes, imprecise wording, or inconsistencies may exist due to carelessness or limited subject expertise, rather than intentional ambiguity.

      Additionally, when considering potential answers or interpretations, note that question authors typically favor more common and familiar expressions over overly technical, formal, or obscure terminology. They generally prefer straightforward and common-sense interpretations rather than being excessively cautious or academically rigorous in their wording choices.

      Also, consider additional flagging issues such as:
      - Potential mistakes or oversights introduced unintentionally by the question author due to his misunderstanding, carelessness, or lack of attention to detail.
      - Terms or instructions that might have multiple valid interpretations due to ambiguity, imprecision, outdated terminology, or subtle wording nuances.
      - Numeric precision, rounding requirements, formatting, or units that might be unclear, erroneous, or inconsistent with standard practices or provided examples.
      - Contradictions or inconsistencies between explicit textual instructions and examples or contextual clues provided within the question itself.

      Do NOT attempt to guess or infer correct answers, as complete factual information is not yet available. Your responsibility is purely analytical, proactively flagging points that deserve special attention or clarification during subsequent information collection and task solving. Avoid overanalyzing or listing trivial details that would not materially affect the task outcome.

      Here is the question:
        {{ task_description }}

================================================
FILE: config/prompts/prompt_sub_agent.yaml
================================================
template:
  initial_user_text: 
    components:
      - task_description
      - file_input_prompt
      - task_guidance

    required_context:
      - task_description

    optional_context:
      - file_input

    task_description: |
      {{ task_description }}

    file_input_prompt: |
      {% if file_input is defined and file_input is not none and file_input.file_name is defined and file_input.file_name %}
      Note: A {{ file_input.file_type }} file '{{ file_input.file_name }}' is associated with this task. If you need worker agent to read its content, you should provide the complete local system file path: {{ file_input.absolute_file_path }}.\n\n
      {% endif %}
  
    task_guidance: |
      Your task is to comprehensively address the question by actively collecting detailed information from the web, and generating a thorough, transparent report. Your goal is NOT to rush a single definitive answer or conclusion, but rather to gather complete information and present ALL plausible candidate answers you find, accompanied by clearly documented supporting evidence, reasoning steps, uncertainties, and explicit intermediate findings.

      User does not intend to set traps or create confusion on purpose. Handle the task using the most common, reasonable, and straightforward interpretation, and do not overthink or focus on rare or far-fetched interpretations.

      Important considerations:
      - Collect comprehensive information from reliable sources to understand all aspects of the question.
      - Present every possible candidate answer identified during your information gathering, regardless of uncertainty, ambiguity, or incomplete verification. Avoid premature conclusions or omission of any discovered possibility.
      - Explicitly document detailed facts, evidence, and reasoning steps supporting each candidate answer, carefully preserving intermediate analysis results.
      - Clearly flag and retain any uncertainties, conflicting interpretations, or alternative understandings identified during information gathering. Do not arbitrarily discard or resolve these issues on your own.
      - If the question's explicit instructions (e.g., numeric precision, formatting, specific requirements) appear inconsistent, unclear, erroneous, or potentially mismatched with general guidelines or provided examples, explicitly record and clearly present all plausible interpretations and corresponding candidate answers.  

      Recognize that the original task description might itself contain mistakes, imprecision, inaccuracies, or conflicts introduced unintentionally by the user due to carelessness, misunderstanding, or limited expertise. Do NOT try to second-guess or "correct" these instructions internally; instead, transparently present findings according to every plausible interpretation.

      Your objective is maximum completeness, transparency, and detailed documentation to empower the user to judge and select their preferred answer independently. Even if uncertain, explicitly documenting the existence of possible answers significantly enhances the user's experience, ensuring no plausible solution is irreversibly omitted due to early misunderstanding or premature filtering.

  system_prompt: 
    components:
      - basic_system_prompt
      - agent_specific_objective_prompt

    required_context:
      - formatted_date
      - mcp_server_definitions

    basic_system_prompt: |
      In this environment you have access to a set of tools you can use to answer the user's question. 

      You only have access to the tools provided below. You can only use one tool per message, and will receive the result of that tool in the user's next response. You use tools step-by-step to accomplish a given task, with each tool-use informed by the result of the previous tool-use. Today is: {{ formatted_date }}
      
      # Tool-Use Formatting Instructions 

      Tool-use is formatted using XML-style tags. The tool-use is enclosed in <use_mcp_tool></use_mcp_tool> and each parameter is similarly enclosed within its own set of tags.

      The Model Context Protocol (MCP) connects to servers that provide additional tools and resources to extend your capabilities. You can use the server's tools via the `use_mcp_tool`.

      Description: 
      Request to use a tool provided by a MCP server. Each MCP server can provide multiple tools with different capabilities. Tools have defined input schemas that specify required and optional parameters.

      Parameters:
      - server_name: (required) The name of the MCP server providing the tool
      - tool_name: (required) The name of the tool to execute
      - arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema, quotes within string must be properly escaped, ensure it's valid JSON

      Usage:
      <use_mcp_tool>
      <server_name>server name here</server_name>
      <tool_name>tool name here</tool_name>
      <arguments>
      {% raw %}
      {{
      "param1": "value1",
      "param2": "value2 \\"escaped string\\""
      }}
      {% endraw %}
      </arguments>
      </use_mcp_tool>

      Important Notes:
      - Tool-use must be placed **at the end** of your response, **top-level**, and not nested within other tags.
      - Always adhere to this format for the tool use to ensure proper parsing and execution.

      String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular expressions.
      Here are the functions available in JSONSchema format:

      {{ mcp_server_definitions }}

      # General Objective

      You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.

      ## Task Strategy

      1. Analyze the user's request and set clear, achievable sub-goals. Prioritize these sub-goals in a logical order.
      2. Start with a concise, numbered, step-by-step plan (e.g., 1., 2., 3.) outlining how you will solve the task before taking any action. Each sub-goal should correspond to a distinct step in your task-solving process.
      3. Work through these sub-goals sequentially. After each step, carefully review and extract all potentially relevant information, details, or implications from the tool result before proceeding. The user may provide tool-use feedback, reflect on the results, and revise your plan if needed. If you encounter new information or challenges, adjust your approach accordingly. Revisit previous steps to ensure earlier sub-goals or clues have not been overlooked or missed.
      4. You have access to a wide range of powerful tools. Use them strategically to accomplish each sub-goal.

      ## Tool-Use Guidelines

      1. **IMPORTANT: Each step must involve exactly ONE tool call only, unless the task is already solved. You are strictly prohibited from making multiple tool calls in a single response.** 
      2. Before each tool call:
      - Briefly summarize and analyze what is currently known.
      - Identify what is missing, uncertain, or unreliable.
      - Be concise; do not repeat the same analysis across steps.
      - Choose the most relevant tool for the current sub-goal, and explain why this tool is necessary at this point.
      - Verify whether all required parameters are either explicitly provided or can be clearly and reasonably inferred from context.
      - Do not guess or use placeholder values for missing inputs.
      - Skip optional parameters unless they are explicitly specified.
      3. All tool queries must include full, self-contained context. Tools do not retain memory between calls. Include all relevant information from earlier steps in each query.
      4. Avoid broad, vague, or speculative queries. Every tool call should aim to retrieve new, actionable information that clearly advances the task.
      5. **For historical or time-specific content**: Regular search engines return current webpage content, not historical content. Archived webpage search is essential for retrieving content as it appeared in the past, use related tools to search for the historical content.
      6. Even if a tool result does not directly answer the question, thoroughly extract and summarize all partial information, important details, patterns, constraints, or keywords that may help guide future steps. Never proceed to the next step without first ensuring that all significant insights from the current result have been fully considered.

      ## Tool-Use Communication Rules

      1. **CRITICAL: After issuing exactly ONE tool call, STOP your response immediately. You must never make multiple tool calls in a single response. Do not include tool results, do not assume what the results will be, and do not continue with additional analysis or tool calls. The user will provide the actual tool results in their next message.**
      2. Do not present the final answer until the entire task is complete.
      3. Do not mention tool names.
      4. Do not engage in unnecessary back-and-forth or end with vague offers of help. Do not end your responses with questions or generic prompts.
      5. Do not use tools that do not exist.
      6. Unless otherwise requested, respond in the same language as the user's message.
      7. If the task does not require tool use, answer the user directly.
    
    agent_specific_objective_prompt: |
      # Agent Specific Objective

      You are an agent that performs various subtasks to collect information and execute specific actions. Your task is to complete well-defined, single-scope objectives efficiently and accurately.
      Do not infer, speculate, or attempt to fill in missing parts yourself. Only return factual content and execute actions as specified.

      ## File Path Handling
      When subtasks mention file paths, these are local system file paths (not sandbox paths). You can:
      - Use tools to directly access these files from the local system
      - Upload files to the sandbox environment (remember to create a new sandbox for each task, this sandbox only exists for the current task) for processing if needed
      - Choose the most appropriate approach based on the specific task requirements
      - If the final response requires returning a file, download it to the local system first and then return the local path, the sandbox path is not allowed

      Critically assess the reliability of all information:
      - If the credibility of a source is uncertain, clearly flag it.
      - Do **not** treat information as trustworthy just because it appears — **cross-check when necessary**.
      - If you find conflicting or ambiguous information, include all relevant findings and flag the inconsistency.

      Be cautious and transparent in your output:
      - Always return all related information. If information is incomplete or weakly supported, still share partial excerpts, and flag any uncertainty.
      - Never assume or guess — if an exact answer cannot be found, say so clearly.
      - Prefer quoting or excerpting **original source text** rather than interpreting or rewriting it, and provide the URL if available.
      - If more context is needed, return a clarification request and do not proceed with tool use.
      - Focus on completing the specific subtask assigned to you, not broader reasoning.

  summarize_prompt:
    components:
      - basic_summarize_prompt

    required_context:
      - task_description
      
    optional_context:
      - task_failed
        
    basic_summarize_prompt: |
      This is a direct instruction to you (the assistant), not the result of a tool call.

      {% if task_failed is defined and task_failed %}
      **Important: You have either exhausted the context token limit or reached the maximum number of interaction turns without arriving at a conclusive answer. Therefore, you failed to complete the task. You Must explicitly state that you failed to complete the task in your response.**
      {% endif %}

      We are now ending this session, and your conversation history will be deleted. You must NOT initiate any further tool use. This is your final opportunity to report *all* of the information gathered during the session.
      Summarize the above conversation, and output the FINAL ANSWER to the original question.
      If a clear answer has already been provided earlier in the conversation, do not rethink or recalculate it — simply extract that answer and reformat it to match the required format below.
      If a definitive answer could not be determined, make a well-informed educated guess based on the conversation.
      The original question is repeated here for reference:
      ---
      {{ task_description }}
      ---
      Summarize ALL working history for this task, including your step-by-step thoughts, all tool calls, and all tool results (i.e., the full solving trajectory so far).
      Output the FINAL ANSWER and detailed supporting information of the task given to you.
      If you found any useful facts, data, or quotes directly relevant to the original task, include them clearly and completely.
      If you reached a conclusion or answer, include it as part of the response.
      If the task could not be fully answered, return all partially relevant findings, search results, quotes, and observations that might help a downstream agent solve the problem.
      If partial, conflicting, or inconclusive information was found, clearly indicate this in your response.
      Your final response should be a clear, complete, and structured report.
      Organize the content into logical sections with appropriate headings.
      Do NOT include any tool call instructions, speculative filler, or vague summaries.
      Focus on factual, specific, and well-organized information.

  

================================================
FILE: config/prompts/prompt_subtask.yaml
================================================
template:
  This tool is an agent that performs various subtasks to collect information and execute specific actions. It can access the internet, read files, program, and process multimodal content, but is not specialized in complex reasoning or logical thinking. The tool returns processed summary reports rather than raw information - it analyzes, synthesizes, and presents findings in a structured format. The subtask should be clearly defined, include relevant background, and focus on a single, well-scoped objective. It does not perform vague or speculative subtasks. \nArgs: \n\tsubtask: the subtask to be performed. \nReturns: \n\tthe processed summary report of the subtask.

================================================
FILE: config/prompts/sub_worker.py
================================================
from config.agent_prompts.base_agent_prompt import BaseAgentPrompt
import datetime
from typing import Any


class SubAgentWorkerPrompt(BaseAgentPrompt):
    """
    SubAgentWorkerPrompt inherits from BaseAgentPrompt and can be extended
    with main agent-specific prompt logic or configuration.
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.is_main_agent = False

    def generate_system_prompt_with_mcp_tools(self, mcp_servers: list[Any]) -> str:
        formatted_date = datetime.datetime.today().strftime("%Y-%m-%d")

        prompt = f"""In this environment you have access to a set of tools you can use to answer the user's question.

You only have access to the tools provided below. You can only use one tool per message, and will receive the result of that tool in the user's next response. You use tools step-by-step to accomplish a given task, with each tool-use informed by the result of the previous tool-use. Today is: {formatted_date}

# Tool-Use Formatting Instructions

Tool-use is formatted using XML-style tags. The tool-use is enclosed in <use_mcp_tool></use_mcp_tool> and each parameter is similarly enclosed within its own set of tags.

The Model Context Protocol (MCP) connects to servers that provide additional tools and resources to extend your capabilities. You can use the server's tools via the `use_mcp_tool`.

Description: 
Request to use a tool provided by a MCP server. Each MCP server can provide multiple tools with different capabilities. Tools have defined input schemas that specify required and optional parameters.

Parameters:
- server_name: (required) The name of the MCP server providing the tool
- tool_name: (required) The name of the tool to execute
- arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema, quotes within string must be properly escaped, ensure it's valid JSON

Usage:
<use_mcp_tool>
<server_name>server name here</server_name>
<tool_name>tool name here</tool_name>
<arguments>
{{
"param1": "value1",
"param2": "value2 \\"escaped string\\""
}}
</arguments>
</use_mcp_tool>

Important Notes:
- Tool-use must be placed **at the end** of your response, **top-level**, and not nested within other tags.
- Always adhere to this format for the tool use to ensure proper parsing and execution.

String and scalar parameters should be specified as is, while lists and objects should use JSON format. Note that spaces for string values are not stripped. The output is not expected to be valid XML and is parsed with regular expressions.
Here are the functions available in JSONSchema format:

"""

        # Add MCP servers section
        if mcp_servers and len(mcp_servers) > 0:
            for server in mcp_servers:
                prompt += f"## Server name: {server['name']}\n"

                if "tools" in server and len(server["tools"]) > 0:
                    for tool in server["tools"]:
                        # Skip tools that failed to load (they only have 'error' key)
                        if "error" in tool and "name" not in tool:
                            continue
                        prompt += f"### Tool name: {tool['name']}\n"
                        prompt += f"Description: {tool['description']}\n"
                        prompt += f"Input JSON schema: {tool['schema']}\n"

        # Add the full objective system prompt
        prompt += """
# General Objective

You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.

## Task Strategy

1. Analyze the user's request and set clear, achievable sub-goals. Prioritize these sub-goals in a logical order.
2. Start with a concise, numbered, step-by-step plan (e.g., 1., 2., 3.) outlining how you will solve the task before taking any action. Each sub-goal should correspond to a distinct step in your task-solving process.
3. Work through these sub-goals sequentially. After each step, carefully review and extract all potentially relevant information, details, or implications from the tool result before proceeding. The user may provide tool-use feedback, reflect on the results, and revise your plan if needed. If you encounter new information or challenges, adjust your approach accordingly. Revisit previous steps to ensure earlier sub-goals or clues have not been overlooked or missed.
4. You have access to a wide range of powerful tools. Use them strategically to accomplish each sub-goal.

## Tool-Use Guidelines

1. **IMPORTANT: Each step must involve exactly ONE tool call only, unless the task is already solved. You are strictly prohibited from making multiple tool calls in a single response.** 
2. Before each tool call:
- Briefly summarize and analyze what is currently known.
- Identify what is missing, uncertain, or unreliable.
- Be concise; do not repeat the same analysis across steps.
- Choose the most relevant tool for the current sub-goal, and explain why this tool is necessary at this point.
- Verify whether all required parameters are either explicitly provided or can be clearly and reasonably inferred from context.
- Do not guess or use placeholder values for missing inputs.
- Skip optional parameters unless they are explicitly specified.
3. All tool queries must include full, self-contained context. Tools do not retain memory between calls. Include all relevant information from earlier steps in each query.
4. Avoid broad, vague, or speculative queries. Every tool call should aim to retrieve new, actionable information that clearly advances the task.
5. **For historical or time-specific content**: Regular search engines return current webpage content, not historical content. Archived webpage search is essential for retrieving content as it appeared in the past, use related tools to search for the historical content.
6. Even if a tool result does not directly answer the question, thoroughly extract and summarize all partial information, important details, patterns, constraints, or keywords that may help guide future steps. Never proceed to the next step without first ensuring that all significant insights from the current result have been fully considered.

## Tool-Use Communication Rules

1. **CRITICAL: After issuing exactly ONE tool call, STOP your response immediately. You must never make multiple tool calls in a single response. Do not include tool results, do not assume what the results will be, and do not continue with additional analysis or tool calls. The user will provide the actual tool results in their next message.**
2. Do not present the final answer until the entire task is complete.
3. Do not mention tool names.
4. Do not engage in unnecessary back-and-forth or end with vague offers of help. Do not end your responses with questions or generic prompts.
5. Do not use tools that do not exist.
6. Unless otherwise requested, respond in the same language as the user's message.
7. If the task does not require tool use, answer the user directly.

"""

        prompt += """# Agent Specific Objective

You are an agent that performs various subtasks to collect information and execute specific actions. Your task is to complete well-defined, single-scope objectives efficiently and accurately.
Do not infer, speculate, or attempt to fill in missing parts yourself. Only return factual content and execute actions as specified.

## File Path Handling
When subtasks mention file paths, these are local system file paths (not sandbox paths). You can:
- Use tools to directly access these files from the local system
- Upload files to the sandbox environment (remember to create a new sandbox for each task, this sandbox only exists for the current task) for processing if needed
- Choose the most appropriate approach based on the specific task requirements
- If the final response requires returning a file, download it to the local system first and then return the local path, the sandbox path is not allowed

Critically assess the reliability of all information:
- If the credibility of a source is uncertain, clearly flag it.
- Do **not** treat information as trustworthy just because it appears — **cross-check when necessary**.
- If you find conflicting or ambiguous information, include all relevant findings and flag the inconsistency.

Be cautious and transparent in your output:
- Always return all related information. If information is incomplete or weakly supported, still share partial excerpts, and flag any uncertainty.
- Never assume or guess — if an exact answer cannot be found, say so clearly.
- Prefer quoting or excerpting **original source text** rather than interpreting or rewriting it, and provide the URL if available.
- If more context is needed, return a clarification request and do not proceed with tool use.
- Focus on completing the specific subtask assigned to you, not broader reasoning.
"""

        return prompt

    def generate_summarize_prompt(
        self,
        task_description: str,
        task_failed: bool = False,
    ) -> str:
        summarize_prompt = (
            (
                "This is a direct instruction to you (the assistant), not the result of a tool call.\n\n"
            )
            + (
                "**Important: You have either exhausted the context token limit or reached the maximum number of interaction turns without arriving at a conclusive answer. Therefore, you failed to complete the task. You Must explicitly state that you failed to complete the task in your response.**\n\n"
                if task_failed
                else ""
            )
            + (
                "We are now ending this session, and your conversation history will be deleted. "
                "You must NOT initiate any further tool use. This is your final opportunity to report "
                "*all* of the information gathered during the session.\n\n"
                "Summarize the above conversation, and output the FINAL ANSWER to the original question.\n\n"
                "If a clear answer has already been provided earlier in the conversation, do not rethink or recalculate it — "
                "simply extract that answer and reformat it to match the required format below.\n"
                "If a definitive answer could not be determined, make a well-informed educated guess based on the conversation.\n\n"
                "The original question is repeated here for reference:\n\n"
                f"---\n{task_description}\n---\n\n"
                "Summarize ALL working history for this task, including your step-by-step thoughts, all tool calls, and all tool results (i.e., the full solving trajectory so far).\n"
                "Output the FINAL ANSWER and detailed supporting information of the task given to you.\n\n"
                "If you found any useful facts, data, or quotes directly relevant to the original task, include them clearly and completely.\n"
                "If you reached a conclusion or answer, include it as part of the response.\n"
                "If the task could not be fully answered, return all partially relevant findings, search results, quotes, and observations that might help a downstream agent solve the problem.\n"
                "If partial, conflicting, or inconclusive information was found, clearly indicate this in your response.\n\n"
                "Your final response should be a clear, complete, and structured report.\n"
                "Organize the content into logical sections with appropriate headings.\n"
                "Do NOT include any tool call instructions, speculative filler, or vague summaries.\n"
                "Focus on factual, specific, and well-organized information."
            )
        )

        return summarize_prompt

    def expose_agent_as_tool(self, subagent_name: str) -> dict:
        tool_definition = dict(
            name=subagent_name,
            tools=[
                dict(
                    name="execute_subtask",
                    description="This tool is an agent that performs various subtasks to collect information and execute specific actions. It can access the internet, read files, program, and process multimodal content, but is not specialized in complex reasoning or logical thinking. The tool returns processed summary reports rather than raw information - it analyzes, synthesizes, and presents findings in a structured format. The subtask should be clearly defined, include relevant background, and focus on a single, well-scoped objective. It does not perform vague or speculative subtasks. \nArgs: \n\tsubtask: the subtask to be performed. \nReturns: \n\tthe processed summary report of the subtask. ",
                    schema={
                        "type": "object",
                        "properties": {
                            "subtask": {"title": "Subtask", "type": "string"}
                        },
                        "required": ["subtask"],
                        "title": "execute_subtaskArguments",
                    },
                )
            ],
        )
        return tool_definition


class SubAgentWorkerPromptDeepSeek(SubAgentWorkerPrompt):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.is_main_agent = False

    def generate_system_prompt_with_mcp_tools(self, mcp_servers: list[Any]) -> str:
        formatted_date = datetime.datetime.today().strftime("%Y-%m-%d")

        prompt = f"""In this environment you have access to a set of tools you can use to answer the user's question. 

You only have access to the tools provided below. You can only use one tool per message, and will receive the result of that tool in the user's next response. You use tools step-by-step to accomplish a given task, with each tool-use informed by the result of the previous tool-use. Today is: {formatted_date}. Here are the functions available in JSONSchema format:

"""

        # Add MCP servers section
        if mcp_servers and len(mcp_servers) > 0:
            for server in mcp_servers:
                prompt += f"## Server name: {server['name']}\n"

                if "tools" in server and len(server["tools"]) > 0:
                    for tool in server["tools"]:
                        # Skip tools that failed to load (they only have 'error' key)
                        if "error" in tool and "name" not in tool:
                            continue
                        prompt += f"### Tool name: {tool['name']}\n"
                        prompt += f"Description: {tool['description']}\n"
                        prompt += f"Input JSON schema: {tool['schema']}\n"

        # Add the full objective system prompt
        prompt += """
# General Objective

You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.

## Task Strategy

1. Analyze the user's request and set clear, achievable sub-goals. Prioritize these sub-goals in a logical order.
2. Start with a concise, numbered, step-by-step plan (e.g., 1., 2., 3.) outlining how you will solve the task before taking any action. Each sub-goal should correspond to a distinct step in your task-solving process.
3. Work through these sub-goals sequentially. After each step, carefully review and extract all potentially relevant information, details, or implications from the tool result before proceeding. The user may provide tool-use feedback, reflect on the results, and revise your plan if needed. If you encounter new information or challenges, adjust your approach accordingly. Revisit previous steps to ensure earlier sub-goals or clues have not been overlooked or missed.
4. You have access to a wide range of powerful tools. Use them strategically to accomplish each sub-goal.

## Tool-Use Guidelines

1. **IMPORTANT: Each step must involve exactly ONE tool call only, unless the task is already solved. You are strictly prohibited from making multiple tool calls in a single response.** 
2. Before each tool call:
- Briefly summarize and analyze what is currently known.
- Identify what is missing, uncertain, or unreliable.
- Be concise; do not repeat the same analysis across steps.
- Choose the most relevant tool for the current sub-goal, and explain why this tool is necessary at this point.
- Verify whether all required parameters are either explicitly provided or can be clearly and reasonably inferred from context.
- Do not guess or use placeholder values for missing inputs.
- Skip optional parameters unless they are explicitly specified.
3. All tool queries must include full, self-contained context. Tools do not retain memory between calls. Include all relevant information from earlier steps in each query.
4. Avoid broad, vague, or speculative queries. Every tool call should aim to retrieve new, actionable information that clearly advances the task.
5. **For historical or time-specific content**: Regular search engines return current webpage content, not historical content. Archived webpage search is essential for retrieving content as it appeared in the past, use related tools to search for the historical content.
6. Even if a tool result does not directly answer the question, thoroughly extract and summarize all partial information, important details, patterns, constraints, or keywords that may help guide future steps. Never proceed to the next step without first ensuring that all significant insights from the current result have been fully considered.

## Tool-Use Communication Rules

1. **CRITICAL: After issuing exactly ONE tool call, STOP your response immediately. You must never make multiple tool calls in a single response. Do not include tool results, do not assume what the results will be, and do not continue with additional analysis or tool calls. The user will provide the actual tool results in their next message.**
2. Do not present the final answer until the entire task is complete.
3. Do not mention tool names.
4. Do not engage in unnecessary back-and-forth or end with vague offers of help. Do not end your responses with questions or generic prompts.
5. Do not use tools that do not exist.
6. Unless otherwise requested, respond in the same language as the user's message.
7. If the task does not require tool use, answer the user directly.

"""

        prompt += """# Agent Specific Objective

You are an agent that performs various subtasks to collect information and execute specific actions. Your task is to complete well-defined, single-scope objectives efficiently and accurately.
Do not infer, speculate, or attempt to fill in missing parts yourself. Only return factual content and execute actions as specified.

## File Path Handling
When subtasks mention file paths, these are local system file paths (not sandbox paths). You can:
- Use tools to directly access these files from the local system
- Upload files to the sandbox environment (remember to create a new sandbox for each task, this sandbox only exists for the current task) for processing if needed
- Choose the most appropriate approach based on the specific task requirements
- If the final response requires returning a file, download it to the local system first and then return the local path, the sandbox path is not allowed

Critically assess the reliability of all information:
- If the credibility of a source is uncertain, clearly flag it.
- Do **not** treat information as trustworthy just because it appears — **cross-check when necessary**.
- If you find conflicting or ambiguous information, include all relevant findings and flag the inconsistency.

Be cautious and transparent in your output:
- Always return all related information. If information is incomplete or weakly supported, still share partial excerpts, and flag any uncertainty.
- Never assume or guess — if an exact answer cannot be found, say so clearly.
- Prefer quoting or excerpting **original source text** rather than interpreting or rewriting it, and provide the URL if available.
- If more context is needed, return a clarification request and do not proceed with tool use.
- Focus on completing the specific subtask assigned to you, not broader reasoning.
"""

        return prompt


================================================
FILE: config/tool/tool-audio-os.yaml
================================================
name: "tool-audio-os"
tool_command: "python"
args:
  - "-m"
  - "miroflow.tool.mcp_servers.audio_mcp_server_os"
env:
  WHISPER_API_KEY: "${oc.env:WHISPER_API_KEY}"
  WHISPER_BASE_URL: "${oc.env:WHISPER_BASE_URL}"
  WHISPER_MODEL_NAME: "${oc.env:WHISPER_MODEL_NAME}"

================================================
FILE: config/tool/tool-audio.yaml
================================================
name: "tool-audio"
tool_command: "python"
args:
  - "-m"
  - "miroflow.tool.mcp_servers.audio_mcp_server"
env:
# Audio processing API configuration - these values will be loaded from the .env file at runtime
  OPENAI_API_KEY: "${oc.env:OPENAI_API_KEY}"
  OPENAI_BASE_URL: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"
  OPENAI_TRANSCRIPTION_MODEL_NAME: "${oc.env:OPENAI_TRANSCRIPTION_MODEL_NAME,gpt-4o-mini-transcribe}"
  OPENAI_AUDIO_MODEL_NAME: "${oc.env:OPENAI_AUDIO_MODEL_NAME,gpt-4o-audio-preview}"

================================================
FILE: config/tool/tool-browsing.yaml
================================================
name: "tool-browsing"
tool_command: "python"
args:
  - "-m"
  - "miroflow.tool.mcp_servers.browsing_mcp_server"
env:
# Browsing AI API configuration - these values will be loaded from the .env file at runtime
  ANTHROPIC_API_KEY: "${oc.env:ANTHROPIC_API_KEY}"
  ANTHROPIC_BASE_URL: "${oc.env:ANTHROPIC_BASE_URL,https://api.anthropic.com}"
  ANTHROPIC_MODEL_NAME: "${oc.env:ANTHROPIC_MODEL_NAME,claude-3-7-sonnet-20250219}"
  OPENAI_API_KEY: "${oc.env:OPENAI_API_KEY}"
  OPENAI_BASE_URL: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"
  OPENAI_MODEL_NAME: "${oc.env:OPENAI_MODEL_NAME,gpt-4o}"

================================================
FILE: config/tool/tool-code-sandbox.yaml
================================================
name: "tool-code-sandbox"
tool_command: "python"
args:
  - "-m"
  - "miroflow.tool.mcp_servers.code_sandbox"
env:
  E2B_API_KEY: "${oc.env:E2B_API_KEY}"
  LOGS_DIR: "./logs"


================================================
FILE: config/tool/tool-image-video-os.yaml
================================================
name: "tool-image-video-os"
tool_command: "python"
args:
  - "-m"
  - "miroflow.tool.mcp_servers.vision_mcp_server_os"
env:
  VISION_API_KEY: "${oc.env:VISION_API_KEY}"
  VISION_BASE_URL: "${oc.env:VISION_BASE_URL}"
  VISION_MODEL_NAME: "${oc.env:VISION_MODEL_NAME}"

================================================
FILE: config/tool/tool-image-video.yaml
================================================
name: "tool-image-video"
tool_command: "python"
args:
  - "-m"
  - "miroflow.tool.mcp_servers.vision_mcp_server"
env:
# Visual Question Answering (VQA) provider selection order:
# 1. If ANTHROPIC_API_KEY is set, Anthropic will be used for VQA.
# 2. If not, but OPENAI_API_KEY is set, OpenAI will be used for VQA.
# 3. If neither is set, Gemini will be used for VQA (requires GEMINI_API_KEY).
# 4. Gemini key is a must to use YouTube video analysis.
# These values will be loaded from the .env file at runtime
  ANTHROPIC_API_KEY: "${oc.env:ANTHROPIC_API_KEY,???}"
  ANTHROPIC_BASE_URL: "${oc.env:ANTHROPIC_BASE_URL,https://api.anthropic.com}"
  ANTHROPIC_MODEL_NAME: "${oc.env:ANTHROPIC_MODEL_NAME,claude-3-7-sonnet-20250219}"
  OPENAI_API_KEY: "${oc.env:OPENAI_API_KEY}"
  OPENAI_BASE_URL: "${oc.env:OPENAI_BASE_URL,https://api.openai.com/v1}"
  OPENAI_MODEL_NAME: "${oc.env:OPENAI_MODEL_NAME,gpt-4o}"
  GEMINI_API_KEY: "${oc.env:GEMINI_API_KEY,???}"

================================================
FILE: config/tool/tool-jina-scrape.yaml
================================================
name: "tool-jina-scrape"
tool_command: "python"
args:
  - "-m"
  - "miroflow.tool.mcp_servers.jina_scrape"
env:
# Jina and LLM API keys - these values will be loa
Download .txt
gitextract_m3xbil2z/

├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── pull_request_template.md
│   ├── scripts/
│   │   └── check_pr_title.py
│   └── workflows/
│       ├── check-pr-title.yml
│       └── run-ruff.yml
├── .gitignore
├── LICENSE
├── README.md
├── REUSE.toml
├── config/
│   ├── __init__.py
│   ├── agent_quickstart.yaml
│   ├── agent_quickstart_graph.yaml
│   ├── agent_quickstart_skill.yaml
│   ├── agent_single-test.yaml
│   ├── agent_web_demo.yaml
│   ├── benchmark/
│   │   ├── browsecomp-en-200.yaml
│   │   ├── browsecomp-en.yaml
│   │   ├── browsecomp-zh.yaml
│   │   ├── default.yaml
│   │   ├── example_dataset.yaml
│   │   ├── finsearchcomp.yaml
│   │   ├── frames-test.yaml
│   │   ├── futurex.yaml
│   │   ├── gaia-test.yaml
│   │   ├── gaia-validation-165.yaml
│   │   ├── gaia-validation-text-only.yaml
│   │   ├── gaia-validation.yaml
│   │   ├── hle-text-only.yaml
│   │   ├── hle.yaml
│   │   ├── webwalkerqa.yaml
│   │   └── xbench-ds.yaml
│   ├── benchmark_browsecomp-en-200_mirothinker_v1.yaml
│   ├── benchmark_browsecomp-en_mirothinker.yaml
│   ├── benchmark_browsecomp-zh_mirothinker_v1.yaml
│   ├── benchmark_browsecomp-zh_mirothinker_v2.yaml
│   ├── benchmark_browsecomp-zh_mirothinker_v3.yaml
│   ├── benchmark_frames-test_mirothinker.yaml
│   ├── benchmark_gaia-validation-165_mirothinker_tool.yaml
│   ├── benchmark_gaia-validation-165_mirothinker_v1.yaml
│   ├── benchmark_gaia-validation-text-103_kimi_k25.yaml
│   ├── benchmark_gaia-validation-text-103_mirothinker_multi-agent.yaml
│   ├── benchmark_gaia-validation-text-103_mirothinker_v1.yaml
│   ├── benchmark_gaia-validation-text-103_mirothinker_v2.yaml
│   ├── benchmark_hle-text-only_mirothinker.yaml
│   ├── benchmark_hle_mirothinker_v1.yaml
│   ├── benchmark_webwalkerqa_mirothinker.yaml
│   ├── benchmark_xbench-ds_mirothinker.yaml
│   ├── llm/
│   │   ├── base_kimi_k25.yaml
│   │   ├── base_mirothinker.yaml
│   │   └── base_openai.yaml
│   ├── prompts/
│   │   ├── __init__.py
│   │   ├── base_agent_prompt.py
│   │   ├── main_agent_prompt_deepseek.py
│   │   ├── main_agent_prompt_gaia.py
│   │   ├── main_boxed_answer.py
│   │   ├── prompt_final_answer_extraction.yaml
│   │   ├── prompt_main_agent.yaml
│   │   ├── prompt_main_agent_benchmark.yaml
│   │   ├── prompt_main_agent_gaia.yaml
│   │   ├── prompt_sub_agent.yaml
│   │   ├── prompt_subtask.yaml
│   │   └── sub_worker.py
│   └── tool/
│       ├── tool-audio-os.yaml
│       ├── tool-audio.yaml
│       ├── tool-browsing.yaml
│       ├── tool-code-sandbox.yaml
│       ├── tool-image-video-os.yaml
│       ├── tool-image-video.yaml
│       ├── tool-jina-scrape.yaml
│       ├── tool-markitdown.yaml
│       ├── tool-reading.yaml
│       ├── tool-reasoning-os.yaml
│       ├── tool-reasoning.yaml
│       ├── tool-scrape-website-v1.yaml
│       ├── tool-searching-serper.yaml
│       ├── tool-searching.yaml
│       ├── tool-serper-search.yaml
│       └── tool-serper-sogou-search.yaml
├── data/
│   ├── FSI-2023-DOWNLOAD.xlsx
│   └── README.md
├── docs/
│   └── mkdocs/
│       ├── README.md
│       ├── docs/
│       │   ├── all_about_agents.md
│       │   ├── browsecomp_en.md
│       │   ├── browsecomp_zh.md
│       │   ├── claude-3.7-sonnet.md
│       │   ├── contribute_benchmarks.md
│       │   ├── contribute_llm_clients.md
│       │   ├── contribute_tools.md
│       │   ├── contributors.md
│       │   ├── core_concepts.md
│       │   ├── data.md
│       │   ├── deepseek.md
│       │   ├── download_datasets.md
│       │   ├── e2b_advanced_features.md
│       │   ├── evaluation_overview.md
│       │   ├── faqs.md
│       │   ├── finsearchcomp.md
│       │   ├── futurex.md
│       │   ├── gaia_test.md
│       │   ├── gaia_validation_claude37sonnet.md
│       │   ├── gaia_validation_gpt5.md
│       │   ├── gaia_validation_mirothinker.md
│       │   ├── gaia_validation_prerequisites.md
│       │   ├── gaia_validation_text_only.md
│       │   ├── hle.md
│       │   ├── hle_text_only.md
│       │   ├── index.md
│       │   ├── license.md
│       │   ├── llm_clients_overview.md
│       │   ├── mirothinker.md
│       │   ├── model_comparison.md
│       │   ├── openai-gpt4o.md
│       │   ├── openai-gpt5.md
│       │   ├── openrouter-claude-3.7-sonnet.md
│       │   ├── quickstart.md
│       │   ├── tool_audio.md
│       │   ├── tool_audio_os.md
│       │   ├── tool_overview.md
│       │   ├── tool_python.md
│       │   ├── tool_reading.md
│       │   ├── tool_reasoning.md
│       │   ├── tool_reasoning_os.md
│       │   ├── tool_searching.md
│       │   ├── tool_searching_serper.md
│       │   ├── tool_vqa.md
│       │   ├── tool_vqa_os.md
│       │   ├── webwalkerqa.md
│       │   ├── whats_new.md
│       │   ├── why_miroflow.md
│       │   ├── xbench_ds.md
│       │   └── yaml_config.md
│       └── mkdocs.yml
├── miroflow/
│   ├── __init__.py
│   ├── agents/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── context.py
│   │   ├── factory.py
│   │   ├── iterative_agent_with_rollback.py
│   │   └── sequential_agent.py
│   ├── benchmark/
│   │   ├── __init__.py
│   │   ├── calculate_average_score.py
│   │   ├── eval_utils.py
│   │   ├── run_benchmark.py
│   │   ├── task_runner.py
│   │   └── verifiers/
│   │       ├── __init__.py
│   │       ├── base_verifier.py
│   │       ├── browsecomp_en_verifier.py
│   │       ├── browsecomp_zh_verifier.py
│   │       ├── finsearchcomp_verifier.py
│   │       ├── gaia_common_verifier.py
│   │       ├── gaia_verifier.py
│   │       ├── hle_verifier.py
│   │       ├── simpleqa_verifier.py
│   │       └── xbench_verifier.py
│   ├── io_processor/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── exceed_max_turn_summary_generator.py
│   │   ├── file_content_preprocessor.py
│   │   ├── final_answer_extractor.py
│   │   ├── input_hint_generator.py
│   │   ├── input_message_generator.py
│   │   ├── regex_boxed_extractor.py
│   │   └── summary_generator.py
│   ├── llm/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── claude_anthropic.py
│   │   ├── claude_openrouter.py
│   │   ├── factory.py
│   │   ├── gpt5_openai.py
│   │   ├── gpt_openai.py
│   │   ├── mirothinker_sglang.py
│   │   ├── openai_client.py
│   │   ├── openrouter.py
│   │   └── util.py
│   ├── logging/
│   │   ├── __init__.py
│   │   ├── decorators.py
│   │   ├── span.py
│   │   ├── task_tracer.py
│   │   └── tool_logging.py
│   ├── py.typed
│   ├── registry.py
│   ├── skill/
│   │   ├── __init__.py
│   │   ├── manager.py
│   │   └── skills/
│   │       ├── Afternoon_feeling/
│   │       │   └── SKILL.md
│   │       ├── Today_feeling/
│   │       │   └── SKILL.md
│   │       └── simple_file_understanding/
│   │           └── SKILL.md
│   ├── tool/
│   │   ├── __init__.py
│   │   ├── factory.py
│   │   ├── manager.py
│   │   └── mcp_servers/
│   │       ├── __init__.py
│   │       ├── audio_mcp_server.py
│   │       ├── audio_mcp_server_os.py
│   │       ├── browser_session.py
│   │       ├── code_sandbox.py
│   │       ├── jina_scrape.py
│   │       ├── miroapi_serper_mcp_server.py
│   │       ├── reading_mcp_server.py
│   │       ├── reasoning_mcp_server.py
│   │       ├── reasoning_mcp_server_os.py
│   │       ├── scrape_website_v1.py
│   │       ├── searching_mcp_server.py
│   │       ├── serper_search.py
│   │       ├── serper_sogou_search.py
│   │       ├── skill_mcp_server.py
│   │       ├── utils/
│   │       │   ├── smart_request.py
│   │       │   └── url_unquote.py
│   │       ├── vision_mcp_server.py
│   │       └── vision_mcp_server_os.py
│   └── utils/
│       ├── __init__.py
│       ├── file_content_utils.py
│       ├── io_utils.py
│       ├── parsing_utils.py
│       ├── prepare_benchmark/
│       │   ├── README.md
│       │   ├── __init__.py
│       │   ├── common.py
│       │   ├── gen_browsecomp.py
│       │   ├── gen_finsearchcomp.py
│       │   ├── gen_frames.py
│       │   ├── gen_futurex.py
│       │   ├── gen_gaia.py
│       │   ├── gen_gaia_text_only.py
│       │   ├── gen_hle.py
│       │   ├── gen_hle_text_only.py
│       │   ├── gen_webwalkerqa.py
│       │   ├── gen_xbench_ds.py
│       │   └── main.py
│       ├── prompt_utils.py
│       ├── summary_utils.py
│       └── tool_utils.py
├── pyproject.toml
├── scripts/
│   ├── benchmark/
│   │   ├── check_progress/
│   │   │   ├── check_progress_browsecomp-en-200.py
│   │   │   ├── check_progress_browsecomp-en.py
│   │   │   ├── check_progress_browsecomp-zh.py
│   │   │   ├── check_progress_frames-test.py
│   │   │   ├── check_progress_gaia-validation-165.py
│   │   │   ├── check_progress_gaia-validation-text-103.py
│   │   │   ├── check_progress_hle-text-only.py
│   │   │   ├── check_progress_hle.py
│   │   │   ├── check_progress_webwalkerqa.py
│   │   │   └── check_progress_xbench-ds.py
│   │   ├── kimi_k25/
│   │   │   └── gaia-validation-text-103_kimi_k25_8runs.sh
│   │   └── mirothinker/
│   │       ├── browsecomp-en-200_mirothinker_v1.sh
│   │       ├── browsecomp-en_mirothinker_3runs.sh
│   │       ├── browsecomp-zh_mirothinker_v1.sh
│   │       ├── browsecomp-zh_mirothinker_v2.sh
│   │       ├── browsecomp-zh_mirothinker_v3.sh
│   │       ├── frames-test_mirothinker_3runs.sh
│   │       ├── gaia-validation-165_mirothinker_v1.sh
│   │       ├── gaia-validation-text-103_mirothinker_v1.sh
│   │       ├── gaia-validation-text-103_mirothinker_v2.sh
│   │       ├── hle-text-only_mirothinker_3runs.sh
│   │       ├── hle_mirothinker_v1.sh
│   │       ├── webwalkerqa_mirothinker_3runs.sh
│   │       └── xbench-ds_mirothinker_8runs.sh
│   ├── run_prepare_benchmark.sh
│   ├── run_single_task.py
│   ├── start_web.sh
│   └── test_single_task.sh
└── web_app/
    ├── __init__.py
    ├── api/
    │   ├── __init__.py
    │   ├── dependencies.py
    │   └── routes/
    │       ├── __init__.py
    │       ├── configs.py
    │       ├── health.py
    │       ├── tasks.py
    │       └── uploads.py
    ├── core/
    │   ├── __init__.py
    │   ├── config.py
    │   ├── session_manager.py
    │   └── task_executor.py
    ├── frontend/
    │   ├── index.html
    │   ├── package.json
    │   ├── postcss.config.js
    │   ├── src/
    │   │   ├── App.tsx
    │   │   ├── api/
    │   │   │   ├── client.ts
    │   │   │   └── tasks.ts
    │   │   ├── components/
    │   │   │   ├── common/
    │   │   │   │   ├── FileUpload.tsx
    │   │   │   │   ├── LoadingSpinner.tsx
    │   │   │   │   └── MarkdownRenderer.tsx
    │   │   │   └── task/
    │   │   │       ├── TaskForm.tsx
    │   │   │       ├── TaskHistory.tsx
    │   │   │       └── TaskStatus.tsx
    │   │   ├── hooks/
    │   │   │   └── usePolling.ts
    │   │   ├── index.css
    │   │   ├── main.tsx
    │   │   ├── types/
    │   │   │   └── task.ts
    │   │   └── vite-env.d.ts
    │   ├── tailwind.config.js
    │   ├── tsconfig.json
    │   ├── tsconfig.node.json
    │   └── vite.config.ts
    ├── main.py
    └── models/
        ├── __init__.py
        └── task.py
Download .txt
SYMBOL INDEX (822 symbols across 119 files)

FILE: .github/scripts/check_pr_title.py
  class CheckResult (line 36) | class CheckResult:
    method to_markdown (line 41) | def to_markdown(self) -> str:
  function check_pr_title (line 48) | def check_pr_title(title: str) -> CheckResult:
  function main (line 87) | def main() -> None:

FILE: config/__init__.py
  function load_config (line 13) | def load_config(config_path: str, *overrides) -> omegaconf.DictConfig:

FILE: config/prompts/base_agent_prompt.py
  class BaseAgentPrompt (line 7) | class BaseAgentPrompt(ABC):
    method __init__ (line 15) | def __init__(self, *args, **kwargs):
    method generate_system_prompt_with_mcp_tools (line 19) | def generate_system_prompt_with_mcp_tools(
    method generate_summarize_prompt (line 41) | def generate_summarize_prompt(
    method expose_agent_as_tool (line 66) | def expose_agent_as_tool(self, subagent_name: str, **kwargs) -> dict:

FILE: config/prompts/main_agent_prompt_deepseek.py
  class MainAgentPromptBoxedDeepSeek (line 5) | class MainAgentPromptBoxedDeepSeek:
    method __init__ (line 10) | def __init__(self, *args, **kwargs):
    method generate_system_prompt_with_mcp_tools (line 14) | def generate_system_prompt_with_mcp_tools(self, mcp_servers: list[Any]...
    method generate_summarize_prompt (line 81) | def generate_summarize_prompt(

FILE: config/prompts/main_agent_prompt_gaia.py
  class MainAgentPrompt_GAIA (line 6) | class MainAgentPrompt_GAIA(BaseAgentPrompt):
    method __init__ (line 12) | def __init__(self, *args, **kwargs):
    method generate_system_prompt_with_mcp_tools (line 16) | def generate_system_prompt_with_mcp_tools(self, mcp_servers: list[Any]...
    method generate_summarize_prompt (line 116) | def generate_summarize_prompt(

FILE: config/prompts/main_boxed_answer.py
  class MainAgentPromptBoxedAnswer (line 6) | class MainAgentPromptBoxedAnswer(BaseAgentPrompt):
    method __init__ (line 12) | def __init__(self, *args, **kwargs):
    method generate_system_prompt_with_mcp_tools (line 16) | def generate_system_prompt_with_mcp_tools(self, mcp_servers: list[Any]...
    method generate_summarize_prompt (line 116) | def generate_summarize_prompt(

FILE: config/prompts/sub_worker.py
  class SubAgentWorkerPrompt (line 6) | class SubAgentWorkerPrompt(BaseAgentPrompt):
    method __init__ (line 12) | def __init__(self, *args, **kwargs):
    method generate_system_prompt_with_mcp_tools (line 16) | def generate_system_prompt_with_mcp_tools(self, mcp_servers: list[Any]...
    method generate_summarize_prompt (line 140) | def generate_summarize_prompt(
    method expose_agent_as_tool (line 179) | def expose_agent_as_tool(self, subagent_name: str) -> dict:
  class SubAgentWorkerPromptDeepSeek (line 200) | class SubAgentWorkerPromptDeepSeek(SubAgentWorkerPrompt):
    method __init__ (line 201) | def __init__(self, *args, **kwargs):
    method generate_system_prompt_with_mcp_tools (line 205) | def generate_system_prompt_with_mcp_tools(self, mcp_servers: list[Any]...

FILE: miroflow/agents/base.py
  class BaseAgent (line 25) | class BaseAgent(ABC):
    method __init_subclass__ (line 31) | def __init_subclass__(cls, **kwargs):
    method get_instance_count (line 35) | def get_instance_count(cls):
    method get_instance_name (line 39) | def get_instance_name(cls, cfg):
    method create_sub_module (line 45) | def create_sub_module(self, sub_agent_cfg: DictConfig | dict, name: st...
    method __init__ (line 59) | def __init__(self, cfg: Optional[DictConfig | dict] = None, parent=None):
    method _parse_tool_blacklist (line 82) | def _parse_tool_blacklist(self, blacklist_cfg) -> set:
    method run_internal (line 107) | async def run_internal(self, ctx: AgentContext) -> AgentContext:
    method run (line 111) | async def run(self, ctx: AgentContext) -> AgentContext:
    method run_as_mcp_tool (line 116) | async def run_as_mcp_tool(
    method post_initialize (line 131) | async def post_initialize(self):
    method get_mcp_server_definitions_from_tool_definitions (line 135) | def get_mcp_server_definitions_from_tool_definitions(
    method init_tool_definitions (line 153) | async def init_tool_definitions(self):
    method run_sub_agents_as_mcp_tools (line 205) | async def run_sub_agents_as_mcp_tools(
    method build (line 228) | def build(cls, cfg: DictConfig | dict):
    method __repr__ (line 232) | def __repr__(self):

FILE: miroflow/agents/context.py
  class AgentContext (line 10) | class AgentContext(dict):
    method __init__ (line 18) | def __init__(self, **kwargs):

FILE: miroflow/agents/factory.py
  function build_agent_from_config (line 26) | def build_agent_from_config(cfg: Union[DictConfig, dict]) -> BaseAgent:
  function build_agent (line 35) | def build_agent(cfg: Union[DictConfig, dict], sequential: bool = False) ...

FILE: miroflow/agents/iterative_agent_with_rollback.py
  class IterativeAgentWithToolAndRollback (line 50) | class IterativeAgentWithToolAndRollback(BaseAgent):
    method __init__ (line 53) | def __init__(self, cfg: DictConfig):
    method _get_query_key (line 75) | def _get_query_key(tool_call: dict) -> str:
    method _check_duplicate_tool_calls (line 82) | def _check_duplicate_tool_calls(
    method _should_rollback (line 99) | def _should_rollback(
    method run_internal (line 149) | async def run_internal(self, ctx: AgentContext) -> AgentContext:

FILE: miroflow/agents/sequential_agent.py
  class SequentialAgent (line 17) | class SequentialAgent(BaseAgent):
    method __init__ (line 20) | def __init__(
    method run_internal (line 51) | async def run_internal(
    method __repr__ (line 59) | def __repr__(self):

FILE: miroflow/benchmark/calculate_average_score.py
  function detect_pass_at_k (line 14) | def detect_pass_at_k(results_dir: str) -> tuple:
  function calculate_average_scores (line 48) | def calculate_average_scores(results_dir: str) -> dict:
  function print_results (line 93) | def print_results(stats: dict):
  function main (line 110) | def main(results_dir: str):

FILE: miroflow/benchmark/eval_utils.py
  function is_valid_box (line 61) | def is_valid_box(final_boxed_answer: str) -> bool:
  class Task (line 74) | class Task:
    method to_dict (line 83) | def to_dict(self) -> Dict[str, Any]:
    method from_dict (line 94) | def from_dict(cls, data: Dict[str, Any]) -> "Task":
  class AttemptResult (line 105) | class AttemptResult:
    method __init__ (line 108) | def __init__(
    method to_dict (line 140) | def to_dict(self) -> Dict[str, Any]:
    method from_dict (line 159) | def from_dict(cls, data: Dict[str, Any], task: Task) -> "AttemptResult":
    method update_from_response (line 177) | def update_from_response(self, response: Dict[str, Any], log_path: Path):
    method update_with_evaluation (line 186) | async def update_with_evaluation(
    method update_log_with_evaluation (line 196) | async def update_log_with_evaluation(
  class TaskResult (line 224) | class TaskResult:
    method __init__ (line 227) | def __init__(self, task: Task):
    method to_dict (line 240) | def to_dict(self) -> Dict[str, Any]:
    method update_with_attempt (line 269) | def update_with_attempt(self, attempt_result: AttemptResult):
    method from_dict (line 285) | def from_dict(cls, data: Dict[str, Any]) -> "TaskResult":
  class Evaluator (line 315) | class Evaluator:
    method __init__ (line 318) | def __init__(self, cfg: DictConfig, parse_func: Optional[TaskParser] =...
    method load_tasks (line 335) | def load_tasks(self) -> List[Task]:
    method _validate_load_requirements (line 347) | def _validate_load_requirements(self) -> None:
    method _download_gaia_val (line 361) | def _download_gaia_val(self) -> None:
    method _should_include_task (line 409) | def _should_include_task(self, task: Task) -> bool:
    method _parse_tasks_from_file (line 414) | def _parse_tasks_from_file(self) -> List[Task]:
    method _apply_task_limit (line 427) | def _apply_task_limit(self, tasks: List[Task]) -> List[Task]:
    method save_results (line 435) | def save_results(self, results: List["TaskResult"], output_path: Path)...
    method evaluate_accuracy (line 444) | async def evaluate_accuracy(self, results: List["TaskResult"]) -> float:
    method _print_task_result (line 464) | def _print_task_result(self, result: TaskResult) -> None:
    method _print_attempt_details (line 478) | def _print_attempt_details(self, attempt: AttemptResult) -> None:
    method _get_status_icon (line 487) | def _get_status_icon(is_correct: bool, judge_result: str) -> str:
    method _print_accuracy_summary (line 493) | def _print_accuracy_summary(
    method verify_attempt_result (line 501) | async def verify_attempt_result(
  function get_verifier (line 546) | def get_verifier(
  function verify_answer_for_benchmark (line 583) | async def verify_answer_for_benchmark(

FILE: miroflow/benchmark/run_benchmark.py
  function _main_signal_handler (line 29) | def _main_signal_handler(signum, frame):
  function test_benchmark (line 42) | async def test_benchmark(cfg: DictConfig) -> float:

FILE: miroflow/benchmark/task_runner.py
  function _set_pdeathsig (line 45) | def _set_pdeathsig():
  function _cleanup_executor (line 61) | def _cleanup_executor():
  function _signal_handler (line 102) | def _signal_handler(signum, frame):
  function _worker_signal_handler (line 121) | def _worker_signal_handler(signum, frame):
  function _worker_initializer (line 126) | def _worker_initializer():
  function _task_worker (line 136) | def _task_worker(task_dict, cfg_dict, pass_at_k, max_retry, exceed_max_t...
  function _build_exceed_max_turn_summary_text (line 206) | def _build_exceed_max_turn_summary_text(
  function run_single_retry (line 245) | async def run_single_retry(
  function run_single_task (line 338) | async def run_single_task(
  function run_tasks (line 443) | def run_tasks(

FILE: miroflow/benchmark/verifiers/base_verifier.py
  class BaseVerifier (line 35) | class BaseVerifier:
    method __init__ (line 38) | def __init__(self, openai_client: Optional[AsyncOpenAI] = None):
    method verify (line 41) | async def verify(

FILE: miroflow/benchmark/verifiers/browsecomp_en_verifier.py
  class BrowseCompEnVerifier (line 101) | class BrowseCompEnVerifier(BaseVerifier):
    method verify (line 114) | async def verify(

FILE: miroflow/benchmark/verifiers/browsecomp_zh_verifier.py
  class BrowseCompZhVerifier (line 102) | class BrowseCompZhVerifier(BaseVerifier):
    method verify (line 115) | async def verify(

FILE: miroflow/benchmark/verifiers/finsearchcomp_verifier.py
  class FinSearchCompVerifier (line 24) | class FinSearchCompVerifier(BaseVerifier):
    method verify (line 33) | async def verify(
    method _parse_response (line 77) | def _parse_response(content: str) -> str:

FILE: miroflow/benchmark/verifiers/gaia_common_verifier.py
  class GAIACommonVerifier (line 24) | class GAIACommonVerifier(BaseVerifier):
    method _normalize_number_str (line 39) | def _normalize_number_str(number_str: str) -> float:
    method _normalize_str (line 49) | def _normalize_str(input_str: str, remove_punct: bool = True) -> str:
    method _is_float (line 58) | def _is_float(element: Any) -> bool:
    method _split_string (line 67) | def _split_string(s: str, char_list: List[str] = None) -> List[str]:
    method _compare_as_number (line 74) | def _compare_as_number(self, model_answer: str, ground_truth: str) -> ...
    method _compare_as_list (line 78) | def _compare_as_list(self, model_answer: str, ground_truth: str) -> bool:
    method _compare_as_string (line 100) | def _compare_as_string(self, model_answer: str, ground_truth: str) -> ...
    method _exact_match (line 104) | def _exact_match(self, model_answer: str, ground_truth: str) -> bool:
    method verify (line 119) | async def verify(

FILE: miroflow/benchmark/verifiers/gaia_verifier.py
  class GAIAVerifier (line 15) | class GAIAVerifier(BaseVerifier):
    method verify (line 18) | async def verify(
    method _normalize_number_str (line 34) | def _normalize_number_str(number_str: str) -> float:
    method _split_string (line 45) | def _split_string(s: str, char_list: List[str] = None) -> List[str]:
    method _normalize_str (line 53) | def _normalize_str(input_str: str, remove_punct: bool = True) -> str:
    method _is_float (line 62) | def _is_float(element: Any) -> bool:
    method _compare_as_number (line 70) | def _compare_as_number(self, model_answer: str, ground_truth: str) -> ...
    method _compare_as_list (line 75) | def _compare_as_list(self, model_answer: str, ground_truth: str) -> bool:
    method _compare_as_string (line 100) | def _compare_as_string(self, model_answer: str, ground_truth: str) -> ...
    method _score_answer (line 105) | def _score_answer(self, model_answer: str, ground_truth: str) -> bool:

FILE: miroflow/benchmark/verifiers/hle_verifier.py
  class HLEVerifier (line 22) | class HLEVerifier(BaseVerifier):
    class ExtractedAnswer (line 45) | class ExtractedAnswer(BaseModel):
    method verify (line 57) | async def verify(

FILE: miroflow/benchmark/verifiers/simpleqa_verifier.py
  class SimpleQAVerifier (line 24) | class SimpleQAVerifier(BaseVerifier):
    method _normalize_number_str (line 109) | def _normalize_number_str(number_str: str) -> float:
    method _normalize_str (line 119) | def _normalize_str(input_str: str, remove_punct: bool = True) -> str:
    method _is_float (line 128) | def _is_float(element: Any) -> bool:
    method _split_string (line 137) | def _split_string(s: str, char_list: List[str] = None) -> List[str]:
    method _compare_as_number (line 144) | def _compare_as_number(self, model_answer: str, ground_truth: str) -> ...
    method _compare_as_list (line 148) | def _compare_as_list(self, model_answer: str, ground_truth: str) -> bool:
    method _compare_as_string (line 170) | def _compare_as_string(self, model_answer: str, ground_truth: str) -> ...
    method _exact_match (line 174) | def _exact_match(self, model_answer: str, ground_truth: str) -> bool:
    method verify (line 189) | async def verify(

FILE: miroflow/benchmark/verifiers/xbench_verifier.py
  class XBenchVerifier (line 23) | class XBenchVerifier(BaseVerifier):
    method _parse_match_result (line 50) | def _parse_match_result(match):
    method verify (line 64) | async def verify(

FILE: miroflow/io_processor/base.py
  class BaseIOProcessor (line 15) | class BaseIOProcessor(BaseAgent):

FILE: miroflow/io_processor/exceed_max_turn_summary_generator.py
  class ExceedMaxTurnSummaryGenerator (line 35) | class ExceedMaxTurnSummaryGenerator(BaseIOProcessor):
    method _extract_failure_experience_summary (line 44) | def _extract_failure_experience_summary(text: str) -> str:
    method run_internal (line 78) | async def run_internal(self, ctx: AgentContext) -> AgentContext:

FILE: miroflow/io_processor/file_content_preprocessor.py
  class FileContentPreprocessor (line 21) | class FileContentPreprocessor(BaseIOProcessor):
    method run_internal (line 35) | async def run_internal(self, ctx: AgentContext) -> AgentContext:

FILE: miroflow/io_processor/final_answer_extractor.py
  class FinalAnswerExtractor (line 19) | class FinalAnswerExtractor(BaseIOProcessor):
    method _extract_boxed_content (line 25) | def _extract_boxed_content(text: str) -> str:
    method _format_final_summary_and_log (line 75) | def _format_final_summary_and_log(extracted_answer):
    method run_internal (line 99) | async def run_internal(self, ctx: AgentContext) -> AgentContext:

FILE: miroflow/io_processor/input_hint_generator.py
  class InputHintGenerator (line 15) | class InputHintGenerator(BaseIOProcessor):
    method run_internal (line 20) | async def run_internal(self, ctx: AgentContext) -> AgentContext:

FILE: miroflow/io_processor/input_message_generator.py
  class InputMessageGenerator (line 19) | class InputMessageGenerator(BaseIOProcessor):
    method run_internal (line 24) | async def run_internal(self, ctx: AgentContext) -> AgentContext:

FILE: miroflow/io_processor/regex_boxed_extractor.py
  class RegexBoxedExtractor (line 20) | class RegexBoxedExtractor(BaseIOProcessor):
    method _extract_boxed_content (line 24) | def _extract_boxed_content(text: str) -> str:
    method _extract_boxed_from_message_history (line 67) | def _extract_boxed_from_message_history(message_history: list) -> str:
    method run_internal (line 91) | async def run_internal(self, ctx: AgentContext) -> AgentContext:

FILE: miroflow/io_processor/summary_generator.py
  class SummaryGenerator (line 16) | class SummaryGenerator(BaseIOProcessor):
    method run_internal (line 21) | async def run_internal(self, ctx: AgentContext) -> AgentContext:

FILE: miroflow/llm/base.py
  class ContextLimitError (line 30) | class ContextLimitError(Exception):
  class LLMOutput (line 37) | class LLMOutput(ABC):
  class LLMClientBase (line 46) | class LLMClientBase(ABC):
    method __init__ (line 49) | def __init__(self, cfg: DictConfig):
    method _create_client (line 82) | def _create_client(self, config: DictConfig) -> Any:
    method _create_message (line 87) | async def _create_message(
    method process_llm_response (line 98) | def process_llm_response(self, llm_response) -> tuple[str, bool, dict]:
    method extract_tool_calls_info (line 115) | def extract_tool_calls_info(
    method _strip_think_from_messages (line 121) | def _strip_think_from_messages(self, messages: List[Dict]) -> List[Dict]:
    method _remove_tool_result_from_messages (line 131) | def _remove_tool_result_from_messages(
    method create_message (line 200) | async def create_message(
    method convert_tool_definition_to_tool_call (line 249) | async def convert_tool_definition_to_tool_call(tools_definitions):
    method close (line 269) | def close(self):
    method _format_response_for_log (line 287) | def _format_response_for_log(self, response) -> Dict:
    method update_message_history (line 345) | def update_message_history(
    method handle_max_turns_reached_summary_prompt (line 354) | def handle_max_turns_reached_summary_prompt(
    method _inject_message_ids (line 359) | def _inject_message_ids(self, message_history: list[dict]) -> None:
    method _estimate_tokens (line 380) | def _estimate_tokens(self, text: str) -> int:
    method ensure_summary_context (line 384) | def ensure_summary_context(
    method __repr__ (line 448) | def __repr__(self):

FILE: miroflow/llm/claude_anthropic.py
  class ClaudeAnthropicClient (line 22) | class ClaudeAnthropicClient(LLMClientBase):
    method __post_init__ (line 23) | def __post_init__(self):
    method _create_client (line 26) | def _create_client(self, config: DictConfig):
    method _create_message (line 42) | async def _create_message(
    method process_llm_response (line 107) | def process_llm_response(self, llm_response) -> tuple[str, bool, dict]:
    method extract_tool_calls_info (line 146) | def extract_tool_calls_info(self, llm_response, assistant_response_text):
    method update_message_history (line 153) | def update_message_history(
    method handle_max_turns_reached_summary_prompt (line 171) | def handle_max_turns_reached_summary_prompt(self, message_history, sum...
    method _apply_cache_control (line 183) | def _apply_cache_control(self, messages):

FILE: miroflow/llm/claude_openrouter.py
  class ClaudeOpenRouterClient (line 24) | class ClaudeOpenRouterClient(LLMClientBase):
    method _create_client (line 25) | def _create_client(self, config: DictConfig):
    method _create_message (line 45) | async def _create_message(
    method _create_completion (line 205) | async def _create_completion(self, params: Dict[str, Any], is_async: b...
    method _clean_user_content_from_response (line 212) | def _clean_user_content_from_response(self, text: str) -> str:
    method process_llm_response (line 220) | def process_llm_response(self, llm_response) -> tuple[str, bool, dict]:
    method extract_tool_calls_info (line 264) | def extract_tool_calls_info(self, llm_response, assistant_response_text):
    method update_message_history (line 271) | def update_message_history(
    method parse_llm_response (line 332) | def parse_llm_response(self, llm_response) -> str:
    method _estimate_tokens (line 338) | def _estimate_tokens(self, text: str) -> int:
    method handle_max_turns_reached_summary_prompt (line 354) | def handle_max_turns_reached_summary_prompt(self, message_history, sum...
    method _apply_cache_control (line 366) | def _apply_cache_control(self, messages):

FILE: miroflow/llm/factory.py
  function build_llm_client (line 17) | def build_llm_client(

FILE: miroflow/llm/gpt5_openai.py
  class GPT5OpenAIClient (line 26) | class GPT5OpenAIClient(LLMClientBase):
    method _create_client (line 27) | def _create_client(self, config: DictConfig):
    method _create_message (line 47) | async def _create_message(
    method _create_completion_with_service_tier_fallback (line 208) | async def _create_completion_with_service_tier_fallback(
    method _clean_user_content_from_response (line 241) | def _clean_user_content_from_response(self, text: str) -> str:
    method process_llm_response (line 249) | def process_llm_response(self, llm_response) -> tuple[str, bool, dict]:
    method extract_tool_calls_info (line 301) | def extract_tool_calls_info(self, llm_response, assistant_response_text):
    method get_user_msg_from_tool_call (line 308) | def get_user_msg_from_tool_call(self, tool_call_info, tool_calls_excee...
    method update_message_history (line 357) | def update_message_history(
    method parse_llm_response (line 418) | def parse_llm_response(self, llm_response) -> str:
    method _estimate_tokens (line 424) | def _estimate_tokens(self, text: str) -> int:
    method handle_max_turns_reached_summary_prompt (line 440) | def handle_max_turns_reached_summary_prompt(self, message_history, sum...
    method _apply_cache_control (line 452) | def _apply_cache_control(self, messages):

FILE: miroflow/llm/gpt_openai.py
  class GPTOpenAIClient (line 24) | class GPTOpenAIClient(LLMClientBase):
    method __init__ (line 25) | def __init__(self, cfg: DictConfig):
    method _create_client (line 29) | def _create_client(self, config: DictConfig):
    method _create_message (line 45) | async def _create_message(
    method _create_completion (line 149) | async def _create_completion(self, params: Dict[str, Any], is_async: b...
    method _handle_oai_tool_thinking (line 156) | async def _handle_oai_tool_thinking(
    method process_llm_response (line 182) | def process_llm_response(self, llm_response) -> tuple[str, bool, dict]:
    method extract_tool_calls_info (line 247) | def extract_tool_calls_info(self, llm_response, assistant_response_text):
    method update_message_history (line 259) | def update_message_history(
    method handle_max_turns_reached_summary_prompt (line 275) | def handle_max_turns_reached_summary_prompt(self, message_history, sum...

FILE: miroflow/llm/mirothinker_sglang.py
  class MiroThinkerSGLangClient (line 26) | class MiroThinkerSGLangClient(LLMClientBase):
    method __post_init__ (line 27) | def __post_init__(self):
    method _create_client (line 30) | def _create_client(self, config: DictConfig):
    method _create_message (line 55) | async def _create_message(
    method _create_completion (line 237) | async def _create_completion(self, params: Dict[str, Any], is_async: b...
    method _clean_user_content_from_response (line 252) | def _clean_user_content_from_response(self, text: str) -> str:
    method process_llm_response (line 260) | def process_llm_response(self, llm_response) -> tuple[str, bool, dict]:
    method extract_tool_calls_info (line 312) | def extract_tool_calls_info(self, llm_response, assistant_response_text):
    method get_user_msg_from_tool_call (line 319) | def get_user_msg_from_tool_call(self, tool_call_info, tool_calls_excee...
    method update_message_history (line 369) | def update_message_history(
    method parse_llm_response (line 430) | def parse_llm_response(self, llm_response) -> str:
    method _estimate_tokens (line 436) | def _estimate_tokens(self, text: str) -> int:
    method handle_max_turns_reached_summary_prompt (line 452) | def handle_max_turns_reached_summary_prompt(self, message_history, sum...

FILE: miroflow/llm/openai_client.py
  class UnifiedOpenAIClient (line 30) | class UnifiedOpenAIClient(LLMClientBase):
    method __init__ (line 47) | def __init__(self, cfg: DictConfig):
    method _create_client (line 58) | def _create_client(self, config: DictConfig):
    method _create_message (line 81) | async def _create_message(
    method _decide_tool_mode (line 158) | def _decide_tool_mode(self, tools_definitions) -> str:
    method _is_oai_new_model (line 177) | def _is_oai_new_model(self) -> bool:
    method _inject_system_prompt (line 188) | def _inject_system_prompt(
    method _build_messages (line 210) | def _build_messages(
    method _build_params (line 234) | def _build_params(
    method _create_completion (line 278) | async def _create_completion(self, params: Dict[str, Any], is_async: b...
    method _handle_oai_tool_thinking (line 284) | async def _handle_oai_tool_thinking(
    method _validate_response_or_raise (line 319) | def _validate_response_or_raise(self, response, params: Dict[str, Any]...
    method _maybe_raise_context_limit (line 340) | def _maybe_raise_context_limit(self, e: Exception) -> None:
    method _clean_user_content_from_response (line 357) | def _clean_user_content_from_response(self, text: str) -> str:
    method process_llm_response (line 365) | def process_llm_response(self, llm_response) -> Tuple[str, bool, dict]:
    method extract_tool_calls_info (line 435) | def extract_tool_calls_info(self, llm_response, assistant_response_text):
    method update_message_history (line 461) | def update_message_history(
    method parse_llm_response (line 543) | def parse_llm_response(self, llm_response) -> str:
    method _estimate_tokens (line 548) | def _estimate_tokens(self, text: str) -> int:
    method handle_max_turns_reached_summary_prompt (line 561) | def handle_max_turns_reached_summary_prompt(self, message_history, sum...
    method _apply_cache_control (line 572) | def _apply_cache_control(self, messages):

FILE: miroflow/llm/openrouter.py
  class OpenRouterClient (line 41) | class OpenRouterClient(LLMClientBase):
    method __init__ (line 42) | def __init__(self, cfg: DictConfig):
    method _create_client (line 54) | def _create_client(self, config: DictConfig):
    method _create_message (line 74) | async def _create_message(
    method _create_completion (line 248) | async def _create_completion(self, params: Dict[str, Any], is_async: b...
    method _clean_user_content_from_response (line 255) | def _clean_user_content_from_response(self, text: str) -> str:
    method process_llm_response (line 263) | def process_llm_response(self, llm_response) -> tuple[str, bool, dict]:
    method extract_tool_calls_info (line 344) | def extract_tool_calls_info(self, llm_response, assistant_response_text):
    method update_message_history (line 358) | def update_message_history(
    method get_user_msg_from_tool_call (line 419) | def get_user_msg_from_tool_call(self, tool_call_info, tool_calls_excee...
    method parse_llm_response (line 473) | def parse_llm_response(self, llm_response) -> str:
    method _estimate_tokens (line 479) | def _estimate_tokens(self, text: str) -> int:
    method handle_max_turns_reached_summary_prompt (line 495) | def handle_max_turns_reached_summary_prompt(self, message_history, sum...
    method _apply_cache_control (line 507) | def _apply_cache_control(self, messages):

FILE: miroflow/llm/util.py
  function with_timeout (line 12) | def with_timeout(

FILE: miroflow/logging/decorators.py
  function _default_span_name (line 24) | def _default_span_name(func: Callable[..., Any], args: tuple[Any, ...]) ...
  function span (line 31) | def span(
  function span_decorator (line 166) | def span_decorator(*args, **kwargs):

FILE: miroflow/logging/span.py
  function new_id (line 13) | def new_id(prefix: str = "") -> str:
  class Span (line 19) | class Span:
    method end (line 33) | def end(self) -> None:
    method duration_ms (line 37) | def duration_ms(self) -> Optional[int]:

FILE: miroflow/logging/task_tracer.py
  function utc_iso (line 24) | def utc_iso(ts: Optional[float] = None) -> str:
  function _ensure_jsonable (line 31) | def _ensure_jsonable(x: Any) -> Any:
  class TaskContextVar (line 49) | class TaskContextVar:
    method __repr__ (line 54) | def __repr__(self) -> str:
  function set_current_task_context_var (line 66) | def set_current_task_context_var(task_context_var: TaskContextVar):
  function reset_current_task_context_var (line 70) | def reset_current_task_context_var(token):
  function get_current_task_context_var (line 74) | def get_current_task_context_var() -> TaskContextVar:
  class TaskMeta (line 83) | class TaskMeta(BaseModel):
  class AgentStateEntry (line 110) | class AgentStateEntry(BaseModel):
  class TaskLogFile (line 115) | class TaskLogFile(BaseModel):
  class TaskTracer (line 129) | class TaskTracer:
    method __init__ (line 134) | def __init__(self, log_path: str | Path = "./logs"):
    method set_log_path (line 153) | def set_log_path(self, log_path: Path | str) -> None:
    method _get_context_key (line 160) | def _get_context_key(self) -> str:
    method _get_or_create_log (line 165) | def _get_or_create_log(self, key: str) -> TaskLogFile:
    method _flush_to_disk (line 174) | def _flush_to_disk(self, key: str, log_obj: TaskLogFile):
    method flush (line 196) | def flush(self):
    method start (line 219) | def start(self) -> None:
    method finish (line 230) | def finish(
    method update_task_meta (line 263) | def update_task_meta(self, patch: Dict[str, Any]) -> None:
    method save_agent_states (line 273) | def save_agent_states(self, node_name: str, states: Dict[str, Any]) ->...
    method set_current_span (line 283) | def set_current_span(self, current_span: Span) -> None:
    method append_step_event (line 295) | def append_step_event(self, event: Dict[str, Any]) -> None:
    method log (line 314) | def log(
    method debug (line 340) | def debug(self, msg: str, **kwargs) -> None:
    method info (line 343) | def info(self, msg: str, **kwargs) -> None:
    method warning (line 346) | def warning(self, msg: str, **kwargs) -> None:
    method error (line 349) | def error(self, msg: str, **kwargs) -> None:
  function set_tracer (line 361) | def set_tracer(log_path: Path):
  function get_tracer (line 370) | def get_tracer() -> TaskTracer:

FILE: miroflow/logging/tool_logging.py
  function _find_available_port (line 7) | def _find_available_port(
  function _extract_port_from_address (line 23) | def _extract_port_from_address(addr: str) -> int:

FILE: miroflow/registry.py
  class ComponentType (line 29) | class ComponentType(str, Enum):
  function _lazy_import_modules (line 62) | def _lazy_import_modules(component_type: ComponentType):
  function register (line 87) | def register(component_type: ComponentType, name: str) -> Callable[[Type...
  function get_registered_components (line 110) | def get_registered_components(component_type: ComponentType) -> Dict[str...
  function get_component_class (line 116) | def get_component_class(component_type: ComponentType, name: str) -> Type:
  function register_module (line 131) | def register_module(name: str) -> Callable[[Type], Type]:
  function get_registered_modules (line 160) | def get_registered_modules() -> Dict[str, Type]:
  function safe_get_module_class (line 171) | def safe_get_module_class(cls_name: str) -> Type:

FILE: miroflow/skill/manager.py
  class SkillMeta (line 13) | class SkillMeta:
  class SkillError (line 21) | class SkillError(Exception):
  function _parse_frontmatter (line 28) | def _parse_frontmatter(md_text: str) -> Tuple[Dict[str, Any], str]:
  class SkillManager (line 89) | class SkillManager:
    method __init__ (line 90) | def __init__(
    method get_all_skills_definitions (line 106) | def get_all_skills_definitions(self) -> List[SkillMeta]:
    method discover (line 133) | def discover(self) -> Dict[str, SkillMeta]:
    method list (line 170) | def list(self) -> List[SkillMeta]:
    method get (line 173) | def get(self, skill_id: str) -> SkillMeta:
    method load (line 178) | def load(self, skill_id: str) -> str:
    method execute_skill_command (line 195) | def execute_skill_command(self, skill_id: str, run_command: str) -> Di...
    method execute_skill_calls_batch (line 198) | async def execute_skill_calls_batch(

FILE: miroflow/tool/factory.py
  function get_mcp_server_configs_from_tool_cfg_paths (line 18) | def get_mcp_server_configs_from_tool_cfg_paths(

FILE: miroflow/tool/manager.py
  function update_server_params_with_context_var (line 31) | def update_server_params_with_context_var(
  function with_timeout (line 45) | def with_timeout(timeout_s: float = 300.0):
  class ToolManager (line 65) | class ToolManager:
    method __init__ (line 66) | def __init__(
    method _is_huggingface_dataset_or_space_url (line 94) | def _is_huggingface_dataset_or_space_url(self, url):
    method _should_block_hf_scraping (line 104) | def _should_block_hf_scraping(self, tool_name, arguments):
    method get_server_params (line 117) | def get_server_params(self, server_name):
    method _find_servers_with_tool (line 121) | async def _find_servers_with_tool(self, tool_name):
    method get_all_tool_definitions (line 182) | async def get_all_tool_definitions(self) -> list[dict]:
    method execute_tool_call (line 267) | async def execute_tool_call(self, server_name, tool_name, arguments) -...
    method execute_tool_calls_batch (line 531) | async def execute_tool_calls_batch(
    method format_tool_results (line 572) | def format_tool_results(self, results):

FILE: miroflow/tool/mcp_servers/audio_mcp_server.py
  function _get_audio_extension (line 32) | def _get_audio_extension(url: str, content_type: str = None) -> str:
  function _get_audio_duration (line 73) | def _get_audio_duration(audio_path: str) -> float:
  function _encode_audio_file (line 105) | def _encode_audio_file(audio_path: str) -> tuple[str, str]:
  function audio_transcription (line 130) | async def audio_transcription(audio_path_or_url: str) -> str:
  function audio_question_answering (line 201) | async def audio_question_answering(audio_path_or_url: str, question: str...

FILE: miroflow/tool/mcp_servers/audio_mcp_server_os.py
  function _get_audio_extension (line 37) | def _get_audio_extension(url: str, content_type: str = None) -> str:
  function _get_audio_duration (line 78) | def _get_audio_duration(audio_path: str) -> float:
  function _encode_audio_file (line 110) | def _encode_audio_file(audio_path: str) -> tuple[str, str]:
  function audio_transcription (line 135) | async def audio_transcription(audio_path_or_url: str) -> str:

FILE: miroflow/tool/mcp_servers/browser_session.py
  class PlaywrightSession (line 14) | class PlaywrightSession:
    method __init__ (line 17) | def __init__(self, server_params):
    method connect (line 24) | async def connect(self):
    method call_tool (line 37) | async def call_tool(self, tool_name, arguments=None):
    method close (line 47) | async def close(self):
  function test_persistent_session (line 62) | async def test_persistent_session():

FILE: miroflow/tool/mcp_servers/code_sandbox.py
  function looks_like_dir (line 66) | def looks_like_dir(path: str) -> bool:
  function truncate_result (line 79) | def truncate_result(result: str) -> str:
  function create_sandbox (line 95) | async def create_sandbox(timeout: int = DEFAULT_TIMEOUT) -> str:
  function run_command (line 135) | async def run_command(command: str, sandbox_id: str) -> str:
  function run_python_code (line 181) | async def run_python_code(code_block: str, sandbox_id: str) -> str:
  function upload_file_from_local_to_sandbox (line 220) | async def upload_file_from_local_to_sandbox(
  function download_file_from_internet_to_sandbox (line 280) | async def download_file_from_internet_to_sandbox(
  function download_file_from_sandbox_to_local (line 368) | async def download_file_from_sandbox_to_local(

FILE: miroflow/tool/mcp_servers/jina_scrape.py
  function scrape_and_extract_info (line 29) | async def scrape_and_extract_info(
  function _is_huggingface_dataset_or_space_url (line 123) | def _is_huggingface_dataset_or_space_url(url):
  function scrape_url_with_jina (line 134) | async def scrape_url_with_jina(
  function scrape_url_with_python (line 372) | async def scrape_url_with_python(
  function get_prompt_with_truncation (line 578) | def get_prompt_with_truncation(
  function extract_info_with_llm (line 589) | async def extract_info_with_llm(

FILE: miroflow/tool/mcp_servers/miroapi_serper_mcp_server.py
  function make_serper_request (line 49) | def make_serper_request(
  function _is_huggingface_dataset_or_space_url (line 58) | def _is_huggingface_dataset_or_space_url(url):
  function google_search (line 70) | def google_search(

FILE: miroflow/tool/mcp_servers/reading_mcp_server.py
  function read_file (line 24) | async def read_file(uri: str) -> str:

FILE: miroflow/tool/mcp_servers/reasoning_mcp_server.py
  function reasoning (line 27) | async def reasoning(question: str) -> str:

FILE: miroflow/tool/mcp_servers/reasoning_mcp_server_os.py
  function post_with_retry (line 38) | def post_with_retry(url, json, headers):
  function reasoning (line 68) | async def reasoning(question: str) -> str:

FILE: miroflow/tool/mcp_servers/scrape_website_v1.py
  function smart_split_content (line 100) | def smart_split_content(text: str, chunk_size: int, overlap: int) -> Lis...
  function _is_huggingface_dataset_or_space_url (line 148) | def _is_huggingface_dataset_or_space_url(url: str) -> bool:
  function check_content_quality (line 155) | def check_content_quality(text: str) -> Dict[str, Any]:
  function get_content_score (line 183) | def get_content_score(res: Dict[str, Any], query: str = "") -> int:
  function get_prompt_with_truncation (line 281) | def get_prompt_with_truncation(
  function scrape_url_with_jina (line 299) | async def scrape_url_with_jina(
  function scrape_url_with_firecrawl (line 489) | async def scrape_url_with_firecrawl(
  function scrape_url_with_playwright (line 606) | async def scrape_url_with_playwright(
  function scrape_url_with_python (line 703) | async def scrape_url_with_python(
  function call_robust_llm (line 754) | async def call_robust_llm(
  function scrape_and_extract_info (line 889) | async def scrape_and_extract_info(

FILE: miroflow/tool/mcp_servers/searching_mcp_server.py
  function filter_google_search_result (line 43) | def filter_google_search_result(result_content: str) -> str:
  function google_search (line 87) | async def google_search(
  function wiki_get_page_content (line 174) | async def wiki_get_page_content(entity: str, first_sentences: int = 10) ...
  function search_wiki_revision (line 283) | async def search_wiki_revision(
  function search_archived_webpage (line 447) | async def search_archived_webpage(url: str, year: int, month: int, day: ...
  function scrape_website (line 679) | async def scrape_website(url: str) -> str:

FILE: miroflow/tool/mcp_servers/serper_search.py
  function make_serper_request (line 50) | async def make_serper_request(
  function _is_huggingface_dataset_or_space_url (line 64) | def _is_huggingface_dataset_or_space_url(url):
  function google_search (line 76) | async def google_search(

FILE: miroflow/tool/mcp_servers/serper_sogou_search.py
  function _get_sogou_semaphore (line 46) | def _get_sogou_semaphore() -> asyncio.Semaphore:
  function _contains_chinese (line 58) | def _contains_chinese(text: str) -> bool:
  function _normalize_url (line 63) | def _normalize_url(url: str) -> str:
  function _clean_sogou_query (line 76) | def _clean_sogou_query(query: str) -> str:
  function _dedup_and_interleave (line 83) | def _dedup_and_interleave(serper_results: list, sogou_results: list) -> ...
  function make_serper_request (line 108) | async def make_serper_request(
  function _is_huggingface_dataset_or_space_url (line 122) | def _is_huggingface_dataset_or_space_url(url):
  function _sogou_search_sync (line 133) | def _sogou_search_sync(query: str, num_results: int = 10) -> list:
  function _sogou_search_async (line 194) | async def _sogou_search_async(query: str, num_results: int = 10) -> list:
  function _serper_search (line 204) | async def _serper_search(
  function google_search (line 266) | async def google_search(

FILE: miroflow/tool/mcp_servers/utils/smart_request.py
  function request_to_json (line 18) | def request_to_json(content: str) -> dict:
  function smart_request (line 25) | async def smart_request(url: str, params: dict = None, env: dict = None)...
  function scrape_jina (line 108) | async def scrape_jina(
  function scrape_serper (line 156) | async def scrape_serper(url: str, serper_api_key: str) -> tuple[str, str]:
  function scrape_request (line 187) | def scrape_request(url: str) -> tuple[str, str]:

FILE: miroflow/tool/mcp_servers/utils/url_unquote.py
  function safe_unquote (line 45) | def safe_unquote(url: str) -> str:
  function decode_http_urls_in_dict (line 105) | def decode_http_urls_in_dict(data):
  function strip_markdown_links (line 129) | def strip_markdown_links(markdown: str) -> str:

FILE: miroflow/tool/mcp_servers/vision_mcp_server.py
  function detect_image_format (line 38) | async def detect_image_format(file_path: str) -> str:
  function guess_mime_media_type_from_extension (line 56) | async def guess_mime_media_type_from_extension(file_path: str) -> str:
  function call_claude_vision (line 72) | async def call_claude_vision(image_path_or_url: str, question: str) -> str:
  function call_openai_vision (line 147) | async def call_openai_vision(image_path_or_url: str, question: str) -> str:
  function call_gemini_vision (line 196) | async def call_gemini_vision(image_path_or_url: str, question: str) -> str:
  function visual_question_answering (line 285) | async def visual_question_answering(image_path_or_url: str, question: st...
  function visual_audio_youtube_analyzing (line 355) | async def visual_audio_youtube_analyzing(

FILE: miroflow/tool/mcp_servers/vision_mcp_server_os.py
  function guess_mime_media_type_from_extension (line 30) | def guess_mime_media_type_from_extension(file_path: str) -> str:
  function visual_question_answering (line 45) | async def visual_question_answering(image_path_or_url: str, question: st...

FILE: miroflow/utils/file_content_utils.py
  function _generate_image_caption (line 52) | def _generate_image_caption(
  function _generate_audio_caption (line 125) | def _generate_audio_caption(
  function _generate_video_caption (line 165) | def _generate_video_caption(
  function _extract_task_relevant_info_from_image (line 238) | def _extract_task_relevant_info_from_image(
  function _extract_task_relevant_info_from_audio (line 317) | def _extract_task_relevant_info_from_audio(
  function _extract_task_relevant_info_from_video (line 398) | def _extract_task_relevant_info_from_video(
  class _CustomMarkdownify (line 477) | class _CustomMarkdownify(markdownify.MarkdownConverter):
    method __init__ (line 487) | def __init__(self, **options: Any):
    method convert_hn (line 491) | def convert_hn(self, n: int, el: Any, text: str, convert_as_inline: bo...
    method convert_a (line 499) | def convert_a(self, el: Any, text: str, convert_as_inline: bool):
    method convert_img (line 541) | def convert_img(self, el: Any, text: str, convert_as_inline: bool) -> ...
    method convert_soup (line 560) | def convert_soup(self, soup: Any) -> str:
  class DocumentConverterResult (line 564) | class DocumentConverterResult:
    method __init__ (line 567) | def __init__(self, title: Union[str, None] = None, text_content: str =...
  function _convert_html_to_md (line 572) | def _convert_html_to_md(html_content: str) -> DocumentConverterResult:
  function _html_converter (line 602) | def _html_converter(local_path: str) -> DocumentConverterResult:
  function _docx_converter (line 617) | def _docx_converter(local_path: str) -> DocumentConverterResult:
  function _xlsx_converter (line 636) | def _xlsx_converter(local_path: str) -> DocumentConverterResult:
  function _pptx_converter (line 881) | def _pptx_converter(local_path: str) -> DocumentConverterResult:
  function _zip_converter (line 980) | def _zip_converter(
  function process_file_content (line 1146) | def process_file_content(

FILE: miroflow/utils/io_utils.py
  function get_file_type (line 12) | def get_file_type(file_name: str) -> str:
  function process_input (line 34) | def process_input(task_description, task_file_name):
  class OutputFormatter (line 89) | class OutputFormatter:
    method _extract_boxed_content (line 90) | def _extract_boxed_content(self, text: str) -> str:
    method format_final_summary_and_log (line 139) | def format_final_summary_and_log(self, final_answer_text, client=None):

FILE: miroflow/utils/parsing_utils.py
  function _smart_json_truncate (line 15) | def _smart_json_truncate(json_str):
  function _fix_unterminated_string_values (line 65) | def _fix_unterminated_string_values(json_str):
  function preprocess_json_string (line 159) | def preprocess_json_string(json_str):
  function robust_json_loads (line 185) | def robust_json_loads(json_str, apply_preprocessing=True):
  function escape_string_content (line 220) | def escape_string_content(content, key_name=None):
  function fix_python_syntax (line 287) | def fix_python_syntax(content):
  function fix_shell_syntax (line 306) | def fix_shell_syntax(content):
  function fix_json_syntax (line 324) | def fix_json_syntax(content):
  function parse_escaped_json_string (line 337) | def parse_escaped_json_string(raw_str):
  function _try_direct_parse (line 382) | def _try_direct_parse(raw_str):
  function _try_line_start_pattern (line 391) | def _try_line_start_pattern(raw_str):
  function _try_negative_lookbehind_pattern (line 396) | def _try_negative_lookbehind_pattern(raw_str):
  function _try_legacy_method (line 401) | def _try_legacy_method(raw_str):
  function _try_parse_with_pattern (line 411) | def _try_parse_with_pattern(raw_str, pattern):
  function _find_value_end_position (line 482) | def _find_value_end_position(raw_str, start_pos, search_limit):
  function _legacy_escape_method (line 496) | def _legacy_escape_method(raw_str):
  function _escape_for_json (line 546) | def _escape_for_json(value: str) -> str:
  function _conservative_escape_fallback (line 556) | def _conservative_escape_fallback(raw_str):
  function parse_llm_response_for_tool_calls (line 581) | def parse_llm_response_for_tool_calls(llm_response_content_text):
  function main (line 802) | def main():

FILE: miroflow/utils/prepare_benchmark/common.py
  class Task (line 11) | class Task:
    method to_json (line 20) | def to_json(self) -> bytes:
    method from_json (line 24) | def from_json(cls, b: bytes):

FILE: miroflow/utils/prepare_benchmark/gen_browsecomp.py
  function derive_key (line 20) | def derive_key(password: str, length: int) -> bytes:
  function decrypt (line 28) | def decrypt(ciphertext_b64: str, password: str) -> str:
  function gen_browsecomp_test (line 36) | def gen_browsecomp_test(hf_token: str) -> Generator[Task, None, None]:
  function gen_browsecomp_zh_test (line 58) | def gen_browsecomp_zh_test(hf_token: str) -> Generator[Task, None, None]:

FILE: miroflow/utils/prepare_benchmark/gen_finsearchcomp.py
  function gen_finsearchcomp (line 12) | def gen_finsearchcomp(hf_token: str) -> Generator[Task, None, None]:

FILE: miroflow/utils/prepare_benchmark/gen_frames.py
  function gen_frames_test (line 12) | def gen_frames_test(hf_token: str) -> Generator[Task, None, None]:

FILE: miroflow/utils/prepare_benchmark/gen_futurex.py
  function gen_futurex (line 12) | def gen_futurex(hf_token: str) -> Generator[Task, None, None]:

FILE: miroflow/utils/prepare_benchmark/gen_gaia.py
  function download_file (line 15) | def download_file(hf_token: str, file_path: str, data_dir: str, task_id:...
  function gen_gaia_validation (line 60) | def gen_gaia_validation(hf_token: str, data_dir: str) -> Generator[Task,...

FILE: miroflow/utils/prepare_benchmark/gen_gaia_text_only.py
  function gen_gaia_text_only (line 17) | def gen_gaia_text_only() -> Generator[Task, None, None]:

FILE: miroflow/utils/prepare_benchmark/gen_hle.py
  function save_image (line 15) | def save_image(image, data_dir: str, task_id: str) -> str:
  function gen_hle_test (line 68) | def gen_hle_test(hf_token: str, data_dir: str) -> Generator[Task, None, ...

FILE: miroflow/utils/prepare_benchmark/gen_hle_text_only.py
  function gen_hle_text_only (line 14) | def gen_hle_text_only(hf_token: str) -> Generator[Task, None, None]:

FILE: miroflow/utils/prepare_benchmark/gen_webwalkerqa.py
  function gen_webwalkerqa (line 12) | def gen_webwalkerqa(hf_token: str) -> Generator[Task, None, None]:

FILE: miroflow/utils/prepare_benchmark/gen_xbench_ds.py
  function xor_decrypt (line 13) | def xor_decrypt(data, key):
  function gen_xbench_ds (line 22) | def gen_xbench_ds(hf_token: str) -> Generator[Task, None, None]:

FILE: miroflow/utils/prepare_benchmark/main.py
  class _Env (line 27) | class _Env:
    method from_dotenv (line 46) | def from_dotenv(cls):
  function _prepare_filesystem (line 57) | def _prepare_filesystem(env: _Env):
  function _prepare_dataset (line 65) | def _prepare_dataset(env: _Env, dataset: str):
  function rm (line 143) | def rm():
  function ls (line 155) | def ls():
  function get (line 171) | def get(dataset: str):

FILE: miroflow/utils/prompt_utils.py
  class PromptManager (line 5) | class PromptManager:
    method __init__ (line 6) | def __init__(self, config_path: str = None):
    method from_config (line 23) | def from_config(cls, cfg, instance=None):
    method _validate_required_context (line 40) | def _validate_required_context(
    method _render_components (line 51) | def _render_components(
    method render_prompt (line 76) | def render_prompt(self, prompt_name: str, context: dict) -> str:
    method render_prompt_component (line 88) | def render_prompt_component(

FILE: miroflow/utils/summary_utils.py
  function _generate_message_id (line 13) | def _generate_message_id() -> str:
  function _reraise_with_log (line 19) | def _reraise_with_log(retry_state):
  function extract_hints (line 34) | async def extract_hints(
  function get_gaia_answer_type (line 91) | async def get_gaia_answer_type(task_description: str, llm_client: LLMCli...
  function extract_gaia_final_answer (line 128) | async def extract_gaia_final_answer(
  function extract_browsecomp_zh_final_answer (line 440) | async def extract_browsecomp_zh_final_answer(  # TODO Gaia is implemente...

FILE: miroflow/utils/tool_utils.py
  function _load_agent_prompt_class (line 12) | def _load_agent_prompt_class(prompt_class_name: str):
  function expose_sub_agents_as_tools (line 50) | def expose_sub_agents_as_tools(sub_agent_names):
  function format_tool_result (line 84) | def format_tool_result(tool_call_execution_result):

FILE: scripts/benchmark/check_progress/check_progress_browsecomp-en-200.py
  function create_progress_bar (line 42) | def create_progress_bar(percentage: float, width: int = PROGRESS_BAR_WID...
  function parse_task_filename (line 60) | def parse_task_filename(filename: str) -> Optional[Tuple[str, int, int]]:
  function parse_timestamp (line 73) | def parse_timestamp(time_str: str) -> Optional[datetime]:
  function format_duration (line 86) | def format_duration(minutes: float) -> str:
  class RetryResult (line 99) | class RetryResult:
  class AttemptResult (line 113) | class AttemptResult:
  class TaskResult (line 125) | class TaskResult:
  class RunStats (line 143) | class RunStats:
    method accuracy (line 184) | def accuracy(self) -> float:
    method avg_turns (line 188) | def avg_turns(self) -> float:
  function find_task_files (line 196) | def find_task_files(log_folder: Path) -> Dict[str, Dict[str, List[Path]]]:
  function load_task_meta_fast (line 225) | def load_task_meta_fast(file_path: Path) -> Optional[Dict[str, Any]]:
  function count_turns_fast (line 275) | def count_turns_fast(file_path: Path) -> int:
  function analyze_task_attempts (line 297) | def analyze_task_attempts(task_id: str, attempt_files: List[Path]) -> Ta...
  function _analyze_task_wrapper (line 389) | def _analyze_task_wrapper(args: Tuple[str, List[Path]]) -> TaskResult:
  function analyze_run (line 395) | def analyze_run(task_files: Dict[str, List[Path]], parallel: bool = True...
  function display_run_summary (line 486) | def display_run_summary(run_id: str, stats: RunStats) -> None:
  function display_overall_summary (line 499) | def display_overall_summary(all_results: Dict[str, RunStats], num_runs: ...
  function main (line 642) | def main():

FILE: scripts/benchmark/check_progress/check_progress_browsecomp-en.py
  function create_progress_bar (line 42) | def create_progress_bar(percentage: float, width: int = PROGRESS_BAR_WID...
  function parse_task_filename (line 60) | def parse_task_filename(filename: str) -> Optional[Tuple[str, int, int]]:
  function parse_timestamp (line 73) | def parse_timestamp(time_str: str) -> Optional[datetime]:
  function format_duration (line 86) | def format_duration(minutes: float) -> str:
  class RetryResult (line 99) | class RetryResult:
  class AttemptResult (line 113) | class AttemptResult:
  class TaskResult (line 125) | class TaskResult:
  class RunStats (line 143) | class RunStats:
    method accuracy (line 184) | def accuracy(self) -> float:
    method avg_turns (line 188) | def avg_turns(self) -> float:
  function find_task_files (line 196) | def find_task_files(log_folder: Path) -> Dict[str, Dict[str, List[Path]]]:
  function load_task_meta_fast (line 225) | def load_task_meta_fast(file_path: Path) -> Optional[Dict[str, Any]]:
  function count_turns_fast (line 275) | def count_turns_fast(file_path: Path) -> int:
  function analyze_task_attempts (line 297) | def analyze_task_attempts(task_id: str, attempt_files: List[Path]) -> Ta...
  function _analyze_task_wrapper (line 389) | def _analyze_task_wrapper(args: Tuple[str, List[Path]]) -> TaskResult:
  function analyze_run (line 395) | def analyze_run(task_files: Dict[str, List[Path]], parallel: bool = True...
  function display_run_summary (line 486) | def display_run_summary(run_id: str, stats: RunStats) -> None:
  function display_overall_summary (line 499) | def display_overall_summary(all_results: Dict[str, RunStats], num_runs: ...
  function main (line 642) | def main():

FILE: scripts/benchmark/check_progress/check_progress_browsecomp-zh.py
  function create_progress_bar (line 42) | def create_progress_bar(percentage: float, width: int = PROGRESS_BAR_WID...
  function parse_task_filename (line 60) | def parse_task_filename(filename: str) -> Optional[Tuple[str, int, int]]:
  function parse_timestamp (line 73) | def parse_timestamp(time_str: str) -> Optional[datetime]:
  function format_duration (line 86) | def format_duration(minutes: float) -> str:
  class RetryResult (line 99) | class RetryResult:
  class AttemptResult (line 113) | class AttemptResult:
  class TaskResult (line 125) | class TaskResult:
  class RunStats (line 143) | class RunStats:
    method accuracy (line 184) | def accuracy(self) -> float:
    method avg_turns (line 188) | def avg_turns(self) -> float:
  function find_task_files (line 196) | def find_task_files(log_folder: Path) -> Dict[str, Dict[str, List[Path]]]:
  function load_task_meta_fast (line 225) | def load_task_meta_fast(file_path: Path) -> Optional[Dict[str, Any]]:
  function count_turns_fast (line 275) | def count_turns_fast(file_path: Path) -> int:
  function analyze_task_attempts (line 297) | def analyze_task_attempts(task_id: str, attempt_files: List[Path]) -> Ta...
  function _analyze_task_wrapper (line 390) | def _analyze_task_wrapper(args: Tuple[str, List[Path]]) -> TaskResult:
  function analyze_run (line 396) | def analyze_run(task_files: Dict[str, List[Path]], parallel: bool = True...
  function display_run_summary (line 487) | def display_run_summary(run_id: str, stats: RunStats) -> None:
  function display_overall_summary (line 501) | def display_overall_summary(all_results: Dict[str, RunStats], num_runs: ...
  function main (line 644) | def main():

FILE: scripts/benchmark/check_progress/check_progress_frames-test.py
  function create_progress_bar (line 42) | def create_progress_bar(percentage: float, width: int = PROGRESS_BAR_WID...
  function parse_task_filename (line 60) | def parse_task_filename(filename: str) -> Optional[Tuple[str, int, int]]:
  function parse_timestamp (line 73) | def parse_timestamp(time_str: str) -> Optional[datetime]:
  function format_duration (line 86) | def format_duration(minutes: float) -> str:
  class RetryResult (line 99) | class RetryResult:
  class AttemptResult (line 113) | class AttemptResult:
  class TaskResult (line 125) | class TaskResult:
  class RunStats (line 143) | class RunStats:
    method accuracy (line 184) | def accuracy(self) -> float:
    method avg_turns (line 188) | def avg_turns(self) -> float:
  function find_task_files (line 196) | def find_task_files(log_folder: Path) -> Dict[str, Dict[str, List[Path]]]:
  function load_task_meta_fast (line 225) | def load_task_meta_fast(file_path: Path) -> Optional[Dict[str, Any]]:
  function count_turns_fast (line 275) | def count_turns_fast(file_path: Path) -> int:
  function analyze_task_attempts (line 297) | def analyze_task_attempts(task_id: str, attempt_files: List[Path]) -> Ta...
  function _analyze_task_wrapper (line 389) | def _analyze_task_wrapper(args: Tuple[str, List[Path]]) -> TaskResult:
  function analyze_run (line 395) | def analyze_run(task_files: Dict[str, List[Path]], parallel: bool = True...
  function display_run_summary (line 486) | def display_run_summary(run_id: str, stats: RunStats) -> None:
  function display_overall_summary (line 499) | def display_overall_summary(all_results: Dict[str, RunStats], num_runs: ...
  function main (line 642) | def main():

FILE: scripts/benchmark/check_progress/check_progress_gaia-validation-165.py
  function create_progress_bar (line 42) | def create_progress_bar(percentage: float, width: int = PROGRESS_BAR_WID...
  function parse_task_filename (line 60) | def parse_task_filename(filename: str) -> Optional[Tuple[str, int, int]]:
  function parse_timestamp (line 73) | def parse_timestamp(time_str: str) -> Optional[datetime]:
  function format_duration (line 86) | def format_duration(minutes: float) -> str:
  class RetryResult (line 99) | class RetryResult:
  class AttemptResult (line 113) | class AttemptResult:
  class TaskResult (line 125) | class TaskResult:
  class RunStats (line 143) | class RunStats:
    method accuracy (line 184) | def accuracy(self) -> float:
    method avg_turns (line 188) | def avg_turns(self) -> float:
  function find_task_files (line 196) | def find_task_files(log_folder: Path) -> Dict[str, Dict[str, List[Path]]]:
  function load_task_meta_fast (line 225) | def load_task_meta_fast(file_path: Path) -> Optional[Dict[str, Any]]:
  function count_turns_fast (line 275) | def count_turns_fast(file_path: Path) -> int:
  function analyze_task_attempts (line 297) | def analyze_task_attempts(task_id: str, attempt_files: List[Path]) -> Ta...
  function _analyze_task_wrapper (line 389) | def _analyze_task_wrapper(args: Tuple[str, List[Path]]) -> TaskResult:
  function analyze_run (line 395) | def analyze_run(task_files: Dict[str, List[Path]], parallel: bool = True...
  function display_run_summary (line 486) | def display_run_summary(run_id: str, stats: RunStats) -> None:
  function display_overall_summary (line 499) | def display_overall_summary(all_results: Dict[str, RunStats], num_runs: ...
  function main (line 642) | def main():

FILE: scripts/benchmark/check_progress/check_progress_gaia-validation-text-103.py
  function create_progress_bar (line 42) | def create_progress_bar(percentage: float, width: int = PROGRESS_BAR_WID...
  function parse_task_filename (line 60) | def parse_task_filename(filename: str) -> Optional[Tuple[str, int, int]]:
  function parse_timestamp (line 73) | def parse_timestamp(time_str: str) -> Optional[datetime]:
  function format_duration (line 86) | def format_duration(minutes: float) -> str:
  class RetryResult (line 99) | class RetryResult:
  class AttemptResult (line 113) | class AttemptResult:
  class TaskResult (line 125) | class TaskResult:
  class RunStats (line 143) | class RunStats:
    method accuracy (line 184) | def accuracy(self) -> float:
    method avg_turns (line 188) | def avg_turns(self) -> float:
  function find_task_files (line 196) | def find_task_files(log_folder: Path) -> Dict[str, Dict[str, List[Path]]]:
  function load_task_meta_fast (line 225) | def load_task_meta_fast(file_path: Path) -> Optional[Dict[str, Any]]:
  function count_turns_fast (line 275) | def count_turns_fast(file_path: Path) -> int:
  function analyze_task_attempts (line 297) | def analyze_task_attempts(task_id: str, attempt_files: List[Path]) -> Ta...
  function _analyze_task_wrapper (line 389) | def _analyze_task_wrapper(args: Tuple[str, List[Path]]) -> TaskResult:
  function analyze_run (line 395) | def analyze_run(task_files: Dict[str, List[Path]], parallel: bool = True...
  function display_run_summary (line 486) | def display_run_summary(run_id: str, stats: RunStats) -> None:
  function display_overall_summary (line 499) | def display_overall_summary(all_results: Dict[str, RunStats], num_runs: ...
  function main (line 642) | def main():

FILE: scripts/benchmark/check_progress/check_progress_hle-text-only.py
  function create_progress_bar (line 42) | def create_progress_bar(percentage: float, width: int = PROGRESS_BAR_WID...
  function parse_task_filename (line 60) | def parse_task_filename(filename: str) -> Optional[Tuple[str, int, int]]:
  function parse_timestamp (line 73) | def parse_timestamp(time_str: str) -> Optional[datetime]:
  function format_duration (line 86) | def format_duration(minutes: float) -> str:
  class RetryResult (line 99) | class RetryResult:
  class AttemptResult (line 113) | class AttemptResult:
  class TaskResult (line 125) | class TaskResult:
  class RunStats (line 143) | class RunStats:
    method accuracy (line 184) | def accuracy(self) -> float:
    method avg_turns (line 188) | def avg_turns(self) -> float:
  function find_task_files (line 196) | def find_task_files(log_folder: Path) -> Dict[str, Dict[str, List[Path]]]:
  function load_task_meta_fast (line 225) | def load_task_meta_fast(file_path: Path) -> Optional[Dict[str, Any]]:
  function count_turns_fast (line 275) | def count_turns_fast(file_path: Path) -> int:
  function analyze_task_attempts (line 297) | def analyze_task_attempts(task_id: str, attempt_files: List[Path]) -> Ta...
  function _analyze_task_wrapper (line 389) | def _analyze_task_wrapper(args: Tuple[str, List[Path]]) -> TaskResult:
  function analyze_run (line 395) | def analyze_run(task_files: Dict[str, List[Path]], parallel: bool = True...
  function display_run_summary (line 486) | def display_run_summary(run_id: str, stats: RunStats) -> None:
  function display_overall_summary (line 499) | def display_overall_summary(all_results: Dict[str, RunStats], num_runs: ...
  function main (line 642) | def main():

FILE: scripts/benchmark/check_progress/check_progress_hle.py
  function create_progress_bar (line 42) | def create_progress_bar(percentage: float, width: int = PROGRESS_BAR_WID...
  function parse_task_filename (line 60) | def parse_task_filename(filename: str) -> Optional[Tuple[str, int, int]]:
  function parse_timestamp (line 73) | def parse_timestamp(time_str: str) -> Optional[datetime]:
  function format_duration (line 86) | def format_duration(minutes: float) -> str:
  class RetryResult (line 99) | class RetryResult:
  class AttemptResult (line 113) | class AttemptResult:
  class TaskResult (line 125) | class TaskResult:
  class RunStats (line 143) | class RunStats:
    method accuracy (line 184) | def accuracy(self) -> float:
    method avg_turns (line 188) | def avg_turns(self) -> float:
  function find_task_files (line 196) | def find_task_files(log_folder: Path) -> Dict[str, Dict[str, List[Path]]]:
  function load_task_meta_fast (line 225) | def load_task_meta_fast(file_path: Path) -> Optional[Dict[str, Any]]:
  function count_turns_fast (line 275) | def count_turns_fast(file_path: Path) -> int:
  function analyze_task_attempts (line 297) | def analyze_task_attempts(task_id: str, attempt_files: List[Path]) -> Ta...
  function _analyze_task_wrapper (line 389) | def _analyze_task_wrapper(args: Tuple[str, List[Path]]) -> TaskResult:
  function analyze_run (line 395) | def analyze_run(task_files: Dict[str, List[Path]], parallel: bool = True...
  function display_run_summary (line 486) | def display_run_summary(run_id: str, stats: RunStats) -> None:
  function display_overall_summary (line 499) | def display_overall_summary(all_results: Dict[str, RunStats], num_runs: ...
  function main (line 642) | def main():

FILE: scripts/benchmark/check_progress/check_progress_webwalkerqa.py
  function create_progress_bar (line 42) | def create_progress_bar(percentage: float, width: int = PROGRESS_BAR_WID...
  function parse_task_filename (line 60) | def parse_task_filename(filename: str) -> Optional[Tuple[str, int, int]]:
  function parse_timestamp (line 73) | def parse_timestamp(time_str: str) -> Optional[datetime]:
  function format_duration (line 86) | def format_duration(minutes: float) -> str:
  class RetryResult (line 99) | class RetryResult:
  class AttemptResult (line 113) | class AttemptResult:
  class TaskResult (line 125) | class TaskResult:
  class RunStats (line 143) | class RunStats:
    method accuracy (line 184) | def accuracy(self) -> float:
    method avg_turns (line 188) | def avg_turns(self) -> float:
  function find_task_files (line 196) | def find_task_files(log_folder: Path) -> Dict[str, Dict[str, List[Path]]]:
  function load_task_meta_fast (line 225) | def load_task_meta_fast(file_path: Path) -> Optional[Dict[str, Any]]:
  function count_turns_fast (line 275) | def count_turns_fast(file_path: Path) -> int:
  function analyze_task_attempts (line 297) | def analyze_task_attempts(task_id: str, attempt_files: List[Path]) -> Ta...
  function _analyze_task_wrapper (line 389) | def _analyze_task_wrapper(args: Tuple[str, List[Path]]) -> TaskResult:
  function analyze_run (line 395) | def analyze_run(task_files: Dict[str, List[Path]], parallel: bool = True...
  function display_run_summary (line 486) | def display_run_summary(run_id: str, stats: RunStats) -> None:
  function display_overall_summary (line 499) | def display_overall_summary(all_results: Dict[str, RunStats], num_runs: ...
  function main (line 642) | def main():

FILE: scripts/benchmark/check_progress/check_progress_xbench-ds.py
  function create_progress_bar (line 42) | def create_progress_bar(percentage: float, width: int = PROGRESS_BAR_WID...
  function parse_task_filename (line 60) | def parse_task_filename(filename: str) -> Optional[Tuple[str, int, int]]:
  function parse_timestamp (line 73) | def parse_timestamp(time_str: str) -> Optional[datetime]:
  function format_duration (line 86) | def format_duration(minutes: float) -> str:
  class RetryResult (line 99) | class RetryResult:
  class AttemptResult (line 113) | class AttemptResult:
  class TaskResult (line 125) | class TaskResult:
  class RunStats (line 143) | class RunStats:
    method accuracy (line 184) | def accuracy(self) -> float:
    method avg_turns (line 188) | def avg_turns(self) -> float:
  function find_task_files (line 196) | def find_task_files(log_folder: Path) -> Dict[str, Dict[str, List[Path]]]:
  function load_task_meta_fast (line 225) | def load_task_meta_fast(file_path: Path) -> Optional[Dict[str, Any]]:
  function count_turns_fast (line 275) | def count_turns_fast(file_path: Path) -> int:
  function analyze_task_attempts (line 297) | def analyze_task_attempts(task_id: str, attempt_files: List[Path]) -> Ta...
  function _analyze_task_wrapper (line 389) | def _analyze_task_wrapper(args: Tuple[str, List[Path]]) -> TaskResult:
  function analyze_run (line 395) | def analyze_run(task_files: Dict[str, List[Path]], parallel: bool = True...
  function display_run_summary (line 486) | def display_run_summary(run_id: str, stats: RunStats) -> None:
  function display_overall_summary (line 499) | def display_overall_summary(all_results: Dict[str, RunStats], num_runs: ...
  function main (line 642) | def main():

FILE: scripts/run_single_task.py
  function parse_task_from_json (line 28) | def parse_task_from_json(x: str) -> Task:
  function test_single_task (line 40) | def test_single_task(cfg: DictConfig, task: Task):
  function main (line 120) | def main():

FILE: web_app/api/dependencies.py
  function get_config (line 16) | def get_config() -> AppConfig:
  function get_session_manager (line 21) | def get_session_manager() -> SessionManager:
  function get_task_executor (line 29) | def get_task_executor() -> TaskExecutor:
  function init_dependencies (line 37) | def init_dependencies() -> None:

FILE: web_app/api/routes/configs.py
  function list_configs (line 17) | async def list_configs(

FILE: web_app/api/routes/health.py
  function health_check (line 13) | async def health_check() -> dict[str, str]:

FILE: web_app/api/routes/tasks.py
  function create_task (line 27) | async def create_task(
  function list_tasks (line 76) | async def list_tasks(
  function get_task (line 92) | async def get_task(
  function get_task_status (line 113) | async def get_task_status(
  function delete_task (line 160) | async def delete_task(

FILE: web_app/api/routes/uploads.py
  function upload_file (line 37) | async def upload_file(

FILE: web_app/core/config.py
  class AppConfig (line 13) | class AppConfig:
    method __post_init__ (line 68) | def __post_init__(self):

FILE: web_app/core/session_manager.py
  class SessionManager (line 17) | class SessionManager:
    method __init__ (line 20) | def __init__(self, sessions_dir: Path):
    method _get_session_path (line 25) | def _get_session_path(self, task_id: str) -> Path:
    method _read_session (line 29) | def _read_session(self, task_id: str) -> dict[str, Any] | None:
    method _write_session (line 38) | def _write_session(self, task_id: str, data: dict[str, Any]) -> None:
    method create_task (line 47) | def create_task(
    method get_task (line 77) | def get_task(self, task_id: str) -> TaskResponse | None:
    method list_tasks (line 84) | def list_tasks(
    method update_task (line 107) | def update_task(self, task_id: str, updates: dict[str, Any]) -> TaskRe...
    method delete_task (line 118) | def delete_task(self, task_id: str) -> bool:
    method task_exists (line 127) | def task_exists(self, task_id: str) -> bool:

FILE: web_app/core/task_executor.py
  class TaskExecutor (line 24) | class TaskExecutor:
    method __init__ (line 27) | def __init__(self, config: AppConfig, session_manager: SessionManager):
    method submit_task (line 34) | def submit_task(
    method _run_task_sync (line 50) | def _run_task_sync(
    method _run_task (line 60) | async def _run_task(
    method _get_all_messages_from_tracer (line 172) | def _get_all_messages_from_tracer(self, tracer: Any) -> list[dict]:
    method get_task_progress (line 190) | def get_task_progress(self, task_id: str) -> dict[str, Any]:
    method _format_recent_logs (line 239) | def _format_recent_logs(self, logs: list[dict]) -> list[dict]:
    method _format_messages (line 305) | def _format_messages(self, messages: list[dict]) -> list[dict]:
    method _truncate_output (line 350) | def _truncate_output(self, output: Any) -> Any:
    method cancel_task (line 358) | def cancel_task(self, task_id: str) -> bool:
    method is_task_running (line 371) | def is_task_running(self, task_id: str) -> bool:

FILE: web_app/frontend/src/App.tsx
  function App (line 9) | function App() {
  type ParsedContent (line 528) | interface ParsedContent {
  function parseMessageContent (line 534) | function parseMessageContent(content: string): ParsedContent {
  function ThinkingSection (line 610) | function ThinkingSection({ content, defaultExpanded = false }: { content...
  function SummaryHeader (line 641) | function SummaryHeader() {
  function CompletedView (line 651) | function CompletedView({
  function MessageBubble (line 763) | function MessageBubble({ role, content, isAnswer, fileInfo, isRunning }:...
  function SmartTextContent (line 822) | function SmartTextContent({ content }: { content: string }) {
  function ToolCallDisplay (line 922) | function ToolCallDisplay({ tool }: { tool: { name: string; args: string;...
  function LogItem (line 1103) | function LogItem({ log }: { log: Record<string, unknown> }) {

FILE: web_app/frontend/src/api/client.ts
  constant API_BASE_URL (line 3) | const API_BASE_URL = import.meta.env.VITE_API_URL || '';

FILE: web_app/frontend/src/api/tasks.ts
  function createTask (line 11) | async function createTask(data: TaskCreate): Promise<Task> {
  function listTasks (line 16) | async function listTasks(page = 1, pageSize = 20): Promise<TaskListRespo...
  function getTask (line 23) | async function getTask(taskId: string): Promise<Task> {
  function getTaskStatus (line 28) | async function getTaskStatus(taskId: string): Promise<TaskStatusUpdate> {
  function deleteTask (line 33) | async function deleteTask(taskId: string): Promise<void> {
  function listConfigs (line 37) | async function listConfigs(): Promise<ConfigListResponse> {
  function uploadFile (line 42) | async function uploadFile(file: File): Promise<UploadResponse> {

FILE: web_app/frontend/src/components/common/FileUpload.tsx
  type FileUploadProps (line 6) | interface FileUploadProps {
  function FileUpload (line 11) | function FileUpload({ onFileUploaded, uploadedFile }: FileUploadProps) {

FILE: web_app/frontend/src/components/common/LoadingSpinner.tsx
  type LoadingSpinnerProps (line 1) | interface LoadingSpinnerProps {
  function LoadingSpinner (line 5) | function LoadingSpinner({ size = 'md' }: LoadingSpinnerProps) {

FILE: web_app/frontend/src/components/common/MarkdownRenderer.tsx
  type MarkdownRendererProps (line 3) | interface MarkdownRendererProps {
  function MarkdownRenderer (line 7) | function MarkdownRenderer({ content }: MarkdownRendererProps) {

FILE: web_app/frontend/src/components/task/TaskForm.tsx
  type TaskFormProps (line 8) | interface TaskFormProps {
  function TaskForm (line 12) | function TaskForm({ onTaskCreated }: TaskFormProps) {

FILE: web_app/frontend/src/components/task/TaskHistory.tsx
  type TaskHistoryProps (line 6) | interface TaskHistoryProps {
  function truncateTitle (line 12) | function truncateTitle(title: string, maxTokens: number = 20): string {
  function formatTimestamp (line 18) | function formatTimestamp(dateStr: string): string {
  function TaskHistory (line 29) | function TaskHistory({ onSelectTask, selectedTaskId, refreshKey }: TaskH...
  function StatusIcon (line 97) | function StatusIcon({ status }: { status: string }) {

FILE: web_app/frontend/src/components/task/TaskStatus.tsx
  type TaskStatusProps (line 9) | interface TaskStatusProps {
  function TaskStatus (line 14) | function TaskStatus({ task, onStatusUpdate }: TaskStatusProps) {
  function MessageBubble (line 182) | function MessageBubble({ message }: { message: Message }) {
  function LogEntry (line 210) | function LogEntry({ log }: { log: Record<string, unknown> }) {
  function StatusBadge (line 322) | function StatusBadge({ status }: { status: string }) {

FILE: web_app/frontend/src/hooks/usePolling.ts
  type UsePollingOptions (line 3) | interface UsePollingOptions<T> {
  function usePolling (line 11) | function usePolling<T>({

FILE: web_app/frontend/src/types/task.ts
  type TaskStatus (line 1) | type TaskStatus = 'pending' | 'running' | 'completed' | 'failed' | 'canc...
  type FileInfo (line 3) | interface FileInfo {
  type Task (line 10) | interface Task {
  type TaskCreate (line 27) | interface TaskCreate {
  type Message (line 33) | interface Message {
  type TaskStatusUpdate (line 38) | interface TaskStatusUpdate {
  type TaskListResponse (line 50) | interface TaskListResponse {
  type ConfigListResponse (line 57) | interface ConfigListResponse {
  type UploadResponse (line 62) | interface UploadResponse {

FILE: web_app/frontend/src/vite-env.d.ts
  type ImportMetaEnv (line 3) | interface ImportMetaEnv {
  type ImportMeta (line 7) | interface ImportMeta {

FILE: web_app/main.py
  function lifespan (line 28) | async def lifespan(app: FastAPI):
  function root (line 73) | async def root():

FILE: web_app/models/task.py
  class FileInfo (line 16) | class FileInfo(BaseModel):
  class TaskCreate (line 25) | class TaskCreate(BaseModel):
  class TaskResponse (line 37) | class TaskResponse(BaseModel):
  class TaskListResponse (line 64) | class TaskListResponse(BaseModel):
  class Message (line 73) | class Message(BaseModel):
  class TaskStatusUpdate (line 80) | class TaskStatusUpdate(BaseModel):
  class UploadResponse (line 94) | class UploadResponse(BaseModel):
  class ConfigListResponse (line 103) | class ConfigListResponse(BaseModel):
Condensed preview — 296 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,660K chars).
[
  {
    "path": ".gitattributes",
    "chars": 297,
    "preview": "*.pdf filter=lfs diff=lfs merge=lfs -text\n*.pptx filter=lfs diff=lfs merge=lfs -text\n*.png filter=lfs diff=lfs merge=lfs"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 834,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 1556,
    "preview": "# Describe this PR\n\n<!-- Please provide a clear and concise description of what this PR does -->\n\n## What changed?\n<!-- "
  },
  {
    "path": ".github/scripts/check_pr_title.py",
    "chars": 2700,
    "preview": "# /// script\n# requires-python = \">=3.10\"\n# dependencies = []\n# ///\nimport argparse\nimport dataclasses\nimport os\nimport "
  },
  {
    "path": ".github/workflows/check-pr-title.yml",
    "chars": 446,
    "preview": "name: check-pr-title\n\non:\n  pull_request:\n   types: [opened, synchronize, edited]\n\njobs:\n  check-pr-title:\n    name: Che"
  },
  {
    "path": ".github/workflows/run-ruff.yml",
    "chars": 1361,
    "preview": "name: lint\n\non:\n  pull_request:\n    types: [opened, synchronize, edited]\n  push:\n    branches: [ \"main\" ]\n\njobs:\n  lint:"
  },
  {
    "path": ".gitignore",
    "chars": 4993,
    "preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[codz]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packag"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 7072,
    "preview": "<div align=\"center\">\n  <img src=\"docs/mkdocs/docs/assets/miromind_logo.png\" width=\"45%\" alt=\"MiroMind\" />\n\n  <h3>Perform"
  },
  {
    "path": "REUSE.toml",
    "chars": 695,
    "preview": "version = 1\n\n# cursor, gitignore and github workflow\n[[annotations]]\npath = [\"**/.cursor/**\", \".github/**\", \"**/.gitigno"
  },
  {
    "path": "config/__init__.py",
    "chars": 1797,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport os\nimport pathlib\nfrom datetim"
  },
  {
    "path": "config/agent_quickstart.yaml",
    "chars": 1585,
    "preview": "# MiroFlow Gradio Demo Configuration\n# A simplified configuration for the Gradio web interface (using MiroThinker)\n\n# No"
  },
  {
    "path": "config/agent_quickstart_graph.yaml",
    "chars": 2626,
    "preview": "# MiroFlow Gradio Demo Configuration\n# A simplified configuration for the Gradio web interface (using MiroThinker)\n\n# No"
  },
  {
    "path": "config/agent_quickstart_skill.yaml",
    "chars": 1501,
    "preview": "# MiroFlow Quickstart with Skill Configuration\n# A simple single-agent setup with the reading tool and simple_file_under"
  },
  {
    "path": "config/agent_single-test.yaml",
    "chars": 1455,
    "preview": "defaults:\n  - benchmark: gaia-validation\n  - override hydra/job_logging: none\n  - _self_  # Allow defining variables at "
  },
  {
    "path": "config/agent_web_demo.yaml",
    "chars": 1484,
    "preview": "# MiroFlow Web Demo Configuration\n# A simplified configuration for the web interface (using MiroThinker)\n\n# No benchmark"
  },
  {
    "path": "config/benchmark/browsecomp-en-200.yaml",
    "chars": 744,
    "preview": "# config/benchmark/browsecomp-en.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"browsecomp-en-200\"\n\ndata:\n  data_dir: \"${"
  },
  {
    "path": "config/benchmark/browsecomp-en.yaml",
    "chars": 742,
    "preview": "# config/benchmark/browsecomp-en.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"browsecomp-en\"\n\ndata:\n  data_dir: \"${data"
  },
  {
    "path": "config/benchmark/browsecomp-zh.yaml",
    "chars": 749,
    "preview": "# config/benchmark/browsecomp-zh.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"browsecomp-zh\"\n\ndata:\n  data_dir: \"${data"
  },
  {
    "path": "config/benchmark/default.yaml",
    "chars": 379,
    "preview": "# config/benchmark/default.yaml - Default benchmark configuration\n# This is a base configuration for benchmarks. Specifi"
  },
  {
    "path": "config/benchmark/example_dataset.yaml",
    "chars": 616,
    "preview": "# config/benchmark/example_dataset.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"example_dataset\"\n\ndata:\n  data_dir: \"${"
  },
  {
    "path": "config/benchmark/finsearchcomp.yaml",
    "chars": 683,
    "preview": "# config/benchmark/finsearchcomp.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"finsearchcomp\"\n\ndata:\n  data_dir: \"${data"
  },
  {
    "path": "config/benchmark/frames-test.yaml",
    "chars": 720,
    "preview": "# config/benchmark/frames-test.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"frames-test\"\n\ndata:\n  data_dir: \"${data_dir"
  },
  {
    "path": "config/benchmark/futurex.yaml",
    "chars": 615,
    "preview": "# config/benchmark/futurex.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"futurex\"\n\ndata:\n  data_dir: \"${data_dir}/future"
  },
  {
    "path": "config/benchmark/gaia-test.yaml",
    "chars": 343,
    "preview": "# config/benchmark/gaia-validation.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"gaia-test\"\n\ndata:\n  data_dir: \"${data_d"
  },
  {
    "path": "config/benchmark/gaia-validation-165.yaml",
    "chars": 379,
    "preview": "# config/benchmark/gaia-validation-165.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"gaia-validation-165\"\n\ndata:\n  data_"
  },
  {
    "path": "config/benchmark/gaia-validation-text-only.yaml",
    "chars": 390,
    "preview": "# config/benchmark/gaia-validation.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"gaia-validation-text-only\"\n\ndata:\n  dat"
  },
  {
    "path": "config/benchmark/gaia-validation.yaml",
    "chars": 393,
    "preview": "# config/benchmark/gaia-validation.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"gaia-validation\"\n\ndata:\n  data_dir: \"${"
  },
  {
    "path": "config/benchmark/hle-text-only.yaml",
    "chars": 732,
    "preview": "# config/benchmark/hle-text-only.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"hle-text-only\"\n\ndata:\n  data_dir: \"${data"
  },
  {
    "path": "config/benchmark/hle.yaml",
    "chars": 682,
    "preview": "# config/benchmark/hle.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"hle\"\n\ndata:\n  data_dir: \"${data_dir}/hle\"  # Path t"
  },
  {
    "path": "config/benchmark/webwalkerqa.yaml",
    "chars": 722,
    "preview": "# config/benchmark/webwalkerqa.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"webwalkerqa\"\n\ndata:\n  data_dir: \"${data_dir"
  },
  {
    "path": "config/benchmark/xbench-ds.yaml",
    "chars": 384,
    "preview": "# config/benchmark/xbench-ds.yaml\ndefaults:\n  - default\n  - _self_\n\nname: \"xbench-ds\"\n\ndata:\n  data_dir: \"${data_dir}/xb"
  },
  {
    "path": "config/benchmark_browsecomp-en-200_mirothinker_v1.yaml",
    "chars": 1238,
    "preview": "defaults:\n  - benchmark: browsecomp-en-200\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmain_"
  },
  {
    "path": "config/benchmark_browsecomp-en_mirothinker.yaml",
    "chars": 1234,
    "preview": "defaults:\n  - benchmark: browsecomp-en\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmain_agen"
  },
  {
    "path": "config/benchmark_browsecomp-zh_mirothinker_v1.yaml",
    "chars": 1234,
    "preview": "defaults:\n  - benchmark: browsecomp-zh\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmain_agen"
  },
  {
    "path": "config/benchmark_browsecomp-zh_mirothinker_v2.yaml",
    "chars": 1178,
    "preview": "defaults:\n  - benchmark: browsecomp-zh\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmain_agen"
  },
  {
    "path": "config/benchmark_browsecomp-zh_mirothinker_v3.yaml",
    "chars": 1178,
    "preview": "defaults:\n  - benchmark: browsecomp-zh\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmain_agen"
  },
  {
    "path": "config/benchmark_frames-test_mirothinker.yaml",
    "chars": 1232,
    "preview": "defaults:\n  - benchmark: frames-test\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmain_agent:"
  },
  {
    "path": "config/benchmark_gaia-validation-165_mirothinker_tool.yaml",
    "chars": 1444,
    "preview": "defaults:\n  - benchmark: gaia-validation-165\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmai"
  },
  {
    "path": "config/benchmark_gaia-validation-165_mirothinker_v1.yaml",
    "chars": 1339,
    "preview": "defaults:\n  - benchmark: gaia-validation-165\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmai"
  },
  {
    "path": "config/benchmark_gaia-validation-text-103_kimi_k25.yaml",
    "chars": 1240,
    "preview": "defaults:\n  - benchmark: gaia-validation-text-only\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_age"
  },
  {
    "path": "config/benchmark_gaia-validation-text-103_mirothinker_multi-agent.yaml",
    "chars": 1643,
    "preview": "defaults:\n  - benchmark: gaia-validation-text-only\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_age"
  },
  {
    "path": "config/benchmark_gaia-validation-text-103_mirothinker_v1.yaml",
    "chars": 1246,
    "preview": "defaults:\n  - benchmark: gaia-validation-text-only\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_age"
  },
  {
    "path": "config/benchmark_gaia-validation-text-103_mirothinker_v2.yaml",
    "chars": 1190,
    "preview": "defaults:\n  - benchmark: gaia-validation-text-only\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_age"
  },
  {
    "path": "config/benchmark_hle-text-only_mirothinker.yaml",
    "chars": 1234,
    "preview": "defaults:\n  - benchmark: hle-text-only\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmain_agen"
  },
  {
    "path": "config/benchmark_hle_mirothinker_v1.yaml",
    "chars": 1224,
    "preview": "defaults:\n  - benchmark: hle\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmain_agent:\n  name:"
  },
  {
    "path": "config/benchmark_webwalkerqa_mirothinker.yaml",
    "chars": 1232,
    "preview": "defaults:\n  - benchmark: webwalkerqa\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmain_agent:"
  },
  {
    "path": "config/benchmark_xbench-ds_mirothinker.yaml",
    "chars": 1230,
    "preview": "defaults:\n  - benchmark: xbench-ds\n  - override hydra/job_logging: none\n  - _self_\n\nentrypoint: main_agent\nmain_agent:\n "
  },
  {
    "path": "config/llm/base_kimi_k25.yaml",
    "chars": 516,
    "preview": "# config/llm/base_kimi_k25.yaml\nprovider_class: \"OpenRouterClient\"\nmodel_name: \"moonshotai/kimi-k2.5\"\nopenrouter_api_key"
  },
  {
    "path": "config/llm/base_mirothinker.yaml",
    "chars": 506,
    "preview": "# config/llm/base.yaml\nprovider_class: \"MiroThinkerSGLangClient\"\nmodel_name: mirothinker-v1.5\napi_key: ${oc.env:OAI_MIRO"
  },
  {
    "path": "config/llm/base_openai.yaml",
    "chars": 431,
    "preview": "# config/llm/base.yaml\nprovider_class: \"GPTOpenAIClient\"\nmodel_name: null\napi_key: ${oc.env:OPENAI_API_KEY,???}\nbase_url"
  },
  {
    "path": "config/prompts/__init__.py",
    "chars": 843,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport os\nimport importlib\nimport pkg"
  },
  {
    "path": "config/prompts/base_agent_prompt.py",
    "chars": 3592,
    "preview": "from abc import ABC, abstractmethod\nimport dataclasses\nfrom typing import Any\n\n\n@dataclasses.dataclass\nclass BaseAgentPr"
  },
  {
    "path": "config/prompts/main_agent_prompt_deepseek.py",
    "chars": 8723,
    "preview": "import datetime\nfrom typing import Any\n\n\nclass MainAgentPromptBoxedDeepSeek:\n    \"\"\"\n    Adapted from MainAgentPromptBox"
  },
  {
    "path": "config/prompts/main_agent_prompt_gaia.py",
    "chars": 9933,
    "preview": "from config.agent_prompts.base_agent_prompt import BaseAgentPrompt\nimport datetime\nfrom typing import Any\n\n\nclass MainAg"
  },
  {
    "path": "config/prompts/main_boxed_answer.py",
    "chars": 10208,
    "preview": "from config.agent_prompts.base_agent_prompt import BaseAgentPrompt\nimport datetime\nfrom typing import Any\n\n\nclass MainAg"
  },
  {
    "path": "config/prompts/prompt_final_answer_extraction.yaml",
    "chars": 1561,
    "preview": "template:\n  gaia_final_answer_type_prompt:\n    components:\n      - default\n\n    required_context: task_description\n\n    "
  },
  {
    "path": "config/prompts/prompt_main_agent.yaml",
    "chars": 16783,
    "preview": "template:\n  initial_user_text: \n    components:\n      - task_description\n      - file_input_prompt\n      - task_guidance"
  },
  {
    "path": "config/prompts/prompt_main_agent_benchmark.yaml",
    "chars": 10272,
    "preview": "template:\n  initial_user_text: \n    components:\n      - task_description\n      - task_guidance\n      - file_input_prompt"
  },
  {
    "path": "config/prompts/prompt_main_agent_gaia.yaml",
    "chars": 16718,
    "preview": "template:\n  initial_user_text: \n    components:\n      - task_description\n      - file_input_prompt\n      - task_guidance"
  },
  {
    "path": "config/prompts/prompt_sub_agent.yaml",
    "chars": 13979,
    "preview": "template:\n  initial_user_text: \n    components:\n      - task_description\n      - file_input_prompt\n      - task_guidance"
  },
  {
    "path": "config/prompts/prompt_subtask.yaml",
    "chars": 683,
    "preview": "template:\n  This tool is an agent that performs various subtasks to collect information and execute specific actions. It"
  },
  {
    "path": "config/prompts/sub_worker.py",
    "chars": 20211,
    "preview": "from config.agent_prompts.base_agent_prompt import BaseAgentPrompt\nimport datetime\nfrom typing import Any\n\n\nclass SubAge"
  },
  {
    "path": "config/tool/tool-audio-os.yaml",
    "chars": 265,
    "preview": "name: \"tool-audio-os\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.audio_mcp_server_os\"\nenv:\n  W"
  },
  {
    "path": "config/tool/tool-audio.yaml",
    "chars": 511,
    "preview": "name: \"tool-audio\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.audio_mcp_server\"\nenv:\n# Audio p"
  },
  {
    "path": "config/tool/tool-browsing.yaml",
    "chars": 598,
    "preview": "name: \"tool-browsing\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.browsing_mcp_server\"\nenv:\n# B"
  },
  {
    "path": "config/tool/tool-code-sandbox.yaml",
    "chars": 174,
    "preview": "name: \"tool-code-sandbox\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.code_sandbox\"\nenv:\n  E2B_"
  },
  {
    "path": "config/tool/tool-image-video-os.yaml",
    "chars": 266,
    "preview": "name: \"tool-image-video-os\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.vision_mcp_server_os\"\ne"
  },
  {
    "path": "config/tool/tool-image-video.yaml",
    "chars": 951,
    "preview": "name: \"tool-image-video\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.vision_mcp_server\"\nenv:\n# "
  },
  {
    "path": "config/tool/tool-jina-scrape.yaml",
    "chars": 472,
    "preview": "name: \"tool-jina-scrape\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.jina_scrape\"\nenv:\n# Jina a"
  },
  {
    "path": "config/tool/tool-markitdown.yaml",
    "chars": 54,
    "preview": "name: \"tool-markitdown\"\ntool_command: \"markitdown-mcp\""
  },
  {
    "path": "config/tool/tool-reading.yaml",
    "chars": 207,
    "preview": "name: \"tool-reading\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.reading_mcp_server\"\nenv:\n  SER"
  },
  {
    "path": "config/tool/tool-reasoning-os.yaml",
    "chars": 285,
    "preview": "name: \"tool-reasoning-os\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.reasoning_mcp_server_os\"\n"
  },
  {
    "path": "config/tool/tool-reasoning.yaml",
    "chars": 706,
    "preview": "name: \"tool-reasoning\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.reasoning_mcp_server\"\nenv:\n#"
  },
  {
    "path": "config/tool/tool-scrape-website-v1.yaml",
    "chars": 680,
    "preview": "name: \"tool-scrape-website-v1\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.scrape_website_v1\"\ne"
  },
  {
    "path": "config/tool/tool-searching-serper.yaml",
    "chars": 228,
    "preview": "name: \"tool-searching-serper\"\ntool_command: \"npx\"\nargs:\n  - \"-y\"\n  - \"serper-search-scrape-mcp-server\"\nenv:\n# Search API"
  },
  {
    "path": "config/tool/tool-searching.yaml",
    "chars": 459,
    "preview": "name: \"tool-searching\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.searching_mcp_server\"\nenv:\n#"
  },
  {
    "path": "config/tool/tool-serper-search.yaml",
    "chars": 494,
    "preview": "name: \"tool-serper-search\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.serper_search\"\nenv:\n# Se"
  },
  {
    "path": "config/tool/tool-serper-sogou-search.yaml",
    "chars": 448,
    "preview": "name: \"tool-serper-sogou-search\"\ntool_command: \"python\"\nargs:\n  - \"-m\"\n  - \"miroflow.tool.mcp_servers.serper_sogou_searc"
  },
  {
    "path": "data/README.md",
    "chars": 1563,
    "preview": "# Data Directory\n\nThis directory contains evaluation datasets used for testing and benchmarking.\n\n## Dataset Download In"
  },
  {
    "path": "docs/mkdocs/README.md",
    "chars": 1968,
    "preview": "# MiroFlow Documentation\n\nThis directory contains the MkDocs documentation site using the Material theme.\n\n## Setup\n\nmkd"
  },
  {
    "path": "docs/mkdocs/docs/all_about_agents.md",
    "chars": 29207,
    "preview": "# 📚 All About Agents\n\nWelcome to our comprehensive resource collection for AI agents. This page curates valuable tools, "
  },
  {
    "path": "docs/mkdocs/docs/browsecomp_en.md",
    "chars": 2754,
    "preview": "# BrowseComp-EN (English)\n\nMiroFlow's evaluation on the BrowseComp-EN benchmark demonstrates advanced web browsing and i"
  },
  {
    "path": "docs/mkdocs/docs/browsecomp_zh.md",
    "chars": 3096,
    "preview": "# BrowseComp-ZH (Chinese)\n\nMiroFlow's evaluation on the BrowseComp-ZH benchmark demonstrates advanced web browsing and i"
  },
  {
    "path": "docs/mkdocs/docs/claude-3.7-sonnet.md",
    "chars": 1638,
    "preview": "# Claude 3.7 Sonnet\n\nAnthropic's Claude 3.7 Sonnet model with 200K context, strong reasoning, and tool use capabilities."
  },
  {
    "path": "docs/mkdocs/docs/contribute_benchmarks.md",
    "chars": 5836,
    "preview": "# Contributing New Benchmarks to MiroFlow\n\nThis comprehensive guide walks you through adding new evaluation benchmarks t"
  },
  {
    "path": "docs/mkdocs/docs/contribute_llm_clients.md",
    "chars": 2418,
    "preview": "# Contributing New LLM Clients\n\nAdd support for new LLM providers to MiroFlow by creating a provider class that integrat"
  },
  {
    "path": "docs/mkdocs/docs/contribute_tools.md",
    "chars": 2252,
    "preview": "# Contributing New Tools\n\nMiroFlow's extensible tool system allows you to add custom functionality by implementing new M"
  },
  {
    "path": "docs/mkdocs/docs/contributors.md",
    "chars": 2550,
    "preview": "# 📝 Contributors\n\nThank you to all the amazing contributors who have helped make MiroFlow better! 🙏\n\n---\n\n## Core Team\n\n"
  },
  {
    "path": "docs/mkdocs/docs/core_concepts.md",
    "chars": 9736,
    "preview": "# Core Concepts\n\nMiroFlow is a flexible framework for building and deploying intelligent agents capable of complex reaso"
  },
  {
    "path": "docs/mkdocs/docs/data.md",
    "chars": 16491,
    "preview": "# 📊 Data\n\nThe MiroVerse dataset collection provides comprehensive training data for building advanced AI agents with ful"
  },
  {
    "path": "docs/mkdocs/docs/deepseek.md",
    "chars": 1601,
    "preview": "# DeepSeek\n\nDeepSeek's advanced language models with strong reasoning capabilities and tool use support, accessible via "
  },
  {
    "path": "docs/mkdocs/docs/download_datasets.md",
    "chars": 4052,
    "preview": "# Dataset Download Instructions\n\nThis guide walks you through downloading and preparing benchmark datasets for MiroFlow "
  },
  {
    "path": "docs/mkdocs/docs/e2b_advanced_features.md",
    "chars": 5836,
    "preview": "# E2B Advanced Features\n\n!!! warning \"Preview Documentation\"\n    This section is in preview and not fully ready. The fea"
  },
  {
    "path": "docs/mkdocs/docs/evaluation_overview.md",
    "chars": 2774,
    "preview": "# Evaluation Methodology\n\nMiroFlow provides a standardized evaluation framework for fair, reproducible model comparison "
  },
  {
    "path": "docs/mkdocs/docs/faqs.md",
    "chars": 1641,
    "preview": "# 🐛 FAQ and Known Issues\n\nCommon questions and development roadmap for MiroFlow framework.\n\n---\n\n## FAQ\n\n!!! question \"F"
  },
  {
    "path": "docs/mkdocs/docs/finsearchcomp.md",
    "chars": 4060,
    "preview": "# FinSearchComp\n\nMiroFlow's evaluation on the FinSearchComp benchmark demonstrates capabilities in financial information"
  },
  {
    "path": "docs/mkdocs/docs/futurex.md",
    "chars": 4285,
    "preview": "# Futurex-Online\n\nMiroFlow's evaluation on the Futurex-Online benchmark demonstrates capabilities in future event predic"
  },
  {
    "path": "docs/mkdocs/docs/gaia_test.md",
    "chars": 2141,
    "preview": "# GAIA Test\n\nThe GAIA (General AI Assistant) test set provides a comprehensive evaluation dataset for assessing AI agent"
  },
  {
    "path": "docs/mkdocs/docs/gaia_validation_claude37sonnet.md",
    "chars": 3556,
    "preview": "# GAIA Validation - Claude 3.7 Sonnet\n\n!!! tip \"Cross-Model Comparison\"\n    See how Claude 3.7 Sonnet compares to other "
  },
  {
    "path": "docs/mkdocs/docs/gaia_validation_gpt5.md",
    "chars": 1923,
    "preview": "# GAIA Validation - GPT-5\n\n!!! tip \"Cross-Model Comparison\"\n    See how GPT-5 compares to other models on GAIA and other"
  },
  {
    "path": "docs/mkdocs/docs/gaia_validation_mirothinker.md",
    "chars": 2429,
    "preview": "# GAIA Validation - MiroThinker\n\n!!! tip \"Cross-Model Comparison\"\n    See how MiroThinker compares to other models on GA"
  },
  {
    "path": "docs/mkdocs/docs/gaia_validation_prerequisites.md",
    "chars": 2935,
    "preview": "# GAIA Validation Prerequisites\n\nThis document covers the common setup requirements and prerequisites for running GAIA v"
  },
  {
    "path": "docs/mkdocs/docs/gaia_validation_text_only.md",
    "chars": 3293,
    "preview": "# GAIA Validation Text-Only\n\nThe GAIA (General AI Assistant) benchmark is a comprehensive evaluation dataset designed to"
  },
  {
    "path": "docs/mkdocs/docs/hle.md",
    "chars": 2642,
    "preview": "# HLE\n\nMiroFlow's evaluation on the HLE benchmark demonstrates capabilities in multimodal reasoning and question answeri"
  },
  {
    "path": "docs/mkdocs/docs/hle_text_only.md",
    "chars": 2550,
    "preview": "# HLE Text-Only\n\nMiroFlow's evaluation on the HLE-text-only benchmark demonstrates capabilities in reasoning and questio"
  },
  {
    "path": "docs/mkdocs/docs/index.md",
    "chars": 4875,
    "preview": "<div align=\"center\" markdown=\"1\">\n  ![MiroMind Logo](assets/miromind_logo.png){ width=\"45%\" }\n</div>\n\n<div align=\"center"
  },
  {
    "path": "docs/mkdocs/docs/license.md",
    "chars": 1640,
    "preview": "# License\n\n## Overview\n\nMiroFlow is released under the **Apache License 2.0**, which is a permissive open-source license"
  },
  {
    "path": "docs/mkdocs/docs/llm_clients_overview.md",
    "chars": 2906,
    "preview": "# LLM Clients Overview\n\nMiroFlow is model-agnostic — plug in any LLM and get better agent performance through smart roll"
  },
  {
    "path": "docs/mkdocs/docs/mirothinker.md",
    "chars": 3180,
    "preview": "# MiroThinker\n\n[MiroThinker](https://github.com/MiroMindAI/MiroThinker) (4B/7B/14B/32B) is our suite of open-source agen"
  },
  {
    "path": "docs/mkdocs/docs/model_comparison.md",
    "chars": 3404,
    "preview": "# Model Comparison Leaderboard\n\n> **Same tools. Same prompts. Same infrastructure. The only variable is the model.**\n\nMi"
  },
  {
    "path": "docs/mkdocs/docs/openai-gpt4o.md",
    "chars": 1496,
    "preview": "# OpenAI GPT-4o\n\nOpenAI's GPT-4o model with multimodal capabilities, strong reasoning, and efficient performance.\n\n## Cl"
  },
  {
    "path": "docs/mkdocs/docs/openai-gpt5.md",
    "chars": 1581,
    "preview": "# OpenAI GPT-5\n\nOpenAI's GPT-5 model with advanced reasoning capabilities and strong coding, vision, and problem-solving"
  },
  {
    "path": "docs/mkdocs/docs/openrouter-claude-3.7-sonnet.md",
    "chars": 1549,
    "preview": "# OpenRouter Claude 3.7 Sonnet (Recommended)\n\nAccess multiple models via OpenRouter using unified OpenAI chat format. Su"
  },
  {
    "path": "docs/mkdocs/docs/quickstart.md",
    "chars": 6093,
    "preview": "# Get Started in Under 5 Minutes\n\nClone the repository, configure your API keys, and run your first intelligent agent wi"
  },
  {
    "path": "docs/mkdocs/docs/tool_audio.md",
    "chars": 2016,
    "preview": "# Audio Tools (`tool-audio`)\n\nAudio processing capabilities including transcription and audio-based question answering.\n"
  },
  {
    "path": "docs/mkdocs/docs/tool_audio_os.md",
    "chars": 4347,
    "preview": "# Audio Tools - Open Source (`audio_mcp_server_os.py`)\n\nThe Audio MCP Server (Open Source) enables audio transcription u"
  },
  {
    "path": "docs/mkdocs/docs/tool_overview.md",
    "chars": 2217,
    "preview": "# Tool Overview\n\nMiroFlow provides a comprehensive set of tools that extend agent capabilities through the Model Context"
  },
  {
    "path": "docs/mkdocs/docs/tool_python.md",
    "chars": 4310,
    "preview": "# Code Sandbox Tools (`code_sandbox.py`)\n\nThe Code Sandbox Server provides a secure sandboxed environment for running Py"
  },
  {
    "path": "docs/mkdocs/docs/tool_reading.md",
    "chars": 1638,
    "preview": "# Reading Tools (`tool-reading`)\n\nRead and convert various document formats (DOC, PDF, Excel, etc.) to markdown for easy"
  },
  {
    "path": "docs/mkdocs/docs/tool_reasoning.md",
    "chars": 2424,
    "preview": "# Reasoning Tools (`reasoning_mcp_server.py`)\n\nThe Reasoning MCP Server provides a **pure text-based reasoning engine**."
  },
  {
    "path": "docs/mkdocs/docs/tool_reasoning_os.md",
    "chars": 4689,
    "preview": "# Reasoning Tools - Open Source (`reasoning_mcp_server_os.py`)\n\nThe Reasoning MCP Server (Open Source) provides a **pure"
  },
  {
    "path": "docs/mkdocs/docs/tool_searching.md",
    "chars": 5336,
    "preview": "# Searching Tools (`searching_mcp_server.py`)\n\nThe Searching MCP Server provides comprehensive search capabilities inclu"
  },
  {
    "path": "docs/mkdocs/docs/tool_searching_serper.md",
    "chars": 2140,
    "preview": "# Searching Tools - Serper (`tool-searching-serper`)\n\nLightweight Google search and web scraping via Serper API using NP"
  },
  {
    "path": "docs/mkdocs/docs/tool_vqa.md",
    "chars": 3761,
    "preview": "# Vision Tools (`vision_mcp_server.py`)\n\nThe Vision MCP Server enables OCR + Visual Question Answering (VQA) over images"
  },
  {
    "path": "docs/mkdocs/docs/tool_vqa_os.md",
    "chars": 4649,
    "preview": "# Vision Tools - Open Source (`vision_mcp_server_os.py`)\n\nThe Vision MCP Server (Open Source) enables Visual Question An"
  },
  {
    "path": "docs/mkdocs/docs/webwalkerqa.md",
    "chars": 3021,
    "preview": "# WebWalkerQA\n\nMiroFlow's evaluation on the WebWalkerQA benchmark demonstrates web navigation and question-answering cap"
  },
  {
    "path": "docs/mkdocs/docs/whats_new.md",
    "chars": 8647,
    "preview": "# What's New in MiroFlow v1.7\n\nMiroFlow v1.7 is a major architectural upgrade over the [original open-source release](ht"
  },
  {
    "path": "docs/mkdocs/docs/why_miroflow.md",
    "chars": 4587,
    "preview": "# Why MiroFlow\n\n## The Problem\n\nMost agent frameworks are tightly coupled to a single model or provider. When you want t"
  },
  {
    "path": "docs/mkdocs/docs/xbench_ds.md",
    "chars": 3940,
    "preview": "# xbench-DeepSearch\n\nThe **xbench** benchmark is an evaluation framework designed to measure both the intelligence front"
  },
  {
    "path": "docs/mkdocs/docs/yaml_config.md",
    "chars": 7094,
    "preview": "# YAML Configuration Guide\n\nMiroFlow uses a configuration system for customizing AI agents, tools, and benchmarks.\n\n## C"
  },
  {
    "path": "docs/mkdocs/mkdocs.yml",
    "chars": 3469,
    "preview": "site_name: MiroFlow\nsite_description: Performance-first agent framework that makes any model better — and proves it\n\nthe"
  },
  {
    "path": "miroflow/__init__.py",
    "chars": 82,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n"
  },
  {
    "path": "miroflow/agents/__init__.py",
    "chars": 373,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nAgents module\n\"\"\"\n\nfrom miroflow."
  },
  {
    "path": "miroflow/agents/base.py",
    "chars": 8617,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nAgent base class module\n\"\"\"\n\nimpo"
  },
  {
    "path": "miroflow/agents/context.py",
    "chars": 435,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nAgent context module - for passin"
  },
  {
    "path": "miroflow/agents/factory.py",
    "chars": 2139,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nAgent factory module - builds Age"
  },
  {
    "path": "miroflow/agents/iterative_agent_with_rollback.py",
    "chars": 17436,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nIterative Agent - with tool calli"
  },
  {
    "path": "miroflow/agents/sequential_agent.py",
    "chars": 2079,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nSequential Agent - executes multi"
  },
  {
    "path": "miroflow/benchmark/__init__.py",
    "chars": 748,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nBenchmark module for running and "
  },
  {
    "path": "miroflow/benchmark/calculate_average_score.py",
    "chars": 4180,
    "preview": "#!/usr/bin/env python3\n\n# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport glob\ni"
  },
  {
    "path": "miroflow/benchmark/eval_utils.py",
    "chars": 23586,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"Evaluation utilities for benchmark"
  },
  {
    "path": "miroflow/benchmark/run_benchmark.py",
    "chars": 4460,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport argparse\nimport asyncio\nimport"
  },
  {
    "path": "miroflow/benchmark/task_runner.py",
    "chars": 18022,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"Task execution utilities for bench"
  },
  {
    "path": "miroflow/benchmark/verifiers/__init__.py",
    "chars": 1284,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"Verifiers module for benchmark eva"
  },
  {
    "path": "miroflow/benchmark/verifiers/base_verifier.py",
    "chars": 1430,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"Base verifier class and shared con"
  },
  {
    "path": "miroflow/benchmark/verifiers/browsecomp_en_verifier.py",
    "chars": 7912,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"BrowseComp-EN Verifier for benchma"
  },
  {
    "path": "miroflow/benchmark/verifiers/browsecomp_zh_verifier.py",
    "chars": 4322,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"BrowseComp-ZH Verifier for benchma"
  },
  {
    "path": "miroflow/benchmark/verifiers/finsearchcomp_verifier.py",
    "chars": 2967,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"FinSearchComp Verifier using dynam"
  },
  {
    "path": "miroflow/benchmark/verifiers/gaia_common_verifier.py",
    "chars": 5328,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"GAIA Common Verifier with exact ma"
  },
  {
    "path": "miroflow/benchmark/verifiers/gaia_verifier.py",
    "chars": 4271,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"GAIA Verifier using exact matching"
  },
  {
    "path": "miroflow/benchmark/verifiers/hle_verifier.py",
    "chars": 3291,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"HLE Verifier for benchmark evaluat"
  },
  {
    "path": "miroflow/benchmark/verifiers/simpleqa_verifier.py",
    "chars": 10879,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"SimpleQA Verifier with exact match"
  },
  {
    "path": "miroflow/benchmark/verifiers/xbench_verifier.py",
    "chars": 3024,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"XBench Verifier for Chinese benchm"
  },
  {
    "path": "miroflow/io_processor/__init__.py",
    "chars": 592,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"IO processor module for input/outp"
  },
  {
    "path": "miroflow/io_processor/base.py",
    "chars": 544,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nIO processor base class\n\nIO proce"
  },
  {
    "path": "miroflow/io_processor/exceed_max_turn_summary_generator.py",
    "chars": 4900,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nExceed Max Turn Summary Generator"
  },
  {
    "path": "miroflow/io_processor/file_content_preprocessor.py",
    "chars": 2424,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nFile content preprocessor for pro"
  },
  {
    "path": "miroflow/io_processor/final_answer_extractor.py",
    "chars": 4122,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nFinal answer extractor - extracts"
  },
  {
    "path": "miroflow/io_processor/input_hint_generator.py",
    "chars": 876,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nInput hint generator - generates "
  },
  {
    "path": "miroflow/io_processor/input_message_generator.py",
    "chars": 1841,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nInput message generator - generat"
  },
  {
    "path": "miroflow/io_processor/regex_boxed_extractor.py",
    "chars": 3885,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nRegex-based boxed answer extracto"
  },
  {
    "path": "miroflow/io_processor/summary_generator.py",
    "chars": 2158,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nSummary generator - generates sum"
  },
  {
    "path": "miroflow/llm/__init__.py",
    "chars": 1458,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nLLM Module\n\nContains all LLM clie"
  },
  {
    "path": "miroflow/llm/base.py",
    "chars": 17334,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nLLM client base class module\n\"\"\"\n"
  },
  {
    "path": "miroflow/llm/claude_anthropic.py",
    "chars": 8607,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport asyncio\n\nfrom anthropic import"
  },
  {
    "path": "miroflow/llm/claude_openrouter.py",
    "chars": 16845,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport asyncio\nimport re\nfrom typing "
  },
  {
    "path": "miroflow/llm/factory.py",
    "chars": 2122,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nLLM client factory module - build"
  },
  {
    "path": "miroflow/llm/gpt5_openai.py",
    "chars": 20178,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport asyncio\nimport re\nfrom typing "
  },
  {
    "path": "miroflow/llm/gpt_openai.py",
    "chars": 10684,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport asyncio\nfrom typing import Any"
  },
  {
    "path": "miroflow/llm/mirothinker_sglang.py",
    "chars": 18518,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport asyncio\nimport re\nfrom typing "
  },
  {
    "path": "miroflow/llm/openai_client.py",
    "chars": 22870,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport asyncio\nimport re\nfrom typing "
  },
  {
    "path": "miroflow/llm/openrouter.py",
    "chars": 22966,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport asyncio\nimport re\nfrom typing "
  },
  {
    "path": "miroflow/llm/util.py",
    "chars": 767,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport asyncio\nimport functools\nfrom "
  },
  {
    "path": "miroflow/logging/__init__.py",
    "chars": 82,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n"
  },
  {
    "path": "miroflow/logging/decorators.py",
    "chars": 5773,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nfrom __future__ import annotations\n\ni"
  },
  {
    "path": "miroflow/logging/span.py",
    "chars": 1001,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nfrom __future__ import annotations\n\nf"
  },
  {
    "path": "miroflow/logging/task_tracer.py",
    "chars": 12459,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n# SPDX-License-Identifier: Apache-2.0\n\nfrom __future__ import annotations\n\nimp"
  },
  {
    "path": "miroflow/logging/tool_logging.py",
    "chars": 865,
    "preview": "import socket\n\nDEFAULT_ZMQ_ADDRESS: str = \"tcp://127.0.0.1:6000\"\nDEFAULT_ZMQ_PORT: int = 6000\n\n\ndef _find_available_port"
  },
  {
    "path": "miroflow/py.typed",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "miroflow/registry.py",
    "chars": 5217,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nUnified registration mechanism - "
  },
  {
    "path": "miroflow/skill/__init__.py",
    "chars": 322,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nSkill module\n\nNote: Skills are di"
  },
  {
    "path": "miroflow/skill/manager.py",
    "chars": 7544,
    "preview": "from __future__ import annotations\n\nimport logging\nimport re\nfrom dataclasses import dataclass\nfrom pathlib import Path\n"
  },
  {
    "path": "miroflow/skill/skills/Afternoon_feeling/SKILL.md",
    "chars": 212,
    "preview": "---\nname: Afternoon_feeling\ndescription: Quickly understand Jam's feeling today. Use when you need to understand Jam's f"
  },
  {
    "path": "miroflow/skill/skills/Today_feeling/SKILL.md",
    "chars": 214,
    "preview": "---\nname: Today_feeling\ndescription: Quickly understand Jam's feeling today. Use when you need to understand Jam's feeli"
  },
  {
    "path": "miroflow/skill/skills/simple_file_understanding/SKILL.md",
    "chars": 1899,
    "preview": "---\nname: simple_file_understanding\ndescription: Understand and analyze CSV files. Use when the task involves reading, p"
  },
  {
    "path": "miroflow/tool/__init__.py",
    "chars": 394,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nTool module\n\nNote: Tools are dyna"
  },
  {
    "path": "miroflow/tool/factory.py",
    "chars": 1628,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nTool factory module - creates MCP"
  },
  {
    "path": "miroflow/tool/manager.py",
    "chars": 27595,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nTool manager module - manages and"
  },
  {
    "path": "miroflow/tool/mcp_servers/__init__.py",
    "chars": 82,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n"
  },
  {
    "path": "miroflow/tool/mcp_servers/audio_mcp_server.py",
    "chars": 11999,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport os\nimport tempfile\nimport requ"
  },
  {
    "path": "miroflow/tool/mcp_servers/audio_mcp_server_os.py",
    "chars": 8154,
    "preview": "# Copyright 2025 Miromind.ai\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
  },
  {
    "path": "miroflow/tool/mcp_servers/browser_session.py",
    "chars": 3241,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport asyncio\nimport json\n\nfrom mcp "
  },
  {
    "path": "miroflow/tool/mcp_servers/code_sandbox.py",
    "chars": 18572,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\n\"\"\"\nPython MCP Server - E2B Sandbox b"
  },
  {
    "path": "miroflow/tool/mcp_servers/jina_scrape.py",
    "chars": 32344,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport asyncio\nimport json\nimport log"
  },
  {
    "path": "miroflow/tool/mcp_servers/miroapi_serper_mcp_server.py",
    "chars": 5255,
    "preview": "# Copyright 2025 Miromind.ai\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
  },
  {
    "path": "miroflow/tool/mcp_servers/reading_mcp_server.py",
    "chars": 6165,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport argparse\nimport os\nimport temp"
  },
  {
    "path": "miroflow/tool/mcp_servers/reasoning_mcp_server.py",
    "chars": 4734,
    "preview": "# SPDX-FileCopyrightText: 2025 MiromindAI\n#\n# SPDX-License-Identifier: Apache-2.0\n\nimport os\n\nfrom anthropic import Anth"
  },
  {
    "path": "miroflow/tool/mcp_servers/reasoning_mcp_server_os.py",
    "chars": 3552,
    "preview": "# Copyright 2025 Miromind.ai\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
  }
]

// ... and 96 more files (download for full content)

About this extraction

This page contains the full source code of the MiroMindAI/MiroFlow GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 296 files (1.5 MB), approximately 365.9k tokens, and a symbol index with 822 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.

Copied to clipboard!