docs: update SKILL.md / README.md / CLI.md / INTEGRATION.md for v2

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-11 18:34:42 +08:00
parent dbf5604090
commit 1792ba2a0d
4 changed files with 335 additions and 155 deletions

View File

@@ -1,7 +1,7 @@
--- ---
name: 账号与凭据管理 name: 账号与凭据管理
description: "通用 Credential & Browser Profile Manager管理网页账号、RPA 浏览器 profile、LLM/API 平台 API Key。支持物流平台Maersk、COSCO、MSC 等、LLM 平台DeepSeek、豆包等、内容平台。业务 skill 通过 CLI 获取账号,不直接读 SQLite。" description: "通用账号 & 凭据 & 登录流程管理器。管理网页/RPA 账号、API Key/Token支持 9 种登录策略账密自动、扫码、2FA、SSO 等提供加密本地存储Fernet提供 rpa_helpers 库供业务 skill 同进程调用 ensure_logged_in 完成多平台自动登录。涵盖物流、LLM、内容、开发、API 五类平台。"
version: 1.0.56 version: 2.0.0
author: 深圳匠厂科技有限公司 author: 深圳匠厂科技有限公司
metadata: metadata:
openclaw: openclaw:
@@ -14,24 +14,30 @@ allowed-tools:
# 账号与凭据管理account-manager # 账号与凭据管理account-manager
通用 Credential & Browser Profile Manager。在本地 SQLite 管理平台注册、账号身份、凭据元数据API Key/Token 不存明文、RPA 并发锁lease供其它技能通过 CLI 调用 `scripts/main.py` 获取账号信息 通用账号、凭据与浏览器 Profile 管理器。在本地 SQLite 管理平台注册、账号身份、凭据元数据;可选 Fernet 加密密码入库;提供租约lease防并发;供其它技能通过 CLI 调用 `scripts/main.py` 或通过 **同进程** [`references/RPA_HELPERS.md`](references/RPA_HELPERS.md) 完成登录流程
## 核心原则 ## 核心原则
1. **account-manager 是唯一账号/凭据管理入口** — 业务 skill 不能自己账号、密码、API Key、Token。 1. **account-manager 是唯一账号/凭据管理入口** — 业务 skill 不能自己散落存储账号、密码、API Key、Token。
2. **SQLite 保存元数据**`secret_ref``secret_mask`,不保存原始 secret 明文。 2. **SQLite 主要保存元数据**`secret_ref``secret_mask`;非 `local_encrypted` 路径不在库中存明文。
3. **浏览器登录态** — 使用独立 `profile_dir` 保存 cookie/session,不保存网页登录密码 3. **浏览器登录态** — 使用独立 `profile_dir` 保存 cookie/session。
4. **业务 skill 通过 CLI/API 拿账号** — 不直接读 SQLite 4. **业务 skill 优先通过 CLI 获取结构化账号 JSON** — 需要时再组合同进程 rpa_helpers见集成文档
5. **9 种登录策略统一接口**`auth_strategy` 标识账号登录方式,业务 skill 可调用 `ensure_logged_in` 自动分派。
6. **加密 secret 双钥分离**master key 文件默认与数据库同目录,也可用环境变量覆盖;**数据库密文 + 合法 master key** 才能解密。
## 何时使用本技能 ## 何时使用本技能
1. **登记网页/RPA 账号**`account add-web` — 平台 + 登录标识 + 自动生成 profile_dir。 1. **登记网页/RPA 账号**`account add-web` — 平台 + 登录标识 + 自动生成 profile_dir;可选 `--auth-strategy` / `--session-persistent` / `--device-fingerprint`
2. **登记 API Key/Token 账号**`account add-secret`平台 + 凭据类型 + secret 存储方式 2. **登记凭据(API Key / Token / 加密密码)**`account add-secret``none` / `env` / `windows_credential` / `local_encrypted`
3. **查看/列出账号**`account get/list` — JSON 输出。 3. **查看/列出账号**`account get/list` — JSON 输出。
4. **为 RPA 挑选账号**`account pick-web` — 按环境/租户/角色筛选,可带 lease。 4. **为 RPA 挑选账号**`account pick-web` — 按环境/租户/角色筛选,可带 lease。
5. **获取 API Key**`credential pick` — 默认隐藏 secret`--reveal` 时才返回。 5. **获取 API Key(凭据表)**`credential pick` — 默认隐藏 secret`--reveal` 时才返回。
6. **浏览器打开查看**`account open <id>`(或兼容别名 `open <id>`)— 仅查看,不做登录检测 6. **浏览器打开查看**`account open <id>`(或兼容别名 `open <id>`)— 仅查看,不做站点侧登录判定
7. **管理 lease**`lease release/list/cleanup` — 防止 RPA 并发。 7. **管理 lease**`lease release/list/cleanup` — 防止 RPA 并发。
8. **初始化加密**`account init-master-key` — 生成 Fernet master.key。
9. **加密备份与迁移**`account export-credentials --plaintext` / `account import-credentials` — 导出明文 JSON、在新环境重新加密写入。
10. **按 lease 取明文密码**`account get-credential <id> --reveal --lease-token <token>` — 结合 pick-web 返回的 lease 解密 `local_encrypted` 等路径。
11. **业务 skill 同进程登录**`from service.rpa_helpers import ensure_logged_in` — 详见 [`references/RPA_HELPERS.md`](references/RPA_HELPERS.md)。
## CLI 调用 ## CLI 调用
@@ -39,20 +45,25 @@ allowed-tools:
## 支持的平台 ## 支持的平台
`references/PLATFORMS.md`支持物流、LLM、内容三大业务域 [`references/PLATFORMS.md`](references/PLATFORMS.md);代码注册表按业务域分为 logistics / llm / content / dev / sim实际数量与别名以 `scripts/util/platforms.py` 为准)
## 数据与环境 ## 数据与环境
库路径、profile 布局、环境变量见 `references/RUNTIME.md`;表结构见 `references/SCHEMA.md` 库路径、profile 布局、环境变量见 [`references/RUNTIME.md`](references/RUNTIME.md);表结构见 [`references/SCHEMA.md`](references/SCHEMA.md)
## 跨技能集成 ## 跨技能集成
`account get/list/pick-web` / `credential pick` 的 stdout 协议见 `references/INTEGRATION.md` stdout 协议与同进程 import 见 [`references/INTEGRATION.md`](references/INTEGRATION.md);登录 helper 细节见 [`references/RPA_HELPERS.md`](references/RPA_HELPERS.md)
## Secret 存储 ## Secret 存储
- `none`:无 secret浏览器 profile 登录态) - `none`:无 secret浏览器 profile 登录态)
- `env`SQLite 保存环境变量名,运行时从 `os.environ` 读取 - `env`SQLite 保存环境变量名,运行时从 `os.environ` 读取
- `windows_credential`:正式 Windows 部署,真实 secret 存 Windows Credential Manager - `windows_credential`:正式 Windows 部署,真实 secret 存 Windows Credential Manager
- `local_encrypted`Fernet 加密后存 SQLite`secret_ciphertext`),密钥从 `ACCOUNT_MANAGER_MASTER_KEY``master.key` 读取(须先 `account init-master-key`
详见 `references/RUNTIME.md` 详见 [`references/RUNTIME.md`](references/RUNTIME.md)。
## v2 升级说明
v1→v2 为**平滑迁移**:启动时 `ensure_schema` 幂等执行 `migrate_v1_to_v2``migrate_v2_to_v2_1`,自动补列与 `_schema_meta.schema_version`(最终为 `"2.1"`)。旧有三种 `secret_storage``none` / `env` / `windows_credential`仍可用CLI 旧别名(`get` / `pick-web` / `add` 等)保留。

View File

@@ -1,160 +1,203 @@
# account-manager CLI 速查 # account-manager CLI 速查
`{baseDir}` 替换为技能根目录。所有命令通过 `python {baseDir}/scripts/main.py` 调用(工作目录可为技能根或 `scripts/`,与命令中的路径一致即可)。下文示例简写为 `python main.py` 表示在 `scripts/` 下执行。 `{baseDir}` 替换为技能根目录。所有命令通过 `python {baseDir}/scripts/main.py` 调用(工作目录可为技能根或 `scripts/`,与命令中的路径一致即可)。下文示例简写为 `python main.py`表示在 `{baseDir}/scripts/` 下执行。
## 子命令与实现(与代码一致) > **说明**`scripts/cli/app.py` 内置的帮助字符串 `_USAGE` 主要覆盖 platform / account / credential / lease / open实际路由还支持 **`account init-master-key` / `account export-credentials` / `account import-credentials`**(本文档以代码为准)。
### 平台管理 ## stdout / JSON 约定(集成必读)
- 若干命令输出 **单层 JSON 对象**(例如 `account pick-web``account get``account get-credential` 成功时),**没有**统一的 `{"success":true}` 外层包裹。
- `account add-web``account add-secret`(等多数字命令)成功时为 **`{"success": true, "data": {...}}`**。
- `credential pick` / `credential resolve` 成功时为 **`{"success": true, ...字段}`**。
- `platform list` / `platform get` 成功时为 **`{"success": true, "data": ...}`**。
- 失败行多为 **`{"success": false, "error": {"code": "...", "message": "..."}}`**(个别老旧路径仍可能打印 `ERROR:` 前缀文本,首行解析逻辑见 [INTEGRATION.md](INTEGRATION.md))。
---
## 子命令速查(按业务流程)
### A. 平台管理
| CLI | 说明 | | CLI | 说明 |
|-----|------| |---|---|
| `platform list [--domain logistics\|llm\|content]` | 列出平台注册 | | `platform list [--domain logistics\|llm\|content]` | 列出平台注册`--domain` 仅接受这三种;`dev`/`sim` 等平台请省略 `--domain` 查全量或在 JSON 里筛选) |
| `platform get <platform>` | 获取平台详情 | | `platform get <platform>` | 获取数据库中的平台详情 |
### 账号管理 ### B. 加密初始化v2
| CLI | 说明 | | CLI | 说明 |
|-----|------| |---|---|
| `account add-web --platform <p> --login-id <id> [...]` | 创建网页/RPA 账号 | | `account init-master-key` | 生成 master.key写入 `{数据根}/{用户}/account-manager/master.key` |
| `account add-secret --platform <p> --credential-type <type> [...]` | 创建 API Key/Token 凭据 | | `account init-master-key --print` | 生成密钥并 **单行 JSON** 打印完整 key备份用不落盘 |
| `account get <id> [--with-credentials]` | 获取单条账号 JSON | | `account init-master-key --from-env` | 从 `ACCOUNT_MANAGER_MASTER_KEY` 读取合法 Fernet key 并写入文件 |
| `account list [--platform <p>] [--environment <env>] [--tenant-id <t>] [--role <role>]` | 列出账号 JSON 数组 | | `account init-master-key --rotate` | 覆盖现有 master.keystderr 会先打印警告;应先有 export 备份) |
| `account pick-web --platform <p> [--lease] [--ttl-sec 900]` | 挑选网页自动化候选 |
| `account mark-session <id> --session-status <status>` | 标记登录状态 | ### C. 账号管理v2 扩展)
| CLI | 说明 |
|---|---|
| `account add-web --platform <p> [--login-id <id>] [--login-id-type <type>] [...]` | 创建网页/RPA 账号;可选 `--auth-strategy` / `--session-persistent 0\|1` / `--device-fingerprint <fp>` |
| `account add-secret --platform <p> --credential-type <t> --secret-storage env\|windows_credential\|none\|local_encrypted` | 创建凭据;`local_encrypted` **必须** `--secret-stdin` |
| `account get <id> [--with-credentials]` | 输出账号 JSON若带 `--with-credentials` 则附加关联凭据摘要) |
| `account get-credential <account_id> [--reveal --lease-token <token>]` | v2**按账号 id** 取活跃凭据;`--reveal` 必须配合合法 lease |
| `account list [--platform <p>] [--environment <env>] [--tenant-id <t>] [--role <role>] [--limit N]` | 输出账号 JSON **数组** |
| `account pick-web --platform <p> [--environment <env>] [--tenant-id <t>] [--role <role>] [--lease] [--ttl-sec 900] [--holder <h>] [--purpose <purpose>]` | 挑选网页自动化候选;返回 JSON 含 `auth_strategy` / `session_persistent` / `device_fingerprint` |
| `account mark-session <id> --session-status <status>` | 标记会话状态 |
| `account mark-error <id> --code <code> --message <msg>` | 标记错误 | | `account mark-error <id> --code <code> --message <msg>` | 标记错误 |
| `account mark-used <id>` | 标记已使用 | | `account mark-used <id>` | 标记已使用 |
| `account open <id>` | 打开持久化浏览器 profile仅查看 | | `account open <id>` | 打开持久化浏览器 profile仅查看 |
### 凭据管理 ### D. 加密备份与迁移v2
| CLI | 说明 | | CLI | 说明 |
|-----|------| |---|---|
| `credential pick --platform <p> [--type <type>] [--reveal]` | 挑选凭据(默认隐藏 secret | | `account export-credentials --plaintext` | 将所有凭据行导出为 JSON **数组** 打到 stdoutstderr 有人类可读警告);**必须**显式 `--plaintext` |
| `credential resolve --id <credential_id> [--reveal]` | 按 ID 解析凭据 | | `account import-credentials [--replace-all]` | 从 stdin 读 JSON 数组,仅对带 `plaintext` 的行调用加密插入;结果摘要打到 **stderr** |
### 租约管理 ### E. 凭据 / 租约 / 浏览器v1 兼容入口保留)
以下命令仍推荐使用,行为与 v1 时期一致,适合「只拿 API Key」或脚本兼容
| CLI | 说明 | | CLI | 说明 |
|-----|------| |---|---|
| `credential pick --platform <p> [--type <type>] [--environment <env>] [--role <role>] [--reveal]` | v1 兼容:挑选凭据 |
| `credential resolve --id <credential_id> [--reveal]` | v1 兼容:按凭据 id 解析 |
| `lease release <lease_token>` | 释放租约 | | `lease release <lease_token>` | 释放租约 |
| `lease list [--active]` | 列出租约 | | `lease list [--active]` | 列出租约 |
| `lease cleanup` | 清理过期租约 | | `lease cleanup` | 清理过期租约 |
| `account open <id>` / `open <id>` | 浏览器查看 |
### 浏览器
| CLI | 说明 |
|-----|------|
| `account open <id>` | 打开浏览器查看(仅查看) |
| `open <id>` | 同上(兼容别名) |
### 兼容入口(旧版别名) ### 兼容入口(旧版别名)
| CLI | 等价 | | CLI | 等价 / 说明 |
|-----|--------| |---|---|
| `get <id>` | `account get <id>` | | `get <id>` | `account get <id>` |
| `list-json <platform\|all> [--limit N]` | JSON 数组输出 | | `list-json <platform\|all> [--limit N]` | JSON 数组输出 |
| `pick-web <platform>` | `account pick-web --platform <platform>` | | `pick-web <platform>` | `account pick-web --platform <platform>`(无 lease 参数) |
| `list [platform\|all]` | 人类可读列表 | | `list [platform\|all]` | 人类可读列表 |
| `add <platform> <phone>` | `account add-web`phone 作为 login_id | | `add <platform> <phone>` | 映射到 `account add-web``login_id_type=phone`),不传 v2 扩展参数 |
| `delete id\|platform <...>` | 删除账号 | | `delete id\|platform <...>` | 删除账号 |
--- ---
## account add-web ## account add-web(扩参示例)
```bash ```bash
# 扫码登录的抖音账号
python main.py account add-web \ python main.py account add-web \
--platform maersk \ --platform douyin \
--login-id demo@maersk.com \ --label "douyin-creator-1" \
--login-id-type email \ --auth-strategy qr_code_manual \
--label "Maersk simulator booking" \ --session-persistent 1
--tenant-id tenant-demo \
--environment simulator \
--role booking \
--provider-code maersk \
--url http://localhost:5180/industries/logistics/maersk/login
``` ```
- `--platform`(必填):平台键/别名 - `--auth-strategy``password_auto` / `password_with_captcha` / `password_plus_2fa` / `qr_code_manual` / `per_session_manual` / `device_bound` / `client_certificate` / `api_token` / `sso_redirect`;省略时按平台默认(`seed_platforms` + `platforms.default_auth_strategy`,回填规则见 `db/platform_defaults.py`);非法值返回 **`ERR_AUTH_STRATEGY_NOT_SUPPORTED`**。
- `--login-id`登录标识email/username/phone/customer_code - `--session-persistent``0``1`;省略时由代码推导:`qr_code_manual``password_plus_2fa``device_bound``sso_redirect``1``per_session_manual``client_certificate``0`;其余默认 `1`
- `--login-id-type`:默认 `unknown` - `--device-fingerprint`**仅当** `--auth-strategy=device_bound` 时允许设置;否则 **`ERR_DEVICE_FINGERPRINT_NOT_APPLICABLE`**。
- `--label`:人可读名称,不填则自动拼接 - 成功 stdout`{"success": true, "data": { ... }}``data` 内含 `id``platform_key``profile_dir``auth_strategy``session_persistent``device_fingerprint` 等。
- `--tenant-id`:租户/项目标识
- `--environment`:默认 `production`
- `--role`:默认 `default`
- `--provider-code`:默认取平台 provider_code
- `--url`:默认取平台 default_url
- `--extra-json`:扩展 JSON
- `--profile-dir`:高级调试用,不推荐
输出 JSON包含 `id``profile_dir``url` 等。 ---
## account add-secret ## account add-secret`local_encrypted` 示例)
```bash ```bash
# env 方式 echo "my-icbc-password" | python main.py account add-secret \
python main.py account add-secret \ --platform icbc_sim \
--platform deepseek \ --credential-type password \
--credential-type api_key \ --secret-storage local_encrypted \
--label "DeepSeek env key" \
--secret-storage env \
--secret-ref DEEPSEEK_API_KEY \
--environment production \
--role api
# windows_credential 方式
echo "sk-test-1234" | python main.py account add-secret \
--platform deepseek \
--credential-type api_key \
--label "DeepSeek production key" \
--secret-storage windows_credential \
--secret-stdin \ --secret-stdin \
--environment production \ --label "工行仿真主账号"
--role api
``` ```
- `--secret-storage``env` / `windows_credential` / `none` - `local_encrypted` **必须** `--secret-stdin`(否则 **`ERR_LOCAL_ENCRYPTED_REQUIRES_STDIN`**)。
- `--secret-stdin`:从 stdin 读取 secret仅 windows_credential - 允许的 `credential_type``password``api_key``api_token``bearer_token``refresh_token``oauth_client``browser_profile` / `note` 会被 **`ERR_LOCAL_ENCRYPTED_TYPE_NOT_ALLOWED`** 拒绝)。
- `--secret-ref`:环境变量名(仅 env - stdin 为空:**`ERR_LOCAL_ENCRYPTED_EMPTY_STDIN`**。
- `none` 仅允许 `credential_type=browser_profile``note` - master key 未就绪:**`ERR_MASTER_KEY_MISSING`**。
- 成功:`{"success": true, "data": {"credential_id", "account_id", "platform_key", "credential_type", "secret_storage", "secret_mask"}}`
输出 JSON包含 `account_id`(未指定 `--account-id` 时会自动创建一条用于挂载凭据的账号记录)、`credential_id``secret_mask``secret_ref`**不包含 secret 明文**。 ---
## account pick-web ## account get-credential示例
```bash ```bash
python main.py account pick-web \ # 不 reveal仅返回 metadata + mask
--platform maersk \ python main.py account get-credential 42
--environment simulator \
--tenant-id tenant-demo \ # reveal必须带合法 lease-token通常来自 pick-web --lease
--role booking \ LEASE=$(python main.py account pick-web --platform icbc_sim --lease --holder my-rpa | jq -r .lease_token)
--lease \ python main.py account get-credential 42 --reveal --lease-token "$LEASE"
--ttl-sec 900 \
--holder monitor-competitor-rates \
--purpose maersk_sim_rpa
``` ```
- 筛选 status=active 且未被 active lease 占用的账号 - `--reveal`:单行 JSON`success`/`account_id`/`credential_id`/`secret_storage`/`secret_mask` 等。
- 优先 session_status != expired - `--reveal``secret_storage=local_encrypted` 等在 lease 校验通过后追加 **`plaintext`**;若底层存储为 `none`,返回 **`plaintext: null`** 及说明字段(并非抛错)。
- 优先 last_used_at 为空的账号 - 常见错误:`ERR_LEASE_INVALID``ERR_CREDENTIAL_MISSING``ERR_MASTER_KEY_MISSING``ERR_CREDENTIAL_DECRYPT_FAILED`(见 [ERRORS.md](ERRORS.md))。
- `--lease`:创建 lease返回 `lease_token``lease_expires_at`
- `--ttl-sec`:租约时长,默认 900 秒
## credential pick ---
成功时输出单行 JSON`{"success": true, ...fields }`;失败时为 [ERRORS.md](ERRORS.md) 的机器 JSON。 ## account export-credentials / import-credentials示例
```bash ```bash
# 默认不返回 secret # 备份stdout 为 JSON 数组,含解密后的 plaintext务必妥善销毁
python main.py credential pick --platform deepseek --type api_key --environment production --role api python main.py account export-credentials --plaintext > backup-2026-05-11.json
# --reveal 才返回 secret 明文 # 在新机器恢复(需先 init-master-key使 master key 可用)
python main.py credential pick --platform deepseek --type api_key --environment production --role api --reveal python main.py account import-credentials --replace-all < backup-2026-05-11.json
``` ```
- 未带 `--plaintext`**`ERR_EXPORT_REQUIRES_PLAINTEXT_FLAG`**(单行 JSON
- `import-credentials` 成功时 **stdout 通常为空**,进度与计数在 **stderr**
---
## account init-master-key示例
```bash
# 首次初始化(写入 master.key
python main.py account init-master-key
# 打印 key 备份到密码管理器(不落盘)
python main.py account init-master-key --print
# 从环境变量恢复写入文件
ACCOUNT_MANAGER_MASTER_KEY="<base64-44-chars>" python main.py account init-master-key --from-env
```
- 文件已存在且未 `--rotate`**`ERR_MASTER_KEY_EXISTS`**JSON
- `--from-env` 字符串非法:**`ERR_MASTER_KEY_INVALID`**。
---
## account pick-web字段
成功时为 **单行 JSON 对象**(非 `_ok_json` 包裹)。核心字段:
- `id`, `platform_key`, `account_label`, `login_id`, `profile_dir`, `url`, `tenant_id`, `environment`, `role`, `provider_code`, `session_status`
- **v2**`auth_strategy`, `session_persistent`, `device_fingerprint`
-`--lease``lease_token`, `lease_expires_at`ISO8601 **本地时间**字符串,由内部 Unix 秒字段转换而来)
---
## 9 种 `auth_strategy` 简表(参考)
| 策略键 | 适用场景 | 是否要 plaintext典型 | 是否要人介入 |
|---|---|---|---|
| `password_auto` | 标准账密表单 | 是 | 否 |
| `password_with_captcha` | 带图形验证码 | 是 | 是(填码阶段) |
| `password_plus_2fa` | 短信/邮件/OTP 2FA | 是 | 是OTP 阶段) |
| `qr_code_manual` | 扫码登录 | 否 | 是(扫码阶段) |
| `per_session_manual` | 银行/政务等每次手动 | 否 | 是 |
| `device_bound` | 绑机器 / U-Key 等 | 可选(有密码则自动填) | 视情况 |
| `client_certificate` | 客户端证书 + PIN | — | 不可自动化rpa_helpers 抛错) |
| `api_token` | 无浏览器登录 | 否 | 否 |
| `sso_redirect` | OAuth / SSO 跳转 | 否 | 是SSO 页阶段) |
业务 skill 同进程调用详见 [RPA_HELPERS.md](RPA_HELPERS.md)。
---
## 通用说明 ## 通用说明
- **平台参数**:可为 `scripts/util/platforms.py`配置的**展示名、别名或英文键**(如 `sohu``搜狐号``maersk``马士基`)。详见 [PLATFORMS.md](PLATFORMS.md)。 - **平台参数**:可为 `scripts/util/platforms.py`的英文键、`display_name`、任一 alias不区分大小写)。详见 [PLATFORMS.md](PLATFORMS.md)。
- **数据与路径**库文件、profile 目录由环境变量决定。详见 [RUNTIME.md](RUNTIME.md)。 - **数据与路径**库文件、profile`master.key` 布局见 [RUNTIME.md](RUNTIME.md)。
- **机器可读命令**成功时输出单行 JSON失败时首行 `ERROR:`。详见 [INTEGRATION.md](INTEGRATION.md)。 - **机器可读集成**:见 [INTEGRATION.md](INTEGRATION.md)。
- **错误码**:见 [ERRORS.md](ERRORS.md)。 - **错误码**:见 [ERRORS.md](ERRORS.md)。

