Release v1.0.56: Credential & Browser Profile Manager
All checks were successful
技能自动化发布 / release (push) Successful in 7s
All checks were successful
技能自动化发布 / release (push) Successful in 7s
This commit is contained in:
@@ -4,102 +4,157 @@
|
||||
|
||||
## 子命令与实现(与代码一致)
|
||||
|
||||
| CLI(`main.py` 第一参或等价路由) | 实现(`scripts/service/`) |
|
||||
|----------------------------------|---------------------------|
|
||||
| `add` | `account_service.cmd_add` |
|
||||
| `list`;或首参为平台且 `list`/单参 | `account_service.cmd_list`(路由见 `cli/app.py`) |
|
||||
| `get` | `account_service.cmd_get` |
|
||||
| `list-json` | `account_service.cmd_list_json` |
|
||||
| `pick-web` | `account_service.cmd_pick_web` |
|
||||
| `open` | `browser_service.cmd_open` |
|
||||
| `delete` | `account_service.cmd_delete_by_id` / `cmd_delete_by_platform` / `cmd_delete_by_platform_phone` |
|
||||
### 平台管理
|
||||
|
||||
入口:`scripts/main.py` → `cli/app.py` → 上表。
|
||||
| CLI | 说明 |
|
||||
|-----|------|
|
||||
| `platform list [--domain logistics\|llm\|content]` | 列出平台注册 |
|
||||
| `platform get <platform>` | 获取平台详情 |
|
||||
|
||||
### 账号管理
|
||||
|
||||
| CLI | 说明 |
|
||||
|-----|------|
|
||||
| `account add-web --platform <p> --login-id <id> [...]` | 创建网页/RPA 账号 |
|
||||
| `account add-secret --platform <p> --credential-type <type> [...]` | 创建 API Key/Token 凭据 |
|
||||
| `account get <id> [--with-credentials]` | 获取单条账号 JSON |
|
||||
| `account list [--platform <p>] [--environment <env>] [--tenant-id <t>] [--role <role>]` | 列出账号 JSON 数组 |
|
||||
| `account pick-web --platform <p> [--lease] [--ttl-sec 900]` | 挑选网页自动化候选 |
|
||||
| `account mark-session <id> --session-status <status>` | 标记登录状态 |
|
||||
| `account mark-error <id> --code <code> --message <msg>` | 标记错误 |
|
||||
| `account mark-used <id>` | 标记已使用 |
|
||||
| `account open <id>` | 打开持久化浏览器 profile(仅查看) |
|
||||
|
||||
### 凭据管理
|
||||
|
||||
| CLI | 说明 |
|
||||
|-----|------|
|
||||
| `credential pick --platform <p> [--type <type>] [--reveal]` | 挑选凭据(默认隐藏 secret) |
|
||||
| `credential resolve --id <credential_id> [--reveal]` | 按 ID 解析凭据 |
|
||||
|
||||
### 租约管理
|
||||
|
||||
| CLI | 说明 |
|
||||
|-----|------|
|
||||
| `lease release <lease_token>` | 释放租约 |
|
||||
| `lease list [--active]` | 列出租约 |
|
||||
| `lease cleanup` | 清理过期租约 |
|
||||
|
||||
### 浏览器
|
||||
|
||||
| CLI | 说明 |
|
||||
|-----|------|
|
||||
| `account open <id>` | 打开浏览器查看(仅查看) |
|
||||
| `open <id>` | 同上(兼容别名) |
|
||||
|
||||
### 兼容入口(旧版别名)
|
||||
|
||||
| CLI | 等价于 |
|
||||
|-----|--------|
|
||||
| `get <id>` | `account get <id>` |
|
||||
| `list-json <platform\|all> [--limit N]` | JSON 数组输出 |
|
||||
| `pick-web <platform>` | `account pick-web --platform <platform>` |
|
||||
| `list [platform\|all]` | 人类可读列表 |
|
||||
| `add <platform> <phone>` | `account add-web`(phone 作为 login_id) |
|
||||
| `delete id\|platform <...>` | 删除账号 |
|
||||
|
||||
---
|
||||
|
||||
## account add-web
|
||||
|
||||
```bash
|
||||
python main.py account add-web \
|
||||
--platform maersk \
|
||||
--login-id demo@maersk.com \
|
||||
--login-id-type email \
|
||||
--label "Maersk simulator booking" \
|
||||
--tenant-id tenant-demo \
|
||||
--environment simulator \
|
||||
--role booking \
|
||||
--provider-code maersk \
|
||||
--url http://localhost:5180/industries/logistics/maersk/login
|
||||
```
|
||||
|
||||
- `--platform`(必填):平台键/别名
|
||||
- `--login-id`:登录标识(email/username/phone/customer_code)
|
||||
- `--login-id-type`:默认 `unknown`
|
||||
- `--label`:人可读名称,不填则自动拼接
|
||||
- `--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
|
||||
|
||||
```bash
|
||||
# env 方式
|
||||
python main.py account add-secret \
|
||||
--platform deepseek \
|
||||
--credential-type api_key \
|
||||
--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 \
|
||||
--environment production \
|
||||
--role api
|
||||
```
|
||||
|
||||
- `--secret-storage`:`env` / `windows_credential` / `none`
|
||||
- `--secret-stdin`:从 stdin 读取 secret(仅 windows_credential)
|
||||
- `--secret-ref`:环境变量名(仅 env)
|
||||
- `none` 仅允许 `credential_type=browser_profile` 或 `note`
|
||||
|
||||
输出 JSON,包含 `account_id`(未指定 `--account-id` 时会自动创建一条用于挂载凭据的账号记录)、`credential_id`、`secret_mask`、`secret_ref`,**不包含 secret 明文**。
|
||||
|
||||
## account pick-web
|
||||
|
||||
```bash
|
||||
python main.py account pick-web \
|
||||
--platform maersk \
|
||||
--environment simulator \
|
||||
--tenant-id tenant-demo \
|
||||
--role booking \
|
||||
--lease \
|
||||
--ttl-sec 900 \
|
||||
--holder monitor-competitor-rates \
|
||||
--purpose maersk_sim_rpa
|
||||
```
|
||||
|
||||
- 筛选 status=active 且未被 active lease 占用的账号
|
||||
- 优先 session_status != expired
|
||||
- 优先 last_used_at 为空的账号
|
||||
- `--lease`:创建 lease,返回 `lease_token` 和 `lease_expires_at`
|
||||
- `--ttl-sec`:租约时长,默认 900 秒
|
||||
|
||||
## credential pick
|
||||
|
||||
成功时输出单行 JSON:`{"success": true, ...fields }`;失败时为 [ERRORS.md](ERRORS.md) 的机器 JSON。
|
||||
|
||||
```bash
|
||||
# 默认不返回 secret
|
||||
python main.py credential pick --platform deepseek --type api_key --environment production --role api
|
||||
|
||||
# --reveal 才返回 secret 明文
|
||||
python main.py credential pick --platform deepseek --type api_key --environment production --role api --reveal
|
||||
```
|
||||
|
||||
## 通用说明
|
||||
|
||||
- **平台参数**:可为 `scripts/util/platforms.py` 中配置的**中文展示名、别名或英文键**(如 `sohu`、`搜狐号`)。详见 [PLATFORMS.md](PLATFORMS.md)。
|
||||
- **数据与路径**:库文件、profile 目录由环境变量决定,网关与本地终端不一致时会「看不到同一份数据」。详见 [RUNTIME.md](RUNTIME.md)。
|
||||
- **机器可读子命令**:`get`、`list-json`、`pick-web` 的成功/失败约定见 [INTEGRATION.md](INTEGRATION.md)。
|
||||
- **错误码前缀**:见 [ERRORS.md](ERRORS.md)。
|
||||
|
||||
> 说明:当前版本 **未实现** `health` / `version` 子命令;与工作区其它技能的统一约定可对齐后另补。
|
||||
|
||||
---
|
||||
|
||||
## 子命令一览
|
||||
|
||||
### `add` — 添加账号
|
||||
|
||||
```bash
|
||||
python main.py add <平台> <手机号>
|
||||
```
|
||||
|
||||
- 手机号为**中国大陆 11 位**(`1` 开头,第二位 `3–9`),可含空格/分隔符,入库前会归一成数字。
|
||||
- 同一 `platform` 下同一手机号不可重复。
|
||||
|
||||
### `list` — 列出账号(人类可读多行块)
|
||||
|
||||
```bash
|
||||
python main.py list [平台|all|全部]
|
||||
```
|
||||
|
||||
- 省略第二参数时等价于 `all`。
|
||||
- 默认最多 **10** 条(按创建时间倒序);内部实现见 `service/account_service.cmd_list`。
|
||||
|
||||
### 简写:`python main.py <平台>` / `python main.py <平台> list`
|
||||
|
||||
- 若第一个参数能解析为平台,则等价于 `list <平台>`。
|
||||
|
||||
### `get` — 按 id 输出**单行 JSON**
|
||||
|
||||
```bash
|
||||
python main.py get <id>
|
||||
```
|
||||
|
||||
- 成功:`stdout` **仅一行** JSON 对象(UTF-8)。
|
||||
- 失败:首行 `ERROR:ACCOUNT_NOT_FOUND`,路径提示在 stderr。
|
||||
|
||||
### `list-json` — 列表的**单行 JSON 数组**(跨技能)
|
||||
|
||||
```bash
|
||||
python main.py list-json <平台|all|全部> [--limit N]
|
||||
```
|
||||
|
||||
- 成功:`stdout` **仅一行** JSON 数组;元素结构与 `get` 单条一致。
|
||||
- 默认 `limit=200`,实际 clamp 为 `1..500`。
|
||||
- 排序:按 `updated_at` 倒序。
|
||||
|
||||
### `pick-web` — 网页自动化候选账号(单行 JSON)
|
||||
|
||||
```bash
|
||||
python main.py pick-web <平台>
|
||||
```
|
||||
|
||||
- 按该平台 `updated_at`、`created_at` 倒序选一条;**不**表示当前浏览器已登录。
|
||||
- 失败:首行 `ERROR:`。
|
||||
|
||||
### `open` — 仅打开浏览器(**不写库、不检测登录**)
|
||||
|
||||
```bash
|
||||
python main.py open <id>
|
||||
```
|
||||
|
||||
- 需本机 Chrome/Edge + Playwright;详见运行环境说明。
|
||||
- 仅供人工核对页面;登录与否由业务侧(如 llm-manager 网页引擎)在使用账号时自行处理。
|
||||
|
||||
### `delete` — 删除库记录并尽量删除 profile 目录
|
||||
|
||||
```bash
|
||||
python main.py delete id <id>
|
||||
python main.py delete platform <平台>
|
||||
python main.py delete platform <平台> <手机号>
|
||||
```
|
||||
|
||||
- 第二段必须为 `id` 或 `platform`(小写不敏感)。
|
||||
|
||||
---
|
||||
|
||||
## 无参数 / 未知子命令
|
||||
|
||||
- 无参数或无法解析:打印用法概览;未知子命令时首行 `ERROR:CLI_UNKNOWN_OR_BAD_ARGS`,退出码 `1`。
|
||||
- **平台参数**:可为 `scripts/util/platforms.py` 中配置的**展示名、别名或英文键**(如 `sohu`、`搜狐号`、`maersk`、`马士基`)。详见 [PLATFORMS.md](PLATFORMS.md)。
|
||||
- **数据与路径**:库文件、profile 目录由环境变量决定。详见 [RUNTIME.md](RUNTIME.md)。
|
||||
- **机器可读命令**:成功时输出单行 JSON;失败时首行 `ERROR:`。详见 [INTEGRATION.md](INTEGRATION.md)。
|
||||
- **错误码**:见 [ERRORS.md](ERRORS.md)。
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
# 终端前缀约定(account-manager)
|
||||
# 终端错误码(account-manager)
|
||||
|
||||
约定:**机器解析只依赖 `stdout` 首行**时,应先判断首行是否以 `ERROR:` 开头;多行说明可忽略或仅作展示。
|
||||
|
||||
## `ERROR:` — CLI 参数 / 路由
|
||||
## 新增机器 JSON 失败格式
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": {
|
||||
"code": "ERROR:...",
|
||||
"message": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## ERROR:CLI — CLI 参数 / 路由
|
||||
|
||||
| 前缀 | 含义 |
|
||||
|------|------|
|
||||
@@ -13,31 +25,55 @@
|
||||
| `ERROR:CLI_DELETE_BAD_MODE` | `delete` 第二段不是 `id`/`platform` |
|
||||
| `ERROR:CLI_LIST_JSON_MISSING_PLATFORM` | `list-json` 缺少平台参数 |
|
||||
| `ERROR:CLI_PICK_WEB_MISSING_ARGS` | `pick-web` 缺少平台 |
|
||||
| `ERROR:CLI_BAD_ARGS` | 子命令参数缺失或非法 |
|
||||
| `ERROR:CLI_UNKNOWN_OR_BAD_ARGS` | 无法识别的子命令或参数组合 |
|
||||
|
||||
## `ERROR:` — 业务与数据
|
||||
## ERROR: — 数据库
|
||||
|
||||
| 前缀 | 含义 |
|
||||
|------|------|
|
||||
| `ERROR:INVALID_PLATFORM_LIST` | `list` 的平台名无法识别 |
|
||||
| `ERROR:INVALID_PLATFORM_LIST_JSON` | `list-json` 的平台名无法识别 |
|
||||
| `ERROR:INVALID_PLATFORM` | 其它子命令中平台无法识别 |
|
||||
| `ERROR:NO_ACCOUNTS_FOUND` | 列表无结果(或 `delete platform` 下无记录) |
|
||||
| `ERROR:ACCOUNT_NOT_FOUND` | 指定 id/记录不存在 |
|
||||
| `ERROR:PHONE_REQUIRED` | 缺少手机号 |
|
||||
| `ERROR:PHONE_INVALID` | 手机号格式不符合大陆 11 位规则 |
|
||||
| `ERROR:DUPLICATE_PHONE_PLATFORM` | 同平台下山手机号已存在 |
|
||||
| `ERROR:DELETE_INVALID_ID` | 删除 id 非法 |
|
||||
| `ERROR:NO_ACCOUNT` | `pick-web` 该平台无任何记录 |
|
||||
| `ERROR:DB_ERROR` | SQLite 写入失败等 |
|
||||
|
||||
## `ERROR:` — 浏览器 / 环境
|
||||
## ERROR: — 平台与账号
|
||||
|
||||
| 前缀 | 含义 |
|
||||
|------|------|
|
||||
| `ERROR:需要 playwright Python 包:…` | 未安装 `playwright` 包,或本机无 Chrome/Edge(channel 模式,**不**需 `playwright install chromium`) |
|
||||
| `ERROR:INVALID_PLATFORM` | 平台名无法识别 |
|
||||
| `ERROR:NO_ACCOUNTS_FOUND` | 列表无结果 |
|
||||
| `ERROR:ACCOUNT_NOT_FOUND` | 指定 id 不存在 |
|
||||
| `ERROR:ACCOUNT_DISABLED` | 账号状态为 disabled |
|
||||
| `ERROR:NO_ACCOUNT` | `pick-web` 无符合条件的可用账号(含:均被 active 未过期 lease 占用时) |
|
||||
|
||||
## ERROR: — 租约
|
||||
|
||||
| 前缀 | 含义 |
|
||||
|------|------|
|
||||
| `ERROR:LEASE_CONFLICT` | 同账号已有 active 未过期 lease |
|
||||
| `ERROR:LEASE_NOT_FOUND` | 未找到活跃租约 |
|
||||
| `ERROR:LEASE_EXPIRED` | 租约已过期 |
|
||||
|
||||
## ERROR: — 凭据与 Secret
|
||||
|
||||
| 前缀 | 含义 |
|
||||
|------|------|
|
||||
| `ERROR:CREDENTIAL_NOT_FOUND` | 凭据不存在 |
|
||||
| `ERROR:CREDENTIAL_DISABLED` | 凭据不可用 |
|
||||
| `ERROR:SECRET_STORAGE_UNSUPPORTED` | 不支持的 secret 存储方式 |
|
||||
| `ERROR:SECRET_REF_MISSING` | env 存储缺少环境变量名 |
|
||||
| `ERROR:SECRET_READ_FAILED` | 读取 secret 失败 |
|
||||
| `ERROR:SECRET_WRITE_FAILED` | 写入 secret 失败 |
|
||||
| `ERROR:SECRET_ENV_MISSING` | 环境变量未设置 |
|
||||
| `ERROR:WINDOWS_CREDENTIAL_UNAVAILABLE` | 非 Windows 平台不支持 |
|
||||
|
||||
## ERROR: — 浏览器 / 环境
|
||||
|
||||
| 前缀 | 含义 |
|
||||
|------|------|
|
||||
| `ERROR:需要 playwright Python 包` | 未安装 `playwright` 包或本机无 Chrome/Edge |
|
||||
| `ERROR:PROFILE_DIR_MISSING` | 账号记录中 `profile_dir` 为空 |
|
||||
|
||||
## 非前缀输出
|
||||
|
||||
- **成功添加账号**、**删除成功**等可能包含 `✅` 等人类可读行,**不宜**作为稳定协议解析。
|
||||
- **`get` / `list-json` / `pick-web` 成功**:`stdout` 应为**单行 JSON**(失败时首行 `ERROR:`,勿当 JSON)。
|
||||
- **`get` / `list-json` / `pick-web`** 成功时:`stdout` 应为**单行 JSON**。
|
||||
- 失败时首行 `ERROR:`,可能有后续说明行。
|
||||
- **新增机器命令建议统一 JSON 输出**,旧兼容命令可继续输出 `ERROR:` 文本前缀。
|
||||
|
||||
@@ -1,35 +1,93 @@
|
||||
# 与其它 Skill 集成(account-manager)
|
||||
|
||||
## 核心约束
|
||||
|
||||
业务 skill **不能自己存账号、密码、API Key、Token**。必须通过 account-manager CLI 获取。
|
||||
|
||||
## 推荐调用方式
|
||||
|
||||
使用 **`subprocess`** 调用技能根目录下的 `scripts/main.py`,工作目录可为技能根或 `scripts/`(只要命令中的 `python` 与路径一致)。宿主注入的 **`JIANGCHANG_DATA_ROOT` / `JIANGCHANG_USER_ID`** 必须与最终用户会话一致,否则读写到错误库。
|
||||
使用 **`subprocess`** 调用 `scripts/main.py`,工作目录可为技能根或 `scripts/`。宿主注入的 **`JIANGCHANG_DATA_ROOT` / `JIANGCHANG_USER_ID`** 必须与最终用户会话一致。
|
||||
|
||||
## 机器可读命令摘要
|
||||
|
||||
| 目的 | 命令 | 成功时 stdout |
|
||||
|------|------|----------------|
|
||||
| 取单条账号 JSON | `get <id>` | 单行 JSON 对象 |
|
||||
| 批量账号 JSON | `list-json <平台或all> [--limit N]` | 单行 JSON 数组 |
|
||||
| 网页自动化候选账号 | `pick-web <平台>` | 单行 JSON 对象(按 `updated_at` 选一条,**不**表示当前已登录) |
|
||||
| 取单条账号 JSON | `account get <id>` | 单行 JSON 对象 |
|
||||
| 批量账号 JSON | `account list --platform <p> [--environment <e>]` | 单行 JSON 数组 |
|
||||
| 网页自动化候选 | `account pick-web --platform <p> [--lease]` | 单行 JSON 对象 |
|
||||
| 获取 API Key | `credential pick --platform <p> --type api_key [--reveal]` | 单行 JSON(`success: true` + 字段) |
|
||||
| 兼容入口 | `get <id>` / `list-json <p>` / `pick-web <p>` | 同上 |
|
||||
|
||||
## 解析协议(强建议)
|
||||
## 解析协议
|
||||
|
||||
1. 读取子进程 **stdout** 全文或首行。
|
||||
2. 若首行以 **`ERROR:`** 开头 → 失败,不要 `json.loads` 整段 stdout。
|
||||
3. **`get` / `list-json` / `pick-web`**:成功时应对**第一行**做 `json.loads`;后续行应不存在,若有则视为非协议内容。
|
||||
1. 读取子进程 **stdout** 首行。
|
||||
2. 若首行以 **`ERROR:`** 开头 → 失败。
|
||||
3. 否则对首行做 `json.loads`。
|
||||
|
||||
## JSON 对象字段(与 `get` 一致)
|
||||
## JSON 对象字段
|
||||
|
||||
典型字段见仓库 `assets/examples/get-response.json` 与 `assets/schemas/account-record.schema.json`。
|
||||
### account get / pick-web
|
||||
|
||||
常见键名包括:`id`, `name`, `platform`, `phone`, `profile_dir`, `url`, `created_at`, `updated_at`;`extra_json` 列中的扁平扩展可能并入同一对象。
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"platform_key": "maersk",
|
||||
"account_label": "Maersk simulator booking",
|
||||
"login_id": "demo@maersk.com",
|
||||
"login_id_type": "email",
|
||||
"tenant_id": "tenant-demo",
|
||||
"environment": "simulator",
|
||||
"role": "booking",
|
||||
"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",
|
||||
"last_used_at": "2026-05-01T10:00:00",
|
||||
"created_at": "2026-05-01T09:00:00",
|
||||
"updated_at": "2026-05-01T09:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
**库中不再持久化「是否已登录」**;编排侧在网页自动化中自行处理登录(与 `pick-web` / `get` 返回的 `profile_dir` 同一浏览器会话)。
|
||||
pick-web 额外字段(带 lease 时):
|
||||
- `lease_token`: 租约 token
|
||||
- `lease_expires_at`: 过期时间
|
||||
|
||||
## Publisher / 自动化流水线示例
|
||||
### credential pick
|
||||
|
||||
1. `pick-web 搜狐号`(或目标平台)→ 解析 JSON → 取 `id`、`profile_dir`、`url`。
|
||||
2. 使用 `profile_dir` 启动持久化浏览器上下文,在业务页面内完成或等待登录。
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"id": 1,
|
||||
"platform_key": "deepseek",
|
||||
"credential_label": "DeepSeek production key",
|
||||
"credential_type": "api_key",
|
||||
"secret_storage": "env",
|
||||
"secret_ref": "DEEPSEEK_API_KEY",
|
||||
"secret_mask": "****7890",
|
||||
"status": "active"
|
||||
}
|
||||
```
|
||||
|
||||
**只有 `--reveal` 时才返回 `secret` 字段。业务 skill 不要向最终用户展示 reveal 输出。**
|
||||
|
||||
失败时使用统一 JSON:`{"success": false, "error": {"code": "ERROR:...", "message": "..."}}`(见 [ERRORS.md](ERRORS.md))。
|
||||
|
||||
## 业务流程示例
|
||||
|
||||
### 物流 RPA
|
||||
|
||||
1. `account pick-web --platform maersk --environment simulator --role booking --lease --holder my-skill`
|
||||
2. 解析 JSON → 取 `id`、`profile_dir`、`url`、`lease_token`
|
||||
3. 用 `profile_dir` 启动持久化浏览器上下文
|
||||
4. 业务完成后:`lease release <lease_token>`
|
||||
5. 如遇登录失效:`account mark-session <id> --session-status needs_login`
|
||||
|
||||
### LLM API 调用
|
||||
|
||||
1. `credential pick --platform deepseek --type api_key --environment production --reveal`
|
||||
2. 解析 JSON → 取 `secret` 字段
|
||||
3. 在业务进程内存中使用,不写文件、不打日志
|
||||
|
||||
## 退出码
|
||||
|
||||
|
||||
@@ -1,24 +1,50 @@
|
||||
# 平台与别名(account-manager)
|
||||
|
||||
**权威来源**:`scripts/util/platforms.py` 中的 `PLATFORMS`。下表便于 AI/文档阅读;若与代码不一致,**以代码为准**。
|
||||
**权威来源**:`scripts/util/platforms.py` 中的 `PLATFORMS`。下表便于文档阅读;若与代码不一致,**以代码为准**。
|
||||
|
||||
入库字段 `accounts.platform` 使用下表 **英文键**(小写)。CLI 与用户话术可使用 **展示名** 或 **别名**。
|
||||
## 物流平台
|
||||
|
||||
| 英文键 (`platform`) | 展示名 (`label`) | 默认账号名前缀 (`prefix`) | 别名 (`aliases`) | 默认 URL |
|
||||
|---------------------|------------------|---------------------------|------------------|----------|
|
||||
| `sohu` | 搜狐号 | 搜狐 | 搜狐 | https://mp.sohu.com |
|
||||
| `toutiao` | 头条号 | 头条 | 头条 | https://mp.toutiao.com/ |
|
||||
| `zhihu` | 知乎 | (同 label) | 知乎号 | https://www.zhihu.com |
|
||||
| `wechat` | 微信公众号 | 微信 | 公众号、微信 | https://mp.weixin.qq.com |
|
||||
| `kimi` | Kimi | (同 label) | 月之暗面 | https://kimi.moonshot.cn |
|
||||
| `deepseek` | DeepSeek | (同 label) | — | https://chat.deepseek.com |
|
||||
| `doubao` | 豆包 | (同 label) | — | https://www.doubao.com |
|
||||
| `qianwen` | 通义千问 | 通义 | 通义、千问 | https://tongyi.aliyun.com |
|
||||
| `yiyan` | 文心一言 | 文心 | 文心、一言 | https://yiyan.baidu.com |
|
||||
| `yuanbao` | 腾讯元宝 | 元宝 | 元宝 | https://yuanbao.tencent.com |
|
||||
| `gemini` | Gemini | Gemini | 谷歌Gemini、Google Gemini、google gemini、Bard | https://gemini.google.com |
|
||||
| 英文键 | 展示名 | 供应商代码 | 别名 |
|
||||
|--------|--------|-----------|------|
|
||||
| `maersk` | Maersk | maersk | 马士基 |
|
||||
| `cosco` | COSCO | cosco | 中远海运 |
|
||||
| `msc` | MSC | msc | 地中海航运 |
|
||||
| `cma_cgm` | CMA CGM | cma_cgm | 达飞 |
|
||||
| `evergreen` | Evergreen | evergreen | 长荣 |
|
||||
| `cargo_wise` | CargoWise | cargo_wise | Cargo Wise |
|
||||
| `freightos` | Freightos | freightos | — |
|
||||
| `webcargo` | WebCargo | webcargo | Web Cargo |
|
||||
| `sinotrans` | Sinotrans | sinotrans | 中外运 |
|
||||
|
||||
## 解析规则(摘要)
|
||||
## LLM / AI 平台
|
||||
|
||||
- 英文键本身、各 `label`、各 `aliases` 条目(及小写形式)均可解析到对应键。
|
||||
- 无法识别时,相关子命令会输出 `ERROR:INVALID_PLATFORM` 或 `ERROR:INVALID_PLATFORM_LIST` / `INVALID_PLATFORM_LIST_JSON` 等,并附带「支持的平台」提示。
|
||||
| 英文键 | 展示名 | 别名 | 默认 URL |
|
||||
|--------|--------|------|----------|
|
||||
| `deepseek` | DeepSeek | — | https://chat.deepseek.com |
|
||||
| `doubao` | Doubao | 豆包 | https://www.doubao.com |
|
||||
| `kimi` | Kimi | 月之暗面 | https://kimi.moonshot.cn |
|
||||
| `qianwen` | Qianwen | 通义千问、通义、千问 | https://tongyi.aliyun.com |
|
||||
| `yiyan` | YiYan | 文心一言、文心、一言 | https://yiyan.baidu.com |
|
||||
| `yuanbao` | Yuanbao | 腾讯元宝、元宝 | https://yuanbao.tencent.com |
|
||||
| `gemini` | Gemini | 谷歌Gemini、Google Gemini、Bard | https://gemini.google.com |
|
||||
| `minimax` | MiniMax | — | — |
|
||||
|
||||
## 内容平台
|
||||
|
||||
| 英文键 | 展示名 | 别名 | 默认 URL |
|
||||
|--------|--------|------|----------|
|
||||
| `sohu` | 搜狐号 | 搜狐 | https://mp.sohu.com |
|
||||
| `toutiao` | 头条号 | 头条 | https://mp.toutiao.com/ |
|
||||
| `zhihu` | 知乎 | 知乎号 | https://www.zhihu.com |
|
||||
| `wechat` | 微信公众号 | 公众号、微信 | https://mp.weixin.qq.com |
|
||||
|
||||
## 解析规则
|
||||
|
||||
- 英文键本身、各 `display_name`、各 `aliases` 条目(及小写形式)均可解析到对应键。
|
||||
- 不区分大小写。
|
||||
- 无法识别时输出 `ERROR:INVALID_PLATFORM`,并附带支持的平台列表。
|
||||
- 解析函数:`resolve_platform_key(name)` — 支持 key、display_name、aliases。
|
||||
|
||||
## 平台注册到数据库
|
||||
|
||||
`seed_platforms(conn)` 在每次 `init_db()` 后自动执行,将 `PLATFORMS` 字典 upsert 到 `platforms` 表。
|
||||
|
||||
@@ -1,51 +1,52 @@
|
||||
---
|
||||
description: "统一管理搜狐、头条、知乎、微信、豆包、Kimi、DeepSeek 等多平台账号与浏览器配置目录。添加账号后,其它技能(如大模型写作、平台发布)可按平台自动选用对应环境。"
|
||||
description: "通用 Credential & Browser Profile Manager:管理网页账号、RPA 浏览器 profile、LLM/API 平台 API Key。支持物流、LLM、内容三大业务域。"
|
||||
---
|
||||
|
||||
# 👤 账号管理
|
||||
# 🔐 账号与凭据管理
|
||||
|
||||
把你在各平台的账号**登记到本地**,后续「用大模型写稿」「发布到搜狐号」等技能才能按平台选用对应账号。
|
||||
把你在各平台的账号与凭据**登记到本地**,后续物流 RPA、大模型写作、内容发布等技能才能自动选用对应环境。
|
||||
|
||||
> 本技能**只负责登记账号**,不在此处判断「有没有登录网站」。真正打开网页时,由对应业务(例如大模型网页版)在同窗口里提示你完成登录。
|
||||
> 本技能是**唯一**账号/凭据管理入口。业务 skill 不自己存密码、API Key,而是通过 CLI 调用获取。
|
||||
|
||||
## 它能帮你做什么
|
||||
|
||||
- **添加账号** —— 选一个平台(如豆包、搜狐号),在对话里说出 **11 位大陆手机号**即可。
|
||||
- **查看列表** —— 按平台或全部列出已登记的账号。
|
||||
- **删除账号** —— 按 id、按平台整批、或按「平台 + 手机号」删除,并可清理对应本地目录。
|
||||
- **给其它技能用** —— 自动化的技能会通过内部接口按平台**取一条候选账号**(不要求你手工抄 id)。
|
||||
- **添加网页/RPA 账号** — 选平台,给出登录标识(邮箱/手机/用户名),自动创建浏览器 profile 目录。
|
||||
- **添加 API Key/Token** — 安全存储:API Key 明文存入 Windows Credential Manager 或环境变量引用,SQLite 只保存元数据和打码值。
|
||||
- **查看/列出账号** — 按平台、环境、角色等多维度筛选。
|
||||
- **给 RPA 技能用** — `pick-web` 按规则挑候选账号,支持 lease 防并发。
|
||||
- **给 LLM 技能用** — `credential pick` 安全获取 API Key。
|
||||
- **在浏览器里查看** — `open <id>` 打开 Chrome/Edge 查看,仅查看不写库。
|
||||
|
||||
## 你可以这样对它说
|
||||
|
||||
- 「帮我添加一个豆包账号,手机号 138xxxx。」
|
||||
- 「列出我所有的搜狐号账号。」
|
||||
- 「删除头条号里手机尾号 3701 的那条。」
|
||||
- 「我想看看 3 号账号在浏览器里打开是什么页面。」
|
||||
- 「帮我添加一个 Maersk 模拟器账号,邮箱 demo@maersk.com。」
|
||||
- 「添加 DeepSeek 的 API Key,存在 Windows 凭据管理器里。」
|
||||
- 「列出所有物流平台的账号。」
|
||||
- 「用浏览器打开 3 号账号看看页面。」
|
||||
- 「给 RPA 技能取一个 maersk 模拟器的 booking 账号。」
|
||||
|
||||
## 你需要提供什么
|
||||
|
||||
| 场景 | 你需要给的 |
|
||||
|---|---|
|
||||
| 添加账号 | **平台名称**(可说中文,如豆包、搜狐号) + **大陆 11 位手机号**(同平台下同号不能重复) |
|
||||
| 删除 | 账号 **id**,或平台名,或平台名 + 手机号 |
|
||||
| 仅打开浏览器核对 | 账号 **id**(需本机已安装 Chrome 或 Edge) |
|
||||
|
||||
## 失败了怎么办
|
||||
|
||||
- **提示手机号格式不对**:需 **1 开头、第二位 3~9、共 11 位数字**。
|
||||
- **提示同平台手机号已存在**:该平台上这条号已经加过,无需重复添加。
|
||||
- **列表是空的但你觉得应该有**:可能是当前设备与云端使用了**不同的数据目录**;在宿主设置里确认数据根目录与账号一致,或联系管理员。
|
||||
| 添加网页账号 | **平台名称** + **登录标识**(邮箱/手机/用户名) |
|
||||
| 添加 API Key | **平台名称** + **凭据类型**(api_key 等)+ **secret**(通过 stdin 或环境变量) |
|
||||
| 查看/列出 | 可选:平台名、环境、角色等筛选条件 |
|
||||
| 浏览器打开 | 账号 **id**(需本机已安装 Chrome 或 Edge) |
|
||||
|
||||
## 它不做什么
|
||||
|
||||
- ❌ 不在此处替你**判定**各网站「是否已登录」(由使用账号的具体功能负责)
|
||||
- ❌ 不代替**内容管理、发布、大模型调用**等业务技能(本技能只提供账号与目录信息)
|
||||
- ❌ 不存储你的**大模型 API Key**(那是大模型管理技能的职责)
|
||||
- 不在此处判定各网站「是否已登录」(由业务技能自行处理)
|
||||
- 不代替内容管理、发布、大模型调用等业务技能
|
||||
- 不保存 API Key 明文在 SQLite 中(仅存引用和打码值)
|
||||
|
||||
## 相关技能
|
||||
## Secret 存储方式
|
||||
|
||||
- **大模型管理**:写稿时若走网页版大模型,会依赖本技能登记的账号与目录。
|
||||
- **内容管理、各平台发布**:按平台取账号时也会用到本技能的数据。
|
||||
| 方式 | 说明 |
|
||||
|---|---|
|
||||
| `none` | 无 secret(浏览器 profile 登录态) |
|
||||
| `env` | 引用环境变量名,运行时读取 |
|
||||
| `windows_credential` | 正式推荐:真实 secret 存 Windows Credential Manager |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,48 +1,59 @@
|
||||
# 运行环境与数据路径(account-manager)
|
||||
|
||||
## 数据落盘位置(当前实现)
|
||||
## 数据落盘位置
|
||||
|
||||
`get_data_root()` / `get_user_id()` 来自 **`scripts/jiangchang_skill_core/runtime_env.py`**(与 `jiangchang-platform-kit` 同源);`scripts/util/runtime_paths.py` 在此基础上拼技能子目录。
|
||||
`get_data_root()` / `get_user_id()` 来自 **`scripts/jiangchang_skill_core/runtime_env.py`**;`scripts/util/runtime_paths.py` 在此基础上拼技能子目录。
|
||||
|
||||
- **数据根目录**:优先 **`JIANGCHANG_DATA_ROOT`**;未设置且未走本地注入时,Windows 默认 `D:\jiangchang-data`,其它系统 `~/.jiangchang-data`。
|
||||
- **用户/工作空间 id**:优先 **`JIANGCHANG_USER_ID`**;未设置且未走本地注入时为 **`_anon`**。
|
||||
- **用户/工作空间 id**:优先 **`JIANGCHANG_USER_ID`**;未设置时为 **`_anon`**。
|
||||
- **技能数据目录**:`{数据根}/{用户id}/account-manager/`
|
||||
- **SQLite**:`account-manager.db`
|
||||
- **Profile**:`profiles/<平台展示名>/<手机号>/`(由 `get_default_profile_dir` 生成)
|
||||
- **日志**:与其它技能共用**用户级**目录 `{数据根}/{用户id}/logs/jiangchang.log`(按日轮转)
|
||||
- **Profile**:`profiles/{domain}/{platform_key}/{safe_label}[_{login_id_suffix}]/`
|
||||
- **日志**:与其它技能共用 `{数据根}/{用户id}/logs/jiangchang.log`
|
||||
|
||||
## 调试:为什么「list 没数据」
|
||||
|
||||
- 若终端与网关注入的 `JIANGCHANG_*` 不一致,会写到**不同用户目录**,库文件不是同一份。
|
||||
- 设置 **`JIANGCHANG_ACCOUNT_DEBUG_PATHS=1`**(`1`/`true`/`yes`/`on`)后,每次 CLI 子命令前会在 **stderr** 打印实际根目录、用户 id 与数据库路径(`_maybe_print_paths_debug_cli`)。
|
||||
- 若终端与网关注入的 `JIANGCHANG_*` 不一致,会写到**不同用户目录**。
|
||||
- 设置 **`JIANGCHANG_ACCOUNT_DEBUG_PATHS=1`** 后,每次 CLI 命令前在 **stderr** 打印实际路径。
|
||||
|
||||
## 本地 CLI 默认值(`runtime_env`)
|
||||
## 本地 CLI 默认值
|
||||
|
||||
各技能 **`main.py`** 在 `sys.path` 就绪后、import 业务包之前调用 **`apply_cli_local_defaults()`**(实现见 `jiangchang_skill_core.runtime_env`):
|
||||
各技能 `main.py` 调用 `apply_cli_local_defaults()`:
|
||||
- `CLI_LOCAL_DEV_ENABLED = True` 时,未设置环境变量则注入平台默认值。
|
||||
- 发版前改为 `False` 或依赖宿主注入。
|
||||
|
||||
- 代码内 **`CLI_LOCAL_DEV_ENABLED = True`** 时,若当前未设置 `JIANGCHANG_DATA_ROOT` / `JIANGCHANG_USER_ID`,会注入平台默认数据根与 **`DEFAULT_LOCAL_USER_ID`**(与 kit 中常量一致)。
|
||||
- 代码内为 **`False`** 时,可设环境变量 **`JIANGCHANG_CLI_LOCAL_DEV=1`** 达到同样效果。
|
||||
- **发版/嵌入宿主前**:将各技能 vendored 的 `runtime_env.py` 中 `CLI_LOCAL_DEV_ENABLED` 改为 **`False`**,或完全依赖宿主注入。
|
||||
## Secret 存储
|
||||
|
||||
| 方式 | 说明 | 适用场景 |
|
||||
|------|------|----------|
|
||||
| `none` | 不存 secret | 浏览器 profile 登录态 |
|
||||
| `env` | SQLite 只存环境变量名,运行时从 `os.environ` 读取 | 轻量测试 |
|
||||
| `windows_credential` | 真实 secret 存 Windows Credential Manager | Windows 本地正式部署 |
|
||||
|
||||
- **不把 secret 明文写入 SQLite**
|
||||
- **不在日志中记录 secret 明文**
|
||||
- 只有 `credential pick --reveal` 或 `credential resolve --reveal` 才返回 secret
|
||||
|
||||
## 日志
|
||||
|
||||
实现见 `scripts/jiangchang_skill_core/unified_logging.py`,`util/logging_config.py` 仅 re-export。
|
||||
|
||||
| 变量 | 作用 |
|
||||
|------|------|
|
||||
| `JIANGCHANG_LOG_LEVEL` | 日志级别,默认 `INFO` |
|
||||
| `JIANGCHANG_LOG_TO_STDERR` | 设为 `1`/`true` 等时,WARNING 及以上同步 stderr |
|
||||
| `JIANGCHANG_LOG_FILE` | 覆盖主日志文件绝对路径(默认 `{数据根}/{用户id}/logs/jiangchang.log`) |
|
||||
| `JIANGCHANG_LOG_FILE` | 覆盖主日志文件绝对路径 |
|
||||
| `JIANGCHANG_LOG_BACKUP_COUNT` | 轮转保留份数,默认 `30` |
|
||||
| `JIANGCHANG_TRACE_ID` | 可选;跨技能子进程由父进程注入以串联同一调用链 |
|
||||
| `JIANGCHANG_TRACE_ID` | 可选;跨技能子进程由父进程注入 |
|
||||
|
||||
## 浏览器(open)
|
||||
|
||||
`open` 由 `service/browser_service.py` 与子进程 `service/open_child_runner.py` 启动持久化上下文,仅用于人工查看;**不做**登录态 DOM 检测。
|
||||
- 本机已安装 Chrome 或 Edge
|
||||
- Python 环境需 `playwright` 包(匠厂共享 runtime 已包含)
|
||||
- 使用 **channel 模式**(`channel=chrome|msedge`),**不下载 Chromium**
|
||||
- **不要执行 `playwright install chromium`**
|
||||
|
||||
依赖:**本机已安装 Chrome 或 Edge**;Python 环境需 **`playwright` 包**(匠厂共享 `python-runtime` 已包含)。运行时使用 **Playwright `channel=chrome|msedge`** 调系统浏览器,**不要**执行 `playwright install chromium`(避免下载自带 Chromium)。
|
||||
### 关键浏览器参数
|
||||
|
||||
## 常见问题(简要)
|
||||
|
||||
- **`ERROR:需要 playwright Python 包`**:确认共享 venv 已 `uv sync`;本机安装 Chrome 或 Edge。
|
||||
- **`ERROR:PROFILE_DIR_MISSING`**:库中该账号 `profile_dir` 为空,需检查数据或重新添加账号流程。
|
||||
- `headless=False`
|
||||
- `no_viewport=True`
|
||||
- `args` 包含 `--start-maximized`
|
||||
- stealth 模式可选(`OPENCLAW_PLAYWRIGHT_STEALTH` 环境变量控制)
|
||||
|
||||
@@ -1,28 +1,122 @@
|
||||
# 数据存储(account-manager)
|
||||
# 数据库表结构(account-manager v2)
|
||||
|
||||
## 数据库路径
|
||||
|
||||
`{JIANGCHANG_DATA_ROOT}/{JIANGCHANG_USER_ID}/account-manager/account-manager.db`
|
||||
|
||||
`JIANGCHANG_DATA_ROOT` 与 `JIANGCHANG_USER_ID` 由宿主注入,与兄弟技能保持一致。路径解析细节见 [RUNTIME.md](RUNTIME.md)。
|
||||
路径解析细节见 [RUNTIME.md](RUNTIME.md)。
|
||||
|
||||
## `accounts` 表(核心字段)
|
||||
## Schema 版本
|
||||
|
||||
- `id` —— 自增主键,CLI 与跨技能常称「账号 id」
|
||||
- `name` —— 展示用名称(如「豆包1号」)
|
||||
- `platform` —— 平台英文键(小写,如 `doubao`、`sohu`),见 [PLATFORMS.md](PLATFORMS.md)
|
||||
- `phone` —— 归一化后的 11 位数字串
|
||||
- `profile_dir` —— 持久化浏览器用户数据目录绝对路径,供 Playwright 等复用
|
||||
- `url` —— 该平台默认入口 URL
|
||||
- `extra_json` —— 可选扩展(JSON 文本),`get` 成功时可能并入返回对象
|
||||
- `created_at` / `updated_at` —— Unix 秒;`pick-web` 等按更新时间排序选候选
|
||||
`PRAGMA user_version = 2`
|
||||
|
||||
**说明**:表中**不**存「是否已登录」字段;业务侧在真实浏览器会话中自行处理登录态。
|
||||
## 1. platforms — 平台注册表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `platform_key` | TEXT PK | 平台唯一键(maersk / deepseek / sohu 等) |
|
||||
| `display_name` | TEXT NOT NULL | 展示名(Maersk / DeepSeek / 搜狐号) |
|
||||
| `domain` | TEXT NOT NULL | 业务域:logistics / llm / content / ecommerce / generic |
|
||||
| `provider_code` | TEXT | 供应商代码,物流 profile 可复用 |
|
||||
| `default_url` | TEXT | 默认入口 URL |
|
||||
| `aliases_json` | TEXT | 别名 JSON 数组 |
|
||||
| `capabilities_json` | TEXT | 能力声明 JSON(`{"web":true,"api_key":true,"rpa":true}`) |
|
||||
| `enabled` | INTEGER | 是否启用(1=yes 0=no) |
|
||||
| `created_at` | INTEGER | Unix 秒 UTC |
|
||||
| `updated_at` | INTEGER | Unix 秒 UTC |
|
||||
|
||||
**索引:** `idx_platforms_domain`, `idx_platforms_provider_code`
|
||||
|
||||
## 2. accounts — 账号身份
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | INTEGER PK AUTO | 主键 |
|
||||
| `platform_key` | TEXT NOT NULL | 对应 platforms.platform_key |
|
||||
| `account_label` | TEXT NOT NULL | 人可读名称 |
|
||||
| `login_id` | TEXT | 登录标识(email/phone/username/customer_code),可空 |
|
||||
| `login_id_type` | TEXT | email / username / phone / customer_code / api_account / unknown |
|
||||
| `tenant_id` | TEXT | 租户/项目标识,可空 |
|
||||
| `environment` | TEXT | simulator / staging / production / test |
|
||||
| `role` | TEXT | booking / tracking / admin / sales / api / default |
|
||||
| `provider_code` | TEXT | 冗余供应商码 |
|
||||
| `profile_dir` | TEXT | Playwright 持久化浏览器 profile 目录 |
|
||||
| `url` | TEXT | 账号默认入口 URL |
|
||||
| `status` | TEXT | active / disabled / needs_review |
|
||||
| `session_status` | TEXT | unknown / likely_valid / needs_login / expired |
|
||||
| `last_used_at` | INTEGER | 最近 pick/使用时间 |
|
||||
| `last_login_check_at` | INTEGER | 最近登录检查时间 |
|
||||
| `last_error_code` | TEXT | 最近错误代码 |
|
||||
| `last_error_message` | TEXT | 最近错误消息 |
|
||||
| `extra_json` | TEXT | 扩展字段 JSON |
|
||||
| `created_at` | INTEGER | Unix 秒 UTC |
|
||||
| `updated_at` | INTEGER | Unix 秒 UTC |
|
||||
|
||||
**索引:** `idx_accounts_platform`, `idx_accounts_pick_web`, `idx_accounts_provider`, `idx_accounts_status`
|
||||
|
||||
**唯一约束说明:** `(platform_key, login_id, tenant_id, environment, role)` 通过应用层检查,因为 SQLite 允许多条 NULL login_id。
|
||||
|
||||
## 3. credentials — 凭据(API Key / Token / Password)
|
||||
|
||||
**核心原则:SQLite 只保存元数据,不保存 secret 明文。**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | INTEGER PK AUTO | 主键 |
|
||||
| `account_id` | INTEGER | 关联 accounts.id,可空(平台级 API Key) |
|
||||
| `platform_key` | TEXT NOT NULL | 平台唯一键 |
|
||||
| `credential_label` | TEXT NOT NULL | 人可读名称 |
|
||||
| `credential_type` | TEXT | api_key / password / bearer_token / oauth_client / refresh_token / browser_profile / note |
|
||||
| `secret_storage` | TEXT | none / env / windows_credential |
|
||||
| `secret_ref` | TEXT | env 时为环境变量名;windows_credential 时为 target name |
|
||||
| `secret_mask` | TEXT | 打码展示(sk-****abcd),不可反推 |
|
||||
| `expires_at` | INTEGER | 过期时间 |
|
||||
| `status` | TEXT | active / disabled / expired / needs_rotation |
|
||||
| `last_used_at` | INTEGER | 最近使用时间 |
|
||||
| `extra_json` | TEXT | 扩展字段 JSON |
|
||||
| `created_at` | INTEGER | Unix 秒 UTC |
|
||||
| `updated_at` | INTEGER | Unix 秒 UTC |
|
||||
|
||||
**索引:** `idx_credentials_platform_type`, `idx_credentials_account`, `idx_credentials_status`
|
||||
|
||||
## 4. account_leases — RPA 并发锁
|
||||
|
||||
防止多个任务同时打开同一个 profile_dir。
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | INTEGER PK AUTO | 主键 |
|
||||
| `account_id` | INTEGER NOT NULL | 关联 accounts.id |
|
||||
| `lease_token` | TEXT UNIQUE | 随机 token,用于 release/heartbeat |
|
||||
| `holder` | TEXT NOT NULL | 持有者标识 |
|
||||
| `purpose` | TEXT | 用途说明 |
|
||||
| `expires_at` | INTEGER NOT NULL | 过期时间 |
|
||||
| `heartbeat_at` | INTEGER | 最近心跳时间 |
|
||||
| `released_at` | INTEGER | 主动释放时间 |
|
||||
| `status` | TEXT | active / released / expired |
|
||||
| `created_at` | INTEGER | Unix 秒 UTC |
|
||||
| `updated_at` | INTEGER | Unix 秒 UTC |
|
||||
|
||||
**索引:** `idx_leases_account_status`, `idx_leases_token`, `idx_leases_expires`
|
||||
|
||||
**约束:**
|
||||
- acquire 前先把过期 active lease 标记为 expired
|
||||
- 同一 account_id 同时只能有一个 active 未过期 lease
|
||||
- release 必须校验 lease_token
|
||||
|
||||
## Profile 文件布局
|
||||
|
||||
浏览器配置目录通常位于技能数据目录下的 `profiles/` 分层路径,由实现生成。删除账号时实现会尽量同时删除对应目录,见 [CLI.md](CLI.md) `delete` 说明。
|
||||
```
|
||||
{DATA_ROOT}/{USER_ID}/account-manager/
|
||||
├── account-manager.db
|
||||
└── profiles/
|
||||
└── {domain}/
|
||||
└── {platform_key}/
|
||||
└── {safe_label}[_{login_id_suffix}]/
|
||||
```
|
||||
|
||||
删除账号时实现会尽量同时删除对应目录。
|
||||
|
||||
## 与 JSON 输出的对应关系
|
||||
|
||||
`get` / `list-json` / `pick-web` 单行 JSON 的键名与上表及 `extra_json` 展开规则见 [INTEGRATION.md](INTEGRATION.md) 与仓库 `assets/schemas/`。
|
||||
`account get/list/pick-web` 和 `credential pick` 的 JSON 输出字段与上表一一对应。详见 [INTEGRATION.md](INTEGRATION.md) 与 `assets/schemas/`。
|
||||
|
||||
Reference in New Issue
Block a user