@foxden-app/foxclaw 0.10.0 → 0.11.1
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 +9 -8
- package/CHANGELOG.md +43 -0
- package/dist/antigravity/adapter.d.ts +2 -1
- package/dist/antigravity/adapter.js +180 -42
- package/dist/antigravity/auth.d.ts +5 -0
- package/dist/antigravity/auth.js +37 -0
- package/dist/antigravity/client.js +8 -2
- package/dist/antigravity/controller.d.ts +10 -0
- package/dist/antigravity/controller.js +189 -28
- package/dist/antigravity/events.d.ts +1 -0
- package/dist/antigravity/events.js +29 -0
- package/dist/antigravity/runtime.d.ts +2 -0
- package/dist/antigravity/subagents.d.ts +66 -0
- package/dist/antigravity/subagents.js +459 -0
- package/dist/config.d.ts +3 -1
- package/dist/config.js +36 -29
- package/dist/controller/controller.d.ts +4 -0
- package/dist/controller/controller.js +71 -0
- package/dist/core/engine_spi.d.ts +1 -0
- package/dist/core/orchestrator.d.ts +6 -1
- package/dist/core/orchestrator.js +291 -139
- package/dist/main.js +346 -551
- package/dist/opencode/adapter.js +1 -0
- package/dist/opencode/controller.js +2 -2
- package/dist/store/database.d.ts +3 -0
- package/dist/store/database.js +33 -0
- package/dist/telegram/api.d.ts +1 -0
- package/dist/telegram/api.js +60 -12
- package/dist/telegram/bot_home.js +5 -4
- package/dist/types.d.ts +2 -0
- package/dist/update.js +17 -1
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@ import { formatQuotaResetTime, AntigravityAuthManager } from './auth.js';
|
|
|
10
10
|
import { AntigravityConversationManager, formatAge } from './conversations.js';
|
|
11
11
|
import { UnifiedChannelOrchestrator } from '../core/orchestrator.js';
|
|
12
12
|
import { AntigravityEngineAdapter } from './adapter.js';
|
|
13
|
+
import { AntigravitySubagentTracker } from './subagents.js';
|
|
13
14
|
import { CodexEngineAdapter } from '../codex_app/adapter.js';
|
|
14
15
|
import { OpencodeEngineAdapter } from '../opencode/adapter.js';
|
|
15
16
|
import { BridgeSessionCore } from '../controller/controller.js';
|
|
@@ -64,6 +65,7 @@ export class UnifiedBridgeCore {
|
|
|
64
65
|
codexCore;
|
|
65
66
|
opencodeAdapter;
|
|
66
67
|
defaultBackendId;
|
|
68
|
+
selfUpdater;
|
|
67
69
|
orchestrator;
|
|
68
70
|
watchers = new Map();
|
|
69
71
|
pendingAgyRenames = new Map();
|
|
@@ -80,6 +82,7 @@ export class UnifiedBridgeCore {
|
|
|
80
82
|
this.messaging = messaging ?? new TelegramMessagingPort(bot);
|
|
81
83
|
this.codexApp = options?.codexApp;
|
|
82
84
|
this.defaultBackendId = options?.defaultBackendId ?? 'antigravity';
|
|
85
|
+
this.selfUpdater = options?.selfUpdater;
|
|
83
86
|
this.codexCore = options?.codexCore;
|
|
84
87
|
if (!this.codexCore && options?.codexApp) {
|
|
85
88
|
try {
|
|
@@ -288,8 +291,12 @@ export class UnifiedBridgeCore {
|
|
|
288
291
|
catch (err) {
|
|
289
292
|
this.logger.warn('antigravity.restore_watchers_error', { error: String(err) });
|
|
290
293
|
}
|
|
294
|
+
if (this.selfUpdater) {
|
|
295
|
+
this.scheduleSelfUpdateStatusPoll(500);
|
|
296
|
+
}
|
|
291
297
|
}
|
|
292
298
|
async stop() {
|
|
299
|
+
this.clearSelfUpdateStatusPoll();
|
|
293
300
|
await this.orchestrator.stop();
|
|
294
301
|
this.auth.stopKeepAlive();
|
|
295
302
|
for (const [scopeId, watcher] of this.watchers.entries()) {
|
|
@@ -299,6 +306,73 @@ export class UnifiedBridgeCore {
|
|
|
299
306
|
this.watchers.delete(scopeId);
|
|
300
307
|
}
|
|
301
308
|
}
|
|
309
|
+
selfUpdatePollTimer = null;
|
|
310
|
+
scheduleSelfUpdateStatusPoll(delay = 1000) {
|
|
311
|
+
if (!this.selfUpdater || this.selfUpdatePollTimer) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
this.selfUpdatePollTimer = setTimeout(() => {
|
|
315
|
+
this.selfUpdatePollTimer = null;
|
|
316
|
+
void this.pollSelfUpdateStatus().catch((error) => {
|
|
317
|
+
this.logger.error('antigravity.self_update_poll_failed', { error: String(error) });
|
|
318
|
+
this.scheduleSelfUpdateStatusPoll();
|
|
319
|
+
});
|
|
320
|
+
}, delay);
|
|
321
|
+
this.selfUpdatePollTimer.unref?.();
|
|
322
|
+
}
|
|
323
|
+
clearSelfUpdateStatusPoll() {
|
|
324
|
+
if (!this.selfUpdatePollTimer)
|
|
325
|
+
return;
|
|
326
|
+
clearTimeout(this.selfUpdatePollTimer);
|
|
327
|
+
this.selfUpdatePollTimer = null;
|
|
328
|
+
}
|
|
329
|
+
ownsScope(scopeId) {
|
|
330
|
+
if (this.bot.identity) {
|
|
331
|
+
return scopeId.includes(`:${this.bot.identity}:`);
|
|
332
|
+
}
|
|
333
|
+
return !scopeId.includes(':bot');
|
|
334
|
+
}
|
|
335
|
+
async pollSelfUpdateStatus() {
|
|
336
|
+
const status = await this.selfUpdater?.readStatus();
|
|
337
|
+
if (!status)
|
|
338
|
+
return;
|
|
339
|
+
if (status.state === 'pending') {
|
|
340
|
+
this.scheduleSelfUpdateStatusPoll();
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (status.scopeId.startsWith('cluster:')) {
|
|
344
|
+
await this.selfUpdater?.clearStatus();
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
if (!this.ownsScope(status.scopeId)) {
|
|
348
|
+
this.scheduleSelfUpdateStatusPoll();
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const isZh = status.locale === 'zh';
|
|
352
|
+
if (status.state === 'succeeded') {
|
|
353
|
+
const notes = status.releaseNotes?.filter((n) => n.trim()) ?? [];
|
|
354
|
+
const title = isZh ? '🎉 FoxClaw 全链路升级完成' : '🎉 FoxClaw Update Completed';
|
|
355
|
+
const lines = [
|
|
356
|
+
`**${title}**`,
|
|
357
|
+
`• FoxClaw: \`${status.fromVersion}\` ➔ \`${status.toVersion ?? '0.11.0'}\``,
|
|
358
|
+
`• Codex CLI: \`${status.codexFromVersion ?? '0.157.1'}\` ➔ \`${status.codexToVersion ?? '0.159.2'}\``,
|
|
359
|
+
`• Antigravity CLI: \`${status.agyFromVersion ?? '1.2.14'}\` (最新)`,
|
|
360
|
+
];
|
|
361
|
+
if (notes.length > 0) {
|
|
362
|
+
lines.push('', isZh ? '**更新日志**:' : '**Release Notes**:');
|
|
363
|
+
for (const note of notes) {
|
|
364
|
+
lines.push(`• ${note}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
lines.push('', isZh ? '服务已自动重载并恢复就绪。' : 'Service reloaded and ready.');
|
|
368
|
+
await this.sendMessage(status.scopeId, lines.join('\n')).catch(() => { });
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
const errorMsg = status.error ?? (isZh ? '未知错误' : 'Unknown error');
|
|
372
|
+
await this.sendMessage(status.scopeId, `❌ **FoxClaw 升级失败**: ${errorMsg}`).catch(() => { });
|
|
373
|
+
}
|
|
374
|
+
await this.selfUpdater?.clearStatus();
|
|
375
|
+
}
|
|
302
376
|
getRuntimeStatus() {
|
|
303
377
|
const isConnected = this.codexApp && typeof this.codexApp.isConnected === 'function'
|
|
304
378
|
? this.codexApp.isConnected()
|
|
@@ -612,6 +686,25 @@ export class UnifiedBridgeCore {
|
|
|
612
686
|
const activeBackend = this.orchestrator.getBackendDescriptorForScope(scopeId);
|
|
613
687
|
const isCodex = activeBackend.engineType === 'codex';
|
|
614
688
|
if (cmd.toLowerCase() === 'update') {
|
|
689
|
+
if (this.selfUpdater) {
|
|
690
|
+
const status = await this.selfUpdater.readStatus();
|
|
691
|
+
if (status?.state === 'pending') {
|
|
692
|
+
await this.sendMessage(scopeId, locale === 'zh'
|
|
693
|
+
? '⏳ 升级任务已在后台执行中,请稍候…'
|
|
694
|
+
: '⏳ Self-update is already running, please wait…');
|
|
695
|
+
return true;
|
|
696
|
+
}
|
|
697
|
+
await this.sendMessage(scopeId, locale === 'zh'
|
|
698
|
+
? '🚀 正在启动全链路自升级(FoxClaw + Codex + Antigravity CLI),服务将自动更新并重载…'
|
|
699
|
+
: '🚀 Starting full-stack self-update (FoxClaw + Codex + Antigravity CLI). Service will restart automatically…');
|
|
700
|
+
try {
|
|
701
|
+
await this.selfUpdater.launch(scopeId, locale);
|
|
702
|
+
}
|
|
703
|
+
catch (err) {
|
|
704
|
+
await this.sendMessage(scopeId, `❌ 自升级启动失败: ${String(err)}`);
|
|
705
|
+
}
|
|
706
|
+
return true;
|
|
707
|
+
}
|
|
615
708
|
if (this.codexCore) {
|
|
616
709
|
if (_event) {
|
|
617
710
|
this.codexCore.dispatchInboundLikeTelegramText(_event);
|
|
@@ -858,7 +951,7 @@ export class UnifiedBridgeCore {
|
|
|
858
951
|
}
|
|
859
952
|
if (data.startsWith(AGY_MODEL_CALLBACK_PREFIX)) {
|
|
860
953
|
const model = data.slice(AGY_MODEL_CALLBACK_PREFIX.length);
|
|
861
|
-
this.store.
|
|
954
|
+
this.store.setChatModel(scopeId, model === 'default' ? null : model);
|
|
862
955
|
this.orchestrator.syncCurrentBackendSettings(scopeId);
|
|
863
956
|
await this.messaging.answerCallback(data, `Model: ${model}`);
|
|
864
957
|
await this.orchestrator.sendModelsMenu(scopeId, locale, messageId);
|
|
@@ -870,7 +963,7 @@ export class UnifiedBridgeCore {
|
|
|
870
963
|
if (effort !== 'high' && settings?.serviceTier === 'boost') {
|
|
871
964
|
this.store.setChatServiceTier(scopeId, null);
|
|
872
965
|
}
|
|
873
|
-
this.store.
|
|
966
|
+
this.store.setChatEffort(scopeId, effort);
|
|
874
967
|
this.orchestrator.syncCurrentBackendSettings(scopeId);
|
|
875
968
|
await this.messaging.answerCallback(data, `Effort: ${effort}`);
|
|
876
969
|
await this.sendEffortMenu(scopeId, '', locale, messageId);
|
|
@@ -1401,6 +1494,7 @@ export class UnifiedBridgeCore {
|
|
|
1401
1494
|
messageId: null,
|
|
1402
1495
|
currentToolLines: [],
|
|
1403
1496
|
lastContentPreview: '',
|
|
1497
|
+
subagentTracker: new AntigravitySubagentTracker(conv.conversationId, undefined, this.logger),
|
|
1404
1498
|
};
|
|
1405
1499
|
this.watchers.set(scopeId, watcher);
|
|
1406
1500
|
this.store.setWatchedThread(scopeId, conv.conversationId);
|
|
@@ -1472,9 +1566,45 @@ export class UnifiedBridgeCore {
|
|
|
1472
1566
|
}, 1500);
|
|
1473
1567
|
watcher.timer?.unref?.();
|
|
1474
1568
|
}
|
|
1569
|
+
getScopeLocale(scopeId) {
|
|
1570
|
+
return this.store.getChatSettings(scopeId)?.locale || 'zh';
|
|
1571
|
+
}
|
|
1572
|
+
async renderWatcherProgressUpdate(watcher) {
|
|
1573
|
+
const locale = this.getScopeLocale(watcher.scopeId);
|
|
1574
|
+
let messageText = `👁 <b>[Antigravity 观察中]</b>\n\n`;
|
|
1575
|
+
if (watcher.currentToolLines.length > 0) {
|
|
1576
|
+
const recent = watcher.currentToolLines.slice(-8);
|
|
1577
|
+
messageText += `<blockquote expandable>🛠️ <b>主会话工具 (${watcher.currentToolLines.length} 项)</b>\n${recent.join('\n')}</blockquote>\n\n`;
|
|
1578
|
+
}
|
|
1579
|
+
const subBlock = watcher.subagentTracker.renderTelegramBlock(locale);
|
|
1580
|
+
if (subBlock) {
|
|
1581
|
+
messageText += `${subBlock}\n\n`;
|
|
1582
|
+
}
|
|
1583
|
+
const activeSubSummary = watcher.subagentTracker.getActiveSummaryLine(locale);
|
|
1584
|
+
if (activeSubSummary) {
|
|
1585
|
+
messageText += `⏳ <b>${escapeTelegramHtml(activeSubSummary)}</b>`;
|
|
1586
|
+
}
|
|
1587
|
+
else if (watcher.lastContentPreview) {
|
|
1588
|
+
messageText += watcher.lastContentPreview.slice(-3000);
|
|
1589
|
+
}
|
|
1590
|
+
else {
|
|
1591
|
+
messageText += `⏳ 正在执行中…`;
|
|
1592
|
+
}
|
|
1593
|
+
if (watcher.messageId) {
|
|
1594
|
+
await this.editMessage(watcher.scopeId, watcher.messageId, messageText).catch(() => { });
|
|
1595
|
+
}
|
|
1596
|
+
else {
|
|
1597
|
+
watcher.messageId = await this.sendMessage(watcher.scopeId, messageText).catch(() => null);
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1475
1600
|
async pollWatcher(watcher) {
|
|
1476
1601
|
if (watcher.stopped)
|
|
1477
1602
|
return;
|
|
1603
|
+
const currentBinding = this.store.getBinding(watcher.scopeId);
|
|
1604
|
+
if (currentBinding?.threadId && currentBinding.threadId !== watcher.conversationId) {
|
|
1605
|
+
await this.unwatchConversation(watcher.scopeId, this.getScopeLocale(watcher.scopeId), false);
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1478
1608
|
if (this.orchestrator.hasActiveTurn(watcher.scopeId)) {
|
|
1479
1609
|
try {
|
|
1480
1610
|
if (fs.existsSync(watcher.transcriptPath)) {
|
|
@@ -1487,31 +1617,32 @@ export class UnifiedBridgeCore {
|
|
|
1487
1617
|
return;
|
|
1488
1618
|
}
|
|
1489
1619
|
try {
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1620
|
+
let hasParentLines = false;
|
|
1621
|
+
const lines = [];
|
|
1622
|
+
if (fs.existsSync(watcher.transcriptPath)) {
|
|
1623
|
+
const stats = fs.statSync(watcher.transcriptPath);
|
|
1624
|
+
if (stats.size < watcher.fileOffset) {
|
|
1625
|
+
watcher.fileOffset = 0;
|
|
1626
|
+
watcher.remainder = '';
|
|
1627
|
+
}
|
|
1628
|
+
else if (stats.size > watcher.fileOffset) {
|
|
1629
|
+
const bytesToRead = stats.size - watcher.fileOffset;
|
|
1630
|
+
const buffer = Buffer.alloc(bytesToRead);
|
|
1631
|
+
const fd = fs.openSync(watcher.transcriptPath, 'r');
|
|
1632
|
+
try {
|
|
1633
|
+
fs.readSync(fd, buffer, 0, bytesToRead, watcher.fileOffset);
|
|
1634
|
+
}
|
|
1635
|
+
finally {
|
|
1636
|
+
fs.closeSync(fd);
|
|
1637
|
+
}
|
|
1638
|
+
watcher.fileOffset = stats.size;
|
|
1639
|
+
const chunk = watcher.remainder + buffer.toString('utf8');
|
|
1640
|
+
const splitLines = chunk.split('\n');
|
|
1641
|
+
watcher.remainder = splitLines.pop() ?? '';
|
|
1642
|
+
lines.push(...splitLines);
|
|
1643
|
+
hasParentLines = splitLines.length > 0;
|
|
1644
|
+
}
|
|
1510
1645
|
}
|
|
1511
|
-
watcher.fileOffset = stats.size;
|
|
1512
|
-
const chunk = watcher.remainder + buffer.toString('utf8');
|
|
1513
|
-
const lines = chunk.split('\n');
|
|
1514
|
-
watcher.remainder = lines.pop() ?? '';
|
|
1515
1646
|
for (const line of lines) {
|
|
1516
1647
|
const trimmed = line.trim();
|
|
1517
1648
|
if (!trimmed)
|
|
@@ -1525,12 +1656,19 @@ export class UnifiedBridgeCore {
|
|
|
1525
1656
|
}
|
|
1526
1657
|
await this.handleWatcherTranscriptEntry(watcher, entry);
|
|
1527
1658
|
}
|
|
1659
|
+
// Poll subagents
|
|
1660
|
+
const subResult = await watcher.subagentTracker.poll();
|
|
1661
|
+
// If subagents had new tool events or status updates while the parent has no new lines
|
|
1662
|
+
if (subResult.hasUpdates && !hasParentLines) {
|
|
1663
|
+
await this.renderWatcherProgressUpdate(watcher);
|
|
1664
|
+
}
|
|
1528
1665
|
}
|
|
1529
1666
|
catch (err) {
|
|
1530
1667
|
this.logger.debug('antigravity.poll_watcher_error', { error: String(err) });
|
|
1531
1668
|
}
|
|
1532
1669
|
}
|
|
1533
1670
|
async handleWatcherTranscriptEntry(watcher, entry) {
|
|
1671
|
+
const locale = this.getScopeLocale(watcher.scopeId);
|
|
1534
1672
|
if (entry.type === 'USER_INPUT') {
|
|
1535
1673
|
const text = typeof entry.content === 'string' ? entry.content : '';
|
|
1536
1674
|
const preview = text.length > 300 ? text.slice(0, 300) + '…' : text;
|
|
@@ -1540,6 +1678,16 @@ export class UnifiedBridgeCore {
|
|
|
1540
1678
|
watcher.lastContentPreview = '';
|
|
1541
1679
|
return;
|
|
1542
1680
|
}
|
|
1681
|
+
if (entry.type === 'GENERIC') {
|
|
1682
|
+
const content = typeof entry.content === 'string' ? entry.content : '';
|
|
1683
|
+
if (content.includes('Created the following subagents') || content.includes('conversationId')) {
|
|
1684
|
+
const subResult = await watcher.subagentTracker.poll();
|
|
1685
|
+
if (subResult.hasUpdates) {
|
|
1686
|
+
await this.renderWatcherProgressUpdate(watcher);
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1543
1691
|
if (entry.type === 'PLANNER_RESPONSE') {
|
|
1544
1692
|
let hasUpdate = false;
|
|
1545
1693
|
if (Array.isArray(entry.tool_calls) && entry.tool_calls.length > 0) {
|
|
@@ -1573,6 +1721,10 @@ export class UnifiedBridgeCore {
|
|
|
1573
1721
|
: '';
|
|
1574
1722
|
progressFinal += `\n\n<blockquote expandable>🛠️ <b>已调用工具 (${watcher.currentToolLines.length} 项)</b>\n${recent.join('\n')}${hiddenNote}</blockquote>`;
|
|
1575
1723
|
}
|
|
1724
|
+
const subBlock = watcher.subagentTracker.renderTelegramBlock(locale);
|
|
1725
|
+
if (subBlock) {
|
|
1726
|
+
progressFinal += `\n\n<blockquote expandable>${subBlock}</blockquote>`;
|
|
1727
|
+
}
|
|
1576
1728
|
await this.editMessage(watcher.scopeId, watcher.messageId, progressFinal).catch(() => { });
|
|
1577
1729
|
}
|
|
1578
1730
|
const chunks = chunkTelegramMessage(entry.content.trim(), 4000);
|
|
@@ -1582,6 +1734,7 @@ export class UnifiedBridgeCore {
|
|
|
1582
1734
|
watcher.messageId = null;
|
|
1583
1735
|
watcher.currentToolLines = [];
|
|
1584
1736
|
watcher.lastContentPreview = '';
|
|
1737
|
+
watcher.subagentTracker = new AntigravitySubagentTracker(watcher.conversationId, undefined, this.logger);
|
|
1585
1738
|
return;
|
|
1586
1739
|
}
|
|
1587
1740
|
if (entry.content) {
|
|
@@ -1594,7 +1747,15 @@ export class UnifiedBridgeCore {
|
|
|
1594
1747
|
const recent = watcher.currentToolLines.slice(-8);
|
|
1595
1748
|
messageText += `<blockquote expandable>🛠️ <b>已调用工具 (${watcher.currentToolLines.length} 项)</b>\n${recent.join('\n')}</blockquote>\n\n`;
|
|
1596
1749
|
}
|
|
1597
|
-
|
|
1750
|
+
const subBlock = watcher.subagentTracker.renderTelegramBlock(locale);
|
|
1751
|
+
if (subBlock) {
|
|
1752
|
+
messageText += `${subBlock}\n\n`;
|
|
1753
|
+
}
|
|
1754
|
+
const activeSubSummary = watcher.subagentTracker.getActiveSummaryLine(locale);
|
|
1755
|
+
if (activeSubSummary) {
|
|
1756
|
+
messageText += `⏳ <b>${escapeTelegramHtml(activeSubSummary)}</b>`;
|
|
1757
|
+
}
|
|
1758
|
+
else if (watcher.lastContentPreview) {
|
|
1598
1759
|
messageText += watcher.lastContentPreview.slice(-3000);
|
|
1599
1760
|
}
|
|
1600
1761
|
else {
|
|
@@ -1877,7 +2038,7 @@ export class UnifiedBridgeCore {
|
|
|
1877
2038
|
if (target !== 'high' && isBoost) {
|
|
1878
2039
|
this.store.setChatServiceTier(scopeId, null);
|
|
1879
2040
|
}
|
|
1880
|
-
this.store.
|
|
2041
|
+
this.store.setChatEffort(scopeId, target);
|
|
1881
2042
|
this.orchestrator.syncCurrentBackendSettings(scopeId);
|
|
1882
2043
|
await this.sendMessage(scopeId, locale === 'zh' ? `✅ 思考深度已切换为: \`${target}\`` : `✅ Effort switched to: \`${target}\``);
|
|
1883
2044
|
return;
|
|
@@ -90,6 +90,7 @@ export type AntigravityBridgeEvent = AgInitBridgeEvent | AgTextEvent | AgToolEve
|
|
|
90
90
|
export declare function isVerificationError(errorMessage: string): boolean;
|
|
91
91
|
export declare function isQuotaOrAuthError(errorMessage: string): boolean;
|
|
92
92
|
export declare function isCapacityOrUnavailableError(errorMessage: string): boolean;
|
|
93
|
+
export declare function isTransientNetworkError(errorMessage: string): boolean;
|
|
93
94
|
/**
|
|
94
95
|
* Normalizes raw NDJSON stream events from `agy` into clean bridge events.
|
|
95
96
|
*/
|
|
@@ -28,6 +28,35 @@ export function isCapacityOrUnavailableError(errorMessage) {
|
|
|
28
28
|
lower.includes('overloaded') ||
|
|
29
29
|
lower.includes('high load'));
|
|
30
30
|
}
|
|
31
|
+
export function isTransientNetworkError(errorMessage) {
|
|
32
|
+
if (!errorMessage)
|
|
33
|
+
return false;
|
|
34
|
+
const lower = errorMessage.toLowerCase();
|
|
35
|
+
return (lower.includes('client network socket disconnected') ||
|
|
36
|
+
lower.includes('connection timed out') ||
|
|
37
|
+
lower.includes('timed out') ||
|
|
38
|
+
lower.includes('timeout') ||
|
|
39
|
+
lower.includes('econnreset') ||
|
|
40
|
+
lower.includes('etimedout') ||
|
|
41
|
+
lower.includes('enotfound') ||
|
|
42
|
+
lower.includes('eai_again') ||
|
|
43
|
+
lower.includes('econnrefused') ||
|
|
44
|
+
lower.includes('socket hang up') ||
|
|
45
|
+
lower.includes('network socket disconnected') ||
|
|
46
|
+
lower.includes('retryable') ||
|
|
47
|
+
lower.includes('grpc') ||
|
|
48
|
+
lower.includes('network error') ||
|
|
49
|
+
lower.includes('fetch failed') ||
|
|
50
|
+
lower.includes('502 bad gateway') ||
|
|
51
|
+
lower.includes('504 gateway timeout') ||
|
|
52
|
+
lower.includes('proxy error') ||
|
|
53
|
+
lower.includes('read tcp') ||
|
|
54
|
+
lower.includes('und_err_') ||
|
|
55
|
+
lower.includes('broken pipe') ||
|
|
56
|
+
lower.includes('ehostunreach') ||
|
|
57
|
+
lower.includes('enetunreach') ||
|
|
58
|
+
lower.includes('exited unexpectedly'));
|
|
59
|
+
}
|
|
31
60
|
/**
|
|
32
61
|
* Normalizes raw NDJSON stream events from `agy` into clean bridge events.
|
|
33
62
|
*/
|
|
@@ -6,6 +6,7 @@ import { AntigravityAppClient } from './client.js';
|
|
|
6
6
|
import { AntigravityAuthManager } from './auth.js';
|
|
7
7
|
import { AntigravityBridgeCore } from './controller.js';
|
|
8
8
|
import type { CodexAppClient } from '../codex_app/client.js';
|
|
9
|
+
import type { SelfUpdateRuntime } from '../update.js';
|
|
9
10
|
export interface AntigravityRuntimeOptions {
|
|
10
11
|
botToken?: string | undefined;
|
|
11
12
|
botId?: string | undefined;
|
|
@@ -16,6 +17,7 @@ export interface AntigravityRuntimeOptions {
|
|
|
16
17
|
codexApp?: CodexAppClient | undefined;
|
|
17
18
|
app?: AntigravityAppClient | undefined;
|
|
18
19
|
auth?: AntigravityAuthManager | undefined;
|
|
20
|
+
selfUpdater?: SelfUpdateRuntime | undefined;
|
|
19
21
|
}
|
|
20
22
|
/** Keeps the optional Antigravity Telegram bot lifecycle decoupled from Codex and OpenCode runtimes. */
|
|
21
23
|
export declare class AntigravityTelegramRuntime {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Logger } from '../logger.js';
|
|
2
|
+
import type { AppLocale } from '../types.js';
|
|
3
|
+
export interface SubagentProgressInfo {
|
|
4
|
+
conversationId: string;
|
|
5
|
+
parentConversationId: string;
|
|
6
|
+
agentName: string;
|
|
7
|
+
role?: string | undefined;
|
|
8
|
+
typeName?: string | undefined;
|
|
9
|
+
status: 'running' | 'idle' | 'done';
|
|
10
|
+
stepIndex: number;
|
|
11
|
+
toolCount: number;
|
|
12
|
+
currentTool: string | null;
|
|
13
|
+
recentTools: string[];
|
|
14
|
+
lastAction: string;
|
|
15
|
+
lastContentPreview: string;
|
|
16
|
+
updatedAt: number;
|
|
17
|
+
completedAt?: number | undefined;
|
|
18
|
+
}
|
|
19
|
+
export interface SubagentToolEvent {
|
|
20
|
+
subagentName: string;
|
|
21
|
+
conversationId: string;
|
|
22
|
+
toolName: string;
|
|
23
|
+
args?: Record<string, unknown> | string | undefined;
|
|
24
|
+
summary?: string | undefined;
|
|
25
|
+
status: 'running' | 'completed' | 'failed';
|
|
26
|
+
stepIndex?: number | undefined;
|
|
27
|
+
}
|
|
28
|
+
export interface SubagentPollResult {
|
|
29
|
+
subagents: SubagentProgressInfo[];
|
|
30
|
+
activeSubagents: SubagentProgressInfo[];
|
|
31
|
+
newToolEvents: SubagentToolEvent[];
|
|
32
|
+
hasUpdates: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function cleanParameterValue(val: unknown): string;
|
|
35
|
+
export declare function extractSubagentToolSummary(name: string, parameters?: Record<string, unknown> | string | undefined): string | undefined;
|
|
36
|
+
export declare function escapeTelegramHtml(value: string): string;
|
|
37
|
+
export declare class AntigravitySubagentTracker {
|
|
38
|
+
private readonly baseDir;
|
|
39
|
+
private readonly dbPath;
|
|
40
|
+
private readonly logger;
|
|
41
|
+
private readonly parentConversationId;
|
|
42
|
+
private readonly subagents;
|
|
43
|
+
private parentTranscriptOffset;
|
|
44
|
+
private parentTranscriptRemainder;
|
|
45
|
+
constructor(parentConversationId: string, baseDir?: string, logger?: Logger);
|
|
46
|
+
get trackedCount(): number;
|
|
47
|
+
getSubagents(): SubagentProgressInfo[];
|
|
48
|
+
getActiveSubagents(): SubagentProgressInfo[];
|
|
49
|
+
getTranscriptPath(conversationId: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Discovers and polls active subagents for new steps, tool calls, and completion status.
|
|
52
|
+
*/
|
|
53
|
+
poll(): Promise<SubagentPollResult>;
|
|
54
|
+
private discoverSubagentsFromDb;
|
|
55
|
+
private discoverSubagentsFromParentTranscript;
|
|
56
|
+
private extractSubagentsFromTranscriptEntry;
|
|
57
|
+
private pollSubagentTranscript;
|
|
58
|
+
/**
|
|
59
|
+
* Renders subagent progress for Telegram messages (watch mode or stream preview).
|
|
60
|
+
*/
|
|
61
|
+
renderTelegramBlock(locale?: AppLocale): string;
|
|
62
|
+
/**
|
|
63
|
+
* One-line summary of what active subagents are currently doing.
|
|
64
|
+
*/
|
|
65
|
+
getActiveSummaryLine(locale?: AppLocale): string | null;
|
|
66
|
+
}
|