fix: add init-db CLI for host install/upgrade metadata seed
All checks were successful
技能自动化发布 / release (push) Successful in 6s
All checks were successful
技能自动化发布 / release (push) Successful in 6s
This commit is contained in:
29
SKILL.md
29
SKILL.md
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: 账号与凭据管理
|
||||
description: "通用账号 & 凭据 & 登录流程管理器。管理网页/RPA 账号、API Key/Token;支持 9 种登录策略(账密自动、扫码、2FA、SSO 等);提供加密本地存储(Fernet);提供 rpa_helpers 库供业务 skill 同进程调用 ensure_logged_in 完成多平台自动登录。涵盖物流、LLM、内容、开发、API 五类平台。"
|
||||
version: 2.0.12
|
||||
version: 2.0.13
|
||||
author: 深圳匠厂科技有限公司
|
||||
metadata:
|
||||
openclaw:
|
||||
@@ -27,19 +27,20 @@ allowed-tools:
|
||||
|
||||
## 何时使用本技能
|
||||
|
||||
1. **登记网页/RPA 账号**:`account add-web` — 平台 + 登录标识 + 自动生成 profile_dir;可选 `--auth-strategy` / `--session-persistent` / `--device-fingerprint`。
|
||||
2. **登记凭据(API Key / Token / 加密密码)**:`account add-secret` — `none` / `env` / `windows_credential` / `local_encrypted`。
|
||||
3. **查看/列出账号**:`account get/list` — JSON 输出;list 可按 `--login-id` / `--label` 筛选。
|
||||
4. **用人话定位账号**:`account resolve --login-id <手机号/用户名>` 或 `--label` / `--query`(不必先查数字 id)。
|
||||
5. **为 RPA 挑选账号**:`account pick-web` — 按平台/环境/角色,也可 `--login-id` / `--label`;业务首启推荐 `account ensure-web`(或 `pick-web --ensure`):无账号则自动 `add-web` 再返回。
|
||||
6. **获取 API Key(凭据表)**:`credential pick` — 默认隐藏 secret,`--reveal` 时才返回。
|
||||
7. **浏览器打开查看**:`account open <id>`(或兼容别名 `open <id>`)— 仅查看,不做站点侧登录判定。
|
||||
8. **管理 lease**:`lease release/list/cleanup` — 防止 RPA 并发。
|
||||
9. **初始化加密**:`account init-master-key` — 生成 Fernet master.key。
|
||||
10. **加密备份与迁移**:`account export-credentials --plaintext` / `account import-credentials` — 导出明文 JSON、在新环境重新加密写入。
|
||||
11. **按 lease 取明文密码**:`account get-credential <id> --reveal --lease-token <token>` — 结合 pick-web 返回的 lease 解密 `local_encrypted` 等路径。
|
||||
12. **业务 skill 同进程登录**:`from service.rpa_helpers import ensure_logged_in` — 详见 [`references/RPA_HELPERS.md`](references/RPA_HELPERS.md)。
|
||||
13. **有则用、无则建(网页账号)**:`account ensure-web --platform <p>` — 登记账号 ≠ 已登录;登录仍由业务技能 / `ensure_logged_in` 处理。
|
||||
1. **安装/升级后初始化库与数据管理元数据**:`init-db`(宿主会自动调用;也可手工执行)
|
||||
2. **登记网页/RPA 账号**:`account add-web` — 平台 + 登录标识 + 自动生成 profile_dir;可选 `--auth-strategy` / `--session-persistent` / `--device-fingerprint`。
|
||||
3. **登记凭据(API Key / Token / 加密密码)**:`account add-secret` — `none` / `env` / `windows_credential` / `local_encrypted`。
|
||||
4. **查看/列出账号**:`account get/list` — JSON 输出;list 可按 `--login-id` / `--label` 筛选。
|
||||
5. **用人话定位账号**:`account resolve --login-id <手机号/用户名>` 或 `--label` / `--query`(不必先查数字 id)。
|
||||
6. **为 RPA 挑选账号**:`account pick-web` — 按平台/环境/角色,也可 `--login-id` / `--label`;业务首启推荐 `account ensure-web`(或 `pick-web --ensure`):无账号则自动 `add-web` 再返回。
|
||||
7. **获取 API Key(凭据表)**:`credential pick` — 默认隐藏 secret,`--reveal` 时才返回。
|
||||
8. **浏览器打开查看**:`account open <id>`(或兼容别名 `open <id>`)— 仅查看,不做站点侧登录判定。
|
||||
9. **管理 lease**:`lease release/list/cleanup` — 防止 RPA 并发。
|
||||
10. **初始化加密**:`account init-master-key` — 生成 Fernet master.key。
|
||||
11. **加密备份与迁移**:`account export-credentials --plaintext` / `account import-credentials` — 导出明文 JSON、在新环境重新加密写入。
|
||||
12. **按 lease 取明文密码**:`account get-credential <id> --reveal --lease-token <token>` — 结合 pick-web 返回的 lease 解密 `local_encrypted` 等路径。
|
||||
13. **业务 skill 同进程登录**:`from service.rpa_helpers import ensure_logged_in` — 详见 [`references/RPA_HELPERS.md`](references/RPA_HELPERS.md)。
|
||||
14. **有则用、无则建(网页账号)**:`account ensure-web --platform <p>` — 登记账号 ≠ 已登录;登录仍由业务技能 / `ensure_logged_in` 处理。
|
||||
|
||||
## CLI 调用
|
||||
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
|
||||
## 子命令速查(按业务流程)
|
||||
|
||||
### 0. 运行时初始化(宿主标准)
|
||||
|
||||
| CLI | 说明 |
|
||||
|---|---|
|
||||
| `init-db` | 幂等初始化本地 SQLite、schema 迁移与数据管理中文元数据(`_jiangchang_*`)。成功输出 JSON:`{"ok":true,"skill":"account-manager","db_path":"..."}`。**匠厂安装/升级技能时会调用本命令**;业务命令内部也会触发同等 `init_db()`。 |
|
||||
|
||||
### A. 平台管理
|
||||
|
||||
| CLI | 说明 |
|
||||
|
||||
@@ -38,6 +38,7 @@ from service.account_service import (
|
||||
cmd_delete_by_platform,
|
||||
cmd_delete_by_platform_phone,
|
||||
cmd_get,
|
||||
cmd_init_db,
|
||||
cmd_lease_cleanup,
|
||||
cmd_lease_list,
|
||||
cmd_lease_release,
|
||||
@@ -60,6 +61,9 @@ from util.runtime_paths import _maybe_print_paths_debug_cli
|
||||
|
||||
_USAGE = """account-manager v2 — Credential & Browser Profile Manager
|
||||
|
||||
运行时 / 数据管理:
|
||||
init-db # 幂等初始化本地库与数据管理中文元数据(宿主安装/升级会调用)
|
||||
|
||||
平台管理:
|
||||
platform list [--domain logistics|llm|content]
|
||||
platform get <platform>
|
||||
@@ -217,6 +221,10 @@ def main() -> None:
|
||||
# Determine if first arg is a platform key (for legacy shorthand)
|
||||
plat_from_first = resolve_platform_key(cmd)
|
||||
|
||||
# ---- init-db(宿主 install/upgrade 标准入口)----
|
||||
if cmd == "init-db":
|
||||
sys.exit(cmd_init_db())
|
||||
|
||||
# ---- platform subcommand ----
|
||||
if cmd == "platform":
|
||||
if len(av) < 3:
|
||||
|
||||
@@ -39,7 +39,12 @@ from service.legacy_commands import (
|
||||
cmd_list,
|
||||
)
|
||||
from service.lease_commands import cmd_lease_cleanup, cmd_lease_list, cmd_lease_release
|
||||
from service.platform_commands import cmd_platform_ensure, cmd_platform_get, cmd_platform_list
|
||||
from service.platform_commands import (
|
||||
cmd_init_db,
|
||||
cmd_platform_ensure,
|
||||
cmd_platform_get,
|
||||
cmd_platform_list,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"PlatformCallerMeta",
|
||||
@@ -60,6 +65,7 @@ __all__ = [
|
||||
"cmd_delete_by_platform",
|
||||
"cmd_delete_by_platform_phone",
|
||||
"cmd_get",
|
||||
"cmd_init_db",
|
||||
"cmd_lease_cleanup",
|
||||
"cmd_lease_list",
|
||||
"cmd_lease_release",
|
||||
|
||||
@@ -6,8 +6,38 @@ from typing import Optional
|
||||
from db.accounts_repo import get_platform_from_db, list_platforms_from_db, upsert_platform
|
||||
from db.connection import get_conn, init_db
|
||||
from service._svc_common import _err_json, _ok_json, _resolve_or_fail, _say
|
||||
from util.constants import SKILL_SLUG
|
||||
from util.logging_config import get_skill_logger
|
||||
from util.platforms import DEFAULT_CAPABILITIES_JSON, is_valid_platform_key_format, seed_platforms
|
||||
from util.runtime_paths import get_db_path
|
||||
|
||||
|
||||
def cmd_init_db() -> int:
|
||||
"""幂等创建/迁移本地 SQLite 与数据管理元数据(宿主 install/upgrade 可调用)。"""
|
||||
log = get_skill_logger()
|
||||
log.info("cli_start subcommand=init_db")
|
||||
try:
|
||||
init_db()
|
||||
except Exception as exc: # noqa: BLE001 — CLI 边界,统一成可机读失败
|
||||
log.exception("init_db_failure")
|
||||
print(
|
||||
json.dumps(
|
||||
{"ok": False, "skill": SKILL_SLUG, "error": str(exc)},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
)
|
||||
return 1
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"ok": True,
|
||||
"skill": SKILL_SLUG,
|
||||
"db_path": get_db_path(),
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
def cmd_platform_list(domain: Optional[str] = None) -> None:
|
||||
|
||||
@@ -23,6 +23,7 @@ def test_usage_includes_all_account_subcommands():
|
||||
assert r.returncode == 1
|
||||
usage = r.stdout
|
||||
for cmd in (
|
||||
"init-db",
|
||||
"init-master-key",
|
||||
"export-credentials",
|
||||
"import-credentials",
|
||||
@@ -35,3 +36,44 @@ def test_usage_includes_all_account_subcommands():
|
||||
assert cmd in usage, f"USAGE 缺少 {cmd}"
|
||||
assert "--ensure" in usage
|
||||
assert "--login-id" in usage
|
||||
|
||||
|
||||
def test_init_db_cli_succeeds(fake_env):
|
||||
"""宿主调用的 init-db 必须成功并写入展示元数据。"""
|
||||
import json
|
||||
|
||||
env = {
|
||||
**os.environ,
|
||||
"PYTHONPATH": _scripts,
|
||||
"JIANGCHANG_DATA_ROOT": fake_env["data_root"],
|
||||
"JIANGCHANG_USER_ID": fake_env["user_id"],
|
||||
}
|
||||
r = subprocess.run(
|
||||
[sys.executable, "main.py", "init-db"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
env=env,
|
||||
cwd=_scripts,
|
||||
)
|
||||
assert r.returncode == 0, r.stdout + r.stderr
|
||||
payload = json.loads(r.stdout.strip().splitlines()[-1])
|
||||
assert payload.get("ok") is True
|
||||
assert payload.get("skill") == "account-manager"
|
||||
assert payload.get("db_path")
|
||||
|
||||
from db.connection import get_conn
|
||||
|
||||
conn = get_conn()
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT COUNT(*) FROM _jiangchang_columns")
|
||||
assert int(cur.fetchone()[0]) > 0
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT display_name FROM _jiangchang_columns
|
||||
WHERE table_name = 'accounts' AND column_name = 'role'
|
||||
"""
|
||||
)
|
||||
assert cur.fetchone()[0] == "角色"
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
Reference in New Issue
Block a user