@foxden-app/foxclaw 0.4.12 → 0.4.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +12 -2
- package/CHANGELOG.md +24 -0
- package/README.md +5 -3
- package/README_EN.md +5 -3
- package/dist/auth/cross_node_sync.d.ts +112 -0
- package/dist/auth/cross_node_sync.js +682 -0
- package/dist/auth/mirror.d.ts +37 -1
- package/dist/auth/mirror.js +136 -3
- package/dist/config.d.ts +10 -0
- package/dist/config.js +14 -0
- package/dist/controller/controller.d.ts +21 -0
- package/dist/controller/controller.js +200 -9
- package/dist/i18n.d.ts +42 -2
- package/dist/i18n.js +42 -2
- package/dist/main.js +192 -8
- package/dist/telegram/api.d.ts +6 -0
- package/dist/telegram/api.js +50 -0
- package/dist/telegram/gateway.d.ts +9 -0
- package/dist/telegram/gateway.js +33 -2
- package/dist/types.d.ts +16 -0
- package/dist/update.d.ts +2 -0
- package/dist/update.js +44 -6
- package/docs/user-manual.md +40 -4
- package/docs/zh/user-manual.md +40 -4
- package/package.json +1 -1
- package/skills/foxclaw/SKILL.md +4 -2
package/docs/user-manual.md
CHANGED
|
@@ -233,7 +233,7 @@ Later commands are sorted by recent usage. Plain text, photos, and files continu
|
|
|
233
233
|
- `/status`: FoxClaw, app-server, current thread binding, model, access, and Codex usage summary. In multi-bot mode it also lists every bot's connection, current auth, active turns, and the most recent auth mirror and service/Codex update outcomes. Local session, token, and visible-reply-throughput metrics use a background-generated historical snapshot instead of scanning large logs during the request; throughput is computed end-to-end for completed turns, excluding reasoning tokens while including waiting and tool execution time.
|
|
234
234
|
- `/account`: current Codex account.
|
|
235
235
|
- `/quota`: Codex usage and quota window.
|
|
236
|
-
- `/update`: upgrade FoxClaw, attempt to update an npm/pnpm-managed Codex CLI, run checks, and restart the service; it refuses while any Telegram bot runtime, an enabled Weixin default runtime, or an auth mirror write is busy, then reports
|
|
236
|
+
- `/update`: upgrade FoxClaw, attempt to update an npm/pnpm-managed Codex CLI, run checks, and restart the service; it refuses while any Telegram bot runtime, an enabled Weixin default runtime, or an auth mirror write is busy, then reports both FoxClaw and Codex CLI version changes through the initiating bot after restart.
|
|
237
237
|
|
|
238
238
|
### 3.3 `/config`, `/requirements`, `/provider`
|
|
239
239
|
|
|
@@ -391,7 +391,7 @@ If the login is cancelled or fails, FoxClaw tries to restore the previous auth t
|
|
|
391
391
|
|
|
392
392
|
`/auth` lists candidate accounts, the current account, and the auth directory. It also provides buttons for switching, disabling, login, and reload. In multi-bot mode the panel names the `@botname` runtime being managed, because private chats, groups, and topics on one bot share that bot's current auth. The panel shows 8 candidates per page and supports paging, `All / Enabled / Attention` filters, and `/auth list <keyword>` filename search for large local inventories. Panel text and buttons omit the repeated `auth.json_` prefix from standard candidate filenames, so `auth.json_personal` on disk renders as `personal`; files are not renamed, and search and commands still operate on the original candidates. `/auth use <n>` always uses the full-list candidate number, independent of panel paging.
|
|
393
393
|
|
|
394
|
-
|
|
394
|
+
Candidate rows are prefixed with observed `window:remaining-percent` values. For example, a Plus account may show `5h:20|7d:25`, while an account with one monthly window may show `30d:97`. Buttons use a compact two-number `primary|secondary` form such as `20|25`; unknown values render as `—`. The current auth quota is refreshed when the panel opens; other candidates are not switched merely to query quota. When multiple bot runtimes have recently used the same ChatGPT account, FoxClaw combines their cached quota snapshots by verified account ID, so one bot's `/auth` panel can show quota information learned by another bot without mixing different accounts.
|
|
395
395
|
|
|
396
396
|
Approximation:
|
|
397
397
|
|
|
@@ -404,8 +404,8 @@ Quota remaining: window:percent|auth
|
|
|
404
404
|
1. 5h:20|7d:25|personal * [Plus · ready · refreshed 2h ago]
|
|
405
405
|
2. --|team [quota unknown]
|
|
406
406
|
|
|
407
|
-
[✅
|
|
408
|
-
[🔐
|
|
407
|
+
[✅ 20|25|personal] [✅]
|
|
408
|
+
[🔐 —|—|team] [✅]
|
|
409
409
|
[☑️ All] [Enabled] [Attention]
|
|
410
410
|
[🛡️ Access] [🔑 Login]
|
|
411
411
|
[🔄 Reload auth]
|
|
@@ -417,6 +417,41 @@ The right-side `✅` / `⏸️` button controls whether the candidate participat
|
|
|
417
417
|
|
|
418
418
|
OpenAI does not publish a fixed ChatGPT refresh-token lifetime or an old-token replay grace period. Codex refreshes automatically when an access token approaches expiry; when it cannot parse the access-token `exp`, current Codex uses a `last_refresh` fallback of about 8 days. The panel labels candidates without a refresh record in that interval as `not recently refreshed`, but this is only a maintenance hint. It does not prove expiry and does not trigger bulk keepalive refreshes. Do not use `/auth refresh all` as a routine keepalive command.
|
|
419
419
|
|
|
420
|
+
### 6.4 Cross-Node Auth Sync
|
|
421
|
+
|
|
422
|
+
Cross-node auth sync is disabled by default. It is for multiple machines you control that share the same legally owned ChatGPT auth candidate pool, so a token refreshed by Codex on one node can be copied to the others. v1 uses Telegram Bot-to-Bot private messages to carry encrypted files, so it does not require public IPs or FRP. Enable Bot-to-Bot Communication Mode for the participating bots in BotFather first.
|
|
423
|
+
|
|
424
|
+
Example:
|
|
425
|
+
|
|
426
|
+
```dotenv
|
|
427
|
+
AUTH_SYNC_ENABLED=true
|
|
428
|
+
AUTH_SYNC_KEY=<shared key with at least 32 bytes>
|
|
429
|
+
AUTH_SYNC_PEERS=@other_node_bot,@third_node_bot
|
|
430
|
+
AUTH_SYNC_CLUSTER_ID=my-codex-auth-pool
|
|
431
|
+
# Optional; FoxClaw generates and persists a local node id when omitted.
|
|
432
|
+
AUTH_SYNC_NODE_ID=workstation-a
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Safety boundaries:
|
|
436
|
+
|
|
437
|
+
- Telegram only carries ciphertext. Auth contents, candidate names, account ids, and `last_refresh` live inside the AES-256-GCM encrypted payload.
|
|
438
|
+
- FoxClaw only accepts sync files from bots listed in `AUTH_SYNC_PEERS`; wrong key, cluster, nonce, or payload validation never writes files.
|
|
439
|
+
- Remote imports wait for global local idleness, temporarily switch to the candidate for app-server usage validation, and only then write the candidate.
|
|
440
|
+
- A same-name candidate known to belong to a different account id is never overwritten.
|
|
441
|
+
- Cross-node recovery only pulls an already-held valid peer copy. It does not automatically rotate refresh tokens; if no peer has a usable copy, it stops and asks you to maintain auth on one node manually.
|
|
442
|
+
|
|
443
|
+
Dual-active behavior:
|
|
444
|
+
|
|
445
|
+
- Push: after local login, Codex automatic refresh, or `/auth refresh all` succeeds and passes local mirror validation, the newer candidate is encrypted and pushed to peers.
|
|
446
|
+
- Pull: before auth switch or reload, FoxClaw first searches local runtimes for a newer same-account candidate; if none is found, it asks peers for a newer same-name same-account copy.
|
|
447
|
+
- Lease: `/auth refresh all confirm` requests a cross-node refresh lease before rotating tokens. Any busy, denying, or non-responsive peer blocks the refresh.
|
|
448
|
+
|
|
449
|
+
Commands:
|
|
450
|
+
|
|
451
|
+
- `/auth sync status`: show node id, peers, recent sends/receives/imports, pending imports, and the latest error.
|
|
452
|
+
- `/auth sync test`: send an encrypted ping to verify peer config, shared key, and Bot-to-Bot private messages.
|
|
453
|
+
- `/auth sync push all`: manually broadcast all locally verified candidates without refreshing tokens.
|
|
454
|
+
|
|
420
455
|
Equivalent commands:
|
|
421
456
|
|
|
422
457
|
- `/auth` or `/auth list [keyword]`: show candidates, optionally filtered by filename.
|
|
@@ -428,6 +463,7 @@ Equivalent commands:
|
|
|
428
463
|
- `/auth reload` or `/auth_reload`: restart app-server and reload the current `auth.json`.
|
|
429
464
|
- `/auth refresh all`: show the refresh-token rotation risk confirmation.
|
|
430
465
|
- `/auth refresh all confirm`: run Refresh all after accepting the token-rotation risk.
|
|
466
|
+
- `/auth sync status|test|push all`: inspect, test, or manually push cross-node auth sync.
|
|
431
467
|
|
|
432
468
|
If the requesting bot runtime has active turns, pending approvals, pending user inputs, or MCP elicitations, FoxClaw refuses manual auth switching to avoid changing accounts mid-request; another idle bot is unaffected.
|
|
433
469
|
|
package/docs/zh/user-manual.md
CHANGED
|
@@ -233,7 +233,7 @@ TG_ALLOWED_TOPIC_ID=42
|
|
|
233
233
|
- `/status`:查看 FoxClaw、app-server、当前绑定线程、模型、权限和 Codex 用量摘要。多 bot 模式还会列出所有 bot 的连接、当前 auth、活动 turn,以及最近一次 auth 镜像和服务/Codex 升级结果。本地 session/Token/可见答复吞吐使用后台生成的历史快照,避免状态查询现场扫描大量日志;答复吞吐按完成轮次端到端耗时计算,排除推理 token,但包含等待与工具执行时间。
|
|
234
234
|
- `/account`:查看当前 Codex 登录账号。
|
|
235
235
|
- `/quota`:查看 Codex 用量和额度窗口。
|
|
236
|
-
- `/update`:升级 FoxClaw,并尝试升级 npm/pnpm 安装的 Codex CLI,然后自检和重启服务;任意 Telegram bot、启用的微信默认 runtime 或 auth 镜像写入不空闲时都会拒绝执行,重启后通过发起命令的 bot
|
|
236
|
+
- `/update`:升级 FoxClaw,并尝试升级 npm/pnpm 安装的 Codex CLI,然后自检和重启服务;任意 Telegram bot、启用的微信默认 runtime 或 auth 镜像写入不空闲时都会拒绝执行,重启后通过发起命令的 bot 回报 FoxClaw 与 Codex CLI 的版本变化。
|
|
237
237
|
|
|
238
238
|
### 3.3 `/config`、`/requirements`、`/provider`
|
|
239
239
|
|
|
@@ -391,7 +391,7 @@ cp -L ~/.codex/auth.json ~/.codex/auth.json_personal
|
|
|
391
391
|
|
|
392
392
|
`/auth` 会列出候选账号、当前账号和 auth 目录,并提供按钮切换、禁用、登录和重载。多 bot 模式中,面板顶部还会显示当前正在管理的 `@botname`,因为该 bot 内的私聊、群聊和话题共享同一个当前 auth。面板每页显示 8 个候选,支持翻页、`全部 / 已启用 / 需关注` 筛选和 `/auth list <关键词>` 文件名搜索,适合管理较大的本地候选清单。面板文本和按钮会省略标准候选文件名中重复的 `auth.json_` 前缀,例如磁盘上的 `auth.json_personal` 显示为 `personal`;文件本身不会重命名,搜索和命令仍按原候选工作。命令 `/auth use <n>` 的编号始终对应完整候选列表,不会因为分页变化。
|
|
393
393
|
|
|
394
|
-
|
|
394
|
+
文本列表中每个候选名前的 `窗口:剩余百分比` 来自最近一次观察到的真实额度窗口,例如 Plus 账号可能显示 `5h:20|7d:25`,只有一个月度窗口的账号可能显示 `30d:97`。按钮为了适配窄屏,只显示两个剩余百分比数字,例如 `20|25`;未知值显示为 `—`。当前 auth 会在打开面板时刷新额度;其他候选不会为了查询额度被自动切换。如果多个 bot runtime 最近使用过同一个 ChatGPT 账号,FoxClaw 会按已验证的账号 ID 合并它们缓存到的额度快照,因此一个 bot 的 `/auth` 面板可以显示另一个 bot 掌握到的额度信息,同时不会把不同账号混在一起。
|
|
395
395
|
|
|
396
396
|
示意:
|
|
397
397
|
|
|
@@ -404,8 +404,8 @@ Candidates: 2
|
|
|
404
404
|
1. 5h:20|7d:25|personal * [Plus · 正常 · 刷新于 2小时前]
|
|
405
405
|
2. --|team [额度未知]
|
|
406
406
|
|
|
407
|
-
[✅
|
|
408
|
-
[🔐
|
|
407
|
+
[✅ 20|25|personal] [✅]
|
|
408
|
+
[🔐 —|—|team] [✅]
|
|
409
409
|
[☑️ 全部] [已启用] [需关注]
|
|
410
410
|
[🛡️ Access] [🔑 设备登录]
|
|
411
411
|
[🔄 Reload auth]
|
|
@@ -417,6 +417,41 @@ Candidates: 2
|
|
|
417
417
|
|
|
418
418
|
OpenAI 没有公开 ChatGPT refresh token 的固定有效期或旧 token 重放宽限期。Codex 会在 access token 临近到期时自动刷新;如果 access token 里无法解析 `exp`,Codex 当前使用 `last_refresh` 超过约 8 天作为兜底刷新条件。面板把超过 8 天没有刷新记录的候选标为“长期未刷新”,但这只是维护提醒,不代表 refresh token 已经过期,也不会触发批量保活刷新。不要把 `/auth refresh all` 当作日常保活命令。
|
|
419
419
|
|
|
420
|
+
### 6.4 跨节点 auth 同步
|
|
421
|
+
|
|
422
|
+
跨节点 auth 同步默认关闭。它适合你在多台自己控制的机器上使用同一组合法 ChatGPT 账号候选,并希望某台机器上 Codex 自动刷新出的新 token 能同步到其他机器。v1 使用 Telegram Bot-to-Bot 私聊传输加密文件,不需要公网 IP 或 FRP;需要先在 BotFather 为参与同步的 bot 开启 Bot-to-Bot Communication Mode。
|
|
423
|
+
|
|
424
|
+
配置示例:
|
|
425
|
+
|
|
426
|
+
```dotenv
|
|
427
|
+
AUTH_SYNC_ENABLED=true
|
|
428
|
+
AUTH_SYNC_KEY=<至少32字节的共享密钥>
|
|
429
|
+
AUTH_SYNC_PEERS=@other_node_bot,@third_node_bot
|
|
430
|
+
AUTH_SYNC_CLUSTER_ID=my-codex-auth-pool
|
|
431
|
+
# 可选;不填时 FoxClaw 会生成并持久化本机 node id
|
|
432
|
+
AUTH_SYNC_NODE_ID=workstation-a
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
安全边界:
|
|
436
|
+
|
|
437
|
+
- Telegram 只承载密文;auth 文件内容、候选名、account id、`last_refresh` 都在 AES-256-GCM 加密 payload 内。
|
|
438
|
+
- 只接收 `AUTH_SYNC_PEERS` 中 peer bot 发来的同步文件;密钥、cluster、nonce 或 payload 校验失败时不会写盘。
|
|
439
|
+
- 远端导入必须等本机全局空闲,再临时切换到待验证 auth、重启 app-server、读取 usage 验证成功后才写入候选。
|
|
440
|
+
- 同名候选如果已知属于不同 account id,永远拒绝覆盖。
|
|
441
|
+
- 跨节点恢复只拉取 peer 已持有的有效副本,不会自动触发 refresh token 轮换;找不到有效副本时会停止,提示你在一个节点手动维护授权。
|
|
442
|
+
|
|
443
|
+
双主动流程:
|
|
444
|
+
|
|
445
|
+
- push:本节点登录、Codex 自动刷新或 `/auth refresh all` 成功并通过本机镜像验证后,会主动把较新的候选加密推送给 peer。
|
|
446
|
+
- pull:本节点切换或重载 auth 前如果发现本地候选不是最新,会先查本机其他 runtime;仍找不到时,再向 peer 拉取同名同账号的较新副本。
|
|
447
|
+
- lease:执行会旋转 refresh token 的 `/auth refresh all confirm` 前,会向 peer 申请跨节点刷新锁。任一 peer 忙碌、拒绝或无响应都会阻止刷新。
|
|
448
|
+
|
|
449
|
+
命令:
|
|
450
|
+
|
|
451
|
+
- `/auth sync status`:查看 node id、peer、最近收发、最近导入、待导入和最近错误。
|
|
452
|
+
- `/auth sync test`:发送加密 ping,确认 peer、共享密钥和 Bot-to-Bot 私聊可用。
|
|
453
|
+
- `/auth sync push all`:手动广播当前节点已验证的全部候选,不刷新 token。
|
|
454
|
+
|
|
420
455
|
命令等价用法:
|
|
421
456
|
|
|
422
457
|
- `/auth` 或 `/auth list [关键词]`:查看候选,可按文件名搜索。
|
|
@@ -428,6 +463,7 @@ OpenAI 没有公开 ChatGPT refresh token 的固定有效期或旧 token 重放
|
|
|
428
463
|
- `/auth reload` 或 `/auth_reload`:重启 app-server,重新加载当前 `auth.json`。
|
|
429
464
|
- `/auth refresh all`:显示 refresh token 轮换风险确认。
|
|
430
465
|
- `/auth refresh all confirm`:接受 token 轮换风险后执行刷新全部。
|
|
466
|
+
- `/auth sync status|test|push all`:查看、测试或手动推送跨节点 auth 同步。
|
|
431
467
|
|
|
432
468
|
切换 auth 时,如果当前 bot runtime 还有活跃 turn、待审批、待用户输入或 MCP elicitation,FoxClaw 会先拒绝切换,避免中途换号破坏正在进行的请求;另一个空闲 bot 不受影响。
|
|
433
469
|
|
package/package.json
CHANGED
package/skills/foxclaw/SKILL.md
CHANGED
|
@@ -67,9 +67,11 @@ Telegram behavior:
|
|
|
67
67
|
- when `TG_BOT_TOKENS` contains multiple bots, one FoxClaw service starts independent Codex app-servers and auth selections per bot
|
|
68
68
|
- isolated Telegram runtimes use independent `CODEX_HOME` directories and file-backed credentials; they do not share Codex sessions
|
|
69
69
|
- refreshed ChatGPT candidates are mirrored only after online usage-endpoint validation; before auth switch or reload, a runtime restores any newer same-account credential found in another Codex home
|
|
70
|
-
- `/auth` paginates large candidate inventories at 8 rows per page, supports all/enabled/attention filters and filename search, renders
|
|
70
|
+
- `/auth` paginates large candidate inventories at 8 rows per page, supports all/enabled/attention filters and filename search, renders actual observed quota windows in text rows, uses compact two-number remaining quota labels on buttons, and omits the repeated `auth.json_` prefix from panel labels without renaming files
|
|
71
71
|
- treat the `/auth` `not recently refreshed` state as a maintenance hint only: OpenAI does not publish a fixed ChatGPT refresh-token lifetime or replay grace period, and FoxClaw must not add routine bulk keepalive refreshes
|
|
72
72
|
- `/auth refresh all` remains a command-only maintenance action, not a panel button; it requires explicit token-rotation risk confirmation, then force-refreshes every ChatGPT candidate through Codex `account/read refreshToken=true`, validates usage, mirrors successful candidates, and restores the original current auth while every runtime is globally idle
|
|
73
|
+
- optional cross-node auth sync uses Telegram Bot-to-Bot private messages with encrypted auth bundles; configure `AUTH_SYNC_ENABLED=true`, a shared `AUTH_SYNC_KEY`, and `AUTH_SYNC_PEERS`, then use `/auth sync status`, `/auth sync test`, and `/auth sync push all`; cross-node recovery pulls already-held valid peer copies and does not auto-refresh tokens
|
|
74
|
+
- when cross-node auth sync is enabled, `/auth refresh all confirm` must obtain a cross-node refresh lease before rotating refresh tokens; any busy, denying, or non-responsive peer blocks the refresh
|
|
73
75
|
- if `TG_BOT_TOKEN` is also set to one exact token from `TG_BOT_TOKENS`, that bot uses the default/shared-terminal runtime instead of an isolated Telegram home
|
|
74
76
|
- if Weixin is enabled alongside multiple Telegram bots, it remains on the default Codex runtime instead of borrowing a Telegram bot runtime
|
|
75
77
|
- in a group with multiple configured bots, address a bot by mention, reply, or suffixed command such as `/status@botname`
|
|
@@ -205,7 +207,7 @@ When the user says development is complete, asks to "收尾", or asks to push/pu
|
|
|
205
207
|
- For macOS launchd, use the launchd install/start path from this skill and verify with `node dist/main.js status`.
|
|
206
208
|
- Verify the running service reports the expected FoxClaw version in `status`.
|
|
207
209
|
- If `doctor` fails only because `DEFAULT_CWD` is missing, report that separately; do not treat it as evidence that the service update failed.
|
|
208
|
-
- `/update` now attempts to update globally npm/pnpm-managed Codex CLI installations and refuses to restart while any configured Telegram runtime, enabled Weixin default runtime, or auth mirror write is busy.
|
|
210
|
+
- `/update` now attempts to update globally npm/pnpm-managed Codex CLI installations, reports FoxClaw and Codex CLI version changes, and refuses to restart while any configured Telegram runtime, enabled Weixin default runtime, or auth mirror write is busy.
|
|
209
211
|
7. Publish to npm when requested:
|
|
210
212
|
- Prefer GitHub Actions trusted publishing via `.github/workflows/publish.yml`: bump and commit the package version, push `main`, then push a matching `v<version>` tag. The tag version must match `package.json`.
|
|
211
213
|
- Ensure the matching changelog section exists before pushing the version tag; the publish workflow uses it to create or update the GitHub Release.
|