View File

@@ -2,31 +2,53 @@
## 核心约束 ## 核心约束
业务 skill **不能自己账号、密码、API Key、Token**必须通过 account-manager CLI 获取。 业务 skill **不能自己散落存储账号、密码、API Key、Token**通过 account-manager **CLI**(进程隔离)或 **CLI + `service.rpa_helpers` 同进程库**(浏览器自动化)组合获取。
## 两种集成方式
| 方式 | 适用场景 | 调用形态 |
|---|---|---|
| **A. CLI subprocessv1 起)** | 任意业务 skill一次性取账号 JSON / 凭据 / lease | `subprocess.run([sys.executable, f"{skill_root}/scripts/main.py", "account", "pick-web", ...])` |
| **B. rpa_helpers 同进程 importv2** | 需要 Playwright 上下文内完成登录与页面操作 | `sys.path.insert(0, f"{account_manager_root}/scripts"); from service.rpa_helpers import ensure_logged_in` |
常见组合:**CLI** 负责 pick / lease / `get-credential --reveal`**rpa_helpers** 负责 `launch_browser_with_profile` + `ensure_logged_in`。详见 [`RPA_HELPERS.md`](RPA_HELPERS.md)。
## 推荐调用方式 ## 推荐调用方式
使用 **`subprocess`** 调用 `scripts/main.py`,工作目录可为技能根或 `scripts/`。宿主注入的 **`JIANGCHANG_DATA_ROOT` / `JIANGCHANG_USER_ID`** 必须与最终用户会话一致 使用 **`subprocess`** 调用 `scripts/main.py`。宿主注入的 **`JIANGCHANG_DATA_ROOT` / `JIANGCHANG_USER_ID`**(或上层包装的 `CLAW_*`)必须与最终用户会话一致——否则会写到另一套目录。路径调试见 [`RUNTIME.md`](RUNTIME.md)
## 机器可读命令摘要 ## 机器可读命令摘要
| 目的 | 命令 | 成功时 stdout | | 目的 | 命令 | 成功时 stdout(摘要) |
|------|------|----------------| |---|---|---|
| 取单条账号 JSON | `account get <id>` | 单行 JSON 对象 | | 枚举平台 | `platform list [--domain ...]` | `{"success": true, "data": {"platforms": [...]}}` |
| 批量账号 JSON | `account list --platform <p> [--environment <e>]` | 单行 JSON 数组 | | 平台详情 | `platform get <p>` | `{"success": true, "data": {...}}` |
| 网页自动化候选 | `account pick-web --platform <p> [--lease]` | 单行 JSON 对象 | | 取单条账号 JSON | `account get <id>` | **单行 JSON 对象**(无固定 `success` 字段) |
| 获取 API Key | `credential pick --platform <p> --type api_key [--reveal]` | 单行 JSON`success: true` + 字段) | | 批量账号 JSON | `account list ...` | **单行 JSON 数组** |
| 兼容入口 | `get <id>` / `list-json <p>` / `pick-web <p>` | 同上 | | 网页自动化候选 | `account pick-web ...` | **单行 JSON 对象** |
| 取加密凭据明文 | `account get-credential <id> --reveal --lease-token <t>` | **单行 JSON**,含 `plaintext`(若可解密) |
| 备份加密凭据 | `account export-credentials --plaintext` | **JSON 数组**stderr 有警告行) |
| 导入加密凭据 | `account import-credentials [--replace-all]` | **通常为空**(计数在 stderr |
| 初始化 master key | `account init-master-key [--print\|--from-env\|--rotate]` | **单行 JSON** |
| 新增网页账号 | `account add-web ...` | `{"success": true, "data": {...}}` |
| 新增凭据 | `account add-secret ...` | `{"success": true, "data": {...}}` |
| 获取 API Key | `credential pick ... [--reveal]` | `{"success": true, ...}` |
| 兼容入口 | `get <id>` / `list-json <p>` / `pick-web <p>` | 同上对应新式命令 |
## 解析协议 更完整的命令表见 [`CLI.md`](CLI.md)。
1. 读取子进程 **stdout** 首行。 ## 解析协议(稳妥做法)
2. 若首行以 **`ERROR:`** 开头 → 失败。
3. 否则对首行做 `json.loads` 1. 读取子进程 **stdout**;若有多行,**集成应以首行为准**export/import 例外:`export` 整块 stdout 即 JSON`import` 读 stderr
2. **优先尝试 `json.loads`**
- 若为 dict 且 `success is False` → 读取 `error.code` / `error.message`
- 若 dict 且 `success is True` 且存在 `data` → 业务字段通常在 `data` 内(`add-web` / `add-secret` / `platform`)。
3. 若 JSON 首字段不是上述统一格式(例如 `pick-web`)→ 直接按字段读取。
4. **遗留文本失败**:首行以 **`ERROR:`** 开头 → 视为失败(旧别名路径仍可能出现)。
## JSON 对象字段 ## JSON 对象字段
### account get / pick-web ### `account pick-web`(典型)
```json ```json
{ {
@@ -34,26 +56,28 @@
"platform_key": "maersk", "platform_key": "maersk",
"account_label": "Maersk simulator booking", "account_label": "Maersk simulator booking",
"login_id": "demo@maersk.com", "login_id": "demo@maersk.com",
"login_id_type": "email", "profile_dir": "D:/claw-data/10032/account-manager/profiles/logistics/maersk/Maersk_simulator_booking_demo@maersk.com",
"url": "http://localhost:5180/industries/logistics/maersk/login",
"tenant_id": "tenant-demo", "tenant_id": "tenant-demo",
"environment": "simulator", "environment": "simulator",
"role": "booking", "role": "booking",
"provider_code": "maersk", "provider_code": "maersk",
"profile_dir": "D:/claw-data/10032/account-manager/profiles/logistics/maersk/Maersk_simulator_booking_demo@maersk.com",
"url": "http://localhost:5180/industries/logistics/maersk/login",
"status": "active",
"session_status": "unknown", "session_status": "unknown",
"last_used_at": "2026-05-01T10:00:00", "auth_strategy": "qr_code_manual",
"created_at": "2026-05-01T09:00:00", "session_persistent": 1,
"updated_at": "2026-05-01T09:00:00" "device_fingerprint": null,
"lease_token": "…………",
"lease_expires_at": "2026-05-11T12:34:56"
} }
``` ```
pick-web 额外字段(带 lease 时): `lease_*` 仅在传入 `--lease` 时出现;时间与仓库 `_unix_to_iso_local` 一致。
- `lease_token`: 租约 token
- `lease_expires_at`: 过期时间
### credential pick ### `account get`
输出即数据库映射字典(字段与 [`SCHEMA.md`](SCHEMA.md) `accounts` 一致,`extra_json` 等为结构化 JSON
### `credential pick`
```json ```json
{ {
@@ -69,13 +93,48 @@ pick-web 额外字段(带 lease 时):
} }
``` ```
**只有 `--reveal` 时才返回 `secret` 字段。业务 skill 不要向最终用户展示 reveal 输出。** `--reveal`附加 **`secret`**。请勿向终端用户打印 reveal 结果。
失败时使用统一 JSON`{"success": false, "error": {"code": "ERROR:...", "message": "..."}}`(见 [ERRORS.md](ERRORS.md))。 ### `account get-credential`
成功示例:
```json
{
"success": true,
"account_id": 42,
"credential_id": 7,
"credential_type": "password",
"secret_storage": "local_encrypted",
"secret_mask": "****abcd",
"plaintext": "……"
}
```
失败时使用统一 JSON`{"success": false, "error": {"code": "...", "message": "..."}}`(亦可能夹杂历史 `ERROR:` 文本命令——见 [`ERRORS.md`](ERRORS.md))。
## rpa_helpers 同进程使用(摘要)
```python
import sys
AM_ROOT = r"D:\OpenClaw\client-commons\account-manager"
sys.path.insert(0, f"{AM_ROOT}/scripts")
from service.rpa_helpers import (
launch_browser_with_profile,
close_browser,
ensure_logged_in,
)
```
**务必**`sys.path` 指向 **`account-manager/scripts`**,因此 import 形态为 **`from service.rpa_helpers ...`**(而不是 `from scripts.service.rpa_helpers ...`)。
完整 API、登录判定 hook、`LoginResult` / `AuthStrategyError` 说明见 [`RPA_HELPERS.md`](RPA_HELPERS.md)。
## 业务流程示例 ## 业务流程示例
### 物流 RPA ### 物流 RPACLI
1. `account pick-web --platform maersk --environment simulator --role booking --lease --holder my-skill` 1. `account pick-web --platform maersk --environment simulator --role booking --lease --holder my-skill`
2. 解析 JSON → 取 `id``profile_dir``url``lease_token` 2. 解析 JSON → 取 `id``profile_dir``url``lease_token`
@@ -83,12 +142,71 @@ pick-web 额外字段(带 lease 时):
4. 业务完成后:`lease release <lease_token>` 4. 业务完成后:`lease release <lease_token>`
5. 如遇登录失效:`account mark-session <id> --session-status needs_login` 5. 如遇登录失效:`account mark-session <id> --session-status needs_login`
### LLM API 调用 ### LLM API 调用CLI
1. `credential pick --platform deepseek --type api_key --environment production --reveal` 1. `credential pick --platform deepseek --type api_key --environment production --reveal`
2. 解析 JSON → 取 `secret` 字段 2. 解析 JSON → 取 `secret` 字段
3.业务进程内存中使用,不写文件、不打日志 3. 在内存中使用,不写磁盘、不打日志
### 加密密码 + 自动登录CLI + rpa_helpers
```python
import json
import subprocess
import sys
AM = r"D:\OpenClaw\client-commons\account-manager"
PY = sys.executable
MAIN = f"{AM}/scripts/main.py"
sys.path.insert(0, f"{AM}/scripts")
from service.rpa_helpers import launch_browser_with_profile, close_browser, ensure_logged_in
def am_json(argv: list[str]) -> dict:
r = subprocess.run([PY, MAIN, *argv], capture_output=True, text=True, check=False)
line = (r.stdout or "").splitlines()[0] if r.stdout else ""
return json.loads(line)
# 1) pick 账号 + lease
acc = am_json(
[
"account",
"pick-web",
"--platform",
"icbc_sim",
"--lease",
"--holder",
"my-rpa",
]
)
# 2) 取明文密码(必须 reveal + lease
cred = am_json(
[
"account",
"get-credential",
str(acc["id"]),
"--reveal",
"--lease-token",
acc["lease_token"],
]
)
# 3) 浏览器 + 登录
ctx, page = launch_browser_with_profile(acc["profile_dir"])
try:
result = ensure_logged_in(page, acc, credentials={"plaintext": cred["plaintext"]})
if not result.ok:
print(result.message, file=sys.stderr)
sys.exit(1)
# …业务逻辑…
finally:
close_browser(ctx)
subprocess.run([PY, MAIN, "lease", "release", acc["lease_token"]], check=False)
```
## 退出码 ## 退出码
请以 **stdout 首行前缀****JSON 可解析性** 为准;不要仅依赖退出码。 请以 **stdout JSON / `ERROR:` 前缀** 为准;不要仅依赖退出码。

View File

@@ -1,21 +1,24 @@
--- ---
description: "通用 Credential & Browser Profile Manager管理网页账号、RPA 浏览器 profile、LLM/API 平台 API Key。支持物流、LLM、内容三大业务域。" description: "通用账号 & 凭据 & 登录流程管理器。管理网页/RPA 账号、API Key/Token支持 9 种登录策略与 Fernet 加密入库;可选 CLI + rpa_helpers 同进程自动登录。涵盖物流、LLM、内容、开发、仿真等平台。"
--- ---
# 🔐 账号与凭据管理 # 🔐 账号与凭据管理
把你在各平台的账号与凭据**登记到本地**,后续物流 RPA、大模型写作、内容发布等技能才能自动选用对应环境。 把你在各平台的账号与凭据**登记到本地**,后续物流 RPA、大模型写作、内容发布等技能才能自动选用对应环境。
> 本技能是**唯一**账号/凭据管理入口。业务 skill 不自己密码、API Key而是通过 CLI 调用获取。 > 本技能是**唯一**账号/凭据管理入口。业务 skill 不自己散落密码、API Key而是通过 CLI(或与 CLI 组合的同进程 [`RPA_HELPERS.md`](RPA_HELPERS.md)获取。
## 它能帮你做什么 ## 它能帮你做什么
- **添加网页/RPA 账号** — 选平台,给出登录标识(邮箱/手机/用户名),自动创建浏览器 profile 目录。 - **添加网页/RPA 账号** — 选平台,给出登录标识(邮箱/手机/用户名),自动创建浏览器 profile 目录。
- **添加 API Key/Token** — 安全存储API Key 明文存入 Windows Credential Manager 或环境变量引用SQLite 只保存元数据和打码值 - **添加 API Key/Token / 加密密码** — `none` / `env` / `windows_credential` / `local_encrypted`Fernet 密文入库)
- **查看/列出账号** — 按平台、环境、角色等多维度筛选。 - **查看/列出账号** — 按平台、环境、角色等多维度筛选。
- **给 RPA 技能用** — `pick-web` 按规则挑候选账号,支持 lease 防并发。 - **给 RPA 技能用** — `pick-web` 按规则挑候选账号,支持 lease 防并发;输出含 `auth_strategy` / `session_persistent` / `device_fingerprint`
- **给 LLM 技能用** — `credential pick` 安全获取 API Key。 - **给 LLM 技能用** — `credential pick` 安全获取 API Key。
- **在浏览器里查看** — `open <id>` 打开 Chrome/Edge 查看,仅查看不写库。 - **在浏览器里查看** — `open <id>` 打开 Chrome/Edge 查看,仅查看不写库。
- **加密存储密码** — Fernet 加密,密码在 SQLite 中以密文形式存在;只有持有 master key 才能解密。
- **9 种登录策略** — 账密自动、账密+图形验证码、账密+2FA、扫码、每次手动登录、设备绑定、客户端证书、API Token、SSO 跳转;业务 skill 可调用统一入口 `ensure_logged_in`(见 [`RPA_HELPERS.md`](RPA_HELPERS.md))。
- **加密备份与迁移** — `export-credentials --plaintext` 导出 JSON`import-credentials` 在新机器重新加密写入(需先 `init-master-key`)。
## 你可以这样对它说 ## 你可以这样对它说
@@ -24,21 +27,23 @@ description: "通用 Credential & Browser Profile Manager管理网页账号
- 「列出所有物流平台的账号。」 - 「列出所有物流平台的账号。」
- 「用浏览器打开 3 号账号看看页面。」 - 「用浏览器打开 3 号账号看看页面。」
- 「给 RPA 技能取一个 maersk 模拟器的 booking 账号。」 - 「给 RPA 技能取一个 maersk 模拟器的 booking 账号。」
- 「我要把工行仿真账号的密码加密保存,下次 RPA 自动登录用。」
- 「给我导出所有加密凭据,明天换台电脑要用。」
## 你需要提供什么 ## 你需要提供什么
| 场景 | 你需要给的 | | 场景 | 你需要给的 |
|---|---| |---|---|
| 添加网页账号 | **平台名称** + **登录标识**(邮箱/手机/用户名) | | 添加网页账号 | **平台名称** + **登录标识**(邮箱/手机/用户名) |
| 添加 API Key | **平台名称** + **凭据类型**api_key 等)+ **secret**通过 stdin 环境变量) | | 添加 API Key / 加密密码 | **平台名称** + **凭据类型**api_key 等)+ **secret**stdin / 环境变量引用等 |
| 查看/列出 | 可选:平台名、环境、角色等筛选条件 | | 查看/列出 | 可选:平台名、环境、角色等筛选条件 |
| 浏览器打开 | 账号 **id**(需本机已安装 Chrome 或 Edge | | 浏览器打开 | 账号 **id**(需本机已安装 Chrome 或 Edge |
## 它不做什么 ## 它不做什么
- 不在此处判定各网站「是否已登录」(由业务技能自行处理 - 不在此处包办所有网站的 DOM 自动化细节(具体抓取逻辑在各业务 skill
- 不代替内容管理、发布、大模型调用等业务技能 - 不代替内容管理、发布、大模型调用等业务技能
- 不保存 API Key 明文在 SQLite 中(仅存引用和打码值) - `windows_credential` / `env` 路径下不把明文写入 SQLite`local_encrypted` 仅存 Fernet 密文
## Secret 存储方式 ## Secret 存储方式
@@ -47,7 +52,10 @@ description: "通用 Credential & Browser Profile Manager管理网页账号
| `none` | 无 secret浏览器 profile 登录态) | | `none` | 无 secret浏览器 profile 登录态) |
| `env` | 引用环境变量名,运行时读取 | | `env` | 引用环境变量名,运行时读取 |
| `windows_credential` | 正式推荐:真实 secret 存 Windows Credential Manager | | `windows_credential` | 正式推荐:真实 secret 存 Windows Credential Manager |
| `local_encrypted` | 本地 Fernet 加密存 DB需先 `account init-master-key` |
命令细节见 [`CLI.md`](CLI.md);加密与环境变量见 [`RUNTIME.md`](RUNTIME.md)。
--- ---
**作者**:深圳匠厂科技有限公司 · **版本**:1.0.55 **作者**:深圳匠厂科技有限公司 · **版本**:2.0.0