@foxden-app/foxclaw 0.5.9 → 0.5.11
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/CHANGELOG.md +26 -0
- package/README.md +1 -0
- package/README_EN.md +1 -0
- package/dist/auth/mirror.d.ts +6 -0
- package/dist/auth/mirror.js +49 -0
- package/dist/controller/controller.d.ts +21 -2
- package/dist/controller/controller.js +516 -55
- package/dist/i18n.d.ts +36 -6
- package/dist/i18n.js +36 -6
- package/dist/main.js +22 -0
- package/dist/store/database.d.ts +25 -1
- package/dist/store/database.js +321 -0
- package/dist/telegram/gateway.d.ts +1 -0
- package/dist/telegram/gateway.js +1 -0
- package/dist/types.d.ts +53 -0
- package/dist/update.d.ts +3 -0
- package/dist/update.js +72 -3
- package/docs/devlogs//346/212/200/346/234/257/351/200/232/350/256/257/01./346/212/212 Codex /345/270/246/345/210/260/346/234/200/345/220/216/344/270/200/345/205/254/351/207/214/357/274/232FoxClaw /347/232/204 auth /347/224/237/345/221/275/345/221/250/346/234/237/344/270/216/350/267/250/350/212/202/347/202/271/345/220/214/346/255/245.md" +341 -0
- package/docs/release.md +102 -0
- package/docs/zh/release.md +102 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
All notable FoxClaw changes are listed here. Each release note is bilingual so GitHub Releases and the npm package are useful to both Chinese and English readers.
|
|
4
4
|
|
|
5
|
+
## 0.5.11 - 2026-06-08
|
|
6
|
+
|
|
7
|
+
### 中文
|
|
8
|
+
- `/auth` 面板的 `Bot runtime` 现在显示 Telegram bot id,例如 `@WuguiAI2_Bot (bot8949529424)`,便于和 `~/.foxclaw/codex/telegram/<botid>/home` 对应。
|
|
9
|
+
- `/auth` 面板新增“安全同步”按钮,并支持 `/auth sync safe`,可在全局空闲时安全打平本机多 bot auth,并把已校验的候选推送到跨节点 peer。
|
|
10
|
+
- 本机 auth mirror 新增全量安全同步路径:只传播通过既有在线校验的刷新候选,同时补齐 canonical 中已知、同账号且更新的 runtime 副本。
|
|
11
|
+
|
|
12
|
+
### English
|
|
13
|
+
- The `/auth` panel now shows the Telegram bot id in `Bot runtime`, for example `@WuguiAI2_Bot (bot8949529424)`, making it easy to match the runtime with `~/.foxclaw/codex/telegram/<botid>/home`.
|
|
14
|
+
- Added a Safe sync button to the `/auth` panel, plus `/auth sync safe`, to flatten same-node multi-bot auth while globally idle and push validated candidates to cross-node peers.
|
|
15
|
+
- Added a full safe-sync path for the local auth mirror: it only propagates candidates that pass the existing online validation and fills runtime copies from newer same-account canonical candidates.
|
|
16
|
+
|
|
17
|
+
## 0.5.10 - 2026-06-08
|
|
18
|
+
|
|
19
|
+
### 中文
|
|
20
|
+
- Telegram 输入队列改为 SQLite 持久化 FIFO,FoxClaw 重启后不再丢失排队中的 Codex 请求,并在 `/status` 中显示排队数量。
|
|
21
|
+
- Telegram 图片和文件会先进入附件暂存区,支持媒体组归并、下一条文字自动带附件发给 Codex,以及“分析 / 清空”按钮操作。
|
|
22
|
+
- 引导式 Plan 会话现在会持久化并在重启后恢复,减少长任务或确认流程被服务重启打断的风险。
|
|
23
|
+
- `/update` 完成回报会从已安装包的 `CHANGELOG.md` 读取当前版本更新内容,让 Telegram 里直接看到这次升级改了什么。
|
|
24
|
+
|
|
25
|
+
### English
|
|
26
|
+
- Replaced the in-memory Telegram prompt queue with a persisted SQLite FIFO so queued Codex requests survive FoxClaw restarts, and `/status` now reports queued turn count.
|
|
27
|
+
- Telegram photos and files are staged before dispatch, with media-group merging, next-message attachment consumption, and Analyze/Clear buttons.
|
|
28
|
+
- Guided Plan sessions are persisted and restored after restart, reducing interruption risk for long-running or confirmation-based flows.
|
|
29
|
+
- `/update` completion reports now read the installed package `CHANGELOG.md` entry for the target version so Telegram shows what changed in the upgrade.
|
|
30
|
+
|
|
5
31
|
## 0.5.9 - 2026-06-07
|
|
6
32
|
|
|
7
33
|
### 中文
|
package/README.md
CHANGED
|
@@ -39,6 +39,7 @@ FoxClaw(狸爪)的目标很直接:让你用手机控制本机的 Codex,
|
|
|
39
39
|
- 已经装好,想系统了解 `/help`、`/setup`、`/threads`、`/watch`、`/auth` 和账号轮转?看 [用户手册](./docs/zh/user-manual.md)。
|
|
40
40
|
- 想把同一组合法 ChatGPT auth 候选同步到多台机器?看 [跨节点 auth 同步配置指南](./docs/zh/cross-node-auth-sync.md)。
|
|
41
41
|
- 想了解每个版本改了什么?看 [更新日志](./CHANGELOG.md)。
|
|
42
|
+
- 维护者准备发版?看 [发布 runbook](./docs/zh/release.md)。
|
|
42
43
|
- Git、Node、`.env` 都玩得转?直接往下看快速设置。
|
|
43
44
|
- 卡住了?看 [故障排查](./docs/zh/troubleshooting.md)。
|
|
44
45
|
|
package/README_EN.md
CHANGED
|
@@ -39,6 +39,7 @@ FoxClaw is more than message forwarding. It provides Telegram panels for Codex w
|
|
|
39
39
|
- Already installed and want the full command guide for `/help`, `/setup`, `/threads`, `/watch`, `/auth`, and auth rotation? Read the [User Manual](./docs/user-manual.md).
|
|
40
40
|
- Want to sync the same legally owned ChatGPT auth candidate pool across multiple machines? Read the [Cross-Node Auth Sync Setup Guide](./docs/cross-node-auth-sync.md).
|
|
41
41
|
- Want to see what changed in each release? Read the [Changelog](./CHANGELOG.md).
|
|
42
|
+
- Maintaining a release? Use the [Release Runbook](./docs/release.md).
|
|
42
43
|
- Already comfortable with Git, Node, and `.env` files? Use the quick setup below.
|
|
43
44
|
- Something failed? Check [Troubleshooting](./docs/troubleshooting.md).
|
|
44
45
|
|
package/dist/auth/mirror.d.ts
CHANGED
|
@@ -52,6 +52,10 @@ export interface AuthMirrorSyncedEvent {
|
|
|
52
52
|
status: AuthMirrorStatus;
|
|
53
53
|
record: AuthMirrorCandidateRecord;
|
|
54
54
|
}
|
|
55
|
+
export interface AuthMirrorSyncAllResult {
|
|
56
|
+
synced: number;
|
|
57
|
+
skipped: number;
|
|
58
|
+
}
|
|
55
59
|
export interface AuthMirrorHooks {
|
|
56
60
|
onSynced?: (event: AuthMirrorSyncedEvent) => Promise<void> | void;
|
|
57
61
|
}
|
|
@@ -77,8 +81,10 @@ export declare class AuthCandidateMirror {
|
|
|
77
81
|
readRuntimeCandidate(runtimeId: string, candidateName: string): Promise<AuthMirrorCandidateRecord | null>;
|
|
78
82
|
listNewestCandidates(): Promise<AuthMirrorCandidateRecord[]>;
|
|
79
83
|
syncRuntimeCandidate(runtimeId: string, candidateName: string): Promise<boolean>;
|
|
84
|
+
syncAllRuntimeCandidates(): Promise<AuthMirrorSyncAllResult>;
|
|
80
85
|
recoverRuntimeCandidate(runtimeId: string, candidateName: string): Promise<AuthMirrorRecovery | null>;
|
|
81
86
|
private scan;
|
|
87
|
+
private distributeCanonicalCandidates;
|
|
82
88
|
importExternalCandidate(candidateName: string, raw: string, source: {
|
|
83
89
|
nodeId: string;
|
|
84
90
|
label?: string | null;
|
package/dist/auth/mirror.js
CHANGED
|
@@ -126,6 +126,28 @@ export class AuthCandidateMirror {
|
|
|
126
126
|
return false;
|
|
127
127
|
return this.withActivity(() => this.propagateValidatedCandidate(runtime, candidateName));
|
|
128
128
|
}
|
|
129
|
+
async syncAllRuntimeCandidates() {
|
|
130
|
+
return this.withActivity(async () => {
|
|
131
|
+
let synced = 0;
|
|
132
|
+
let skipped = 0;
|
|
133
|
+
for (const runtime of this.runtimes) {
|
|
134
|
+
const names = await listAuthCandidateNames(runtime.authDir);
|
|
135
|
+
for (const name of names) {
|
|
136
|
+
if (await this.propagateValidatedCandidate(runtime, name)) {
|
|
137
|
+
synced += 1;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
skipped += 1;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const distributed = await this.distributeCanonicalCandidates();
|
|
145
|
+
return {
|
|
146
|
+
synced: synced + distributed.synced,
|
|
147
|
+
skipped: skipped + distributed.skipped,
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
}
|
|
129
151
|
async recoverRuntimeCandidate(runtimeId, candidateName) {
|
|
130
152
|
if (!isAuthCandidateName(candidateName))
|
|
131
153
|
return null;
|
|
@@ -169,6 +191,33 @@ export class AuthCandidateMirror {
|
|
|
169
191
|
}
|
|
170
192
|
});
|
|
171
193
|
}
|
|
194
|
+
async distributeCanonicalCandidates() {
|
|
195
|
+
let synced = 0;
|
|
196
|
+
let skipped = 0;
|
|
197
|
+
for (const name of await listAuthCandidateNames(this.canonicalDir)) {
|
|
198
|
+
const canonical = await readChatGptAuthRecord(path.join(this.canonicalDir, name));
|
|
199
|
+
if (!canonical) {
|
|
200
|
+
skipped += this.runtimes.length;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
for (const runtime of this.runtimes) {
|
|
204
|
+
const destinationPath = path.join(runtime.authDir, name);
|
|
205
|
+
const destination = await readChatGptAuthRecord(destinationPath);
|
|
206
|
+
if (destination && destination.accountId !== canonical.accountId) {
|
|
207
|
+
skipped += 1;
|
|
208
|
+
this.logger.warn('auth.mirror.distribution_conflict', { runtimeId: runtime.id, name });
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (destination && destination.lastRefreshMs >= canonical.lastRefreshMs) {
|
|
212
|
+
skipped += 1;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
await atomicWrite(destinationPath, canonical.raw);
|
|
216
|
+
synced += 1;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return { synced, skipped };
|
|
220
|
+
}
|
|
172
221
|
async importExternalCandidate(candidateName, raw, source) {
|
|
173
222
|
if (!isAuthCandidateName(candidateName)) {
|
|
174
223
|
return { ok: false, imported: false, reason: 'invalid candidate name' };
|
|
@@ -19,6 +19,12 @@ export interface CoreCoordinator {
|
|
|
19
19
|
}>;
|
|
20
20
|
releaseAuthRefreshLease?: (leaseId: string | null) => Promise<void>;
|
|
21
21
|
getAuthSyncStatus?: () => RuntimeStatus['authSync'];
|
|
22
|
+
authSyncSafeAll?: () => Promise<{
|
|
23
|
+
localSynced: number;
|
|
24
|
+
localSkipped: number;
|
|
25
|
+
sent: number;
|
|
26
|
+
skipped: number;
|
|
27
|
+
}>;
|
|
22
28
|
authSyncPushAll?: () => Promise<{
|
|
23
29
|
sent: number;
|
|
24
30
|
skipped: number;
|
|
@@ -50,11 +56,9 @@ export declare class BridgeSessionCore {
|
|
|
50
56
|
private activeTurns;
|
|
51
57
|
private activeTurnsByTurnId;
|
|
52
58
|
private observedThreadWatchers;
|
|
53
|
-
private queuedPrompts;
|
|
54
59
|
private pendingTurnErrors;
|
|
55
60
|
private pendingUserInputs;
|
|
56
61
|
private pendingMcpElicitations;
|
|
57
|
-
private pendingPlanImplementations;
|
|
58
62
|
private pendingLoginsByScope;
|
|
59
63
|
private pendingLoginScopesById;
|
|
60
64
|
private pendingAuthAddsByLoginId;
|
|
@@ -159,6 +163,8 @@ export declare class BridgeSessionCore {
|
|
|
159
163
|
private maybeSendPlanImplementationPrompt;
|
|
160
164
|
private findPendingPlanImplementation;
|
|
161
165
|
private clearPlanImplementationPromptsForScope;
|
|
166
|
+
private pendingPlanImplementationFromSession;
|
|
167
|
+
private restoreGuidedPlanSessions;
|
|
162
168
|
private hasPendingUserInputForTurn;
|
|
163
169
|
private finalizeUserInputsForTurn;
|
|
164
170
|
private handlePlanImplementationCallback;
|
|
@@ -173,8 +179,15 @@ export declare class BridgeSessionCore {
|
|
|
173
179
|
private createBinding;
|
|
174
180
|
private startTurnWithRecovery;
|
|
175
181
|
private buildTurnInput;
|
|
182
|
+
private buildTurnInputFromStagedAttachments;
|
|
176
183
|
private resolveServiceTierForTurn;
|
|
177
184
|
private stageAttachments;
|
|
185
|
+
private handleTelegramAttachmentBatch;
|
|
186
|
+
private consumePendingAttachmentBatchWithText;
|
|
187
|
+
private handleAttachmentBatchCallback;
|
|
188
|
+
private consumePendingAttachmentBatch;
|
|
189
|
+
private startTurnFromPreparedAttachmentBatch;
|
|
190
|
+
private renderAttachmentBatchCard;
|
|
178
191
|
private registerActiveTurn;
|
|
179
192
|
private createActiveTurnState;
|
|
180
193
|
getCurrentAuthLabel(): Promise<string | null>;
|
|
@@ -247,7 +260,11 @@ export declare class BridgeSessionCore {
|
|
|
247
260
|
private handleActiveTurnInboundMessage;
|
|
248
261
|
private queuePromptAfterActiveTurn;
|
|
249
262
|
private steerActiveTurn;
|
|
263
|
+
private enqueuePreparedTurnInput;
|
|
264
|
+
private startBoundTurnFromQueuedInput;
|
|
250
265
|
private startQueuedPromptIfPresent;
|
|
266
|
+
private recoverQueuedTurns;
|
|
267
|
+
private markQueuedTurnCompleted;
|
|
251
268
|
private handleModeCommand;
|
|
252
269
|
private handleActiveTurnMessageModeCommand;
|
|
253
270
|
private handleGoalCommand;
|
|
@@ -263,6 +280,7 @@ export declare class BridgeSessionCore {
|
|
|
263
280
|
private clearSelfUpdateStatusPoll;
|
|
264
281
|
private pollSelfUpdateStatus;
|
|
265
282
|
private formatSelfUpdateResult;
|
|
283
|
+
private formatSelfUpdateReleaseNotes;
|
|
266
284
|
private formatCodexUpdateResult;
|
|
267
285
|
private scheduleProactiveAuthRefresh;
|
|
268
286
|
private clearProactiveAuthRefreshTimer;
|
|
@@ -271,6 +289,7 @@ export declare class BridgeSessionCore {
|
|
|
271
289
|
private notifyProactiveAuthRefresh;
|
|
272
290
|
private handleAuthCommand;
|
|
273
291
|
private handleAuthSyncCommand;
|
|
292
|
+
private runAuthSafeSyncAll;
|
|
274
293
|
private handleAuthRefreshAllCommand;
|
|
275
294
|
private handleAuthUseCommand;
|
|
276
295
|
private handleAuthToggleCommand;
|