{"owner":"AstrBotDevs","repo":"AstrBot","hasSkills":true,"totalSkillsCount":12,"totalTokensCount":10650,"categories":["copilot-instructions","root-instruction","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":[".github/copilot-instructions.md","AGENTS.md","astrbot/builtin_stars/astrbot/skills/documents/SKILL.md","astrbot/builtin_stars/astrbot/skills/documents/references/advanced-ooxml.md","astrbot/builtin_stars/astrbot/skills/documents/references/styling.md","astrbot/builtin_stars/astrbot/skills/pdf/SKILL.md","astrbot/builtin_stars/astrbot/skills/pdf/references/forms.md","astrbot/builtin_stars/astrbot/skills/skill-creator/SKILL.md","astrbot/builtin_stars/astrbot/skills/spreadsheets/SKILL.md","astrbot/builtin_stars/astrbot/skills/spreadsheets/references/charts.md","astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formatting.md","astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formulas.md"],"skills":{".github/copilot-instructions.md":"# AstrBot Development Instructions\n\nAstrBot is a multi-platform LLM chatbot and development framework written in Python with a Vue.js dashboard. It supports multiple messaging platforms (QQ, Telegram, Discord, etc.) and various LLM providers (OpenAI, Anthropic, Google Gemini, etc.).\n\nAlways reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.\n\n## Working Effectively\n\n### Bootstrap and Install Dependencies\n- **Python 3.10+ required** - Check `.python-version` file\n- Install UV package manager: `pip install uv`\n- Install project dependencies: `uv sync` -- takes 6-7 minutes. NEVER CANCEL. Set timeout to 10+ minutes.\n- Create required directories: `mkdir -p data/plugins data/config data/temp`\n\n### Running the Application\n- Run main application: `uv run main.py` -- starts in ~3 seconds\n- Application creates WebUI on http://localhost:6185 (default credentials: `astrbot`/`astrbot`)\n\n### Dashboard Build (Vue.js/Node.js)\n- **Prerequisites**: Node.js 20+ and npm 10+ required\n- Navigate to dashboard: `cd dashboard`\n- Install dashboard dependencies: `npm install` -- takes 2-3 minutes. NEVER CANCEL. Set timeout to 5+ minutes.\n- Build dashboard: `npm run build` -- takes 25-30 seconds. NEVER CANCEL.\n- Dashboard creates optimized production build in `dashboard/dist/`\n\n### Testing\n- Do not generate test files for now.\n\n### Code Quality and Linting\n- Install ruff linter: `uv add --dev ruff`\n- Check code style: `uv run ruff check .` -- takes <1 second\n- Check formatting: `uv run ruff format --check .` -- takes <1 second\n- Fix formatting: `uv run ruff format .`\n- **ALWAYS** run `uv run ruff check .` and `uv run ruff format .` before committing changes\n\n### Plugin Development\n- Plugins load from `astrbot/builtin_stars/` (built-in) and `data/plugins/` (user-installed)\n- Plugin system supports function tools and message handlers\n- Key plugins: python_interpreter, web_searcher, astrbot, reminder, session_controller\n\n### Common Issues and Workarounds\n- **Dashboard download fails**: Known issue with \"division by zero\" error - application still works\n- **Import errors in tests**: Ensure `uv run` is used to run tests in proper environment\n=- **Build timeouts**: Always set appropriate timeouts (10+ minutes for uv sync, 5+ minutes for npm install)\n\n## CI/CD Integration\n- GitHub Actions workflows in `.github/workflows/`\n- Docker builds supported via `Dockerfile`\n- Pre-commit hooks enforce ruff formatting and linting\n\n## Docker Support\n- Primary deployment method: `docker run soulter/astrbot:latest`\n- Compose file available: `compose.yml`\n- Exposes ports: 6185 (WebUI), 6195 (WeChat), 6199 (QQ), etc.\n- Volume mount required: `./data:/AstrBot/data`\n\n## Multi-language Support\n- Documentation in Chinese (README.md), English (README_en.md), Japanese (README_ja.md)\n- UI supports internationalization\n- Default language is Chinese\n\nRemember: This is a production chatbot framework with real users. Always test thoroughly and ensure changes don't break existing functionality.\n","AGENTS.md":"## Setup commands\n\n### Core\n\n```\nuv sync\nuv run main.py\n```\n\nExposed an API server on `http://localhost:6185` by default.\n\n### Dashboard(WebUI)\n\n```\ncd dashboard\npnpm install # First time only. Use npm install -g pnpm if pnpm is not installed.\npnpm dev\n```\n\nRuns on `http://localhost:3000` by default.\n\n## Pre-commit setup\n\nAstrBot uses [pre-commit](https://pre-commit.com/) hooks to automatically format and lint Python code before each commit. The hooks run `ruff check`, `ruff format`, and `pyupgrade` (see [`.pre-commit-config.yaml`](.pre-commit-config.yaml) for details).\n\nTo set it up:\n\n```bash\npip install pre-commit\npre-commit install\n```\n\nAfter installation, the hooks will run automatically on `git commit`. You can also run them manually at any time:\n\n```bash\nruff format .\nruff check .\n```\n\n> **Note:** If you use VSCode, install the `Ruff` extension for real-time formatting and linting in the editor.\n\n## Dev environment tips\n\n### Basic\n\n1. When modifying the WebUI, be sure to maintain componentization and clean code. Avoid duplicate code.\n2. Do not add any report files such as xxx_SUMMARY.md.\n3. After finishing, use `ruff format .` and `ruff check .` to format and check the code.\n4. When committing, ensure to use conventional commits messages, such as `feat: add new agent for data analysis` or `fix: resolve bug in provider manager`.\n5. Use **English** for all comments and logs.\n6. For path handling, use `pathlib.Path` instead of string paths, and use `astrbot.core.utils.path_utils` to get the AstrBot data and temp directory.\n7. When backend API routes, request/response schemas, or OpenAPI definitions change, regenerate the frontend API client by running `cd dashboard && pnpm generate:api`.\n8. When updating the project version, keep `[project].version` in `pyproject.toml` and `__version__` in `astrbot/__init__.py` in sync. `VERSION` in `astrbot/core/config/default.py` should derive from `astrbot.__version__` instead of hardcoding a separate version string.\n9. When designing WebUI dialogs, use `text-h3 pa-4 pb-0 pl-6` as the base class for dialog titles, and use `variant=\"text\"` or `variant=\"tonal\"` for dialog buttons.\n10. Consider cross-platform compatibility (e.g., Windows, macOS, and Linux, as well as Arm64 and x86 CPU architectures) and compatibility with Python 3.10+.\n11. When changing WebUI navigation, page structure, or terminology, update the affected instructions and screenshots in `docs/zh` and `docs/en` in the same PR. For renamed, moved, or merged entry points, include an old-to-new mapping in the relevant docs and changelog. Keep layout redesigns separate from feature additions where practical, and explain necessary navigation changes in the PR. See `CONTRIBUTING.md` for the review checklist.\n\n### KISS and First Principles\n\nFollow the KISS principle and reason from first principles during development. Start by identifying the real problem, required behavior, and smallest useful change before adding code. Do not pile on features, configuration switches, abstractions, dependencies, or compatibility layers unless they directly solve the current problem and have clear evidence of need.\n\nPrefer the simplest implementation that is correct, maintainable, and consistent with the existing codebase. If a broader design seems attractive, reduce it to the essential behavior needed now and leave optional expansion for a later, explicit requirement.\n\n### No Unnecessary Helpers\n\nPrioritize inline implementation over abstraction. Avoid over-engineering and do not create helper functions unless absolutely necessary.\n\n1. **Inline-First Rule**: If a logic block can be implemented directly within the main function without breaking overall readability, **do not** extract it into a new helper function.\n2. **Strict Justification for Helpers**: You may only create a separate helper function if it meets at least one of these criteria:\n   - **High Reuse**: The exact same logic is repeated across **3 or more** different locations.\n   - **Extreme Complexity**: Inlining the logic makes the main function too long (e.g., >50 lines) or severely derails the main execution flow.\n3. **No Fragmentation**: Do not split continuous linear logic (e.g., a single API call, simple form validation, or one-time data formatting) into tiny functions just for the sake of \"clean code.\"\n4. **Keep Context Compact**: Handle edge cases, error catching, and logging directly inside the main function block instead of offloading them.\n5. **Refactoring Constraint**: When modifying existing code, do not alter the current function structure or extract code into new helpers unless the existing code already violates the complexity or reuse rules above.\n\n### Mandatory Google-Style Docstrings\n* **Comment the complex**: Add clear comments to any non-obvious function, method, or parameter.\n* **Google Format**: All docstrings must strictly use the Google format (`Args:`, `Returns:`, `Raises:`).\n\n#### Example:\n\n```py\ndef calculate_metrics(user_id: int, force_refresh: bool = False) -> dict:\n    \"\"\"Brief description of the function.\n\n    Args:\n        user_id: Description of the ID.\n        force_refresh: Description of the flag.\n\n    Returns:\n        Description of the returned dict.\n\n    Raises:\n        ValueError: Description of when this occurs.\n    \"\"\"\n    # Inline implementation here...\n```\n\n\n## PR instructions\n\n1. Title format: use conventional commit messages\n2. Use English to write PR title and descriptions.\n\n## Release versions\n\nUse a short-lived `release/*` branch for each release. The release branch is the stabilization area for version bumps, changelog updates, release-blocking fixes, and final validation only. Do not add unrelated features or broad refactors to a release branch.\n\nPrepare a release from a clean worktree with:\n\n```bash\nuv run python scripts/prepare_release.py 4.25.0\n```\n\nThe script updates `pyproject.toml` and `astrbot/__init__.py`, creates `changelogs/v4.25.0.md`, runs the required Python checks, and prints the remaining steps. Use these flags when needed:\n\n```bash\nuv run python scripts/prepare_release.py 4.25.0 --generate-api-client\nuv run python scripts/prepare_release.py 4.25.0 --dashboard-build\nuv run python scripts/prepare_release.py 4.25.0 --commit --push\n```\n\nOpen a PR from `release/4.25.0` to `master`. The PR title must use the conventional commit format, for example `chore: bump version to 4.25.0`. After the release PR is merged, create and push the tag from the updated `master` branch so the tag points to the exact code that was merged:\n\n```bash\ngit checkout master\ngit pull --ff-only origin master\ngit tag v4.25.0\ngit push origin v4.25.0\n```\n\nFor one-off release candidate branches, delete the release branch after the tag is pushed and verified. For maintained release lines, use a branch such as `release/4.25` and keep it until that line reaches EOL.\n\n```bash\ngit branch -d release/4.25.0\ngit push origin --delete release/4.25.0\n```\n","astrbot/builtin_stars/astrbot/skills/documents/SKILL.md":"---\nname: documents\ndescription: Create, read, edit, review, comment on, sanitize, render, and validate Microsoft Word DOCX documents. Use whenever a DOCX or Word document is a primary input or deliverable, including reports, proposals, forms, templates, tracked revisions, comments, tables, images, headers, footers, and style-preserving edits.\n---\n\n# Work with DOCX documents\n\nUse `python-docx` for ordinary creation and editing. Use direct OOXML inspection or small targeted patches only for features that `python-docx` cannot represent safely. Preserve the source unless the user explicitly requests an in-place edit.\n\n## Follow the workflow\n\n1. Inspect the source document's text, styles, sections, tables, images, comments, fields, tracked changes, content controls, headers, footers, and metadata as relevant.\n2. For edits, preserve the existing design and apply the smallest local change. Do not rebuild the document merely because creating a new one is easier.\n3. For new documents and major rewrites, choose a coherent design system before authoring. Read [styling.md](references/styling.md).\n4. Save to a new DOCX, reopen it with `python-docx`, validate the OOXML package, and render every page when LibreOffice and a PDF renderer are available.\n5. Inspect the rendered pages and iterate until there is no clipping, overlap, broken table geometry, missing glyph, awkward page break, or header/footer problem.\n\nUse the bundled inspector before unfamiliar edits:\n\n```text\npython <this-skill-directory>/scripts/inspect_docx.py input.docx\n```\n\nFor a quick text-only read, `astrbot_file_read_tool` is sufficient. Text extraction does not prove layout, comments, fields, tracked changes, or images are correct.\n\n## Create and edit with real document structure\n\n- Use Word paragraph styles for Normal, Title, Subtitle, Heading 1, Heading 2, and Heading 3 rather than styling every paragraph directly.\n- Use real list styles or numbering definitions. Do not type bullet characters, hyphen prefixes, or manual numbers into ordinary paragraphs.\n- Use tables only for genuinely tabular, comparable, or form-like content. Do not package long prose into grids.\n- Set page size, margins, orientation, header/footer distance, and section breaks explicitly.\n- Size table columns deliberately, enable wrapping, avoid fixed row heights, and repeat header rows when a table spans pages.\n- Preserve hyperlinks, relationships, bookmarks, captions, fields, comments, and tracked changes that are outside the requested edit.\n- Keep headings with following content and avoid leaving a heading alone at the bottom of a page.\n- Use comments for review feedback at the relevant text rather than collecting every note at the end.\n\n## Handle fonts and Chinese text\n\nDOCX files normally record font names rather than embedding the actual fonts. Choose common fonts and expect the opening application to substitute when a font is unavailable.\n\nSet all relevant Word font mappings for each styled run or style:\n\n```python\nfrom docx.oxml.ns import qn\n\nrun.font.name = \"Noto Sans CJK SC\"\nfonts = run._element.get_or_add_rPr().get_or_add_rFonts()\nfonts.set(qn(\"w:ascii\"), \"Noto Sans CJK SC\")\nfonts.set(qn(\"w:hAnsi\"), \"Noto Sans CJK SC\")\nfonts.set(qn(\"w:eastAsia\"), \"Noto Sans CJK SC\")\n```\n\nPrefer the user's template fonts. For a new cross-platform Chinese document, choose a readable system CJK font, verify that it exists in the actual render environment (`fc-match \"Font Name\"` when Fontconfig is available), and inspect the rendered output. Do not claim font consistency across devices unless the required font is installed or intentionally embedded with a licensed workflow.\n\n## Preserve advanced features\n\nRead [advanced-ooxml.md](references/advanced-ooxml.md) before changing tracked revisions, fields, content controls, protection, footnotes, endnotes, macros, digital signatures, or document relationships.\n\n- `python-docx` can create and read ordinary comments in current versions, but comments still require structural validation because headless renderers may omit them.\n- Tracked changes are not a safe first-class editing surface. Use targeted OOXML patches and preserve author/date data.\n- A visible table of contents is often cached field content. Preserve the field instructions and disclose when a calculating Word-compatible application must refresh them.\n- Preserve VBA only when explicitly working with a macro-enabled format. Do not rename DOCM to DOCX or claim macros are safe.\n- Editing a digitally signed document invalidates its signature. Preserve the source and report this before modifying it.\n\n## Inspect privacy and metadata\n\nReview author, last editor, creation/modification time, comments, tracked-change authors, custom properties, hidden text, document variables, external links, and embedded files before publishing sensitive documents.\n\nUse the bundled scrubber only when the user requests metadata removal:\n\n```text\npython <this-skill-directory>/scripts/privacy_scrub.py input.docx sanitized.docx\n```\n\nScrubbing metadata is not content redaction. Search visible text, headers, footers, comments, tracked changes, fields, hyperlinks, images, and embedded objects separately when removing sensitive information.\n\n## Validate and render\n\nRun structural validation after every create or edit operation:\n\n```text\npython <this-skill-directory>/scripts/validate_docx.py output.docx\n```\n\nWhen LibreOffice and a PDF renderer are available, render the document:\n\n```text\npython <this-skill-directory>/scripts/render_docx.py output.docx rendered\n```\n\nInspect every rendered page at normal zoom. Rendering is strong evidence for layout, fonts, spacing, tables, images, headers, footers, and page breaks. It is not sufficient proof for comments, field instructions, content controls, accessibility metadata, or tracked-change structure.\n\nIf rendering is unavailable, perform structural validation and disclose that visual QA was skipped. Do not imply that the document passed a render gate.\n\n## Finish\n\nDeliver only the requested DOCX unless the user asks for rendered pages, PDF, or other intermediates. Report the output path, representative changes, structural checks, visual QA status, and any limitation involving fonts, fields, macros, signatures, comments, revisions, or unsupported OOXML features.\n","astrbot/builtin_stars/astrbot/skills/documents/references/advanced-ooxml.md":"# Advanced DOCX and OOXML operations\n\nRead this reference before modifying features that `python-docx` does not fully support.\n\n## Work safely\n\n1. Preserve the original package.\n2. Inspect ZIP members, content types, relationships, and the exact XML elements involved.\n3. Patch only the necessary parts and relationships.\n4. Write a new package without dropping unrelated members.\n5. Reopen with `python-docx`, parse every XML part, run structural validation, and render again.\n\nUse namespace-aware XML handling. Never use regular-expression replacement across XML markup.\n\n## Comments\n\nValidate all of these together:\n\n- `word/comments.xml`\n- comment relationships and content-type declarations\n- `w:commentRangeStart`, `w:commentRangeEnd`, and `w:commentReference` anchors\n- unique comment IDs and preserved author/date values\n\nHeadless PDF exports frequently omit comments. Structural validation remains mandatory.\n\n## Tracked changes\n\nTracked insertions and deletions use `w:ins` and `w:del`, with author, date, and ID metadata. Text inside deletions commonly uses `w:delText` rather than `w:t`.\n\n- Do not flatten revisions unless the user asks to accept or reject them.\n- Preserve revision metadata when adding or editing tracked changes.\n- Inspect headers, footers, footnotes, and comments in addition to the main document.\n- Render the revision view when possible, but also inspect the XML because renderer settings can hide revisions.\n\n## Fields and navigation\n\nTOCs, page numbers, cross-references, captions, and many calculated values use field instructions and cached display text.\n\n- Preserve `w:fldSimple` or complex `w:fldChar` begin/separate/end sequences.\n- Preserve bookmarks and relationship targets used by internal links.\n- Do not replace a dynamic field with static visible text unless the user requests flattening.\n- Disclose when Word or LibreOffice must refresh field results.\n\n## Content controls and forms\n\nContent controls use `w:sdt`. Preserve aliases, tags, data binding, locks, placeholder state, and repeating-section structure. Do not convert a content control to plain text merely to edit its visible value unless the user accepts losing the control.\n\n## Protection, macros, and signatures\n\n- Treat editing restrictions as workflow controls, not encryption.\n- Preserve macros only in macro-enabled formats and never execute them during inspection.\n- Do not remove or bypass protection without explicit authorization.\n- Any document edit can invalidate a digital signature. Preserve the signed source and report the consequence.\n\n## Merge and template operations\n\nDOCX parts can reuse style IDs, numbering IDs, relationship IDs, bookmark IDs, image names, and drawing IDs. A safe merge must remap collisions and preserve referenced parts. Prefer template-based creation or a well-tested merge library over appending raw XML from unrelated packages.\n","astrbot/builtin_stars/astrbot/skills/documents/references/styling.md":"# DOCX styling and layout\n\nUse this reference for new documents and major rewrites. For existing-document edits, preserve the document's style unless the user requests a redesign.\n\n## Choose a design system\n\nResolve the following values before authoring:\n\n- page size, orientation, margins, and header/footer distance\n- body font, East Asian font, base size, line spacing, and paragraph spacing\n- title and heading sizes, colors, and keep-with-next behavior\n- bullet and numbered-list indentation\n- table width, column widths, cell margins, borders, fills, and repeated headers\n- callout, caption, source-note, header, and footer treatments\n\nApply these values through Word styles and reusable table/list definitions. Use direct formatting only for intentional exceptions.\n\n## Recommended neutral preset\n\nFor a general professional document when the user provides no template:\n\n| Element | Suggested values |\n|---|---|\n| Page | A4 or Letter according to locale, portrait |\n| Margins | 20-25 mm / 0.8-1.0 in |\n| Body | 10.5-11 pt, 1.15-1.3 line spacing, 6-8 pt after |\n| Title | 24-28 pt, dark neutral, 12-18 pt after |\n| Heading 1 | 16-18 pt, 12-16 pt before, 6-8 pt after |\n| Heading 2 | 13-15 pt, 10-12 pt before, 4-6 pt after |\n| Heading 3 | 11-12 pt, 8 pt before, 3-4 pt after |\n| Table text | 9-10.5 pt with explicit cell margins |\n| Header/footer | 8-9 pt muted text, used only when helpful |\n\nFor Chinese documents, set both Latin and East Asian fonts on styles. Prefer a system font that can be rendered in the current environment and inspect the final pages for substitution or missing glyphs.\n\n## Use appropriate form factors\n\n- Use prose for background, explanation, and rationale.\n- Use numbered steps for sequences and procedures.\n- Use bullets for loose factors, requirements, and grouped considerations.\n- Use checklists for acceptance criteria and review tasks.\n- Use restrained callouts for decisions, warnings, and key takeaways.\n- Use tables for repeated comparable records, schedules, budgets, status grids, and forms.\n- Use captions and source notes near the figures or tables they describe.\n\nAvoid consecutive dense tables, walls of text, decorative separators, excessive accent colors, and tables used only to position ordinary prose.\n\n## Tables\n\n- Choose widths based on content rather than equal-width defaults.\n- Keep short identifiers, dates, statuses, and numeric fields compact.\n- Give narrative columns enough width to wrap naturally.\n- Set cell margins and vertical alignment explicitly.\n- Never use fixed row heights that can clip text.\n- Repeat header rows for multi-page tables.\n- Keep captions and short source notes with the table when practical.\n- Render and inspect every page containing a dense or multi-page table.\n\n## Existing templates\n\nTreat a user-provided template as the design authority. Inspect its styles, theme fonts, numbering, page sections, table styles, headers, footers, and sample content before editing. Extend the nearest matching styles instead of imposing this default preset.\n","astrbot/builtin_stars/astrbot/skills/pdf/SKILL.md":"---\nname: pdf\ndescription: Read, create, inspect, merge, split, rotate, encrypt, fill, and validate PDF files. Use when the user asks to work with a PDF or convert supported Markdown into a polished PDF in AstrBot.\n---\n\n# Work with PDFs\n\nUse `pypdf` for PDF structure operations and validation. Use ReportLab for new page layout. Do not install another PDF library unless the requested feature cannot be implemented safely with the bundled dependencies.\n\n## Follow the workflow\n\n1. Preserve source files unless the user explicitly requests an in-place change.\n2. Inspect the input with `pypdf.PdfReader`: page count, metadata, encryption, page sizes, text, annotations, and form fields as relevant.\n3. Perform the smallest operation that satisfies the request.\n4. Reopen every output with `pypdf` and verify its page count, expected text or fields, and encryption state.\n5. Render representative pages when a PDF renderer is available. Inspect the rendered images for clipping, overlap, missing glyphs, broken spacing, and blank pages. If rendering is unavailable, state that only structural validation was completed.\n\nWork in the current workspace unless the user provides another writable location. Keep intermediate files separate from final outputs and remove them when they are no longer needed.\n\n## Read and inspect\n\nUse `astrbot_file_read_tool` for a quick text extraction when it is sufficient. Use Python with `pypdf` when page structure or exact metadata matters:\n\n```python\nfrom pypdf import PdfReader\n\nreader = PdfReader(input_path)\nprint(len(reader.pages), reader.metadata)\nfor page_number, page in enumerate(reader.pages, start=1):\n    print(page_number, page.mediabox, page.rotation)\n    print(page.extract_text() or \"\")\n```\n\nText extraction does not prove that visual layout is correct. Render with `pdftoppm` when it is available:\n\n```text\npdftoppm -png -r 144 input.pdf rendered/page\n```\n\n## Create from Markdown\n\nPrefer the bundled deterministic converter:\n\n```text\npython <this-skill-directory>/scripts/markdown_to_pdf.py input.md output.pdf\n```\n\nThe converter intentionally supports a limited Markdown subset:\n\n- ATX headings (`#` through `######`)\n- paragraphs\n- flat ordered and unordered lists\n- block quotes\n- fenced code blocks\n- horizontal rules\n- `<!-- pagebreak -->`\n- bold, italic, inline code, and HTTP(S) or mail links\n\nIt does not interpret raw HTML, images, tables, nested lists, footnotes, or arbitrary Markdown extensions. Simplify unsupported content or explain the limitation instead of silently changing meaning.\n\nFont selection follows this order:\n\n1. Use an explicit readable font passed with `--font path/to/font.ttf` or `--font path/to/font.ttc`.\n2. Otherwise, search common system locations for a readable Chinese font and verify that it contains every character used by the document.\n3. If no suitable system font is available, use ReportLab's built-in Simplified Chinese fallback for supported Latin and Chinese text. The converter stops instead of silently emitting missing glyphs when the fallback cannot represent the input.\n\nWhen a broader or embedded font is required and no suitable system font is readable, download it into the workspace and pass its path with `--font`. Prefer an official source over an arbitrary font mirror or CDN:\n\n- [MiSans from Xiaomi](https://hyperos.mi.com/font/zh/download/) is an official source that is generally accessible from mainland China. Review its license before use and do not redistribute the font package unless the license permits it.\n- [Noto Sans CJK](https://github.com/notofonts/noto-cjk/blob/main/Sans/README.md) is an official open-source fallback with documented download options.\n\nIf an official GitHub font URL times out for a user in mainland China, the user may choose one of these third-party proxy prefixes:\n\n- `https://edgeone.gh-proxy.com/`\n- `https://hk.gh-proxy.com/`\n- `https://gh-proxy.com/`\n- `https://gh.dpik.top/`\n\nAppend the complete official GitHub URL directly after the prefix. For example:\n\n```text\nOfficial: https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/TTF/Subset/NotoSansSC-VF.ttf\nProxy:   https://edgeone.gh-proxy.com/https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/TTF/Subset/NotoSansSC-VF.ttf\n```\n\nThese proxies are not operated by the font project or AstrBot. Their availability and returned content can change. Never send credentials, private repository URLs, or other sensitive data through them. After downloading, verify that the final response used HTTPS, inspect the file type, and compare a checksum with an official checksum when one is published.\n\nDo not download a font silently. Obtain user approval when network access or a new file is required, use HTTPS, and keep the downloaded font in a workspace or temporary directory rather than installing it system-wide.\n\nAfter conversion, use `pypdf` to confirm the output opens, contains pages, and exposes representative expected text. Render and inspect the first page plus any page with dense content, code, or a page break.\n\n## Transform existing PDFs\n\nUse small `pypdf` scripts directly for ordinary operations.\n\nMerge documents in the requested order:\n\n```python\nfrom pypdf import PdfWriter\n\nwriter = PdfWriter()\nfor path in input_paths:\n    writer.append(path)\nwriter.write(output_path)\n```\n\nSplit selected pages without modifying the source:\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(input_path)\nwriter = PdfWriter()\nfor page_index in selected_zero_based_indexes:\n    writer.add_page(reader.pages[page_index])\nwriter.write(output_path)\n```\n\nRotate by a multiple of 90 degrees with `page.rotate(angle)`. Encrypt with `writer.encrypt(password)` only when the user asks, and never echo a password into logs or the final response. Reopen encrypted outputs with the password before reporting success.\n\n## Fill forms\n\nRead [forms.md](references/forms.md) before modifying AcroForms. Preserve interactivity unless the user requests a flattened result. Validate both the canonical field tree and page widget annotations; a successful render alone is not proof that field values were saved.\n\n## Finish\n\nReport the final path, the operation performed, and the validation completed. Mention any unsupported content, unavailable renderer, password requirement, or form ambiguity. Do not claim visual verification unless rendered pages were actually inspected.\n","astrbot/builtin_stars/astrbot/skills/pdf/references/forms.md":"# AcroForm handling\n\nUse this reference only for interactive PDF form tasks.\n\n## Inspect before editing\n\nCheck both representations of every field:\n\n1. Read the canonical tree with `PdfReader.get_fields()`.\n2. Enumerate `/Widget` annotations in every page's `/Annots` array.\n3. Follow `/Parent` and `/Kids` references when resolving field names and values.\n\nA widget can display a value from its appearance stream while the canonical `/AcroForm/Fields` tree contains a different value. If unrelated canonical fields and widgets reuse the same name, report the ambiguity instead of automatically reattaching fields.\n\n## Fill with pypdf\n\n```python\nfrom pypdf import PdfReader, PdfWriter\nfrom pypdf.generic import NameObject\n\nreader = PdfReader(input_path)\nwriter = PdfWriter()\nwriter.clone_document_from_reader(reader)\n\nwriter.reattach_fields()\nfields = writer.get_fields() or {}\nmissing = set(values) - set(fields)\nif missing:\n    raise ValueError(f\"Form fields not found: {sorted(missing)}\")\n\nvalues_to_write = dict(values)\nif flatten:\n    values_to_write = {\n        name: field.get(\"/V\", \"/Off\" if field.get(\"/FT\") == \"/Btn\" else \"\")\n        for name, field in fields.items()\n    }\n    values_to_write.update(values)\n\nwriter.update_page_form_field_values(\n    None,\n    values_to_write,\n    auto_regenerate=False,\n    flatten=flatten,\n)\n\nif flatten:\n    writer.remove_annotations(subtypes=\"/Widget\")\n    writer.root_object.pop(NameObject(\"/AcroForm\"), None)\n\nwith open(output_path, \"wb\") as output_file:\n    writer.write(output_file)\n```\n\nDo not flatten a signed document without an explicit decision from the user. Preserve the source and, when useful, retain an interactive copy alongside the flattened copy.\n\n## Validate after writing\n\nFor an interactive result:\n\n- Reopen the output and verify every expected field value in `get_fields()`.\n- Enumerate widgets again and verify their effective values, including inherited parent values.\n- Require updated widgets to have non-empty normal appearance streams under `/AP` and `/N`.\n- Render the affected pages to detect stale, clipped, or invisible appearances.\n\nFor a flattened result:\n\n- Require zero `/Widget` annotations.\n- Require no remaining `/AcroForm` field tree.\n- Render the affected pages and confirm the painted values remain visible.\n","astrbot/builtin_stars/astrbot/skills/skill-creator/SKILL.md":"---\nname: skill-creator\ndescription: Create, revise, and validate AstrBot Skills built around SKILL.md instruction bundles. Use when the user asks to create, scaffold, improve, package, or review a Skill for an AstrBot workspace, local installation, or plugin.\n---\n\n# Create AstrBot Skills\n\nBuild small, reusable instruction bundles that another agent can discover and follow reliably.\n\n## Follow the core design rules\n\n- Assume the model already knows general facts. Include only task-specific procedures, constraints, and resources.\n- Match instruction precision to risk. Use flexible guidance for judgment-heavy work and deterministic scripts for fragile operations.\n- Keep `SKILL.md` focused. Put detailed reference material in `references/`, repeatable automation in `scripts/`, and output material in `assets/`.\n- Link every optional resource directly from `SKILL.md` and state when to use it. Avoid deep chains of references.\n- Do not add process documents such as `README.md`, changelogs, installation guides, or quick-reference duplicates.\n- Do not add OpenAI- or Codex-specific metadata, directories, tools, or installation steps unless the user explicitly targets that runtime.\n\n## Establish the intended behavior\n\nBefore writing files, identify:\n\n1. Concrete requests that should trigger the Skill.\n2. Expected outputs or actions.\n3. Required tools, permissions, and runtime assumptions.\n4. Failure cases that need explicit guardrails.\n\nAsk only for information that materially changes the result. Infer ordinary details from the current task and environment.\n\n## Choose the target\n\nUse the runtime declared in the system instructions and the location requested by the user. Do not infer the runtime from filesystem paths.\n\nIn local mode, common targets are:\n\n- Workspace Skill: `<workspace>/skills/<skill-name>`\n- Locally installed Skill: `<astrbot-data>/skills/<skill-name>`.\n- Installed third-party plugin Skill: `<astrbot-data>/plugins/<plugin-name>/skills/<skill-name>`.\n\nIf no location is specified in local mode, create the Skill under `skills/<skill-name>` in the current AstrBot workspace. Creating or modifying a locally installed Skill requires administrator access and is enforced by the filesystem tools. If permission is denied, use the workspace target and explain the fallback.\n\nIn sandbox mode, do not use `<astrbot-data>` or attempt to install a Skill into the host AstrBot instance. Create it under `skills/<skill-name>` in the current sandbox workspace, and treat it as sandbox-scoped unless the runtime provides a dedicated persistence or release workflow.\n\nTreat plugin-provided Skills as read-only during normal runtime. Modify a plugin Skill only when the user is working in that plugin's source tree and has explicitly requested the change. If the requested target is not writable, create the Skill in the workspace and explain how to install or move it.\n\n## Name the Skill\n\n- Use lowercase letters, digits, and hyphens only.\n- Keep the name under 64 characters.\n- Prefer a short action-oriented name.\n- Name the folder exactly the same as the frontmatter `name`.\n\n## Plan only necessary resources\n\nFor each repeated operation, decide whether plain instructions are sufficient:\n\n- Add `scripts/` only for deterministic, repeatable operations.\n- Add `references/` only for material the agent may need to consult while working.\n- Add `assets/` only for files intended to be copied or incorporated into outputs.\n\nDo not create empty resource directories.\n\n## Write SKILL.md\n\nStart with YAML frontmatter containing only `name` and `description`:\n\n```yaml\n---\nname: example-skill\ndescription: Describe what the Skill does and the concrete requests or situations that should trigger it.\n---\n```\n\nMake the description specific enough for discovery. Put all trigger guidance in the description because AstrBot loads the body only after the Skill is selected.\n\nWrite the body as direct instructions:\n\n- Use imperative language.\n- Put the main workflow before edge cases.\n- State important safety boundaries close to the affected action.\n- Use the AstrBot tool names actually available in the current runtime when a workflow depends on tools.\n- Prefer relative paths inside the Skill so it works after installation or sandbox synchronization.\n- Keep examples short and representative.\n\n## Initialize or update files\n\nFor a new Skill, prefer the bundled initializer when Python and shell execution are available:\n\n```text\npython <this-skill-directory>/scripts/init_skill.py <skill-name> --path <target-skills-root> --description <description>\n```\n\nAdd `--resources scripts,references,assets` with only the directories that are needed. The initializer refuses to overwrite an existing Skill.\n\nIf shell execution is unavailable, create the directory and UTF-8 `SKILL.md` with `astrbot_file_write_tool`. Create optional resources only after their content is known.\n\nWhen updating a Skill, read its complete `SKILL.md` and directly referenced resources before editing. Preserve useful behavior and avoid unrelated restructuring.\n\n## Validate\n\nWhen Python and shell execution are available, run:\n\n```text\npython <this-skill-directory>/scripts/validate_skill.py <created-skill-directory>\n```\n\nOtherwise verify manually:\n\n- The directory name is valid and matches frontmatter `name`.\n- `SKILL.md` is UTF-8 and has valid YAML frontmatter.\n- `description` explains both capability and trigger conditions.\n- The body is non-empty and operational.\n- Every referenced file exists and every bundled file has a clear purpose.\n- Instructions do not assume unavailable tools, paths, credentials, or permissions.\n\nRun any bundled scripts on representative safe inputs. Fix validation or execution failures before presenting the Skill.\n\n## Finish\n\nReport the created or updated location, included resources, validation performed, and any runtime or activation step still required. Do not enable a globally installed Skill or change an AstrBot configuration unless the user requested it.\n","astrbot/builtin_stars/astrbot/skills/spreadsheets/SKILL.md":"---\nname: spreadsheets\ndescription: Create, read, edit, analyze, convert, chart, and validate spreadsheet files including XLSX, XLSM, XLS, CSV, and TSV. Use when a spreadsheet is a primary input or deliverable, or when tabular data must remain editable and auditable in workbook form.\n---\n\n# Work with spreadsheets\n\nUse `openpyxl` for XLSX/XLSM authoring, `xlrd` for legacy XLS reading, `pandas` for substantial data cleaning or analysis, and the standard `csv` module for simple CSV/TSV work. Preserve the source unless the user explicitly requests an in-place edit.\n\n## Choose the workflow\n\n1. For a read-only question, inspect only the relevant sheets, labels, values, formulas, tables, charts, and comments. Do not export a modified copy.\n2. For an existing workbook, study its structure and formatting before editing. Apply the smallest local change and extend nearby formulas, validation, conditional formatting, tables, and charts when the edited range requires it.\n3. For a new workbook, separate inputs, calculations, and outputs when the task contains derived values. Keep calculations visible and auditable.\n4. Save to a new file, reopen it, validate formulas and structure, and render every populated sheet when a renderer is available.\n\nUse the bundled inspector before unfamiliar edits:\n\n```text\npython <this-skill-directory>/scripts/inspect_workbook.py input.xlsx\n```\n\n## Respect format boundaries\n\n- Use `openpyxl.load_workbook(..., keep_vba=True)` for XLSM files and preserve the `.xlsm` extension. Do not claim that macros were inspected or are safe merely because they were preserved.\n- Treat XLS as a legacy read-only source. `xlrd` reads values and basic metadata but does not provide reliable modern editing. Convert the result to XLSX or CSV instead of overwriting the XLS file.\n- Preserve CSV/TSV delimiter, quoting, encoding, header order, and typed meaning. Keep identifiers such as ZIP codes and account numbers as text.\n- Never change a workbook's file extension without actually converting its format.\n\n## Keep formulas auditable\n\n- Write derived values as formulas rather than hardcoded results.\n- Place assumptions and raw inputs in visible cells or dedicated sheets.\n- Avoid magic numbers inside formulas. Reference an assumption cell instead.\n- Use correct absolute and relative references for fill behavior.\n- Quote every cross-sheet name: `='Revenue Model'!B4`, even when the current name has no spaces.\n- Prefer bounded ranges over full-column references in calculation-heavy formulas.\n- Use helper cells when a formula becomes difficult to understand or audit.\n- Add comments to important assumptions and source-backed inputs.\n- Check for `#REF!`, `#DIV/0!`, `#VALUE!`, `#NAME?`, `#NUM!`, `#NULL!`, and unexpected circular references.\n\n`openpyxl` writes formulas but does not calculate them. If formulas must be recalculated, open and save a copy with LibreOffice or Excel when available, then reopen the result with `data_only=False` and `data_only=True`. Never replace formulas with calculated constants merely to make validation pass. Read [formulas.md](references/formulas.md) for the detailed validation contract.\n\n## Format by meaning\n\nRead [formatting.md](references/formatting.md) before creating or substantially redesigning a workbook.\n\n- Store dates, numbers, currency, and percentages as typed values with explicit number formats.\n- Distinguish title, header, input, calculation, output, note, and warning roles consistently.\n- Prefer restrained fills and light structural borders. Do not decorate every populated cell with a border.\n- Freeze useful headers, enable filters, and use named tables for editable datasets.\n- Prefer conditional formatting over one-time manual fills when color represents a value or status.\n- Use data validation for editable categorical fields when practical.\n- Size columns and rows deliberately. Widen before wrapping, cap very wide columns, and avoid formatting unused ranges.\n- Hide gridlines only when explicit formatting already provides structure.\n\n## Use charts deliberately\n\nRead [charts.md](references/charts.md) before creating or editing charts. Create a chart only when it improves comparison, trend, distribution, ranking, progress, or relationship understanding.\n\n- Link chart series to worksheet ranges, not duplicated literal values.\n- Keep units explicit and titles focused on one takeaway.\n- Place charts in reserved areas without covering source data or controls.\n- Verify categories, series orientation, source ranges, point counts, axes, and placement after saving.\n- Prefer a compact table over a chart when exact values are the main point.\n\n## Convert CSV or TSV\n\nUse the bundled converter for a clean, typed, filterable workbook:\n\n```text\npython <this-skill-directory>/scripts/csv_to_xlsx.py input.csv output.xlsx\npython <this-skill-directory>/scripts/csv_to_xlsx.py input.tsv output.xlsx --delimiter tab\n```\n\nThe converter infers conservative scalar types, freezes the header, creates a table, applies number formats, and caps column widths. Inspect identifiers and locale-specific dates before accepting inferred types.\n\n## Validate and render\n\nRun structural validation after every create or edit operation:\n\n```text\npython <this-skill-directory>/scripts/validate_workbook.py output.xlsx\n```\n\nWhen LibreOffice and a PDF renderer are available, render the workbook:\n\n```text\npython <this-skill-directory>/scripts/render_workbook.py output.xlsx rendered\n```\n\nInspect every rendered page at normal zoom. Check for clipped headers or values, unexpected blank pages, broken charts, unreadable colors, bad page breaks, missing glyphs, formula errors, and content outside the visible area. Rendering does not prove formula correctness; structural and formula validation remain required.\n\nIf rendering is unavailable, report that only structural validation was completed. Do not imply that a workbook passed visual QA.\n\n## Finish\n\nDeliver only the requested workbook or tabular output unless the user asks for previews or intermediates. Report the output path, important sheets or changes, formula/recalculation status, validation performed, and any limitation involving macros, legacy XLS, unsupported formulas, fonts, or rendering.\n","astrbot/builtin_stars/astrbot/skills/spreadsheets/references/charts.md":"# Spreadsheet charts\n\nCreate a chart only when it makes a comparison, trend, distribution, ranking, progress measure, or relationship easier to understand.\n\n## Select a chart\n\n- Use bars or columns for category comparison and ranking.\n- Use lines for trends over time.\n- Use scatter plots for relationships between numeric variables.\n- Use a histogram for a distribution when supported by the target viewer.\n- Use pie or doughnut charts only for a small number of meaningful parts of one whole.\n- Use a compact table when exact values matter more than visual pattern.\n\n## Build auditable chart data\n\n- Link series and categories directly to worksheet cells.\n- Use a formula-backed helper range only when reshaping, grouping dates, or shortening labels is necessary.\n- Keep unknown values blank rather than inventing zeroes.\n- Verify headers are not included as numeric points.\n- Keep category and value ranges the same length.\n- Use a text helper label such as `2026-08` when date-axis rendering is unreliable.\n\n## Format and place\n\n- Give each chart one clear takeaway and include units in the title or axis.\n- Use restrained, consistent colors and avoid gradients, 3D effects, and heavy borders.\n- Keep labels, ticks, legends, and titles readable at normal zoom.\n- Place charts beside or below the data they explain with blank gutters around them.\n- Do not cover cells, controls, notes, or other charts.\n- Set explicit axis number formats for currency, percentages, and dates.\n\nAfter saving, reopen the workbook and inspect chart series formulas. Render the sheet and check for blank charts, clipped labels, stale ranges, wrong orientation, unreadable legends, and excessive whitespace.\n","astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formatting.md":"# Spreadsheet formatting\n\nUse this reference for new workbooks and substantial redesigns. Preserve an existing workbook's visual language unless the user requests a redesign.\n\n## Establish roles\n\nChoose a small role-based style system before writing cells:\n\n| Role | Default treatment |\n|---|---|\n| Workbook title | 16-18 pt, bold, dark neutral text, generous spacing |\n| Section title | 12-14 pt, bold, restrained accent or neutral fill |\n| Table header | Bold, high-contrast fill, centered only when appropriate |\n| Input | Light neutral or pale blue fill, unlocked when protection is used |\n| Formula | No fill or a subtle neutral fill; keep formulas visible |\n| Key output | Bold, explicit number format, light callout fill |\n| Note/source | Smaller muted text, URL in cell or comment |\n| Warning | Restrained amber or red used only for actionable exceptions |\n\nUse one body font and one optional display font. Prefer fonts commonly available across platforms. For Chinese workbooks, verify the chosen CJK font in the actual render environment (`fc-match \"Font Name\"` when Fontconfig is available), then inspect the rendered pages for substitution or missing glyphs. Keep body text around 10-11 pt and do not depend on color alone to communicate status.\n\n## Lay out the workbook\n\n- Put a clear title or table header near the top-left of each important sheet.\n- Keep assumptions and inputs separate from derived calculations in complex models.\n- Place important totals or KPIs where users can find them without scrolling to the bottom.\n- Freeze the header row for long tables and freeze identifier columns for wide tables.\n- Add filters or an Excel table for editable datasets.\n- Avoid merged cells in calculation or filter ranges. Reserve merges for titles or compact presentation labels.\n- Set print area, orientation, margins, repeated header rows, and fit-to-width for reports intended to print or render.\n- Remove empty default sheets and avoid large formatted-but-empty used ranges.\n\n## Size and align cells\n\n- Left-align descriptive text, right-align numbers, and use intentional alignment for short statuses and dates.\n- Widen columns before enabling deep wrapping. Cap descriptive columns around 50-60 characters unless the user requests otherwise.\n- Increase row height only enough to reveal wrapped content.\n- Use explicit formats such as `#,##0`, `#,##0.00`, `0.0%`, `yyyy-mm-dd`, and currency formats appropriate to the requested currency.\n- Preserve identifiers as text when leading zeroes or exact digits matter.\n\n## Tables and conditional formatting\n\n- Use light internal borders and a clearer outside or header boundary.\n- Use banded rows only when they materially improve scanning.\n- Apply conditional formatting over the intended editable range, not an entire worksheet.\n- Verify that formulas used by conditional formatting are anchored correctly at the top-left cell of the applied range.\n- Prefer data bars, color scales, or icon sets only when their scale and direction are meaningful.\n\n## Accessibility and usability\n\n- Use descriptive sheet names and unique table names.\n- Avoid hidden assumptions and unexplained abbreviations.\n- Add comments for important assumptions, unusual formulas, and data provenance.\n- Use data validation prompts and error messages for constrained inputs.\n- Keep color contrast readable and provide text or numeric cues in addition to color.\n","astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formulas.md":"# Formula and validation rules\n\nUse this reference for formula-heavy workbooks and any task where calculated outputs matter.\n\n## Author formulas\n\n1. Create every referenced sheet before assigning cross-sheet formulas.\n2. Use formulas for derived values and hardcode only assumptions, raw facts, or explicitly requested fixed outputs.\n3. Use `$` anchors deliberately and test the first, middle, and last filled formulas.\n4. Quote sheet names in cross-sheet references.\n5. Bound lookup and aggregation ranges to the intended data area.\n6. Prefer `IFERROR` only when the fallback has a clear business meaning. Do not hide an unexpected error.\n7. Keep units consistent across inputs and outputs.\n\n## Understand calculation limits\n\n`openpyxl` preserves and writes formulas but does not calculate them. Loading with `data_only=True` returns cached values last saved by a calculating application; a newly authored formula may have no cached value.\n\nWhen a calculated result is required:\n\n1. Save the workbook with formulas intact.\n2. If LibreOffice or Excel is available, open and save a copy to recalculate it.\n3. Reopen the recalculated copy twice: once with `data_only=False` to verify formulas and once with `data_only=True` to inspect cached results.\n4. Reconcile important totals independently in Python for high-risk outputs.\n\nDo not treat a missing cached value as proof that a formula is wrong. Do treat a literal error value, `#REF!` inside a formula, a broken chart range, or a missing sheet reference as an error.\n\n## Validate\n\n- Scan all populated cells for Excel error literals.\n- Scan formulas and chart series for `#REF!`.\n- Confirm table and filter ranges include their headers and intended rows.\n- Confirm data validation and conditional-format ranges include future editable rows when requested.\n- Check duplicate table and defined-name identifiers.\n- Check for formulas that accidentally reference the header row or omit the final data row.\n- Review external links and disclose them; do not silently remove them.\n- Open macro-enabled files with `keep_vba=True` and preserve their extension.\n\nFor financial, legal, medical, or other high-stakes workbooks, independently recalculate representative results and document assumptions and source URLs inside the workbook.\n"},"files":{".github/copilot-instructions.md":"# AstrBot Development Instructions\n\nAstrBot is a multi-platform LLM chatbot and development framework written in Python with a Vue.js dashboard. It supports multiple messaging platforms (QQ, Telegram, Discord, etc.) and various LLM providers (OpenAI, Anthropic, Google Gemini, etc.).\n\nAlways reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.\n\n## Working Effectively\n\n### Bootstrap and Install Dependencies\n- **Python 3.10+ required** - Check `.python-version` file\n- Install UV package manager: `pip install uv`\n- Install project dependencies: `uv sync` -- takes 6-7 minutes. NEVER CANCEL. Set timeout to 10+ minutes.\n- Create required directories: `mkdir -p data/plugins data/config data/temp`\n\n### Running the Application\n- Run main application: `uv run main.py` -- starts in ~3 seconds\n- Application creates WebUI on http://localhost:6185 (default credentials: `astrbot`/`astrbot`)\n\n### Dashboard Build (Vue.js/Node.js)\n- **Prerequisites**: Node.js 20+ and npm 10+ required\n- Navigate to dashboard: `cd dashboard`\n- Install dashboard dependencies: `npm install` -- takes 2-3 minutes. NEVER CANCEL. Set timeout to 5+ minutes.\n- Build dashboard: `npm run build` -- takes 25-30 seconds. NEVER CANCEL.\n- Dashboard creates optimized production build in `dashboard/dist/`\n\n### Testing\n- Do not generate test files for now.\n\n### Code Quality and Linting\n- Install ruff linter: `uv add --dev ruff`\n- Check code style: `uv run ruff check .` -- takes <1 second\n- Check formatting: `uv run ruff format --check .` -- takes <1 second\n- Fix formatting: `uv run ruff format .`\n- **ALWAYS** run `uv run ruff check .` and `uv run ruff format .` before committing changes\n\n### Plugin Development\n- Plugins load from `astrbot/builtin_stars/` (built-in) and `data/plugins/` (user-installed)\n- Plugin system supports function tools and message handlers\n- Key plugins: python_interpreter, web_searcher, astrbot, reminder, session_controller\n\n### Common Issues and Workarounds\n- **Dashboard download fails**: Known issue with \"division by zero\" error - application still works\n- **Import errors in tests**: Ensure `uv run` is used to run tests in proper environment\n=- **Build timeouts**: Always set appropriate timeouts (10+ minutes for uv sync, 5+ minutes for npm install)\n\n## CI/CD Integration\n- GitHub Actions workflows in `.github/workflows/`\n- Docker builds supported via `Dockerfile`\n- Pre-commit hooks enforce ruff formatting and linting\n\n## Docker Support\n- Primary deployment method: `docker run soulter/astrbot:latest`\n- Compose file available: `compose.yml`\n- Exposes ports: 6185 (WebUI), 6195 (WeChat), 6199 (QQ), etc.\n- Volume mount required: `./data:/AstrBot/data`\n\n## Multi-language Support\n- Documentation in Chinese (README.md), English (README_en.md), Japanese (README_ja.md)\n- UI supports internationalization\n- Default language is Chinese\n\nRemember: This is a production chatbot framework with real users. Always test thoroughly and ensure changes don't break existing functionality.\n","AGENTS.md":"## Setup commands\n\n### Core\n\n```\nuv sync\nuv run main.py\n```\n\nExposed an API server on `http://localhost:6185` by default.\n\n### Dashboard(WebUI)\n\n```\ncd dashboard\npnpm install # First time only. Use npm install -g pnpm if pnpm is not installed.\npnpm dev\n```\n\nRuns on `http://localhost:3000` by default.\n\n## Pre-commit setup\n\nAstrBot uses [pre-commit](https://pre-commit.com/) hooks to automatically format and lint Python code before each commit. The hooks run `ruff check`, `ruff format`, and `pyupgrade` (see [`.pre-commit-config.yaml`](.pre-commit-config.yaml) for details).\n\nTo set it up:\n\n```bash\npip install pre-commit\npre-commit install\n```\n\nAfter installation, the hooks will run automatically on `git commit`. You can also run them manually at any time:\n\n```bash\nruff format .\nruff check .\n```\n\n> **Note:** If you use VSCode, install the `Ruff` extension for real-time formatting and linting in the editor.\n\n## Dev environment tips\n\n### Basic\n\n1. When modifying the WebUI, be sure to maintain componentization and clean code. Avoid duplicate code.\n2. Do not add any report files such as xxx_SUMMARY.md.\n3. After finishing, use `ruff format .` and `ruff check .` to format and check the code.\n4. When committing, ensure to use conventional commits messages, such as `feat: add new agent for data analysis` or `fix: resolve bug in provider manager`.\n5. Use **English** for all comments and logs.\n6. For path handling, use `pathlib.Path` instead of string paths, and use `astrbot.core.utils.path_utils` to get the AstrBot data and temp directory.\n7. When backend API routes, request/response schemas, or OpenAPI definitions change, regenerate the frontend API client by running `cd dashboard && pnpm generate:api`.\n8. When updating the project version, keep `[project].version` in `pyproject.toml` and `__version__` in `astrbot/__init__.py` in sync. `VERSION` in `astrbot/core/config/default.py` should derive from `astrbot.__version__` instead of hardcoding a separate version string.\n9. When designing WebUI dialogs, use `text-h3 pa-4 pb-0 pl-6` as the base class for dialog titles, and use `variant=\"text\"` or `variant=\"tonal\"` for dialog buttons.\n10. Consider cross-platform compatibility (e.g., Windows, macOS, and Linux, as well as Arm64 and x86 CPU architectures) and compatibility with Python 3.10+.\n11. When changing WebUI navigation, page structure, or terminology, update the affected instructions and screenshots in `docs/zh` and `docs/en` in the same PR. For renamed, moved, or merged entry points, include an old-to-new mapping in the relevant docs and changelog. Keep layout redesigns separate from feature additions where practical, and explain necessary navigation changes in the PR. See `CONTRIBUTING.md` for the review checklist.\n\n### KISS and First Principles\n\nFollow the KISS principle and reason from first principles during development. Start by identifying the real problem, required behavior, and smallest useful change before adding code. Do not pile on features, configuration switches, abstractions, dependencies, or compatibility layers unless they directly solve the current problem and have clear evidence of need.\n\nPrefer the simplest implementation that is correct, maintainable, and consistent with the existing codebase. If a broader design seems attractive, reduce it to the essential behavior needed now and leave optional expansion for a later, explicit requirement.\n\n### No Unnecessary Helpers\n\nPrioritize inline implementation over abstraction. Avoid over-engineering and do not create helper functions unless absolutely necessary.\n\n1. **Inline-First Rule**: If a logic block can be implemented directly within the main function without breaking overall readability, **do not** extract it into a new helper function.\n2. **Strict Justification for Helpers**: You may only create a separate helper function if it meets at least one of these criteria:\n   - **High Reuse**: The exact same logic is repeated across **3 or more** different locations.\n   - **Extreme Complexity**: Inlining the logic makes the main function too long (e.g., >50 lines) or severely derails the main execution flow.\n3. **No Fragmentation**: Do not split continuous linear logic (e.g., a single API call, simple form validation, or one-time data formatting) into tiny functions just for the sake of \"clean code.\"\n4. **Keep Context Compact**: Handle edge cases, error catching, and logging directly inside the main function block instead of offloading them.\n5. **Refactoring Constraint**: When modifying existing code, do not alter the current function structure or extract code into new helpers unless the existing code already violates the complexity or reuse rules above.\n\n### Mandatory Google-Style Docstrings\n* **Comment the complex**: Add clear comments to any non-obvious function, method, or parameter.\n* **Google Format**: All docstrings must strictly use the Google format (`Args:`, `Returns:`, `Raises:`).\n\n#### Example:\n\n```py\ndef calculate_metrics(user_id: int, force_refresh: bool = False) -> dict:\n    \"\"\"Brief description of the function.\n\n    Args:\n        user_id: Description of the ID.\n        force_refresh: Description of the flag.\n\n    Returns:\n        Description of the returned dict.\n\n    Raises:\n        ValueError: Description of when this occurs.\n    \"\"\"\n    # Inline implementation here...\n```\n\n\n## PR instructions\n\n1. Title format: use conventional commit messages\n2. Use English to write PR title and descriptions.\n\n## Release versions\n\nUse a short-lived `release/*` branch for each release. The release branch is the stabilization area for version bumps, changelog updates, release-blocking fixes, and final validation only. Do not add unrelated features or broad refactors to a release branch.\n\nPrepare a release from a clean worktree with:\n\n```bash\nuv run python scripts/prepare_release.py 4.25.0\n```\n\nThe script updates `pyproject.toml` and `astrbot/__init__.py`, creates `changelogs/v4.25.0.md`, runs the required Python checks, and prints the remaining steps. Use these flags when needed:\n\n```bash\nuv run python scripts/prepare_release.py 4.25.0 --generate-api-client\nuv run python scripts/prepare_release.py 4.25.0 --dashboard-build\nuv run python scripts/prepare_release.py 4.25.0 --commit --push\n```\n\nOpen a PR from `release/4.25.0` to `master`. The PR title must use the conventional commit format, for example `chore: bump version to 4.25.0`. After the release PR is merged, create and push the tag from the updated `master` branch so the tag points to the exact code that was merged:\n\n```bash\ngit checkout master\ngit pull --ff-only origin master\ngit tag v4.25.0\ngit push origin v4.25.0\n```\n\nFor one-off release candidate branches, delete the release branch after the tag is pushed and verified. For maintained release lines, use a branch such as `release/4.25` and keep it until that line reaches EOL.\n\n```bash\ngit branch -d release/4.25.0\ngit push origin --delete release/4.25.0\n```\n","astrbot/builtin_stars/astrbot/skills/documents/SKILL.md":"---\nname: documents\ndescription: Create, read, edit, review, comment on, sanitize, render, and validate Microsoft Word DOCX documents. Use whenever a DOCX or Word document is a primary input or deliverable, including reports, proposals, forms, templates, tracked revisions, comments, tables, images, headers, footers, and style-preserving edits.\n---\n\n# Work with DOCX documents\n\nUse `python-docx` for ordinary creation and editing. Use direct OOXML inspection or small targeted patches only for features that `python-docx` cannot represent safely. Preserve the source unless the user explicitly requests an in-place edit.\n\n## Follow the workflow\n\n1. Inspect the source document's text, styles, sections, tables, images, comments, fields, tracked changes, content controls, headers, footers, and metadata as relevant.\n2. For edits, preserve the existing design and apply the smallest local change. Do not rebuild the document merely because creating a new one is easier.\n3. For new documents and major rewrites, choose a coherent design system before authoring. Read [styling.md](references/styling.md).\n4. Save to a new DOCX, reopen it with `python-docx`, validate the OOXML package, and render every page when LibreOffice and a PDF renderer are available.\n5. Inspect the rendered pages and iterate until there is no clipping, overlap, broken table geometry, missing glyph, awkward page break, or header/footer problem.\n\nUse the bundled inspector before unfamiliar edits:\n\n```text\npython <this-skill-directory>/scripts/inspect_docx.py input.docx\n```\n\nFor a quick text-only read, `astrbot_file_read_tool` is sufficient. Text extraction does not prove layout, comments, fields, tracked changes, or images are correct.\n\n## Create and edit with real document structure\n\n- Use Word paragraph styles for Normal, Title, Subtitle, Heading 1, Heading 2, and Heading 3 rather than styling every paragraph directly.\n- Use real list styles or numbering definitions. Do not type bullet characters, hyphen prefixes, or manual numbers into ordinary paragraphs.\n- Use tables only for genuinely tabular, comparable, or form-like content. Do not package long prose into grids.\n- Set page size, margins, orientation, header/footer distance, and section breaks explicitly.\n- Size table columns deliberately, enable wrapping, avoid fixed row heights, and repeat header rows when a table spans pages.\n- Preserve hyperlinks, relationships, bookmarks, captions, fields, comments, and tracked changes that are outside the requested edit.\n- Keep headings with following content and avoid leaving a heading alone at the bottom of a page.\n- Use comments for review feedback at the relevant text rather than collecting every note at the end.\n\n## Handle fonts and Chinese text\n\nDOCX files normally record font names rather than embedding the actual fonts. Choose common fonts and expect the opening application to substitute when a font is unavailable.\n\nSet all relevant Word font mappings for each styled run or style:\n\n```python\nfrom docx.oxml.ns import qn\n\nrun.font.name = \"Noto Sans CJK SC\"\nfonts = run._element.get_or_add_rPr().get_or_add_rFonts()\nfonts.set(qn(\"w:ascii\"), \"Noto Sans CJK SC\")\nfonts.set(qn(\"w:hAnsi\"), \"Noto Sans CJK SC\")\nfonts.set(qn(\"w:eastAsia\"), \"Noto Sans CJK SC\")\n```\n\nPrefer the user's template fonts. For a new cross-platform Chinese document, choose a readable system CJK font, verify that it exists in the actual render environment (`fc-match \"Font Name\"` when Fontconfig is available), and inspect the rendered output. Do not claim font consistency across devices unless the required font is installed or intentionally embedded with a licensed workflow.\n\n## Preserve advanced features\n\nRead [advanced-ooxml.md](references/advanced-ooxml.md) before changing tracked revisions, fields, content controls, protection, footnotes, endnotes, macros, digital signatures, or document relationships.\n\n- `python-docx` can create and read ordinary comments in current versions, but comments still require structural validation because headless renderers may omit them.\n- Tracked changes are not a safe first-class editing surface. Use targeted OOXML patches and preserve author/date data.\n- A visible table of contents is often cached field content. Preserve the field instructions and disclose when a calculating Word-compatible application must refresh them.\n- Preserve VBA only when explicitly working with a macro-enabled format. Do not rename DOCM to DOCX or claim macros are safe.\n- Editing a digitally signed document invalidates its signature. Preserve the source and report this before modifying it.\n\n## Inspect privacy and metadata\n\nReview author, last editor, creation/modification time, comments, tracked-change authors, custom properties, hidden text, document variables, external links, and embedded files before publishing sensitive documents.\n\nUse the bundled scrubber only when the user requests metadata removal:\n\n```text\npython <this-skill-directory>/scripts/privacy_scrub.py input.docx sanitized.docx\n```\n\nScrubbing metadata is not content redaction. Search visible text, headers, footers, comments, tracked changes, fields, hyperlinks, images, and embedded objects separately when removing sensitive information.\n\n## Validate and render\n\nRun structural validation after every create or edit operation:\n\n```text\npython <this-skill-directory>/scripts/validate_docx.py output.docx\n```\n\nWhen LibreOffice and a PDF renderer are available, render the document:\n\n```text\npython <this-skill-directory>/scripts/render_docx.py output.docx rendered\n```\n\nInspect every rendered page at normal zoom. Rendering is strong evidence for layout, fonts, spacing, tables, images, headers, footers, and page breaks. It is not sufficient proof for comments, field instructions, content controls, accessibility metadata, or tracked-change structure.\n\nIf rendering is unavailable, perform structural validation and disclose that visual QA was skipped. Do not imply that the document passed a render gate.\n\n## Finish\n\nDeliver only the requested DOCX unless the user asks for rendered pages, PDF, or other intermediates. Report the output path, representative changes, structural checks, visual QA status, and any limitation involving fonts, fields, macros, signatures, comments, revisions, or unsupported OOXML features.\n","astrbot/builtin_stars/astrbot/skills/documents/references/advanced-ooxml.md":"# Advanced DOCX and OOXML operations\n\nRead this reference before modifying features that `python-docx` does not fully support.\n\n## Work safely\n\n1. Preserve the original package.\n2. Inspect ZIP members, content types, relationships, and the exact XML elements involved.\n3. Patch only the necessary parts and relationships.\n4. Write a new package without dropping unrelated members.\n5. Reopen with `python-docx`, parse every XML part, run structural validation, and render again.\n\nUse namespace-aware XML handling. Never use regular-expression replacement across XML markup.\n\n## Comments\n\nValidate all of these together:\n\n- `word/comments.xml`\n- comment relationships and content-type declarations\n- `w:commentRangeStart`, `w:commentRangeEnd`, and `w:commentReference` anchors\n- unique comment IDs and preserved author/date values\n\nHeadless PDF exports frequently omit comments. Structural validation remains mandatory.\n\n## Tracked changes\n\nTracked insertions and deletions use `w:ins` and `w:del`, with author, date, and ID metadata. Text inside deletions commonly uses `w:delText` rather than `w:t`.\n\n- Do not flatten revisions unless the user asks to accept or reject them.\n- Preserve revision metadata when adding or editing tracked changes.\n- Inspect headers, footers, footnotes, and comments in addition to the main document.\n- Render the revision view when possible, but also inspect the XML because renderer settings can hide revisions.\n\n## Fields and navigation\n\nTOCs, page numbers, cross-references, captions, and many calculated values use field instructions and cached display text.\n\n- Preserve `w:fldSimple` or complex `w:fldChar` begin/separate/end sequences.\n- Preserve bookmarks and relationship targets used by internal links.\n- Do not replace a dynamic field with static visible text unless the user requests flattening.\n- Disclose when Word or LibreOffice must refresh field results.\n\n## Content controls and forms\n\nContent controls use `w:sdt`. Preserve aliases, tags, data binding, locks, placeholder state, and repeating-section structure. Do not convert a content control to plain text merely to edit its visible value unless the user accepts losing the control.\n\n## Protection, macros, and signatures\n\n- Treat editing restrictions as workflow controls, not encryption.\n- Preserve macros only in macro-enabled formats and never execute them during inspection.\n- Do not remove or bypass protection without explicit authorization.\n- Any document edit can invalidate a digital signature. Preserve the signed source and report the consequence.\n\n## Merge and template operations\n\nDOCX parts can reuse style IDs, numbering IDs, relationship IDs, bookmark IDs, image names, and drawing IDs. A safe merge must remap collisions and preserve referenced parts. Prefer template-based creation or a well-tested merge library over appending raw XML from unrelated packages.\n","astrbot/builtin_stars/astrbot/skills/documents/references/styling.md":"# DOCX styling and layout\n\nUse this reference for new documents and major rewrites. For existing-document edits, preserve the document's style unless the user requests a redesign.\n\n## Choose a design system\n\nResolve the following values before authoring:\n\n- page size, orientation, margins, and header/footer distance\n- body font, East Asian font, base size, line spacing, and paragraph spacing\n- title and heading sizes, colors, and keep-with-next behavior\n- bullet and numbered-list indentation\n- table width, column widths, cell margins, borders, fills, and repeated headers\n- callout, caption, source-note, header, and footer treatments\n\nApply these values through Word styles and reusable table/list definitions. Use direct formatting only for intentional exceptions.\n\n## Recommended neutral preset\n\nFor a general professional document when the user provides no template:\n\n| Element | Suggested values |\n|---|---|\n| Page | A4 or Letter according to locale, portrait |\n| Margins | 20-25 mm / 0.8-1.0 in |\n| Body | 10.5-11 pt, 1.15-1.3 line spacing, 6-8 pt after |\n| Title | 24-28 pt, dark neutral, 12-18 pt after |\n| Heading 1 | 16-18 pt, 12-16 pt before, 6-8 pt after |\n| Heading 2 | 13-15 pt, 10-12 pt before, 4-6 pt after |\n| Heading 3 | 11-12 pt, 8 pt before, 3-4 pt after |\n| Table text | 9-10.5 pt with explicit cell margins |\n| Header/footer | 8-9 pt muted text, used only when helpful |\n\nFor Chinese documents, set both Latin and East Asian fonts on styles. Prefer a system font that can be rendered in the current environment and inspect the final pages for substitution or missing glyphs.\n\n## Use appropriate form factors\n\n- Use prose for background, explanation, and rationale.\n- Use numbered steps for sequences and procedures.\n- Use bullets for loose factors, requirements, and grouped considerations.\n- Use checklists for acceptance criteria and review tasks.\n- Use restrained callouts for decisions, warnings, and key takeaways.\n- Use tables for repeated comparable records, schedules, budgets, status grids, and forms.\n- Use captions and source notes near the figures or tables they describe.\n\nAvoid consecutive dense tables, walls of text, decorative separators, excessive accent colors, and tables used only to position ordinary prose.\n\n## Tables\n\n- Choose widths based on content rather than equal-width defaults.\n- Keep short identifiers, dates, statuses, and numeric fields compact.\n- Give narrative columns enough width to wrap naturally.\n- Set cell margins and vertical alignment explicitly.\n- Never use fixed row heights that can clip text.\n- Repeat header rows for multi-page tables.\n- Keep captions and short source notes with the table when practical.\n- Render and inspect every page containing a dense or multi-page table.\n\n## Existing templates\n\nTreat a user-provided template as the design authority. Inspect its styles, theme fonts, numbering, page sections, table styles, headers, footers, and sample content before editing. Extend the nearest matching styles instead of imposing this default preset.\n","astrbot/builtin_stars/astrbot/skills/pdf/SKILL.md":"---\nname: pdf\ndescription: Read, create, inspect, merge, split, rotate, encrypt, fill, and validate PDF files. Use when the user asks to work with a PDF or convert supported Markdown into a polished PDF in AstrBot.\n---\n\n# Work with PDFs\n\nUse `pypdf` for PDF structure operations and validation. Use ReportLab for new page layout. Do not install another PDF library unless the requested feature cannot be implemented safely with the bundled dependencies.\n\n## Follow the workflow\n\n1. Preserve source files unless the user explicitly requests an in-place change.\n2. Inspect the input with `pypdf.PdfReader`: page count, metadata, encryption, page sizes, text, annotations, and form fields as relevant.\n3. Perform the smallest operation that satisfies the request.\n4. Reopen every output with `pypdf` and verify its page count, expected text or fields, and encryption state.\n5. Render representative pages when a PDF renderer is available. Inspect the rendered images for clipping, overlap, missing glyphs, broken spacing, and blank pages. If rendering is unavailable, state that only structural validation was completed.\n\nWork in the current workspace unless the user provides another writable location. Keep intermediate files separate from final outputs and remove them when they are no longer needed.\n\n## Read and inspect\n\nUse `astrbot_file_read_tool` for a quick text extraction when it is sufficient. Use Python with `pypdf` when page structure or exact metadata matters:\n\n```python\nfrom pypdf import PdfReader\n\nreader = PdfReader(input_path)\nprint(len(reader.pages), reader.metadata)\nfor page_number, page in enumerate(reader.pages, start=1):\n    print(page_number, page.mediabox, page.rotation)\n    print(page.extract_text() or \"\")\n```\n\nText extraction does not prove that visual layout is correct. Render with `pdftoppm` when it is available:\n\n```text\npdftoppm -png -r 144 input.pdf rendered/page\n```\n\n## Create from Markdown\n\nPrefer the bundled deterministic converter:\n\n```text\npython <this-skill-directory>/scripts/markdown_to_pdf.py input.md output.pdf\n```\n\nThe converter intentionally supports a limited Markdown subset:\n\n- ATX headings (`#` through `######`)\n- paragraphs\n- flat ordered and unordered lists\n- block quotes\n- fenced code blocks\n- horizontal rules\n- `<!-- pagebreak -->`\n- bold, italic, inline code, and HTTP(S) or mail links\n\nIt does not interpret raw HTML, images, tables, nested lists, footnotes, or arbitrary Markdown extensions. Simplify unsupported content or explain the limitation instead of silently changing meaning.\n\nFont selection follows this order:\n\n1. Use an explicit readable font passed with `--font path/to/font.ttf` or `--font path/to/font.ttc`.\n2. Otherwise, search common system locations for a readable Chinese font and verify that it contains every character used by the document.\n3. If no suitable system font is available, use ReportLab's built-in Simplified Chinese fallback for supported Latin and Chinese text. The converter stops instead of silently emitting missing glyphs when the fallback cannot represent the input.\n\nWhen a broader or embedded font is required and no suitable system font is readable, download it into the workspace and pass its path with `--font`. Prefer an official source over an arbitrary font mirror or CDN:\n\n- [MiSans from Xiaomi](https://hyperos.mi.com/font/zh/download/) is an official source that is generally accessible from mainland China. Review its license before use and do not redistribute the font package unless the license permits it.\n- [Noto Sans CJK](https://github.com/notofonts/noto-cjk/blob/main/Sans/README.md) is an official open-source fallback with documented download options.\n\nIf an official GitHub font URL times out for a user in mainland China, the user may choose one of these third-party proxy prefixes:\n\n- `https://edgeone.gh-proxy.com/`\n- `https://hk.gh-proxy.com/`\n- `https://gh-proxy.com/`\n- `https://gh.dpik.top/`\n\nAppend the complete official GitHub URL directly after the prefix. For example:\n\n```text\nOfficial: https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/TTF/Subset/NotoSansSC-VF.ttf\nProxy:   https://edgeone.gh-proxy.com/https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/TTF/Subset/NotoSansSC-VF.ttf\n```\n\nThese proxies are not operated by the font project or AstrBot. Their availability and returned content can change. Never send credentials, private repository URLs, or other sensitive data through them. After downloading, verify that the final response used HTTPS, inspect the file type, and compare a checksum with an official checksum when one is published.\n\nDo not download a font silently. Obtain user approval when network access or a new file is required, use HTTPS, and keep the downloaded font in a workspace or temporary directory rather than installing it system-wide.\n\nAfter conversion, use `pypdf` to confirm the output opens, contains pages, and exposes representative expected text. Render and inspect the first page plus any page with dense content, code, or a page break.\n\n## Transform existing PDFs\n\nUse small `pypdf` scripts directly for ordinary operations.\n\nMerge documents in the requested order:\n\n```python\nfrom pypdf import PdfWriter\n\nwriter = PdfWriter()\nfor path in input_paths:\n    writer.append(path)\nwriter.write(output_path)\n```\n\nSplit selected pages without modifying the source:\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(input_path)\nwriter = PdfWriter()\nfor page_index in selected_zero_based_indexes:\n    writer.add_page(reader.pages[page_index])\nwriter.write(output_path)\n```\n\nRotate by a multiple of 90 degrees with `page.rotate(angle)`. Encrypt with `writer.encrypt(password)` only when the user asks, and never echo a password into logs or the final response. Reopen encrypted outputs with the password before reporting success.\n\n## Fill forms\n\nRead [forms.md](references/forms.md) before modifying AcroForms. Preserve interactivity unless the user requests a flattened result. Validate both the canonical field tree and page widget annotations; a successful render alone is not proof that field values were saved.\n\n## Finish\n\nReport the final path, the operation performed, and the validation completed. Mention any unsupported content, unavailable renderer, password requirement, or form ambiguity. Do not claim visual verification unless rendered pages were actually inspected.\n","astrbot/builtin_stars/astrbot/skills/pdf/references/forms.md":"# AcroForm handling\n\nUse this reference only for interactive PDF form tasks.\n\n## Inspect before editing\n\nCheck both representations of every field:\n\n1. Read the canonical tree with `PdfReader.get_fields()`.\n2. Enumerate `/Widget` annotations in every page's `/Annots` array.\n3. Follow `/Parent` and `/Kids` references when resolving field names and values.\n\nA widget can display a value from its appearance stream while the canonical `/AcroForm/Fields` tree contains a different value. If unrelated canonical fields and widgets reuse the same name, report the ambiguity instead of automatically reattaching fields.\n\n## Fill with pypdf\n\n```python\nfrom pypdf import PdfReader, PdfWriter\nfrom pypdf.generic import NameObject\n\nreader = PdfReader(input_path)\nwriter = PdfWriter()\nwriter.clone_document_from_reader(reader)\n\nwriter.reattach_fields()\nfields = writer.get_fields() or {}\nmissing = set(values) - set(fields)\nif missing:\n    raise ValueError(f\"Form fields not found: {sorted(missing)}\")\n\nvalues_to_write = dict(values)\nif flatten:\n    values_to_write = {\n        name: field.get(\"/V\", \"/Off\" if field.get(\"/FT\") == \"/Btn\" else \"\")\n        for name, field in fields.items()\n    }\n    values_to_write.update(values)\n\nwriter.update_page_form_field_values(\n    None,\n    values_to_write,\n    auto_regenerate=False,\n    flatten=flatten,\n)\n\nif flatten:\n    writer.remove_annotations(subtypes=\"/Widget\")\n    writer.root_object.pop(NameObject(\"/AcroForm\"), None)\n\nwith open(output_path, \"wb\") as output_file:\n    writer.write(output_file)\n```\n\nDo not flatten a signed document without an explicit decision from the user. Preserve the source and, when useful, retain an interactive copy alongside the flattened copy.\n\n## Validate after writing\n\nFor an interactive result:\n\n- Reopen the output and verify every expected field value in `get_fields()`.\n- Enumerate widgets again and verify their effective values, including inherited parent values.\n- Require updated widgets to have non-empty normal appearance streams under `/AP` and `/N`.\n- Render the affected pages to detect stale, clipped, or invisible appearances.\n\nFor a flattened result:\n\n- Require zero `/Widget` annotations.\n- Require no remaining `/AcroForm` field tree.\n- Render the affected pages and confirm the painted values remain visible.\n","astrbot/builtin_stars/astrbot/skills/skill-creator/SKILL.md":"---\nname: skill-creator\ndescription: Create, revise, and validate AstrBot Skills built around SKILL.md instruction bundles. Use when the user asks to create, scaffold, improve, package, or review a Skill for an AstrBot workspace, local installation, or plugin.\n---\n\n# Create AstrBot Skills\n\nBuild small, reusable instruction bundles that another agent can discover and follow reliably.\n\n## Follow the core design rules\n\n- Assume the model already knows general facts. Include only task-specific procedures, constraints, and resources.\n- Match instruction precision to risk. Use flexible guidance for judgment-heavy work and deterministic scripts for fragile operations.\n- Keep `SKILL.md` focused. Put detailed reference material in `references/`, repeatable automation in `scripts/`, and output material in `assets/`.\n- Link every optional resource directly from `SKILL.md` and state when to use it. Avoid deep chains of references.\n- Do not add process documents such as `README.md`, changelogs, installation guides, or quick-reference duplicates.\n- Do not add OpenAI- or Codex-specific metadata, directories, tools, or installation steps unless the user explicitly targets that runtime.\n\n## Establish the intended behavior\n\nBefore writing files, identify:\n\n1. Concrete requests that should trigger the Skill.\n2. Expected outputs or actions.\n3. Required tools, permissions, and runtime assumptions.\n4. Failure cases that need explicit guardrails.\n\nAsk only for information that materially changes the result. Infer ordinary details from the current task and environment.\n\n## Choose the target\n\nUse the runtime declared in the system instructions and the location requested by the user. Do not infer the runtime from filesystem paths.\n\nIn local mode, common targets are:\n\n- Workspace Skill: `<workspace>/skills/<skill-name>`\n- Locally installed Skill: `<astrbot-data>/skills/<skill-name>`.\n- Installed third-party plugin Skill: `<astrbot-data>/plugins/<plugin-name>/skills/<skill-name>`.\n\nIf no location is specified in local mode, create the Skill under `skills/<skill-name>` in the current AstrBot workspace. Creating or modifying a locally installed Skill requires administrator access and is enforced by the filesystem tools. If permission is denied, use the workspace target and explain the fallback.\n\nIn sandbox mode, do not use `<astrbot-data>` or attempt to install a Skill into the host AstrBot instance. Create it under `skills/<skill-name>` in the current sandbox workspace, and treat it as sandbox-scoped unless the runtime provides a dedicated persistence or release workflow.\n\nTreat plugin-provided Skills as read-only during normal runtime. Modify a plugin Skill only when the user is working in that plugin's source tree and has explicitly requested the change. If the requested target is not writable, create the Skill in the workspace and explain how to install or move it.\n\n## Name the Skill\n\n- Use lowercase letters, digits, and hyphens only.\n- Keep the name under 64 characters.\n- Prefer a short action-oriented name.\n- Name the folder exactly the same as the frontmatter `name`.\n\n## Plan only necessary resources\n\nFor each repeated operation, decide whether plain instructions are sufficient:\n\n- Add `scripts/` only for deterministic, repeatable operations.\n- Add `references/` only for material the agent may need to consult while working.\n- Add `assets/` only for files intended to be copied or incorporated into outputs.\n\nDo not create empty resource directories.\n\n## Write SKILL.md\n\nStart with YAML frontmatter containing only `name` and `description`:\n\n```yaml\n---\nname: example-skill\ndescription: Describe what the Skill does and the concrete requests or situations that should trigger it.\n---\n```\n\nMake the description specific enough for discovery. Put all trigger guidance in the description because AstrBot loads the body only after the Skill is selected.\n\nWrite the body as direct instructions:\n\n- Use imperative language.\n- Put the main workflow before edge cases.\n- State important safety boundaries close to the affected action.\n- Use the AstrBot tool names actually available in the current runtime when a workflow depends on tools.\n- Prefer relative paths inside the Skill so it works after installation or sandbox synchronization.\n- Keep examples short and representative.\n\n## Initialize or update files\n\nFor a new Skill, prefer the bundled initializer when Python and shell execution are available:\n\n```text\npython <this-skill-directory>/scripts/init_skill.py <skill-name> --path <target-skills-root> --description <description>\n```\n\nAdd `--resources scripts,references,assets` with only the directories that are needed. The initializer refuses to overwrite an existing Skill.\n\nIf shell execution is unavailable, create the directory and UTF-8 `SKILL.md` with `astrbot_file_write_tool`. Create optional resources only after their content is known.\n\nWhen updating a Skill, read its complete `SKILL.md` and directly referenced resources before editing. Preserve useful behavior and avoid unrelated restructuring.\n\n## Validate\n\nWhen Python and shell execution are available, run:\n\n```text\npython <this-skill-directory>/scripts/validate_skill.py <created-skill-directory>\n```\n\nOtherwise verify manually:\n\n- The directory name is valid and matches frontmatter `name`.\n- `SKILL.md` is UTF-8 and has valid YAML frontmatter.\n- `description` explains both capability and trigger conditions.\n- The body is non-empty and operational.\n- Every referenced file exists and every bundled file has a clear purpose.\n- Instructions do not assume unavailable tools, paths, credentials, or permissions.\n\nRun any bundled scripts on representative safe inputs. Fix validation or execution failures before presenting the Skill.\n\n## Finish\n\nReport the created or updated location, included resources, validation performed, and any runtime or activation step still required. Do not enable a globally installed Skill or change an AstrBot configuration unless the user requested it.\n","astrbot/builtin_stars/astrbot/skills/spreadsheets/SKILL.md":"---\nname: spreadsheets\ndescription: Create, read, edit, analyze, convert, chart, and validate spreadsheet files including XLSX, XLSM, XLS, CSV, and TSV. Use when a spreadsheet is a primary input or deliverable, or when tabular data must remain editable and auditable in workbook form.\n---\n\n# Work with spreadsheets\n\nUse `openpyxl` for XLSX/XLSM authoring, `xlrd` for legacy XLS reading, `pandas` for substantial data cleaning or analysis, and the standard `csv` module for simple CSV/TSV work. Preserve the source unless the user explicitly requests an in-place edit.\n\n## Choose the workflow\n\n1. For a read-only question, inspect only the relevant sheets, labels, values, formulas, tables, charts, and comments. Do not export a modified copy.\n2. For an existing workbook, study its structure and formatting before editing. Apply the smallest local change and extend nearby formulas, validation, conditional formatting, tables, and charts when the edited range requires it.\n3. For a new workbook, separate inputs, calculations, and outputs when the task contains derived values. Keep calculations visible and auditable.\n4. Save to a new file, reopen it, validate formulas and structure, and render every populated sheet when a renderer is available.\n\nUse the bundled inspector before unfamiliar edits:\n\n```text\npython <this-skill-directory>/scripts/inspect_workbook.py input.xlsx\n```\n\n## Respect format boundaries\n\n- Use `openpyxl.load_workbook(..., keep_vba=True)` for XLSM files and preserve the `.xlsm` extension. Do not claim that macros were inspected or are safe merely because they were preserved.\n- Treat XLS as a legacy read-only source. `xlrd` reads values and basic metadata but does not provide reliable modern editing. Convert the result to XLSX or CSV instead of overwriting the XLS file.\n- Preserve CSV/TSV delimiter, quoting, encoding, header order, and typed meaning. Keep identifiers such as ZIP codes and account numbers as text.\n- Never change a workbook's file extension without actually converting its format.\n\n## Keep formulas auditable\n\n- Write derived values as formulas rather than hardcoded results.\n- Place assumptions and raw inputs in visible cells or dedicated sheets.\n- Avoid magic numbers inside formulas. Reference an assumption cell instead.\n- Use correct absolute and relative references for fill behavior.\n- Quote every cross-sheet name: `='Revenue Model'!B4`, even when the current name has no spaces.\n- Prefer bounded ranges over full-column references in calculation-heavy formulas.\n- Use helper cells when a formula becomes difficult to understand or audit.\n- Add comments to important assumptions and source-backed inputs.\n- Check for `#REF!`, `#DIV/0!`, `#VALUE!`, `#NAME?`, `#NUM!`, `#NULL!`, and unexpected circular references.\n\n`openpyxl` writes formulas but does not calculate them. If formulas must be recalculated, open and save a copy with LibreOffice or Excel when available, then reopen the result with `data_only=False` and `data_only=True`. Never replace formulas with calculated constants merely to make validation pass. Read [formulas.md](references/formulas.md) for the detailed validation contract.\n\n## Format by meaning\n\nRead [formatting.md](references/formatting.md) before creating or substantially redesigning a workbook.\n\n- Store dates, numbers, currency, and percentages as typed values with explicit number formats.\n- Distinguish title, header, input, calculation, output, note, and warning roles consistently.\n- Prefer restrained fills and light structural borders. Do not decorate every populated cell with a border.\n- Freeze useful headers, enable filters, and use named tables for editable datasets.\n- Prefer conditional formatting over one-time manual fills when color represents a value or status.\n- Use data validation for editable categorical fields when practical.\n- Size columns and rows deliberately. Widen before wrapping, cap very wide columns, and avoid formatting unused ranges.\n- Hide gridlines only when explicit formatting already provides structure.\n\n## Use charts deliberately\n\nRead [charts.md](references/charts.md) before creating or editing charts. Create a chart only when it improves comparison, trend, distribution, ranking, progress, or relationship understanding.\n\n- Link chart series to worksheet ranges, not duplicated literal values.\n- Keep units explicit and titles focused on one takeaway.\n- Place charts in reserved areas without covering source data or controls.\n- Verify categories, series orientation, source ranges, point counts, axes, and placement after saving.\n- Prefer a compact table over a chart when exact values are the main point.\n\n## Convert CSV or TSV\n\nUse the bundled converter for a clean, typed, filterable workbook:\n\n```text\npython <this-skill-directory>/scripts/csv_to_xlsx.py input.csv output.xlsx\npython <this-skill-directory>/scripts/csv_to_xlsx.py input.tsv output.xlsx --delimiter tab\n```\n\nThe converter infers conservative scalar types, freezes the header, creates a table, applies number formats, and caps column widths. Inspect identifiers and locale-specific dates before accepting inferred types.\n\n## Validate and render\n\nRun structural validation after every create or edit operation:\n\n```text\npython <this-skill-directory>/scripts/validate_workbook.py output.xlsx\n```\n\nWhen LibreOffice and a PDF renderer are available, render the workbook:\n\n```text\npython <this-skill-directory>/scripts/render_workbook.py output.xlsx rendered\n```\n\nInspect every rendered page at normal zoom. Check for clipped headers or values, unexpected blank pages, broken charts, unreadable colors, bad page breaks, missing glyphs, formula errors, and content outside the visible area. Rendering does not prove formula correctness; structural and formula validation remain required.\n\nIf rendering is unavailable, report that only structural validation was completed. Do not imply that a workbook passed visual QA.\n\n## Finish\n\nDeliver only the requested workbook or tabular output unless the user asks for previews or intermediates. Report the output path, important sheets or changes, formula/recalculation status, validation performed, and any limitation involving macros, legacy XLS, unsupported formulas, fonts, or rendering.\n","astrbot/builtin_stars/astrbot/skills/spreadsheets/references/charts.md":"# Spreadsheet charts\n\nCreate a chart only when it makes a comparison, trend, distribution, ranking, progress measure, or relationship easier to understand.\n\n## Select a chart\n\n- Use bars or columns for category comparison and ranking.\n- Use lines for trends over time.\n- Use scatter plots for relationships between numeric variables.\n- Use a histogram for a distribution when supported by the target viewer.\n- Use pie or doughnut charts only for a small number of meaningful parts of one whole.\n- Use a compact table when exact values matter more than visual pattern.\n\n## Build auditable chart data\n\n- Link series and categories directly to worksheet cells.\n- Use a formula-backed helper range only when reshaping, grouping dates, or shortening labels is necessary.\n- Keep unknown values blank rather than inventing zeroes.\n- Verify headers are not included as numeric points.\n- Keep category and value ranges the same length.\n- Use a text helper label such as `2026-08` when date-axis rendering is unreliable.\n\n## Format and place\n\n- Give each chart one clear takeaway and include units in the title or axis.\n- Use restrained, consistent colors and avoid gradients, 3D effects, and heavy borders.\n- Keep labels, ticks, legends, and titles readable at normal zoom.\n- Place charts beside or below the data they explain with blank gutters around them.\n- Do not cover cells, controls, notes, or other charts.\n- Set explicit axis number formats for currency, percentages, and dates.\n\nAfter saving, reopen the workbook and inspect chart series formulas. Render the sheet and check for blank charts, clipped labels, stale ranges, wrong orientation, unreadable legends, and excessive whitespace.\n","astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formatting.md":"# Spreadsheet formatting\n\nUse this reference for new workbooks and substantial redesigns. Preserve an existing workbook's visual language unless the user requests a redesign.\n\n## Establish roles\n\nChoose a small role-based style system before writing cells:\n\n| Role | Default treatment |\n|---|---|\n| Workbook title | 16-18 pt, bold, dark neutral text, generous spacing |\n| Section title | 12-14 pt, bold, restrained accent or neutral fill |\n| Table header | Bold, high-contrast fill, centered only when appropriate |\n| Input | Light neutral or pale blue fill, unlocked when protection is used |\n| Formula | No fill or a subtle neutral fill; keep formulas visible |\n| Key output | Bold, explicit number format, light callout fill |\n| Note/source | Smaller muted text, URL in cell or comment |\n| Warning | Restrained amber or red used only for actionable exceptions |\n\nUse one body font and one optional display font. Prefer fonts commonly available across platforms. For Chinese workbooks, verify the chosen CJK font in the actual render environment (`fc-match \"Font Name\"` when Fontconfig is available), then inspect the rendered pages for substitution or missing glyphs. Keep body text around 10-11 pt and do not depend on color alone to communicate status.\n\n## Lay out the workbook\n\n- Put a clear title or table header near the top-left of each important sheet.\n- Keep assumptions and inputs separate from derived calculations in complex models.\n- Place important totals or KPIs where users can find them without scrolling to the bottom.\n- Freeze the header row for long tables and freeze identifier columns for wide tables.\n- Add filters or an Excel table for editable datasets.\n- Avoid merged cells in calculation or filter ranges. Reserve merges for titles or compact presentation labels.\n- Set print area, orientation, margins, repeated header rows, and fit-to-width for reports intended to print or render.\n- Remove empty default sheets and avoid large formatted-but-empty used ranges.\n\n## Size and align cells\n\n- Left-align descriptive text, right-align numbers, and use intentional alignment for short statuses and dates.\n- Widen columns before enabling deep wrapping. Cap descriptive columns around 50-60 characters unless the user requests otherwise.\n- Increase row height only enough to reveal wrapped content.\n- Use explicit formats such as `#,##0`, `#,##0.00`, `0.0%`, `yyyy-mm-dd`, and currency formats appropriate to the requested currency.\n- Preserve identifiers as text when leading zeroes or exact digits matter.\n\n## Tables and conditional formatting\n\n- Use light internal borders and a clearer outside or header boundary.\n- Use banded rows only when they materially improve scanning.\n- Apply conditional formatting over the intended editable range, not an entire worksheet.\n- Verify that formulas used by conditional formatting are anchored correctly at the top-left cell of the applied range.\n- Prefer data bars, color scales, or icon sets only when their scale and direction are meaningful.\n\n## Accessibility and usability\n\n- Use descriptive sheet names and unique table names.\n- Avoid hidden assumptions and unexplained abbreviations.\n- Add comments for important assumptions, unusual formulas, and data provenance.\n- Use data validation prompts and error messages for constrained inputs.\n- Keep color contrast readable and provide text or numeric cues in addition to color.\n","astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formulas.md":"# Formula and validation rules\n\nUse this reference for formula-heavy workbooks and any task where calculated outputs matter.\n\n## Author formulas\n\n1. Create every referenced sheet before assigning cross-sheet formulas.\n2. Use formulas for derived values and hardcode only assumptions, raw facts, or explicitly requested fixed outputs.\n3. Use `$` anchors deliberately and test the first, middle, and last filled formulas.\n4. Quote sheet names in cross-sheet references.\n5. Bound lookup and aggregation ranges to the intended data area.\n6. Prefer `IFERROR` only when the fallback has a clear business meaning. Do not hide an unexpected error.\n7. Keep units consistent across inputs and outputs.\n\n## Understand calculation limits\n\n`openpyxl` preserves and writes formulas but does not calculate them. Loading with `data_only=True` returns cached values last saved by a calculating application; a newly authored formula may have no cached value.\n\nWhen a calculated result is required:\n\n1. Save the workbook with formulas intact.\n2. If LibreOffice or Excel is available, open and save a copy to recalculate it.\n3. Reopen the recalculated copy twice: once with `data_only=False` to verify formulas and once with `data_only=True` to inspect cached results.\n4. Reconcile important totals independently in Python for high-risk outputs.\n\nDo not treat a missing cached value as proof that a formula is wrong. Do treat a literal error value, `#REF!` inside a formula, a broken chart range, or a missing sheet reference as an error.\n\n## Validate\n\n- Scan all populated cells for Excel error literals.\n- Scan formulas and chart series for `#REF!`.\n- Confirm table and filter ranges include their headers and intended rows.\n- Confirm data validation and conditional-format ranges include future editable rows when requested.\n- Check duplicate table and defined-name identifiers.\n- Check for formulas that accidentally reference the header row or omit the final data row.\n- Review external links and disclose them; do not silently remove them.\n- Open macro-enabled files with `keep_vba=True` and preserve their extension.\n\nFor financial, legal, medical, or other high-stakes workbooks, independently recalculate representative results and document assumptions and source URLs inside the workbook.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"## Setup commands\n\n### Core\n\n```\nuv sync\nuv run main.py\n```\n\nExposed an API server on `http://localhost:6185` by default.\n\n### Dashboard(WebUI)\n\n```\ncd dashboard\npnpm install # First time only. Use npm install -g pnpm if pnpm is not installed.\npnpm dev\n```\n\nRuns on `http://localhost:3000` by default.\n\n## Pre-commit setup\n\nAstrBot uses [pre-commit](https://pre-commit.com/) hooks to automatically format and lint Python code before each commit. The hooks run `ruff check`, `ruff format`, and `pyupgrade` (see [`.pre-commit-config.yaml`](.pre-commit-config.yaml) for details).\n\nTo set it up:\n\n```bash\npip install pre-commit\npre-commit install\n```\n\nAfter installation, the hooks will run automatically on `git commit`. You can also run them manually at any time:\n\n```bash\nruff format .\nruff check .\n```\n\n> **Note:** If you use VSCode, install the `Ruff` extension for real-time formatting and linting in the editor.\n\n## Dev environment tips\n\n### Basic\n\n1. When modifying the WebUI, be sure to maintain componentization and clean code. Avoid duplicate code.\n2. Do not add any report files such as xxx_SUMMARY.md.\n3. After finishing, use `ruff format .` and `ruff check .` to format and check the code.\n4. When committing, ensure to use conventional commits messages, such as `feat: add new agent for data analysis` or `fix: resolve bug in provider manager`.\n5. Use **English** for all comments and logs.\n6. For path handling, use `pathlib.Path` instead of string paths, and use `astrbot.core.utils.path_utils` to get the AstrBot data and temp directory.\n7. When backend API routes, request/response schemas, or OpenAPI definitions change, regenerate the frontend API client by running `cd dashboard && pnpm generate:api`.\n8. When updating the project version, keep `[project].version` in `pyproject.toml` and `__version__` in `astrbot/__init__.py` in sync. `VERSION` in `astrbot/core/config/default.py` should derive from `astrbot.__version__` instead of hardcoding a separate version string.\n9. When designing WebUI dialogs, use `text-h3 pa-4 pb-0 pl-6` as the base class for dialog titles, and use `variant=\"text\"` or `variant=\"tonal\"` for dialog buttons.\n10. Consider cross-platform compatibility (e.g., Windows, macOS, and Linux, as well as Arm64 and x86 CPU architectures) and compatibility with Python 3.10+.\n11. When changing WebUI navigation, page structure, or terminology, update the affected instructions and screenshots in `docs/zh` and `docs/en` in the same PR. For renamed, moved, or merged entry points, include an old-to-new mapping in the relevant docs and changelog. Keep layout redesigns separate from feature additions where practical, and explain necessary navigation changes in the PR. See `CONTRIBUTING.md` for the review checklist.\n\n### KISS and First Principles\n\nFollow the KISS principle and reason from first principles during development. Start by identifying the real problem, required behavior, and smallest useful change before adding code. Do not pile on features, configuration switches, abstractions, dependencies, or compatibility layers unless they directly solve the current problem and have clear evidence of need.\n\nPrefer the simplest implementation that is correct, maintainable, and consistent with the existing codebase. If a broader design seems attractive, reduce it to the essential behavior needed now and leave optional expansion for a later, explicit requirement.\n\n### No Unnecessary Helpers\n\nPrioritize inline implementation over abstraction. Avoid over-engineering and do not create helper functions unless absolutely necessary.\n\n1. **Inline-First Rule**: If a logic block can be implemented directly within the main function without breaking overall readability, **do not** extract it into a new helper function.\n2. **Strict Justification for Helpers**: You may only create a separate helper function if it meets at least one of these criteria:\n   - **High Reuse**: The exact same logic is repeated across **3 or more** different locations.\n   - **Extreme Complexity**: Inlining the logic makes the main function too long (e.g., >50 lines) or severely derails the main execution flow.\n3. **No Fragmentation**: Do not split continuous linear logic (e.g., a single API call, simple form validation, or one-time data formatting) into tiny functions just for the sake of \"clean code.\"\n4. **Keep Context Compact**: Handle edge cases, error catching, and logging directly inside the main function block instead of offloading them.\n5. **Refactoring Constraint**: When modifying existing code, do not alter the current function structure or extract code into new helpers unless the existing code already violates the complexity or reuse rules above.\n\n### Mandatory Google-Style Docstrings\n* **Comment the complex**: Add clear comments to any non-obvious function, method, or parameter.\n* **Google Format**: All docstrings must strictly use the Google format (`Args:`, `Returns:`, `Raises:`).\n\n#### Example:\n\n```py\ndef calculate_metrics(user_id: int, force_refresh: bool = False) -> dict:\n    \"\"\"Brief description of the function.\n\n    Args:\n        user_id: Description of the ID.\n        force_refresh: Description of the flag.\n\n    Returns:\n        Description of the returned dict.\n\n    Raises:\n        ValueError: Description of when this occurs.\n    \"\"\"\n    # Inline implementation here...\n```\n\n\n## PR instructions\n\n1. Title format: use conventional commit messages\n2. Use English to write PR title and descriptions.\n\n## Release versions\n\nUse a short-lived `release/*` branch for each release. The release branch is the stabilization area for version bumps, changelog updates, release-blocking fixes, and final validation only. Do not add unrelated features or broad refactors to a release branch.\n\nPrepare a release from a clean worktree with:\n\n```bash\nuv run python scripts/prepare_release.py 4.25.0\n```\n\nThe script updates `pyproject.toml` and `astrbot/__init__.py`, creates `changelogs/v4.25.0.md`, runs the required Python checks, and prints the remaining steps. Use these flags when needed:\n\n```bash\nuv run python scripts/prepare_release.py 4.25.0 --generate-api-client\nuv run python scripts/prepare_release.py 4.25.0 --dashboard-build\nuv run python scripts/prepare_release.py 4.25.0 --commit --push\n```\n\nOpen a PR from `release/4.25.0` to `master`. The PR title must use the conventional commit format, for example `chore: bump version to 4.25.0`. After the release PR is merged, create and push the tag from the updated `master` branch so the tag points to the exact code that was merged:\n\n```bash\ngit checkout master\ngit pull --ff-only origin master\ngit tag v4.25.0\ngit push origin v4.25.0\n```\n\nFor one-off release candidate branches, delete the release branch after the tag is pushed and verified. For maintained release lines, use a branch such as `release/4.25` and keep it until that line reaches EOL.\n\n```bash\ngit branch -d release/4.25.0\ngit push origin --delete release/4.25.0\n```\n","isInternal":false,"tokens":1591,"sizeBytes":6943},{"name":"copilot-instructions.md","path":".github/copilot-instructions.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/.github/copilot-instructions.md","title":"GitHub Copilot Instructions","category":"copilot-instructions","format":"markdown","content":"# AstrBot Development Instructions\n\nAstrBot is a multi-platform LLM chatbot and development framework written in Python with a Vue.js dashboard. It supports multiple messaging platforms (QQ, Telegram, Discord, etc.) and various LLM providers (OpenAI, Anthropic, Google Gemini, etc.).\n\nAlways reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.\n\n## Working Effectively\n\n### Bootstrap and Install Dependencies\n- **Python 3.10+ required** - Check `.python-version` file\n- Install UV package manager: `pip install uv`\n- Install project dependencies: `uv sync` -- takes 6-7 minutes. NEVER CANCEL. Set timeout to 10+ minutes.\n- Create required directories: `mkdir -p data/plugins data/config data/temp`\n\n### Running the Application\n- Run main application: `uv run main.py` -- starts in ~3 seconds\n- Application creates WebUI on http://localhost:6185 (default credentials: `astrbot`/`astrbot`)\n\n### Dashboard Build (Vue.js/Node.js)\n- **Prerequisites**: Node.js 20+ and npm 10+ required\n- Navigate to dashboard: `cd dashboard`\n- Install dashboard dependencies: `npm install` -- takes 2-3 minutes. NEVER CANCEL. Set timeout to 5+ minutes.\n- Build dashboard: `npm run build` -- takes 25-30 seconds. NEVER CANCEL.\n- Dashboard creates optimized production build in `dashboard/dist/`\n\n### Testing\n- Do not generate test files for now.\n\n### Code Quality and Linting\n- Install ruff linter: `uv add --dev ruff`\n- Check code style: `uv run ruff check .` -- takes <1 second\n- Check formatting: `uv run ruff format --check .` -- takes <1 second\n- Fix formatting: `uv run ruff format .`\n- **ALWAYS** run `uv run ruff check .` and `uv run ruff format .` before committing changes\n\n### Plugin Development\n- Plugins load from `astrbot/builtin_stars/` (built-in) and `data/plugins/` (user-installed)\n- Plugin system supports function tools and message handlers\n- Key plugins: python_interpreter, web_searcher, astrbot, reminder, session_controller\n\n### Common Issues and Workarounds\n- **Dashboard download fails**: Known issue with \"division by zero\" error - application still works\n- **Import errors in tests**: Ensure `uv run` is used to run tests in proper environment\n=- **Build timeouts**: Always set appropriate timeouts (10+ minutes for uv sync, 5+ minutes for npm install)\n\n## CI/CD Integration\n- GitHub Actions workflows in `.github/workflows/`\n- Docker builds supported via `Dockerfile`\n- Pre-commit hooks enforce ruff formatting and linting\n\n## Docker Support\n- Primary deployment method: `docker run soulter/astrbot:latest`\n- Compose file available: `compose.yml`\n- Exposes ports: 6185 (WebUI), 6195 (WeChat), 6199 (QQ), etc.\n- Volume mount required: `./data:/AstrBot/data`\n\n## Multi-language Support\n- Documentation in Chinese (README.md), English (README_en.md), Japanese (README_ja.md)\n- UI supports internationalization\n- Default language is Chinese\n\nRemember: This is a production chatbot framework with real users. Always test thoroughly and ensure changes don't break existing functionality.\n","isInternal":false,"tokens":740,"sizeBytes":3092},{"name":"advanced-ooxml.md","path":"astrbot/builtin_stars/astrbot/skills/documents/references/advanced-ooxml.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/astrbot/builtin_stars/astrbot/skills/documents/references/advanced-ooxml.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Advanced DOCX and OOXML operations\n\nRead this reference before modifying features that `python-docx` does not fully support.\n\n## Work safely\n\n1. Preserve the original package.\n2. Inspect ZIP members, content types, relationships, and the exact XML elements involved.\n3. Patch only the necessary parts and relationships.\n4. Write a new package without dropping unrelated members.\n5. Reopen with `python-docx`, parse every XML part, run structural validation, and render again.\n\nUse namespace-aware XML handling. Never use regular-expression replacement across XML markup.\n\n## Comments\n\nValidate all of these together:\n\n- `word/comments.xml`\n- comment relationships and content-type declarations\n- `w:commentRangeStart`, `w:commentRangeEnd`, and `w:commentReference` anchors\n- unique comment IDs and preserved author/date values\n\nHeadless PDF exports frequently omit comments. Structural validation remains mandatory.\n\n## Tracked changes\n\nTracked insertions and deletions use `w:ins` and `w:del`, with author, date, and ID metadata. Text inside deletions commonly uses `w:delText` rather than `w:t`.\n\n- Do not flatten revisions unless the user asks to accept or reject them.\n- Preserve revision metadata when adding or editing tracked changes.\n- Inspect headers, footers, footnotes, and comments in addition to the main document.\n- Render the revision view when possible, but also inspect the XML because renderer settings can hide revisions.\n\n## Fields and navigation\n\nTOCs, page numbers, cross-references, captions, and many calculated values use field instructions and cached display text.\n\n- Preserve `w:fldSimple` or complex `w:fldChar` begin/separate/end sequences.\n- Preserve bookmarks and relationship targets used by internal links.\n- Do not replace a dynamic field with static visible text unless the user requests flattening.\n- Disclose when Word or LibreOffice must refresh field results.\n\n## Content controls and forms\n\nContent controls use `w:sdt`. Preserve aliases, tags, data binding, locks, placeholder state, and repeating-section structure. Do not convert a content control to plain text merely to edit its visible value unless the user accepts losing the control.\n\n## Protection, macros, and signatures\n\n- Treat editing restrictions as workflow controls, not encryption.\n- Preserve macros only in macro-enabled formats and never execute them during inspection.\n- Do not remove or bypass protection without explicit authorization.\n- Any document edit can invalidate a digital signature. Preserve the signed source and report the consequence.\n\n## Merge and template operations\n\nDOCX parts can reuse style IDs, numbering IDs, relationship IDs, bookmark IDs, image names, and drawing IDs. A safe merge must remap collisions and preserve referenced parts. Prefer template-based creation or a well-tested merge library over appending raw XML from unrelated packages.\n","isInternal":false,"tokens":574,"sizeBytes":2881},{"name":"styling.md","path":"astrbot/builtin_stars/astrbot/skills/documents/references/styling.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/astrbot/builtin_stars/astrbot/skills/documents/references/styling.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# DOCX styling and layout\n\nUse this reference for new documents and major rewrites. For existing-document edits, preserve the document's style unless the user requests a redesign.\n\n## Choose a design system\n\nResolve the following values before authoring:\n\n- page size, orientation, margins, and header/footer distance\n- body font, East Asian font, base size, line spacing, and paragraph spacing\n- title and heading sizes, colors, and keep-with-next behavior\n- bullet and numbered-list indentation\n- table width, column widths, cell margins, borders, fills, and repeated headers\n- callout, caption, source-note, header, and footer treatments\n\nApply these values through Word styles and reusable table/list definitions. Use direct formatting only for intentional exceptions.\n\n## Recommended neutral preset\n\nFor a general professional document when the user provides no template:\n\n| Element | Suggested values |\n|---|---|\n| Page | A4 or Letter according to locale, portrait |\n| Margins | 20-25 mm / 0.8-1.0 in |\n| Body | 10.5-11 pt, 1.15-1.3 line spacing, 6-8 pt after |\n| Title | 24-28 pt, dark neutral, 12-18 pt after |\n| Heading 1 | 16-18 pt, 12-16 pt before, 6-8 pt after |\n| Heading 2 | 13-15 pt, 10-12 pt before, 4-6 pt after |\n| Heading 3 | 11-12 pt, 8 pt before, 3-4 pt after |\n| Table text | 9-10.5 pt with explicit cell margins |\n| Header/footer | 8-9 pt muted text, used only when helpful |\n\nFor Chinese documents, set both Latin and East Asian fonts on styles. Prefer a system font that can be rendered in the current environment and inspect the final pages for substitution or missing glyphs.\n\n## Use appropriate form factors\n\n- Use prose for background, explanation, and rationale.\n- Use numbered steps for sequences and procedures.\n- Use bullets for loose factors, requirements, and grouped considerations.\n- Use checklists for acceptance criteria and review tasks.\n- Use restrained callouts for decisions, warnings, and key takeaways.\n- Use tables for repeated comparable records, schedules, budgets, status grids, and forms.\n- Use captions and source notes near the figures or tables they describe.\n\nAvoid consecutive dense tables, walls of text, decorative separators, excessive accent colors, and tables used only to position ordinary prose.\n\n## Tables\n\n- Choose widths based on content rather than equal-width defaults.\n- Keep short identifiers, dates, statuses, and numeric fields compact.\n- Give narrative columns enough width to wrap naturally.\n- Set cell margins and vertical alignment explicitly.\n- Never use fixed row heights that can clip text.\n- Repeat header rows for multi-page tables.\n- Keep captions and short source notes with the table when practical.\n- Render and inspect every page containing a dense or multi-page table.\n\n## Existing templates\n\nTreat a user-provided template as the design authority. Inspect its styles, theme fonts, numbering, page sections, table styles, headers, footers, and sample content before editing. Extend the nearest matching styles instead of imposing this default preset.\n","isInternal":false,"tokens":679,"sizeBytes":3037},{"name":"SKILL.md","path":"astrbot/builtin_stars/astrbot/skills/documents/SKILL.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/astrbot/builtin_stars/astrbot/skills/documents/SKILL.md","title":"documents","category":"anthropic-skill","format":"markdown","content":"---\nname: documents\ndescription: Create, read, edit, review, comment on, sanitize, render, and validate Microsoft Word DOCX documents. Use whenever a DOCX or Word document is a primary input or deliverable, including reports, proposals, forms, templates, tracked revisions, comments, tables, images, headers, footers, and style-preserving edits.\n---\n\n# Work with DOCX documents\n\nUse `python-docx` for ordinary creation and editing. Use direct OOXML inspection or small targeted patches only for features that `python-docx` cannot represent safely. Preserve the source unless the user explicitly requests an in-place edit.\n\n## Follow the workflow\n\n1. Inspect the source document's text, styles, sections, tables, images, comments, fields, tracked changes, content controls, headers, footers, and metadata as relevant.\n2. For edits, preserve the existing design and apply the smallest local change. Do not rebuild the document merely because creating a new one is easier.\n3. For new documents and major rewrites, choose a coherent design system before authoring. Read [styling.md](references/styling.md).\n4. Save to a new DOCX, reopen it with `python-docx`, validate the OOXML package, and render every page when LibreOffice and a PDF renderer are available.\n5. Inspect the rendered pages and iterate until there is no clipping, overlap, broken table geometry, missing glyph, awkward page break, or header/footer problem.\n\nUse the bundled inspector before unfamiliar edits:\n\n```text\npython <this-skill-directory>/scripts/inspect_docx.py input.docx\n```\n\nFor a quick text-only read, `astrbot_file_read_tool` is sufficient. Text extraction does not prove layout, comments, fields, tracked changes, or images are correct.\n\n## Create and edit with real document structure\n\n- Use Word paragraph styles for Normal, Title, Subtitle, Heading 1, Heading 2, and Heading 3 rather than styling every paragraph directly.\n- Use real list styles or numbering definitions. Do not type bullet characters, hyphen prefixes, or manual numbers into ordinary paragraphs.\n- Use tables only for genuinely tabular, comparable, or form-like content. Do not package long prose into grids.\n- Set page size, margins, orientation, header/footer distance, and section breaks explicitly.\n- Size table columns deliberately, enable wrapping, avoid fixed row heights, and repeat header rows when a table spans pages.\n- Preserve hyperlinks, relationships, bookmarks, captions, fields, comments, and tracked changes that are outside the requested edit.\n- Keep headings with following content and avoid leaving a heading alone at the bottom of a page.\n- Use comments for review feedback at the relevant text rather than collecting every note at the end.\n\n## Handle fonts and Chinese text\n\nDOCX files normally record font names rather than embedding the actual fonts. Choose common fonts and expect the opening application to substitute when a font is unavailable.\n\nSet all relevant Word font mappings for each styled run or style:\n\n```python\nfrom docx.oxml.ns import qn\n\nrun.font.name = \"Noto Sans CJK SC\"\nfonts = run._element.get_or_add_rPr().get_or_add_rFonts()\nfonts.set(qn(\"w:ascii\"), \"Noto Sans CJK SC\")\nfonts.set(qn(\"w:hAnsi\"), \"Noto Sans CJK SC\")\nfonts.set(qn(\"w:eastAsia\"), \"Noto Sans CJK SC\")\n```\n\nPrefer the user's template fonts. For a new cross-platform Chinese document, choose a readable system CJK font, verify that it exists in the actual render environment (`fc-match \"Font Name\"` when Fontconfig is available), and inspect the rendered output. Do not claim font consistency across devices unless the required font is installed or intentionally embedded with a licensed workflow.\n\n## Preserve advanced features\n\nRead [advanced-ooxml.md](references/advanced-ooxml.md) before changing tracked revisions, fields, content controls, protection, footnotes, endnotes, macros, digital signatures, or document relationships.\n\n- `python-docx` can create and read ordinary comments in current versions, but comments still require structural validation because headless renderers may omit them.\n- Tracked changes are not a safe first-class editing surface. Use targeted OOXML patches and preserve author/date data.\n- A visible table of contents is often cached field content. Preserve the field instructions and disclose when a calculating Word-compatible application must refresh them.\n- Preserve VBA only when explicitly working with a macro-enabled format. Do not rename DOCM to DOCX or claim macros are safe.\n- Editing a digitally signed document invalidates its signature. Preserve the source and report this before modifying it.\n\n## Inspect privacy and metadata\n\nReview author, last editor, creation/modification time, comments, tracked-change authors, custom properties, hidden text, document variables, external links, and embedded files before publishing sensitive documents.\n\nUse the bundled scrubber only when the user requests metadata removal:\n\n```text\npython <this-skill-directory>/scripts/privacy_scrub.py input.docx sanitized.docx\n```\n\nScrubbing metadata is not content redaction. Search visible text, headers, footers, comments, tracked changes, fields, hyperlinks, images, and embedded objects separately when removing sensitive information.\n\n## Validate and render\n\nRun structural validation after every create or edit operation:\n\n```text\npython <this-skill-directory>/scripts/validate_docx.py output.docx\n```\n\nWhen LibreOffice and a PDF renderer are available, render the document:\n\n```text\npython <this-skill-directory>/scripts/render_docx.py output.docx rendered\n```\n\nInspect every rendered page at normal zoom. Rendering is strong evidence for layout, fonts, spacing, tables, images, headers, footers, and page breaks. It is not sufficient proof for comments, field instructions, content controls, accessibility metadata, or tracked-change structure.\n\nIf rendering is unavailable, perform structural validation and disclose that visual QA was skipped. Do not imply that the document passed a render gate.\n\n## Finish\n\nDeliver only the requested DOCX unless the user asks for rendered pages, PDF, or other intermediates. Report the output path, representative changes, structural checks, visual QA status, and any limitation involving fonts, fields, macros, signatures, comments, revisions, or unsupported OOXML features.\n","frontmatter":{"name":"documents","description":"Create, read, edit, review, comment on, sanitize, render, and validate Microsoft Word DOCX documents. Use whenever a DOCX or Word document is a primary input or deliverable, including reports, proposals, forms, templates, tracked revisions, comments, tables, images, headers, footers, and style-preserving edits."},"isInternal":false,"tokens":1304,"sizeBytes":6307},{"name":"forms.md","path":"astrbot/builtin_stars/astrbot/skills/pdf/references/forms.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/astrbot/builtin_stars/astrbot/skills/pdf/references/forms.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# AcroForm handling\n\nUse this reference only for interactive PDF form tasks.\n\n## Inspect before editing\n\nCheck both representations of every field:\n\n1. Read the canonical tree with `PdfReader.get_fields()`.\n2. Enumerate `/Widget` annotations in every page's `/Annots` array.\n3. Follow `/Parent` and `/Kids` references when resolving field names and values.\n\nA widget can display a value from its appearance stream while the canonical `/AcroForm/Fields` tree contains a different value. If unrelated canonical fields and widgets reuse the same name, report the ambiguity instead of automatically reattaching fields.\n\n## Fill with pypdf\n\n```python\nfrom pypdf import PdfReader, PdfWriter\nfrom pypdf.generic import NameObject\n\nreader = PdfReader(input_path)\nwriter = PdfWriter()\nwriter.clone_document_from_reader(reader)\n\nwriter.reattach_fields()\nfields = writer.get_fields() or {}\nmissing = set(values) - set(fields)\nif missing:\n    raise ValueError(f\"Form fields not found: {sorted(missing)}\")\n\nvalues_to_write = dict(values)\nif flatten:\n    values_to_write = {\n        name: field.get(\"/V\", \"/Off\" if field.get(\"/FT\") == \"/Btn\" else \"\")\n        for name, field in fields.items()\n    }\n    values_to_write.update(values)\n\nwriter.update_page_form_field_values(\n    None,\n    values_to_write,\n    auto_regenerate=False,\n    flatten=flatten,\n)\n\nif flatten:\n    writer.remove_annotations(subtypes=\"/Widget\")\n    writer.root_object.pop(NameObject(\"/AcroForm\"), None)\n\nwith open(output_path, \"wb\") as output_file:\n    writer.write(output_file)\n```\n\nDo not flatten a signed document without an explicit decision from the user. Preserve the source and, when useful, retain an interactive copy alongside the flattened copy.\n\n## Validate after writing\n\nFor an interactive result:\n\n- Reopen the output and verify every expected field value in `get_fields()`.\n- Enumerate widgets again and verify their effective values, including inherited parent values.\n- Require updated widgets to have non-empty normal appearance streams under `/AP` and `/N`.\n- Render the affected pages to detect stale, clipped, or invisible appearances.\n\nFor a flattened result:\n\n- Require zero `/Widget` annotations.\n- Require no remaining `/AcroForm` field tree.\n- Render the affected pages and confirm the painted values remain visible.\n","isInternal":false,"tokens":496,"sizeBytes":2300},{"name":"SKILL.md","path":"astrbot/builtin_stars/astrbot/skills/pdf/SKILL.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/astrbot/builtin_stars/astrbot/skills/pdf/SKILL.md","title":"pdf","category":"anthropic-skill","format":"markdown","content":"---\nname: pdf\ndescription: Read, create, inspect, merge, split, rotate, encrypt, fill, and validate PDF files. Use when the user asks to work with a PDF or convert supported Markdown into a polished PDF in AstrBot.\n---\n\n# Work with PDFs\n\nUse `pypdf` for PDF structure operations and validation. Use ReportLab for new page layout. Do not install another PDF library unless the requested feature cannot be implemented safely with the bundled dependencies.\n\n## Follow the workflow\n\n1. Preserve source files unless the user explicitly requests an in-place change.\n2. Inspect the input with `pypdf.PdfReader`: page count, metadata, encryption, page sizes, text, annotations, and form fields as relevant.\n3. Perform the smallest operation that satisfies the request.\n4. Reopen every output with `pypdf` and verify its page count, expected text or fields, and encryption state.\n5. Render representative pages when a PDF renderer is available. Inspect the rendered images for clipping, overlap, missing glyphs, broken spacing, and blank pages. If rendering is unavailable, state that only structural validation was completed.\n\nWork in the current workspace unless the user provides another writable location. Keep intermediate files separate from final outputs and remove them when they are no longer needed.\n\n## Read and inspect\n\nUse `astrbot_file_read_tool` for a quick text extraction when it is sufficient. Use Python with `pypdf` when page structure or exact metadata matters:\n\n```python\nfrom pypdf import PdfReader\n\nreader = PdfReader(input_path)\nprint(len(reader.pages), reader.metadata)\nfor page_number, page in enumerate(reader.pages, start=1):\n    print(page_number, page.mediabox, page.rotation)\n    print(page.extract_text() or \"\")\n```\n\nText extraction does not prove that visual layout is correct. Render with `pdftoppm` when it is available:\n\n```text\npdftoppm -png -r 144 input.pdf rendered/page\n```\n\n## Create from Markdown\n\nPrefer the bundled deterministic converter:\n\n```text\npython <this-skill-directory>/scripts/markdown_to_pdf.py input.md output.pdf\n```\n\nThe converter intentionally supports a limited Markdown subset:\n\n- ATX headings (`#` through `######`)\n- paragraphs\n- flat ordered and unordered lists\n- block quotes\n- fenced code blocks\n- horizontal rules\n- `<!-- pagebreak -->`\n- bold, italic, inline code, and HTTP(S) or mail links\n\nIt does not interpret raw HTML, images, tables, nested lists, footnotes, or arbitrary Markdown extensions. Simplify unsupported content or explain the limitation instead of silently changing meaning.\n\nFont selection follows this order:\n\n1. Use an explicit readable font passed with `--font path/to/font.ttf` or `--font path/to/font.ttc`.\n2. Otherwise, search common system locations for a readable Chinese font and verify that it contains every character used by the document.\n3. If no suitable system font is available, use ReportLab's built-in Simplified Chinese fallback for supported Latin and Chinese text. The converter stops instead of silently emitting missing glyphs when the fallback cannot represent the input.\n\nWhen a broader or embedded font is required and no suitable system font is readable, download it into the workspace and pass its path with `--font`. Prefer an official source over an arbitrary font mirror or CDN:\n\n- [MiSans from Xiaomi](https://hyperos.mi.com/font/zh/download/) is an official source that is generally accessible from mainland China. Review its license before use and do not redistribute the font package unless the license permits it.\n- [Noto Sans CJK](https://github.com/notofonts/noto-cjk/blob/main/Sans/README.md) is an official open-source fallback with documented download options.\n\nIf an official GitHub font URL times out for a user in mainland China, the user may choose one of these third-party proxy prefixes:\n\n- `https://edgeone.gh-proxy.com/`\n- `https://hk.gh-proxy.com/`\n- `https://gh-proxy.com/`\n- `https://gh.dpik.top/`\n\nAppend the complete official GitHub URL directly after the prefix. For example:\n\n```text\nOfficial: https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/TTF/Subset/NotoSansSC-VF.ttf\nProxy:   https://edgeone.gh-proxy.com/https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/TTF/Subset/NotoSansSC-VF.ttf\n```\n\nThese proxies are not operated by the font project or AstrBot. Their availability and returned content can change. Never send credentials, private repository URLs, or other sensitive data through them. After downloading, verify that the final response used HTTPS, inspect the file type, and compare a checksum with an official checksum when one is published.\n\nDo not download a font silently. Obtain user approval when network access or a new file is required, use HTTPS, and keep the downloaded font in a workspace or temporary directory rather than installing it system-wide.\n\nAfter conversion, use `pypdf` to confirm the output opens, contains pages, and exposes representative expected text. Render and inspect the first page plus any page with dense content, code, or a page break.\n\n## Transform existing PDFs\n\nUse small `pypdf` scripts directly for ordinary operations.\n\nMerge documents in the requested order:\n\n```python\nfrom pypdf import PdfWriter\n\nwriter = PdfWriter()\nfor path in input_paths:\n    writer.append(path)\nwriter.write(output_path)\n```\n\nSplit selected pages without modifying the source:\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(input_path)\nwriter = PdfWriter()\nfor page_index in selected_zero_based_indexes:\n    writer.add_page(reader.pages[page_index])\nwriter.write(output_path)\n```\n\nRotate by a multiple of 90 degrees with `page.rotate(angle)`. Encrypt with `writer.encrypt(password)` only when the user asks, and never echo a password into logs or the final response. Reopen encrypted outputs with the password before reporting success.\n\n## Fill forms\n\nRead [forms.md](references/forms.md) before modifying AcroForms. Preserve interactivity unless the user requests a flattened result. Validate both the canonical field tree and page widget annotations; a successful render alone is not proof that field values were saved.\n\n## Finish\n\nReport the final path, the operation performed, and the validation completed. Mention any unsupported content, unavailable renderer, password requirement, or form ambiguity. Do not claim visual verification unless rendered pages were actually inspected.\n","frontmatter":{"name":"pdf","description":"Read, create, inspect, merge, split, rotate, encrypt, fill, and validate PDF files. Use when the user asks to work with a PDF or convert supported Markdown into a polished PDF in AstrBot."},"isInternal":false,"tokens":1356,"sizeBytes":6398},{"name":"SKILL.md","path":"astrbot/builtin_stars/astrbot/skills/skill-creator/SKILL.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/astrbot/builtin_stars/astrbot/skills/skill-creator/SKILL.md","title":"skill-creator","category":"anthropic-skill","format":"markdown","content":"---\nname: skill-creator\ndescription: Create, revise, and validate AstrBot Skills built around SKILL.md instruction bundles. Use when the user asks to create, scaffold, improve, package, or review a Skill for an AstrBot workspace, local installation, or plugin.\n---\n\n# Create AstrBot Skills\n\nBuild small, reusable instruction bundles that another agent can discover and follow reliably.\n\n## Follow the core design rules\n\n- Assume the model already knows general facts. Include only task-specific procedures, constraints, and resources.\n- Match instruction precision to risk. Use flexible guidance for judgment-heavy work and deterministic scripts for fragile operations.\n- Keep `SKILL.md` focused. Put detailed reference material in `references/`, repeatable automation in `scripts/`, and output material in `assets/`.\n- Link every optional resource directly from `SKILL.md` and state when to use it. Avoid deep chains of references.\n- Do not add process documents such as `README.md`, changelogs, installation guides, or quick-reference duplicates.\n- Do not add OpenAI- or Codex-specific metadata, directories, tools, or installation steps unless the user explicitly targets that runtime.\n\n## Establish the intended behavior\n\nBefore writing files, identify:\n\n1. Concrete requests that should trigger the Skill.\n2. Expected outputs or actions.\n3. Required tools, permissions, and runtime assumptions.\n4. Failure cases that need explicit guardrails.\n\nAsk only for information that materially changes the result. Infer ordinary details from the current task and environment.\n\n## Choose the target\n\nUse the runtime declared in the system instructions and the location requested by the user. Do not infer the runtime from filesystem paths.\n\nIn local mode, common targets are:\n\n- Workspace Skill: `<workspace>/skills/<skill-name>`\n- Locally installed Skill: `<astrbot-data>/skills/<skill-name>`.\n- Installed third-party plugin Skill: `<astrbot-data>/plugins/<plugin-name>/skills/<skill-name>`.\n\nIf no location is specified in local mode, create the Skill under `skills/<skill-name>` in the current AstrBot workspace. Creating or modifying a locally installed Skill requires administrator access and is enforced by the filesystem tools. If permission is denied, use the workspace target and explain the fallback.\n\nIn sandbox mode, do not use `<astrbot-data>` or attempt to install a Skill into the host AstrBot instance. Create it under `skills/<skill-name>` in the current sandbox workspace, and treat it as sandbox-scoped unless the runtime provides a dedicated persistence or release workflow.\n\nTreat plugin-provided Skills as read-only during normal runtime. Modify a plugin Skill only when the user is working in that plugin's source tree and has explicitly requested the change. If the requested target is not writable, create the Skill in the workspace and explain how to install or move it.\n\n## Name the Skill\n\n- Use lowercase letters, digits, and hyphens only.\n- Keep the name under 64 characters.\n- Prefer a short action-oriented name.\n- Name the folder exactly the same as the frontmatter `name`.\n\n## Plan only necessary resources\n\nFor each repeated operation, decide whether plain instructions are sufficient:\n\n- Add `scripts/` only for deterministic, repeatable operations.\n- Add `references/` only for material the agent may need to consult while working.\n- Add `assets/` only for files intended to be copied or incorporated into outputs.\n\nDo not create empty resource directories.\n\n## Write SKILL.md\n\nStart with YAML frontmatter containing only `name` and `description`:\n\n```yaml\n---\nname: example-skill\ndescription: Describe what the Skill does and the concrete requests or situations that should trigger it.\n---\n```\n\nMake the description specific enough for discovery. Put all trigger guidance in the description because AstrBot loads the body only after the Skill is selected.\n\nWrite the body as direct instructions:\n\n- Use imperative language.\n- Put the main workflow before edge cases.\n- State important safety boundaries close to the affected action.\n- Use the AstrBot tool names actually available in the current runtime when a workflow depends on tools.\n- Prefer relative paths inside the Skill so it works after installation or sandbox synchronization.\n- Keep examples short and representative.\n\n## Initialize or update files\n\nFor a new Skill, prefer the bundled initializer when Python and shell execution are available:\n\n```text\npython <this-skill-directory>/scripts/init_skill.py <skill-name> --path <target-skills-root> --description <description>\n```\n\nAdd `--resources scripts,references,assets` with only the directories that are needed. The initializer refuses to overwrite an existing Skill.\n\nIf shell execution is unavailable, create the directory and UTF-8 `SKILL.md` with `astrbot_file_write_tool`. Create optional resources only after their content is known.\n\nWhen updating a Skill, read its complete `SKILL.md` and directly referenced resources before editing. Preserve useful behavior and avoid unrelated restructuring.\n\n## Validate\n\nWhen Python and shell execution are available, run:\n\n```text\npython <this-skill-directory>/scripts/validate_skill.py <created-skill-directory>\n```\n\nOtherwise verify manually:\n\n- The directory name is valid and matches frontmatter `name`.\n- `SKILL.md` is UTF-8 and has valid YAML frontmatter.\n- `description` explains both capability and trigger conditions.\n- The body is non-empty and operational.\n- Every referenced file exists and every bundled file has a clear purpose.\n- Instructions do not assume unavailable tools, paths, credentials, or permissions.\n\nRun any bundled scripts on representative safe inputs. Fix validation or execution failures before presenting the Skill.\n\n## Finish\n\nReport the created or updated location, included resources, validation performed, and any runtime or activation step still required. Do not enable a globally installed Skill or change an AstrBot configuration unless the user requested it.\n","frontmatter":{"name":"skill-creator","description":"Create, revise, and validate AstrBot Skills built around SKILL.md instruction bundles. Use when the user asks to create, scaffold, improve, package, or review a Skill for an AstrBot workspace, local installation, or plugin."},"isInternal":false,"tokens":1180,"sizeBytes":5995},{"name":"charts.md","path":"astrbot/builtin_stars/astrbot/skills/spreadsheets/references/charts.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/astrbot/builtin_stars/astrbot/skills/spreadsheets/references/charts.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Spreadsheet charts\n\nCreate a chart only when it makes a comparison, trend, distribution, ranking, progress measure, or relationship easier to understand.\n\n## Select a chart\n\n- Use bars or columns for category comparison and ranking.\n- Use lines for trends over time.\n- Use scatter plots for relationships between numeric variables.\n- Use a histogram for a distribution when supported by the target viewer.\n- Use pie or doughnut charts only for a small number of meaningful parts of one whole.\n- Use a compact table when exact values matter more than visual pattern.\n\n## Build auditable chart data\n\n- Link series and categories directly to worksheet cells.\n- Use a formula-backed helper range only when reshaping, grouping dates, or shortening labels is necessary.\n- Keep unknown values blank rather than inventing zeroes.\n- Verify headers are not included as numeric points.\n- Keep category and value ranges the same length.\n- Use a text helper label such as `2026-08` when date-axis rendering is unreliable.\n\n## Format and place\n\n- Give each chart one clear takeaway and include units in the title or axis.\n- Use restrained, consistent colors and avoid gradients, 3D effects, and heavy borders.\n- Keep labels, ticks, legends, and titles readable at normal zoom.\n- Place charts beside or below the data they explain with blank gutters around them.\n- Do not cover cells, controls, notes, or other charts.\n- Set explicit axis number formats for currency, percentages, and dates.\n\nAfter saving, reopen the workbook and inspect chart series formulas. Render the sheet and check for blank charts, clipped labels, stale ranges, wrong orientation, unreadable legends, and excessive whitespace.\n","isInternal":false,"tokens":339,"sizeBytes":1689},{"name":"formatting.md","path":"astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formatting.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formatting.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Spreadsheet formatting\n\nUse this reference for new workbooks and substantial redesigns. Preserve an existing workbook's visual language unless the user requests a redesign.\n\n## Establish roles\n\nChoose a small role-based style system before writing cells:\n\n| Role | Default treatment |\n|---|---|\n| Workbook title | 16-18 pt, bold, dark neutral text, generous spacing |\n| Section title | 12-14 pt, bold, restrained accent or neutral fill |\n| Table header | Bold, high-contrast fill, centered only when appropriate |\n| Input | Light neutral or pale blue fill, unlocked when protection is used |\n| Formula | No fill or a subtle neutral fill; keep formulas visible |\n| Key output | Bold, explicit number format, light callout fill |\n| Note/source | Smaller muted text, URL in cell or comment |\n| Warning | Restrained amber or red used only for actionable exceptions |\n\nUse one body font and one optional display font. Prefer fonts commonly available across platforms. For Chinese workbooks, verify the chosen CJK font in the actual render environment (`fc-match \"Font Name\"` when Fontconfig is available), then inspect the rendered pages for substitution or missing glyphs. Keep body text around 10-11 pt and do not depend on color alone to communicate status.\n\n## Lay out the workbook\n\n- Put a clear title or table header near the top-left of each important sheet.\n- Keep assumptions and inputs separate from derived calculations in complex models.\n- Place important totals or KPIs where users can find them without scrolling to the bottom.\n- Freeze the header row for long tables and freeze identifier columns for wide tables.\n- Add filters or an Excel table for editable datasets.\n- Avoid merged cells in calculation or filter ranges. Reserve merges for titles or compact presentation labels.\n- Set print area, orientation, margins, repeated header rows, and fit-to-width for reports intended to print or render.\n- Remove empty default sheets and avoid large formatted-but-empty used ranges.\n\n## Size and align cells\n\n- Left-align descriptive text, right-align numbers, and use intentional alignment for short statuses and dates.\n- Widen columns before enabling deep wrapping. Cap descriptive columns around 50-60 characters unless the user requests otherwise.\n- Increase row height only enough to reveal wrapped content.\n- Use explicit formats such as `#,##0`, `#,##0.00`, `0.0%`, `yyyy-mm-dd`, and currency formats appropriate to the requested currency.\n- Preserve identifiers as text when leading zeroes or exact digits matter.\n\n## Tables and conditional formatting\n\n- Use light internal borders and a clearer outside or header boundary.\n- Use banded rows only when they materially improve scanning.\n- Apply conditional formatting over the intended editable range, not an entire worksheet.\n- Verify that formulas used by conditional formatting are anchored correctly at the top-left cell of the applied range.\n- Prefer data bars, color scales, or icon sets only when their scale and direction are meaningful.\n\n## Accessibility and usability\n\n- Use descriptive sheet names and unique table names.\n- Avoid hidden assumptions and unexplained abbreviations.\n- Add comments for important assumptions, unusual formulas, and data provenance.\n- Use data validation prompts and error messages for constrained inputs.\n- Keep color contrast readable and provide text or numeric cues in addition to color.\n","isInternal":false,"tokens":668,"sizeBytes":3397},{"name":"formulas.md","path":"astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formulas.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formulas.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Formula and validation rules\n\nUse this reference for formula-heavy workbooks and any task where calculated outputs matter.\n\n## Author formulas\n\n1. Create every referenced sheet before assigning cross-sheet formulas.\n2. Use formulas for derived values and hardcode only assumptions, raw facts, or explicitly requested fixed outputs.\n3. Use `$` anchors deliberately and test the first, middle, and last filled formulas.\n4. Quote sheet names in cross-sheet references.\n5. Bound lookup and aggregation ranges to the intended data area.\n6. Prefer `IFERROR` only when the fallback has a clear business meaning. Do not hide an unexpected error.\n7. Keep units consistent across inputs and outputs.\n\n## Understand calculation limits\n\n`openpyxl` preserves and writes formulas but does not calculate them. Loading with `data_only=True` returns cached values last saved by a calculating application; a newly authored formula may have no cached value.\n\nWhen a calculated result is required:\n\n1. Save the workbook with formulas intact.\n2. If LibreOffice or Excel is available, open and save a copy to recalculate it.\n3. Reopen the recalculated copy twice: once with `data_only=False` to verify formulas and once with `data_only=True` to inspect cached results.\n4. Reconcile important totals independently in Python for high-risk outputs.\n\nDo not treat a missing cached value as proof that a formula is wrong. Do treat a literal error value, `#REF!` inside a formula, a broken chart range, or a missing sheet reference as an error.\n\n## Validate\n\n- Scan all populated cells for Excel error literals.\n- Scan formulas and chart series for `#REF!`.\n- Confirm table and filter ranges include their headers and intended rows.\n- Confirm data validation and conditional-format ranges include future editable rows when requested.\n- Check duplicate table and defined-name identifiers.\n- Check for formulas that accidentally reference the header row or omit the final data row.\n- Review external links and disclose them; do not silently remove them.\n- Open macro-enabled files with `keep_vba=True` and preserve their extension.\n\nFor financial, legal, medical, or other high-stakes workbooks, independently recalculate representative results and document assumptions and source URLs inside the workbook.\n","isInternal":false,"tokens":452,"sizeBytes":2279},{"name":"SKILL.md","path":"astrbot/builtin_stars/astrbot/skills/spreadsheets/SKILL.md","rawUrl":"https://raw.githubusercontent.com/AstrBotDevs/AstrBot/HEAD/astrbot/builtin_stars/astrbot/skills/spreadsheets/SKILL.md","title":"spreadsheets","category":"anthropic-skill","format":"markdown","content":"---\nname: spreadsheets\ndescription: Create, read, edit, analyze, convert, chart, and validate spreadsheet files including XLSX, XLSM, XLS, CSV, and TSV. Use when a spreadsheet is a primary input or deliverable, or when tabular data must remain editable and auditable in workbook form.\n---\n\n# Work with spreadsheets\n\nUse `openpyxl` for XLSX/XLSM authoring, `xlrd` for legacy XLS reading, `pandas` for substantial data cleaning or analysis, and the standard `csv` module for simple CSV/TSV work. Preserve the source unless the user explicitly requests an in-place edit.\n\n## Choose the workflow\n\n1. For a read-only question, inspect only the relevant sheets, labels, values, formulas, tables, charts, and comments. Do not export a modified copy.\n2. For an existing workbook, study its structure and formatting before editing. Apply the smallest local change and extend nearby formulas, validation, conditional formatting, tables, and charts when the edited range requires it.\n3. For a new workbook, separate inputs, calculations, and outputs when the task contains derived values. Keep calculations visible and auditable.\n4. Save to a new file, reopen it, validate formulas and structure, and render every populated sheet when a renderer is available.\n\nUse the bundled inspector before unfamiliar edits:\n\n```text\npython <this-skill-directory>/scripts/inspect_workbook.py input.xlsx\n```\n\n## Respect format boundaries\n\n- Use `openpyxl.load_workbook(..., keep_vba=True)` for XLSM files and preserve the `.xlsm` extension. Do not claim that macros were inspected or are safe merely because they were preserved.\n- Treat XLS as a legacy read-only source. `xlrd` reads values and basic metadata but does not provide reliable modern editing. Convert the result to XLSX or CSV instead of overwriting the XLS file.\n- Preserve CSV/TSV delimiter, quoting, encoding, header order, and typed meaning. Keep identifiers such as ZIP codes and account numbers as text.\n- Never change a workbook's file extension without actually converting its format.\n\n## Keep formulas auditable\n\n- Write derived values as formulas rather than hardcoded results.\n- Place assumptions and raw inputs in visible cells or dedicated sheets.\n- Avoid magic numbers inside formulas. Reference an assumption cell instead.\n- Use correct absolute and relative references for fill behavior.\n- Quote every cross-sheet name: `='Revenue Model'!B4`, even when the current name has no spaces.\n- Prefer bounded ranges over full-column references in calculation-heavy formulas.\n- Use helper cells when a formula becomes difficult to understand or audit.\n- Add comments to important assumptions and source-backed inputs.\n- Check for `#REF!`, `#DIV/0!`, `#VALUE!`, `#NAME?`, `#NUM!`, `#NULL!`, and unexpected circular references.\n\n`openpyxl` writes formulas but does not calculate them. If formulas must be recalculated, open and save a copy with LibreOffice or Excel when available, then reopen the result with `data_only=False` and `data_only=True`. Never replace formulas with calculated constants merely to make validation pass. Read [formulas.md](references/formulas.md) for the detailed validation contract.\n\n## Format by meaning\n\nRead [formatting.md](references/formatting.md) before creating or substantially redesigning a workbook.\n\n- Store dates, numbers, currency, and percentages as typed values with explicit number formats.\n- Distinguish title, header, input, calculation, output, note, and warning roles consistently.\n- Prefer restrained fills and light structural borders. Do not decorate every populated cell with a border.\n- Freeze useful headers, enable filters, and use named tables for editable datasets.\n- Prefer conditional formatting over one-time manual fills when color represents a value or status.\n- Use data validation for editable categorical fields when practical.\n- Size columns and rows deliberately. Widen before wrapping, cap very wide columns, and avoid formatting unused ranges.\n- Hide gridlines only when explicit formatting already provides structure.\n\n## Use charts deliberately\n\nRead [charts.md](references/charts.md) before creating or editing charts. Create a chart only when it improves comparison, trend, distribution, ranking, progress, or relationship understanding.\n\n- Link chart series to worksheet ranges, not duplicated literal values.\n- Keep units explicit and titles focused on one takeaway.\n- Place charts in reserved areas without covering source data or controls.\n- Verify categories, series orientation, source ranges, point counts, axes, and placement after saving.\n- Prefer a compact table over a chart when exact values are the main point.\n\n## Convert CSV or TSV\n\nUse the bundled converter for a clean, typed, filterable workbook:\n\n```text\npython <this-skill-directory>/scripts/csv_to_xlsx.py input.csv output.xlsx\npython <this-skill-directory>/scripts/csv_to_xlsx.py input.tsv output.xlsx --delimiter tab\n```\n\nThe converter infers conservative scalar types, freezes the header, creates a table, applies number formats, and caps column widths. Inspect identifiers and locale-specific dates before accepting inferred types.\n\n## Validate and render\n\nRun structural validation after every create or edit operation:\n\n```text\npython <this-skill-directory>/scripts/validate_workbook.py output.xlsx\n```\n\nWhen LibreOffice and a PDF renderer are available, render the workbook:\n\n```text\npython <this-skill-directory>/scripts/render_workbook.py output.xlsx rendered\n```\n\nInspect every rendered page at normal zoom. Check for clipped headers or values, unexpected blank pages, broken charts, unreadable colors, bad page breaks, missing glyphs, formula errors, and content outside the visible area. Rendering does not prove formula correctness; structural and formula validation remain required.\n\nIf rendering is unavailable, report that only structural validation was completed. Do not imply that a workbook passed visual QA.\n\n## Finish\n\nDeliver only the requested workbook or tabular output unless the user asks for previews or intermediates. Report the output path, important sheets or changes, formula/recalculation status, validation performed, and any limitation involving macros, legacy XLS, unsupported formulas, fonts, or rendering.\n","frontmatter":{"name":"spreadsheets","description":"Create, read, edit, analyze, convert, chart, and validate spreadsheet files including XLSX, XLSM, XLS, CSV, and TSV. Use when a spreadsheet is a primary input or deliverable, or when tabular data must remain editable and auditable in workbook form."},"isInternal":false,"tokens":1271,"sizeBytes":6232}],"systemPromptSnippet":"<yakaai_skills repo=\"AstrBotDevs/AstrBot\">\n<!-- File: AGENTS.md (Tokens: ~1591 | Category: root-instruction) -->\n## Setup commands\n\n### Core\n\n```\nuv sync\nuv run main.py\n```\n\nExposed an API server on `http://localhost:6185` by default.\n\n### Dashboard(WebUI)\n\n```\ncd dashboard\npnpm install # First time only. Use npm install -g pnpm if pnpm is not installed.\npnpm dev\n```\n\nRuns on `http://localhost:3000` by default.\n\n## Pre-commit setup\n\nAstrBot uses [pre-commit](https://pre-commit.com/) hooks to automatically format and lint Python code before each commit. The hooks run `ruff check`, `ruff format`, and `pyupgrade` (see [`.pre-commit-config.yaml`](.pre-commit-config.yaml) for details).\n\nTo set it up:\n\n```bash\npip install pre-commit\npre-commit install\n```\n\nAfter installation, the hooks will run automatically on `git commit`. You can also run them manually at any time:\n\n```bash\nruff format .\nruff check .\n```\n\n> **Note:** If you use VSCode, install the `Ruff` extension for real-time formatting and linting in the editor.\n\n## Dev environment tips\n\n### Basic\n\n1. When modifying the WebUI, be sure to maintain componentization and clean code. Avoid duplicate code.\n2. Do not add any report files such as xxx_SUMMARY.md.\n3. After finishing, use `ruff format .` and `ruff check .` to format and check the code.\n4. When committing, ensure to use conventional commits messages, such as `feat: add new agent for data analysis` or `fix: resolve bug in provider manager`.\n5. Use **English** for all comments and logs.\n6. For path handling, use `pathlib.Path` instead of string paths, and use `astrbot.core.utils.path_utils` to get the AstrBot data and temp directory.\n7. When backend API routes, request/response schemas, or OpenAPI definitions change, regenerate the frontend API client by running `cd dashboard && pnpm generate:api`.\n8. When updating the project version, keep `[project].version` in `pyproject.toml` and `__version__` in `astrbot/__init__.py` in sync. `VERSION` in `astrbot/core/config/default.py` should derive from `astrbot.__version__` instead of hardcoding a separate version string.\n9. When designing WebUI dialogs, use `text-h3 pa-4 pb-0 pl-6` as the base class for dialog titles, and use `variant=\"text\"` or `variant=\"tonal\"` for dialog buttons.\n10. Consider cross-platform compatibility (e.g., Windows, macOS, and Linux, as well as Arm64 and x86 CPU architectures) and compatibility with Python 3.10+.\n11. When changing WebUI navigation, page structure, or terminology, update the affected instructions and screenshots in `docs/zh` and `docs/en` in the same PR. For renamed, moved, or merged entry points, include an old-to-new mapping in the relevant docs and changelog. Keep layout redesigns separate from feature additions where practical, and explain necessary navigation changes in the PR. See `CONTRIBUTING.md` for the review checklist.\n\n### KISS and First Principles\n\nFollow the KISS principle and reason from first principles during development. Start by identifying the real problem, required behavior, and smallest useful change before adding code. Do not pile on features, configuration switches, abstractions, dependencies, or compatibility layers unless they directly solve the current problem and have clear evidence of need.\n\nPrefer the simplest implementation that is correct, maintainable, and consistent with the existing codebase. If a broader design seems attractive, reduce it to the essential behavior needed now and leave optional expansion for a later, explicit requirement.\n\n### No Unnecessary Helpers\n\nPrioritize inline implementation over abstraction. Avoid over-engineering and do not create helper functions unless absolutely necessary.\n\n1. **Inline-First Rule**: If a logic block can be implemented directly within the main function without breaking overall readability, **do not** extract it into a new helper function.\n2. **Strict Justification for Helpers**: You may only create a separate helper function if it meets at least one of these criteria:\n   - **High Reuse**: The exact same logic is repeated across **3 or more** different locations.\n   - **Extreme Complexity**: Inlining the logic makes the main function too long (e.g., >50 lines) or severely derails the main execution flow.\n3. **No Fragmentation**: Do not split continuous linear logic (e.g., a single API call, simple form validation, or one-time data formatting) into tiny functions just for the sake of \"clean code.\"\n4. **Keep Context Compact**: Handle edge cases, error catching, and logging directly inside the main function block instead of offloading them.\n5. **Refactoring Constraint**: When modifying existing code, do not alter the current function structure or extract code into new helpers unless the existing code already violates the complexity or reuse rules above.\n\n### Mandatory Google-Style Docstrings\n* **Comment the complex**: Add clear comments to any non-obvious function, method, or parameter.\n* **Google Format**: All docstrings must strictly use the Google format (`Args:`, `Returns:`, `Raises:`).\n\n#### Example:\n\n```py\ndef calculate_metrics(user_id: int, force_refresh: bool = False) -> dict:\n    \"\"\"Brief description of the function.\n\n    Args:\n        user_id: Description of the ID.\n        force_refresh: Description of the flag.\n\n    Returns:\n        Description of the returned dict.\n\n    Raises:\n        ValueError: Description of when this occurs.\n    \"\"\"\n    # Inline implementation here...\n```\n\n\n## PR instructions\n\n1. Title format: use conventional commit messages\n2. Use English to write PR title and descriptions.\n\n## Release versions\n\nUse a short-lived `release/*` branch for each release. The release branch is the stabilization area for version bumps, changelog updates, release-blocking fixes, and final validation only. Do not add unrelated features or broad refactors to a release branch.\n\nPrepare a release from a clean worktree with:\n\n```bash\nuv run python scripts/prepare_release.py 4.25.0\n```\n\nThe script updates `pyproject.toml` and `astrbot/__init__.py`, creates `changelogs/v4.25.0.md`, runs the required Python checks, and prints the remaining steps. Use these flags when needed:\n\n```bash\nuv run python scripts/prepare_release.py 4.25.0 --generate-api-client\nuv run python scripts/prepare_release.py 4.25.0 --dashboard-build\nuv run python scripts/prepare_release.py 4.25.0 --commit --push\n```\n\nOpen a PR from `release/4.25.0` to `master`. The PR title must use the conventional commit format, for example `chore: bump version to 4.25.0`. After the release PR is merged, create and push the tag from the updated `master` branch so the tag points to the exact code that was merged:\n\n```bash\ngit checkout master\ngit pull --ff-only origin master\ngit tag v4.25.0\ngit push origin v4.25.0\n```\n\nFor one-off release candidate branches, delete the release branch after the tag is pushed and verified. For maintained release lines, use a branch such as `release/4.25` and keep it until that line reaches EOL.\n\n```bash\ngit branch -d release/4.25.0\ngit push origin --delete release/4.25.0\n```\n\n<!-- File: .github/copilot-instructions.md (Tokens: ~740 | Category: copilot-instructions) -->\n# AstrBot Development Instructions\n\nAstrBot is a multi-platform LLM chatbot and development framework written in Python with a Vue.js dashboard. It supports multiple messaging platforms (QQ, Telegram, Discord, etc.) and various LLM providers (OpenAI, Anthropic, Google Gemini, etc.).\n\nAlways reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.\n\n## Working Effectively\n\n### Bootstrap and Install Dependencies\n- **Python 3.10+ required** - Check `.python-version` file\n- Install UV package manager: `pip install uv`\n- Install project dependencies: `uv sync` -- takes 6-7 minutes. NEVER CANCEL. Set timeout to 10+ minutes.\n- Create required directories: `mkdir -p data/plugins data/config data/temp`\n\n### Running the Application\n- Run main application: `uv run main.py` -- starts in ~3 seconds\n- Application creates WebUI on http://localhost:6185 (default credentials: `astrbot`/`astrbot`)\n\n### Dashboard Build (Vue.js/Node.js)\n- **Prerequisites**: Node.js 20+ and npm 10+ required\n- Navigate to dashboard: `cd dashboard`\n- Install dashboard dependencies: `npm install` -- takes 2-3 minutes. NEVER CANCEL. Set timeout to 5+ minutes.\n- Build dashboard: `npm run build` -- takes 25-30 seconds. NEVER CANCEL.\n- Dashboard creates optimized production build in `dashboard/dist/`\n\n### Testing\n- Do not generate test files for now.\n\n### Code Quality and Linting\n- Install ruff linter: `uv add --dev ruff`\n- Check code style: `uv run ruff check .` -- takes <1 second\n- Check formatting: `uv run ruff format --check .` -- takes <1 second\n- Fix formatting: `uv run ruff format .`\n- **ALWAYS** run `uv run ruff check .` and `uv run ruff format .` before committing changes\n\n### Plugin Development\n- Plugins load from `astrbot/builtin_stars/` (built-in) and `data/plugins/` (user-installed)\n- Plugin system supports function tools and message handlers\n- Key plugins: python_interpreter, web_searcher, astrbot, reminder, session_controller\n\n### Common Issues and Workarounds\n- **Dashboard download fails**: Known issue with \"division by zero\" error - application still works\n- **Import errors in tests**: Ensure `uv run` is used to run tests in proper environment\n=- **Build timeouts**: Always set appropriate timeouts (10+ minutes for uv sync, 5+ minutes for npm install)\n\n## CI/CD Integration\n- GitHub Actions workflows in `.github/workflows/`\n- Docker builds supported via `Dockerfile`\n- Pre-commit hooks enforce ruff formatting and linting\n\n## Docker Support\n- Primary deployment method: `docker run soulter/astrbot:latest`\n- Compose file available: `compose.yml`\n- Exposes ports: 6185 (WebUI), 6195 (WeChat), 6199 (QQ), etc.\n- Volume mount required: `./data:/AstrBot/data`\n\n## Multi-language Support\n- Documentation in Chinese (README.md), English (README_en.md), Japanese (README_ja.md)\n- UI supports internationalization\n- Default language is Chinese\n\nRemember: This is a production chatbot framework with real users. Always test thoroughly and ensure changes don't break existing functionality.\n\n<!-- File: astrbot/builtin_stars/astrbot/skills/documents/references/advanced-ooxml.md (Tokens: ~574 | Category: anthropic-skill) -->\n# Advanced DOCX and OOXML operations\n\nRead this reference before modifying features that `python-docx` does not fully support.\n\n## Work safely\n\n1. Preserve the original package.\n2. Inspect ZIP members, content types, relationships, and the exact XML elements involved.\n3. Patch only the necessary parts and relationships.\n4. Write a new package without dropping unrelated members.\n5. Reopen with `python-docx`, parse every XML part, run structural validation, and render again.\n\nUse namespace-aware XML handling. Never use regular-expression replacement across XML markup.\n\n## Comments\n\nValidate all of these together:\n\n- `word/comments.xml`\n- comment relationships and content-type declarations\n- `w:commentRangeStart`, `w:commentRangeEnd`, and `w:commentReference` anchors\n- unique comment IDs and preserved author/date values\n\nHeadless PDF exports frequently omit comments. Structural validation remains mandatory.\n\n## Tracked changes\n\nTracked insertions and deletions use `w:ins` and `w:del`, with author, date, and ID metadata. Text inside deletions commonly uses `w:delText` rather than `w:t`.\n\n- Do not flatten revisions unless the user asks to accept or reject them.\n- Preserve revision metadata when adding or editing tracked changes.\n- Inspect headers, footers, footnotes, and comments in addition to the main document.\n- Render the revision view when possible, but also inspect the XML because renderer settings can hide revisions.\n\n## Fields and navigation\n\nTOCs, page numbers, cross-references, captions, and many calculated values use field instructions and cached display text.\n\n- Preserve `w:fldSimple` or complex `w:fldChar` begin/separate/end sequences.\n- Preserve bookmarks and relationship targets used by internal links.\n- Do not replace a dynamic field with static visible text unless the user requests flattening.\n- Disclose when Word or LibreOffice must refresh field results.\n\n## Content controls and forms\n\nContent controls use `w:sdt`. Preserve aliases, tags, data binding, locks, placeholder state, and repeating-section structure. Do not convert a content control to plain text merely to edit its visible value unless the user accepts losing the control.\n\n## Protection, macros, and signatures\n\n- Treat editing restrictions as workflow controls, not encryption.\n- Preserve macros only in macro-enabled formats and never execute them during inspection.\n- Do not remove or bypass protection without explicit authorization.\n- Any document edit can invalidate a digital signature. Preserve the signed source and report the consequence.\n\n## Merge and template operations\n\nDOCX parts can reuse style IDs, numbering IDs, relationship IDs, bookmark IDs, image names, and drawing IDs. A safe merge must remap collisions and preserve referenced parts. Prefer template-based creation or a well-tested merge library over appending raw XML from unrelated packages.\n\n<!-- File: astrbot/builtin_stars/astrbot/skills/documents/references/styling.md (Tokens: ~679 | Category: anthropic-skill) -->\n# DOCX styling and layout\n\nUse this reference for new documents and major rewrites. For existing-document edits, preserve the document's style unless the user requests a redesign.\n\n## Choose a design system\n\nResolve the following values before authoring:\n\n- page size, orientation, margins, and header/footer distance\n- body font, East Asian font, base size, line spacing, and paragraph spacing\n- title and heading sizes, colors, and keep-with-next behavior\n- bullet and numbered-list indentation\n- table width, column widths, cell margins, borders, fills, and repeated headers\n- callout, caption, source-note, header, and footer treatments\n\nApply these values through Word styles and reusable table/list definitions. Use direct formatting only for intentional exceptions.\n\n## Recommended neutral preset\n\nFor a general professional document when the user provides no template:\n\n| Element | Suggested values |\n|---|---|\n| Page | A4 or Letter according to locale, portrait |\n| Margins | 20-25 mm / 0.8-1.0 in |\n| Body | 10.5-11 pt, 1.15-1.3 line spacing, 6-8 pt after |\n| Title | 24-28 pt, dark neutral, 12-18 pt after |\n| Heading 1 | 16-18 pt, 12-16 pt before, 6-8 pt after |\n| Heading 2 | 13-15 pt, 10-12 pt before, 4-6 pt after |\n| Heading 3 | 11-12 pt, 8 pt before, 3-4 pt after |\n| Table text | 9-10.5 pt with explicit cell margins |\n| Header/footer | 8-9 pt muted text, used only when helpful |\n\nFor Chinese documents, set both Latin and East Asian fonts on styles. Prefer a system font that can be rendered in the current environment and inspect the final pages for substitution or missing glyphs.\n\n## Use appropriate form factors\n\n- Use prose for background, explanation, and rationale.\n- Use numbered steps for sequences and procedures.\n- Use bullets for loose factors, requirements, and grouped considerations.\n- Use checklists for acceptance criteria and review tasks.\n- Use restrained callouts for decisions, warnings, and key takeaways.\n- Use tables for repeated comparable records, schedules, budgets, status grids, and forms.\n- Use captions and source notes near the figures or tables they describe.\n\nAvoid consecutive dense tables, walls of text, decorative separators, excessive accent colors, and tables used only to position ordinary prose.\n\n## Tables\n\n- Choose widths based on content rather than equal-width defaults.\n- Keep short identifiers, dates, statuses, and numeric fields compact.\n- Give narrative columns enough width to wrap naturally.\n- Set cell margins and vertical alignment explicitly.\n- Never use fixed row heights that can clip text.\n- Repeat header rows for multi-page tables.\n- Keep captions and short source notes with the table when practical.\n- Render and inspect every page containing a dense or multi-page table.\n\n## Existing templates\n\nTreat a user-provided template as the design authority. Inspect its styles, theme fonts, numbering, page sections, table styles, headers, footers, and sample content before editing. Extend the nearest matching styles instead of imposing this default preset.\n\n<!-- File: astrbot/builtin_stars/astrbot/skills/documents/SKILL.md (Tokens: ~1304 | Category: anthropic-skill) -->\n---\nname: documents\ndescription: Create, read, edit, review, comment on, sanitize, render, and validate Microsoft Word DOCX documents. Use whenever a DOCX or Word document is a primary input or deliverable, including reports, proposals, forms, templates, tracked revisions, comments, tables, images, headers, footers, and style-preserving edits.\n---\n\n# Work with DOCX documents\n\nUse `python-docx` for ordinary creation and editing. Use direct OOXML inspection or small targeted patches only for features that `python-docx` cannot represent safely. Preserve the source unless the user explicitly requests an in-place edit.\n\n## Follow the workflow\n\n1. Inspect the source document's text, styles, sections, tables, images, comments, fields, tracked changes, content controls, headers, footers, and metadata as relevant.\n2. For edits, preserve the existing design and apply the smallest local change. Do not rebuild the document merely because creating a new one is easier.\n3. For new documents and major rewrites, choose a coherent design system before authoring. Read [styling.md](references/styling.md).\n4. Save to a new DOCX, reopen it with `python-docx`, validate the OOXML package, and render every page when LibreOffice and a PDF renderer are available.\n5. Inspect the rendered pages and iterate until there is no clipping, overlap, broken table geometry, missing glyph, awkward page break, or header/footer problem.\n\nUse the bundled inspector before unfamiliar edits:\n\n```text\npython <this-skill-directory>/scripts/inspect_docx.py input.docx\n```\n\nFor a quick text-only read, `astrbot_file_read_tool` is sufficient. Text extraction does not prove layout, comments, fields, tracked changes, or images are correct.\n\n## Create and edit with real document structure\n\n- Use Word paragraph styles for Normal, Title, Subtitle, Heading 1, Heading 2, and Heading 3 rather than styling every paragraph directly.\n- Use real list styles or numbering definitions. Do not type bullet characters, hyphen prefixes, or manual numbers into ordinary paragraphs.\n- Use tables only for genuinely tabular, comparable, or form-like content. Do not package long prose into grids.\n- Set page size, margins, orientation, header/footer distance, and section breaks explicitly.\n- Size table columns deliberately, enable wrapping, avoid fixed row heights, and repeat header rows when a table spans pages.\n- Preserve hyperlinks, relationships, bookmarks, captions, fields, comments, and tracked changes that are outside the requested edit.\n- Keep headings with following content and avoid leaving a heading alone at the bottom of a page.\n- Use comments for review feedback at the relevant text rather than collecting every note at the end.\n\n## Handle fonts and Chinese text\n\nDOCX files normally record font names rather than embedding the actual fonts. Choose common fonts and expect the opening application to substitute when a font is unavailable.\n\nSet all relevant Word font mappings for each styled run or style:\n\n```python\nfrom docx.oxml.ns import qn\n\nrun.font.name = \"Noto Sans CJK SC\"\nfonts = run._element.get_or_add_rPr().get_or_add_rFonts()\nfonts.set(qn(\"w:ascii\"), \"Noto Sans CJK SC\")\nfonts.set(qn(\"w:hAnsi\"), \"Noto Sans CJK SC\")\nfonts.set(qn(\"w:eastAsia\"), \"Noto Sans CJK SC\")\n```\n\nPrefer the user's template fonts. For a new cross-platform Chinese document, choose a readable system CJK font, verify that it exists in the actual render environment (`fc-match \"Font Name\"` when Fontconfig is available), and inspect the rendered output. Do not claim font consistency across devices unless the required font is installed or intentionally embedded with a licensed workflow.\n\n## Preserve advanced features\n\nRead [advanced-ooxml.md](references/advanced-ooxml.md) before changing tracked revisions, fields, content controls, protection, footnotes, endnotes, macros, digital signatures, or document relationships.\n\n- `python-docx` can create and read ordinary comments in current versions, but comments still require structural validation because headless renderers may omit them.\n- Tracked changes are not a safe first-class editing surface. Use targeted OOXML patches and preserve author/date data.\n- A visible table of contents is often cached field content. Preserve the field instructions and disclose when a calculating Word-compatible application must refresh them.\n- Preserve VBA only when explicitly working with a macro-enabled format. Do not rename DOCM to DOCX or claim macros are safe.\n- Editing a digitally signed document invalidates its signature. Preserve the source and report this before modifying it.\n\n## Inspect privacy and metadata\n\nReview author, last editor, creation/modification time, comments, tracked-change authors, custom properties, hidden text, document variables, external links, and embedded files before publishing sensitive documents.\n\nUse the bundled scrubber only when the user requests metadata removal:\n\n```text\npython <this-skill-directory>/scripts/privacy_scrub.py input.docx sanitized.docx\n```\n\nScrubbing metadata is not content redaction. Search visible text, headers, footers, comments, tracked changes, fields, hyperlinks, images, and embedded objects separately when removing sensitive information.\n\n## Validate and render\n\nRun structural validation after every create or edit operation:\n\n```text\npython <this-skill-directory>/scripts/validate_docx.py output.docx\n```\n\nWhen LibreOffice and a PDF renderer are available, render the document:\n\n```text\npython <this-skill-directory>/scripts/render_docx.py output.docx rendered\n```\n\nInspect every rendered page at normal zoom. Rendering is strong evidence for layout, fonts, spacing, tables, images, headers, footers, and page breaks. It is not sufficient proof for comments, field instructions, content controls, accessibility metadata, or tracked-change structure.\n\nIf rendering is unavailable, perform structural validation and disclose that visual QA was skipped. Do not imply that the document passed a render gate.\n\n## Finish\n\nDeliver only the requested DOCX unless the user asks for rendered pages, PDF, or other intermediates. Report the output path, representative changes, structural checks, visual QA status, and any limitation involving fonts, fields, macros, signatures, comments, revisions, or unsupported OOXML features.\n\n<!-- File: astrbot/builtin_stars/astrbot/skills/pdf/references/forms.md (Tokens: ~496 | Category: anthropic-skill) -->\n# AcroForm handling\n\nUse this reference only for interactive PDF form tasks.\n\n## Inspect before editing\n\nCheck both representations of every field:\n\n1. Read the canonical tree with `PdfReader.get_fields()`.\n2. Enumerate `/Widget` annotations in every page's `/Annots` array.\n3. Follow `/Parent` and `/Kids` references when resolving field names and values.\n\nA widget can display a value from its appearance stream while the canonical `/AcroForm/Fields` tree contains a different value. If unrelated canonical fields and widgets reuse the same name, report the ambiguity instead of automatically reattaching fields.\n\n## Fill with pypdf\n\n```python\nfrom pypdf import PdfReader, PdfWriter\nfrom pypdf.generic import NameObject\n\nreader = PdfReader(input_path)\nwriter = PdfWriter()\nwriter.clone_document_from_reader(reader)\n\nwriter.reattach_fields()\nfields = writer.get_fields() or {}\nmissing = set(values) - set(fields)\nif missing:\n    raise ValueError(f\"Form fields not found: {sorted(missing)}\")\n\nvalues_to_write = dict(values)\nif flatten:\n    values_to_write = {\n        name: field.get(\"/V\", \"/Off\" if field.get(\"/FT\") == \"/Btn\" else \"\")\n        for name, field in fields.items()\n    }\n    values_to_write.update(values)\n\nwriter.update_page_form_field_values(\n    None,\n    values_to_write,\n    auto_regenerate=False,\n    flatten=flatten,\n)\n\nif flatten:\n    writer.remove_annotations(subtypes=\"/Widget\")\n    writer.root_object.pop(NameObject(\"/AcroForm\"), None)\n\nwith open(output_path, \"wb\") as output_file:\n    writer.write(output_file)\n```\n\nDo not flatten a signed document without an explicit decision from the user. Preserve the source and, when useful, retain an interactive copy alongside the flattened copy.\n\n## Validate after writing\n\nFor an interactive result:\n\n- Reopen the output and verify every expected field value in `get_fields()`.\n- Enumerate widgets again and verify their effective values, including inherited parent values.\n- Require updated widgets to have non-empty normal appearance streams under `/AP` and `/N`.\n- Render the affected pages to detect stale, clipped, or invisible appearances.\n\nFor a flattened result:\n\n- Require zero `/Widget` annotations.\n- Require no remaining `/AcroForm` field tree.\n- Render the affected pages and confirm the painted values remain visible.\n\n<!-- File: astrbot/builtin_stars/astrbot/skills/pdf/SKILL.md (Tokens: ~1356 | Category: anthropic-skill) -->\n---\nname: pdf\ndescription: Read, create, inspect, merge, split, rotate, encrypt, fill, and validate PDF files. Use when the user asks to work with a PDF or convert supported Markdown into a polished PDF in AstrBot.\n---\n\n# Work with PDFs\n\nUse `pypdf` for PDF structure operations and validation. Use ReportLab for new page layout. Do not install another PDF library unless the requested feature cannot be implemented safely with the bundled dependencies.\n\n## Follow the workflow\n\n1. Preserve source files unless the user explicitly requests an in-place change.\n2. Inspect the input with `pypdf.PdfReader`: page count, metadata, encryption, page sizes, text, annotations, and form fields as relevant.\n3. Perform the smallest operation that satisfies the request.\n4. Reopen every output with `pypdf` and verify its page count, expected text or fields, and encryption state.\n5. Render representative pages when a PDF renderer is available. Inspect the rendered images for clipping, overlap, missing glyphs, broken spacing, and blank pages. If rendering is unavailable, state that only structural validation was completed.\n\nWork in the current workspace unless the user provides another writable location. Keep intermediate files separate from final outputs and remove them when they are no longer needed.\n\n## Read and inspect\n\nUse `astrbot_file_read_tool` for a quick text extraction when it is sufficient. Use Python with `pypdf` when page structure or exact metadata matters:\n\n```python\nfrom pypdf import PdfReader\n\nreader = PdfReader(input_path)\nprint(len(reader.pages), reader.metadata)\nfor page_number, page in enumerate(reader.pages, start=1):\n    print(page_number, page.mediabox, page.rotation)\n    print(page.extract_text() or \"\")\n```\n\nText extraction does not prove that visual layout is correct. Render with `pdftoppm` when it is available:\n\n```text\npdftoppm -png -r 144 input.pdf rendered/page\n```\n\n## Create from Markdown\n\nPrefer the bundled deterministic converter:\n\n```text\npython <this-skill-directory>/scripts/markdown_to_pdf.py input.md output.pdf\n```\n\nThe converter intentionally supports a limited Markdown subset:\n\n- ATX headings (`#` through `######`)\n- paragraphs\n- flat ordered and unordered lists\n- block quotes\n- fenced code blocks\n- horizontal rules\n- `<!-- pagebreak -->`\n- bold, italic, inline code, and HTTP(S) or mail links\n\nIt does not interpret raw HTML, images, tables, nested lists, footnotes, or arbitrary Markdown extensions. Simplify unsupported content or explain the limitation instead of silently changing meaning.\n\nFont selection follows this order:\n\n1. Use an explicit readable font passed with `--font path/to/font.ttf` or `--font path/to/font.ttc`.\n2. Otherwise, search common system locations for a readable Chinese font and verify that it contains every character used by the document.\n3. If no suitable system font is available, use ReportLab's built-in Simplified Chinese fallback for supported Latin and Chinese text. The converter stops instead of silently emitting missing glyphs when the fallback cannot represent the input.\n\nWhen a broader or embedded font is required and no suitable system font is readable, download it into the workspace and pass its path with `--font`. Prefer an official source over an arbitrary font mirror or CDN:\n\n- [MiSans from Xiaomi](https://hyperos.mi.com/font/zh/download/) is an official source that is generally accessible from mainland China. Review its license before use and do not redistribute the font package unless the license permits it.\n- [Noto Sans CJK](https://github.com/notofonts/noto-cjk/blob/main/Sans/README.md) is an official open-source fallback with documented download options.\n\nIf an official GitHub font URL times out for a user in mainland China, the user may choose one of these third-party proxy prefixes:\n\n- `https://edgeone.gh-proxy.com/`\n- `https://hk.gh-proxy.com/`\n- `https://gh-proxy.com/`\n- `https://gh.dpik.top/`\n\nAppend the complete official GitHub URL directly after the prefix. For example:\n\n```text\nOfficial: https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/TTF/Subset/NotoSansSC-VF.ttf\nProxy:   https://edgeone.gh-proxy.com/https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/TTF/Subset/NotoSansSC-VF.ttf\n```\n\nThese proxies are not operated by the font project or AstrBot. Their availability and returned content can change. Never send credentials, private repository URLs, or other sensitive data through them. After downloading, verify that the final response used HTTPS, inspect the file type, and compare a checksum with an official checksum when one is published.\n\nDo not download a font silently. Obtain user approval when network access or a new file is required, use HTTPS, and keep the downloaded font in a workspace or temporary directory rather than installing it system-wide.\n\nAfter conversion, use `pypdf` to confirm the output opens, contains pages, and exposes representative expected text. Render and inspect the first page plus any page with dense content, code, or a page break.\n\n## Transform existing PDFs\n\nUse small `pypdf` scripts directly for ordinary operations.\n\nMerge documents in the requested order:\n\n```python\nfrom pypdf import PdfWriter\n\nwriter = PdfWriter()\nfor path in input_paths:\n    writer.append(path)\nwriter.write(output_path)\n```\n\nSplit selected pages without modifying the source:\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(input_path)\nwriter = PdfWriter()\nfor page_index in selected_zero_based_indexes:\n    writer.add_page(reader.pages[page_index])\nwriter.write(output_path)\n```\n\nRotate by a multiple of 90 degrees with `page.rotate(angle)`. Encrypt with `writer.encrypt(password)` only when the user asks, and never echo a password into logs or the final response. Reopen encrypted outputs with the password before reporting success.\n\n## Fill forms\n\nRead [forms.md](references/forms.md) before modifying AcroForms. Preserve interactivity unless the user requests a flattened result. Validate both the canonical field tree and page widget annotations; a successful render alone is not proof that field values were saved.\n\n## Finish\n\nReport the final path, the operation performed, and the validation completed. Mention any unsupported content, unavailable renderer, password requirement, or form ambiguity. Do not claim visual verification unless rendered pages were actually inspected.\n\n<!-- File: astrbot/builtin_stars/astrbot/skills/skill-creator/SKILL.md (Tokens: ~1180 | Category: anthropic-skill) -->\n---\nname: skill-creator\ndescription: Create, revise, and validate AstrBot Skills built around SKILL.md instruction bundles. Use when the user asks to create, scaffold, improve, package, or review a Skill for an AstrBot workspace, local installation, or plugin.\n---\n\n# Create AstrBot Skills\n\nBuild small, reusable instruction bundles that another agent can discover and follow reliably.\n\n## Follow the core design rules\n\n- Assume the model already knows general facts. Include only task-specific procedures, constraints, and resources.\n- Match instruction precision to risk. Use flexible guidance for judgment-heavy work and deterministic scripts for fragile operations.\n- Keep `SKILL.md` focused. Put detailed reference material in `references/`, repeatable automation in `scripts/`, and output material in `assets/`.\n- Link every optional resource directly from `SKILL.md` and state when to use it. Avoid deep chains of references.\n- Do not add process documents such as `README.md`, changelogs, installation guides, or quick-reference duplicates.\n- Do not add OpenAI- or Codex-specific metadata, directories, tools, or installation steps unless the user explicitly targets that runtime.\n\n## Establish the intended behavior\n\nBefore writing files, identify:\n\n1. Concrete requests that should trigger the Skill.\n2. Expected outputs or actions.\n3. Required tools, permissions, and runtime assumptions.\n4. Failure cases that need explicit guardrails.\n\nAsk only for information that materially changes the result. Infer ordinary details from the current task and environment.\n\n## Choose the target\n\nUse the runtime declared in the system instructions and the location requested by the user. Do not infer the runtime from filesystem paths.\n\nIn local mode, common targets are:\n\n- Workspace Skill: `<workspace>/skills/<skill-name>`\n- Locally installed Skill: `<astrbot-data>/skills/<skill-name>`.\n- Installed third-party plugin Skill: `<astrbot-data>/plugins/<plugin-name>/skills/<skill-name>`.\n\nIf no location is specified in local mode, create the Skill under `skills/<skill-name>` in the current AstrBot workspace. Creating or modifying a locally installed Skill requires administrator access and is enforced by the filesystem tools. If permission is denied, use the workspace target and explain the fallback.\n\nIn sandbox mode, do not use `<astrbot-data>` or attempt to install a Skill into the host AstrBot instance. Create it under `skills/<skill-name>` in the current sandbox workspace, and treat it as sandbox-scoped unless the runtime provides a dedicated persistence or release workflow.\n\nTreat plugin-provided Skills as read-only during normal runtime. Modify a plugin Skill only when the user is working in that plugin's source tree and has explicitly requested the change. If the requested target is not writable, create the Skill in the workspace and explain how to install or move it.\n\n## Name the Skill\n\n- Use lowercase letters, digits, and hyphens only.\n- Keep the name under 64 characters.\n- Prefer a short action-oriented name.\n- Name the folder exactly the same as the frontmatter `name`.\n\n## Plan only necessary resources\n\nFor each repeated operation, decide whether plain instructions are sufficient:\n\n- Add `scripts/` only for deterministic, repeatable operations.\n- Add `references/` only for material the agent may need to consult while working.\n- Add `assets/` only for files intended to be copied or incorporated into outputs.\n\nDo not create empty resource directories.\n\n## Write SKILL.md\n\nStart with YAML frontmatter containing only `name` and `description`:\n\n```yaml\n---\nname: example-skill\ndescription: Describe what the Skill does and the concrete requests or situations that should trigger it.\n---\n```\n\nMake the description specific enough for discovery. Put all trigger guidance in the description because AstrBot loads the body only after the Skill is selected.\n\nWrite the body as direct instructions:\n\n- Use imperative language.\n- Put the main workflow before edge cases.\n- State important safety boundaries close to the affected action.\n- Use the AstrBot tool names actually available in the current runtime when a workflow depends on tools.\n- Prefer relative paths inside the Skill so it works after installation or sandbox synchronization.\n- Keep examples short and representative.\n\n## Initialize or update files\n\nFor a new Skill, prefer the bundled initializer when Python and shell execution are available:\n\n```text\npython <this-skill-directory>/scripts/init_skill.py <skill-name> --path <target-skills-root> --description <description>\n```\n\nAdd `--resources scripts,references,assets` with only the directories that are needed. The initializer refuses to overwrite an existing Skill.\n\nIf shell execution is unavailable, create the directory and UTF-8 `SKILL.md` with `astrbot_file_write_tool`. Create optional resources only after their content is known.\n\nWhen updating a Skill, read its complete `SKILL.md` and directly referenced resources before editing. Preserve useful behavior and avoid unrelated restructuring.\n\n## Validate\n\nWhen Python and shell execution are available, run:\n\n```text\npython <this-skill-directory>/scripts/validate_skill.py <created-skill-directory>\n```\n\nOtherwise verify manually:\n\n- The directory name is valid and matches frontmatter `name`.\n- `SKILL.md` is UTF-8 and has valid YAML frontmatter.\n- `description` explains both capability and trigger conditions.\n- The body is non-empty and operational.\n- Every referenced file exists and every bundled file has a clear purpose.\n- Instructions do not assume unavailable tools, paths, credentials, or permissions.\n\nRun any bundled scripts on representative safe inputs. Fix validation or execution failures before presenting the Skill.\n\n## Finish\n\nReport the created or updated location, included resources, validation performed, and any runtime or activation step still required. Do not enable a globally installed Skill or change an AstrBot configuration unless the user requested it.\n\n<!-- File: astrbot/builtin_stars/astrbot/skills/spreadsheets/references/charts.md (Tokens: ~339 | Category: anthropic-skill) -->\n# Spreadsheet charts\n\nCreate a chart only when it makes a comparison, trend, distribution, ranking, progress measure, or relationship easier to understand.\n\n## Select a chart\n\n- Use bars or columns for category comparison and ranking.\n- Use lines for trends over time.\n- Use scatter plots for relationships between numeric variables.\n- Use a histogram for a distribution when supported by the target viewer.\n- Use pie or doughnut charts only for a small number of meaningful parts of one whole.\n- Use a compact table when exact values matter more than visual pattern.\n\n## Build auditable chart data\n\n- Link series and categories directly to worksheet cells.\n- Use a formula-backed helper range only when reshaping, grouping dates, or shortening labels is necessary.\n- Keep unknown values blank rather than inventing zeroes.\n- Verify headers are not included as numeric points.\n- Keep category and value ranges the same length.\n- Use a text helper label such as `2026-08` when date-axis rendering is unreliable.\n\n## Format and place\n\n- Give each chart one clear takeaway and include units in the title or axis.\n- Use restrained, consistent colors and avoid gradients, 3D effects, and heavy borders.\n- Keep labels, ticks, legends, and titles readable at normal zoom.\n- Place charts beside or below the data they explain with blank gutters around them.\n- Do not cover cells, controls, notes, or other charts.\n- Set explicit axis number formats for currency, percentages, and dates.\n\nAfter saving, reopen the workbook and inspect chart series formulas. Render the sheet and check for blank charts, clipped labels, stale ranges, wrong orientation, unreadable legends, and excessive whitespace.\n\n<!-- File: astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formatting.md (Tokens: ~668 | Category: anthropic-skill) -->\n# Spreadsheet formatting\n\nUse this reference for new workbooks and substantial redesigns. Preserve an existing workbook's visual language unless the user requests a redesign.\n\n## Establish roles\n\nChoose a small role-based style system before writing cells:\n\n| Role | Default treatment |\n|---|---|\n| Workbook title | 16-18 pt, bold, dark neutral text, generous spacing |\n| Section title | 12-14 pt, bold, restrained accent or neutral fill |\n| Table header | Bold, high-contrast fill, centered only when appropriate |\n| Input | Light neutral or pale blue fill, unlocked when protection is used |\n| Formula | No fill or a subtle neutral fill; keep formulas visible |\n| Key output | Bold, explicit number format, light callout fill |\n| Note/source | Smaller muted text, URL in cell or comment |\n| Warning | Restrained amber or red used only for actionable exceptions |\n\nUse one body font and one optional display font. Prefer fonts commonly available across platforms. For Chinese workbooks, verify the chosen CJK font in the actual render environment (`fc-match \"Font Name\"` when Fontconfig is available), then inspect the rendered pages for substitution or missing glyphs. Keep body text around 10-11 pt and do not depend on color alone to communicate status.\n\n## Lay out the workbook\n\n- Put a clear title or table header near the top-left of each important sheet.\n- Keep assumptions and inputs separate from derived calculations in complex models.\n- Place important totals or KPIs where users can find them without scrolling to the bottom.\n- Freeze the header row for long tables and freeze identifier columns for wide tables.\n- Add filters or an Excel table for editable datasets.\n- Avoid merged cells in calculation or filter ranges. Reserve merges for titles or compact presentation labels.\n- Set print area, orientation, margins, repeated header rows, and fit-to-width for reports intended to print or render.\n- Remove empty default sheets and avoid large formatted-but-empty used ranges.\n\n## Size and align cells\n\n- Left-align descriptive text, right-align numbers, and use intentional alignment for short statuses and dates.\n- Widen columns before enabling deep wrapping. Cap descriptive columns around 50-60 characters unless the user requests otherwise.\n- Increase row height only enough to reveal wrapped content.\n- Use explicit formats such as `#,##0`, `#,##0.00`, `0.0%`, `yyyy-mm-dd`, and currency formats appropriate to the requested currency.\n- Preserve identifiers as text when leading zeroes or exact digits matter.\n\n## Tables and conditional formatting\n\n- Use light internal borders and a clearer outside or header boundary.\n- Use banded rows only when they materially improve scanning.\n- Apply conditional formatting over the intended editable range, not an entire worksheet.\n- Verify that formulas used by conditional formatting are anchored correctly at the top-left cell of the applied range.\n- Prefer data bars, color scales, or icon sets only when their scale and direction are meaningful.\n\n## Accessibility and usability\n\n- Use descriptive sheet names and unique table names.\n- Avoid hidden assumptions and unexplained abbreviations.\n- Add comments for important assumptions, unusual formulas, and data provenance.\n- Use data validation prompts and error messages for constrained inputs.\n- Keep color contrast readable and provide text or numeric cues in addition to color.\n\n<!-- File: astrbot/builtin_stars/astrbot/skills/spreadsheets/references/formulas.md (Tokens: ~452 | Category: anthropic-skill) -->\n# Formula and validation rules\n\nUse this reference for formula-heavy workbooks and any task where calculated outputs matter.\n\n## Author formulas\n\n1. Create every referenced sheet before assigning cross-sheet formulas.\n2. Use formulas for derived values and hardcode only assumptions, raw facts, or explicitly requested fixed outputs.\n3. Use `$` anchors deliberately and test the first, middle, and last filled formulas.\n4. Quote sheet names in cross-sheet references.\n5. Bound lookup and aggregation ranges to the intended data area.\n6. Prefer `IFERROR` only when the fallback has a clear business meaning. Do not hide an unexpected error.\n7. Keep units consistent across inputs and outputs.\n\n## Understand calculation limits\n\n`openpyxl` preserves and writes formulas but does not calculate them. Loading with `data_only=True` returns cached values last saved by a calculating application; a newly authored formula may have no cached value.\n\nWhen a calculated result is required:\n\n1. Save the workbook with formulas intact.\n2. If LibreOffice or Excel is available, open and save a copy to recalculate it.\n3. Reopen the recalculated copy twice: once with `data_only=False` to verify formulas and once with `data_only=True` to inspect cached results.\n4. Reconcile important totals independently in Python for high-risk outputs.\n\nDo not treat a missing cached value as proof that a formula is wrong. Do treat a literal error value, `#REF!` inside a formula, a broken chart range, or a missing sheet reference as an error.\n\n## Validate\n\n- Scan all populated cells for Excel error literals.\n- Scan formulas and chart series for `#REF!`.\n- Confirm table and filter ranges include their headers and intended rows.\n- Confirm data validation and conditional-format ranges include future editable rows when requested.\n- Check duplicate table and defined-name identifiers.\n- Check for formulas that accidentally reference the header row or omit the final data row.\n- Review external links and disclose them; do not silently remove them.\n- Open macro-enabled files with `keep_vba=True` and preserve their extension.\n\nFor financial, legal, medical, or other high-stakes workbooks, independently recalculate representative results and document assumptions and source URLs inside the workbook.\n\n<!-- File: astrbot/builtin_stars/astrbot/skills/spreadsheets/SKILL.md (Tokens: ~1271 | Category: anthropic-skill) -->\n---\nname: spreadsheets\ndescription: Create, read, edit, analyze, convert, chart, and validate spreadsheet files including XLSX, XLSM, XLS, CSV, and TSV. Use when a spreadsheet is a primary input or deliverable, or when tabular data must remain editable and auditable in workbook form.\n---\n\n# Work with spreadsheets\n\nUse `openpyxl` for XLSX/XLSM authoring, `xlrd` for legacy XLS reading, `pandas` for substantial data cleaning or analysis, and the standard `csv` module for simple CSV/TSV work. Preserve the source unless the user explicitly requests an in-place edit.\n\n## Choose the workflow\n\n1. For a read-only question, inspect only the relevant sheets, labels, values, formulas, tables, charts, and comments. Do not export a modified copy.\n2. For an existing workbook, study its structure and formatting before editing. Apply the smallest local change and extend nearby formulas, validation, conditional formatting, tables, and charts when the edited range requires it.\n3. For a new workbook, separate inputs, calculations, and outputs when the task contains derived values. Keep calculations visible and auditable.\n4. Save to a new file, reopen it, validate formulas and structure, and render every populated sheet when a renderer is available.\n\nUse the bundled inspector before unfamiliar edits:\n\n```text\npython <this-skill-directory>/scripts/inspect_workbook.py input.xlsx\n```\n\n## Respect format boundaries\n\n- Use `openpyxl.load_workbook(..., keep_vba=True)` for XLSM files and preserve the `.xlsm` extension. Do not claim that macros were inspected or are safe merely because they were preserved.\n- Treat XLS as a legacy read-only source. `xlrd` reads values and basic metadata but does not provide reliable modern editing. Convert the result to XLSX or CSV instead of overwriting the XLS file.\n- Preserve CSV/TSV delimiter, quoting, encoding, header order, and typed meaning. Keep identifiers such as ZIP codes and account numbers as text.\n- Never change a workbook's file extension without actually converting its format.\n\n## Keep formulas auditable\n\n- Write derived values as formulas rather than hardcoded results.\n- Place assumptions and raw inputs in visible cells or dedicated sheets.\n- Avoid magic numbers inside formulas. Reference an assumption cell instead.\n- Use correct absolute and relative references for fill behavior.\n- Quote every cross-sheet name: `='Revenue Model'!B4`, even when the current name has no spaces.\n- Prefer bounded ranges over full-column references in calculation-heavy formulas.\n- Use helper cells when a formula becomes difficult to understand or audit.\n- Add comments to important assumptions and source-backed inputs.\n- Check for `#REF!`, `#DIV/0!`, `#VALUE!`, `#NAME?`, `#NUM!`, `#NULL!`, and unexpected circular references.\n\n`openpyxl` writes formulas but does not calculate them. If formulas must be recalculated, open and save a copy with LibreOffice or Excel when available, then reopen the result with `data_only=False` and `data_only=True`. Never replace formulas with calculated constants merely to make validation pass. Read [formulas.md](references/formulas.md) for the detailed validation contract.\n\n## Format by meaning\n\nRead [formatting.md](references/formatting.md) before creating or substantially redesigning a workbook.\n\n- Store dates, numbers, currency, and percentages as typed values with explicit number formats.\n- Distinguish title, header, input, calculation, output, note, and warning roles consistently.\n- Prefer restrained fills and light structural borders. Do not decorate every populated cell with a border.\n- Freeze useful headers, enable filters, and use named tables for editable datasets.\n- Prefer conditional formatting over one-time manual fills when color represents a value or status.\n- Use data validation for editable categorical fields when practical.\n- Size columns and rows deliberately. Widen before wrapping, cap very wide columns, and avoid formatting unused ranges.\n- Hide gridlines only when explicit formatting already provides structure.\n\n## Use charts deliberately\n\nRead [charts.md](references/charts.md) before creating or editing charts. Create a chart only when it improves comparison, trend, distribution, ranking, progress, or relationship understanding.\n\n- Link chart series to worksheet ranges, not duplicated literal values.\n- Keep units explicit and titles focused on one takeaway.\n- Place charts in reserved areas without covering source data or controls.\n- Verify categories, series orientation, source ranges, point counts, axes, and placement after saving.\n- Prefer a compact table over a chart when exact values are the main point.\n\n## Convert CSV or TSV\n\nUse the bundled converter for a clean, typed, filterable workbook:\n\n```text\npython <this-skill-directory>/scripts/csv_to_xlsx.py input.csv output.xlsx\npython <this-skill-directory>/scripts/csv_to_xlsx.py input.tsv output.xlsx --delimiter tab\n```\n\nThe converter infers conservative scalar types, freezes the header, creates a table, applies number formats, and caps column widths. Inspect identifiers and locale-specific dates before accepting inferred types.\n\n## Validate and render\n\nRun structural validation after every create or edit operation:\n\n```text\npython <this-skill-directory>/scripts/validate_workbook.py output.xlsx\n```\n\nWhen LibreOffice and a PDF renderer are available, render the workbook:\n\n```text\npython <this-skill-directory>/scripts/render_workbook.py output.xlsx rendered\n```\n\nInspect every rendered page at normal zoom. Check for clipped headers or values, unexpected blank pages, broken charts, unreadable colors, bad page breaks, missing glyphs, formula errors, and content outside the visible area. Rendering does not prove formula correctness; structural and formula validation remain required.\n\nIf rendering is unavailable, report that only structural validation was completed. Do not imply that a workbook passed visual QA.\n\n## Finish\n\nDeliver only the requested workbook or tabular output unless the user asks for previews or intermediates. Report the output path, important sheets or changes, formula/recalculation status, validation performed, and any limitation involving macros, legacy XLS, unsupported formulas, fonts, or rendering.\n</yakaai_skills>"}