feat: 导出 SproutClaw .sproutclaw 配置

包含 extensions、skills、prompts、settings、auth、models、mcp 等配置。
排除 node_modules、npm 缓存、sessions 等运行时数据。
This commit is contained in:
2026-06-26 15:48:56 +08:00
commit 50edff80f5
13904 changed files with 411646 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
# Project Rules
Conventions and style guides for contributors and AI agents working in this repository. These rules are derived from the de facto patterns in existing code and reference documents.
| Rule | Scope |
|---|---|
| [`prompt-style.md`](./prompt-style.md) | Style guide for files under `skills/ppt-master/references/` — voice, sectioning, table-first, forbidden patterns |
| [`code-style.md`](./code-style.md) | Style guide for Python under `skills/ppt-master/scripts/` — file headers, imports, CLI entry points, error handling, no-tests rule |
When adding a new rule file:
- One topic per file
- File name `<topic>.md` (lowercase, hyphenated)
- Add a row to the table above
- The body should be **prescriptive, not descriptive** — tell readers what to do, not what the project happens to look like

View File

@@ -0,0 +1,327 @@
# Python Code Style Guide
> Style rules for Python code under `skills/ppt-master/scripts/` and any Python that ships with the skill. Derived from the de facto patterns in the existing codebase.
These rules are pragmatic, not exhaustive. They capture the conventions readers actually encounter — anything PEP 8 hands you for free is assumed.
---
## 1. File Header
Every script under `scripts/` starts with:
```python
#!/usr/bin/env python3
"""
PPT Master - Short Tool Name
One-paragraph description of what this script does.
Usage:
python3 scripts/<name>.py <required_arg> [options]
Examples:
python3 scripts/<name>.py projects/<project_name> -o output_dir
Dependencies:
None (only uses standard library) <-- or list third-party deps
"""
```
| Element | Rule |
|---|---|
| Shebang | `#!/usr/bin/env python3` (always — even for non-CLI helper modules) |
| Module docstring | Tool name + purpose + Usage + Examples + Dependencies |
| Internal helper modules | May add an early `--help` short-circuit (see §4) |
---
## 2. Imports
```python
# 1. Standard library
import os
import sys
import argparse
import re
from pathlib import Path
from typing import Optional
# 2. Third-party
import requests
# 3. Local — sometimes need sys.path injection first (see §3)
from image_sources.provider_common import (
AssetCandidate,
ImageSearchRequest,
)
```
| Rule | Note |
|---|---|
| Group order | std → third-party → local, blank line between groups |
| Within a group | Sorted by length when short; alphabetical when ≥ 4 imports |
| `from x import` lists | One name per line if ≥ 4 names, with trailing comma |
| `from __future__ import annotations` | Add at top when the file uses `X \| Y` union syntax (PEP 604) and may run on Python < 3.10 |
---
## 3. sys.path Injection (Project Convention)
`scripts/` is **not a Python package** — it's a flat directory of scripts. Each entry-point script that imports a sibling module injects `scripts/` onto `sys.path` itself:
```python
import sys
from pathlib import Path
_SCRIPTS_DIR = Path(__file__).resolve().parent
if str(_SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(_SCRIPTS_DIR))
from image_backends.backend_common import download_image # noqa: E402
```
| Rule | Why |
|---|---|
| Inject only in entry-points | Library modules under `image_sources/` / `image_backends/` import each other normally |
| Use `Path(__file__).resolve().parent` | Robust under symlinks and aliasing |
| Annotate post-injection imports with `# noqa: E402` | Suppress the lint warning honestly, not via per-file noqa |
---
## 4. CLI Entry Points
```python
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="One-line description.",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument("query", help="...")
parser.add_argument("-o", "--output", default=".", help="...")
return parser
def main(argv: Optional[list[str]] = None) -> int:
parser = build_parser()
args = parser.parse_args(argv)
# ... do the thing ...
return 0
if __name__ == "__main__":
raise SystemExit(main())
```
| Rule | Note |
|---|---|
| `main(argv=None) -> int` | Returns exit code; testable by passing `argv` |
| `raise SystemExit(main())` | Preferred over `sys.exit(main())` |
| `formatter_class=argparse.RawDescriptionHelpFormatter` | Preserves docstring formatting in `--help` |
| Internal helpers `--help` | Module-level: `if __name__ == "__main__" and any(arg in {"-h", "--help", "help"} for arg in sys.argv[1:]): print(__doc__); raise SystemExit(0)` |
| Output | Progress / status to **stderr**; the script's primary output (if any) to stdout |
---
## 5. Type Hints
Required for all new public functions; optional for internal `_helpers`.
| Pattern | Use |
|---|---|
| `def f(x: str, *, y: int = 0) -> bool:` | Public functions |
| `tuple[int, int] \| None` | PEP 604 unions (with `from __future__ import annotations` if needed for compat) |
| `Optional[X]` from `typing` | Acceptable alternative to `X \| None` |
| `list[X]`, `dict[K, V]` | Built-in generics (Python 3.9+) |
| `Any` | Sparingly — only when interfacing with truly heterogeneous data (`raw: Any` in dataclasses for upstream JSON) |
**Forbidden — over-specification**:
- `Callable[[int, str], dict[str, list[Optional[Union[int, str]]]]]` — break this into typed dataclasses
- `Literal["a", "b", "c"]` everywhere — use a constant + plain `str` unless the type itself is the API
---
## 6. Naming
| Kind | Convention | Examples |
|---|---|---|
| Module file | `snake_case.py` | `image_search.py`, `svg_to_pptx.py` |
| Script entrypoint | verb or noun phrase | `finalize_svg.py`, `notes_to_audio.py` |
| Public function | `snake_case` | `download_image`, `parse_results` |
| Private helper | `_snake_case` | `_load_dotenv_if_available`, `_measure_actual_image` |
| Constant | `UPPER_SNAKE_CASE` | `API_URL`, `DEFAULT_PAGE_SIZE`, `LICENSE_TIER_NO_ATTRIBUTION` |
| Class | `PascalCase` | `AssetCandidate`, `SVGQualityChecker` |
| Dataclass field | `snake_case` | `license_tier`, `download_url` |
| Module-private regex | `_PATTERN_RE` (private + `_RE` suffix) | `_TAG_RE`, `HEADING_RE` |
---
## 7. Error Handling
| Situation | Pattern |
|---|---|
| Optional dependency | `try: import x; HAS_X = True\nexcept ImportError: HAS_X = False` |
| Optional sibling module | `try: from project_utils import CANVAS_FORMATS\nexcept ImportError: CANVAS_FORMATS = {}; print("Warning: ...")` |
| Recoverable runtime failure | Catch specific exceptions, log to stderr, return / continue — do NOT halt the pipeline |
| User-facing error | `print("...", file=sys.stderr); return 1` from `main()` |
| Programming error | Raise — don't paper over a bug |
**Hard rule**: never bare-`except:`. Always name the exception class.
**Forbidden — silent fallbacks for security-relevant code**:
- Disabling SSL verification without a domain whitelist + WARNING
- Catching all exceptions in a download path without logging the cause
---
## 8. Dependencies
| Tier | Where it can be required |
|---|---|
| Standard library | Anywhere |
| `requests`, `Pillow`, `lxml` | Common dependencies; safe to require in main scripts |
| Provider SDKs (`google-genai`, `openai`, `anthropic`, etc.) | **Lazy import inside the function that uses it**; soft-fail with `ImportError``RuntimeError` containing install instructions |
| `python-dotenv` | Optional — wrap the import in try/except, no-op if unavailable |
```python
def _require_api_key() -> str:
key = os.environ.get("PEXELS_API_KEY") or ""
if not key:
raise RuntimeError(
"PEXELS_API_KEY is not set. Add it to your environment or .env file. "
"Get one at https://www.pexels.com/api/"
)
return key
```
Error messages **must include the fix** — "what env var to set", "where to get a key", "which package to install".
---
## 9. Shared Helpers Layer
Common functionality lives in two designated submodules. New scripts use these, not their own copies:
| Module | Owns |
|---|---|
| [`image_backends/backend_common.py`](../skills/ppt-master/scripts/image_backends/backend_common.py) | HTTP download, retry, image format detection, save-with-Pillow-transcode |
| [`image_sources/provider_common.py`](../skills/ppt-master/scripts/image_sources/provider_common.py) | License classification, query simplification, scoring, attribution text, dataclasses |
| [`project_utils.py`](../skills/ppt-master/scripts/project_utils.py) | Canvas formats, project path conventions |
| [`error_helper.py`](../skills/ppt-master/scripts/error_helper.py) | User-facing error message templates |
**Forbidden — duplicating logic that exists in a shared helper**. If a helper is missing a feature, extend the helper, don't fork it inside your new script.
---
## 10. Docstrings
Short and imperative. No Args/Returns/Raises sections unless the signature is genuinely complex.
```python
def classify_license(
license_name: str,
license_url: str = "",
provider: str = "",
) -> Optional[str]:
"""Classify a license string into one of the two tiers, or reject it.
Returns:
``"no-attribution"`` / ``"attribution-required"`` / ``None``.
The provider hint lets us treat Pexels and Pixabay's own licenses as
``no-attribution`` even when the upstream API only returns a short
label like ``"Pexels"``.
"""
```
| Use a Google/Sphinx-style block | Skip the block |
|---|---|
| Function returns multiple branches with semantic differences | One-liner that explains itself in the function name |
| Has more than 3 parameters with non-obvious roles | Single-purpose helper |
| Maintains a non-trivial invariant | Pure formatter / accessor |
---
## 11. Testing
**Hard rule**: this repository does **not** ship automated tests.
**Forbidden**:
- `tests/` directories
- `test_*.py` files
- `unittest` / `pytest` imports
- `if __name__ == "__main__":` blocks that run a self-test suite
**Use instead**:
- Inline smoke commands via `python3 -c "..."` against real project samples; show the output in the conversation / PR description
- Manual verification steps in the runbook
- Live-API smoke runs against `projects/_smoke_*` directories (gitignored)
This is a deliberate project convention. When external contributors include tests, ask them to remove tests in PR review (see [`docs/rules/prompt-style.md`](./prompt-style.md) §11 for the parallel rule on reference docs).
---
## 12. Dataclasses
Prefer plain `@dataclass` over `pydantic` / `attrs` for value types. Keep them simple:
```python
@dataclass
class AssetCandidate:
provider: str
title: str
asset_id: str = ""
license_tier: str = ""
width: int = 0
height: int = 0
raw: Any = None
```
| Rule | Note |
|---|---|
| `@dataclass` | Default; no need for `frozen=True` unless mutation is a real risk |
| Fields | All required fields first, then optional with defaults |
| `field(default_factory=...)` | Only when the default needs to be a new container per instance |
| No legacy positional-arg shims | New dataclass = keyword-arg API. YAGNI on positional support |
| Methods | Keep dataclasses dumb; computation goes in module-level functions |
---
## 13. File Encoding & Line Endings
| Property | Value |
|---|---|
| Encoding | UTF-8 |
| Line endings | LF |
| Final newline | Always present |
| BOM | Forbidden |
| Indentation | 4 spaces (no tabs) |
| Max line length | Soft 100; hard 120. Prose in docstrings can flow longer |
---
## 14. Cross-references
When a Python file mirrors a reference doc, cross-link both ways:
- The script's docstring mentions the reference: `See references/image-searcher.md for the on-slide attribution rules.`
- The reference doc cites the script with a backticked relative link
This keeps `prompt-style.md` and `code-style.md` (this file) operating as a pair — neither layer drifts away from the other.
---
## 15. When This Guide Conflicts With Existing Files
Existing files take precedence. If a current script contradicts a rule here, decide whether to (a) update this guide, or (b) refactor the script. The canonical exemplars to model new scripts after:
| If you're writing... | Model after |
|---|---|
| A small CLI utility | [`total_md_split.py`](../skills/ppt-master/scripts/total_md_split.py), [`gemini_watermark_remover.py`](../skills/ppt-master/scripts/gemini_watermark_remover.py) |
| A multi-backend / dispatcher CLI | [`image_search.py`](../skills/ppt-master/scripts/image_search.py), [`image_gen.py`](../skills/ppt-master/scripts/image_gen.py) |
| A library / shared helper | [`image_sources/provider_common.py`](../skills/ppt-master/scripts/image_sources/provider_common.py), [`image_backends/backend_common.py`](../skills/ppt-master/scripts/image_backends/backend_common.py) |
| A class-based checker / validator | [`svg_quality_checker.py`](../skills/ppt-master/scripts/svg_quality_checker.py) |

