{"id":"878a19bb-5a8a-442f-b4aa-8427cf06ee70","entityType":"agent","slug":"clawhub-zhangzhang1997-zhanfu-playwright","name":"zhanfu-playwright","canonicalUrl":"https://www.xpersona.co/agent/clawhub-zhangzhang1997-zhanfu-playwright","canonicalPath":"/agent/clawhub-zhangzhang1997-zhanfu-playwright","generatedAt":"2026-10-11T07:42:41.251Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-11T03:58:35.897Z","emptyReason":null},"description":"站斧 WebDriver 版 Playwright 自动化（Windows≥5.2.12、macOS 版本高于 5.2.10、强制有界面、通讯失败即停）。 获取 WebDriver 端口前仅 HTTP 调用 WebDriverModule；获取端口后 CDP 执行业务。 「战斧」同义「站斧」（如打开战斧=打开站斧）。 适用于站斧、战斧、ZhanFu、WebDriver、Playwright、店铺自动化、小龙虾 OpenClaw RPA。 Skill: zhanfu-playwright Owner: zhangzhang1997 Summary: 站斧 WebDriver 版 Playwright 自动化（Windows≥5.2.12、macOS 版本高于 5.2.10、强制有界面、通讯失败即停）。 获取 WebDriver 端口前仅 HTTP 调用 WebDriverModule；获取端口后 CDP 执行业务。 「战斧」同义「站斧」（如打开战斧=打开站斧）。 适用于站斧、战斧、ZhanFu、WebDriver、Playwright、店铺自动化、小龙虾 OpenClaw RPA。 Tags: latest:1.0.6 Version history: v1.0.6 | 2026-09-03T02:22:31.903Z | auto - Added standalone scripts: separate scripts now handle opening/cl","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.2K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s176sck1nyj1s5qj639t2jhsc98ae35d:zhanfu-playwright","sourceUrl":"https://clawhub.ai/zhangzhang1997/zhanfu-playwright","homepage":"https://clawhub.ai/zhangzhang1997/skills/zhanfu-playwright","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/zhangzhang1997/zhanfu-playwright","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/zhangzhang1997/skills/zhanfu-playwright","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":61,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"站斧 WebDriver 版 Playwright 自动化（Windows≥5.2.12、macOS 版本高于 5.2.10、强制有界面、通讯失败即停）。 获取 WebDriver 端口前仅 HTTP 调用 WebDriverModule；获取端口后 CDP 执行业务。 「战斧」同义「站斧」（如打开战斧=打开站斧）。 "},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T03:58:35.897Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T03:58:35.897Z","emptyReason":null},"stars":null,"forks":null,"downloads":1167,"packageName":null,"latestVersion":"1.0.6","tractionLabel":"1.2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T03:58:35.821Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T03:58:35.897Z","lastCrawledAt":"2026-10-11T03:58:35.821Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T03:58:35.821Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.6","createdAt":"2026-09-03T02:22:31.903Z","changelog":"- Added standalone scripts: separate scripts now handle opening/closing站斧、打开/关闭店铺、登录、列出店铺等基础操作。 - 「战斧」已视为「站斧」同义，更新使用说明及识别，实现客户“战斧”说法与“站斧”功能完全等价。 - 技能硬规矩更新：明确限定获取端口前仅可运行内置 scripts/目录下脚本，禁止编写自定义一次性脚本，脚本列表显式列出。 - 删除自动化临时/数据 Cache 文件与 skill-card，清理老旧内容。 - 使用手册及说明文档细化，同步参考新脚本结构和同义词说明。","fileCount":16,"zipByteSize":65623},{"version":"1.0.5","createdAt":"2026-08-27T02:34:52.302Z","changelog":"zhanfu-playwright 1.0.5 - 移除了冗余文档文件 skill-card.md，精简 Skill 结构。 - 功能、规则与使用指南均未变动。","fileCount":11,"zipByteSize":49430},{"version":"1.0.4","createdAt":"2026-08-12T03:28:51.408Z","changelog":"- 新增 macOS 下「内核 ≤ 130 不支持自动化」检测与用户提示，要求切换高版本内核并手动重启站斧 - 新增「修改店铺账号密码」功能与对应操作指引 - 客户使用指南、常见问题等文档内容同步完善 - 移除多余 skill-card.md 文件","fileCount":11,"zipByteSize":49460},{"version":"1.0.3","createdAt":"2026-07-22T03:22:33.723Z","changelog":"- 增加 macOS 适配，技能文档与硬规矩全面注明 Windows/macOS 各自版本要求（Windows ≥ 5.2.12，macOS > 5.2.10）。 - 客户指南及硬规矩中补充说明 macOS 暂不支持“设置下载目录”“清除缓存（单店/全部）”“设置店铺插件”，遇相关需求应及时告知客户并停止。 - 禁止在 macOS 上通过 Skill 调用 `SetDownLoadPath`、`ClearCacheFolder`、`ClearCache`、`SetInstallPlugins`，并更新表述与规范。 - 明确清除缓存、设置插件等行为的操作限制与平台条件。 - 移除 skill-card.md，新增字节码缓存文件，无业务功能改动。","fileCount":11,"zipByteSize":44352},{"version":"1.0.2","createdAt":"2026-07-22T03:20:56.481Z","changelog":"- 增加对 macOS 的适配说明，Windows 需 ≥5.2.12，macOS 需 >5.2.10，并明确部分高级功能（设置下载目录、缓存、插件）仅支持 Windows - 客户使用指南与硬规矩补充/强化了 macOS 不支持项与交互约定 - 细化客户端操作提示，防止在 macOS 下错误调用不支持接口 - 移除 skill-card.md，新增脚本字节码缓存文件（无影响核心功能） - 文档内容分段优化，提升可读性与平台区分提示","fileCount":14,"zipByteSize":81019},{"version":"1.0.1","createdAt":"2026-07-14T06:13:20.971Z","changelog":"zhanfu-playwright 1.0.1 - 删除了 skill-card.md 文件，不再包含此技能卡。 - 说明文档与功能未做其它更改。","fileCount":11,"zipByteSize":39865},{"version":"1.0.0","createdAt":"2026-07-14T03:36:13.737Z","changelog":"zhanfu-playwright 1.0.0 - Initial release providing Playwright automation support via ZhanFu WebDriver (≥5.2.11), with strict procedural and error-handling rules. - Controls the ZhanFu client and shop opening/closing through HTTP API before retrieving WebDriverPort; switches to Playwright's connect_over_cdp for in-browser automation after port acquisition. - Targeted for use with ZhanFu, WebDriver, Playwright, store automation, and OpenClaw RPA environments. - Comprehensive user guide included for installation, preparation, common tasks, advanced features, FAQs, and strict do/don't operational policies. - Strong compliance and error protocols: immediate stop and user notification on API communication failures, strictly limited tool and action use per documented interface list.","fileCount":11,"zipByteSize":38981}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s176sck1nyj1s5qj639t2jhsc98ae35d:zhanfu-playwright","setupComplexity":"medium","setupSteps":["Python environment detected. Create a strict virtual environment (`python -m venv .venv`) before installing dependencies to prevent system-level package conflicts.","Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zhangzhang1997-zhanfu-playwright/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zhangzhang1997-zhanfu-playwright/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zhangzhang1997-zhanfu-playwright/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zhangzhang1997-zhanfu-playwright/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zhangzhang1997-zhanfu-playwright/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zhangzhang1997-zhanfu-playwright/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T07:42:41.247Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zhangzhang1997-zhanfu-playwright/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zhangzhang1997-zhanfu-playwright/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zhangzhang1997-zhanfu-playwright/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zhangzhang1997-zhanfu-playwright/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-11T03:58:35.897Z","emptyReason":null},"readme":"Skill: zhanfu-playwright\n\nOwner: zhangzhang1997\n\nSummary: 站斧 WebDriver 版 Playwright 自动化（Windows≥5.2.12、macOS 版本高于 5.2.10、强制有界面、通讯失败即停）。 获取 WebDriver 端口前仅 HTTP 调用 WebDriverModule；获取端口后 CDP 执行业务。 「战斧」同义「站斧」（如打开战斧=打开站斧）。 适用于站斧、战斧、ZhanFu、WebDriver、Playwright、店铺自动化、小龙虾 OpenClaw RPA。\n\nTags: latest:1.0.6\n\nVersion history:\n\nv1.0.6 | 2026-09-03T02:22:31.903Z | auto\n\n- Added standalone scripts: separate scripts now handle opening/closing站斧、打开/关闭店铺、登录、列出店铺等基础操作。\n- 「战斧」已视为「站斧」同义，更新使用说明及识别，实现客户“战斧”说法与“站斧”功能完全等价。\n- 技能硬规矩更新：明确限定获取端口前仅可运行内置 scripts/目录下脚本，禁止编写自定义一次性脚本，脚本列表显式列出。\n- 删除自动化临时/数据 Cache 文件与 skill-card，清理老旧内容。\n- 使用手册及说明文档细化，同步参考新脚本结构和同义词说明。\n\nv1.0.5 | 2026-08-27T02:34:52.302Z | user\n\nzhanfu-playwright 1.0.5\n\n- 移除了冗余文档文件 skill-card.md，精简 Skill 结构。\n- 功能、规则与使用指南均未变动。\n\nv1.0.4 | 2026-08-12T03:28:51.408Z | user\n\n- 新增 macOS 下「内核 ≤ 130 不支持自动化」检测与用户提示，要求切换高版本内核并手动重启站斧\n- 新增「修改店铺账号密码」功能与对应操作指引\n- 客户使用指南、常见问题等文档内容同步完善\n- 移除多余 skill-card.md 文件\n\nv1.0.3 | 2026-07-22T03:22:33.723Z | user\n\n- 增加 macOS 适配，技能文档与硬规矩全面注明 Windows/macOS 各自版本要求（Windows ≥ 5.2.12，macOS > 5.2.10）。\n- 客户指南及硬规矩中补充说明 macOS 暂不支持“设置下载目录”“清除缓存（单店/全部）”“设置店铺插件”，遇相关需求应及时告知客户并停止。\n- 禁止在 macOS 上通过 Skill 调用 `SetDownLoadPath`、`ClearCacheFolder`、`ClearCache`、`SetInstallPlugins`，并更新表述与规范。\n- 明确清除缓存、设置插件等行为的操作限制与平台条件。\n- 移除 skill-card.md，新增字节码缓存文件，无业务功能改动。\n\nv1.0.2 | 2026-07-22T03:20:56.481Z | user\n\n- 增加对 macOS 的适配说明，Windows 需 ≥5.2.12，macOS 需 >5.2.10，并明确部分高级功能（设置下载目录、缓存、插件）仅支持 Windows\n- 客户使用指南与硬规矩补充/强化了 macOS 不支持项与交互约定\n- 细化客户端操作提示，防止在 macOS 下错误调用不支持接口\n- 移除 skill-card.md，新增脚本字节码缓存文件（无影响核心功能）\n- 文档内容分段优化，提升可读性与平台区分提示\n\nv1.0.1 | 2026-07-14T06:13:20.971Z | user\n\nzhanfu-playwright 1.0.1\n\n- 删除了 skill-card.md 文件，不再包含此技能卡。\n- 说明文档与功能未做其它更改。\n\nv1.0.0 | 2026-07-14T03:36:13.737Z | auto\n\nzhanfu-playwright 1.0.0\n\n- Initial release providing Playwright automation support via ZhanFu WebDriver (≥5.2.11), with strict procedural and error-handling rules.\n- Controls the ZhanFu client and shop opening/closing through HTTP API before retrieving WebDriverPort; switches to Playwright's connect_over_cdp for in-browser automation after port acquisition.\n- Targeted for use with ZhanFu, WebDriver, Playwright, store automation, and OpenClaw RPA environments.\n- Comprehensive user guide included for installation, preparation, common tasks, advanced features, FAQs, and strict do/don't operational policies.\n- Strong compliance and error protocols: immediate stop and user notification on API communication failures, strictly limited tool and action use per documented interface list.\n\nArchive index:\n\nArchive v1.0.6: 16 files, 65623 bytes\n\nFiles: reference.md (26653b), scripts/check_device_security.py (5932b), scripts/close_mall.py (1829b), scripts/close_zhanfu.py (770b), scripts/headed_mode.py (847b), scripts/list_malls.py (2192b), scripts/login_zhanfu.py (1875b), scripts/open_mall.py (4625b), scripts/open_zhanfu.py (18958b), scripts/requirements.txt (38b), scripts/zhanfu_http.py (6706b), scripts/zhanfu_ops.py (10046b), scripts/zhanfu_playwright.py (47333b), skill-card.md (2362b), SKILL.md (76057b), _meta.json (136b)\n\nFile v1.0.6:SKILL.md\n\n---\r\nname: zhanfu-playwright\r\ndescription: >-\r\n  站斧 WebDriver 版 Playwright 自动化（Windows≥5.2.12、macOS 版本高于 5.2.10、强制有界面、通讯失败即停）。\r\n  获取 WebDriver 端口前仅 HTTP 调用 WebDriverModule；获取端口后 CDP 执行业务。\r\n  「战斧」同义「站斧」（如打开战斧=打开站斧）。\r\n  适用于站斧、战斧、ZhanFu、WebDriver、Playwright、店铺自动化、小龙虾 OpenClaw RPA。\r\n---\r\n\r\n# 站斧 Playwright 自动化\r\n\r\n通过站斧 WebDriver 版 **HTTP API** 控制客户端与店铺；**拿到 WebDriverPort 之后**才用 Playwright `connect_over_cdp` 做页面自动化。\r\n\r\n**Agent 提示**：技能**首次安装**、客户问「怎么用 / 如何使用」时，**先向客户发送下方「客户使用指南」**（可摘要，不必全文照搬）。\r\n\r\n**前置（Agent）**：站斧版本要求 **Windows ≥ 5.2.12**，**macOS > 5.2.10**；环境已安装 `playwright`、`requests`。\r\n\r\n> **macOS 限制**：`SetDownLoadPath`、`ClearCacheFolder`、`ClearCache`、`SetInstallPlugins` **目前不支持**。客户在 Mac 上提出这些需求时，应直接说明暂不支持并停止，勿调用对应 HTTP 接口。\r\n>\r\n> **macOS 内核限制**：macOS **不支持 130 及以下内核**的店铺自动化。打开店铺后 `GetBrowserWebDriver` 返回的 `KernalNumber` **≤ 130** 时，**立即停止**阶段 B，按「macOS 低内核对客户话术」提示客户切换到 **130 以上**内核（或由主账号切换），并请客户**手动重启站斧**后再继续。\r\n\r\n---\r\n\r\n## 客户使用指南（安装技能时向客户说明）\r\n\r\n以下内容可直接复制或摘要发给客户。\r\n\r\n### 一、使用前准备\r\n\r\n1. **站斧版本**：请确认站斧版本要求（**Windows ≥ 5.2.12**，**macOS > 5.2.10**）。\r\n2. **首次打开店铺会下载浏览器内核**，耗时较长，建议您先在站斧客户端里**手动打开一次**目标店铺，等内核下载完成后再用自动化。\r\n3. **不同店铺可能使用不同内核**。若自动化打开失败或提示内核相关错误，请先在站斧里**手动打开一次该店铺**（或与您要用的店铺**同内核**的店铺），内核就绪后再发指令。\r\n4. 店铺须已**绑定 IP / 设备**；未绑定时打开会失败，请在站斧客户端检查店铺设备绑定。\r\n5. **macOS 暂不支持**：设置下载目录、清除缓存（单店/全部）、设置店铺插件（`SetDownLoadPath` / `ClearCache` / `ClearCacheFolder` / `SetInstallPlugins`）。请在 Windows 上使用这些能力。\r\n6. **macOS 内核**：自动化仅支持店铺内核 **> 130**。若提示当前内核 ≤ 130，请在站斧中将该店铺切换到 **130 以上**内核（无权限时请**主账号**切换），然后**手动重启站斧**，再发指令继续。\r\n\r\n### 二、最常用的说法（推荐）\r\n\r\n\r\n| 您想做什么         | 直接发送（示例）                                   |\r\n| ------------- | ------------------------------------------ |\r\n| 启动站斧并打开店铺     | **打开站斧打开 ztest126**（把 `ztest126` 换成您的店铺名）  |\r\n| 仅打开店铺（站斧已在运行） | **打开店铺 ztest126**                          |\r\n| 关闭某个店铺        | **关闭 ztest126 店铺** / **关闭店铺 ztest126**     |\r\n| 退出站斧客户端       | **关闭站斧**                                   |\r\n| **创建新店铺**     | **创建店铺**，并按提示提供下方参数（见「七、创建店铺」）             |\r\n| **修改店铺账号密码**  | **修改店铺账号密码**，提供店铺名与新账号/密码（见「十二、修改店铺账号密码」） |\r\n| **查看我的店铺列表**  | **获取店铺列表** / **列出店铺**（见「八、查看店铺列表」）         |\r\n| **设置浏览器下载目录** | **设置下载目录到 D:\\downloads**（见「十、下载与缓存」）       |\r\n| **清除店铺/全部缓存** | **清除 xxx 店铺缓存** / **清除全部缓存**（见「十、下载与缓存」）   |\r\n| **设置店铺默认插件**  | **设置店铺插件**，提供插件名称；插件 ID 可省略或留空（见「十一、店铺插件」） |\r\n| **清空店铺插件列表**  | **清除默认插件列表** / **清空店铺插件**（见「十一、店铺插件」）      |\r\n\r\n\r\n> 说法可略有不同，只要包含「打开站斧」「打开店铺」和**店铺名称**即可；站斧已在运行时，一般**不会**重启站斧，直接开/关店铺。\r\n>\r\n> **同义说法**：客户发「**打开战斧**」「关闭战斧」「重启战斧」等时，**等同于**「打开站斧 / 关闭站斧 / 重启站斧」——「战斧」一律按「站斧」理解，**不要**当成未知产品或要求客户改口。\r\n\r\n### 三、首次未登录时\r\n\r\n若提示「站斧未登录，请提供账号和密码」，请提供您的**站斧老板账号**和密码（自动化仅使用您当场提供的账号，不会使用内测账号）。\r\n\r\n### 四、店铺已经打开时\r\n\r\n若您要的店铺**已经在运行**，系统会先问：**是否需要关闭该店铺？** 按您的选择回复即可；不需要关闭则可直接继续后续操作。\r\n\r\n### 五、页面自动化（进阶）\r\n\r\n店铺打开后，可继续用自然语言描述要在**店铺浏览器里**做的事，例如：\r\n\r\n- 「在 B 站搜索并播放某某视频」\r\n- 「打开某网址并填写表单」\r\n- 「抓取当前页面某某信息」\r\n\r\n此类操作会先等设备安全检测通过（约 15 秒），再自动操作页面。\r\n\r\n### 七、创建店铺\r\n\r\n发送 **「创建店铺」** 或 **「打开站斧并创建店铺 xxx」**，按提示提供信息即可（须已登录站斧）。\r\n\r\n**必填信息**\r\n\r\n\r\n| 您需提供                    | 说明                                             |\r\n| ----------------------- | ---------------------------------------------- |\r\n| **店铺名** `mall_name`     | 不能与已有店铺重名                                      |\r\n| **所属平台** `platform`     | 如「自定义平台」「Temu前台」等                              |\r\n| **平台网址** `platform_url` | 当平台选 **「自定义平台」** 时必填，如 `https://www.baidu.com` |\r\n\r\n\r\n**建议提供**\r\n\r\n\r\n| 您需提供                     | 说明                                               |\r\n| ------------------------ | ------------------------------------------------ |\r\n| **绑定设备 IP** `ip_content` | 须是站斧里**已有设备**的 IP；不知道时可先说「从已有店铺复用 IP」；未绑定时打开可能失败 |\r\n\r\n\r\n**选填信息**（有则提供，没有可留空）\r\n\r\n\r\n| 字段        | 说明                             |\r\n| --------- | ------------------------------ |\r\n| 店铺账号 / 密码 | `mall_account`、`mall_password` |\r\n| 店铺地址      | `mall_address`                 |\r\n| 标签        | `tags`                         |\r\n| 授权成员      | `authorizationMember`          |\r\n| 浏览器内核版本   | 不指定填 **0**                     |\r\n| 备注        | `remark`                       |\r\n\r\n\r\n**创建成功后**：系统会等列表同步，再按店铺名查询并**打开**新店铺。若创建失败，请检查店铺名是否重复、IP 是否有效、自定义平台是否填写了网址。\r\n\r\n**说法示例**\r\n\r\n> 创建店铺，店铺名 test001，平台自定义平台，网址 [https://www.baidu.com，绑定](https://www.baidu.com，绑定) IP 118.x.x.x\r\n\r\n### 八、查看店铺列表\r\n\r\n发送 **「获取店铺列表」**、**「列出我的店铺」** 或 **「店铺列表第 1 页」** 即可。\r\n\r\n- 系统会拉取您账号下的店铺，默认第 **1** 页、每页 **10** 条（可说「第 2 页」「每页 20 条」调整 `page` / `limit`）。\r\n- 列表中通常包含：**店铺名**、**平台**、**绑定 IP**、**创建/更新时间** 等。\r\n- **能正常拉到列表** = 站斧**已登录**；拉不到或报错 = 需要先登录（见「三、首次未登录时」）。\r\n\r\n**说法示例**\r\n\r\n> 获取店铺列表  \r\n> 列出店铺，第 2 页，每页 20 个\r\n\r\n### 十、下载与缓存（进阶）\r\n\r\n\r\n| 您想做什么     | 直接发送（示例）                      |\r\n| --------- | ----------------------------- |\r\n| 设置浏览器下载目录 | **设置下载目录到 D:\\downloads**      |\r\n| 清除某个店铺缓存  | **清除 ztest126 店铺缓存**（会先关闭该店铺） |\r\n| 清除全部店铺缓存  | **清除全部缓存**（会先关闭所有店铺）          |\r\n\r\n\r\n> 清除缓存为不可逆操作，执行前系统会向您确认。\r\n>\r\n> **macOS 暂不支持**本节全部能力（`SetDownLoadPath` / `ClearCache` / `ClearCacheFolder`）。\r\n\r\n### 十一、店铺插件（进阶）\r\n\r\n发送 **「设置店铺插件」**，在**打开店铺之前**指定默认加载的插件（`SetInstallPlugins` → `OpenBrowser`）。\r\n\r\n**您需提供**\r\n\r\n\r\n| 字段            | 必填  | 说明                          |\r\n| ------------- | --- | --------------------------- |\r\n| `plugin_name` | 是   | 插件名称（非空）                    |\r\n| `chrome_id`   | 否   | 插件 ID；**可省略**，或显式传空字符串 `\"\"` |\r\n\r\n\r\n可一次提供多个插件；说 **「清空店铺插件」**、**「清除默认插件列表」** 或传空列表 `[]` 表示不额外指定插件。\r\n\r\n> **重要**：若插件曾通过自动化安装，清空列表后还须**清除该店铺本地缓存**（`ClearCache`），再重新打开店铺，清空才生效。\r\n>\r\n> **macOS 暂不支持** `SetInstallPlugins`（及依赖的 `ClearCache`）。\r\n\r\n**说法示例**\r\n\r\n> 打开站斧，设置默认插件名称为紫竹自动化插件，插件 ID 为空，再打开店铺 ztest144  \r\n> 设置店铺插件，插件名 RXMallHelper（省略插件 ID）  \r\n> 设置店铺插件，插件名 紫竹自动化插件，插件 ID 为空  \r\n> 清除默认插件列表，重新打开 ztest144（会先 `SetInstallPlugins([])` → `ClearCache` → 再开店铺）\r\n\r\n> 设置会在后续 `OpenBrowser` 时生效；若店铺已打开，需先关闭再重新打开才加载新插件。\r\n\r\n### 十二、修改店铺账号密码\r\n\r\n发送 **「修改店铺账号密码」** / **「改店铺账号」**，按店铺修改登录账号与密码（`UpdateAccount`）。\r\n\r\n**您需提供**\r\n\r\n\r\n| 字段 | 必填 | 说明 |\r\n| ---- | --- | ---- |\r\n| **店铺名** `mall_name`（或已有 `mall_id`） | 是 | 用于 resolve `browserId`（=`mall_id`） |\r\n| **账号** `username` | 否 | 对应 `mall_account`；可空字符串 `\"\"` |\r\n| **密码** `password` | 否 | 对应 `mall_password`；可空字符串 `\"\"` |\r\n\r\n\r\n> 缺少账号/密码时先向客户询问，**禁止猜测**。账号与密码均可显式传空以清空对应字段。\r\n\r\n**说法示例**\r\n\r\n> 修改店铺 ztest126 的账号为 admin，密码为 cyt123456A  \r\n> 修改店铺账号密码，店铺名 ztest126，账号 admin，密码留空\r\n\r\n### 九、常见问题\r\n\r\n\r\n| 现象      | 建议                                 |\r\n| ------- | ---------------------------------- |\r\n| 打开店铺失败  | 检查店铺是否已绑定 IP/设备；首次使用是否已手动开过该店以下载内核 |\r\n| macOS 提示内核过低 | 将店铺切换到 **130 以上**内核（或请主账号切换），**手动重启站斧**后再试 |\r\n| 提示未登录   | 提供站斧账号和密码                          |\r\n| 站斧未启动   | 发送「**打开站斧打开 {店铺名}**」，会自动冷启动站斧再开店铺  |\r\n| 想完全重启站斧 | 明确说「**重启站斧**」                      |\r\n| 创建店铺失败  | 检查店铺名是否重复、IP 是否已绑定、自定义平台是否填了网址     |\r\n| 看不到店铺列表 | 先登录站斧；或说明要查第几页、每页多少条               |\r\n\r\n\r\n---\r\n\r\n## 硬规矩（红线，最高优先级）\r\n\r\n以下规则覆盖本 Skill 其他所有「等待 / 重试 / 备用方案」描述，**冲突时以本节为准**。\r\n\r\n### 1. 获取端口前：禁止写脚本\r\n\r\n在 `**OpenBrowser` 打开店铺并成功拿到 `WebDriverPort` 之前**：\r\n\r\n- **禁止**新建或运行任何 `.py` / `.js` / `.sh` 等可执行脚本文件（含 `_tmp_*.py`、临时业务脚本）\r\n- **禁止**为完成任务而编写「一次性自动化脚本」\r\n- **只允许**调用本 Skill 提供的 **HTTP 接口**（见 [reference.md](reference.md)）或 Shell 直接发 HTTP 请求\r\n- **允许**读写临时**数据文件**（如 `api_port.json`、`mall_cache.json`、`opening_malls.json` 状态文件），但数据文件不可执行\r\n\r\n> **例外（内置脚本）**：打开站斧运行 [`scripts/open_zhanfu.py`](scripts/open_zhanfu.py)；打开店铺运行 [`scripts/open_mall.py`](scripts/open_mall.py)；关店 / 列表 / 关站斧 / 登录 / 创建与插件等分别运行 `close_mall.py`、`list_malls.py`、`close_zhanfu.py`、`login_zhanfu.py`、`zhanfu_ops.py`。**禁止**另写一次性脚本。阶段 B 页面自动化仍禁止落盘为业务 `.py`。\r\n\r\n### 2. 通讯失败或关键操作报错：立即结束\r\n\r\n出现以下情况，**马上停下并向客户报告**（`**GetBrowserList` 探测轮询**、以及「OpenBrowser 前 `GetBrowserWebDriver` **单次 5s** 超时后仍 `OpenBrowser`」除外，见下节）：\r\n\r\n- HTTP **连不上**站斧（连接拒绝、超时、无响应）\r\n- 除登录/运行态探测用 `GetBrowserList` 外，关键 API 返回失败（`returnObj.success == false`、缺必需字段）\r\n- Login / GetMallByName / CreateBrowser / UpdateAccount / SetInstallPlugins / OpenBrowser（`returnObj !== true`）/ GetBrowserWebDriver 失败（**例外**：OpenBrowser **前**探测 `GetBrowserWebDriver` 超时 5s → 仍执行 `OpenBrowser`）\r\n\r\n**禁止**：\r\n\r\n- 反复重试同一失败操作（`GetBrowserList` 的 **8s 轮询**、以及 OpenBrowser 前 `GetBrowserWebDriver` **仅允许单次 5s，超时改走 OpenBrowser**除外）\r\n- 全盘 / 跨盘符搜索站斧安装包（Windows：`where.exe`、`-Recurse`、glob `**\\站斧.exe`；macOS：全盘 `mdfind` / `find`）\r\n- 遍历桌面**全部** `.lnk` 或解析**文件名不含「站斧」**的快捷方式（如逐个扫 GitHub、VS Code、其他浏览器快捷方式）\r\n- 翻代码库「研究」原因\r\n- 写「等通讯好了再跑」的备用方案或延迟任务\r\n- 自行换端口 / 换路径 / 换工具碰运气（**例外**：冷启动前用 `get_available_port(首选)`——首选默认 `12678`，占用则递增 `12679…`；**禁止**盲扫 8081/8082 碰已运行站斧；**禁止**因端口占用要求客户先释放）\r\n- **减少/省略**站斧启动参数（Windows / macOS **均须四项齐全**：`--multip --run_type=web_driver --ipc_type=http --httpport=`）\r\n- 将 `OpenBrowser` / `GetBrowserWebDriver` 的 `browserId` 传成 **JSON 数字**（必须为**字符串**，如 `\"3514488\"`）\r\n- 客户仅要求**打开店铺**或**关闭店铺**时，在 `api_port` HTTP 通讯正常的情况下仍执行杀进程、冷启动或 `ExitClient`（**除非客户明确要求重启站斧**）\r\n- 用 `CheckClientOpen` / `LoadSuccess` / `LoadFailed` **判断站斧是否已打开**（改用 `GetBrowserList`，见下）\r\n- 在 **macOS** 上调用 `SetDownLoadPath` / `ClearCacheFolder` / `ClearCache` / `SetInstallPlugins`（**目前不支持**，应直接告知客户）\r\n- 在 **macOS** 上对 `KernalNumber ≤ 130` 的店铺继续 `connect_over_cdp` / 页面自动化（应提示切内核并让客户手动重启站斧后停止）\r\n\r\n### 3. 获取端口前：只能 HTTP，禁止浏览器工具\r\n\r\n在拿到 `**WebDriverPort` 之前**：\r\n\r\n- **只允许**向 `http://127.0.0.1:{api_port}` 发 HTTP POST（`WebDriverModule`）\r\n- **禁止**打开系统 Chrome / Edge / Firefox\r\n- **禁止**使用 Playwright / Puppeteer（含 `launch`、`connect_over_cdp`）\r\n- **禁止**使用 Cursor browser MCP / CDP 浏览器工具绕开站斧\r\n\r\n拿到端口之后，**仅允许** `playwright.chromium.connect_over_cdp(\"http://127.0.0.1:{WebDriverPort}\")` 接管**站斧店铺浏览器**。\r\n\r\n### 4. 工具名必须来自清单\r\n\r\n**禁止瞎编** action、工具名、命令名。只能使用下方「接口清单」中的 `action` 名称。\r\n\r\n#### 阶段 A — 获取端口前（仅 HTTP）\r\n\r\n\r\n| action                | 用途                                                                     |\r\n| --------------------- | ---------------------------------------------------------------------- |\r\n| `GetBrowserList`      | **判断站斧是否已打开** / 探测登录态 / 列表（**能取到数据 = 站斧已打开**；**禁止**用 `LoadSuccess` 判断） |\r\n| `Login`               | 登录（已登录则跳过；会关闭所有已开店铺）                                                   |\r\n| `GetMallByName`       | 按名称查店铺（`mallName` / `mall_name` / `name`）                              |\r\n| `CreateBrowser`       | 创建店铺                                                                   |\r\n| `UpdateAccount`       | 按 `browserId`（`mall_id`）修改店铺登录账号/密码（`username`→`mall_account`，`password`→`mall_password`，可空） |\r\n| `OpenBrowser`         | 打开店铺（成功 `returnObj===true`）                                            |\r\n| `GetBrowserWebDriver` | 获取 WebDriverPort（须店铺已打开；也可探测店铺是否已开）                                    |\r\n| `CloseBrowser`        | 关闭店铺（成功 `returnObj===null`）                                            |\r\n| `ExitClient`          | 退出站斧                                                                   |\r\n| `SetDownLoadPath`     | 设置浏览器下载目录（**仅 Windows**；macOS 不支持）                                     |\r\n| `SetInstallPlugins`   | 设置打开店铺时默认加载的插件（须在 `OpenBrowser` 前；**仅 Windows**；macOS 不支持）             |\r\n| `ClearCacheFolder`    | 清除全部店铺缓存（**仅 Windows**；macOS 不支持）                                      |\r\n| `ClearCache`          | 清除单个店铺缓存（**仅 Windows**；macOS 不支持）                                      |\r\n| `GetWebDriver`        | 仅 Selenium；Playwright **跳过**                                           |\r\n| `CheckClientOpen`     | **不再用于判断站斧是否已打开**（勿依赖 `LoadSuccess` / `LoadFailed`）                    |\r\n\r\n\r\n> **macOS**：客户要求下载目录 / 清缓存 / 设插件时，**立即停止**并告知「macOS 暂不支持该功能」，**禁止**调用上表标注「仅 Windows」的 action。\r\n\r\nHTTP 格式（固定）：\r\n\r\n```json\r\nPOST http://127.0.0.1:{api_port}\r\nContent-Type: application/json\r\n\r\n{\r\n  \"module\": \"WebDriverModule\",\r\n  \"action\": \"<上表 action>\",\r\n  \"browserId\": \"<mall_id 字符串，可选>\",\r\n  \"args\": \"<JSON 字符串，可选>\"\r\n}\r\n```\r\n\r\n> **`browserId` 类型硬规矩**：`OpenBrowser`、`GetBrowserWebDriver`（以及同样传 `browserId` 的 `CloseBrowser` / `UpdateAccount` / `ClearCache` 等）的 **`browserId` 必须是 JSON 字符串**（如 `\"3514488\"`），**禁止**传数字（如 `3514488`）。从 `mall_id` 取值后一律 `str(mall_id)` 再写入请求。\r\n\r\n站斧启动命令行参数（按操作系统）：\r\n\r\n**Windows**（**四项缺一不可，禁止减少/省略任一参数**；`{api_port}` 为分配到的空闲端口）：\r\n\r\n```\r\n站斧.exe --multip --run_type=web_driver --ipc_type=http --httpport={api_port}\r\n```\r\n\r\n| 参数 | 可否省略 |\r\n|------|----------|\r\n| `--multip` | **否** |\r\n| `--run_type=web_driver` | **否** |\r\n| `--ipc_type=http` | **否** |\r\n| `--httpport={api_port}` | **否**（值可变，键不可少） |\r\n\r\n**macOS**（**四项缺一不可，禁止减少/省略任一参数**，与 Windows 相同；用 `open -a` 启动）：\r\n\r\n```\r\nopen -a /Applications/站斧.app --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}\r\n```\r\n\r\n也可：`open -a 站斧 --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}`\r\n\r\n| 参数 | 可否省略 |\r\n|------|----------|\r\n| `--multip` | **否** |\r\n| `--run_type=web_driver` | **否** |\r\n| `--ipc_type=http` | **否** |\r\n| `--httpport={api_port}` | **否**（值可变，键不可少） |\r\n\r\n**禁止**减少启动参数（例如去掉 `--multip` / `--ipc_type=http`，或只留 `--httpport`）。**默认 API 端口**：首选 `12678`。冷启动前须 `get_available_port(首选)`：**若首选端口已被占用则自动用下一空闲端口（12679…）**，**禁止**因此停下来要求客户释放端口；启动成功后把实际端口写入 Skill 目录 `[api_port.json](api_port.json)`（见下节）。\r\n\r\n#### HTTP 请求方式（阶段 A · 禁止 curl / 禁止换工具试错）\r\n\r\n**Agent 默认只用 Python `requests`**（稳定、无引号逃逸坑）。**禁止**为同一探测在 PowerShell / curl / Python 之间来回换工具（浪费时间）。\r\n\r\n**单次探测超时**：`timeout=1.5` 秒（够判通断，勿用 3～30s 长超时堵死）。\r\n\r\n**推荐模板**（直接复制，勿改成复杂转义；`{api_port}` 换成 `api_port.json` 中的端口，默认 `12678`）：\r\n\r\n```python\r\nimport requests, json\r\napi_port = 12678  # 读自 api_port.json，无文件则用 12678\r\nr = requests.post(\r\n    f\"http://127.0.0.1:{api_port}\",\r\n    json={\"module\": \"WebDriverModule\", \"action\": \"GetBrowserList\",\r\n          \"args\": json.dumps({\"page\": 1, \"limit\": 20})},\r\n    timeout=1.5,\r\n)\r\nprint(r.text)\r\n```\r\n\r\n连接拒绝 / 超时 → 视为**站斧未打开**，立刻清空 `opening_malls.json` 并冷启动；**不要**改用 PowerShell 再探一次。\r\n\r\n**冷启动分配空闲端口**（判定站斧未打开之后、启动之前必做；直接复制）：\r\n\r\n```python\r\nimport socket\r\ndef get_available_port(start=12678):\r\n    port = max(1, int(start))\r\n    while port < 65535:\r\n        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:\r\n            try:\r\n                s.bind((\"127.0.0.1\", port))\r\n                return port\r\n            except OSError:\r\n                port += 1\r\n    raise RuntimeError(f\"自 {start} 起未找到可用端口\")\r\n\r\n# preferred = api_port.json 的 api_port（默认 12678）\r\napi_port = get_available_port(preferred)\r\nprint(api_port)  # 若 12678 被占用，会得到 12679…\r\n```\r\n\r\n> 首选端口被占用（含非站斧服务、TIME_WAIT 等）→ **换下一空闲端口继续启动**，**禁止**要求客户先释放 12678；**禁止**盲扫 8081/8082 碰已运行站斧。\r\n\r\n**备选（仅人工调试）** PowerShell 手动拼 JSON：\r\n\r\n```powershell\r\n$body = '{\"module\":\"WebDriverModule\",\"action\":\"GetBrowserList\",\"args\":\"{\\\"page\\\":1,\\\"limit\\\":20}\"}'\r\nInvoke-RestMethod -Uri \"http://127.0.0.1:12678\" -Method Post -Body $body -ContentType \"application/json\"\r\n```\r\n\r\n**禁止** Windows `curl` 手工转义 JSON；**禁止** PowerShell `ConvertTo-Json` 嵌套 `args`。\r\n\r\n#### 打开站斧快速路径（优先按此执行，少读少试）\r\n\r\n客户说「打开站斧 / 打开战斧」时，在 Skill 目录运行：\r\n\r\n```bash\r\npython scripts/open_zhanfu.py\r\n```\r\n\r\n客户已提供安装路径：`--folder-path \"I:\\ZhanFu\"`；已提供登录账号：`--username ... --password ...`。\r\n\r\n看脚本结尾的 `RESULT_JSON=`：\r\n\r\n| `status` | 动作 |\r\n|----------|------|\r\n| `already_open` / `started` / `logged_in` | 站斧已就绪；仅打开站斧则结束 |\r\n| `need_login` | 向客户索要账号密码后带 `--username/--password` 再跑 |\r\n| `need_install_path` | 向客户索要安装路径后带 `--folder-path` 再跑 |\r\n| `comm_fail` | **原样**把 `msg` 发给客户，禁止重试 |\r\n\r\n脚本内部已包含：单次 `GetBrowserList` 探测、占用换口、四项启动参数、最多 8s 轮询、写回 `api_port.json`。\r\n\r\n#### 打开店铺快速路径\r\n\r\n先确保站斧已开。客户说「打开店铺 xxx」时：\r\n\r\n```bash\r\npython scripts/open_mall.py --mall-name xxx\r\n```\r\n\r\n| `status` | 动作 |\r\n|----------|------|\r\n| `already_open` | **不要**再 OpenBrowser；把 `WebDriverPort` 告诉客户。若客户本意是「打开」且店铺已开，再问是否需要关闭 |\r\n| `opened` | 返回 `mall_id` / `WebDriverPort` |\r\n| `zhanfu_down` | 先跑 `open_zhanfu.py` |\r\n| `open_failed` / `no_webdriver_port` | 停止并提醒 IP/设备绑定与内核下载 |\r\n\r\n关闭店铺：`python scripts/close_mall.py --mall-name xxx`（成功 `returnObj === null`）。\r\n\r\n#### 阶段 B — 拿到 WebDriverPort 之后\r\n\r\n\r\n| 工具 / 方法                                | 用途                                |\r\n| -------------------------------------- | --------------------------------- |\r\n| `playwright.chromium.connect_over_cdp` | 接管站斧店铺浏览器                         |\r\n| `scripts/check_device_security.py`     | 业务自动化前设备安全检测（Skill 内置，**仅端口拿到后**） |\r\n| `ensure_headed_mode()`                 | 强制有界面（见 `scripts/headed_mode.py`） |\r\n\r\n\r\n**禁止**：`playwright.chromium.launch`、`browser_navigate`（MCP）、Puppeteer `launch`。\r\n\r\n---\r\n\r\n## 两阶段工作流\r\n\r\n```\r\n阶段 A（仅 HTTP，禁止脚本 / 禁止 Playwright / 失败即停）\r\n  [读 api_port.json → 单次 GetBrowserList 探测该端口] → 能取到数据则站斧已打开，直接继续（开/关店铺均不重启）\r\n  → 无 HTTP 响应 / 非站斧占用 = 站斧未打开 → **立刻清空 opening_malls.json** → 查路径 → 杀站斧进程 → **get_available_port(首选)（占用则 12679…）** → 冷启动\r\n  → 冷启动前查找站斧：api_port.json →（Windows 快捷方式/常见目录；macOS `/Applications`/`~/Applications`）；**全部找不到则停止并向客户索要安装路径**（禁止全盘搜）\r\n  → GetBrowserList 探测运行态/登录（最多 8s；能取到数据=已打开；禁止用 LoadSuccess 判断）→ [未登录则提示 Login]\r\n  → [SetInstallPlugins / SetDownLoadPath 可选，**仅 Windows**，须在 OpenBrowser 前；**macOS 跳过且勿调用**]\r\n  → 打开（站斧已打开之后）：写入 opening_malls.json → resolve mall_id → GetBrowserWebDriver **单次 5s** 判是否已开（超时仍 OpenBrowser）→ OpenBrowser → GetBrowserWebDriver → **【macOS】检查 `KernalNumber`，≤130 则停并提示切内核/主账号切换 + 手动重启站斧**\r\n  → 关闭：resolve mall_id → CloseBrowser → 从 opening_malls.json 去掉该店铺名\r\n  → 关闭站斧：ExitClient → 清空 opening_malls.json\r\n\r\n阶段 B（端口拿到后；macOS 且 KernalNumber≤130 禁止进入）\r\n  connect_over_cdp → [设备安全检测 15s] → 业务 Playwright 自动化\r\n```\r\n\r\n```\r\nTask Progress:\r\n- [ ] 1. 收集客户参数（含 mall_name）\r\n- [ ] 2. 【阶段 A】读 `api_port.json`，对**唯一目标端口**单次 `GetBrowserList`（无文件则用 **12678**）；**能取到数据 = 站斧已打开，禁止冷启动**（开/关店铺均适用；**禁止**用 `LoadSuccess` 判断）\r\n- [ ] 3. 【阶段 A · 探测到站斧未打开】**立刻清空 `opening_malls.json`** → 查安装路径 → 杀进程（Win:`taskkill` / Mac:`killall 站斧`，最多等 1s）→ **`api_port = get_available_port(首选)`（首选被占用则递增）** → 冷启动 `--httpport={api_port}` → **立刻**轮询 `GetBrowserList`（间隔 0.5s，最多 8s）→ 写回 `api_port.json`\r\n- [ ] 4. 【阶段 A】`GetBrowserList` 探测运行态/登录（间隔 **0.5s**，**总计最多 8s**）；能取到 `mall_list` = 已打开且已登录；仍无法确认则提示客户提供账号密码\r\n- [ ] 5. 【阶段 A · 打开店铺 · 仅站斧已打开后】将 `mall_name` **写入** `opening_malls.json`（打开意图配置；**禁止**在站斧未打开时写入）\r\n- [ ] 6. 【阶段 A】resolve mall_id（读 `mall_cache.json` → 未命中则 `GetMallByName` 并写缓存）/ `CreateBrowser`（失败即停）\r\n- [ ] 7. 【阶段 A】resolve mall_id（关店则跳过 OpenBrowser 相关步骤）\r\n- [ ] 8. 【阶段 A · 打开店铺】`GetBrowserWebDriver` **只请求一次、超时 5s** 判断是否已打开；超时/无端口则**仍执行 OpenBrowser**（禁止二次探测、禁止 15s 长超时）\r\n- [ ] 9. 【阶段 A · 已打开】询问客户是否需要关闭店铺；未确认不操作\r\n- [ ] 10. 【阶段 A · 需打开】OpenBrowser（失败即停）→ GetBrowserWebDriver\r\n- [ ] 10b. 【阶段 A · macOS 内核】`GetBrowserWebDriver` 成功后若 `KernalNumber ≤ 130` → **立即停止**，按「macOS 低内核对客户话术」提示，**禁止**进入阶段 B\r\n- [ ] 11. 【阶段 A · 关闭店铺】CloseBrowser → **从 `opening_malls.json` 去掉该店铺名**（HTTP 正常时不重启站斧）\r\n- [ ] 12. 【阶段 A · 关闭站斧】ExitClient → **清空 `opening_malls.json`**\r\n- [ ] 13. 【阶段 B】connect_over_cdp\r\n- [ ] 14. 【阶段 B · 仅业务自动化】设备安全检测（15s 超时）\r\n- [ ] 15. 【阶段 B】执行业务自动化\r\n- [ ] 16. 收尾：CloseBrowser / ExitClient（**仅客户明确要求时** ExitClient；关店/关站斧时同步清理 `opening_malls.json`）\r\n```\r\n\r\n---\r\n\r\n## 禁止无头模式\r\n\r\n1. 站斧必须以 WebDriver 模式**有界面**启动\r\n2. 只能 `connect_over_cdp`，禁止 `launch(headless=True)`\r\n3. 执行 Playwright 前调用 `ensure_headed_mode()`，设置 `PLAYWRIGHT_HEADLESS=0`\r\n4. 禁止使用 Cursor 内置 browser MCP 替代站斧浏览器\r\n\r\n---\r\n\r\n## 执行前：向客户收集参数\r\n\r\n缺少必填项时先询问，**不要猜测账号密码或 IP**。\r\n\r\n**站斧安装路径**（打开站斧 / 冷启动时）：**先读** `api_port.json` 的 `install_dir` → 无效再按操作系统查找（见「启动站斧」）。**任一方式命中后，立即把安装路径写回** `api_port.json`。**都找不到时，必须停止并向客户索要安装路径**；**禁止**全盘搜索或猜测路径。\r\n\r\n- **Windows**：目录内需含 `站斧.exe`；客户提供后验证 `{folder_path}\\站斧.exe` 存在再继续。\r\n- **macOS**：需为 `站斧.app`（如 `/Applications/站斧.app`）；客户提供后验证 `.app` 存在再继续。\r\n\r\n### 登录态探测与 Login\r\n\r\n站斧启动（或复用 API）后，**必须在 8s 内**通过 `GetBrowserList` 判断站斧是否**已打开**且已登录（**禁止**用 `CheckClientOpen` / `LoadSuccess` / `LoadFailed` 判断）：\r\n\r\n```json\r\n{\"action\": \"GetBrowserList\", \"module\": \"WebDriverModule\", \"args\": \"{\\\"page\\\":1,\\\"limit\\\":20}\"}\r\n```\r\n\r\n\r\n| `GetBrowserList` 结果（8s 内）                                  | 动作                                                               |\r\n| ---------------------------------------------------------- | ---------------------------------------------------------------- |\r\n| `returnObj.success == true` 且能取到 `mall_list`（可解析，非 `null`） | **站斧已打开且已登录**，跳过 `Login`（`Login` 会关闭已开店铺）                        |\r\n| 有 HTTP 响应但 `success == false`、`data=null`、无法解析 `mall_list` | 站斧进程可能在跑但**未登录** → **停止**，提示客户：**「站斧未登录，请提供账号和密码」**（**禁止**因此冷启动） |\r\n| 连接拒绝 / 无响应 / 8s 超时仍无任何 HTTP 响应                             | **站斧未打开** → 才允许冷启动                                               |\r\n| 客户未提供账号密码                                                  | **停止**，不猜测、不擅自登录                                                 |\r\n\r\n\r\n**不要默认主动索要**登录信息；仅在 `GetBrowserList` 失败且后续需要操作店铺时再向客户索取。\r\n\r\n**禁止**在 Skill、脚本或对话中保存、引用或使用任何内测/示例账号密码；**仅**使用客户当场提供的 `username` / `password` 调用 `Login`，且固定 `isboss=true`（老板账号）。\r\n\r\nLogin 请求示例：\r\n\r\n```json\r\n{\r\n  \"action\": \"Login\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"username\\\":\\\"...\\\",\\\"password\\\":\\\"...\\\",\\\"isboss\\\":true}\"\r\n}\r\n```\r\n\r\n`Login` 返回 `success != true` → **立即结束**，原样报告 `returnObj.msg`（如密码错误）。\r\n\r\n### 按名称打开店铺\r\n\r\n\r\n| 参数          | 必填  |\r\n| ----------- | --- |\r\n| `mall_name` | 是   |\r\n\r\n\r\n### 创建店铺\r\n\r\n\r\n| 参数                                    | 必填       | 说明                             |\r\n| ------------------------------------- | -------- | ------------------------------ |\r\n| `mall_name`                           | 是        | 店铺名，不可重复                       |\r\n| `platform`                            | 是        | 所属平台                           |\r\n| `platform_url`                        | 自定义平台时必填 | 如 `https://www.baidu.com`      |\r\n| `ip_content`                          | 否        | 绑定已有设备 IP（或从已有店铺复用）；未绑定时打开可能失败 |\r\n| `mall_account` / `mall_password`      | 否        | 店铺账号密码                         |\r\n| `mall_address`                        | 否        | 店铺地址                           |\r\n| `tags`                                | 否        | 标签                             |\r\n| `authorizationMember`                 | 否        | 授权成员                           |\r\n| `browser_kernel_version`              | 否        | 不指定内核填 `0`                     |\r\n| `window_ua` / `mac_ua` / `android_ua` | 否        | UA                             |\r\n| `remark`                              | 否        | 备注                             |\r\n\r\n\r\n创建成功后须等待列表同步，再 resolve mall_id → `OpenBrowser`。\r\n\r\n### 设置店铺插件（SetInstallPlugins）\r\n\r\n客户要求**打开店铺前加载指定插件**时，须在 `OpenBrowser` **之前**调用。\r\n\r\n**省略 `chrome_id`**：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[{\\\"plugin_name\\\":\\\"RXMallHelper\\\"}]}\"\r\n}\r\n```\r\n\r\n`**chrome_id` 传空字符串**（客户说「插件 ID 为空」时用此写法）：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[{\\\"plugin_name\\\":\\\"紫竹自动化插件\\\",\\\"chrome_id\\\":\\\"\\\"}]}\"\r\n}\r\n```\r\n\r\n\r\n| 参数                             | 必填  | 说明                   |\r\n| ------------------------------ | --- | -------------------- |\r\n| `installPlugins`               | 是   | 插件数组；`[]` 表示清空/不额外指定 |\r\n| `installPlugins[].plugin_name` | 是   | 插件名称，非空字符串           |\r\n| `installPlugins[].chrome_id`   | 否   | 插件 ID；可省略或传 `\"\"`     |\r\n\r\n\r\n**清空插件列表**（`installPlugins: []`）：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[]}\"\r\n}\r\n```\r\n\r\n> 通过自动化安装的插件，**清空列表后须对该店铺调用 `ClearCache`**，再 `OpenBrowser`，清空才生效。\r\n\r\n**清空并重新打开店铺流程**：\r\n\r\n1. `SetInstallPlugins`（`installPlugins: []`）\r\n2. resolve mall_id 取 `mall_id`\r\n3. `ClearCache`（`browserId` = `mall_id`；会关闭该店铺）\r\n4. `OpenBrowser` → 等 10s → `GetBrowserWebDriver`\r\n\r\n`returnObj.success != true` → **立即结束**，原样报告 `returnObj.msg`。\r\n\r\n### 设备安全检测（仅业务自动化）\r\n\r\n客户提出**页面级自动化**（填表、抓取、播放视频等）时，阶段 B 必须先等设备安全检测成功（15s 超时）；仅启动/开店铺不需要。\r\n\r\n超时或未成功 → 告知客户：**「没检测成功无法进行自动化」**，立即结束。\r\n\r\n---\r\n\r\n## 打开店铺 / 关闭店铺（意图路由 · HTTP 正常则不重启）\r\n\r\n客户发送**打开店铺**或**关闭店铺**指令时，**一律先**读 `api_port.json` 并对 `api_port` 做单次 `GetBrowserList` 探测（**禁止**用 `LoadSuccess` 判断）。\r\n\r\n> **口误 / 同义**：客户说「**战斧**」=「**站斧**」。例如「打开战斧」「打开战斧打开 xxx」「关闭战斧」「重启战斧」分别按「打开站斧」「打开站斧打开 xxx」「关闭站斧」「重启站斧」执行。\r\n\r\n\r\n| 客户意图                       | `GetBrowserList` 探测        | 动作                                                                                                                                                    |\r\n| -------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\r\n| **打开店铺**                   | **能取到数据**（站斧已打开）或有 HTTP 响应 | **禁止**杀进程 / 冷启动 / `ExitClient`；将 `mall_name` 写入 `opening_malls.json` → resolve mall_id → `GetBrowserWebDriver` **单次 5s** 判是否已开 → 未开/超时则 `OpenBrowser` |\r\n| **关闭店铺**                   | **能取到数据**或有 HTTP 响应        | **禁止**杀进程 / 冷启动 / `ExitClient`；直接 HTTP：resolve mall_id → `CloseBrowser` → **从 `opening_malls.json` 去掉该店铺名**                                           |\r\n| **关闭站斧** / **关闭战斧** / `ExitClient`    | 任意                         | `ExitClient` → **清空 `opening_malls.json`**                                                                                                            |\r\n| **创建店铺**                   | **能取到数据**或有 HTTP 响应        | **禁止**重启；`CreateBrowser` → 等待同步 → resolve mall_id → `OpenBrowser`（参数见客户指南「七、创建店铺」）                                                                    |\r\n| **修改店铺账号密码**               | **能取到数据**或有 HTTP 响应        | **禁止**重启；resolve mall_id → `UpdateAccount`（`browserId`=`mall_id`，`args.username`/`password` 由客户提供，可空；见「十二、修改店铺账号密码」）                              |\r\n| **获取店铺列表**                 | **能取到数据**或有 HTTP 响应        | **禁止**重启；`GetBrowserList`（默认 `page=1, limit=10`，可按客户指定分页）→ 展示 `mall_list`；**同时将列表中 `mall_name` → `mall_id` 写入 `mall_cache.json`**                     |\r\n| **设置下载目录**                 | **能取到数据**或有 HTTP 响应        | **仅 Windows**；macOS → 告知暂不支持并停止。Windows：`SetDownLoadPath`（`FilePath` 由客户提供）                                                                           |\r\n| **设置店铺插件**                 | **能取到数据**或有 HTTP 响应        | **仅 Windows**；macOS → 告知暂不支持并停止。Windows：`SetInstallPlugins`（须在 `OpenBrowser` 前）                                                                       |\r\n| **清空插件列表**                 | **能取到数据**或有 HTTP 响应        | **仅 Windows**；macOS → 告知暂不支持并停止。Windows：`SetInstallPlugins([])` → `ClearCache` → `OpenBrowser`                                                        |\r\n| **清除全部缓存**                 | **能取到数据**或有 HTTP 响应        | **仅 Windows**；macOS → 告知暂不支持并停止。Windows：确认后 `ClearCacheFolder` → 清空 `opening_malls.json`                                                              |\r\n| **清除单店缓存**                 | **能取到数据**或有 HTTP 响应        | **仅 Windows**；macOS → 告知暂不支持并停止。Windows：确认后 `ClearCache` → 从 `opening_malls.json` 去掉该店                                                                |\r\n| **打开站斧** / **打开战斧** / **打开站斧打开 {店铺}** | **无响应**（站斧未打开）             | **立刻清空 `opening_malls.json`** → 查安装目录（快捷方式/常见目录找不到则**向客户索要**）→ `get_available_port(首选)`（占用则递增）→ 冷启动 → 站斧就绪后再按需写入店铺名并开店铺                                                                |\r\n| **打开 / 关闭店铺**              | **无响应**（连接拒绝 / 超时）         | **立刻清空 `opening_malls.json`** → 才允许冷启动站斧（见「启动站斧」，含端口占用则换口）；**禁止**为关店单独重启（关店只需 HTTP，站斧未运行则先冷启动再继续 HTTP）                                                         |\r\n| **重启站斧** / **重启战斧**                   | 任意                         | 仅当客户**明确要求**时才杀进程 + `get_available_port` 冷启动（Win:`taskkill` / Mac:`killall 站斧`）→ **立刻清空 `opening_malls.json`**                                                             |\r\n\r\n\r\n> **核心**：开店铺、关店铺都是 **HTTP 操作**；`GetBrowserList` **能取到数据** = 站斧**已打开**，**继续 HTTP 即可**，不要「顺手」重启客户端。**禁止**根据 `CheckClientOpen` 的 `LoadSuccess` / `LoadFailed` 判断站斧是否已打开。\r\n\r\n### 关闭店铺流程（阶段 A · 仅 HTTP）\r\n\r\n1. 读 `api_port.json` → 单次探测 `GetBrowserList`\r\n2. 能取到数据或有 HTTP 响应 → resolve mall_id（读 `mall_cache.json` → 未命中则 `GetMallByName` 并写缓存；失败即停）\r\n3. `CloseBrowser`（`browserId` = 字符串形式的 `mall_id`）；成功时 `returnObj === null`，失败时 `returnObj === false`\r\n4. **从 `opening_malls.json` 去掉该 `mall_name`**\r\n5. **不调用** `ExitClient`（除非客户明确要求退出站斧客户端）\r\n6. **禁止**因关店而冷启动或杀站斧进程（Win:`站斧.exe` / Mac:`killall 站斧`）\r\n\r\n```json\r\n{\"action\": \"CloseBrowser\", \"module\": \"WebDriverModule\", \"browserId\": \"3514488\"}\r\n```\r\n\r\n---\r\n\r\n## 站斧运行态复用（读本地端口 · 单次 GetBrowserList · 禁止扫端口）\r\n\r\n客户要求**打开店铺**、**关闭店铺**或**执行业务自动化**时，**不要默认杀进程重启站斧**，也**禁止**依次试探 8081/8082 等端口。\r\n\r\n### 本地状态记录 `api_port.json`\r\n\r\n路径：Skill 目录下 `[api_port.json](api_port.json)`（与 `SKILL.md` 同级）。\r\n\r\n```json\r\n{\r\n  \"api_port\": 12678,\r\n  \"install_dir\": \"I:\\\\ZhanFu\",\r\n  \"updated_at\": \"2026-06-17T12:00:00\"\r\n}\r\n```\r\n\r\n\r\n| 字段            | 说明                                                                                          |\r\n| ------------- | ------------------------------------------------------------------------------------------- |\r\n| `api_port`    | 站斧 HTTP API 端口（首选默认 `12678`；冷启动时若占用则写入实际分配端口）                                                                  |\r\n| `install_dir` | 站斧安装路径：Windows 为含 `站斧.exe` 的文件夹；macOS 为 `站斧.app` 路径（如 `/Applications/站斧.app`）；**查找命中后立即写入** |\r\n| `updated_at`  | 最近一次写入时间                                                                                    |\r\n\r\n\r\n\r\n| 时机                                 | 动作                                                                                   |\r\n| ---------------------------------- | ------------------------------------------------------------------------------------ |\r\n| 每次任务开始                             | **先读** `api_port.json` 的 `api_port`；文件不存在则用 **12678**                                |\r\n| 冷启动前查找站斧                           | **先读** `install_dir`：Windows 验证 `{install_dir}\\站斧.exe`；macOS 验证 `.app` 存在；无效则走原始查找逻辑 |\r\n| 原始逻辑命中安装路径                         | **立即写入** `install_dir` 到 `api_port.json`                                             |\r\n| 客户提供路径且验证通过                        | **写入** `install_dir`                                                                 |\r\n| `GetBrowserList` 能取到数据 / 有 HTTP 响应 | **刷新写入** `api_port`（保留已有 `install_dir`）                                              |\r\n| 冷启动站斧成功                            | **写入** `api_port`（若有 `install_dir` 一并保留/更新）                                          |\r\n\r\n\r\n### 单次探测（仅一个端口 · 用 GetBrowserList，禁止 LoadSuccess）\r\n\r\n对目标端口（本地记录或 12678）发**一次** POST，Body 为正确 JSON 的 `GetBrowserList`：\r\n\r\n```json\r\n{\"module\":\"WebDriverModule\",\"action\":\"GetBrowserList\",\"args\":\"{\\\"page\\\":1,\\\"limit\\\":20}\"}\r\n```\r\n\r\n\r\n| HTTP / 业务结果                                   | 判定              | 动作                                                                    |\r\n| --------------------------------------------- | --------------- | --------------------------------------------------------------------- |\r\n| `success==true` 且能取到 `mall_list`（可解析）         | **站斧已打开**（且已登录） | 记录 `api_port`，**跳过**杀进程与冷启动                                           |\r\n| 有 HTTP 响应体，但取不到 `mall_list` / `success=false` | 站斧进程在跑但可能未登录    | 记录 `api_port`，**禁止冷启动**；进入登录提示流程                                      |\r\n| 有 HTTP 响应但**不是**站斧 WebDriver 结构               | **非站斧占用**       | **立刻清空 `opening_malls.json`** → 杀站斧进程（勿停占用方）→ `get_available_port(首选)` 换口冷启动 |\r\n| **连接拒绝 / 超时 / 无响应**                           | **站斧未打开**       | **立刻清空 `opening_malls.json`** → 杀站斧进程 → `get_available_port(首选)`（占用则递增）→ 冷启动 |\r\n\r\n\r\n> **禁止**再用 `CheckClientOpen` 的 `LoadSuccess` / `LoadFailed` 判断站斧是否已打开。「模块 undefined 未加载」等说明该端口上**已有 HTTP 服务**；若确认为站斧 WebDriver，用正确 JSON 的 `GetBrowserList` 重发即可；若是**非站斧**服务，走 `get_available_port` 换口冷启动，**不要**停占用方、**不要**要求客户释放端口。\r\n\r\n\r\n| 场景                       | 动作                                                                                         |\r\n| ------------------------ | ------------------------------------------------------------------------------------------ |\r\n| 站斧已打开 + **打开店铺**         | **不重启**；写入 `opening_malls.json` → resolve mall_id → 已开确认 → 未开则 `OpenBrowser`               |\r\n| 站斧已打开 + **关闭店铺**         | **不重启**；resolve mall_id → `CloseBrowser` → 清理 `opening_malls.json`                         |\r\n| 站斧已打开 + 阶段 B 业务          | **不重启**；`GetBrowserWebDriver` 拿端口                                                          |\r\n| **打开站斧** / 目标端口无 HTTP 响应 | **立刻清空 `opening_malls.json`** → 查安装目录（找不到则向客户索要）→ `get_available_port(首选)` → 冷启动，写 `api_port.json` |\r\n| 客户明确要求「重启站斧」             | 允许杀进程 + `get_available_port` 冷启动（Win:`taskkill` / Mac:`killall 站斧`），**立刻清空 `opening_malls.json`** |\r\n\r\n\r\n> 复用已运行实例时，**直接**用 `GetBrowserList`（最多 **8s**）判断是否已打开/已登录。**无论冷启动还是复用，探测总耗时不超过约 8s**（不再先等 `CheckClientOpen` / `LoadSuccess`）。\r\n\r\n---\r\n\r\n## 打开意图配置 `opening_malls.json`\r\n\r\n路径：Skill 目录下 `[opening_malls.json](opening_malls.json)`（与 `SKILL.md` 同级）。\r\n\r\n用于记录客户**已发出「打开某店铺」指令**的店铺名；关店 / 关站斧时清理。OpenBrowser 前用 `GetBrowserWebDriver` **统一单次 5s** 探测（与是否已在列表无关）。\r\n\r\n```json\r\n{\r\n  \"malls\": [\"ztest126\"],\r\n  \"updated_at\": \"2026-07-14T10:00:00\"\r\n}\r\n```\r\n\r\n\r\n| 字段           | 说明                              |\r\n| ------------ | ------------------------------- |\r\n| `malls`      | 客户已下达「打开」意图、且尚未通过关店/关站斧清理的店铺名列表 |\r\n| `updated_at` | 最近一次写入时间                        |\r\n\r\n\r\n\r\n| 时机                                                         | 动作                                     |\r\n| ---------------------------------------------------------- | -------------------------------------- |\r\n| 客户发送**打开店铺 / 打开站斧打开 {店铺名}**（**仅当站斧已打开之后**拿到 `mall_name`）   | **写入**该 `mall_name`（已存在则跳过）            |\r\n| **打开站斧** / 探测到**站斧未打开**（`GetBrowserList` 无 HTTP 响应）        | **立刻清空**整个 `malls` 列表（丢弃此前写入的店铺名），再冷启动 |\r\n| 客户发送**关闭店铺 {店铺名}** 且 `CloseBrowser` 成功                     | **去掉**该 `mall_name`                    |\r\n| 客户发送**关闭站斧** / `ExitClient` / 冷启动重启站斧 / `ClearCacheFolder` | **清空**整个 `malls` 列表                    |\r\n| 清除单店缓存 `ClearCache` 成功                                     | **去掉**该店铺名                             |\r\n\r\n\r\n> `opening_malls.json` 只记店铺名，与 `mall_cache.json`（店铺 ID）无关。**禁止**在站斧未打开时写入店铺名。\r\n\r\n---\r\n\r\n## 本地店铺 ID 缓存 `mall_cache.json`\r\n\r\n路径：Skill 目录下 `[mall_cache.json](mall_cache.json)`（与 `SKILL.md` 同级）。\r\n\r\n```json\r\n{\r\n  \"mall_map\": {\r\n    \"ztest126\": \"2786463\",\r\n    \"测试WebDriver随机950317\": \"2786500\"\r\n  },\r\n  \"updated_at\": \"2026-06-24T16:30:00\"\r\n}\r\n```\r\n\r\n\r\n| 字段           | 说明                                                                         |\r\n| ------------ | -------------------------------------------------------------------------- |\r\n| `mall_map`   | 店铺名 → 店铺 ID（`mall_id`）映射；键为**客户提供的店铺名**（与 `GetMallByName` 的 `mallName` 一致） |\r\n| `updated_at` | 最近一次写入时间                                                                   |\r\n\r\n\r\n### resolve mall_id（统一查 ID 流程）\r\n\r\n凡需 `mall_id` 的操作（开/关店铺、`ClearCache`、`GetBrowserWebDriver` 等），**一律先走缓存**：\r\n\r\n```\r\n1. 读 mall_cache.json → mall_map[mall_name] 有值？\r\n   ├─ 是 → 直接用该 mall_id（跳过 GetMallByName）\r\n   └─ 否 → 调用 GetMallByName → 成功后立即写入 mall_map\r\n2. 使用 mall_id 调用后续 API\r\n3. 若后续 API 因店铺 ID 无效失败（如 CloseBrowser returnObj===false）：\r\n   → 删除 mall_map 中该 mall_name 条目\r\n   → 重新 GetMallByName 取 id 并写回缓存\r\n   → 用新 id 重试一次（仍失败则立即结束）\r\n```\r\n\r\n\r\n| 时机                                                                    | 动作                                                             |\r\n| --------------------------------------------------------------------- | -------------------------------------------------------------- |\r\n| 开/关店铺、清缓存、取 WebDriver 等需 `mall_id`                                    | **先读** `mall_cache.json`；命中则**跳过** `GetMallByName`             |\r\n| 缓存未命中                                                                 | `GetMallByName` 成功后**立即写入** `mall_map`                         |\r\n| `GetBrowserList`（登录探测或客户查列表）                                          | 将 `mall_list` 中每条 `mall_name` → `mall_id` **批量写入**缓存（已有且相同则跳过） |\r\n| `CreateBrowser` 成功后                                                   | 等待同步 → `GetMallByName` → 写入缓存                                  |\r\n| 使用缓存 id 调用 `CloseBrowser` / `OpenBrowser` / `GetBrowserWebDriver` 等失败 | **删除**该条缓存 → `GetMallByName` 刷新 → 写回 → **仅重试一次**               |\r\n\r\n\r\n> **注意**：`mall_cache.json` 记录的是店铺 ID，与站斧「清除店铺缓存」(`ClearCache`) 无关；清浏览器缓存**不要**清空 `mall_cache.json`。\r\n\r\n---\r\n\r\n## 已打开店铺的确认（OpenBrowser 前）\r\n\r\n客户要求**打开**某店铺时：\r\n\r\n1. **立刻**将 `mall_name` 写入 `opening_malls.json`（见「打开意图配置」；站斧须已打开）\r\n2. resolve mall_id 拿到 `mall_id`\r\n3. **先**调 `GetBrowserWebDriver` 判断目标店铺是否已打开——**只请求一次，超时固定 5 秒**\r\n\r\n```json\r\n{\"action\": \"GetBrowserWebDriver\", \"module\": \"WebDriverModule\", \"browserId\": \"3514488\"}\r\n```\r\n\r\n> **`browserId` 必须为字符串**（如 `\"3514488\"`），**禁止**传 JSON 数字。\r\n\r\n**判定已打开**：5s 内 `returnObj.success == true` 且 `WebDriverPort` 有值。\r\n\r\n### 探测规则（一律单次 5s，禁止加长或重试）\r\n\r\n\r\n| 步骤                     | 规则                                                                              |\r\n| ---------------------- | ------------------------------------------------------------------------------- |\r\n| 次数 / 超时                | **只请求 1 次**，HTTP `timeout=5`；**禁止**先用 15s 再探测、**禁止**连打第二次                       |\r\n| 5s 内拿到端口               | 按「已打开」处理（询问是否关闭）                                                                |\r\n| **5s 超时 / 连接异常 / 无端口** | **视为未开**，**不要结束流程**，**直接 `OpenBrowser`** → 等 10s → 再 `GetBrowserWebDriver`（取端口） |\r\n\r\n\r\n\r\n| 情况                         | 动作                                                                                                                                   |\r\n| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |\r\n| 目标店铺**未打开**（含探测 **5s 超时**） | 直接 `OpenBrowser` → 等 10s → `GetBrowserWebDriver`                                                                                     |\r\n| 目标店铺**已打开**                | **必须先询问客户**：「店铺 {mall_name} 已打开（WebDriverPort={port}），是否需要关闭店铺？」                                                                     |\r\n| 客户确认**需要关闭**               | `CloseBrowser` → 从 `opening_malls.json` 去掉该名 → 确认关闭成功后，再询问是否重新 `OpenBrowser`；确认后再写入配置并 `OpenBrowser` → 等 10s → `GetBrowserWebDriver` |\r\n| 客户确认**不需要关闭** / 继续使用当前店铺   | **跳过** `OpenBrowser` 与 `CloseBrowser`，直接用现有 `WebDriverPort` 进入阶段 B 或结束                                                               |\r\n| 客户未明确表态                    | **不得**擅自 `OpenBrowser` 或 `CloseBrowser`，等待客户回复                                                                                       |\r\n\r\n\r\n**禁止**：\r\n\r\n- 检测到店铺已打开仍静默调用 `OpenBrowser`（会干扰客户当前页面）\r\n- 检测到店铺已打开未经确认就调用 `CloseBrowser`\r\n- OpenBrowser 前因 `GetBrowserWebDriver` **超时**而整流程失败退出（应改走 `OpenBrowser`）\r\n- OpenBrowser 前对 `GetBrowserWebDriver` **重试或拉长超时**（整体只许 **1 次 × 5s**）\r\n\r\n**与客户说「关闭店铺」的区别**：客户**明确说关闭**且 HTTP 正常 → 直接 `CloseBrowser` 并清理 `opening_malls.json`，无需再问是否关闭；客户**说打开**但检测到已开 → 才须询问是否关闭。\r\n\r\n---\r\n\r\n## 启动站斧（阶段 A · 仅冷启动时）\r\n\r\n**仅当** 目标端口无 HTTP 响应，或端口上是**非站斧 WebDriver** 服务时，才执行：\r\n\r\n1. **立刻清空 `opening_malls.json`**（打开站斧命令检测到未打开时必须清理已写入的店铺名）\r\n2. 杀进程（按 OS；**只杀站斧，不要停掉占用端口的其他服务**）：\r\n\r\n**Windows**：\r\n\r\n```bat\r\ntaskkill /f /t /im 站斧.exe\r\n```\r\n\r\n**macOS**：\r\n\r\n```bash\r\nkillall 站斧\r\n```\r\n\r\n杀进程后**最多等 1s**（可用短轮询看进程是否消失）；进程已退出则**立刻**继续，**禁止**固定干等 3s。\r\n\r\n3. **分配空闲端口**（判定站斧未打开后必做）：`api_port = get_available_port(首选)`（首选 = `api_port.json` 的 `api_port` 或默认 `12678`）；用 `socket.bind((\"127.0.0.1\", port))` 探测——**能 bind = 空闲**；失败则 `port += 1` 继续。12678 被占用则自动用 12679…，**禁止**因此停下来要求客户释放端口，**禁止**盲扫 8081/8082。\r\n4. 再以 WebDriver 参数启动（见上文接口清单；**Win/Mac 均四项缺一不可、禁止减少**；**macOS 用 `open -a`，同样带 `--multip`**），`--httpport=` 用上一步分配的端口。\r\n5. 启动后**立刻**轮询 `GetBrowserList`（对**实际端口**，间隔 **0.5s**，总计最多 **8s**），端口/列表就绪即继续；**禁止**启动后再固定 sleep 再探测。\r\n6. **8s 内仍无 WebDriver 通讯** → **立即停止、禁止重试**，按「通讯失败对客户话术」提示客户。\r\n\r\n### 通讯失败对客户话术（冷启动后 8s 内无 WebDriver 通讯 · 必须原样）\r\n\r\n冷启动后轮询 `GetBrowserList` **总计 8s 仍无 HTTP 响应 / 未能建立 WebDriver 通讯**时：\r\n\r\n- **立即停止**，**禁止**重复尝试、换端口、再冷启动\r\n- **必须**向客户报告以下模板（`{install_path}` 换成已确认路径，如 `I:\\ZhanFu\\站斧.exe` 或 `/Applications/站斧.app`）：\r\n\r\n```\r\n站斧启动后 8 秒内未能建立 WebDriver 通讯，已按技能规则停止操作，未重复尝试。\r\n安装位置已确认：{install_path}。请确认站斧版本要求（Windows ≥ 5.2.12，macOS > 5.2.10）无误；若电脑因卡顿导致启动有延迟，可尝试再次打开站斧，请告诉我“打开站斧”。\r\n```\r\n\r\n**禁止**再说「请先手动打开站斧并确认版本为 WebDriver 版且不低于 5.2.12」；版本提醒**一律**写：**Windows ≥ 5.2.12，macOS > 5.2.10**。\r\n\r\n### 查找站斧（冷启动前 · 禁止全盘搜索）\r\n\r\n**必须按顺序、逐项尝试，命中即停**；**禁止** `where.exe` / `mdfind` 全盘扫、递归 glob、跨盘符搜索、翻代码库猜路径。\r\n\r\n#### Windows\r\n\r\n\r\n| 顺序  | 方式                                                    | 说明                                             |\r\n| --- | ----------------------------------------------------- | ---------------------------------------------- |\r\n| 0   | `**api_port.json` 的 `install_dir`**                   | 验证 `{install_dir}\\站斧.exe` 存在则直接使用；不存在则**跳过**   |\r\n| 1   | 桌面「站斧」快捷方式                                            | **仅**按文件名匹配含「站斧」的 `.lnk`，解析其 `TargetPath` 所在目录 |\r\n| 2   | `C:\\Users\\{用户名}\\AppData\\Local\\Programs\\ZhanFu\\站斧.exe` | `{用户名}` 取当前 Windows 登录名                        |\r\n| 3   | `C:\\Program Files\\ZhanFu\\站斧.exe`                      | 固定路径                                           |\r\n| 4   | **向客户索要**                                             | 提示：「未找到站斧安装目录，请提供站斧安装路径（含 站斧.exe 的文件夹）」        |\r\n\r\n\r\n#### macOS\r\n\r\n\r\n| 顺序  | 方式                                  | 说明                                                             |\r\n| --- | ----------------------------------- | -------------------------------------------------------------- |\r\n| 0   | `**api_port.json` 的 `install_dir`** | 验证为存在的 `站斧.app`（或目录内含 `站斧.app`）则直接使用；无效则**跳过**                 |\r\n| 1   | `/Applications/站斧.app`              | 系统 Applications                                                |\r\n| 2   | `~/Applications/站斧.app`             | 用户 Applications                                                |\r\n| 3   | **向客户索要**                           | 提示：「未找到站斧.app，请提供路径（如 /Applications/站斧.app）」；**禁止**全盘 `mdfind` |\r\n\r\n\r\n**任一顺序命中后**：立即把该路径写入 `api_port.json` 的 `install_dir`，再冷启动。\r\n\r\n**客户提供路径后**：\r\n\r\n- Windows：仅检查 `{folder_path}\\站斧.exe` 是否存在\r\n- macOS：仅检查路径为 `站斧.app` 或目录内含 `站斧.app`\r\n\r\n验证通过后**写入** `install_dir`；不存在则**立即结束**并再次提示路径无效。\r\n\r\n#### 快捷方式解析规则（Windows 顺序 1 · 只查名为「站斧」的快捷方式）\r\n\r\n**只查找快捷方式文件名中含「站斧」的 `.lnk`**，**禁止**遍历桌面全部快捷方式，**禁止**解析文件名不含「站斧」的 `.lnk`（无论其目标 exe 名称为何）。\r\n\r\n查找范围：当前用户桌面 + 公共桌面（`Desktop`、`Public\\Desktop`）。\r\n\r\n**文件名匹配**（按序尝试，解析到有效 `站斧.exe` 即停）：\r\n\r\n1. 精确名：`站斧.lnk`、`站斧浏览器.lnk`\r\n2. 通配：`*站斧*.lnk`（**仅**文件名包含「站斧」者，如 `站斧浏览器完成版.lnk`）\r\n\r\n对每个命中的 `.lnk`：\r\n\r\n1. 解析 `TargetPath`（PowerShell `WScript.Shell.CreateShortcut` 或等价方式）\r\n2. 取目标文件所在目录为 `install_dir`\r\n3. 若 `TargetPath` 本身为 `站斧.exe` → 直接使用\r\n4. 否则检查 `{install_dir}\\站斧.exe`；存在则使用\r\n\r\n全部快捷方式均未解析出 `站斧.exe` → 进入顺序 2（固定安装路径），**不得**改用其他命名规则的快捷方式兜底。\r\n\r\n---\r\n\r\n## 阶段 A 操作要点（HTTP only，失败即停）\r\n\r\n### GetBrowserList（判断站斧是否已打开 + 登录态 · 必做 · 总计最多 8s）\r\n\r\n**禁止**用 `CheckClientOpen` / `LoadSuccess` / `LoadFailed` 判断站斧是否已打开。冷启动或复用后**直接**轮询 `GetBrowserList`：\r\n\r\n```json\r\n{\"action\": \"GetBrowserList\", \"module\": \"WebDriverModule\", \"args\": \"{\\\"page\\\":1,\\\"limit\\\":20}\"}\r\n```\r\n\r\n- **轮询** `GetBrowserList`，间隔 **0.5s**，**总计最多 8s**\r\n- `returnObj.success == true` **且** `returnObj.data.mall_list` 可解析（非 `null`）→ **站斧已打开且已登录**，**禁止**无故调用 `Login`；**同时将 `mall_list` 中 `mall_name` → `mall_id` 写入 `mall_cache.json`**\r\n- 有 HTTP 响应但 **8s 内**仍 `success=false`、`data=null`、无法解析 `mall_list` → **停止**，提示客户：**「站斧未登录，请提供账号和密码」**；拿到凭证后再 `Login`（**禁止**因此冷启动）\r\n- 连接拒绝 / 无响应 → **站斧未打开**，走冷启动\r\n- 客户未提供账号密码 → **停止**，不猜测、不擅自登录\r\n- **单次请求** `timeout=1.5`；Agent **只用 Python requests**，禁止为通断探测切换 PowerShell/curl\r\n\r\n> `CheckClientOpen` **不再作为流程步骤**；勿等待 `LoadSuccess`。\r\n\r\n### Login\r\n\r\n仅在 `GetBrowserList` 表明未登录且**客户已提供**账号密码时调用；`isboss` **固定** `true`。**禁止**使用内测或历史会话中的账号。`success != true` → **立即结束**。\r\n\r\n### GetMallByName / resolve mall_id / CreateBrowser\r\n\r\n**resolve mall_id**：先读 `mall_cache.json`；未命中才调 `GetMallByName`，成功后立即写缓存。\r\n\r\n任一步 `GetMallByName` / `CreateBrowser` 的 `success != true` 或缺字段 → **立即结束**，不重试（缓存 id 导致后续 API 失败时的**一次**刷新重试除外，见「本地店铺 ID 缓存」）。\r\n\r\n### UpdateAccount（修改店铺账号密码）\r\n\r\n客户要求**修改店铺登录账号/密码**时调用。须站斧已打开且已登录；先 resolve `mall_id`，再：\r\n\r\n```json\r\n{\r\n  \"action\": \"UpdateAccount\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"3514488\",\r\n  \"args\": \"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"cyt123456A\\\"}\"\r\n}\r\n```\r\n\r\n\r\n| 字段 | 必填 | 说明 |\r\n| ---- | --- | ---- |\r\n| `browserId` | 是 | 店铺 `mall_id`（**必须为字符串**） |\r\n| `args.username` | 否 | 店铺账号（对应 `mall_account`；可空字符串） |\r\n| `args.password` | 否 | 店铺密码（对应 `mall_password`；可空字符串） |\r\n\r\n\r\n- 缺少店铺名/`mall_id` 或客户未说明要改的账号/密码时 → **先询问**，禁止猜测\r\n- `returnObj.success != true` → **立即结束**，原样报告 `returnObj.msg`（如「缺少 browserId」）\r\n- 成功：`success == true`（`data` 可为 `{}`）\r\n\r\n### OpenBrowser（须先过「已打开店铺确认」）\r\n\r\n```json\r\n{\"action\": \"OpenBrowser\", \"module\": \"WebDriverModule\", \"browserId\": \"3514488\", \"args\": \"{\\\"isDownLoadConfirm\\\":false,\\\"isOpenMallIndex\\\":true,\\\"isSwitchDynamicNetwork\\\":false}\"}\r\n```\r\n\r\n- **`browserId` 必须是字符串**（`\"3514488\"`），**禁止**数字 `3514488`\r\n- **仅站斧已打开后**再写入 `opening_malls.json`（探测未打开时已清空，禁止未打开就写入）\r\n- 目标店铺**未打开**（含 OpenBrowser 前探测 **5s 超时**）→ 可直接 `OpenBrowser`\r\n- 目标店铺**已打开**（客户要求**打开**该店）→ 须先询问客户**是否需要关闭店铺**；确认关闭后再视情况 `CloseBrowser` / `OpenBrowser`（见「已打开店铺的确认」）\r\n- 客户**明确说关闭店铺**且 HTTP 正常 → 直接 `CloseBrowser`，清理 `opening_malls.json`，**不重启**站斧\r\n- `OpenBrowser` 本身 `returnObj !== true` 或 `ret != 200` → **立即结束**，并**提醒客户**：\r\n  > **打开店铺失败，请确认该店铺是否已绑定 IP / 设备。** 可在站斧客户端查看店铺绑定设备后再试。\r\n- `OpenBrowser` **之后**的 `GetBrowserWebDriver` 失败（含「超时未获取到」）→ 同上，**一并提醒检查 IP/设备绑定**；并提醒客户：**首次使用请先在站斧客户端手动打开该店铺以下载内核；不同内核的店铺需分别手动打开一次**\r\n\r\n### GetBrowserWebDriver\r\n\r\n```json\r\n{\"action\": \"GetBrowserWebDriver\", \"module\": \"WebDriverModule\", \"browserId\": \"3514488\"}\r\n```\r\n\r\n- **`browserId` 必须是字符串**（`\"3514488\"`），**禁止**数字 `3514488`\r\n- **OpenBrowser 前探测（是否已开）**：**只请求 1 次，`timeout=5`**；超时/无端口 → **仍 `OpenBrowser`**；禁止重试、禁止加长超时\r\n- **OpenBrowser 后取端口**：`WebDriverPort` 为空或请求失败 → **立即结束**（禁止循环重试、禁止「再等一会」方案）\r\n- `OpenBrowser` 后允许**单次**固定等待 10s 再调 `GetBrowserWebDriver`（不算重试）；若仍失败则结束。\r\n- **macOS 内核检查（拿到端口后、进入阶段 B 前必做）**：若当前 OS 为 **macOS**，且 `returnObj.KernalNumber` 存在且 **≤ 130** → **立即停止**，**禁止** `connect_over_cdp` / 页面自动化，按下方「macOS 低内核对客户话术」提示客户；**Windows 不校验此限制**。复用已开店铺（客户确认不关闭、直接用现有端口）时同样要检查 `KernalNumber`。\r\n\r\n### macOS 低内核对客户话术（KernalNumber ≤ 130 · 必须原样）\r\n\r\n当 **macOS** 且打开店铺后 `GetBrowserWebDriver` 返回 `KernalNumber ≤ 130`（含已打开店铺复用端口的场景）时：\r\n\r\n- **立即停止**，**禁止**进入阶段 B，**禁止**代客户改内核或自动重启站斧\r\n- **必须**向客户报告以下模板（`{kernel}` 换成实际 `KernalNumber`，`{mall_name}` 换成店铺名）：\r\n\r\n```\r\n当前为 macOS，店铺 {mall_name} 的内核为 {kernel}（≤130），暂不支持自动化。\r\n请将该店铺切换到 130 以上内核；若无权限请让主账号切换。切换完成后请您手动重启站斧，再告诉我继续。\r\n```\r\n\r\n---\r\n\r\n## 阶段 B：Playwright CDP（端口拿到后）\r\n\r\n> **macOS**：进入本节前须已确认 `KernalNumber > 130`；否则不得 `connect_over_cdp`。\r\n```python\r\nfrom headed_mode import ensure_headed_mode\r\nfrom playwright.sync_api import sync_playwright\r\n\r\nensure_headed_mode()\r\nbrowser = sync_playwright().start().chromium.connect_over_cdp(\r\n    f\"http://127.0.0.1:{webdriver_port}\"\r\n)\r\n```\r\n\r\n连接失败 → **立即结束**，禁止换系统浏览器替代。\r\n\r\n### 设备安全检测\r\n\r\n找 URL 含 `check.html` 的标签页，**15s 内**轮询，满足以下**任一**条件即视为检测通过：\r\n\r\n1. **「打开店铺」按钮未禁用**（`.openMallOpenBtn`，且非 `disabled` / `aria-disabled=true` / `is-disabled`）\r\n2. **标签页数量 ≥ 2**（通常表示店铺页已打开）\r\n\r\n15s 内仍不满足 → 告知「没检测成功无法进行自动化」，立即结束。\r\n\r\n可运行 Skill 内置（**仅阶段 B**）：\r\n\r\n```bash\r\npython scripts/check_device_security.py --port {webdriver_port} --wait --timeout 15\r\n```\r\n\r\n### 业务自动化\r\n\r\n检测通过后，按客户需求用 Playwright 操作页面。**禁止**在 Skill 目录新增业务脚本；临时逻辑在对话中执行，不落盘为 `.py`。\r\n\r\n---\r\n\r\n## 收尾（阶段 A · HTTP）\r\n\r\n**关闭店铺**（客户明确要求时）：\r\n\r\n```json\r\n{\"action\": \"CloseBrowser\", \"module\": \"WebDriverModule\", \"browserId\": \"3514488\"}\r\n```\r\n\r\n成功后**从 `opening_malls.json` 去掉该 `mall_name`**。\r\n\r\n**退出站斧客户端**（仅客户明确要求「退出站斧」时；开/关店铺**不要**顺带调用）：\r\n\r\n```json\r\n{\"action\": \"ExitClient\", \"module\": \"WebDriverModule\", \"args\": \"\"}\r\n```\r\n\r\n成功后（或冷启动重启前）**清空 `opening_malls.json`**。\r\n\r\n---\r\n\r\n## 失败处理（统一）\r\n\r\n\r\n| 情况                                                 | 动作                                                                                                                  |\r\n| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |\r\n| 目标端口无 HTTP 响应 / **打开站斧且站斧未打开**                     | **立刻清空 `opening_malls.json`** → 查安装目录（快捷方式/常见目录找不到则向客户索要）→ **`get_available_port(首选)`（占用则递增）** → 冷启动并写 `api_port.json`；冷启动后 **8s 仍无通讯** → 按「通讯失败对客户话术」报告（版本无误且卡顿可延迟时可再试，请客户说「打开站斧」） |\r\n| `GetBrowserList` 能取到数据 + **打开店铺**                  | **站斧已打开，不重启**；写入 `opening_malls.json` → HTTP 开店铺流程                                                                  |\r\n| `GetBrowserList` 能取到数据 + **关闭店铺**                  | **不重启**；resolve mall_id → `CloseBrowser` → 清理 `opening_malls.json`                                                  |\r\n| API 已运行 + 开新店铺                                     | **不重启**站斧，直接 HTTP 开店铺                                                                                               |\r\n| 目标店铺已打开（客户要求**打开**）                                | **询问客户**是否需要关闭店铺；未确认不调用 `OpenBrowser` / `CloseBrowser`                                                              |\r\n| OpenBrowser 前 `GetBrowserWebDriver` **5s 超时**      | **不结束**；继续 `OpenBrowser`（只许探测 1 次）                                                                                  |\r\n| 客户明确要求关闭已开店铺                                       | 直接 `CloseBrowser` → 清理 `opening_malls.json`                                                                         |\r\n| 客户明确要求关闭站斧                                         | `ExitClient` → **清空** `opening_malls.json`                                                                          |\r\n| GetBrowserList 8s 内仍无法确认登录（**确认为站斧** WebDriver 有响应） | **停止**，提示客户提供账号密码；**禁止**擅自或内测账号 Login；**禁止**用 `LoadSuccess` 判断。若其实是非站斧占用，应走空闲端口冷启动而非要密码 |\r\n| OpenBrowser / OpenBrowser 后 GetBrowserWebDriver 失败 | 立即结束；`OpenBrowser` 以 `returnObj===true` 判成功；提醒检查 **IP/设备绑定** 及 **是否已手动打开该店铺下载内核**（版本要求：Windows ≥ 5.2.12，macOS > 5.2.10）                     |\r\n| **macOS** 且 `KernalNumber ≤ 130`（打开/复用店铺后） | **立即停止**；按「macOS 低内核对客户话术」提示：切换到 **130 以上**内核或请**主账号**切换，并请客户**手动重启站斧**后再继续；**禁止**阶段 B |\r\n| CloseBrowser 返回 `returnObj===false`                | 立即结束，报告关闭失败                                                                                                         |\r\n| 其他关键 API 失败                                        | 立即结束，原样报告 `returnObj.msg`（`OpenBrowser`/`CloseBrowser` 无 `msg` 时报告 `returnObj` 值）                                   |\r\n| OpenBrowser 后拿不到 WebDriverPort                     | 立即结束，不 retry                                                                                                        |\r\n| 设备安全检测 15s 超时                                      | 立即结束，告知「没检测成功无法进行自动化」                                                                                               |\r\n\nFile v1.0.6:_meta.json\n\n{\n  \"ownerId\": \"kn79xm4hxd563stv6msvy8bvn98ae9jy\",\n  \"slug\": \"zhanfu-playwright\",\n  \"version\": \"1.0.6\",\n  \"publishedAt\": 1788402151903\n}\n\nFile v1.0.6:scripts/requirements.txt\n\nplaywright>=1.40.0\r\nrequests>=2.28.0\n\nFile v1.0.6:reference.md\n\n# 站斧 WebDriver API 参考\r\n\r\n> 模块固定为 `WebDriverModule`，通过 HTTP 服务调用。本文与官方《站斧 WebDriver 接口文档》对齐。\r\n\r\nHTTP 入口：`POST http://127.0.0.1:{api_port}`，Body 为 JSON。\r\n\r\n**默认 API 端口**：`12678`（优先）。Skill 目录 [`api_port.json`](api_port.json) 记录上次成功端口与安装目录；任务开始先探测该端口（用 `GetBrowserList`，**禁止**用 `LoadSuccess` 判断）。无响应或被非站斧占用 → 空闲端口冷启动并写回；**禁止**盲扫 8081/8082 碰已运行站斧；**禁止**因 12678 被占用而要求客户先释放。\r\n\r\n> **识别非站斧占用**：POST `GetBrowserList` 后若响应不是 `WebDriverModule` 结构（如「Electron 本地打包控制台」），视为其他服务占用 → 换空闲端口冷启动，**勿**停止占用方。\r\n\r\n**店铺 ID 缓存**：Skill 目录 [`mall_cache.json`](mall_cache.json) 记录 `mall_name` → `mall_id` 映射。需要 `mall_id` 时**先读缓存**，未命中再 `GetMallByName` 并写回；`GetBrowserList` 返回的 `mall_list` 亦应批量写入缓存。\r\n\r\n**打开意图配置**：Skill 目录 [`opening_malls.json`](opening_malls.json) 记录客户已下达「打开」指令的店铺名。关店 / 关站斧时清理。OpenBrowser 前用 `GetBrowserWebDriver` **只请求 1 次、超时 5s**；超时仍执行 `OpenBrowser`。\r\n\r\n**请求方式**：阶段 A **优先 Python `requests`（`timeout=1.5`）**；**禁止**为同一探测在 PowerShell/curl/Python 间换工具试错；**禁止** Windows `curl` 手工转义 JSON。\r\n\r\n## 通用约定\r\n\r\n### 请求结构\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `action` | 接口动作名 |\r\n| `module` | 固定为 `WebDriverModule` |\r\n| `args` | JSON 字符串，承载业务参数 |\r\n| `browserId` | 部分接口需要的店铺 ID（与 `mall_id` 相同）；**必须为 JSON 字符串**（如 `\"3514488\"`），**禁止**传数字 |\r\n\r\n### 响应结构\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `ret` | HTTP 分发状态码：`200` 表示请求已正常分发处理；`400` / `500` 表示异常请求或框架级错误 |\r\n| `returnObj` | 业务返回值；结构因接口而异 |\r\n| `action` | 回显请求动作 |\r\n| `module` | 回显请求模块 |\r\n\r\n框架级错误示例（`ret=500`）：\r\n\r\n```json\r\n{\r\n  \"ret\": 500,\r\n  \"error\": \"未找到方法\",\r\n  \"action\": \"XXX\",\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n### 业务成功判断\r\n\r\n| 返回类型 | 判断方式 |\r\n|----------|----------|\r\n| `{ success, msg, ... }` | 以 `returnObj.success` 为准（如 `Login`、`GetMallByName`、`UpdateAccount`、`GetBrowserWebDriver`） |\r\n| `true` / `false` | 如 `OpenBrowser`：成功 `returnObj === true`，失败 `returnObj === false` |\r\n| `null` | 如 `CloseBrowser`、`ExitClient` 成功时 `returnObj` 为 `null`；`CloseBrowser` 失败时 `returnObj === false` |\r\n\r\n### 典型调用流程\r\n\r\n```\r\nLogin → SetInstallPlugins（可选，仅 Windows）→ GetBrowserList / GetMallByName → CreateBrowser（可选）\r\n→ SetDownLoadPath（可选，仅 Windows）→ GetWebDriver（Selenium 可选，Playwright 跳过）\r\n→ OpenBrowser → GetBrowserWebDriver → 自动化操作\r\n→ CloseBrowser → ExitClient（结束）\r\n```\r\n\r\n> **macOS 暂不支持**：`SetDownLoadPath`、`ClearCacheFolder`、`ClearCache`、`SetInstallPlugins`。Agent 不得在 Mac 上调用这些 action。\r\n>\r\n> **macOS 内核**：`KernalNumber ≤ 130` 的店铺**不支持**自动化；须提示切换到 130 以上内核（或主账号切换）并让客户**手动重启站斧**。\r\n\r\n## 启动站斧\r\n\r\n**Windows**（**四项缺一不可，禁止减少/省略任一参数**）：\r\n\r\n```\r\n站斧.exe --multip --run_type=web_driver --ipc_type=http --httpport={api_port}\r\n```\r\n\r\n| 参数 | 可否省略 |\r\n|------|----------|\r\n| `--multip` | **否** |\r\n| `--run_type=web_driver` | **否** |\r\n| `--ipc_type=http` | **否** |\r\n| `--httpport={api_port}` | **否**（值可变，键不可少） |\r\n\r\n**macOS**（**四项缺一不可，禁止减少/省略任一参数**，与 Windows 相同；用 `open -a` 启动）：\r\n\r\n```\r\nopen -a /Applications/站斧.app --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}\r\n```\r\n\r\n也可：`open -a 站斧 --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}`\r\n\r\n| 参数 | 可否省略 |\r\n|------|----------|\r\n| `--multip` | **否** |\r\n| `--run_type=web_driver` | **否** |\r\n| `--ipc_type=http` | **否** |\r\n| `--httpport={api_port}` | **否**（值可变，键不可少） |\r\n\r\n`{api_port}` = `get_available_port(首选)`，首选默认 `12678`（占用则递增）。\r\n\r\n关闭旧进程：\r\n\r\n- Windows：`taskkill /f /t /im 站斧.exe`\r\n- macOS：`killall 站斧`\r\n\r\n- **禁止减少启动参数**（Windows / macOS 均不得去掉 `--multip` / `--run_type` / `--ipc_type` / `--httpport` 任一）\r\n- `run_type` 必须为 `web_driver`\r\n- `ipc_type` 必须为 `http`\r\n- 冷启动端口写入 Skill 目录 `api_port.json`\r\n\r\n### 查找站斧（冷启动前）\r\n\r\n**先读** `api_port.json` 的 `install_dir`，验证有效则直接用；无效再按 OS 顺序尝试，命中即停；**禁止**全盘搜索。\r\n\r\n#### Windows\r\n\r\n0. **`api_port.json` 的 `install_dir`**（本地缓存，优先；验证 `{install_dir}\\站斧.exe`）\r\n1. **桌面快捷方式（仅文件名含「站斧」）**：在用户桌面与公共桌面查找 `站斧.lnk`、`站斧浏览器.lnk`、`*站斧*.lnk`；解析 `TargetPath` 所在目录，取该目录下 `站斧.exe`（或目标本身即为 `站斧.exe`）。**不得**解析文件名不含「站斧」的快捷方式。\r\n2. `%LOCALAPPDATA%\\Programs\\ZhanFu\\站斧.exe`\r\n3. `C:\\Program Files\\ZhanFu\\站斧.exe`\r\n4. **向客户索要** `folder_path`：**快捷方式与常见目录均未命中时必须停止询问客户**，禁止猜路径或全盘搜索\r\n\r\n#### macOS\r\n\r\n0. **`api_port.json` 的 `install_dir`**（须为存在的 `站斧.app`，或目录内含 `站斧.app`）\r\n1. `/Applications/站斧.app`\r\n2. `~/Applications/站斧.app`\r\n3. **向客户索要** `.app` 路径；**禁止**全盘 `mdfind` / `find`\r\n\r\n**任一顺序命中后**：立即写入 `api_port.json` 的 `install_dir`。客户提供路径后按 OS 验证再写入。\r\n\r\n## 端口探测（阶段 A 第一步）\r\n\r\n1. 读 `api_port.json` 的 `api_port`；无文件则用 `12678`\r\n2. 对该端口 POST `GetBrowserList`（正确 JSON，单次）\r\n3. **确认为站斧 WebDriver** 且能取到 `mall_list` → **站斧已打开**，复用，刷新 `api_port.json`\r\n4. **确认为站斧 WebDriver** 但取不到 `mall_list` → 可能未登录；**禁止冷启动**，走登录提示\r\n5. **非站斧 HTTP**（如 Electron 控制台）或 **连接拒绝/超时** → **立刻清空 `opening_malls.json`** → 查安装路径 → 杀站斧进程（勿停占用方）→ **`get_available_port(首选)` 空闲端口冷启动** → 写 `api_port.json`\r\n\r\n> **禁止**用 `CheckClientOpen` / `LoadSuccess` / `LoadFailed` 判断站斧是否已打开。\r\n> **禁止**因 12678 被占用而要求客户先停掉其他服务。\r\n\r\n## 打开店铺 / 关闭店铺（HTTP 正常则不重启）\r\n\r\n> **同义**：「战斧」=「站斧」。客户发「打开战斧 / 关闭战斧 / 重启战斧」按「打开站斧 / 关闭站斧 / 重启站斧」执行。\r\n\r\n| 客户意图 | `GetBrowserList` 确认为站斧 / 有响应 | 动作 |\r\n|----------|--------------------------------------|------|\r\n| 打开店铺 | 是（站斧 WebDriver） | **不重启**；写入 `opening_malls.json` → resolve mall_id → `GetBrowserWebDriver` **单次 5s** 判是否已开（超时仍 `OpenBrowser`）→ 已开则询问是否关闭 → 未开则 `OpenBrowser` |\r\n| 关闭店铺 | 是 | **不重启**；resolve mall_id → `CloseBrowser` → 从 `opening_malls.json` 去掉该店；**勿**调用 `ExitClient`（除非客户明确要求退出站斧） |\r\n| 关闭站斧 / 关闭战斧 | — | `ExitClient` → **清空** `opening_malls.json` |\r\n| **打开站斧** / **打开战斧** | 否（无响应或非站斧占用） | **立刻清空 `opening_malls.json`** → 查安装目录 → **空闲端口**冷启动 → 站斧就绪后再写店铺名/开店 |\r\n| 打开 / 关闭 | 否（无响应或非站斧占用） | **立刻清空 `opening_malls.json`** → 空闲端口冷启动后再走上述 HTTP 流程 |\r\n\r\n**已打开 + 客户要求打开**：询问「是否需要关闭店铺？」；确认关闭 → `CloseBrowser` → 清理配置 → 再视客户意愿 `OpenBrowser`。\r\n\r\n**客户明确要求关闭**：直接 `CloseBrowser` 并清理 `opening_malls.json`，无需再问。\r\n\r\n## CheckClientOpen（已弃用为运行态判断）\r\n\r\n**不再用于判断站斧是否已打开**。流程以 `GetBrowserList` 能取到数据为准。接口仍可能存在于客户端，但 Agent **勿**依赖其 `LoadSuccess` / `LoadFailed`。\r\n\r\n```json\r\n{\"action\": \"CheckClientOpen\", \"module\": \"WebDriverModule\"}\r\n```\r\n\r\n## GetBrowserList\r\n\r\n**判断站斧是否已打开 + 登录态探测（阶段 A 必调）**：冷启动或复用后**直接**调用；**轮询总计最多 8s**。`returnObj.success == true` 且 `returnObj.data.mall_list` 可解析 → **站斧已打开且已登录**；有站斧 HTTP 响应但取不到数据 → 未登录，**停止**并提示客户提供账号密码（禁止因此冷启动）；无 HTTP 响应或非站斧占用 → 站斧未打开，空闲端口冷启动。\r\n\r\n**也可用于客户「查看店铺列表」**：按 `page` / `limit` 分页返回账号下店铺。\r\n\r\n请求：\r\n\r\n```json\r\n{\r\n  \"action\": \"GetBrowserList\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"page\\\":1,\\\"limit\\\":10}\"\r\n}\r\n```\r\n\r\n| args 字段 | 说明 |\r\n|-----------|------|\r\n| `page` | 页码，从 1 开始 |\r\n| `limit` | 每页店铺数量 |\r\n\r\n响应示例：\r\n\r\n```json\r\n{\r\n  \"action\": \"GetBrowserList\",\r\n  \"ret\": 200,\r\n  \"returnObj\": {\r\n    \"success\": true,\r\n    \"data\": {\r\n      \"total\": 669,\r\n      \"page_count\": 67,\r\n      \"mall_list\": [\r\n        {\r\n          \"mall_id\": 2786463,\r\n          \"mall_name\": \"测试WebDriver随机950317\",\r\n          \"platform_name\": \"自定义平台\",\r\n          \"ip_address\": \"ip\",\r\n          \"created_at\": \"2025-12-25 17:49:55\",\r\n          \"updated_at\": \"2025-12-25 17:49:55\"\r\n        }\r\n      ]\r\n    },\r\n    \"msg\": \"\"\r\n  },\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n| 响应字段 | 说明 |\r\n|----------|------|\r\n| `data.total` | 店铺总数 |\r\n| `data.page_count` | 总页数 |\r\n| `mall_list[].mall_id` | 店铺 ID |\r\n| `mall_list[].mall_name` | 店铺名称 |\r\n| `mall_list[].platform_name` | 平台名称 |\r\n| `mall_list[].ip_address` | 绑定 IP |\r\n| `mall_list[].created_at` / `updated_at` | 创建/更新时间 |\r\n\r\n## Login\r\n\r\n登录或切换账号。**会关闭所有已打开店铺**；若当前已登录目标账号，无需重复调用。`GetBrowserList` 已成功时勿重复调用。\r\n\r\n仅使用**客户提供的**账号密码；`isboss` **固定** `true`（老板账号）。**禁止**在 Skill 或脚本中写入内测/示例账号。\r\n\r\n请求：\r\n\r\n```json\r\n{\r\n  \"action\": \"Login\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"***\\\",\\\"isboss\\\":true}\"\r\n}\r\n```\r\n\r\n响应：`returnObj.success`、`returnObj.msg`\r\n\r\n## GetMallByName\r\n\r\n按店铺名称查 `mall_id`。**仅在 `mall_cache.json` 未命中时调用**；成功后立即写入缓存。\r\n\r\n```json\r\n{\r\n  \"action\": \"GetMallByName\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"mallName\\\":\\\"WebDriverTest\\\"}\"\r\n}\r\n```\r\n\r\n| args 字段 | 说明 |\r\n|-----------|------|\r\n| `mallName` | 店铺名称（也支持 `mall_name`、`name`） |\r\n\r\n响应字段：`returnObj.data.mall_id`、`mall_name`、`platform_name`、`ip_address`、`remark`、`created_at`、`updated_at`。\r\n\r\n## CreateBrowser\r\n\r\n创建新店铺。`ret=200` 且 `returnObj.success=true` 表示成功；`successCount` 为成功创建数量。\r\n\r\n请求：\r\n\r\n```json\r\n{\r\n  \"action\": \"CreateBrowser\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"mall_name\\\":\\\"测试WebDriver随机950317\\\",\\\"mall_account\\\":\\\"test_account\\\",\\\"mall_password\\\":\\\"test_password\\\",\\\"platform\\\":\\\"自定义平台\\\",\\\"platform_url\\\":\\\"https://www.baidu.com\\\",\\\"mall_address\\\":\\\"\\\",\\\"tags\\\":\\\"\\\",\\\"authorizationMember\\\":\\\"\\\",\\\"ip_content\\\":\\\"IP\\\",\\\"browser_kernel_version\\\":0,\\\"window_ua\\\":\\\"\\\",\\\"mac_ua\\\":\\\"\\\",\\\"android_ua\\\":\\\"\\\",\\\"remark\\\":\\\"这是一个用于测试的店铺\\\"}\"\r\n}\r\n```\r\n\r\n响应示例：\r\n\r\n```json\r\n{\r\n  \"action\": \"CreateBrowser\",\r\n  \"ret\": 200,\r\n  \"returnObj\": {\r\n    \"success\": true,\r\n    \"data\": {\r\n      \"errorCount\": 0,\r\n      \"errorMsgData\": null,\r\n      \"successCount\": 1\r\n    },\r\n    \"msg\": \"\"\r\n  },\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n| args 字段 | 必填 | 说明 |\r\n|-----------|------|------|\r\n| `mall_name` | 是 | 店铺名，**不能重复** |\r\n| `mall_account` | 否 | 店铺账号 |\r\n| `mall_password` | 否 | 店铺密码 |\r\n| `platform` | 是 | 所属平台 |\r\n| `platform_url` | 自定义平台时必填 | 如 `https://www.baidu.com` |\r\n| `mall_address` | 否 | 店铺地址 |\r\n| `tags` | 否 | 标签 |\r\n| `authorizationMember` | 否 | 授权成员 |\r\n| `ip_content` | 否 | 绑定已有设备 IP |\r\n| `browser_kernel_version` | 否 | 不指定内核填 `0` |\r\n| `window_ua` / `mac_ua` / `android_ua` | 否 | UA |\r\n| `remark` | 否 | 备注 |\r\n\r\n创建成功后需**等待列表同步**，再 `GetMallByName` 取 `mall_id` 并 `OpenBrowser`。\r\n\r\n## UpdateAccount\r\n\r\n根据店铺 ID（`browserId`）修改店铺登录账号与密码。`browserId` 为店铺 `mall_id`；`args.username` 对应 `mall_account`，`args.password` 对应 `mall_password`（可空字符串）。\r\n\r\n请求：\r\n\r\n```json\r\n{\r\n  \"action\": \"UpdateAccount\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"3061488\",\r\n  \"args\": \"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"cyt123456A\\\"}\"\r\n}\r\n```\r\n\r\n| 字段 | 类型 | 说明 |\r\n|------|------|------|\r\n| `browserId` | string | 店铺 `mall_id` |\r\n| `username` | string | 店铺账号（对应 `mall_account`，可空） |\r\n| `password` | string | 店铺密码（对应 `mall_password`，可空） |\r\n\r\n成功：\r\n\r\n```json\r\n{\r\n  \"action\": \"UpdateAccount\",\r\n  \"ret\": 200,\r\n  \"returnObj\": {\r\n    \"success\": true,\r\n    \"data\": {},\r\n    \"msg\": \"\"\r\n  },\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n失败：\r\n\r\n```json\r\n{\r\n  \"action\": \"UpdateAccount\",\r\n  \"ret\": 200,\r\n  \"returnObj\": {\r\n    \"success\": false,\r\n    \"msg\": \"缺少 browserId\"\r\n  },\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `success` | 是否修改成功 |\r\n| `msg` | 提示信息 |\r\n| `data` | 成功时的接口返回数据 |\r\n\r\n以 `returnObj.success` 为准；`success != true` → 立即结束并原样报告 `msg`。调用前须 resolve `mall_id`（先读 `mall_cache.json`，未命中再 `GetMallByName`）。\r\n\r\n## OpenBrowser\r\n\r\n根据店铺 `mall_id` 打开店铺。\r\n\r\n```json\r\n{\r\n  \"action\": \"OpenBrowser\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"3061488\",\r\n  \"args\": \"{\\\"isDownLoadConfirm\\\":false,\\\"isOpenMallIndex\\\":true,\\\"isSwitchDynamicNetwork\\\":false}\"\r\n}\r\n```\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `browserId` | 店铺 `mall_id`；**必须为 JSON 字符串**（`\"3061488\"`），**禁止**传数字 `3061488` |\r\n| `isDownLoadConfirm` | 下载前是否询问每个文件的保存位置 |\r\n| `isOpenMallIndex` | 是否默认打开店铺首页 |\r\n| `isSwitchDynamicNetwork` | 绑定了动态 IP 的店铺，传 `true` 则切换动态网络 |\r\n\r\n**成功**：`returnObj === true`（布尔值，非 `{success}` 对象）\r\n\r\n**失败**：`returnObj === false`\r\n\r\n**打开失败时**：向客户提醒检查店铺是否已**绑定 IP/设备**。\r\n\r\n## GetBrowserWebDriver\r\n\r\n获取店铺 CDP 端口；**也用于判断目标店铺是否已打开**（`success=true` 且 `WebDriverPort` 有值 → 已打开）。\r\n\r\n- 客户要求**打开**且已开 → 询问是否需要**关闭店铺**；未确认不调用 `OpenBrowser` / `CloseBrowser`\r\n- 客户要求**关闭** → 直接 `CloseBrowser`，并清理 `opening_malls.json`\r\n- **OpenBrowser 前探测**：一律 **只请求 1 次、`timeout=5`**；超时则**仍执行 `OpenBrowser`**，不因此结束流程；禁止二次探测、禁止 15s 长超时\r\n\r\n```json\r\n{\r\n  \"action\": \"GetBrowserWebDriver\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"2786463\"\r\n}\r\n```\r\n\r\n> **`browserId` 必须为 JSON 字符串**（`\"2786463\"`），**禁止**传数字。从 API/`mall_cache` 取到的 `mall_id` 一律先 `str(mall_id)` 再写入。\r\n\r\n需在店铺**已打开**后调用（OpenBrowser 前探测时：未开或超时则视为未确认已开）。\r\n\r\n响应：\r\n\r\n```json\r\n{\r\n  \"action\": \"GetBrowserWebDriver\",\r\n  \"ret\": 200,\r\n  \"returnObj\": {\r\n    \"success\": true,\r\n    \"msg\": \"\",\r\n    \"WebDriverPort\": 12635,\r\n    \"MainHandle\": \"3020652\",\r\n    \"KernalNumber\": 137\r\n  },\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `WebDriverPort` | 外部 WebDriver 开发端口（Playwright CDP 用） |\r\n| `MainHandle` | 主窗口句柄 |\r\n| `KernalNumber` | 内核版本；**macOS** 下若 **≤ 130** 则**不支持** Playwright 自动化，须提示客户切换到 **130 以上**内核（或主账号切换）并**手动重启站斧**后停止 |\r\n\r\n失败示例：`returnObj.success === false`，`msg` 如「浏览器未启动」。\r\n\r\nPlaywright 使用 `WebDriverPort`：`connect_over_cdp(\"http://127.0.0.1:{WebDriverPort}\")`\r\n\r\n> **macOS 内核限制**：拿到 `WebDriverPort` 后进入 CDP 前，必须检查 `KernalNumber`。`KernalNumber ≤ 130` → 立即停止并提示：\r\n>\r\n> ```\r\n> 当前为 macOS，店铺 {mall_name} 的内核为 {kernel}（≤130），暂不支持自动化。\r\n> 请将该店铺切换到 130 以上内核；若无权限请让主账号切换。切换完成后请您手动重启站斧，再告诉我继续。\r\n> ```\r\n>\r\n> **Windows** 无此限制。Agent **禁止**在低内核场景下自行改内核或自动重启站斧。\r\n\r\n## CloseBrowser\r\n\r\n关闭指定店铺浏览器。**`api_port` HTTP 正常时直接调用，勿重启站斧。**\r\n\r\n```json\r\n{\r\n  \"action\": \"CloseBrowser\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"2786463\",\r\n  \"args\": \"\"\r\n}\r\n```\r\n\r\n**成功**：`returnObj === null`  \r\n**失败**：`returnObj === false`\r\n\r\n流程：`GetMallByName` 取 `mall_id` → `CloseBrowser`。开/关店铺均**不要**顺带 `ExitClient`。\r\n\r\n## ExitClient\r\n\r\n关闭站斧客户端。调用后客户端将退出，无额外业务返回值。\r\n\r\n```json\r\n{\"action\": \"ExitClient\", \"module\": \"WebDriverModule\", \"args\": \"\"}\r\n```\r\n\r\n成功：`returnObj === null`\r\n\r\n## SetDownLoadPath\r\n\r\n设置站斧浏览器文件下载路径。目录不存在时自动创建，成功后写入全局配置 `BrowserFileDwonPath`。\r\n\r\n> **平台**：仅 **Windows**。**macOS 目前不支持**——Agent 须直接告知客户并停止，勿调用本接口。\r\n\r\n```json\r\n{\r\n  \"action\": \"SetDownLoadPath\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"FilePath\\\": \\\"H:\\\\\\\\downloads\\\"}\"\r\n}\r\n```\r\n\r\n| args 字段 | 说明 |\r\n|-----------|------|\r\n| `FilePath` | 下载目录路径（不能为空） |\r\n\r\n响应：`returnObj.success`、`returnObj.msg`\r\n\r\n## ClearCacheFolder\r\n\r\n关闭所有店铺后，清除用户数据目录（保留 `Core`、`Down`）及日志目录。不计算缓存大小，不上报进度，直接删除。\r\n\r\n> **平台**：仅 **Windows**。**macOS 目前不支持**——Agent 须直接告知客户并停止，勿调用本接口。\r\n\r\n```json\r\n{\r\n  \"action\": \"ClearCacheFolder\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{}\"\r\n}\r\n```\r\n\r\n响应：`returnObj.success`、`returnObj.msg`\r\n\r\n## ClearCache\r\n\r\n关闭指定店铺后，删除该店铺的用户数据缓存目录（`RuxWorkbench` 目录跳过）。\r\n\r\n> **平台**：仅 **Windows**。**macOS 目前不支持**——Agent 须直接告知客户并停止，勿调用本接口。\r\n\r\n```json\r\n{\r\n  \"action\": \"ClearCache\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"2786463\",\r\n  \"args\": \"\"\r\n}\r\n```\r\n\r\n响应：`returnObj.success`、`returnObj.msg`；缺少 `browserId` 时 `msg` 如「缺少 browserId」。\r\n\r\n## SetInstallPlugins\r\n\r\nWebDriver 模式下，设置打开店铺时默认加载的插件列表。成功后写入 `ClientGlobal.Data.InstallPlugins`，在后续 `OpenBrowser` 时生效。\r\n\r\n> **平台**：仅 **Windows**。**macOS 目前不支持**——Agent 须直接告知客户并停止，勿调用本接口。\r\n>\r\n> **须在 `OpenBrowser` 之前调用**；传空数组 `[]` 表示不额外指定插件。\r\n\r\n请求：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[{\\\"plugin_name\\\":\\\"RXMallHelper\\\",\\\"chrome_id\\\":\\\"abcdefghijklmnop\\\"}]}\"\r\n}\r\n```\r\n\r\n| 参数 | 类型 | 必填 | 说明 |\r\n|------|------|------|------|\r\n| `installPlugins` | array | 是 | 插件列表 |\r\n| `installPlugins[].plugin_name` | string | 是 | 插件名称，非空字符串 |\r\n| `installPlugins[].chrome_id` | string | 否 | 插件 ID；可省略或传空字符串 `\"\"` |\r\n\r\n**`chrome_id` 省略示例**：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[{\\\"plugin_name\\\":\\\"RXMallHelper\\\"}]}\"\r\n}\r\n```\r\n\r\n**`chrome_id` 传空字符串示例**：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[{\\\"plugin_name\\\":\\\"RXMallHelper\\\",\\\"chrome_id\\\":\\\"\\\"}]}\"\r\n}\r\n```\r\n\r\n**清空插件列表示例**：\r\n\r\n> **备注**：通过自动化安装的插件，清空列表之后需要**清除店铺本地缓存**（`ClearCache`）才能生效。\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[]}\"\r\n}\r\n```\r\n\r\n**清空插件并使其生效的推荐流程**（针对目标店铺）：\r\n\r\n```\r\nSetInstallPlugins([]) → ClearCache（browserId=mall_id）→ OpenBrowser\r\n```\r\n\r\n若店铺已打开，须先 `CloseBrowser` 或依赖 `ClearCache` 自动关店后再 `OpenBrowser`。\r\n\r\n响应：`returnObj.success`、`returnObj.msg`\r\n\r\n| 常见失败 `msg` | 说明 |\r\n|----------------|------|\r\n| `args 必须为 JSON 对象` | `args` 格式不正确 |\r\n| `缺少 installPlugins 参数` | 未传 `installPlugins` 字段 |\r\n| `installPlugins 必须为数组` | `installPlugins` 不是数组 |\r\n| `installPlugins[n].plugin_name 必须为非空字符串` | 第 n 项插件名无效 |\r\n| `installPlugins[n].chrome_id 必须为字符串` | 第 n 项 `chrome_id` 类型无效（传了非字符串且非空值） |\r\n\r\n## GetWebDriver（仅 Selenium）\r\n\r\n仅 **Selenium API** 自动化需要；Playwright / CDP **跳过**此接口。\r\n\r\n将内核目录中的 `webdriver` 文件复制到指定目录（**不可为磁盘根目录**）。\r\n\r\n```json\r\n{\r\n  \"action\": \"GetWebDriver\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"FilePath\\\": \\\"H:\\\\\\\\webdrivers\\\"}\"\r\n}\r\n```\r\n\r\n| args 字段 | 说明 |\r\n|-----------|------|\r\n| `FilePath` | 目标 webdriver 存放目录，不可为根目录 |\r\n\r\n响应：`returnObj.success`、`returnObj.msg`\r\n\r\n## 注意事项（文档 5.x）\r\n\r\n1. 客户端版本要求：**Windows ≥ 5.2.12**，**macOS > 5.2.10**；安装技能时向客户说明「客户使用指南」（见 `SKILL.md`）。冷启动后 8s 内未能建立 WebDriver 通讯时，按 `SKILL.md`「通讯失败对客户话术」提示（版本无误、卡顿可延迟时可再试，请客户说「打开站斧」；**禁止**再说「WebDriver 版且不低于 5.2.12」）。\r\n2. **首次**打开店铺会下载内核，建议客户先在站斧客户端手动打开一次；不同内核的店铺需分别手动打开一次后再自动化。\r\n3. 同时安装普通版与 WebDriver 版时，需使用 WebDriver 版。\r\n4. 用 `GetBrowserList` **能取到数据**判断站斧已打开；**禁止**用 `LoadSuccess` 判断。确认为站斧 WebDriver 时**勿杀进程重启**；打开/关闭店铺均继续 HTTP。仅目标端口无响应、被非站斧占用、或客户明确要求时才冷启动（**空闲端口**，优先 12678，占用则递增）。**打开站斧且探测未打开/非站斧占用时，立刻清空 `opening_malls.json`**；安装目录须按快捷方式/常见目录查找，找不到则向客户索要。**禁止**因 12678 被占用而要求客户先停掉其他服务。\r\n5. 访问本地 HTTP 服务：单次探测 `timeout=1.5`；冷启动后**立刻轮询** `GetBrowserList`（间隔 0.5s，最多 8s），勿固定干等。`OpenBrowser` 成功后固定等待 **10s** 再取 `WebDriverPort`。\r\n6. 自动创建店铺后再打开，中间需**等待**列表同步。\r\n7. 客户要求**打开**但目标店铺已打开时，须询问是否需要**关闭店铺**；客户明确要求**关闭**时直接 `CloseBrowser` 并清理 `opening_malls.json`。\r\n8. 打开店铺指令（**站斧已打开后**）写入 `opening_malls.json`；OpenBrowser 前 `GetBrowserWebDriver` **单次 5s**，超时仍 `OpenBrowser`。关店 / 关站斧 / **探测站斧未打开**时清理该配置。\r\n9. `OpenBrowser` / OpenBrowser 后 `GetBrowserWebDriver` 失败时，提醒客户确认店铺是否已绑定 IP/设备，以及是否已手动打开过该店铺下载内核。\r\n10. 需默认加载插件时，在 `OpenBrowser` **之前**调用 `SetInstallPlugins`；`chrome_id` 可省略或传 `\"\"`；传 `[]` 可清空插件列表。\r\n11. **清空插件列表**（`installPlugins: []`）后，若插件曾通过自动化安装，须再对该店铺调用 **`ClearCache`** 清除本地缓存后重新 `OpenBrowser`，清空才生效。\r\n12. Agent 阶段 A **只用 Python requests**，禁止为通断探测切换 PowerShell/curl；杀进程后最多等 1s（Win:`taskkill` / Mac:`killall 站斧`），勿固定等 3s。\r\n13. **macOS** 不得调用 `SetDownLoadPath` / `ClearCacheFolder` / `ClearCache` / `SetInstallPlugins`（目前不支持）。\r\n14. **macOS** 打开/复用店铺后若 `GetBrowserWebDriver.KernalNumber ≤ 130`：立即停止自动化，提示客户切换到 **130 以上**内核（或请主账号切换），并请客户**手动重启站斧**后再继续。\r\n15. **启动参数禁止减少**：Windows / macOS **均须四项齐全**：`--multip --run_type=web_driver --ipc_type=http --httpport=`（macOS 通过 `open -a … --args` 传入）。\r\n16. **`OpenBrowser` / `GetBrowserWebDriver` 的 `browserId` 必须为 JSON 字符串**（如 `\"3514488\"`），**禁止**传数字；resolve 后一律 `str(mall_id)`。\r\n17. 客户口误「**战斧**」一律按「**站斧**」理解（如「打开战斧」=「打开站斧」），勿当成未知指令。\n\nFile v1.0.6:skill-card.md\n\n## Description:\n\nAutomates the ZhanFu WebDriver client and store browsers with local HTTP calls before connecting Playwright over CDP for user-directed browser tasks.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zhangzhang1997](https://clawhub.ai/user/zhangzhang1997)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users, developers, and store operators use this skill to open, close, create, list, and configure ZhanFu stores, then perform guided Playwright automation in the store browser after a WebDriver port is available.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles high-value ZhanFu account credentials and store-management actions.\n\nMitigation: Use it only on trusted local machines, avoid entering owner or store passwords on shared or monitored systems, and provide credentials only when needed for the requested workflow.\n\nRisk: Local automation can contact the wrong local service or an untrusted ZhanFu workflow if the environment is not verified.\n\nMitigation: Verify the real ZhanFu client is listening before login or store operations and stop when local communication cannot be confirmed.\n\nRisk: Cache clearing, account changes, plugin changes, and client termination can alter store state or interrupt active work.\n\nMitigation: Require explicit user confirmation before running cache clearing, account update, plugin update, or client exit actions.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zhangzhang1997/skills/zhanfu-playwright)\n- [ZhanFu WebDriver API reference](artifact/reference.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown guidance with Python and shell command examples, plus JSON HTTP request examples.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Outputs may operate a local ZhanFu client, store accounts, browser sessions, plugins, download paths, and cache settings.]\n\n## Skill Version(s):\n\n1.0.6 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.5: 11 files, 49430 bytes\n\nFiles: api_port.json (110b), mall_cache.json (1115b), opening_malls.json (67b), reference.md (26296b), scripts/check_device_security.py (5932b), scripts/headed_mode.py (847b), scripts/requirements.txt (38b), scripts/zhanfu_playwright.py (47333b), skill-card.md (2290b), SKILL.md (74095b), _meta.json (136b)\n\nFile v1.0.5:SKILL.md\n\n---\r\nname: zhanfu-playwright\r\ndescription: >-\r\n  站斧 WebDriver 版 Playwright 自动化（Windows≥5.2.12、macOS>5.2.10、强制有界面、通讯失败即停）。\r\n  获取 WebDriver 端口前仅 HTTP 调用 WebDriverModule；获取端口后 CDP 执行业务。\r\n  适用于站斧、ZhanFu、WebDriver、Playwright、店铺自动化、小龙虾 OpenClaw RPA。\r\n---\r\n\r\n# 站斧 Playwright 自动化\r\n\r\n通过站斧 WebDriver 版 **HTTP API** 控制客户端与店铺；**拿到 WebDriverPort 之后**才用 Playwright `connect_over_cdp` 做页面自动化。\r\n\r\n**Agent 提示**：技能**首次安装**、客户问「怎么用 / 如何使用」时，**先向客户发送下方「客户使用指南」**（可摘要，不必全文照搬）。\r\n\r\n**前置（Agent）**：站斧版本要求 **Windows ≥ 5.2.12**，**macOS > 5.2.10**；环境已安装 `playwright`、`requests`。\r\n\r\n> **macOS 限制**：`SetDownLoadPath`、`ClearCacheFolder`、`ClearCache`、`SetInstallPlugins` **目前不支持**。客户在 Mac 上提出这些需求时，应直接说明暂不支持并停止，勿调用对应 HTTP 接口。\r\n>\r\n> **macOS 内核限制**：macOS **不支持 130 及以下内核**的店铺自动化。打开店铺后 `GetBrowserWebDriver` 返回的 `KernalNumber` **≤ 130** 时，**立即停止**阶段 B，按「macOS 低内核对客户话术」提示客户切换到 **130 以上**内核（或由主账号切换），并请客户**手动重启站斧**后再继续。\r\n\r\n---\r\n\r\n## 客户使用指南（安装技能时向客户说明）\r\n\r\n以下内容可直接复制或摘要发给客户。\r\n\r\n### 一、使用前准备\r\n\r\n1. **站斧版本**：请确认站斧版本要求（**Windows ≥ 5.2.12**，**macOS > 5.2.10**）。\r\n2. **首次打开店铺会下载浏览器内核**，耗时较长，建议您先在站斧客户端里**手动打开一次**目标店铺，等内核下载完成后再用自动化。\r\n3. **不同店铺可能使用不同内核**。若自动化打开失败或提示内核相关错误，请先在站斧里**手动打开一次该店铺**（或与您要用的店铺**同内核**的店铺），内核就绪后再发指令。\r\n4. 店铺须已**绑定 IP / 设备**；未绑定时打开会失败，请在站斧客户端检查店铺设备绑定。\r\n5. **macOS 暂不支持**：设置下载目录、清除缓存（单店/全部）、设置店铺插件（`SetDownLoadPath` / `ClearCache` / `ClearCacheFolder` / `SetInstallPlugins`）。请在 Windows 上使用这些能力。\r\n6. **macOS 内核**：自动化仅支持店铺内核 **> 130**。若提示当前内核 ≤ 130，请在站斧中将该店铺切换到 **130 以上**内核（无权限时请**主账号**切换），然后**手动重启站斧**，再发指令继续。\r\n\r\n### 二、最常用的说法（推荐）\r\n\r\n\r\n| 您想做什么         | 直接发送（示例）                                   |\r\n| ------------- | ------------------------------------------ |\r\n| 启动站斧并打开店铺     | **打开站斧打开 ztest126**（把 `ztest126` 换成您的店铺名）  |\r\n| 仅打开店铺（站斧已在运行） | **打开店铺 ztest126**                          |\r\n| 关闭某个店铺        | **关闭 ztest126 店铺** / **关闭店铺 ztest126**     |\r\n| 退出站斧客户端       | **关闭站斧**                                   |\r\n| **创建新店铺**     | **创建店铺**，并按提示提供下方参数（见「七、创建店铺」）             |\r\n| **修改店铺账号密码**  | **修改店铺账号密码**，提供店铺名与新账号/密码（见「十二、修改店铺账号密码」） |\r\n| **查看我的店铺列表**  | **获取店铺列表** / **列出店铺**（见「八、查看店铺列表」）         |\r\n| **设置浏览器下载目录** | **设置下载目录到 D:\\downloads**（见「十、下载与缓存」）       |\r\n| **清除店铺/全部缓存** | **清除 xxx 店铺缓存** / **清除全部缓存**（见「十、下载与缓存」）   |\r\n| **设置店铺默认插件**  | **设置店铺插件**，提供插件名称；插件 ID 可省略或留空（见「十一、店铺插件」） |\r\n| **清空店铺插件列表**  | **清除默认插件列表** / **清空店铺插件**（见「十一、店铺插件」）      |\r\n\r\n\r\n> 说法可略有不同，只要包含「打开站斧」「打开店铺」和**店铺名称**即可；站斧已在运行时，一般**不会**重启站斧，直接开/关店铺。\r\n\r\n### 三、首次未登录时\r\n\r\n若提示「站斧未登录，请提供账号和密码」，请提供您的**站斧老板账号**和密码（自动化仅使用您当场提供的账号，不会使用内测账号）。\r\n\r\n### 四、店铺已经打开时\r\n\r\n若您要的店铺**已经在运行**，系统会先问：**是否需要关闭该店铺？** 按您的选择回复即可；不需要关闭则可直接继续后续操作。\r\n\r\n### 五、页面自动化（进阶）\r\n\r\n店铺打开后，可继续用自然语言描述要在**店铺浏览器里**做的事，例如：\r\n\r\n- 「在 B 站搜索并播放某某视频」\r\n- 「打开某网址并填写表单」\r\n- 「抓取当前页面某某信息」\r\n\r\n此类操作会先等设备安全检测通过（约 15 秒），再自动操作页面。\r\n\r\n### 七、创建店铺\r\n\r\n发送 **「创建店铺」** 或 **「打开站斧并创建店铺 xxx」**，按提示提供信息即可（须已登录站斧）。\r\n\r\n**必填信息**\r\n\r\n\r\n| 您需提供                    | 说明                                             |\r\n| ----------------------- | ---------------------------------------------- |\r\n| **店铺名** `mall_name`     | 不能与已有店铺重名                                      |\r\n| **所属平台** `platform`     | 如「自定义平台」「Temu前台」等                              |\r\n| **平台网址** `platform_url` | 当平台选 **「自定义平台」** 时必填，如 `https://www.baidu.com` |\r\n\r\n\r\n**建议提供**\r\n\r\n\r\n| 您需提供                     | 说明                                               |\r\n| ------------------------ | ------------------------------------------------ |\r\n| **绑定设备 IP** `ip_content` | 须是站斧里**已有设备**的 IP；不知道时可先说「从已有店铺复用 IP」；未绑定时打开可能失败 |\r\n\r\n\r\n**选填信息**（有则提供，没有可留空）\r\n\r\n\r\n| 字段        | 说明                             |\r\n| --------- | ------------------------------ |\r\n| 店铺账号 / 密码 | `mall_account`、`mall_password` |\r\n| 店铺地址      | `mall_address`                 |\r\n| 标签        | `tags`                         |\r\n| 授权成员      | `authorizationMember`          |\r\n| 浏览器内核版本   | 不指定填 **0**                     |\r\n| 备注        | `remark`                       |\r\n\r\n\r\n**创建成功后**：系统会等列表同步，再按店铺名查询并**打开**新店铺。若创建失败，请检查店铺名是否重复、IP 是否有效、自定义平台是否填写了网址。\r\n\r\n**说法示例**\r\n\r\n> 创建店铺，店铺名 test001，平台自定义平台，网址 [https://www.baidu.com，绑定](https://www.baidu.com，绑定) IP 118.x.x.x\r\n\r\n### 八、查看店铺列表\r\n\r\n发送 **「获取店铺列表」**、**「列出我的店铺」** 或 **「店铺列表第 1 页」** 即可。\r\n\r\n- 系统会拉取您账号下的店铺，默认第 **1** 页、每页 **10** 条（可说「第 2 页」「每页 20 条」调整 `page` / `limit`）。\r\n- 列表中通常包含：**店铺名**、**平台**、**绑定 IP**、**创建/更新时间** 等。\r\n- **能正常拉到列表** = 站斧**已登录**；拉不到或报错 = 需要先登录（见「三、首次未登录时」）。\r\n\r\n**说法示例**\r\n\r\n> 获取店铺列表  \r\n> 列出店铺，第 2 页，每页 20 个\r\n\r\n### 十、下载与缓存（进阶）\r\n\r\n\r\n| 您想做什么     | 直接发送（示例）                      |\r\n| --------- | ----------------------------- |\r\n| 设置浏览器下载目录 | **设置下载目录到 D:\\downloads**      |\r\n| 清除某个店铺缓存  | **清除 ztest126 店铺缓存**（会先关闭该店铺） |\r\n| 清除全部店铺缓存  | **清除全部缓存**（会先关闭所有店铺）          |\r\n\r\n\r\n> 清除缓存为不可逆操作，执行前系统会向您确认。\r\n>\r\n> **macOS 暂不支持**本节全部能力（`SetDownLoadPath` / `ClearCache` / `ClearCacheFolder`）。\r\n\r\n### 十一、店铺插件（进阶）\r\n\r\n发送 **「设置店铺插件」**，在**打开店铺之前**指定默认加载的插件（`SetInstallPlugins` → `OpenBrowser`）。\r\n\r\n**您需提供**\r\n\r\n\r\n| 字段            | 必填  | 说明                          |\r\n| ------------- | --- | --------------------------- |\r\n| `plugin_name` | 是   | 插件名称（非空）                    |\r\n| `chrome_id`   | 否   | 插件 ID；**可省略**，或显式传空字符串 `\"\"` |\r\n\r\n\r\n可一次提供多个插件；说 **「清空店铺插件」**、**「清除默认插件列表」** 或传空列表 `[]` 表示不额外指定插件。\r\n\r\n> **重要**：若插件曾通过自动化安装，清空列表后还须**清除该店铺本地缓存**（`ClearCache`），再重新打开店铺，清空才生效。\r\n>\r\n> **macOS 暂不支持** `SetInstallPlugins`（及依赖的 `ClearCache`）。\r\n\r\n**说法示例**\r\n\r\n> 打开站斧，设置默认插件名称为紫竹自动化插件，插件 ID 为空，再打开店铺 ztest144  \r\n> 设置店铺插件，插件名 RXMallHelper（省略插件 ID）  \r\n> 设置店铺插件，插件名 紫竹自动化插件，插件 ID 为空  \r\n> 清除默认插件列表，重新打开 ztest144（会先 `SetInstallPlugins([])` → `ClearCache` → 再开店铺）\r\n\r\n> 设置会在后续 `OpenBrowser` 时生效；若店铺已打开，需先关闭再重新打开才加载新插件。\r\n\r\n### 十二、修改店铺账号密码\r\n\r\n发送 **「修改店铺账号密码」** / **「改店铺账号」**，按店铺修改登录账号与密码（`UpdateAccount`）。\r\n\r\n**您需提供**\r\n\r\n\r\n| 字段 | 必填 | 说明 |\r\n| ---- | --- | ---- |\r\n| **店铺名** `mall_name`（或已有 `mall_id`） | 是 | 用于 resolve `browserId`（=`mall_id`） |\r\n| **账号** `username` | 否 | 对应 `mall_account`；可空字符串 `\"\"` |\r\n| **密码** `password` | 否 | 对应 `mall_password`；可空字符串 `\"\"` |\r\n\r\n\r\n> 缺少账号/密码时先向客户询问，**禁止猜测**。账号与密码均可显式传空以清空对应字段。\r\n\r\n**说法示例**\r\n\r\n> 修改店铺 ztest126 的账号为 admin，密码为 cyt123456A  \r\n> 修改店铺账号密码，店铺名 ztest126，账号 admin，密码留空\r\n\r\n### 九、常见问题\r\n\r\n\r\n| 现象      | 建议                                 |\r\n| ------- | ---------------------------------- |\r\n| 打开店铺失败  | 检查店铺是否已绑定 IP/设备；首次使用是否已手动开过该店以下载内核 |\r\n| macOS 提示内核过低 | 将店铺切换到 **130 以上**内核（或请主账号切换），**手动重启站斧**后再试 |\r\n| 提示未登录   | 提供站斧账号和密码                          |\r\n| 站斧未启动   | 发送「**打开站斧打开 {店铺名}**」，会自动冷启动站斧再开店铺  |\r\n| 想完全重启站斧 | 明确说「**重启站斧**」                      |\r\n| 创建店铺失败  | 检查店铺名是否重复、IP 是否已绑定、自定义平台是否填了网址     |\r\n| 看不到店铺列表 | 先登录站斧；或说明要查第几页、每页多少条               |\r\n\r\n\r\n---\r\n\r\n## 硬规矩（红线，最高优先级）\r\n\r\n以下规则覆盖本 Skill 其他所有「等待 / 重试 / 备用方案」描述，**冲突时以本节为准**。\r\n\r\n### 1. 获取端口前：禁止写脚本\r\n\r\n在 `**OpenBrowser` 打开店铺并成功拿到 `WebDriverPort` 之前**：\r\n\r\n- **禁止**新建或运行任何 `.py` / `.js` / `.sh` 等可执行脚本文件（含 `_tmp_*.py`、临时业务脚本）\r\n- **禁止**为完成任务而编写「一次性自动化脚本」\r\n- **只允许**调用本 Skill 提供的 **HTTP 接口**（见 [reference.md](reference.md)）或 Shell 直接发 HTTP 请求\r\n- **允许**读写临时**数据文件**（如 `api_port.json`、`mall_cache.json`、`opening_malls.json` 状态文件），但数据文件不可执行\r\n\r\n> Skill 目录下 `scripts/*.py` 仅供人工参考或本地调试；**小龙虾 Agent 在获取端口前不得运行这些脚本**，应直接 POST `http://127.0.0.1:{api_port}`。\r\n\r\n### 2. 通讯失败或关键操作报错：立即结束\r\n\r\n出现以下情况，**马上停下并向客户报告**（`**GetBrowserList` 探测轮询**、以及「OpenBrowser 前 `GetBrowserWebDriver` **单次 5s** 超时后仍 `OpenBrowser`」除外，见下节）：\r\n\r\n- HTTP **连不上**站斧（连接拒绝、超时、无响应）\r\n- 除登录/运行态探测用 `GetBrowserList` 外，关键 API 返回失败（`returnObj.success == false`、缺必需字段）\r\n- Login / GetMallByName / CreateBrowser / UpdateAccount / SetInstallPlugins / OpenBrowser（`returnObj !== true`）/ GetBrowserWebDriver 失败（**例外**：OpenBrowser **前**探测 `GetBrowserWebDriver` 超时 5s → 仍执行 `OpenBrowser`）\r\n\r\n**禁止**：\r\n\r\n- 反复重试同一失败操作（`GetBrowserList` 的 **8s 轮询**、以及 OpenBrowser 前 `GetBrowserWebDriver` **仅允许单次 5s，超时改走 OpenBrowser**除外）\r\n- 全盘 / 跨盘符搜索站斧安装包（Windows：`where.exe`、`-Recurse`、glob `**\\站斧.exe`；macOS：全盘 `mdfind` / `find`）\r\n- 遍历桌面**全部** `.lnk` 或解析**文件名不含「站斧」**的快捷方式（如逐个扫 GitHub、VS Code、其他浏览器快捷方式）\r\n- 翻代码库「研究」原因\r\n- 写「等通讯好了再跑」的备用方案或延迟任务\r\n- 自行换端口 / 换路径 / 换工具碰运气（**例外**：冷启动前用 `get_available_port(首选)`——首选默认 `12678`，占用则递增 `12679…`；**禁止**盲扫 8081/8082 碰已运行站斧；**禁止**因端口占用要求客户先释放）\r\n- **减少/省略**站斧启动参数（Windows / macOS **均须四项齐全**：`--multip --run_type=web_driver --ipc_type=http --httpport=`）\r\n- 将 `OpenBrowser` / `GetBrowserWebDriver` 的 `browserId` 传成 **JSON 数字**（必须为**字符串**，如 `\"3514488\"`）\r\n- 客户仅要求**打开店铺**或**关闭店铺**时，在 `api_port` HTTP 通讯正常的情况下仍执行杀进程、冷启动或 `ExitClient`（**除非客户明确要求重启站斧**）\r\n- 用 `CheckClientOpen` / `LoadSuccess` / `LoadFailed` **判断站斧是否已打开**（改用 `GetBrowserList`，见下）\r\n- 在 **macOS** 上调用 `SetDownLoadPath` / `ClearCacheFolder` / `ClearCache` / `SetInstallPlugins`（**目前不支持**，应直接告知客户）\r\n- 在 **macOS** 上对 `KernalNumber ≤ 130` 的店铺继续 `connect_over_cdp` / 页面自动化（应提示切内核并让客户手动重启站斧后停止）\r\n\r\n### 3. 获取端口前：只能 HTTP，禁止浏览器工具\r\n\r\n在拿到 `**WebDriverPort` 之前**：\r\n\r\n- **只允许**向 `http://127.0.0.1:{api_port}` 发 HTTP POST（`WebDriverModule`）\r\n- **禁止**打开系统 Chrome / Edge / Firefox\r\n- **禁止**使用 Playwright / Puppeteer（含 `launch`、`connect_over_cdp`）\r\n- **禁止**使用 Cursor browser MCP / CDP 浏览器工具绕开站斧\r\n\r\n拿到端口之后，**仅允许** `playwright.chromium.connect_over_cdp(\"http://127.0.0.1:{WebDriverPort}\")` 接管**站斧店铺浏览器**。\r\n\r\n### 4. 工具名必须来自清单\r\n\r\n**禁止瞎编** action、工具名、命令名。只能使用下方「接口清单」中的 `action` 名称。\r\n\r\n#### 阶段 A — 获取端口前（仅 HTTP）\r\n\r\n\r\n| action                | 用途                                                                     |\r\n| --------------------- | ---------------------------------------------------------------------- |\r\n| `GetBrowserList`      | **判断站斧是否已打开** / 探测登录态 / 列表（**能取到数据 = 站斧已打开**；**禁止**用 `LoadSuccess` 判断） |\r\n| `Login`               | 登录（已登录则跳过；会关闭所有已开店铺）                                                   |\r\n| `GetMallByName`       | 按名称查店铺（`mallName` / `mall_name` / `name`）                              |\r\n| `CreateBrowser`       | 创建店铺                                                                   |\r\n| `UpdateAccount`       | 按 `browserId`（`mall_id`）修改店铺登录账号/密码（`username`→`mall_account`，`password`→`mall_password`，可空） |\r\n| `OpenBrowser`         | 打开店铺（成功 `returnObj===true`）                                            |\r\n| `GetBrowserWebDriver` | 获取 WebDriverPort（须店铺已打开；也可探测店铺是否已开）                                    |\r\n| `CloseBrowser`        | 关闭店铺（成功 `returnObj===null`）                                            |\r\n| `ExitClient`          | 退出站斧                                                                   |\r\n| `SetDownLoadPath`     | 设置浏览器下载目录（**仅 Windows**；macOS 不支持）                                     |\r\n| `SetInstallPlugins`   | 设置打开店铺时默认加载的插件（须在 `OpenBrowser` 前；**仅 Windows**；macOS 不支持）             |\r\n| `ClearCacheFolder`    | 清除全部店铺缓存（**仅 Windows**；macOS 不支持）                                      |\r\n| `ClearCache`          | 清除单个店铺缓存（**仅 Windows**；macOS 不支持）                                      |\r\n| `GetWebDriver`        | 仅 Selenium；Playwright **跳过**                                           |\r\n| `CheckClientOpen`     | **不再用于判断站斧是否已打开**（勿依赖 `LoadSuccess` / `LoadFailed`）                    |\r\n\r\n\r\n> **macOS**：客户要求下载目录 / 清缓存 / 设插件时，**立即停止**并告知「macOS 暂不支持该功能」，**禁止**调用上表标注「仅 Windows」的 action。\r\n\r\nHTTP 格式（固定）：\r\n\r\n```json\r\nPOST http://127.0.0.1:{api_port}\r\nContent-Type: application/json\r\n\r\n{\r\n  \"module\": \"WebDriverModule\",\r\n  \"action\": \"<上表 action>\",\r\n  \"browserId\": \"<mall_id 字符串，可选>\",\r\n  \"args\": \"<JSON 字符串，可选>\"\r\n}\r\n```\r\n\r\n> **`browserId` 类型硬规矩**：`OpenBrowser`、`GetBrowserWebDriver`（以及同样传 `browserId` 的 `CloseBrowser` / `UpdateAccount` / `ClearCache` 等）的 **`browserId` 必须是 JSON 字符串**（如 `\"3514488\"`），**禁止**传数字（如 `3514488`）。从 `mall_id` 取值后一律 `str(mall_id)` 再写入请求。\r\n\r\n站斧启动命令行参数（按操作系统）：\r\n\r\n**Windows**（**四项缺一不可，禁止减少/省略任一参数**；`{api_port}` 为分配到的空闲端口）：\r\n\r\n```\r\n站斧.exe --multip --run_type=web_driver --ipc_type=http --httpport={api_port}\r\n```\r\n\r\n| 参数 | 可否省略 |\r\n|------|----------|\r\n| `--multip` | **否** |\r\n| `--run_type=web_driver` | **否** |\r\n| `--ipc_type=http` | **否** |\r\n| `--httpport={api_port}` | **否**（值可变，键不可少） |\r\n\r\n**macOS**（**四项缺一不可，禁止减少/省略任一参数**，与 Windows 相同；用 `open -a` 启动）：\r\n\r\n```\r\nopen -a /Applications/站斧.app --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}\r\n```\r\n\r\n也可：`open -a 站斧 --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}`\r\n\r\n| 参数 | 可否省略 |\r\n|------|----------|\r\n| `--multip` | **否** |\r\n| `--run_type=web_driver` | **否** |\r\n| `--ipc_type=http` | **否** |\r\n| `--httpport={api_port}` | **否**（值可变，键不可少） |\r\n\r\n**禁止**减少启动参数（例如去掉 `--multip` / `--ipc_type=http`，或只留 `--httpport`）。**默认 API 端口**：首选 `12678`。冷启动前须 `get_available_port(首选)`：**若首选端口已被占用则自动用下一空闲端口（12679…）**，**禁止**因此停下来要求客户释放端口；启动成功后把实际端口写入 Skill 目录 `[api_port.json](api_port.json)`（见下节）。\r\n\r\n#### HTTP 请求方式（阶段 A · 禁止 curl / 禁止换工具试错）\r\n\r\n**Agent 默认只用 Python `requests`**（稳定、无引号逃逸坑）。**禁止**为同一探测在 PowerShell / curl / Python 之间来回换工具（浪费时间）。\r\n\r\n**单次探测超时**：`timeout=1.5` 秒（够判通断，勿用 3～30s 长超时堵死）。\r\n\r\n**推荐模板**（直接复制，勿改成复杂转义；`{api_port}` 换成 `api_port.json` 中的端口，默认 `12678`）：\r\n\r\n```python\r\nimport requests, json\r\napi_port = 12678  # 读自 api_port.json，无文件则用 12678\r\nr = requests.post(\r\n    f\"http://127.0.0.1:{api_port}\",\r\n    json={\"module\": \"WebDriverModule\", \"action\": \"GetBrowserList\",\r\n          \"args\": json.dumps({\"page\": 1, \"limit\": 20})},\r\n    timeout=1.5,\r\n)\r\nprint(r.text)\r\n```\r\n\r\n连接拒绝 / 超时 → 视为**站斧未打开**，立刻清空 `opening_malls.json` 并冷启动；**不要**改用 PowerShell 再探一次。\r\n\r\n**冷启动分配空闲端口**（判定站斧未打开之后、启动之前必做；直接复制）：\r\n\r\n```python\r\nimport socket\r\ndef get_available_port(start=12678):\r\n    port = max(1, int(start))\r\n    while port < 65535:\r\n        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:\r\n            try:\r\n                s.bind((\"127.0.0.1\", port))\r\n                return port\r\n            except OSError:\r\n                port += 1\r\n    raise RuntimeError(f\"自 {start} 起未找到可用端口\")\r\n\r\n# preferred = api_port.json 的 api_port（默认 12678）\r\napi_port = get_available_port(preferred)\r\nprint(api_port)  # 若 12678 被占用，会得到 12679…\r\n```\r\n\r\n> 首选端口被占用（含非站斧服务、TIME_WAIT 等）→ **换下一空闲端口继续启动**，**禁止**要求客户先释放 12678；**禁止**盲扫 8081/8082 碰已运行站斧。\r\n\r\n**备选（仅人工调试）** PowerShell 手动拼 JSON：\r\n\r\n```powershell\r\n$body = '{\"module\":\"WebDriverModule\",\"action\":\"GetBrowserList\",\"args\":\"{\\\"page\\\":1,\\\"limit\\\":20}\"}'\r\nInvoke-RestMethod -Uri \"http://127.0.0.1:12678\" -Method Post -Body $body -ContentType \"application/json\"\r\n```\r\n\r\n**禁止** Windows `curl` 手工转义 JSON；**禁止** PowerShell `ConvertTo-Json` 嵌套 `args`。\r\n\r\n#### 打开站斧快速路径（优先按此执行，少读少试）\r\n\r\n1. 读 `api_port.json` → 对 `api_port`（默认 12678）发 **一次** 上述 Python `GetBrowserList`（`timeout=1.5`）\r\n2. 能取到 `mall_list` → 已打开，结束（或继续开店铺）\r\n3. 无响应（或端口上是**非站斧** HTTP）→ 清空 `opening_malls.json` → 用 `install_dir`（无效再按 OS 查找；都没有则问客户）定位站斧\r\n4. **杀进程**（最多等 1s；进程已没则可立刻继续，禁止固定干等 3s；**只杀站斧，勿停占用端口的其他服务**）：\r\n  - Windows：`taskkill /f /t /im 站斧.exe`\r\n  - macOS：`killall 站斧`\r\n5. **分配空闲端口**：`api_port = get_available_port(首选)`（首选 = `api_port.json` 的端口或 `12678`）；**占用则递增换口**\r\n6. **启动**（`--httpport=` 用上一步实际端口）：\r\n  - Windows：`站斧.exe --multip --run_type=web_driver --ipc_type=http --httpport={api_port}`\r\n  - macOS：`open -a /Applications/站斧.app --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}`\r\n7. **立刻**轮询 `GetBrowserList`（对**实际启动端口**，间隔 **0.5s**，总计最多 **8s**）；能取到数据即成功写回 `api_port.json`\r\n8. **8s 内仍无 WebDriver 通讯** → **立即停止、禁止重试**，按下方「通讯失败对客户话术」原样提示（含已确认的安装路径）\r\n9. 仅「打开站斧」且无开店需求 → **到此结束**，勿继续 OpenBrowser\r\n\r\n#### 阶段 B — 拿到 WebDriverPort 之后\r\n\r\n\r\n| 工具 / 方法                                | 用途                                |\r\n| -------------------------------------- | --------------------------------- |\r\n| `playwright.chromium.connect_over_cdp` | 接管站斧店铺浏览器                         |\r\n| `scripts/check_device_security.py`     | 业务自动化前设备安全检测（Skill 内置，**仅端口拿到后**） |\r\n| `ensure_headed_mode()`                 | 强制有界面（见 `scripts/headed_mode.py`） |\r\n\r\n\r\n**禁止**：`playwright.chromium.launch`、`browser_navigate`（MCP）、Puppeteer `launch`。\r\n\r\n---\r\n\r\n## 两阶段工作流\r\n\r\n```\r\n阶段 A（仅 HTTP，禁止脚本 / 禁止 Playwright / 失败即停）\r\n  [读 api_port.json → 单次 GetBrowserList 探测该端口] → 能取到数据则站斧已打开，直接继续（开/关店铺均不重启）\r\n  → 无 HTTP 响应 / 非站斧占用 = 站斧未打开 → **立刻清空 opening_malls.json** → 查路径 → 杀站斧进程 → **get_available_port(首选)（占用则 12679…）** → 冷启动\r\n  → 冷启动前查找站斧：api_port.json →（Windows 快捷方式/常见目录；macOS `/Applications`/`~/Applications`）；**全部找不到则停止并向客户索要安装路径**（禁止全盘搜）\r\n  → GetBrowserList 探测运行态/登录（最多 8s；能取到数据=已打开；禁止用 LoadSuccess 判断）→ [未登录则提示 Login]\r\n  → [SetInstallPlugins / SetDownLoadPath 可选，**仅 Windows**，须在 OpenBrowser 前；**macOS 跳过且勿调用**]\r\n  → 打开（站斧已打开之后）：写入 opening_malls.json → resolve mall_id → GetBrowserWebDriver **单次 5s** 判是否已开（超时仍 OpenBrowser）→ OpenBrowser → GetBrowserWebDriver → **【macOS】检查 `KernalNumber`，≤130 则停并提示切内核/主账号切换 + 手动重启站斧**\r\n  → 关闭：resolve mall_id → CloseBrowser → 从 opening_malls.json 去掉该店铺名\r\n  → 关闭站斧：ExitClient → 清空 opening_malls.json\r\n\r\n阶段 B（端口拿到后；macOS 且 KernalNumber≤130 禁止进入）\r\n  connect_over_cdp → [设备安全检测 15s] → 业务 Playwright 自动化\r\n```\r\n\r\n```\r\nTask Progress:\r\n- [ ] 1. 收集客户参数（含 mall_name）\r\n- [ ] 2. 【阶段 A】读 `api_port.json`，对**唯一目标端口**单次 `GetBrowserList`（无文件则用 **12678**）；**能取到数据 = 站斧已打开，禁止冷启动**（开/关店铺均适用；**禁止**用 `LoadSuccess` 判断）\r\n- [ ] 3. 【阶段 A · 探测到站斧未打开】**立刻清空 `opening_malls.json`** → 查安装路径 → 杀进程（Win:`taskkill` / Mac:`killall 站斧`，最多等 1s）→ **`api_port = get_available_port(首选)`（首选被占用则递增）** → 冷启动 `--httpport={api_port}` → **立刻**轮询 `GetBrowserList`（间隔 0.5s，最多 8s）→ 写回 `api_port.json`\r\n- [ ] 4. 【阶段 A】`GetBrowserList` 探测运行态/登录（间隔 **0.5s**，**总计最多 8s**）；能取到 `mall_list` = 已打开且已登录；仍无法确认则提示客户提供账号密码\r\n- [ ] 5. 【阶段 A · 打开店铺 · 仅站斧已打开后】将 `mall_name` **写入** `opening_malls.json`（打开意图配置；**禁止**在站斧未打开时写入）\r\n- [ ] 6. 【阶段 A】resolve mall_id（读 `mall_cache.json` → 未命中则 `GetMallByName` 并写缓存）/ `CreateBrowser`（失败即停）\r\n- [ ] 7. 【阶段 A】resolve mall_id（关店则跳过 OpenBrowser 相关步骤）\r\n- [ ] 8. 【阶段 A · 打开店铺】`GetBrowserWebDriver` **只请求一次、超时 5s** 判断是否已打开；超时/无端口则**仍执行 OpenBrowser**（禁止二次探测、禁止 15s 长超时）\r\n- [ ] 9. 【阶段 A · 已打开】询问客户是否需要关闭店铺；未确认不操作\r\n- [ ] 10. 【阶段 A · 需打开】OpenBrowser（失败即停）→ GetBrowserWebDriver\r\n- [ ] 10b. 【阶段 A · macOS 内核】`GetBrowserWebDriver` 成功后若 `KernalNumber ≤ 130` → **立即停止**，按「macOS 低内核对客户话术」提示，**禁止**进入阶段 B\r\n- [ ] 11. 【阶段 A · 关闭店铺】CloseBrowser → **从 `opening_malls.json` 去掉该店铺名**（HTTP 正常时不重启站斧）\r\n- [ ] 12. 【阶段 A · 关闭站斧】ExitClient → **清空 `opening_malls.json`**\r\n- [ ] 13. 【阶段 B】connect_over_cdp\r\n- [ ] 14. 【阶段 B · 仅业务自动化】设备安全检测（15s 超时）\r\n- [ ] 15. 【阶段 B】执行业务自动化\r\n- [ ] 16. 收尾：CloseBrowser / ExitClient（**仅客户明确要求时** ExitClient；关店/关站斧时同步清理 `opening_malls.json`）\r\n```\r\n\r\n---\r\n\r\n## 禁止无头模式\r\n\r\n1. 站斧必须以 WebDriver 模式**有界面**启动\r\n2. 只能 `connect_over_cdp`，禁止 `launch(headless=True)`\r\n3. 执行 Playwright 前调用 `ensure_headed_mode()`，设置 `PLAYWRIGHT_HEADLESS=0`\r\n4. 禁止使用 Cursor 内置 browser MCP 替代站斧浏览器\r\n\r\n---\r\n\r\n## 执行前：向客户收集参数\r\n\r\n缺少必填项时先询问，**不要猜测账号密码或 IP**。\r\n\r\n**站斧安装路径**（打开站斧 / 冷启动时）：**先读** `api_port.json` 的 `install_dir` → 无效再按操作系统查找（见「启动站斧」）。**任一方式命中后，立即把安装路径写回** `api_port.json`。**都找不到时，必须停止并向客户索要安装路径**；**禁止**全盘搜索或猜测路径。\r\n\r\n- **Windows**：目录内需含 `站斧.exe`；客户提供后验证 `{folder_path}\\站斧.exe` 存在再继续。\r\n- **macOS**：需为 `站斧.app`（如 `/Applications/站斧.app`）；客户提供后验证 `.app` 存在再继续。\r\n\r\n### 登录态探测与 Login\r\n\r\n站斧启动（或复用 API）后，**必须在 8s 内**通过 `GetBrowserList` 判断站斧是否**已打开**且已登录（**禁止**用 `CheckClientOpen` / `LoadSuccess` / `LoadFailed` 判断）：\r\n\r\n```json\r\n{\"action\": \"GetBrowserList\", \"module\": \"WebDriverModule\", \"args\": \"{\\\"page\\\":1,\\\"limit\\\":20}\"}\r\n```\r\n\r\n\r\n| `GetBrowserList` 结果（8s 内）                                  | 动作                                                               |\r\n| ---------------------------------------------------------- | ---------------------------------------------------------------- |\r\n| `returnObj.success == true` 且能取到 `mall_list`（可解析，非 `null`） | **站斧已打开且已登录**，跳过 `Login`（`Login` 会关闭已开店铺）                        |\r\n| 有 HTTP 响应但 `success == false`、`data=null`、无法解析 `mall_list` | 站斧进程可能在跑但**未登录** → **停止**，提示客户：**「站斧未登录，请提供账号和密码」**（**禁止**因此冷启动） |\r\n| 连接拒绝 / 无响应 / 8s 超时仍无任何 HTTP 响应                             | **站斧未打开** → 才允许冷启动                                               |\r\n| 客户未提供账号密码                                                  | **停止**，不猜测、不擅自登录                                                 |\r\n\r\n\r\n**不要默认主动索要**登录信息；仅在 `GetBrowserList` 失败且后续需要操作店铺时再向客户索取。\r\n\r\n**禁止**在 Skill、脚本或对话中保存、引用或使用任何内测/示例账号密码；**仅**使用客户当场提供的 `username` / `password` 调用 `Login`，且固定 `isboss=true`（老板账号）。\r\n\r\nLogin 请求示例：\r\n\r\n```json\r\n{\r\n  \"action\": \"Login\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"username\\\":\\\"...\\\",\\\"password\\\":\\\"...\\\",\\\"isboss\\\":true}\"\r\n}\r\n```\r\n\r\n`Login` 返回 `success != true` → **立即结束**，原样报告 `returnObj.msg`（如密码错误）。\r\n\r\n### 按名称打开店铺\r\n\r\n\r\n| 参数          | 必填  |\r\n| ----------- | --- |\r\n| `mall_name` | 是   |\r\n\r\n\r\n### 创建店铺\r\n\r\n\r\n| 参数                                    | 必填       | 说明                             |\r\n| ------------------------------------- | -------- | ------------------------------ |\r\n| `mall_name`                           | 是        | 店铺名，不可重复                       |\r\n| `platform`                            | 是        | 所属平台                           |\r\n| `platform_url`                        | 自定义平台时必填 | 如 `https://www.baidu.com`      |\r\n| `ip_content`                          | 否        | 绑定已有设备 IP（或从已有店铺复用）；未绑定时打开可能失败 |\r\n| `mall_account` / `mall_password`      | 否        | 店铺账号密码                         |\r\n| `mall_address`                        | 否        | 店铺地址                           |\r\n| `tags`                                | 否        | 标签                             |\r\n| `authorizationMember`                 | 否        | 授权成员                           |\r\n| `browser_kernel_version`              | 否        | 不指定内核填 `0`                     |\r\n| `window_ua` / `mac_ua` / `android_ua` | 否        | UA                             |\r\n| `remark`                              | 否        | 备注                             |\r\n\r\n\r\n创建成功后须等待列表同步，再 resolve mall_id → `OpenBrowser`。\r\n\r\n### 设置店铺插件（SetInstallPlugins）\r\n\r\n客户要求**打开店铺前加载指定插件**时，须在 `OpenBrowser` **之前**调用。\r\n\r\n**省略 `chrome_id`**：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[{\\\"plugin_name\\\":\\\"RXMallHelper\\\"}]}\"\r\n}\r\n```\r\n\r\n`**chrome_id` 传空字符串**（客户说「插件 ID 为空」时用此写法）：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[{\\\"plugin_name\\\":\\\"紫竹自动化插件\\\",\\\"chrome_id\\\":\\\"\\\"}]}\"\r\n}\r\n```\r\n\r\n\r\n| 参数                             | 必填  | 说明                   |\r\n| ------------------------------ | --- | -------------------- |\r\n| `installPlugins`               | 是   | 插件数组；`[]` 表示清空/不额外指定 |\r\n| `installPlugins[].plugin_name` | 是   | 插件名称，非空字符串           |\r\n| `installPlugins[].chrome_id`   | 否   | 插件 ID；可省略或传 `\"\"`     |\r\n\r\n\r\n**清空插件列表**（`installPlugins: []`）：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[]}\"\r\n}\r\n```\r\n\r\n> 通过自动化安装的插件，**清空列表后须对该店铺调用 `ClearCache`**，再 `OpenBrowser`，清空才生效。\r\n\r\n**清空并重新打开店铺流程**：\r\n\r\n1. `SetInstallPlugins`（`installPlugins: []`）\r\n2. resolve mall_id 取 `mall_id`\r\n3. `ClearCache`（`browserId` = `mall_id`；会关闭该店铺）\r\n4. `OpenBrowser` → 等 15s → `GetBrowserWebDriver`\r\n\r\n`returnObj.success != true` → **立即结束**，原样报告 `returnObj.msg`。\r\n\r\n### 设备安全检测（仅业务自动化）\r\n\r\n客户提出**页面级自动化**（填表、抓取、播放视频等）时，阶段 B 必须先等设备安全检测成功（15s 超时）；仅启动/开店铺不需要。\r\n\r\n超时或未成功 → 告知客户：**「没检测成功无法进行自动化」**，立即结束。\r\n\r\n---\r\n\r\n## 打开店铺 / 关闭店铺（意图路由 · HTTP 正常则不重启）\r\n\r\n客户发送**打开店铺**或**关闭店铺**指令时，**一律先**读 `api_port.json` 并对 `api_port` 做单次 `GetBrowserList` 探测（**禁止**用 `LoadSuccess` 判断）。\r\n\r\n\r\n| 客户意图                       | `GetBrowserList` 探测        | 动作                                                                                                                                                    |\r\n| -------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\r\n| **打开店铺**                   | **能取到数据**（站斧已打开）或有 HTTP 响应 | **禁止**杀进程 / 冷启动 / `ExitClient`；将 `mall_name` 写入 `opening_malls.json` → resolve mall_id → `GetBrowserWebDriver` **单次 5s** 判是否已开 → 未开/超时则 `OpenBrowser` |\r\n| **关闭店铺**                   | **能取到数据**或有 HTTP 响应        | **禁止**杀进程 / 冷启动 / `ExitClient`；直接 HTTP：resolve mall_id → `CloseBrowser` → **从 `opening_malls.json` 去掉该店铺名**                                           |\r\n| **关闭站斧** / `ExitClient`    | 任意                         | `ExitClient` → **清空 `opening_malls.json`**                                                                                                            |\r\n| **创建店铺**                   | **能取到数据**或有 HTTP 响应        | **禁止**重启；`CreateBrowser` → 等待同步 → resolve mall_id → `OpenBrowser`（参数见客户指南「七、创建店铺」）                                                                    |\r\n| **修改店铺账号密码**               | **能取到数据**或有 HTTP 响应        | **禁止**重启；resolve mall_id → `UpdateAccount`（`browserId`=`mall_id`，`args.username`/`password` 由客户提供，可空；见「十二、修改店铺账号密码」）                              |\r\n| **获取店铺列表**                 | **能取到数据**或有 HTTP 响应        | **禁止**重启；`GetBrowserList`（默认 `page=1, limit=10`，可按客户指定分页）→ 展示 `mall_list`；**同时将列表中 `mall_name` → `mall_id` 写入 `mall_cache.json`**                     |\r\n| **设置下载目录**                 | **能取到数据**或有 HTTP 响应        | **仅 Windows**；macOS → 告知暂不支持并停止。Windows：`SetDownLoadPath`（`FilePath` 由客户提供）                                                                           |\r\n| **设置店铺插件**                 | **能取到数据**或有 HTTP 响应        | **仅 Windows**；macOS → 告知暂不支持并停止。Windows：`SetInstallPlugins`（须在 `OpenBrowser` 前）                                                                       |\r\n| **清空插件列表**                 | **能取到数据**或有 HTTP 响应        | **仅 Windows**；macOS → 告知暂不支持并停止。Windows：`SetInstallPlugins([])` → `ClearCache` → `OpenBrowser`                                                        |\r\n| **清除全部缓存**                 | **能取到数据**或有 HTTP 响应        | **仅 Windows**；macOS → 告知暂不支持并停止。Windows：确认后 `ClearCacheFolder` → 清空 `opening_malls.json`                                                              |\r\n| **清除单店缓存**                 | **能取到数据**或有 HTTP 响应        | **仅 Windows**；macOS → 告知暂不支持并停止。Windows：确认后 `ClearCache` → 从 `opening_malls.json` 去掉该店                                                                |\r\n| **打开站斧** / **打开站斧打开 {店铺}** | **无响应**（站斧未打开）             | **立刻清空 `opening_malls.json`** → 查安装目录（快捷方式/常见目录找不到则**向客户索要**）→ `get_available_port(首选)`（占用则递增）→ 冷启动 → 站斧就绪后再按需写入店铺名并开店铺                                                                |\r\n| **打开 / 关闭店铺**              | **无响应**（连接拒绝 / 超时）         | **立刻清空 `opening_malls.json`** → 才允许冷启动站斧（见「启动站斧」，含端口占用则换口）；**禁止**为关店单独重启（关店只需 HTTP，站斧未运行则先冷启动再继续 HTTP）                                                         |\r\n| **重启站斧**                   | 任意                         | 仅当客户**明确要求**时才杀进程 + `get_available_port` 冷启动（Win:`taskkill` / Mac:`killall 站斧`）→ **立刻清空 `opening_malls.json`**                                                             |\r\n\r\n\r\n> **核心**：开店铺、关店铺都是 **HTTP 操作**；`GetBrowserList` **能取到数据** = 站斧**已打开**，**继续 HTTP 即可**，不要「顺手」重启客户端。**禁止**根据 `CheckClientOpen` 的 `LoadSuccess` / `LoadFailed` 判断站斧是否已打开。\r\n\r\n### 关闭店铺流程（阶段 A · 仅 HTTP）\r\n\r\n1. 读 `api_port.json` → 单次探测 `GetBrowserList`\r\n2. 能取到数据或有 HTTP 响应 → resolve mall_id（读 `mall_cache.json` → 未命中则 `GetMallByName` 并写缓存；失败即停）\r\n3. `CloseBrowser`（`browserId` = 字符串形式的 `mall_id`）；成功时 `returnObj === null`，失败时 `returnObj === false`\r\n4. **从 `opening_malls.json` 去掉该 `mall_name`**\r\n5. **不调用** `ExitClient`（除非客户明确要求退出站斧客户端）\r\n6. **禁止**因关店而冷启动或杀站斧进程（Win:`站斧.exe` / Mac:`killall 站斧`）\r\n\r\n```json\r\n{\"action\": \"CloseBrowser\", \"module\": \"WebDriverModule\", \"browserId\": \"3514488\"}\r\n```\r\n\r\n---\r\n\r\n## 站斧运行态复用（读本地端口 · 单次 GetBrowserList · 禁止扫端口）\r\n\r\n客户要求**打开店铺**、**关闭店铺**或**执行业务自动化**时，**不要默认杀进程重启站斧**，也**禁止**依次试探 8081/8082 等端口。\r\n\r\n### 本地状态记录 `api_port.json`\r\n\r\n路径：Skill 目录下 `[api_port.json](api_port.json)`（与 `SKILL.md` 同级）。\r\n\r\n```json\r\n{\r\n  \"api_port\": 12678,\r\n  \"install_dir\": \"I:\\\\ZhanFu\",\r\n  \"updated_at\": \"2026-06-17T12:00:00\"\r\n}\r\n```\r\n\r\n\r\n| 字段            | 说明                                                                                          |\r\n| ------------- | ------------------------------------------------------------------------------------------- |\r\n| `api_port`    | 站斧 HTTP API 端口（首选默认 `12678`；冷启动时若占用则写入实际分配端口）                                                                  |\r\n| `install_dir` | 站斧安装路径：Windows 为含 `站斧.exe` 的文件夹；macOS 为 `站斧.app` 路径（如 `/Applications/站斧.app`）；**查找命中后立即写入** |\r\n| `updated_at`  | 最近一次写入时间                                                                                    |\r\n\r\n\r\n\r\n| 时机                                 | 动作                                                                                   |\r\n| ---------------------------------- | ------------------------------------------------------------------------------------ |\r\n| 每次任务开始                             | **先读** `api_port.json` 的 `api_port`；文件不存在则用 **12678**                                |\r\n| 冷启动前查找站斧                           | **先读** `install_dir`：Windows 验证 `{install_dir}\\站斧.exe`；macOS 验证 `.app` 存在；无效则走原始查找逻辑 |\r\n| 原始逻辑命中安装路径                         | **立即写入** `install_dir` 到 `api_port.json`                                             |\r\n| 客户提供路径且验证通过                        | **写入** `install_dir`                                                                 |\r\n| `GetBrowserList` 能取到数据 / 有 HTTP 响应 | **刷新写入** `api_port`（保留已有 `install_dir`）                                              |\r\n| 冷启动站斧成功                            | **写入** `api_port`（若有 `install_dir` 一并保留/更新）                                          |\r\n\r\n\r\n### 单次探测（仅一个端口 · 用 GetBrowserList，禁止 LoadSuccess）\r\n\r\n对目标端口（本地记录或 12678）发**一次** POST，Body 为正确 JSON 的 `GetBrowserList`：\r\n\r\n```json\r\n{\"module\":\"WebDriverModule\",\"action\":\"GetBrowserList\",\"args\":\"{\\\"page\\\":1,\\\"limit\\\":20}\"}\r\n```\r\n\r\n\r\n| HTTP / 业务结果                                   | 判定              | 动作                                                                    |\r\n| --------------------------------------------- | --------------- | --------------------------------------------------------------------- |\r\n| `success==true` 且能取到 `mall_list`（可解析）         | **站斧已打开**（且已登录） | 记录 `api_port`，**跳过**杀进程与冷启动                                           |\r\n| 有 HTTP 响应体，但取不到 `mall_list` / `success=false` | 站斧进程在跑但可能未登录    | 记录 `api_port`，**禁止冷启动**；进入登录提示流程                                      |\r\n| 有 HTTP 响应但**不是**站斧 WebDriver 结构               | **非站斧占用**       | **立刻清空 `opening_malls.json`** → 杀站斧进程（勿停占用方）→ `get_available_port(首选)` 换口冷启动 |\r\n| **连接拒绝 / 超时 / 无响应**                           | **站斧未打开**       | **立刻清空 `opening_malls.json`** → 杀站斧进程 → `get_available_port(首选)`（占用则递增）→ 冷启动 |\r\n\r\n\r\n> **禁止**再用 `CheckClientOpen` 的 `LoadSuccess` / `LoadFailed` 判断站斧是否已打开。「模块 undefined 未加载」等说明该端口上**已有 HTTP 服务**；若确认为站斧 WebDriver，用正确 JSON 的 `GetBrowserList` 重发即可；若是**非站斧**服务，走 `get_available_port` 换口冷启动，**不要**停占用方、**不要**要求客户释放端口。\r\n\r\n\r\n| 场景                       | 动作                                                                                         |\r\n| ------------------------ | ------------------------------------------------------------------------------------------ |\r\n| 站斧已打开 + **打开店铺**         | **不重启**；写入 `opening_malls.json` → resolve mall_id → 已开确认 → 未开则 `OpenBrowser`               |\r\n| 站斧已打开 + **关闭店铺**         | **不重启**；resolve mall_id → `CloseBrowser` → 清理 `opening_malls.json`                         |\r\n| 站斧已打开 + 阶段 B 业务          | **不重启**；`GetBrowserWebDriver` 拿端口                                                          |\r\n| **打开站斧** / 目标端口无 HTTP 响应 | **立刻清空 `opening_malls.json`** → 查安装目录（找不到则向客户索要）→ `get_available_port(首选)` → 冷启动，写 `api_port.json` |\r\n| 客户明确要求「重启站斧」             | 允许杀进程 + `get_available_port` 冷启动（Win:`taskkill` / Mac:`killall 站斧`），**立刻清空 `opening_malls.json`** |\r\n\r\n\r\n> 复用已运行实例时，**直接**用 `GetBrowserList`（最多 **8s**）判断是否已打开/已登录。**无论冷启动还是复用，探测总耗时不超过约 8s**（不再先等 `CheckClientOpen` / `LoadSuccess`）。\r\n\r\n---\r\n\r\n## 打开意图配置 `opening_malls.json`\r\n\r\n路径：Skill 目录下 `[opening_malls.json](opening_malls.json)`（与 `SKILL.md` 同级）。\r\n\r\n用于记录客户**已发出「打开某店铺」指令**的店铺名；关店 / 关站斧时清理。OpenBrowser 前用 `GetBrowserWebDriver` **统一单次 5s** 探测（与是否已在列表无关）。\r\n\r\n```json\r\n{\r\n  \"malls\": [\"ztest126\"],\r\n  \"updated_at\": \"2026-07-14T10:00:00\"\r\n}\r\n```\r\n\r\n\r\n| 字段           | 说明                              |\r\n| ------------ | ------------------------------- |\r\n| `malls`      | 客户已下达「打开」意图、且尚未通过关店/关站斧清理的店铺名列表 |\r\n| `updated_at` | 最近一次写入时间                        |\r\n\r\n\r\n\r\n| 时机                                                         | 动作                                     |\r\n| ---------------------------------------------------------- | -------------------------------------- |\r\n| 客户发送**打开店铺 / 打开站斧打开 {店铺名}**（**仅当站斧已打开之后**拿到 `mall_name`）   | **写入**该 `mall_name`（已存在则跳过）            |\r\n| **打开站斧** / 探测到**站斧未打开**（`GetBrowserList` 无 HTTP 响应）        | **立刻清空**整个 `malls` 列表（丢弃此前写入的店铺名），再冷启动 |\r\n| 客户发送**关闭店铺 {店铺名}** 且 `CloseBrowser` 成功                     | **去掉**该 `mall_name`                    |\r\n| 客户发送**关闭站斧** / `ExitClient` / 冷启动重启站斧 / `ClearCacheFolder` | **清空**整个 `malls` 列表                    |\r\n| 清除单店缓存 `ClearCache` 成功                                     | **去掉**该店铺名                             |\r\n\r\n\r\n> `opening_malls.json` 只记店铺名，与 `mall_cache.json`（店铺 ID）无关。**禁止**在站斧未打开时写入店铺名。\r\n\r\n---\r\n\r\n## 本地店铺 ID 缓存 `mall_cache.json`\r\n\r\n路径：Skill 目录下 `[mall_cache.json](mall_cache.json)`（与 `SKILL.md` 同级）。\r\n\r\n```json\r\n{\r\n  \"mall_map\": {\r\n    \"ztest126\": \"2786463\",\r\n    \"测试WebDriver随机950317\": \"2786500\"\r\n  },\r\n  \"updated_at\": \"2026-06-24T16:30:00\"\r\n}\r\n```\r\n\r\n\r\n| 字段           | 说明                                                                         |\r\n| ------------ | -------------------------------------------------------------------------- |\r\n| `mall_map`   | 店铺名 → 店铺 ID（`mall_id`）映射；键为**客户提供的店铺名**（与 `GetMallByName` 的 `mallName` 一致） |\r\n| `updated_at` | 最近一次写入时间                                                                   |\r\n\r\n\r\n### resolve mall_id（统一查 ID 流程）\r\n\r\n凡需 `mall_id` 的操作（开/关店铺、`ClearCache`、`GetBrowserWebDriver` 等），**一律先走缓存**：\r\n\r\n```\r\n1. 读 mall_cache.json → mall_map[mall_name] 有值？\r\n   ├─ 是 → 直接用该 mall_id（跳过 GetMallByName）\r\n   └─ 否 → 调用 GetMallByName → 成功后立即写入 mall_map\r\n2. 使用 mall_id 调用后续 API\r\n3. 若后续 API 因店铺 ID 无效失败（如 CloseBrowser returnObj===false）：\r\n   → 删除 mall_map 中该 mall_name 条目\r\n   → 重新 GetMallByName 取 id 并写回缓存\r\n   → 用新 id 重试一次（仍失败则立即结束）\r\n```\r\n\r\n\r\n| 时机                                                                    | 动作                                                             |\r\n| --------------------------------------------------------------------- | -------------------------------------------------------------- |\r\n| 开/关店铺、清缓存、取 WebDriver 等需 `mall_id`                                    | **先读** `mall_cache.json`；命中则**跳过** `GetMallByName`             |\r\n| 缓存未命中                                                                 | `GetMallByName` 成功后**立即写入** `mall_map`                         |\r\n| `GetBrowserList`（登录探测或客户查列表）                                          | 将 `mall_list` 中每条 `mall_name` → `mall_id` **批量写入**缓存（已有且相同则跳过） |\r\n| `CreateBrowser` 成功后                                                   | 等待同步 → `GetMallByName` → 写入缓存                                  |\r\n| 使用缓存 id 调用 `CloseBrowser` / `OpenBrowser` / `GetBrowserWebDriver` 等失败 | **删除**该条缓存 → `GetMallByName` 刷新 → 写回 → **仅重试一次**               |\r\n\r\n\r\n> **注意**：`mall_cache.json` 记录的是店铺 ID，与站斧「清除店铺缓存」(`ClearCache`) 无关；清浏览器缓存**不要**清空 `mall_cache.json`。\r\n\r\n---\r\n\r\n## 已打开店铺的确认（OpenBrowser 前）\r\n\r\n客户要求**打开**某店铺时：\r\n\r\n1. **立刻**将 `mall_name` 写入 `opening_malls.json`（见「打开意图配置」；站斧须已打开）\r\n2. resolve mall_id 拿到 `mall_id`\r\n3. **先**调 `GetBrowserWebDriver` 判断目标店铺是否已打开——**只请求一次，超时固定 5 秒**\r\n\r\n```json\r\n{\"action\": \"GetBrowserWebDriver\", \"module\": \"WebDriverModule\", \"browserId\": \"3514488\"}\r\n```\r\n\r\n> **`browserId` 必须为字符串**（如 `\"3514488\"`），**禁止**传 JSON 数字。\r\n\r\n**判定已打开**：5s 内 `returnObj.success == true` 且 `WebDriverPort` 有值。\r\n\r\n### 探测规则（一律单次 5s，禁止加长或重试）\r\n\r\n\r\n| 步骤                     | 规则                                                                              |\r\n| ---------------------- | ------------------------------------------------------------------------------- |\r\n| 次数 / 超时                | **只请求 1 次**，HTTP `timeout=5`；**禁止**先用 15s 再探测、**禁止**连打第二次                       |\r\n| 5s 内拿到端口               | 按「已打开」处理（询问是否关闭）                                                                |\r\n| **5s 超时 / 连接异常 / 无端口** | **视为未开**，**不要结束流程**，**直接 `OpenBrowser`** → 等 15s → 再 `GetBrowserWebDriver`（取端口） |\r\n\r\n\r\n\r\n| 情况                         | 动作                                                                                                                                   |\r\n| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |\r\n| 目标店铺**未打开**（含探测 **5s 超时**） | 直接 `OpenBrowser` → 等 15s → `GetBrowserWebDriver`                                                                                     |\r\n| 目标店铺**已打开**                | **必须先询问客户**：「店铺 {mall_name} 已打开（WebDriverPort={port}），是否需要关闭店铺？」                                                                     |\r\n| 客户确认**需要关闭**               | `CloseBrowser` → 从 `opening_malls.json` 去掉该名 → 确认关闭成功后，再询问是否重新 `OpenBrowser`；确认后再写入配置并 `OpenBrowser` → 等 15s → `GetBrowserWebDriver` |\r\n| 客户确认**不需要关闭** / 继续使用当前店铺   | **跳过** `OpenBrowser` 与 `CloseBrowser`，直接用现有 `WebDriverPort` 进入阶段 B 或结束                                                               |\r\n| 客户未明确表态                    | **不得**擅自 `OpenBrowser` 或 `CloseBrowser`，等待客户回复                                                                                       |\r\n\r\n\r\n**禁止**：\r\n\r\n- 检测到店铺已打开仍静默调用 `OpenBrowser`（会干扰客户当前页面）\r\n- 检测到店铺已打开未经确认就调用 `CloseBrowser`\r\n- OpenBrowser 前因 `GetBrowserWebDriver` **超时**而整流程失败退出（应改走 `OpenBrowser`）\r\n- OpenBrowser 前对 `GetBrowserWebDriver` **重试或拉长超时**（整体只许 **1 次 × 5s**）\r\n\r\n**与客户说「关闭店铺」的区别**：客户**明确说关闭**且 HTTP 正常 → 直接 `CloseBrowser` 并清理 `opening_malls.json`，无需再问是否关闭；客户**说打开**但检测到已开 → 才须询问是否关闭。\r\n\r\n---\r\n\r\n## 启动站斧（阶段 A · 仅冷启动时）\r\n\r\n**仅当** 目标端口无 HTTP 响应，或端口上是**非站斧 WebDriver** 服务时，才执行：\r\n\r\n1. **立刻清空 `opening_malls.json`**（打开站斧命令检测到未打开时必须清理已写入的店铺名）\r\n2. 杀进程（按 OS；**只杀站斧，不要停掉占用端口的其他服务**）：\r\n\r\n**Windows**：\r\n\r\n```bat\r\ntaskkill /f /t /im 站斧.exe\r\n```\r\n\r\n**macOS**：\r\n\r\n```bash\r\nkillall 站斧\r\n```\r\n\r\n杀进程后**最多等 1s**（可用短轮询看进程是否消失）；进程已退出则**立刻**继续，**禁止**固定干等 3s。\r\n\r\n3. **分配空闲端口**（判定站斧未打开后必做）：`api_port = get_available_port(首选)`（首选 = `api_port.json` 的 `api_port` 或默认 `12678`）；用 `socket.bind((\"127.0.0.1\", port))` 探测——**能 bind = 空闲**；失败则 `port += 1` 继续。12678 被占用则自动用 12679…，**禁止**因此停下来要求客户释放端口，**禁止**盲扫 8081/8082。\r\n4. 再以 WebDriver 参数启动（见上文接口清单；**Win/Mac 均四项缺一不可、禁止减少**；**macOS 用 `open -a`，同样带 `--multip`**），`--httpport=` 用上一步分配的端口。\r\n5. 启动后**立刻**轮询 `GetBrowserList`（对**实际端口**，间隔 **0.5s**，总计最多 **8s**），端口/列表就绪即继续；**禁止**启动后再固定 sleep 再探测。\r\n6. **8s 内仍无 WebDriver 通讯** → **立即停止、禁止重试**，按「通讯失败对客户话术」提示客户。\r\n\r\n### 通讯失败对客户话术（冷启动后 8s 内无 WebDriver 通讯 · 必须原样）\r\n\r\n冷启动后轮询 `GetBrowserList` **总计 8s 仍无 HTTP 响应 / 未能建立 WebDriver 通讯**时：\r\n\r\n- **立即停止**，**禁止**重复尝试、换端口、再冷启动\r\n- **必须**向客户报告以下模板（`{install_path}` 换成已确认路径，如 `I:\\ZhanFu\\站斧.exe` 或 `/Applications/站斧.app`）：\r\n\r\n```\r\n站斧启动后 8 秒内未能建立 WebDriver 通讯，已按技能规则停止操作，未重复尝试。\r\n安装位置已确认：{install_path}。请确认站斧版本要求（Windows ≥ 5.2.12，macOS > 5.2.10）无误；若电脑因卡顿导致启动有延迟，可尝试再次打开站斧，请告诉我“打开站斧”。\r\n```\r\n\r\n**禁止**再说「请先手动打开站斧并确认版本为 WebDriver 版且不低于 5.2.12」；版本提醒**一律**写：**Windows ≥ 5.2.12，macOS > 5.2.10**。\r\n\r\n### 查找站斧（冷启动前 · 禁止全盘搜索）\r\n\r\n**必须按顺序、逐项尝试，命中即停**；**禁止** `where.exe` / `mdfind` 全盘扫、递归 glob、跨盘符搜索、翻代码库猜路径。\r\n\r\n#### Windows\r\n\r\n\r\n| 顺序  | 方式                                                    | 说明                                             |\r\n| --- | ----------------------------------------------------- | ---------------------------------------------- |\r\n| 0   | `**api_port.json` 的 `install_dir`**                   | 验证 `{install_dir}\\站斧.exe` 存在则直接使用；不存在则**跳过**   |\r\n| 1   | 桌面「站斧」快捷方式                                            | **仅**按文件名匹配含「站斧」的 `.lnk`，解析其 `TargetPath` 所在目录 |\r\n| 2   | `C:\\Users\\{用户名}\\AppData\\Local\\Programs\\ZhanFu\\站斧.exe` | `{用户名}` 取当前 Windows 登录名                        |\r\n| 3   | `C:\\Program Files\\ZhanFu\\站斧.exe`                      | 固定路径                                           |\r\n| 4   | **向客户索要**                                             | 提示：「未找到站斧安装目录，请提供站斧安装路径（含 站斧.exe 的文件夹）」        |\r\n\r\n\r\n#### macOS\r\n\r\n\r\n| 顺序  | 方式                                  | 说明                                                             |\r\n| --- | ----------------------------------- | -------------------------------------------------------------- |\r\n| 0   | `**api_port.json` 的 `install_dir`** | 验证为存在的 `站斧.app`（或目录内含 `站斧.app`）则直接使用；无效则**跳过**                 |\r\n| 1   | `/Applications/站斧.app`              | 系统 Applications                                                |\r\n| 2   | `~/Applications/站斧.app`             | 用户 Applications                                                |\r\n| 3   | **向客户索要**                           | 提示：「未找到站斧.app，请提供路径（如 /Applications/站斧.app）」；**禁止**全盘 `mdfind` |\r\n\r\n\r\n**任一顺序命中后**：立即把该路径写入 `api_port.json` 的 `install_dir`，再冷启动。\r\n\r\n**客户提供路径后**：\r\n\r\n- Windows：仅检查 `{folder_path}\\站斧.exe` 是否存在\r\n- macOS：仅检查路径为 `站斧.app` 或目录内含 `站斧.app`\r\n\r\n验证通过后**写入** `install_dir`；不存在则**立即结束**并再次提示路径无效。\r\n\r\n#### 快捷方式解析规则（Windows 顺序 1 · 只查名为「站斧」的快捷方式）\r\n\r\n**只查找快捷方式文件名中含「站斧」的 `.lnk`**，**禁止**遍历桌面全部快捷方式，**禁止**解析文件名不含「站斧」的 `.lnk`（无论其目标 exe 名称为何）。\r\n\r\n查找范围：当前用户桌面 + 公共桌面（`Desktop`、`Public\\Desktop`）。\r\n\r\n**文件名匹配**（按序尝试，解析到有效 `站斧.exe` 即停）：\r\n\r\n1. 精确名：`站斧.lnk`、`站斧浏览器.lnk`\r\n2. 通配：`*站斧*.lnk`（**仅**文件名包含「站斧」者，如 `站斧浏览器完成版.lnk`）\r\n\r\n对每个命中的 `.lnk`：\r\n\r\n1. 解析 `TargetPath`（PowerShell `WScript.Shell.CreateShortcut` 或等价方式）\r\n2. 取目标文件所在目录为 `install_dir`\r\n3. 若 `TargetPath` 本身为 `站斧.exe` → 直接使用\r\n4. 否则检查 `{install_dir}\\站斧.exe`；存在则使用\r\n\r\n全部快捷方式均未解析出 `站斧.exe` → 进入顺序 2（固定安装路径），**不得**改用其他命名规则的快捷方式兜底。\r\n\r\n---\r\n\r\n## 阶段 A 操作要点（HTTP only，失败即停）\r\n\r\n### GetBrowserList（判断站斧是否已打开 + 登录态 · 必做 · 总计最多 8s）\r\n\r\n**禁止**用 `CheckClientOpen` / `LoadSuccess` / `LoadFailed` 判断站斧是否已打开。冷启动或复用后**直接**轮询 `GetBrowserList`：\r\n\r\n```json\r\n{\"action\": \"GetBrowserList\", \"module\": \"WebDriverModule\", \"args\": \"{\\\"page\\\":1,\\\"limit\\\":20}\"}\r\n```\r\n\r\n- **轮询** `GetBrowserList`，间隔 **0.5s**，**总计最多 8s**\r\n- `returnObj.success == true` **且** `returnObj.data.mall_list` 可解析（非 `null`）→ **站斧已打开且已登录**，**禁止**无故调用 `Login`；**同时将 `mall_list` 中 `mall_name` → `mall_id` 写入 `mall_cache.json`**\r\n- 有 HTTP 响应但 **8s 内**仍 `success=false`、`data=null`、无法解析 `mall_list` → **停止**，提示客户：**「站斧未登录，请提供账号和密码」**；拿到凭证后再 `Login`（**禁止**因此冷启动）\r\n- 连接拒绝 / 无响应 → **站斧未打开**，走冷启动\r\n- 客户未提供账号密码 → **停止**，不猜测、不擅自登录\r\n- **单次请求** `timeout=1.5`；Agent **只用 Python requests**，禁止为通断探测切换 PowerShell/curl\r\n\r\n> `CheckClientOpen` **不再作为流程步骤**；勿等待 `LoadSuccess`。\r\n\r\n### Login\r\n\r\n仅在 `GetBrowserList` 表明未登录且**客户已提供**账号密码时调用；`isboss` **固定** `true`。**禁止**使用内测或历史会话中的账号。`success != true` → **立即结束**。\r\n\r\n### GetMallByName / resolve mall_id / CreateBrowser\r\n\r\n**resolve mall_id**：先读 `mall_cache.json`；未命中才调 `GetMallByName`，成功后立即写缓存。\r\n\r\n任一步 `GetMallByName` / `CreateBrowser` 的 `success != true` 或缺字段 → **立即结束**，不重试（缓存 id 导致后续 API 失败时的**一次**刷新重试除外，见「本地店铺 ID 缓存」）。\r\n\r\n### UpdateAccount（修改店铺账号密码）\r\n\r\n客户要求**修改店铺登录账号/密码**时调用。须站斧已打开且已登录；先 resolve `mall_id`，再：\r\n\r\n```json\r\n{\r\n  \"action\": \"UpdateAccount\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"3514488\",\r\n  \"args\": \"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"cyt123456A\\\"}\"\r\n}\r\n```\r\n\r\n\r\n| 字段 | 必填 | 说明 |\r\n| ---- | --- | ---- |\r\n| `browserId` | 是 | 店铺 `mall_id`（**必须为字符串**） |\r\n| `args.username` | 否 | 店铺账号（对应 `mall_account`；可空字符串） |\r\n| `args.password` | 否 | 店铺密码（对应 `mall_password`；可空字符串） |\r\n\r\n\r\n- 缺少店铺名/`mall_id` 或客户未说明要改的账号/密码时 → **先询问**，禁止猜测\r\n- `returnObj.success != true` → **立即结束**，原样报告 `returnObj.msg`（如「缺少 browserId」）\r\n- 成功：`success == true`（`data` 可为 `{}`）\r\n\r\n### OpenBrowser（须先过「已打开店铺确认」）\r\n\r\n```json\r\n{\"action\": \"OpenBrowser\", \"module\": \"WebDriverModule\", \"browserId\": \"3514488\", \"args\": \"{\\\"isDownLoadConfirm\\\":false,\\\"isOpenMallIndex\\\":true,\\\"isSwitchDynamicNetwork\\\":false}\"}\r\n```\r\n\r\n- **`browserId` 必须是字符串**（`\"3514488\"`），**禁止**数字 `3514488`\r\n- **仅站斧已打开后**再写入 `opening_malls.json`（探测未打开时已清空，禁止未打开就写入）\r\n- 目标店铺**未打开**（含 OpenBrowser 前探测 **5s 超时**）→ 可直接 `OpenBrowser`\r\n- 目标店铺**已打开**（客户要求**打开**该店）→ 须先询问客户**是否需要关闭店铺**；确认关闭后再视情况 `CloseBrowser` / `OpenBrowser`（见「已打开店铺的确认」）\r\n- 客户**明确说关闭店铺**且 HTTP 正常 → 直接 `CloseBrowser`，清理 `opening_malls.json`，**不重启**站斧\r\n- `OpenBrowser` 本身 `returnObj !== true` 或 `ret != 200` → **立即结束**，并**提醒客户**：\r\n  > **打开店铺失败，请确认该店铺是否已绑定 IP / 设备。** 可在站斧客户端查看店铺绑定设备后再试。\r\n- `OpenBrowser` **之后**的 `GetBrowserWebDriver` 失败（含「超时未获取到」）→ 同上，**一并提醒检查 IP/设备绑定**；并提醒客户：**首次使用请先在站斧客户端手动打开该店铺以下载内核；不同内核的店铺需分别手动打开一次**\r\n\r\n### GetBrowserWebDriver\r\n\r\n```json\r\n{\"action\": \"GetBrowserWebDriver\", \"module\": \"WebDriverModule\", \"browserId\": \"3514488\"}\r\n```\r\n\r\n- **`browserId` 必须是字符串**（`\"3514488\"`），**禁止**数字 `3514488`\r\n- **OpenBrowser 前探测（是否已开）**：**只请求 1 次，`timeout=5`**；超时/无端口 → **仍 `OpenBrowser`**；禁止重试、禁止加长超时\r\n- **OpenBrowser 后取端口**：`WebDriverPort` 为空或请求失败 → **立即结束**（禁止循环重试、禁止「再等一会」方案）\r\n- `OpenBrowser` 后允许**单次**固定等待 15s 再调 `GetBrowserWebDriver`（不算重试）；若仍失败则结束。\r\n- **macOS 内核检查（拿到端口后、进入阶段 B 前必做）**：若当前 OS 为 **macOS**，且 `returnObj.KernalNumber` 存在且 **≤ 130** → **立即停止**，**禁止** `connect_over_cdp` / 页面自动化，按下方「macOS 低内核对客户话术」提示客户；**Windows 不校验此限制**。复用已开店铺（客户确认不关闭、直接用现有端口）时同样要检查 `KernalNumber`。\r\n\r\n### macOS 低内核对客户话术（KernalNumber ≤ 130 · 必须原样）\r\n\r\n当 **macOS** 且打开店铺后 `GetBrowserWebDriver` 返回 `KernalNumber ≤ 130`（含已打开店铺复用端口的场景）时：\r\n\r\n- **立即停止**，**禁止**进入阶段 B，**禁止**代客户改内核或自动重启站斧\r\n- **必须**向客户报告以下模板（`{kernel}` 换成实际 `KernalNumber`，`{mall_name}` 换成店铺名）：\r\n\r\n```\r\n当前为 macOS，店铺 {mall_name} 的内核为 {kernel}（≤130），暂不支持自动化。\r\n请将该店铺切换到 130 以上内核；若无权限请让主账号切换。切换完成后请您手动重启站斧，再告诉我继续。\r\n```\r\n\r\n---\r\n\r\n## 阶段 B：Playwright CDP（端口拿到后）\r\n\r\n> **macOS**：进入本节前须已确认 `KernalNumber > 130`；否则不得 `connect_over_cdp`。\r\n```python\r\nfrom headed_mode import ensure_headed_mode\r\nfrom playwright.sync_api import sync_playwright\r\n\r\nensure_headed_mode()\r\nbrowser = sync_playwright().start().chromium.connect_over_cdp(\r\n    f\"http://127.0.0.1:{webdriver_port}\"\r\n)\r\n```\r\n\r\n连接失败 → **立即结束**，禁止换系统浏览器替代。\r\n\r\n### 设备安全检测\r\n\r\n找 URL 含 `check.html` 的标签页，**15s 内**轮询，满足以下**任一**条件即视为检测通过：\r\n\r\n1. **「打开店铺」按钮未禁用**（`.openMallOpenBtn`，且非 `disabled` / `aria-disabled=true` / `is-disabled`）\r\n2. **标签页数量 ≥ 2**（通常表示店铺页已打开）\r\n\r\n15s 内仍不满足 → 告知「没检测成功无法进行自动化」，立即结束。\r\n\r\n可运行 Skill 内置（**仅阶段 B**）：\r\n\r\n```bash\r\npython scripts/check_device_security.py --port {webdriver_port} --wait --timeout 15\r\n```\r\n\r\n### 业务自动化\r\n\r\n检测通过后，按客户需求用 Playwright 操作页面。**禁止**在 Skill 目录新增业务脚本；临时逻辑在对话中执行，不落盘为 `.py`。\r\n\r\n---\r\n\r\n## 收尾（阶段 A · HTTP）\r\n\r\n**关闭店铺**（客户明确要求时）：\r\n\r\n```json\r\n{\"action\": \"CloseBrowser\", \"module\": \"WebDriverModule\", \"browserId\": \"3514488\"}\r\n```\r\n\r\n成功后**从 `opening_malls.json` 去掉该 `mall_name`**。\r\n\r\n**退出站斧客户端**（仅客户明确要求「退出站斧」时；开/关店铺**不要**顺带调用）：\r\n\r\n```json\r\n{\"action\": \"ExitClient\", \"module\": \"WebDriverModule\", \"args\": \"\"}\r\n```\r\n\r\n成功后（或冷启动重启前）**清空 `opening_malls.json`**。\r\n\r\n---\r\n\r\n## 失败处理（统一）\r\n\r\n\r\n| 情况                                                 | 动作                                                                                                                  |\r\n| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |\r\n| 目标端口无 HTTP 响应 / **打开站斧且站斧未打开**                     | **立刻清空 `opening_malls.json`** → 查安装目录（快捷方式/常见目录找不到则向客户索要）→ **`get_available_port(首选)`（占用则递增）** → 冷启动并写 `api_port.json`；冷启动后 **8s 仍无通讯** → 按「通讯失败对客户话术」报告（版本无误且卡顿可延迟时可再试，请客户说「打开站斧」） |\r\n| `GetBrowserList` 能取到数据 + **打开店铺**                  | **站斧已打开，不重启**；写入 `opening_malls.json` → HTTP 开店铺流程                                                                  |\r\n| `GetBrowserList` 能取到数据 + **关闭店铺**                  | **不重启**；resolve mall_id → `CloseBrowser` → 清理 `opening_malls.json`                                                  |\r\n| API 已运行 + 开新店铺                                     | **不重启**站斧，直接 HTTP 开店铺                                                                                               |\r\n| 目标店铺已打开（客户要求**打开**）                                | **询问客户**是否需要关闭店铺；未确认不调用 `OpenBrowser` / `CloseBrowser`                                                              |\r\n| OpenBrowser 前 `GetBrowserWebDriver` **5s 超时**      | **不结束**；继续 `OpenBrowser`（只许探测 1 次）                                                                                  |\r\n| 客户明确要求关闭已开店铺                                       | 直接 `CloseBrowser` → 清理 `opening_malls.json`                                                                         |\r\n| 客户明确要求关闭站斧                                         | `ExitClient` → **清空** `opening_malls.json`                                                                          |\r\n| GetBrowserList 8s 内仍无法确认登录（**确认为站斧** WebDriver 有响应） | **停止**，提示客户提供账号密码；**禁止**擅自或内测账号 Login；**禁止**用 `LoadSuccess` 判断。若其实是非站斧占用，应走空闲端口冷启动而非要密码 |\r\n| OpenBrowser / OpenBrowser 后 GetBrowserWebDriver 失败 | 立即结束；`OpenBrowser` 以 `returnObj===true` 判成功；提醒检查 **IP/设备绑定** 及 **是否已手动打开该店铺下载内核**（版本要求：Windows ≥ 5.2.12，macOS > 5.2.10）                     |\r\n| **macOS** 且 `KernalNumber ≤ 130`（打开/复用店铺后） | **立即停止**；按「macOS 低内核对客户话术」提示：切换到 **130 以上**内核或请**主账号**切换，并请客户**手动重启站斧**后再继续；**禁止**阶段 B |\r\n| CloseBrowser 返回 `returnObj===false`                | 立即结束，报告关闭失败                                                                                                         |\r\n| 其他关键 API 失败                                        | 立即结束，原样报告 `returnObj.msg`（`OpenBrowser`/`CloseBrowser` 无 `msg` 时报告 `returnObj` 值）                                   |\r\n| OpenBrowser 后拿不到 WebDriverPort                     | 立即结束，不 retry                                                                                                        |\r\n| 设备安全检测 15s 超时                                      | 立即结束，告知「没检测成功无法进行自动化」                                                                                               |\r\n| CDP 连接失败                                           | 立即结束，禁止换浏览器                                                                                                         |\r\n\r\n\r\n**禁止**：重试、翻代码、写备用脚本、写「稍后重跑」方案；**禁止**用 `LoadSuccess` 判断站斧是否已打开。\r\n\r\n---\r\n\r\n## 参考脚本（仅供本地调试，Agent 获取端口前勿运行）\r\n\r\n- [scripts/zhanfu_playwright.py](scripts/zhanfu_playwright.py) — 全流程参考实现\r\n- [scripts/check_device_security.py](scripts/check_device_security.py) — 阶段 B 设备检测\r\n- [scripts/headed_mode.py](scripts/headed_mode.py) — 强制有界面\r\n\r\nAPI 详情（含通用约定与全部接口）：[reference.md](r\n\nFile v1.0.5:_meta.json\n\n{\n  \"ownerId\": \"kn79xm4hxd563stv6msvy8bvn98ae9jy\",\n  \"slug\": \"zhanfu-playwright\",\n  \"version\": \"1.0.5\",\n  \"publishedAt\": 1787798092302\n}\n\nFile v1.0.5:scripts/requirements.txt\n\nplaywright>=1.40.0\r\nrequests>=2.28.0\n\nFile v1.0.5:reference.md\n\n# 站斧 WebDriver API 参考\r\n\r\n> 模块固定为 `WebDriverModule`，通过 HTTP 服务调用。本文与官方《站斧 WebDriver 接口文档》对齐。\r\n\r\nHTTP 入口：`POST http://127.0.0.1:{api_port}`，Body 为 JSON。\r\n\r\n**默认 API 端口**：`12678`（优先）。Skill 目录 [`api_port.json`](api_port.json) 记录上次成功端口与安装目录；任务开始先探测该端口（用 `GetBrowserList`，**禁止**用 `LoadSuccess` 判断）。无响应或被非站斧占用 → 空闲端口冷启动并写回；**禁止**盲扫 8081/8082 碰已运行站斧；**禁止**因 12678 被占用而要求客户先释放。\r\n\r\n> **识别非站斧占用**：POST `GetBrowserList` 后若响应不是 `WebDriverModule` 结构（如「Electron 本地打包控制台」），视为其他服务占用 → 换空闲端口冷启动，**勿**停止占用方。\r\n\r\n**店铺 ID 缓存**：Skill 目录 [`mall_cache.json`](mall_cache.json) 记录 `mall_name` → `mall_id` 映射。需要 `mall_id` 时**先读缓存**，未命中再 `GetMallByName` 并写回；`GetBrowserList` 返回的 `mall_list` 亦应批量写入缓存。\r\n\r\n**打开意图配置**：Skill 目录 [`opening_malls.json`](opening_malls.json) 记录客户已下达「打开」指令的店铺名。关店 / 关站斧时清理。OpenBrowser 前用 `GetBrowserWebDriver` **只请求 1 次、超时 5s**；超时仍执行 `OpenBrowser`。\r\n\r\n**请求方式**：阶段 A **优先 Python `requests`（`timeout=1.5`）**；**禁止**为同一探测在 PowerShell/curl/Python 间换工具试错；**禁止** Windows `curl` 手工转义 JSON。\r\n\r\n## 通用约定\r\n\r\n### 请求结构\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `action` | 接口动作名 |\r\n| `module` | 固定为 `WebDriverModule` |\r\n| `args` | JSON 字符串，承载业务参数 |\r\n| `browserId` | 部分接口需要的店铺 ID（与 `mall_id` 相同）；**必须为 JSON 字符串**（如 `\"3514488\"`），**禁止**传数字 |\r\n\r\n### 响应结构\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `ret` | HTTP 分发状态码：`200` 表示请求已正常分发处理；`400` / `500` 表示异常请求或框架级错误 |\r\n| `returnObj` | 业务返回值；结构因接口而异 |\r\n| `action` | 回显请求动作 |\r\n| `module` | 回显请求模块 |\r\n\r\n框架级错误示例（`ret=500`）：\r\n\r\n```json\r\n{\r\n  \"ret\": 500,\r\n  \"error\": \"未找到方法\",\r\n  \"action\": \"XXX\",\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n### 业务成功判断\r\n\r\n| 返回类型 | 判断方式 |\r\n|----------|----------|\r\n| `{ success, msg, ... }` | 以 `returnObj.success` 为准（如 `Login`、`GetMallByName`、`UpdateAccount`、`GetBrowserWebDriver`） |\r\n| `true` / `false` | 如 `OpenBrowser`：成功 `returnObj === true`，失败 `returnObj === false` |\r\n| `null` | 如 `CloseBrowser`、`ExitClient` 成功时 `returnObj` 为 `null`；`CloseBrowser` 失败时 `returnObj === false` |\r\n\r\n### 典型调用流程\r\n\r\n```\r\nLogin → SetInstallPlugins（可选，仅 Windows）→ GetBrowserList / GetMallByName → CreateBrowser（可选）\r\n→ SetDownLoadPath（可选，仅 Windows）→ GetWebDriver（Selenium 可选，Playwright 跳过）\r\n→ OpenBrowser → GetBrowserWebDriver → 自动化操作\r\n→ CloseBrowser → ExitClient（结束）\r\n```\r\n\r\n> **macOS 暂不支持**：`SetDownLoadPath`、`ClearCacheFolder`、`ClearCache`、`SetInstallPlugins`。Agent 不得在 Mac 上调用这些 action。\r\n>\r\n> **macOS 内核**：`KernalNumber ≤ 130` 的店铺**不支持**自动化；须提示切换到 130 以上内核（或主账号切换）并让客户**手动重启站斧**。\r\n\r\n## 启动站斧\r\n\r\n**Windows**（**四项缺一不可，禁止减少/省略任一参数**）：\r\n\r\n```\r\n站斧.exe --multip --run_type=web_driver --ipc_type=http --httpport={api_port}\r\n```\r\n\r\n| 参数 | 可否省略 |\r\n|------|----------|\r\n| `--multip` | **否** |\r\n| `--run_type=web_driver` | **否** |\r\n| `--ipc_type=http` | **否** |\r\n| `--httpport={api_port}` | **否**（值可变，键不可少） |\r\n\r\n**macOS**（**四项缺一不可，禁止减少/省略任一参数**，与 Windows 相同；用 `open -a` 启动）：\r\n\r\n```\r\nopen -a /Applications/站斧.app --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}\r\n```\r\n\r\n也可：`open -a 站斧 --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}`\r\n\r\n| 参数 | 可否省略 |\r\n|------|----------|\r\n| `--multip` | **否** |\r\n| `--run_type=web_driver` | **否** |\r\n| `--ipc_type=http` | **否** |\r\n| `--httpport={api_port}` | **否**（值可变，键不可少） |\r\n\r\n`{api_port}` = `get_available_port(首选)`，首选默认 `12678`（占用则递增）。\r\n\r\n关闭旧进程：\r\n\r\n- Windows：`taskkill /f /t /im 站斧.exe`\r\n- macOS：`killall 站斧`\r\n\r\n- **禁止减少启动参数**（Windows / macOS 均不得去掉 `--multip` / `--run_type` / `--ipc_type` / `--httpport` 任一）\r\n- `run_type` 必须为 `web_driver`\r\n- `ipc_type` 必须为 `http`\r\n- 冷启动端口写入 Skill 目录 `api_port.json`\r\n\r\n### 查找站斧（冷启动前）\r\n\r\n**先读** `api_port.json` 的 `install_dir`，验证有效则直接用；无效再按 OS 顺序尝试，命中即停；**禁止**全盘搜索。\r\n\r\n#### Windows\r\n\r\n0. **`api_port.json` 的 `install_dir`**（本地缓存，优先；验证 `{install_dir}\\站斧.exe`）\r\n1. **桌面快捷方式（仅文件名含「站斧」）**：在用户桌面与公共桌面查找 `站斧.lnk`、`站斧浏览器.lnk`、`*站斧*.lnk`；解析 `TargetPath` 所在目录，取该目录下 `站斧.exe`（或目标本身即为 `站斧.exe`）。**不得**解析文件名不含「站斧」的快捷方式。\r\n2. `%LOCALAPPDATA%\\Programs\\ZhanFu\\站斧.exe`\r\n3. `C:\\Program Files\\ZhanFu\\站斧.exe`\r\n4. **向客户索要** `folder_path`：**快捷方式与常见目录均未命中时必须停止询问客户**，禁止猜路径或全盘搜索\r\n\r\n#### macOS\r\n\r\n0. **`api_port.json` 的 `install_dir`**（须为存在的 `站斧.app`，或目录内含 `站斧.app`）\r\n1. `/Applications/站斧.app`\r\n2. `~/Applications/站斧.app`\r\n3. **向客户索要** `.app` 路径；**禁止**全盘 `mdfind` / `find`\r\n\r\n**任一顺序命中后**：立即写入 `api_port.json` 的 `install_dir`。客户提供路径后按 OS 验证再写入。\r\n\r\n## 端口探测（阶段 A 第一步）\r\n\r\n1. 读 `api_port.json` 的 `api_port`；无文件则用 `12678`\r\n2. 对该端口 POST `GetBrowserList`（正确 JSON，单次）\r\n3. **确认为站斧 WebDriver** 且能取到 `mall_list` → **站斧已打开**，复用，刷新 `api_port.json`\r\n4. **确认为站斧 WebDriver** 但取不到 `mall_list` → 可能未登录；**禁止冷启动**，走登录提示\r\n5. **非站斧 HTTP**（如 Electron 控制台）或 **连接拒绝/超时** → **立刻清空 `opening_malls.json`** → 查安装路径 → 杀站斧进程（勿停占用方）→ **`get_available_port(首选)` 空闲端口冷启动** → 写 `api_port.json`\r\n\r\n> **禁止**用 `CheckClientOpen` / `LoadSuccess` / `LoadFailed` 判断站斧是否已打开。\r\n> **禁止**因 12678 被占用而要求客户先停掉其他服务。\r\n\r\n## 打开店铺 / 关闭店铺（HTTP 正常则不重启）\r\n\r\n| 客户意图 | `GetBrowserList` 确认为站斧 / 有响应 | 动作 |\r\n|----------|--------------------------------------|------|\r\n| 打开店铺 | 是（站斧 WebDriver） | **不重启**；写入 `opening_malls.json` → resolve mall_id → `GetBrowserWebDriver` **单次 5s** 判是否已开（超时仍 `OpenBrowser`）→ 已开则询问是否关闭 → 未开则 `OpenBrowser` |\r\n| 关闭店铺 | 是 | **不重启**；resolve mall_id → `CloseBrowser` → 从 `opening_malls.json` 去掉该店；**勿**调用 `ExitClient`（除非客户明确要求退出站斧） |\r\n| 关闭站斧 | — | `ExitClient` → **清空** `opening_malls.json` |\r\n| **打开站斧** | 否（无响应或非站斧占用） | **立刻清空 `opening_malls.json`** → 查安装目录 → **空闲端口**冷启动 → 站斧就绪后再写店铺名/开店 |\r\n| 打开 / 关闭 | 否（无响应或非站斧占用） | **立刻清空 `opening_malls.json`** → 空闲端口冷启动后再走上述 HTTP 流程 |\r\n\r\n**已打开 + 客户要求打开**：询问「是否需要关闭店铺？」；确认关闭 → `CloseBrowser` → 清理配置 → 再视客户意愿 `OpenBrowser`。\r\n\r\n**客户明确要求关闭**：直接 `CloseBrowser` 并清理 `opening_malls.json`，无需再问。\r\n\r\n## CheckClientOpen（已弃用为运行态判断）\r\n\r\n**不再用于判断站斧是否已打开**。流程以 `GetBrowserList` 能取到数据为准。接口仍可能存在于客户端，但 Agent **勿**依赖其 `LoadSuccess` / `LoadFailed`。\r\n\r\n```json\r\n{\"action\": \"CheckClientOpen\", \"module\": \"WebDriverModule\"}\r\n```\r\n\r\n## GetBrowserList\r\n\r\n**判断站斧是否已打开 + 登录态探测（阶段 A 必调）**：冷启动或复用后**直接**调用；**轮询总计最多 8s**。`returnObj.success == true` 且 `returnObj.data.mall_list` 可解析 → **站斧已打开且已登录**；有站斧 HTTP 响应但取不到数据 → 未登录，**停止**并提示客户提供账号密码（禁止因此冷启动）；无 HTTP 响应或非站斧占用 → 站斧未打开，空闲端口冷启动。\r\n\r\n**也可用于客户「查看店铺列表」**：按 `page` / `limit` 分页返回账号下店铺。\r\n\r\n请求：\r\n\r\n```json\r\n{\r\n  \"action\": \"GetBrowserList\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"page\\\":1,\\\"limit\\\":10}\"\r\n}\r\n```\r\n\r\n| args 字段 | 说明 |\r\n|-----------|------|\r\n| `page` | 页码，从 1 开始 |\r\n| `limit` | 每页店铺数量 |\r\n\r\n响应示例：\r\n\r\n```json\r\n{\r\n  \"action\": \"GetBrowserList\",\r\n  \"ret\": 200,\r\n  \"returnObj\": {\r\n    \"success\": true,\r\n    \"data\": {\r\n      \"total\": 669,\r\n      \"page_count\": 67,\r\n      \"mall_list\": [\r\n        {\r\n          \"mall_id\": 2786463,\r\n          \"mall_name\": \"测试WebDriver随机950317\",\r\n          \"platform_name\": \"自定义平台\",\r\n          \"ip_address\": \"ip\",\r\n          \"created_at\": \"2025-12-25 17:49:55\",\r\n          \"updated_at\": \"2025-12-25 17:49:55\"\r\n        }\r\n      ]\r\n    },\r\n    \"msg\": \"\"\r\n  },\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n| 响应字段 | 说明 |\r\n|----------|------|\r\n| `data.total` | 店铺总数 |\r\n| `data.page_count` | 总页数 |\r\n| `mall_list[].mall_id` | 店铺 ID |\r\n| `mall_list[].mall_name` | 店铺名称 |\r\n| `mall_list[].platform_name` | 平台名称 |\r\n| `mall_list[].ip_address` | 绑定 IP |\r\n| `mall_list[].created_at` / `updated_at` | 创建/更新时间 |\r\n\r\n## Login\r\n\r\n登录或切换账号。**会关闭所有已打开店铺**；若当前已登录目标账号，无需重复调用。`GetBrowserList` 已成功时勿重复调用。\r\n\r\n仅使用**客户提供的**账号密码；`isboss` **固定** `true`（老板账号）。**禁止**在 Skill 或脚本中写入内测/示例账号。\r\n\r\n请求：\r\n\r\n```json\r\n{\r\n  \"action\": \"Login\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"***\\\",\\\"isboss\\\":true}\"\r\n}\r\n```\r\n\r\n响应：`returnObj.success`、`returnObj.msg`\r\n\r\n## GetMallByName\r\n\r\n按店铺名称查 `mall_id`。**仅在 `mall_cache.json` 未命中时调用**；成功后立即写入缓存。\r\n\r\n```json\r\n{\r\n  \"action\": \"GetMallByName\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"mallName\\\":\\\"WebDriverTest\\\"}\"\r\n}\r\n```\r\n\r\n| args 字段 | 说明 |\r\n|-----------|------|\r\n| `mallName` | 店铺名称（也支持 `mall_name`、`name`） |\r\n\r\n响应字段：`returnObj.data.mall_id`、`mall_name`、`platform_name`、`ip_address`、`remark`、`created_at`、`updated_at`。\r\n\r\n## CreateBrowser\r\n\r\n创建新店铺。`ret=200` 且 `returnObj.success=true` 表示成功；`successCount` 为成功创建数量。\r\n\r\n请求：\r\n\r\n```json\r\n{\r\n  \"action\": \"CreateBrowser\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"mall_name\\\":\\\"测试WebDriver随机950317\\\",\\\"mall_account\\\":\\\"test_account\\\",\\\"mall_password\\\":\\\"test_password\\\",\\\"platform\\\":\\\"自定义平台\\\",\\\"platform_url\\\":\\\"https://www.baidu.com\\\",\\\"mall_address\\\":\\\"\\\",\\\"tags\\\":\\\"\\\",\\\"authorizationMember\\\":\\\"\\\",\\\"ip_content\\\":\\\"IP\\\",\\\"browser_kernel_version\\\":0,\\\"window_ua\\\":\\\"\\\",\\\"mac_ua\\\":\\\"\\\",\\\"android_ua\\\":\\\"\\\",\\\"remark\\\":\\\"这是一个用于测试的店铺\\\"}\"\r\n}\r\n```\r\n\r\n响应示例：\r\n\r\n```json\r\n{\r\n  \"action\": \"CreateBrowser\",\r\n  \"ret\": 200,\r\n  \"returnObj\": {\r\n    \"success\": true,\r\n    \"data\": {\r\n      \"errorCount\": 0,\r\n      \"errorMsgData\": null,\r\n      \"successCount\": 1\r\n    },\r\n    \"msg\": \"\"\r\n  },\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n| args 字段 | 必填 | 说明 |\r\n|-----------|------|------|\r\n| `mall_name` | 是 | 店铺名，**不能重复** |\r\n| `mall_account` | 否 | 店铺账号 |\r\n| `mall_password` | 否 | 店铺密码 |\r\n| `platform` | 是 | 所属平台 |\r\n| `platform_url` | 自定义平台时必填 | 如 `https://www.baidu.com` |\r\n| `mall_address` | 否 | 店铺地址 |\r\n| `tags` | 否 | 标签 |\r\n| `authorizationMember` | 否 | 授权成员 |\r\n| `ip_content` | 否 | 绑定已有设备 IP |\r\n| `browser_kernel_version` | 否 | 不指定内核填 `0` |\r\n| `window_ua` / `mac_ua` / `android_ua` | 否 | UA |\r\n| `remark` | 否 | 备注 |\r\n\r\n创建成功后需**等待列表同步**，再 `GetMallByName` 取 `mall_id` 并 `OpenBrowser`。\r\n\r\n## UpdateAccount\r\n\r\n根据店铺 ID（`browserId`）修改店铺登录账号与密码。`browserId` 为店铺 `mall_id`；`args.username` 对应 `mall_account`，`args.password` 对应 `mall_password`（可空字符串）。\r\n\r\n请求：\r\n\r\n```json\r\n{\r\n  \"action\": \"UpdateAccount\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"3061488\",\r\n  \"args\": \"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"cyt123456A\\\"}\"\r\n}\r\n```\r\n\r\n| 字段 | 类型 | 说明 |\r\n|------|------|------|\r\n| `browserId` | string | 店铺 `mall_id` |\r\n| `username` | string | 店铺账号（对应 `mall_account`，可空） |\r\n| `password` | string | 店铺密码（对应 `mall_password`，可空） |\r\n\r\n成功：\r\n\r\n```json\r\n{\r\n  \"action\": \"UpdateAccount\",\r\n  \"ret\": 200,\r\n  \"returnObj\": {\r\n    \"success\": true,\r\n    \"data\": {},\r\n    \"msg\": \"\"\r\n  },\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n失败：\r\n\r\n```json\r\n{\r\n  \"action\": \"UpdateAccount\",\r\n  \"ret\": 200,\r\n  \"returnObj\": {\r\n    \"success\": false,\r\n    \"msg\": \"缺少 browserId\"\r\n  },\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `success` | 是否修改成功 |\r\n| `msg` | 提示信息 |\r\n| `data` | 成功时的接口返回数据 |\r\n\r\n以 `returnObj.success` 为准；`success != true` → 立即结束并原样报告 `msg`。调用前须 resolve `mall_id`（先读 `mall_cache.json`，未命中再 `GetMallByName`）。\r\n\r\n## OpenBrowser\r\n\r\n根据店铺 `mall_id` 打开店铺。\r\n\r\n```json\r\n{\r\n  \"action\": \"OpenBrowser\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"3061488\",\r\n  \"args\": \"{\\\"isDownLoadConfirm\\\":false,\\\"isOpenMallIndex\\\":true,\\\"isSwitchDynamicNetwork\\\":false}\"\r\n}\r\n```\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `browserId` | 店铺 `mall_id`；**必须为 JSON 字符串**（`\"3061488\"`），**禁止**传数字 `3061488` |\r\n| `isDownLoadConfirm` | 下载前是否询问每个文件的保存位置 |\r\n| `isOpenMallIndex` | 是否默认打开店铺首页 |\r\n| `isSwitchDynamicNetwork` | 绑定了动态 IP 的店铺，传 `true` 则切换动态网络 |\r\n\r\n**成功**：`returnObj === true`（布尔值，非 `{success}` 对象）\r\n\r\n**失败**：`returnObj === false`\r\n\r\n**打开失败时**：向客户提醒检查店铺是否已**绑定 IP/设备**。\r\n\r\n## GetBrowserWebDriver\r\n\r\n获取店铺 CDP 端口；**也用于判断目标店铺是否已打开**（`success=true` 且 `WebDriverPort` 有值 → 已打开）。\r\n\r\n- 客户要求**打开**且已开 → 询问是否需要**关闭店铺**；未确认不调用 `OpenBrowser` / `CloseBrowser`\r\n- 客户要求**关闭** → 直接 `CloseBrowser`，并清理 `opening_malls.json`\r\n- **OpenBrowser 前探测**：一律 **只请求 1 次、`timeout=5`**；超时则**仍执行 `OpenBrowser`**，不因此结束流程；禁止二次探测、禁止 15s 长超时\r\n\r\n```json\r\n{\r\n  \"action\": \"GetBrowserWebDriver\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"2786463\"\r\n}\r\n```\r\n\r\n> **`browserId` 必须为 JSON 字符串**（`\"2786463\"`），**禁止**传数字。从 API/`mall_cache` 取到的 `mall_id` 一律先 `str(mall_id)` 再写入。\r\n\r\n需在店铺**已打开**后调用（OpenBrowser 前探测时：未开或超时则视为未确认已开）。\r\n\r\n响应：\r\n\r\n```json\r\n{\r\n  \"action\": \"GetBrowserWebDriver\",\r\n  \"ret\": 200,\r\n  \"returnObj\": {\r\n    \"success\": true,\r\n    \"msg\": \"\",\r\n    \"WebDriverPort\": 12635,\r\n    \"MainHandle\": \"3020652\",\r\n    \"KernalNumber\": 137\r\n  },\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `WebDriverPort` | 外部 WebDriver 开发端口（Playwright CDP 用） |\r\n| `MainHandle` | 主窗口句柄 |\r\n| `KernalNumber` | 内核版本；**macOS** 下若 **≤ 130** 则**不支持** Playwright 自动化，须提示客户切换到 **130 以上**内核（或主账号切换）并**手动重启站斧**后停止 |\r\n\r\n失败示例：`returnObj.success === false`，`msg` 如「浏览器未启动」。\r\n\r\nPlaywright 使用 `WebDriverPort`：`connect_over_cdp(\"http://127.0.0.1:{WebDriverPort}\")`\r\n\r\n> **macOS 内核限制**：拿到 `WebDriverPort` 后进入 CDP 前，必须检查 `KernalNumber`。`KernalNumber ≤ 130` → 立即停止并提示：\r\n>\r\n> ```\r\n> 当前为 macOS，店铺 {mall_name} 的内核为 {kernel}（≤130），暂不支持自动化。\r\n> 请将该店铺切换到 130 以上内核；若无权限请让主账号切换。切换完成后请您手动重启站斧，再告诉我继续。\r\n> ```\r\n>\r\n> **Windows** 无此限制。Agent **禁止**在低内核场景下自行改内核或自动重启站斧。\r\n\r\n## CloseBrowser\r\n\r\n关闭指定店铺浏览器。**`api_port` HTTP 正常时直接调用，勿重启站斧。**\r\n\r\n```json\r\n{\r\n  \"action\": \"CloseBrowser\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"2786463\",\r\n  \"args\": \"\"\r\n}\r\n```\r\n\r\n**成功**：`returnObj === null`  \r\n**失败**：`returnObj === false`\r\n\r\n流程：`GetMallByName` 取 `mall_id` → `CloseBrowser`。开/关店铺均**不要**顺带 `ExitClient`。\r\n\r\n## ExitClient\r\n\r\n关闭站斧客户端。调用后客户端将退出，无额外业务返回值。\r\n\r\n```json\r\n{\"action\": \"ExitClient\", \"module\": \"WebDriverModule\", \"args\": \"\"}\r\n```\r\n\r\n成功：`returnObj === null`\r\n\r\n## SetDownLoadPath\r\n\r\n设置站斧浏览器文件下载路径。目录不存在时自动创建，成功后写入全局配置 `BrowserFileDwonPath`。\r\n\r\n> **平台**：仅 **Windows**。**macOS 目前不支持**——Agent 须直接告知客户并停止，勿调用本接口。\r\n\r\n```json\r\n{\r\n  \"action\": \"SetDownLoadPath\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"FilePath\\\": \\\"H:\\\\\\\\downloads\\\"}\"\r\n}\r\n```\r\n\r\n| args 字段 | 说明 |\r\n|-----------|------|\r\n| `FilePath` | 下载目录路径（不能为空） |\r\n\r\n响应：`returnObj.success`、`returnObj.msg`\r\n\r\n## ClearCacheFolder\r\n\r\n关闭所有店铺后，清除用户数据目录（保留 `Core`、`Down`）及日志目录。不计算缓存大小，不上报进度，直接删除。\r\n\r\n> **平台**：仅 **Windows**。**macOS 目前不支持**——Agent 须直接告知客户并停止，勿调用本接口。\r\n\r\n```json\r\n{\r\n  \"action\": \"ClearCacheFolder\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{}\"\r\n}\r\n```\r\n\r\n响应：`returnObj.success`、`returnObj.msg`\r\n\r\n## ClearCache\r\n\r\n关闭指定店铺后，删除该店铺的用户数据缓存目录（`RuxWorkbench` 目录跳过）。\r\n\r\n> **平台**：仅 **Windows**。**macOS 目前不支持**——Agent 须直接告知客户并停止，勿调用本接口。\r\n\r\n```json\r\n{\r\n  \"action\": \"ClearCache\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"browserId\": \"2786463\",\r\n  \"args\": \"\"\r\n}\r\n```\r\n\r\n响应：`returnObj.success`、`returnObj.msg`；缺少 `browserId` 时 `msg` 如「缺少 browserId」。\r\n\r\n## SetInstallPlugins\r\n\r\nWebDriver 模式下，设置打开店铺时默认加载的插件列表。成功后写入 `ClientGlobal.Data.InstallPlugins`，在后续 `OpenBrowser` 时生效。\r\n\r\n> **平台**：仅 **Windows**。**macOS 目前不支持**——Agent 须直接告知客户并停止，勿调用本接口。\r\n>\r\n> **须在 `OpenBrowser` 之前调用**；传空数组 `[]` 表示不额外指定插件。\r\n\r\n请求：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[{\\\"plugin_name\\\":\\\"RXMallHelper\\\",\\\"chrome_id\\\":\\\"abcdefghijklmnop\\\"}]}\"\r\n}\r\n```\r\n\r\n| 参数 | 类型 | 必填 | 说明 |\r\n|------|------|------|------|\r\n| `installPlugins` | array | 是 | 插件列表 |\r\n| `installPlugins[].plugin_name` | string | 是 | 插件名称，非空字符串 |\r\n| `installPlugins[].chrome_id` | string | 否 | 插件 ID；可省略或传空字符串 `\"\"` |\r\n\r\n**`chrome_id` 省略示例**：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[{\\\"plugin_name\\\":\\\"RXMallHelper\\\"}]}\"\r\n}\r\n```\r\n\r\n**`chrome_id` 传空字符串示例**：\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[{\\\"plugin_name\\\":\\\"RXMallHelper\\\",\\\"chrome_id\\\":\\\"\\\"}]}\"\r\n}\r\n```\r\n\r\n**清空插件列表示例**：\r\n\r\n> **备注**：通过自动化安装的插件，清空列表之后需要**清除店铺本地缓存**（`ClearCache`）才能生效。\r\n\r\n```json\r\n{\r\n  \"action\": \"SetInstallPlugins\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"installPlugins\\\":[]}\"\r\n}\r\n```\r\n\r\n**清空插件并使其生效的推荐流程**（针对目标店铺）：\r\n\r\n```\r\nSetInstallPlugins([]) → ClearCache（browserId=mall_id）→ OpenBrowser\r\n```\r\n\r\n若店铺已打开，须先 `CloseBrowser` 或依赖 `ClearCache` 自动关店后再 `OpenBrowser`。\r\n\r\n响应：`returnObj.success`、`returnObj.msg`\r\n\r\n| 常见失败 `msg` | 说明 |\r\n|----------------|------|\r\n| `args 必须为 JSON 对象` | `args` 格式不正确 |\r\n| `缺少 installPlugins 参数` | 未传 `installPlugins` 字段 |\r\n| `installPlugins 必须为数组` | `installPlugins` 不是数组 |\r\n| `installPlugins[n].plugin_name 必须为非空字符串` | 第 n 项插件名无效 |\r\n| `installPlugins[n].chrome_id 必须为字符串` | 第 n 项 `chrome_id` 类型无效（传了非字符串且非空值） |\r\n\r\n## GetWebDriver（仅 Selenium）\r\n\r\n仅 **Selenium API** 自动化需要；Playwright / CDP **跳过**此接口。\r\n\r\n将内核目录中的 `webdriver` 文件复制到指定目录（**不可为磁盘根目录**）。\r\n\r\n```json\r\n{\r\n  \"action\": \"GetWebDriver\",\r\n  \"module\": \"WebDriverModule\",\r\n  \"args\": \"{\\\"FilePath\\\": \\\"H:\\\\\\\\webdrivers\\\"}\"\r\n}\r\n```\r\n\r\n| args 字段 | 说明 |\r\n|-----------|------|\r\n| `FilePath` | 目标 webdriver 存放目录，不可为根目录 |\r\n\r\n响应：`returnObj.success`、`returnObj.msg`\r\n\r\n## 注意事项（文档 5.x）\r\n\r\n1. 客户端版本要求：**Windows ≥ 5.2.12**，**macOS > 5.2.10**；安装技能时向客户说明「客户使用指南」（见 `SKILL.md`）。冷启动后 8s 内未能建立 WebDriver 通讯时，按 `SKILL.md`「通讯失败对客户话术」提示（版本无误、卡顿可延迟时可再试，请客户说「打开站斧」；**禁止**再说「WebDriver 版且不低于 5.2.12」）。\r\n2. **首次**打开店铺会下载内核，建议客户先在站斧客户端手动打开一次；不同内核的店铺需分别手动打开一次后再自动化。\r\n3. 同时安装普通版与 WebDriver 版时，需使用 WebDriver 版。\r\n4. 用 `GetBrowserList` **能取到数据**判断站斧已打开；**禁止**用 `LoadSuccess` 判断。确认为站斧 WebDriver 时**勿杀进程重启**；打开/关闭店铺均继续 HTTP。仅目标端口无响应、被非站斧占用、或客户明确要求时才冷启动（**空闲端口**，优先 12678，占用则递增）。**打开站斧且探测未打开/非站斧占用时，立刻清空 `opening_malls.json`**；安装目录须按快捷方式/常见目录查找，找不到则向客户索要。**禁止**因 12678 被占用而要求客户先停掉其他服务。\r\n5. 访问本地 HTTP 服务：单次探测 `timeout=1.5`；冷启动后**立刻轮询** `GetBrowserList`（间隔 0.5s，最多 8s），勿固定干等。打开店铺后仍需延时等待内核启动。\r\n6. 自动创建店铺后再打开，中间需**等待**列表同步。\r\n7. 客户要求**打开**但目标店铺已打开时，须询问是否需要**关闭店铺**；客户明确要求**关闭**时直接 `CloseBrowser` 并清理 `opening_malls.json`。\r\n8. 打开店铺指令（**站斧已打开后**）写入 `opening_malls.json`；OpenBrowser 前 `GetBrowserWebDriver` **单次 5s**，超时仍 `OpenBrowser`。关店 / 关站斧 / **探测站斧未打开**时清理该配置。\r\n9. `OpenBrowser` / OpenBrowser 后 `GetBrowserWebDriver` 失败时，提醒客户确认店铺是否已绑定 IP/设备，以及是否已手动打开过该店铺下载内核。\r\n10. 需默认加载插件时，在 `OpenBrowser` **之前**调用 `SetInstallPlugins`；`chrome_id` 可省略或传 `\"\"`；传 `[]` 可清空插件列表。\r\n11. **清空插件列表**（`installPlugins: []`）后，若插件曾通过自动化安装，须再对该店铺调用 **`ClearCache`** 清除本地缓存后重新 `OpenBrowser`，清空才生效。\r\n12. Agent 阶段 A **只用 Python requests**，禁止为通断探测切换 PowerShell/curl；杀进程后最多等 1s（Win:`taskkill` / Mac:`killall 站斧`），勿固定等 3s。\r\n13. **macOS** 不得调用 `SetDownLoadPath` / `ClearCacheFolder` / `ClearCache` / `SetInstallPlugins`（目前不支持）。\r\n14. **macOS** 打开/复用店铺后若 `GetBrowserWebDriver.KernalNumber ≤ 130`：立即停止自动化，提示客户切换到 **130 以上**内核（或请主账号切换），并请客户**手动重启站斧**后再继续。\r\n15. **启动参数禁止减少**：Windows / macOS **均须四项齐全**：`--multip --run_type=web_driver --ipc_type=http --httpport=`（macOS 通过 `open -a … --args` 传入）。\r\n16. **`OpenBrowser` / `GetBrowserWebDriver` 的 `browserId` 必须为 JSON 字符串**（如 `\"3514488\"`），**禁止**传数字；resolve 后一律 `str(mall_id)`。\n\nFile v1.0.5:skill-card.md\n\n## Description:\n\nZhanfu Playwright automates Zhanfu client and store workflows through the WebDriver HTTP API, then uses Playwright over CDP after a store WebDriver port is available.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zhangzhang1997](https://clawhub.ai/user/zhangzhang1997)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and authorized operators use this skill to control Zhanfu stores, including opening or closing stores, listing or creating stores, changing store account data, configuring supported store settings, and running browser automation inside Z\n\nArchive v1.0.4: 11 files, 49460 bytes\n\nFiles: api_port.json (111b), mall_cache.json (1115b), opening_malls.json (61b), reference.md (26228b), scripts/check_device_security.py (5932b), scripts/headed_mode.py (847b), scripts/requirements.txt (38b), scripts/zhanfu_playwright.py (47333b), skill-card.md (2711b), SKILL.md (74038b), _meta.json (136b)\n\nArchive v1.0.3: 11 files, 44352 bytes\n\nFiles: api_port.json (111b), mall_cache.json (1115b), opening_malls.json (61b), reference.md (22338b), scripts/check_device_security.py (5932b), scripts/headed_mode.py (847b), scripts/requirements.txt (38b), scripts/zhanfu_playwright.py (46980b), skill-card.md (2760b), SKILL.md (64426b), _meta.json (136b)\n\nArchive v1.0.2: 14 files, 81019 bytes\n\nFiles: api_port.json (111b), mall_cache.json (1115b), opening_malls.json (61b), reference.md (22338b), scripts/__pycache__/check_device_security.cpython-311.pyc (8823b), scripts/__pycache__/headed_mode.cpython-311.pyc (1408b), scripts/__pycache__/zhanfu_playwright.cpython-311.pyc (71025b), scripts/check_device_security.py (5932b), scripts/headed_mode.py (847b), scripts/requirements.txt (38b), scripts/zhanfu_playwright.py (46980b), skill-card.md (2879b), SKILL.md (64426b), _meta.json (136b)\n\nArchive v1.0.1: 11 files, 39865 bytes\n\nFiles: api_port.json (111b), mall_cache.json (1115b), opening_malls.json (61b), reference.md (20291b), scripts/check_device_security.py (5932b), scripts/headed_mode.py (847b), scripts/requirements.txt (38b), scripts/zhanfu_playwright.py (40724b), skill-card.md (2804b), SKILL.md (49192b), _meta.json (136b)\n\nArchive v1.0.0: 11 files, 38981 bytes\n\nFiles: api_port.json (111b), mall_cache.json (1115b), opening_malls.json (61b), reference.md (20026b), scripts/check_device_security.py (5932b), scripts/headed_mode.py (847b), scripts/requirements.txt (38b), scripts/zhanfu_playwright.py (40461b), skill-card.md (2446b), SKILL.md (47892b), _meta.json (136b)","readmeExcerpt":"Skill: zhanfu-playwright Owner: zhangzhang1997 Summary: 站斧 WebDriver 版 Playwright 自动化（Windows≥5.2.12、macOS 版本高于 5.2.10、强制有界面、通讯失败即停）。 获取 WebDriver 端口前仅 HTTP 调用 WebDriverModule；获取端口后 CDP 执行业务。 「战斧」同义「站斧」（如打开战斧=打开站斧）。 适用于站斧、战斧、ZhanFu、WebDriver、Playwright、店铺自动化、小龙虾 OpenClaw RPA。 Tags: latest:1.0.6 Version history: v1.0.6 | 2026-09-03T02:22:31.903Z | auto - Added standalone scripts: separate scripts now handle opening/cl","codeSnippets":[],"executableExamples":[],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\r\nname: zhanfu-playwright\r\ndescription: >-\r\n  站斧 WebDriver 版 Playwright 自动化（Windows≥5.2.12、macOS 版本高于 5.2.10、强制有界面、通讯失败即停）。\r\n  获取 WebDriver 端口前仅 HTTP 调用 WebDriverModule；获取端口后 CDP 执行业务。\r\n  「战斧」同义「站斧」（如打开战斧=打开站斧）。\r\n  适用于站斧、战斧、ZhanFu、WebDriver、Playwright、店铺自动化、小龙虾 OpenClaw RPA。\r\n---\r\n\r\n# 站斧 Playwright 自动化\r\n\r\n通过站斧 WebDriver 版 **HTTP API** 控制客户端与店铺；**拿到 WebDriverPort 之后**才用 Playwright `connect_over_cdp` 做页面自动化。\r\n\r\n**Agent 提示**：技能**首次安装**、客户问「怎么用 / 如何使用」时，**先向客户发送下方「客户使用指南」**（可摘要，不必全文照搬）。\r\n\r\n**前置（Agent）**：站斧版本要求 **Windows ≥ 5.2.12**，**macOS > 5.2.10**；环境已安装 `playwright`、`requests`。\r\n\r\n> **macOS 限制**：`SetDownLoadPath`、`ClearCacheFolder`、`ClearCache`、`SetInstallPlugins` **目前不支持**。客户在 Mac 上提出这些需求时，应直接说明暂不支持并停止，勿调用对应 HTTP 接口。\r\n>\r\n> **macOS 内核限制**：macOS **不支持 130 及以下内核**的店铺自动化。打开店铺后 `GetBrowserWebDriver` 返回的 `KernalNumber` **≤ 130** 时，**立即停止**阶段 B，按「macOS 低内核对客户话术」提示客户切换到 **130 以上**内核（或由主账号切换），并请客户**手动重启站斧**后再继续。\r\n\r\n---\r\n\r\n## 客户使用指南（安装技能时向客户说明）\r\n\r\n以下内容可直接复制或摘要发给客户。\r\n\r\n### 一、使用前准备\r\n\r\n1. **站斧版本**：请确认站斧版本要求（**Windows ≥ 5.2.12**，**macOS > 5.2.10**）。\r\n2. **首次打开店铺会下载浏览器内核**，耗时较长，建议您先在站斧客户端里**手动打开一次**目标店铺，等内核下载完成后再用自动化。\r\n3. **不同店铺可能使用不同内核**。若自动化打开失败或提示内核相关错误，请先在站斧里**手动打开一次该店铺**（或与您要用的店铺**同内核**的店铺），内核就绪后再发指令。\r\n4. 店铺须已**绑定 IP / 设备**；未绑定时打开会失败，请在站斧客户端检查店铺设备绑定。\r\n5. **macOS 暂不支持**：设置下载目录、清除缓存（单店/全部）、设置店铺插件（`SetDownLoadPath` / `ClearCache` / `ClearCacheFolder` / `SetInstallPlugins`）。请在 Windows 上使用这些能力。\r\n6. **macOS 内核**：自动化仅支持店铺内核 **> 130**。若提示当前内核 ≤ 130，请在站斧中将该店铺切换到 **130 以上**内核（无权限时请**主账号**切换），然后**手动重启站斧**，再发指令继续。\r\n\r\n### 二、最常用的说法（推荐）\r\n\r\n\r\n| 您想做什么         | 直接发送（示例）                                   |\r\n| ------------- | ------------------------------------------ |\r\n| 启动站斧并打开店铺     | **打开站斧打开 ztest126**（把 `ztest126` 换成您的店铺名）  |\r\n| 仅打开店铺（站斧已在运行） | **打开店铺 ztest126**                          |\r\n| 关闭某个店铺        | **关闭 ztest126 店铺** / **关闭店铺 ztest126**     |\r\n| 退出站斧客户端       | **关闭站斧**                                   |\r\n| **创建新店铺**     | **创建店铺**，并按提示提供下方参数（见「七、创建店铺」）             |\r\n| **修改店铺账号密码**  | **修改店铺账号密码**，提供店铺名与新账号/密码（见「十二、修改店铺账号密码」） |\r\n| **查看我的店铺列表**  | **获取店铺列表** / **列出店铺**（见「八、查看店铺列表」）         |\r\n| **设置浏览器下载目录** | **设置下载目录到 D:\\downloads**（见「十、下载与缓存」）       |\r\n| **清除店铺/全部缓存** | **清除 xxx 店铺缓存** / **清除全部缓存**（见「十、下载与缓存」）   |\r\n| **设置店铺默认插件**  | **设置店铺插件**，提供插件名称；插件 ID 可省略或留空（见「十一、店铺插件」） |\r\n| **清空店铺插件列表**  | **清除默认插件列表** / **清空店铺插件**（见「十一、店铺插件」）      |\r\n\r\n\r\n> 说法可略有不同，只要包含「打开站斧」「打开店铺」和**店铺名称**即可；站斧已在运行时，一般**不会**重启站斧，直接开/关店铺。\r\n>\r\n> **同义说法**：客户发「**打开战斧**」「关闭战斧」「重启战斧」等时，**等同于**「打开站斧 / 关闭站斧 / 重启站斧」——「战斧」一律按「站斧」理解，**不要**当成未知产品或要求客户改口。\r\n\r\n### 三、首次未登录时\r\n\r\n若提示「站斧未登录，请提供账号和密码」，请提供您的**站斧老板账号**和密码（自动化仅使用您当场提供的账号，不会使用内测账号）。\r\n\r\n### 四、店铺已经打开时\r\n\r\n若您要的店铺**已经在运行**，系统会先问：**是否需要关闭该店铺？** 按您的选择回复即可；不需要关闭则可直接继续后续操作。\r\n\r\n### 五、页面自动化（进阶）\r\n\r\n店铺打开后，可继续用自然语言描述要在**店铺浏览器里**做的事，例如：\r\n\r\n- 「在 B 站搜索并播放某某视频」\r\n- 「打开某网址并填写表单」\r\n- 「抓取当前页面某某信息」\r\n\r\n此类操作会先等设备安全检测通过（约 15 秒），再自动操作页面。\r\n\r\n### 七、创建店铺\r\n\r\n发送 **「创建店铺」** 或 **「打开站斧并创建店铺 xxx」**，按提示提供信息即可（须已登录站斧）。\r\n\r\n**必填信息**\r\n\r\n\r\n| 您需提供                    | 说明          "},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn79xm4hxd563stv6msvy8bvn98ae9jy\",\n  \"slug\": \"zhanfu-playwright\",\n  \"version\": \"1.0.6\",\n  \"publishedAt\": 1788402151903\n}"},{"path":"scripts/requirements.txt","content":"playwright>=1.40.0\r\nrequests>=2.28.0"},{"path":"reference.md","content":"# 站斧 WebDriver API 参考\r\n\r\n> 模块固定为 `WebDriverModule`，通过 HTTP 服务调用。本文与官方《站斧 WebDriver 接口文档》对齐。\r\n\r\nHTTP 入口：`POST http://127.0.0.1:{api_port}`，Body 为 JSON。\r\n\r\n**默认 API 端口**：`12678`（优先）。Skill 目录 [`api_port.json`](api_port.json) 记录上次成功端口与安装目录；任务开始先探测该端口（用 `GetBrowserList`，**禁止**用 `LoadSuccess` 判断）。无响应或被非站斧占用 → 空闲端口冷启动并写回；**禁止**盲扫 8081/8082 碰已运行站斧；**禁止**因 12678 被占用而要求客户先释放。\r\n\r\n> **识别非站斧占用**：POST `GetBrowserList` 后若响应不是 `WebDriverModule` 结构（如「Electron 本地打包控制台」），视为其他服务占用 → 换空闲端口冷启动，**勿**停止占用方。\r\n\r\n**店铺 ID 缓存**：Skill 目录 [`mall_cache.json`](mall_cache.json) 记录 `mall_name` → `mall_id` 映射。需要 `mall_id` 时**先读缓存**，未命中再 `GetMallByName` 并写回；`GetBrowserList` 返回的 `mall_list` 亦应批量写入缓存。\r\n\r\n**打开意图配置**：Skill 目录 [`opening_malls.json`](opening_malls.json) 记录客户已下达「打开」指令的店铺名。关店 / 关站斧时清理。OpenBrowser 前用 `GetBrowserWebDriver` **只请求 1 次、超时 5s**；超时仍执行 `OpenBrowser`。\r\n\r\n**请求方式**：阶段 A **优先 Python `requests`（`timeout=1.5`）**；**禁止**为同一探测在 PowerShell/curl/Python 间换工具试错；**禁止** Windows `curl` 手工转义 JSON。\r\n\r\n## 通用约定\r\n\r\n### 请求结构\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `action` | 接口动作名 |\r\n| `module` | 固定为 `WebDriverModule` |\r\n| `args` | JSON 字符串，承载业务参数 |\r\n| `browserId` | 部分接口需要的店铺 ID（与 `mall_id` 相同）；**必须为 JSON 字符串**（如 `\"3514488\"`），**禁止**传数字 |\r\n\r\n### 响应结构\r\n\r\n| 字段 | 说明 |\r\n|------|------|\r\n| `ret` | HTTP 分发状态码：`200` 表示请求已正常分发处理；`400` / `500` 表示异常请求或框架级错误 |\r\n| `returnObj` | 业务返回值；结构因接口而异 |\r\n| `action` | 回显请求动作 |\r\n| `module` | 回显请求模块 |\r\n\r\n框架级错误示例（`ret=500`）：\r\n\r\n```json\r\n{\r\n  \"ret\": 500,\r\n  \"error\": \"未找到方法\",\r\n  \"action\": \"XXX\",\r\n  \"module\": \"WebDriverModule\"\r\n}\r\n```\r\n\r\n### 业务成功判断\r\n\r\n| 返回类型 | 判断方式 |\r\n|----------|----------|\r\n| `{ success, msg, ... }` | 以 `returnObj.success` 为准（如 `Login`、`GetMallByName`、`UpdateAccount`、`GetBrowserWebDriver`） |\r\n| `true` / `false` | 如 `OpenBrowser`：成功 `returnObj === true`，失败 `returnObj === false` |\r\n| `null` | 如 `CloseBrowser`、`ExitClient` 成功时 `returnObj` 为 `null`；`CloseBrowser` 失败时 `returnObj === false` |\r\n\r\n### 典型调用流程\r\n\r\n```\r\nLogin → SetInstallPlugins（可选，仅 Windows）→ GetBrowserList / GetMallByName → CreateBrowser（可选）\r\n→ SetDownLoadPath（可选，仅 Windows）→ GetWebDriver（Selenium 可选，Playwright 跳过）\r\n→ OpenBrowser → GetBrowserWebDriver → 自动化操作\r\n→ CloseBrowser → ExitClient（结束）\r\n```\r\n\r\n> **macOS 暂不支持**：`SetDownLoadPath`、`ClearCacheFolder`、`ClearCache`、`SetInstallPlugins`。Agent 不得在 Mac 上调用这些 action。\r\n>\r\n> **macOS 内核**：`KernalNumber ≤ 130` 的店铺**不支持**自动化；须提示切换到 130 以上内核（或主账号切换）并让客户**手动重启站斧**。\r\n\r\n## 启动站斧\r\n\r\n**Windows**（**四项缺一不可，禁止减少/省略任一参数**）：\r\n\r\n```\r\n站斧.exe --multip --run_type=web_driver --ipc_type=http --httpport={api_port}\r\n```\r\n\r\n| 参数 | 可否省略 |\r\n|------|----------|\r\n| `--multip` | **否** |\r\n| `--run_type=web_driver` | **否** |\r\n| `--ipc_type=http` | **否** |\r\n| `--httpport={api_port}` | **否**（值可变，键不可少） |\r\n\r\n**macOS**（**四项缺一不可，禁止减少/省略任一参数**，与 Windows 相同；用 `open -a` 启动）：\r\n\r\n```\r\nopen -a /Applications/站斧.app --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}\r\n```\r\n\r\n也可：`open -a 站斧 --args --multip --run_type=web_driver --ipc_type=http --httpport={api_port}`\r\n\r\n| 参数 "},{"path":"skill-card.md","content":"## Description:\n\nAutomates the ZhanFu WebDriver client and store browsers with local HTTP calls before connecting Playwright over CDP for user-directed browser tasks.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zhangzhang1997](https://clawhub.ai/user/zhangzhang1997)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users, developers, and store operators use this skill to open, close, create, list, and configure ZhanFu stores, then perform guided Playwright automation in the store browser after a WebDriver port is available.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles high-value ZhanFu account credentials and store-management actions.\n\nMitigation: Use it only on trusted local machines, avoid entering owner or store passwords on shared or monitored systems, and provide credentials only when needed for the requested workflow.\n\nRisk: Local automation can contact the wrong local service or an untrusted ZhanFu workflow if the environment is not verified.\n\nMitigation: Verify the real ZhanFu client is listening before login or store operations and stop when local communication cannot be confirmed.\n\nRisk: Cache clearing, account changes, plugin changes, and client termination can alter store state or interrupt active work.\n\nMitigation: Require explicit user confirmation before running cache clearing, account update, plugin update, or client exit actions.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zhangzhang1997/skills/zhanfu-playwright)\n- [ZhanFu WebDriver API reference](artifact/reference.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown guidance with Python and shell command examples, plus JSON HTTP request examples.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Outputs may operate a local ZhanFu client, store accounts, browser sessions, plugins, download paths, and cache settings.]\n\n## Skill Version(s):\n\n1.0.6 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"站斧 WebDriver 版 Playwright 自动化（Windows≥5.2.12、macOS 版本高于 5.2.10、强制有界面、通讯失败即停）。 获取 WebDriver 端口前仅 HTTP 调用 WebDriverModule；获取端口后 CDP 执行业务。 「战斧」同义「站斧」（如打开战斧=打开站斧）。 适用于站斧、战斧、ZhanFu、WebDriver、Playwright、店铺自动化、小龙虾 OpenClaw RPA。 Skill: zhanfu-playwright Owner: zhangzhang1997 Summary: 站斧 WebDriver 版 Playwright 自动化（Windows≥5.2.12、macOS 版本高于 5.2.10、强制有界面、通讯失败即停）。 获取 WebDriver 端口前仅 HTTP 调用 WebDriverModule；获取端口后 CDP 执行业务。 「战斧」同义「站斧」（如打开战斧=打开站斧）。 适用于站斧、战斧、ZhanFu、WebDriver、Playwright、店铺自动化、小龙虾 OpenClaw RPA。 Tags: latest:1.0.6 Version history: v1.0.6 | 2026-09-03T02:22:31.903Z | auto - Added standalone scripts: separate scripts now handle opening/cl","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1076,"uniquenessScore":52,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T03:58:35.897Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T03:58:35.897Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T07:42:41.251Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}