--- name: miaoshou-erp description: "Miaoshou (妙手) ERP operations: cron auto-import from AtomK, product import via Excel upload, and collect box management." version: 1.2.0 author: Hermes Agent license: MIT metadata: hermes: tags: [miaoshou, erp, cross-border, e-commerce, product-import, collect-box] related_skills: [atomk-platform, tongtool-workflows, credential-management] --- # Miaoshou (妙手) ERP Three workflows for Miaoshou ERP: cron auto-import from AtomK, batch product import via Excel upload, and exploring/managing the collect box (通用采集箱). ## Section 1: Batch Product Import Automate batch product import from AtomK to Miaoshou ERP via Excel upload. **When to use:** Importing large numbers of products from AtomK into Miaoshou for management. **Key patterns:** - Generate Excel file from AtomK product data - Upload to Miaoshou via UI (or API) - Handle validation errors and duplicate detection - Map product fields between AtomK and Miaoshou formats **See:** `references/miaoshou-batch-import.md` for full import workflow. ## Section 2: Collect Box Management Explore and interact with Miaoshou ERP's "通用采集箱" (Common Collect Box) — URLs, collection methods, import paths, and login automation. **When to use:** Adding products to the collect box, checking collected items, importing from collect box to formal listings. **Key topics:** - Collect box URL patterns and API endpoints - Collection methods (URL import, manual add, API) - Import from collect box to product listings - Login automation for Miaoshou **See:** `references/miaoshou-collect-box.md` for full collect box guide. ## Section 3: Cron Auto-Import (AtomK → Miaoshou) The production auto-import pipeline runs hourly via a **`no_agent` Hermes cron job** that invokes a wrapper shell script. The wrapper appends timestamp headers to the cron log, runs the Python import script, and appends an exit-code footer. No LLM session is spawned — the script executes directly, completing in ~3 seconds rather than 3-5 minutes. **Cron job:** `atomk-miaoshou-hourly` (schedule: `0 * * * *`, `no_agent=true`) **Wrapper script:** `/home/ubuntu/.hermes/scripts/miaoshou_hourly.sh` **Main script:** `/home/ubuntu/auto_miaoshou_import.py` **Python:** `/home/ubuntu/.hermes/hermes-agent/venv/bin/python3` **Working dir:** `/home/ubuntu` ### Why `no_agent` (Not LLM-Driven) The cron job was previously LLM-driven (Agent mode). Each run spawned a full LLM session that loaded skills, ran terminal commands, read files, and produced a report — consuming **3-5 minutes of cron queue time** per hour. Since Hermes cron runs jobs sequentially in FIFO order, this caused massive queue congestion: ad-hoc cron jobs got delayed by **17+ hours** (scheduled 19:16, queued to 13:08 next day). The `no_agent` wrapper script eliminates the LLM overhead entirely. See `references/cron-queue-pitfalls.md` for the full diagnosis and fix. ### Key Files | File | Purpose | |------|---------| | `/home/ubuntu/.hermes/scripts/miaoshou_hourly.sh` | Cron wrapper: timestamp header → run script → exit-code footer | | `/home/ubuntu/auto_miaoshou_import.py` | Main import script (441 lines) | | `/home/ubuntu/.hermes/miaoshou_import_state.json` | Tracks which AtomK products have been imported (cumulative count + IDs) | | `/home/ubuntu/.hermes/cookies/miaoshou_cookies.json` | Miaoshou session cookies for browser automation | | `/home/ubuntu/.hermes/miaoshou_import.log` | Script's own internal log (Python `log()` writes here) | | `/home/ubuntu/.hermes/miaoshou_cron.log` | Cron wrapper log (stdout/stderr + timestamp headers) | | `/home/ubuntu/.hermes/credentials.env` | Centralized credentials (chmod 600) — read by `atomk_credentials.py` | | `/home/ubuntu/.hermes/scripts/atomk_credentials.py` | Python credential loader — provides `get_atomk_auth()`, `get_miaoshou_auth()`, etc. | ### Two-Log Architecture The script logs to TWO separate files — this is important when diagnosing runs: - **`miaoshou_import.log`** — the script's Python `log()` function writes here. Contains the actual import narrative (products found, imported, skipped). This is the authoritative record. - **`miaoshou_cron.log`** — the cron wrapper appends stdout/stderr plus `=== TIMESTAMP ===` headers and `=== END (exit code: N) ===` footers. If the script produces no stdout (all output goes to `log()`), the cron log only contains the header/footer markers. ### Normal Behavior - BATCH_SIZE = 6 per run (hourly) - On each run: authenticates to AtomK API → fetches pending products → filters already-imported → opens Miaoshou via DrissionPage → imports each product to collect box - **If AtomK has 0 new products:** script prints "没有新产品需要导入,本次跳过" and exits 0 (this is normal, not an error) - Cumulative import count is displayed at end: `📊 累计已导入: N 个产品` ### Running Manually **Direct run** (for debugging — stdout visible): ```bash cd /home/ubuntu && /home/ubuntu/.hermes/hermes-agent/venv/bin/python3 /home/ubuntu/auto_miaoshou_import.py ``` **Wrapper script** (same as cron): ```bash /home/ubuntu/.hermes/scripts/miaoshou_hourly.sh ``` **Production cron pattern** (for Linux crontab — NOT for Hermes `terminal()`): ```bash cd /home/ubuntu && { echo ""; echo "=== $(date '+%Y-%m-%d %H:%M:%S') ==="; /home/ubuntu/.hermes/hermes-agent/venv/bin/python3 /home/ubuntu/auto_miaoshou_import.py 2>&1; RC=$?; echo "=== END (exit code: $RC) ==="; } >> /home/ubuntu/.hermes/miaoshou_cron.log ``` ### Cron Job Management ```bash # View current state cronjob(action='list') # The job is stored in /home/ubuntu/.hermes/cron/jobs.json # Job ID: eee9ab11fbfc, name: atomk-miaoshou-hourly # no_agent=true, script=miaoshou_hourly.sh # To revert to LLM-driven (not recommended — causes queue congestion): # cronjob(action='update', job_id='eee9ab11fbfc', no_agent=false, script='') ``` ### Pitfalls 1. **Empty stdout** — the script logs internally via `log()` to `miaoshou_import.log`, not to stdout. When debugging, check BOTH log files. 2. **Cookie expiry** — Miaoshou cookies in `miaoshou_cookies.json` can expire; the script uses DrissionPage which may need fresh login if cookies are stale. 3. **Chromium path** — hardcoded to `/home/ubuntu/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome`; must match installed Playwright Chromium version. 4. **AtomK auth** — credentials are loaded from `~/.hermes/credentials.env` via `atomk_credentials.get_atomk_auth()`. If the script fails with `KeyError`, the credential file has `FILL_ME` placeholders that need real values. See `credential-management` skill for the full pattern. 5. **Cron log race condition** — the hourly cron and manual runs both append to `miaoshou_cron.log`. Splitting the timestamp header and script execution across separate `terminal()` calls creates a gap where the hourly cron can interleave its write, causing the manual run's output to be **silently dropped with no error**. If log output appears missing, verify with `stat -c '%y'` that the file's mtime matches when the run should have completed. 6. **`{ }` compound command unreliable via `terminal()`** — the `{ }` grouping with `>>` redirect can **fail silently** when passed to Hermes `terminal()`. Observed: exit code 0 returned but no output appended to the log file, no script execution, and file mtime unchanged. For Hermes-triggered runs, use a **two-step approach** instead: **Step 1:** Run the script directly and capture output: ```bash cd /home/ubuntu && /home/ubuntu/.hermes/hermes-agent/venv/bin/python3 /home/ubuntu/auto_miaoshou_import.py 2>&1; echo "EXIT_CODE=$?" ``` The `terminal()` response contains the script's full stdout (including timestamped log lines), plus `EXIT_CODE=N`. **Step 2:** Append header, captured output, and footer to cron log: ```bash printf '\n=== %s ===\n' "$(date '+%Y-%m-%d %H:%M:%S')" >> /home/ubuntu/.hermes/miaoshou_cron.log ``` This two-step approach avoids the `{ }` + `>>` issue. 7. **LLM-driven cron causes queue congestion** — Hermes cron runs jobs sequentially in FIFO order. An LLM-driven job that takes 3-5 minutes blocks all subsequent jobs. When ad-hoc cron jobs are created during active sessions, they queue behind every pending hourly/scheduled job. **Always use `no_agent` with a wrapper script for frequent recurring tasks.** See `references/cron-queue-pitfalls.md` for the full diagnosis. ## Section 4: Bridge CDP Navigation & Interaction When using Bridge CDP to control the user's desktop browser: ### Login URL - **Correct**: `https://erp.91miaoshou.com/` — main page, auto-redirects to `/welcome` if logged in - **Wrong**: `/auth/login` — returns 404「页面未找到」. Do not use. - If not logged in, the main page will show the login form. ### Navigation structure - Top nav: `ul.nav-list.earth` with `