View File

@@ -0,0 +1,193 @@
# Reference Document Style Guide
> Style rules for files under `skills/ppt-master/references/`. Follow these when writing or reviewing role definitions and shared specs.
The reference layer drives runtime LLM behavior. Style consistency across these files matters as much as correctness — divergent voice / structure forces the model to re-interpret each file from scratch and bloats the loaded context.
---
## 1. Document Header
| Element | Rule |
|---|---|
| Top line | `> See [`xxx`](xxx.md) for ...` — one-line cross-reference, optional |
| H1 title | `# Role: X` (for role files) or `# X Reference Manual` / `# X Specification` |
| Opening paragraph | One sentence stating mission + trigger. Max 2 lines |
| `## Core Mission` | Optional; if present, ≤ 3 sentences |
✅ Good (from `image-searcher.md`):
```
> See [`image-base.md`](./image-base.md) for the common framework.
# Image_Searcher Reference Manual
Role definition for the **web image acquisition path**: translate Strategist intent into keyword queries, search openly-licensed providers, download a license-cleared image into `project/images/`, and record provenance + license metadata into `image_sources.json`.
**Trigger**: resource list rows with `Acquire Via: web`. The role is loaded only when at least one such row exists.
```
❌ Avoid: long "Core Mission" paragraphs that explain *why* the role exists, list its philosophical goals, or narrate the pipeline context.
---
## 2. Sectioning
| Level | Format | Notes |
|---|---|---|
| Main | `## N. Title` | Numbered from 1 |
| Sub | `### N.1` / `### N.2` ... | Or `### a.` / `### b.` for confirmation flows |
| Divider | `---` between main sections | Always |
`## Core Mission`, `## Pipeline Context`, `## Trigger` may appear before `## 1.` without numbering.
---
## 3. Voice — Command, Not Explanation
| Use | Don't use |
|---|---|
| `Run X.` | `You should typically run X because ...` |
| `Output: Y` | `The role outputs Y, which is important because ...` |
| `MUST come from Z` | `It is recommended to source from Z` |
| `Forbidden — values outside the lock` | `Anti-pattern: using values outside the lock` |
**Hard rule**: if a sentence explains *why*, demote it to a single `> Note` blockquote line OR cut it. The agent does not need motivation, only behavior.
---
## 4. Bold Inline Labels
Begin substantive paragraphs with a bolded short label. Reuse this fixed vocabulary:
| Label | Use for |
|---|---|
| `**Hard rule**:` | Non-negotiable behavior |
| `**Forbidden — xxx**:` | Disallowed values / actions, followed by a list |
| `**Mandatory**:` | Required step within an optional phase |
| `**When to run**:` / `**Trigger**:` | Activation condition |
| `**Validation**:` | Post-step assertion |
| `**Per-page xxx**:` / `**Per-row xxx**:` | Loop body description |
| `**Generation pacing (mandatory)**:` | Concurrency / rate constraint |
| `**Missing X**` → ... | Fallback behavior |
✅ Good (from `executor-base.md`):
```
**Hard rule**: Before generating **each** SVG page, `read_file <project_path>/spec_lock.md`.
**Forbidden — values outside the lock**:
- Colors (fill / stroke / stop-color) MUST come from `colors`
- Icons MUST come from `icons.inventory`
```
---
## 5. Tables First
Most sections need at least one table. Reach for a table whenever you would write 3+ parallel bullet points.
| Use case | Format |
|---|---|
| Enums, modes, options | Table with `Key | Behavior` |
| Field definitions | Table with `Field | Notes` |
| Decision matrices | Table with `Condition | Action` |
| Cross-reference index | Table with `Term | Defined in` |
Bullets are fine for ≤ 3 short imperatives or a single ordered procedure.
---
## 6. Examples
| Form | Use |
|---|---|
| Fenced code block (` ``` `) | Commands, file content, ASCII diagrams |
| Inline code (` ` `) | File paths, identifiers, env vars |
| 2-column ✅/❌ table | Short keyword-vs-keyword contrast (one phrase per cell) |
❌ Avoid: 3-column ✅/❌/(why) tables. The "why" column is explanation — drop it or move to a `>` note.
❌ Avoid: long narrative example paragraphs. Use a code block or table.
---
## 7. Forbidden Section Types
These section names are not used anywhere in `references/`. Do not introduce them:
- `## Anti-patterns`
- `## Best Practices`
- `## Tips`
- `## FAQ` (FAQ lives in `docs/faq.md`)
- `## Why X`
- `## Background` / `## Motivation`
If you have rules to communicate that would naturally land in one of these sections, integrate them into the relevant numbered section as a `**Forbidden — xxx**` block or a `> Note` line.
---
## 8. Cross-References
| Reference type | Format |
|---|---|
| Sibling reference file | `[`xxx`](./xxx.md)` |
| Section in same file | `§N.M` (no link) |
| Section in another file | `[`xxx`](./xxx.md) §N.M` |
| Script doc | `[`xxx`](../scripts/docs/xxx.md)` |
| Workflow | `[`xxx`](../workflows/xxx.md)` |
Always backtick-wrap the filename in the link text.
---
## 9. Annotations
| Symbol | Meaning |
|---|---|
| `🚧 **GATE**:` | Mandatory checkpoint before proceeding |
| `**BLOCKING**:` | Must wait for explicit user confirmation |
| `📝 **Template mapping**:` | Page-to-template declaration (Executor-specific) |
| `> Note` blockquote | Edge case, fallback, or single-line context |
Use sparingly. If every paragraph has a symbol, none of them carry weight.
---
## 10. Checkpoint Output Format
Each phase ends with a fenced markdown block showing the agent's expected completion confirmation:
````markdown
## ✅ {Phase Name} Complete
- [x] {evidence-driven assertion 1}
- [x] {evidence-driven assertion 2}
- [ ] **Next**: {next-phase pointer}
````
Items are evidence-driven (`file exists at path X`, `status N is Generated`), not aspirational (`prompts are good`).
---
## 11. Forbidden Patterns Across the Whole Layer
- `> 重要:` / `> 注意:` Chinese exclamations (use `> Note` or omit)
- Emoji as decoration in headings (✅ in checkpoint headings is the only sanctioned use)
- Smiley face / sparkle / fire emoji
- Footnotes (`[^1]`)
- HTML in markdown body (`<details>`, `<br>`, etc.) — only the SVG embedding examples use real `<svg>`/`<image>` in code blocks, never as live markdown
- "**Best practice**: ..." labels — use `**Hard rule**:` if it's required, or omit if it's not
---
## 12. When This Guide Conflicts With Existing Files
Existing files take precedence as ground truth. If a current `references/*.md` violates a rule here, decide whether to (a) update this guide to match the de facto convention, or (b) refactor that file. Don't silently apply a divergent style to one new file.
The canonical exemplars to model new files after:
| If you're writing... | Model after |
|---|---|
| A role reference (Image_X / Strategist-style) | [`image-searcher.md`](../skills/ppt-master/references/image-searcher.md), [`strategist.md`](../skills/ppt-master/references/strategist.md) |
| A shared spec across roles | [`image-base.md`](../skills/ppt-master/references/image-base.md), [`shared-standards.md`](../skills/ppt-master/references/shared-standards.md) |
| A technical / format spec | [`canvas-formats.md`](../skills/ppt-master/references/canvas-formats.md), [`svg-image-embedding.md`](../skills/ppt-master/references/svg-image-embedding.md), [`image-layout-spec.md`](../skills/ppt-master/references/image-layout-spec.md) |
| Workflow runbook | [`workflows/verify-charts.md`](../skills/ppt-master/workflows/verify-charts.md) |