@foxden-app/foxclaw 0.5.34 → 0.5.35
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 +10 -0
- package/dist/controller/controller.d.ts +1 -0
- package/dist/controller/controller.js +77 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
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.35 - 2026-06-17
|
|
6
|
+
|
|
7
|
+
### 中文
|
|
8
|
+
- `/status`、`/auth`、`/auth sync status/events/trace` 在 Telegram 上优先使用 RichMessage 展示,内部状态会自动整理成标题、表格、列表和可展开原文。
|
|
9
|
+
- 保留微信和 RichMessage 失败 fallback:微信继续走原文本通道,Telegram rich 发送失败时退回原 HTML/plain 内容,不影响按钮和回调。
|
|
10
|
+
|
|
11
|
+
### English
|
|
12
|
+
- `/status`, `/auth`, and `/auth sync status/events/trace` now prefer RichMessage on Telegram, rendering internal diagnostics as headings, tables, lists, and expandable plain-text details.
|
|
13
|
+
- Weixin and RichMessage failure fallbacks are preserved: Weixin keeps the previous text path, and Telegram falls back without breaking buttons or callbacks.
|
|
14
|
+
|
|
5
15
|
## 0.5.34 - 2026-06-17
|
|
6
16
|
|
|
7
17
|
### 中文
|
|
@@ -229,6 +229,7 @@ export declare class BridgeSessionCore {
|
|
|
229
229
|
private sendHtmlMessage;
|
|
230
230
|
private sendRichHtmlMessage;
|
|
231
231
|
private sendRichMarkdownMessage;
|
|
232
|
+
private sendRichInternalMessage;
|
|
232
233
|
private editMessage;
|
|
233
234
|
private editHtmlMessage;
|
|
234
235
|
private editRichHtmlMessage;
|
|
@@ -508,7 +508,7 @@ export class BridgeSessionCore {
|
|
|
508
508
|
}
|
|
509
509
|
lines.push(...codexUsageLines);
|
|
510
510
|
lines.push(...codexLocalUsageLines);
|
|
511
|
-
await this.
|
|
511
|
+
await this.sendRichInternalMessage(scopeId, '/status', lines.join('\n'));
|
|
512
512
|
return;
|
|
513
513
|
}
|
|
514
514
|
case 'account': {
|
|
@@ -3377,6 +3377,12 @@ export class BridgeSessionCore {
|
|
|
3377
3377
|
async sendRichMarkdownMessage(scopeId, text, inlineKeyboard) {
|
|
3378
3378
|
return this.sendRichHtmlMessage(scopeId, renderTelegramMarkdownRichHtml(text), escapeTelegramHtml(text), inlineKeyboard);
|
|
3379
3379
|
}
|
|
3380
|
+
async sendRichInternalMessage(scopeId, title, text, inlineKeyboard) {
|
|
3381
|
+
if (scopeId.startsWith(BRIDGE_SCOPE_WEIXIN_PREFIX)) {
|
|
3382
|
+
return this.sendMessage(scopeId, text, inlineKeyboard);
|
|
3383
|
+
}
|
|
3384
|
+
return this.sendRichHtmlMessage(scopeId, formatRichInternalMessage(title, text), escapeTelegramHtml(text), inlineKeyboard);
|
|
3385
|
+
}
|
|
3380
3386
|
async editMessage(scopeId, messageId, text, inlineKeyboard) {
|
|
3381
3387
|
await this.messaging.editPlain(scopeId, messageId, text, inlineKeyboard);
|
|
3382
3388
|
}
|
|
@@ -4572,17 +4578,20 @@ export class BridgeSessionCore {
|
|
|
4572
4578
|
await this.refreshCurrentCodexAuthQuota(state);
|
|
4573
4579
|
const record = createPendingAuthChoiceList(scopeId, state.candidates, listRequest);
|
|
4574
4580
|
this.pendingAuthChoiceLists.set(record.localId, record);
|
|
4575
|
-
const
|
|
4581
|
+
const authListMessage = renderAuthListMessage(locale, state, this.authDisplayBotLabel(), parseWeixinBridgeScope(scopeId) !== null, record);
|
|
4582
|
+
const messageId = await this.sendRichInternalMessage(scopeId, '/auth', authListMessage, authChoiceKeyboard(locale, record));
|
|
4576
4583
|
record.messageId = messageId;
|
|
4577
4584
|
}
|
|
4578
4585
|
async handleAuthSyncCommand(scopeId, locale, args) {
|
|
4579
4586
|
const action = args[0]?.toLowerCase() ?? 'status';
|
|
4580
4587
|
if (action === 'status') {
|
|
4581
|
-
|
|
4588
|
+
const message = formatAuthSyncStatus(locale, this.coordinator?.getAuthSyncStatus?.() ?? null, this.getRuntimeStatus().authProactiveRefresh ?? null);
|
|
4589
|
+
await this.sendRichInternalMessage(scopeId, '/auth sync status', message);
|
|
4582
4590
|
return;
|
|
4583
4591
|
}
|
|
4584
4592
|
if (action === 'events') {
|
|
4585
|
-
|
|
4593
|
+
const message = formatAuthSyncEvents(locale, this.coordinator?.getAuthSyncStatus?.() ?? null, args.slice(1).join(' ').trim() || null);
|
|
4594
|
+
await this.sendRichInternalMessage(scopeId, '/auth sync events', message);
|
|
4586
4595
|
return;
|
|
4587
4596
|
}
|
|
4588
4597
|
if (action === 'trace') {
|
|
@@ -4591,7 +4600,7 @@ export class BridgeSessionCore {
|
|
|
4591
4600
|
await this.sendMessage(scopeId, t(locale, 'auth_sync_trace_missing'));
|
|
4592
4601
|
return;
|
|
4593
4602
|
}
|
|
4594
|
-
await this.
|
|
4603
|
+
await this.sendRichInternalMessage(scopeId, '/auth sync trace', formatAuthSyncTrace(locale, this.coordinator?.getAuthSyncStatus?.() ?? null, requestId));
|
|
4595
4604
|
return;
|
|
4596
4605
|
}
|
|
4597
4606
|
if (action === 'test') {
|
|
@@ -8440,6 +8449,69 @@ function formatRichDemoFallbackMessage(locale) {
|
|
|
8440
8449
|
telegramPreCode('sendRichMessage({ rich_message: { html } })', 'typescript'),
|
|
8441
8450
|
].join('\n');
|
|
8442
8451
|
}
|
|
8452
|
+
function formatRichInternalMessage(title, text) {
|
|
8453
|
+
const sections = splitRichInternalSections(text);
|
|
8454
|
+
const body = sections.map(formatRichInternalSection).filter(Boolean).join('\n');
|
|
8455
|
+
return [
|
|
8456
|
+
`<h3>${escapeTelegramHtml(title)}</h3>`,
|
|
8457
|
+
body || `<p>${escapeTelegramHtml(text)}</p>`,
|
|
8458
|
+
telegramDetails('Plain text', telegramPreCode(text, 'text')),
|
|
8459
|
+
'<footer>FoxClaw · RichMessage</footer>',
|
|
8460
|
+
].join('\n');
|
|
8461
|
+
}
|
|
8462
|
+
function splitRichInternalSections(text) {
|
|
8463
|
+
const sections = [];
|
|
8464
|
+
let current = [];
|
|
8465
|
+
for (const rawLine of text.split('\n')) {
|
|
8466
|
+
const line = rawLine.trimEnd();
|
|
8467
|
+
if (!line.trim()) {
|
|
8468
|
+
if (current.length > 0) {
|
|
8469
|
+
sections.push(current);
|
|
8470
|
+
current = [];
|
|
8471
|
+
}
|
|
8472
|
+
continue;
|
|
8473
|
+
}
|
|
8474
|
+
current.push(line);
|
|
8475
|
+
}
|
|
8476
|
+
if (current.length > 0) {
|
|
8477
|
+
sections.push(current);
|
|
8478
|
+
}
|
|
8479
|
+
return sections;
|
|
8480
|
+
}
|
|
8481
|
+
function formatRichInternalSection(lines) {
|
|
8482
|
+
const rows = lines
|
|
8483
|
+
.map(parseRichInternalKeyValue)
|
|
8484
|
+
.filter((row) => row !== null);
|
|
8485
|
+
if (rows.length >= Math.max(2, Math.floor(lines.length * 0.6))) {
|
|
8486
|
+
return [
|
|
8487
|
+
'<table bordered striped>',
|
|
8488
|
+
...rows.map(([key, value]) => (`<tr><td>${escapeTelegramHtml(key)}</td><td>${formatRichInternalValue(value)}</td></tr>`)),
|
|
8489
|
+
'</table>',
|
|
8490
|
+
].join('\n');
|
|
8491
|
+
}
|
|
8492
|
+
return [
|
|
8493
|
+
'<ul>',
|
|
8494
|
+
...lines.map(line => `<li>${formatRichInternalValue(line.replace(/^\s*[-*]\s+/, '').replace(/^\s*\d+[.)]\s+/, ''))}</li>`),
|
|
8495
|
+
'</ul>',
|
|
8496
|
+
].join('\n');
|
|
8497
|
+
}
|
|
8498
|
+
function parseRichInternalKeyValue(line) {
|
|
8499
|
+
const separator = line.includes(':') ? ':' : ':';
|
|
8500
|
+
const index = line.indexOf(separator);
|
|
8501
|
+
if (index <= 0) {
|
|
8502
|
+
return null;
|
|
8503
|
+
}
|
|
8504
|
+
const key = line.slice(0, index).trim();
|
|
8505
|
+
const value = line.slice(index + separator.length).trim();
|
|
8506
|
+
if (!key || !value || key.length > 80) {
|
|
8507
|
+
return null;
|
|
8508
|
+
}
|
|
8509
|
+
return [key, value];
|
|
8510
|
+
}
|
|
8511
|
+
function formatRichInternalValue(value) {
|
|
8512
|
+
const escaped = escapeTelegramHtml(value);
|
|
8513
|
+
return escaped.replace(/`([^`]+)`/g, '<code>$1</code>');
|
|
8514
|
+
}
|
|
8443
8515
|
function clipRichMessageText(value, limit) {
|
|
8444
8516
|
if (value.length <= limit) {
|
|
8445
8517
|
return value;
|