# psa-tools **Repository Path**: andershsueh/psa-tools ## Basic Information - **Project Name**: psa-tools - **Description**: 从天璇 Cowork 本地数据库提取 PSA LLM API key / baseUrl / 模型列表 (供团队同事绕开公司 harness, 接 Claude Code / Aider / Cline) - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-21 - **Last Updated**: 2026-08-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # psa-tools 从天璇 Cowork (PSA 内部 cowork 工具) 本地数据库提取 LLM API 配置。 **目的**: 让团队同事不用卡在天璇 Cowork 这个"半成品"harness 上, 各自从自己电脑里的本地数据提取 API key + baseUrl + 模型列表, 接 Claude Code / Aider / Cline / Cursor 等更好的 harness 写代码。 **重要**: 这工具只从**你本地**数据库读你自己账号的 key。每个同事跑一次只能拿到自己电脑里的配置 (走的是各自登录态)。 --- ## 一行命令 ```bash git clone git@gitee.com:andershsueh/psa-tools.git ~/psa-tools \ && cd ~/psa-tools \ && ./install.sh \ && python3 extract_keys.py ``` --- ## 一键安装 ```bash # macOS / Linux ./install.sh # 或手动 npm install # Node 后端 (天璇 Cowork 自带 Node 22 即可) pip install sqlcipher3-binary # Python 后端 (可选, 性能更好) ``` 依赖: - Node 18+ (天璇 Cowork 是 Electron 39, 自带 Node 22, 装 app 就有) - Python 3.9+ (可选, 装 sqlcipher3-binary 让解密更快) - 没有 sqlcipher3-binary 时, 工具自动 fallback 到 Node 后端 --- ## 用法 ### 默认: 输出所有 enabled provider (json, summary 格式) ```bash python3 extract_keys.py ``` 输出: ```json [ { "name": "PSA API", "apiKey": "sk-OzbtDaWxBKajOuaoqRxEH5SmEYITH5vmsXeAPjS40OU4Shxb", "baseUrl": "https://ipsapro.isoftstone.com/thor/v1", "models": [ "text-embedding-ada-002", "Bge-Reranker-Large", "gpt-image-2", "deepseek-v4-pro", "hy3", "l-deepseek-v4-flash (本地)", "deepseek-v4-flash", "Qwen3-Embedding-4B" ] }, { "name": "Anthropic", "apiKey": "sk-LIXemdwK1tf6JUBfVbdEcA...", "baseUrl": "https://litellm.int-fp.com", "models": ["GLM-4.6V-Flash"] } ] ``` (实际可能有 3 个 enabled provider — PSA API / Anthropic (GLM) / MiniMax 套餐 (M3)) ### Shell 导出 (直接 source) ```bash python3 extract_keys.py --format env > psa-env.sh chmod 600 psa-env.sh source psa-env.sh # 现在 $OPENAI_API_BASE / $OPENAI_API_KEY 已设好 (用第一个 enabled provider) # 直接跑 aider --model openai/deepseek-v4-flash ``` ### 表格预览 (快速看) ```bash python3 extract_keys.py --format table ``` ``` NAME TYPE BASE URL MODELS API KEY ---------------------------------------------------------------------------------------------------------------------------------- PSA API openai-chat https://ipsapro.isoftstone.com/thor/v1 8 sk-OzbtDaWxB... Anthropic anthropic https://litellm.int-fp.com 1 sk-LIXemdwK1... MiniMax(套餐) anthropic https://api.minimaxi.com/anthropic 1 sk-cp-pp_OkG... ``` ### 只看某个 provider ```bash python3 extract_keys.py --provider "PSA API" ``` ### 也看 disabled (看内置全部 provider 列表, 19 个) ```bash python3 extract_keys.py --include-disabled --format table ``` ### 也输出 OIDC JWT 摘要 (web SSO, 跟 LLM 无关, 但有时排查要) ```bash python3 extract_keys.py --include-oidc ``` ### 详细 json (每模型带字段, 默认 summary 模式太简洁) ```bash python3 extract_keys.py --detailed ``` ### 写文件 (自动 chmod 600) ```bash python3 extract_keys.py --output keys.json python3 extract_keys.py --provider "PSA API" --output psa-api.json ``` ### 强制用某个后端 ```bash python3 extract_keys.py --backend node # 强制 Node python3 extract_keys.py --backend python # 强制 Python (要装 sqlcipher3-binary) python3 extract_keys.py --backend auto # 默认, Python 优先, 失败 fallback Node ``` ### 自定义 psa 目录 ```bash python3 extract_keys.py --psa-home /path/to/.psacowork ``` --- ## 跟 Claude Code 配 ### 方案 A: OpenAI 协议直挂 (Aider / Cline / Cursor) ```bash eval "$(python3 extract_keys.py --provider 'PSA API' --format env | grep OPENAI)" # 现在 $OPENAI_API_BASE / $OPENAI_API_KEY 已设 aider --model openai/deepseek-v4-flash ``` ### 方案 B: Claude Code + LiteLLM 包装 (推荐, Claude Code 不动) `litellm.yaml`: ```yaml model_list: - model_name: psa-deepseek litellm_params: model: openai/deepseek-v4-flash api_base: https://ipsapro.isoftstone.com/thor/v1 api_key: sk-OzbtDaWxBKajOuaoqRxEH5SmEYITH5vmsXeAPjS40OU4Shxb # 关 thinking (默认开会让 content 空) extra_body: thinking: type: disabled ``` 启动: ```bash litellm --config litellm.yaml --port 4000 # 另一个终端: export ANTHROPIC_BASE_URL=http://localhost:4000 export ANTHROPIC_AUTH_TOKEN=anything claude ``` --- ## 关键事实 (以防忘记) - **baseUrl**: `https://ipsapro.isoftstone.com/thor/v1` (公网可达, 腾讯云) - **apiKey**: OpenAI 风格 `sk-...`, **不是 OIDC JWT** - **端点路径**: `${baseUrl}/chat/completions` (`/v1` 已含在 baseUrl, **不要再加**) - **thinking 默认开**: 响应里 `content` 经常空, `reasoning_content` 满, 必须 `extra_body.thinking.type=disabled` 关 - **不要用 OIDC JWT 调 LLM**: 会 401 "Invalid token" (实测) - **不要拼 `/v1/chat/completions`**: 会 404 (实测) --- ## 它怎么工作的 天璇 Cowork 把 LLM provider 配置加密存在 `~/.psacowork/data.db` 里: ``` ~/.psacowork/data.db (SQLCipher 整库加密) └─ config_store 表 └─ key='psacowork-providers' 行 └─ payload 字段 (AES-256-GCM 加密, base64 编码) └─ 解密后是 providers 列表 (json) ``` 加密是**装饰性**的: 1. **SQLCipher 整库密码** = `psacowork@sqlite#2025!FieldEncryption$Key` (硬编码在 `app.asar/out/main/index.js` line 5010) 2. **字段加密** = AES-256-GCM, key = scrypt(SQLCipher 密码, salt=`psacowork/sqlite-field-encryption/v1`, 32 bytes) 3. **加密格式**: `psaenc:v1:::` 任何装了天璇 Cowork 的人都能解自己机器上的数据库 — 密码就在 app.asar 里。 --- ## 安全 / 合规提示 - 工具只读本地数据, 不联网 - 输出包含 apiKey, 默认 chmod 600, 用完请删除 - 团队里分发前请先确认公司内部政策是否允许 - 不在公开仓库 / IM 群发 apiKey 截图 --- ## 已知限制 - macOS / Linux 验证过 (Node 22 wheel 全平台有) - Windows: `npm install better-sqlite3-multiple-ciphers` 即可 (有 prebuilt) - 加密算法依赖天璇 Cowork 客户端版本 — 1.4.9 验证过, 其他版本字段格式可能变 - 如果天璇 Cowork 升级改了加密, dump_db.js 也要跟着改 ## 调研笔记 详细背景见 `/Users/xueyuheng/时事新闻讨论1/investigation.md` (17.8 KB) --- ## License MIT — see [LICENSE](./LICENSE). 提 Issue / PR 自由发挥, 但**不要 commit 任何真实 api_key**(即使是你自己的) — `info.json` 永远不入仓。 ## Contributing 最实用的贡献方式: 1. 试一下你的天璇 Cowork,跑 `python3 extract_keys.py --format table` 2. 如果有 bug / 缺特性 / 想加新 provider, 提 [Issue](https://gitee.com/andershsueh/psa-tools/issues) 3. 改完跑 `python3 extract_keys.py --detailed --include-disabled` 确认输出正常, 然后开 PR ## 致谢 - 天璇 Cowork 团队 — 写出了让我有动力反向工程的 PSA 后端 - [Karpathy Wiki 知识库方法论](https://x.com/karpathy) — 调查笔记用了这套思路 - 所有提 Issue / PR 的同事