@foxden-app/foxclaw 0.12.0 → 0.13.0

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.
Files changed (124) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/antigravity/account_ui.d.ts +34 -0
  3. package/dist/antigravity/account_ui.js +354 -0
  4. package/dist/antigravity/adapter.js +1 -1
  5. package/dist/antigravity/auth.d.ts +4 -1
  6. package/dist/antigravity/auth.js +17 -5
  7. package/dist/antigravity/controller.d.ts +3 -108
  8. package/dist/antigravity/controller.js +2 -2129
  9. package/dist/antigravity/conversation_ui.d.ts +56 -0
  10. package/dist/antigravity/conversation_ui.js +509 -0
  11. package/dist/antigravity/ui_callbacks.d.ts +6 -0
  12. package/dist/antigravity/ui_callbacks.js +6 -0
  13. package/dist/bridge/unified_bridge.d.ts +114 -0
  14. package/dist/bridge/unified_bridge.js +1343 -0
  15. package/dist/channels/bridge_messaging_router.d.ts +8 -4
  16. package/dist/channels/bridge_messaging_router.js +15 -4
  17. package/dist/channels/telegram/telegram_messaging_port.d.ts +16 -0
  18. package/dist/channels/telegram/telegram_messaging_port.js +22 -2
  19. package/dist/channels/text_actions.d.ts +14 -0
  20. package/dist/channels/text_actions.js +48 -0
  21. package/dist/channels/weixin/weixin_channel_adapter.d.ts +3 -4
  22. package/dist/channels/weixin/weixin_channel_adapter.js +2 -2
  23. package/dist/channels/weixin/weixin_messaging_port.d.ts +16 -1
  24. package/dist/channels/weixin/weixin_messaging_port.js +34 -7
  25. package/dist/codex_app/activity.d.ts +62 -0
  26. package/dist/codex_app/activity.js +418 -0
  27. package/dist/codex_app/adapter.d.ts +2 -2
  28. package/dist/codex_app/adapter.js +55 -25
  29. package/dist/codex_app/backend_ui.d.ts +4 -0
  30. package/dist/codex_app/backend_ui.js +48 -0
  31. package/dist/codex_app/client.js +0 -12
  32. package/dist/controller/access.d.ts +1 -11
  33. package/dist/controller/access.js +1 -33
  34. package/dist/controller/activity.d.ts +1 -62
  35. package/dist/controller/activity.js +2 -418
  36. package/dist/controller/auth_errors.d.ts +11 -0
  37. package/dist/controller/auth_errors.js +124 -0
  38. package/dist/controller/auth_files.d.ts +13 -0
  39. package/dist/controller/auth_files.js +156 -0
  40. package/dist/controller/auth_presentation.d.ts +77 -0
  41. package/dist/controller/auth_presentation.js +697 -0
  42. package/dist/controller/auth_quota_service.d.ts +27 -0
  43. package/dist/controller/auth_quota_service.js +151 -0
  44. package/dist/controller/controller.d.ts +30 -56
  45. package/dist/controller/controller.js +181 -3497
  46. package/dist/controller/interactions.d.ts +74 -0
  47. package/dist/controller/interactions.js +560 -0
  48. package/dist/controller/local_usage_service.d.ts +19 -0
  49. package/dist/controller/local_usage_service.js +62 -0
  50. package/dist/controller/native_panel_service.d.ts +55 -0
  51. package/dist/controller/native_panel_service.js +214 -0
  52. package/dist/controller/native_panels.d.ts +61 -0
  53. package/dist/controller/native_panels.js +784 -0
  54. package/dist/controller/shared_helpers.d.ts +53 -0
  55. package/dist/controller/shared_helpers.js +399 -0
  56. package/dist/controller/state_types.d.ts +390 -0
  57. package/dist/controller/state_types.js +82 -0
  58. package/dist/controller/turn_rendering.d.ts +22 -0
  59. package/dist/controller/turn_rendering.js +288 -0
  60. package/dist/core/access.d.ts +11 -0
  61. package/dist/core/access.js +33 -0
  62. package/dist/core/attachment_files.d.ts +13 -0
  63. package/dist/core/attachment_files.js +180 -0
  64. package/dist/core/attachment_types.d.ts +22 -0
  65. package/dist/core/attachment_types.js +1 -0
  66. package/dist/core/attachments.d.ts +5 -3
  67. package/dist/core/attachments.js +2 -2
  68. package/dist/core/backend_registry.d.ts +22 -0
  69. package/dist/core/backend_registry.js +50 -0
  70. package/dist/core/backend_ui.d.ts +28 -0
  71. package/dist/core/backend_ui.js +1 -0
  72. package/dist/core/channel_events.d.ts +48 -0
  73. package/dist/core/channel_events.js +1 -0
  74. package/dist/core/channel_port.d.ts +52 -8
  75. package/dist/core/engine_spi.d.ts +19 -4
  76. package/dist/core/listener_scope.d.ts +11 -0
  77. package/dist/core/listener_scope.js +10 -0
  78. package/dist/core/message_text.d.ts +2 -0
  79. package/dist/core/message_text.js +28 -0
  80. package/dist/core/network_errors.d.ts +1 -0
  81. package/dist/core/network_errors.js +23 -0
  82. package/dist/core/orchestrator.d.ts +53 -24
  83. package/dist/core/orchestrator.js +855 -507
  84. package/dist/core/queued_engine_input.d.ts +12 -0
  85. package/dist/core/queued_engine_input.js +16 -0
  86. package/dist/core/runtime_supervisor.d.ts +19 -0
  87. package/dist/core/runtime_supervisor.js +45 -0
  88. package/dist/core/scope_operations.d.ts +7 -0
  89. package/dist/core/scope_operations.js +19 -0
  90. package/dist/core/stream_preview.js +21 -9
  91. package/dist/dsh/adapter.js +18 -5
  92. package/dist/dsh/backend.d.ts +7 -0
  93. package/dist/dsh/backend.js +21 -0
  94. package/dist/dsh/runtime.d.ts +0 -1
  95. package/dist/dsh/runtime.js +4 -13
  96. package/dist/dsh/ui.d.ts +8 -8
  97. package/dist/dsh/ui.js +1 -1
  98. package/dist/main.js +55 -43
  99. package/dist/opencode/adapter.js +28 -9
  100. package/dist/opencode/controller.js +1 -1
  101. package/dist/store/channel_inbox.d.ts +14 -0
  102. package/dist/store/channel_inbox.js +21 -0
  103. package/dist/store/database.d.ts +7 -3
  104. package/dist/store/database.js +7 -2
  105. package/dist/store/task_journal.d.ts +32 -0
  106. package/dist/store/task_journal.js +70 -0
  107. package/dist/telegram/api.d.ts +2 -2
  108. package/dist/telegram/api.js +10 -28
  109. package/dist/telegram/gateway.d.ts +13 -27
  110. package/dist/telegram/gateway.js +86 -43
  111. package/dist/telegram/media.d.ts +2 -34
  112. package/dist/telegram/media.js +1 -180
  113. package/dist/telegram/task_preview.d.ts +13 -0
  114. package/dist/telegram/task_preview.js +92 -0
  115. package/dist/telegram/task_result.d.ts +2 -0
  116. package/dist/telegram/task_result.js +12 -0
  117. package/dist/telegram/text.d.ts +1 -1
  118. package/dist/telegram/text.js +2 -27
  119. package/dist/types.d.ts +1 -1
  120. package/docs/release.md +13 -11
  121. package/docs/zh/architecture-review.md +106 -0
  122. package/docs/zh/release.md +13 -11
  123. package/docs/zh/telegram-experience.md +40 -0
  124. package/package.json +5 -4
@@ -0,0 +1,27 @@
1
+ import { CodexAuthQuotaSnapshot, CodexAuthCandidate, CodexAuthState, CodexAuthQuotaIdentity } from './state_types.js';
2
+ import { type ChatGptAuthMetadata } from '../auth/mirror.js';
3
+ import type { CodexRateLimitSnapshot } from '../types.js';
4
+ import type { AppConfig } from '../config.js';
5
+ import type { BridgeStore } from '../store/database.js';
6
+ import type { Logger } from '../logger.js';
7
+ import type { CodexAppClient } from '../codex_app/client.js';
8
+ export declare class CodexAuthQuotaService {
9
+ private readonly config;
10
+ private readonly store;
11
+ private readonly logger;
12
+ private readonly app;
13
+ private readonly syncCodexAuthCandidate;
14
+ private authQuotaSnapshots;
15
+ private authQuotaSnapshotsLoaded;
16
+ constructor(config: AppConfig, store: BridgeStore, logger: Logger, app: Pick<CodexAppClient, 'readAccountRateLimits'>, syncCodexAuthCandidate: (name: string) => Promise<void>);
17
+ refreshCurrentCodexAuthQuota(state: CodexAuthState): Promise<void>;
18
+ applySharedCodexAuthQuotaSnapshots(state: CodexAuthState, candidateQuotaIdentities?: Map<string, CodexAuthQuotaIdentity>): Promise<void>;
19
+ recordCodexAuthQuotaSnapshot(candidateName: string, metadata: ChatGptAuthMetadata | null, snapshot: CodexRateLimitSnapshot): Promise<void>;
20
+ readCodexAuthCandidateQuotaIdentities(candidates: CodexAuthCandidate[]): Promise<Map<string, CodexAuthQuotaIdentity>>;
21
+ codexAuthQuotaSnapshotMatchesIdentity(snapshot: CodexAuthQuotaSnapshot | null, identity: CodexAuthQuotaIdentity | null): snapshot is CodexAuthQuotaSnapshot;
22
+ readCodexAuthQuotaSnapshots(): Promise<Record<string, CodexAuthQuotaSnapshot>>;
23
+ writeCodexAuthQuotaSnapshots(): Promise<void>;
24
+ codexAuthQuotaSnapshotPath(): string;
25
+ private authRuntimeId;
26
+ private runtimeSnapshotFilename;
27
+ }
@@ -0,0 +1,151 @@
1
+ import { CODEX_AUTH_QUOTA_SNAPSHOT_FILENAME, } from './state_types.js';
2
+ import { chatGptAuthMetadataMatchesCandidateName, readChatGptAuthRecord, readChatGptAuthMetadata, } from '../auth/mirror.js';
3
+ import { selectCodexRateLimitSnapshot, authQuotaSnapshotFromRateLimit, isFiniteCodexAuthQuotaSnapshotRecord, mergeCodexAuthQuotaSnapshots, codexAuthQuotaSnapshotFromRecord, isCodexAuthQuotaSnapshot, normalizeCodexAuthQuotaSnapshot, } from './auth_presentation.js';
4
+ import { formatUserError } from './shared_helpers.js';
5
+ import { isCodexApiKeyAuthCandidate } from './auth_files.js';
6
+ import { readAccessTokenExpiresAtMs } from '../auth/cross_node_sync.js';
7
+ import fs from 'node:fs/promises';
8
+ import path from 'node:path';
9
+ export class CodexAuthQuotaService {
10
+ config;
11
+ store;
12
+ logger;
13
+ app;
14
+ syncCodexAuthCandidate;
15
+ authQuotaSnapshots = {};
16
+ authQuotaSnapshotsLoaded = false;
17
+ constructor(config, store, logger, app, syncCodexAuthCandidate) {
18
+ this.config = config;
19
+ this.store = store;
20
+ this.logger = logger;
21
+ this.app = app;
22
+ this.syncCodexAuthCandidate = syncCodexAuthCandidate;
23
+ }
24
+ async refreshCurrentCodexAuthQuota(state) {
25
+ const candidate = state.candidates.find(entry => entry.isCurrent);
26
+ if (!candidate) {
27
+ return;
28
+ }
29
+ if (candidate.state === 'needs_repair') {
30
+ return;
31
+ }
32
+ try {
33
+ const metadata = await readChatGptAuthMetadata(candidate.path);
34
+ if (!metadata || !chatGptAuthMetadataMatchesCandidateName(candidate.name, metadata)) {
35
+ return;
36
+ }
37
+ const snapshot = selectCodexRateLimitSnapshot(await this.app.readAccountRateLimits());
38
+ if (!snapshot) {
39
+ return;
40
+ }
41
+ const quota = authQuotaSnapshotFromRateLimit(snapshot, metadata?.accountId ?? null, metadata?.quotaIdentityId ?? null);
42
+ candidate.quota = quota;
43
+ await this.recordCodexAuthQuotaSnapshot(candidate.name, metadata, snapshot);
44
+ await this.applySharedCodexAuthQuotaSnapshots(state);
45
+ await this.syncCodexAuthCandidate(candidate.name);
46
+ }
47
+ catch (error) {
48
+ this.logger.warn('codex.auth_quota_refresh_failed', { error: formatUserError(error) });
49
+ }
50
+ }
51
+ async applySharedCodexAuthQuotaSnapshots(state, candidateQuotaIdentities) {
52
+ const quotaIdentities = candidateQuotaIdentities ?? await this.readCodexAuthCandidateQuotaIdentities(state.candidates);
53
+ const uniqueQuotaIdentityIds = [...new Set([...quotaIdentities.values()].map(identity => identity.quotaIdentityId))];
54
+ if (uniqueQuotaIdentityIds.length === 0) {
55
+ return;
56
+ }
57
+ const snapshotsByIdentity = new Map();
58
+ for (const record of this.store.listCodexAuthQuotaSnapshots(uniqueQuotaIdentityIds)) {
59
+ if (!isFiniteCodexAuthQuotaSnapshotRecord(record)) {
60
+ continue;
61
+ }
62
+ snapshotsByIdentity.set(record.quotaIdentityId, mergeCodexAuthQuotaSnapshots(snapshotsByIdentity.get(record.quotaIdentityId) ?? null, codexAuthQuotaSnapshotFromRecord(record)));
63
+ }
64
+ for (const candidate of state.candidates) {
65
+ const quotaIdentity = quotaIdentities.get(candidate.name);
66
+ if (!quotaIdentity) {
67
+ continue;
68
+ }
69
+ candidate.quota = mergeCodexAuthQuotaSnapshots(candidate.quota, snapshotsByIdentity.get(quotaIdentity.quotaIdentityId) ?? null);
70
+ }
71
+ }
72
+ async recordCodexAuthQuotaSnapshot(candidateName, metadata, snapshot) {
73
+ const quota = authQuotaSnapshotFromRateLimit(snapshot, metadata?.accountId ?? null, metadata?.quotaIdentityId ?? null);
74
+ this.authQuotaSnapshots[candidateName] = quota;
75
+ if (metadata) {
76
+ this.store.setCodexAuthQuotaSnapshot(this.authRuntimeId(), candidateName, metadata.accountId, metadata.quotaIdentityId, quota);
77
+ }
78
+ await this.writeCodexAuthQuotaSnapshots();
79
+ }
80
+ async readCodexAuthCandidateQuotaIdentities(candidates) {
81
+ const entries = await Promise.all(candidates.map(async (candidate) => {
82
+ const record = await readChatGptAuthRecord(candidate.path);
83
+ const metadataMatchesName = record
84
+ ? chatGptAuthMetadataMatchesCandidateName(candidate.name, record)
85
+ : false;
86
+ candidate.credentialKind = record && metadataMatchesName
87
+ ? 'chatgpt'
88
+ : await isCodexApiKeyAuthCandidate(candidate.path)
89
+ ? 'api-key'
90
+ : 'invalid';
91
+ candidate.credentialLastRefreshMs = record && metadataMatchesName ? record.lastRefreshMs : null;
92
+ candidate.credentialExpiresAtMs = record && metadataMatchesName ? readAccessTokenExpiresAtMs(record.raw) : null;
93
+ return [candidate.name, record && metadataMatchesName ? {
94
+ accountId: record.accountId,
95
+ quotaIdentityId: record.quotaIdentityId,
96
+ } : null];
97
+ }));
98
+ const quotaIdentities = new Map();
99
+ for (const [name, quotaIdentity] of entries) {
100
+ if (quotaIdentity) {
101
+ quotaIdentities.set(name, quotaIdentity);
102
+ }
103
+ }
104
+ return quotaIdentities;
105
+ }
106
+ codexAuthQuotaSnapshotMatchesIdentity(snapshot, identity) {
107
+ if (!snapshot) {
108
+ return false;
109
+ }
110
+ const snapshotIdentityId = snapshot.quotaIdentityId ?? snapshot.accountId ?? null;
111
+ if (!snapshotIdentityId) {
112
+ return identity === null;
113
+ }
114
+ return identity !== null && snapshotIdentityId === identity.quotaIdentityId;
115
+ }
116
+ async readCodexAuthQuotaSnapshots() {
117
+ if (this.authQuotaSnapshotsLoaded) {
118
+ return this.authQuotaSnapshots;
119
+ }
120
+ this.authQuotaSnapshotsLoaded = true;
121
+ try {
122
+ const parsed = JSON.parse(await fs.readFile(this.codexAuthQuotaSnapshotPath(), 'utf8'));
123
+ if (parsed && typeof parsed === 'object') {
124
+ for (const [name, value] of Object.entries(parsed)) {
125
+ if (isCodexAuthQuotaSnapshot(value)) {
126
+ this.authQuotaSnapshots[name] = normalizeCodexAuthQuotaSnapshot(value);
127
+ }
128
+ }
129
+ }
130
+ }
131
+ catch {
132
+ // A missing or invalid historical cache should not block the auth panel.
133
+ }
134
+ return this.authQuotaSnapshots;
135
+ }
136
+ async writeCodexAuthQuotaSnapshots() {
137
+ const snapshotPath = this.codexAuthQuotaSnapshotPath();
138
+ await fs.mkdir(path.dirname(snapshotPath), { recursive: true });
139
+ const temporaryPath = `${snapshotPath}.${process.pid}.tmp`;
140
+ await fs.writeFile(temporaryPath, `${JSON.stringify(this.authQuotaSnapshots, null, 2)}\n`, {
141
+ encoding: 'utf8',
142
+ mode: 0o600,
143
+ });
144
+ await fs.rename(temporaryPath, snapshotPath);
145
+ }
146
+ codexAuthQuotaSnapshotPath() {
147
+ return path.join(path.dirname(this.config.statusPath), this.runtimeSnapshotFilename(CODEX_AUTH_QUOTA_SNAPSHOT_FILENAME));
148
+ }
149
+ authRuntimeId() { return this.config.tgScopeBotId ?? 'default'; }
150
+ runtimeSnapshotFilename(filename) { return this.config.tgScopeBotId ? filename.replace(/\.json$/, `-${this.config.tgScopeBotId}.json`) : filename; }
151
+ }
@@ -1,55 +1,13 @@
1
- import type { AppConfig } from '../config.js';
2
- import type { Logger } from '../logger.js';
3
- import type { BridgeStore } from '../store/database.js';
4
- import { type AuthSyncClusterAuditResult } from '../auth/cross_node_sync.js';
5
- import type { AppLocale, RuntimeStatus } from '../types.js';
6
1
  import type { TelegramGateway, TelegramTextEvent, TelegramCallbackEvent } from '../telegram/gateway.js';
7
2
  import { BridgeMessagingRouter } from '../channels/bridge_messaging_router.js';
3
+ import type { AppConfig } from '../config.js';
4
+ import type { BridgeStore } from '../store/database.js';
5
+ import type { Logger } from '../logger.js';
8
6
  import type { CodexAppClient } from '../codex_app/client.js';
9
- import type { SelfUpdateRuntime, SelfUpdateStatus } from '../update.js';
10
- type AuthProactiveRefreshStatus = NonNullable<RuntimeStatus['authProactiveRefresh']>;
11
- export interface CoreCoordinator {
12
- canSelfUpdate?: () => boolean;
13
- authCandidateUpdated?: (runtimeId: string, candidateName: string) => Promise<void>;
14
- authCandidateDeleted?: (runtimeId: string, candidateName: string, reason?: string | null) => Promise<void>;
15
- recoverAuthCandidate?: (runtimeId: string, candidateName: string, options?: {
16
- crossNode?: boolean;
17
- }) => Promise<boolean>;
18
- acquireAuthRefreshLease?: (reason: string) => Promise<{
19
- ok: boolean;
20
- leaseId: string | null;
21
- reason?: string | null;
22
- }>;
23
- releaseAuthRefreshLease?: (leaseId: string | null) => Promise<void>;
24
- getAuthSyncStatus?: () => RuntimeStatus['authSync'];
25
- authSyncSafeAll?: () => Promise<{
26
- localSynced: number;
27
- localSkipped: number;
28
- sent: number;
29
- skipped: number;
30
- }>;
31
- authSyncPushAll?: () => Promise<{
32
- sent: number;
33
- skipped: number;
34
- }>;
35
- authSyncTest?: () => Promise<{
36
- sent: number;
37
- replied: number;
38
- missing: string[];
39
- }>;
40
- authSyncAudit?: () => Promise<AuthSyncClusterAuditResult | null>;
41
- statusUpdated?: (status: RuntimeStatus) => void;
42
- getServiceStatus?: () => Promise<{
43
- currentVersion?: string;
44
- bots: NonNullable<RuntimeStatus['bots']>;
45
- weixinRuntime?: RuntimeStatus['weixinRuntime'];
46
- authMirror?: RuntimeStatus['authMirror'];
47
- authSync?: RuntimeStatus['authSync'];
48
- authProactiveRefresh?: AuthProactiveRefreshStatus | null;
49
- lastUpdate?: SelfUpdateStatus | null;
50
- }>;
51
- selfUpdateCompleted?: (status: SelfUpdateStatus) => void;
52
- }
7
+ import type { SelfUpdateRuntime } from '../update.js';
8
+ import type { AppLocale, RuntimeStatus } from '../types.js';
9
+ import { CoreCoordinator } from './state_types.js';
10
+ export type { CoreCoordinator } from './state_types.js';
53
11
  export declare class BridgeSessionCore {
54
12
  private readonly config;
55
13
  private readonly store;
@@ -59,6 +17,14 @@ export declare class BridgeSessionCore {
59
17
  private readonly selfUpdater;
60
18
  private readonly coordinator;
61
19
  private readonly ownsTelegramRuntime;
20
+ private readonly listeners;
21
+ private readonly controlOperations;
22
+ private controlPlaneStarted;
23
+ private recoverExecution;
24
+ private executionHost;
25
+ private readonly localUsage;
26
+ private readonly authQuota;
27
+ private readonly nativePanels;
62
28
  private activeTurns;
63
29
  private activeTurnsByTurnId;
64
30
  private observedThreadWatchers;
@@ -82,11 +48,6 @@ export declare class BridgeSessionCore {
82
48
  private externalAuthValidationInProgress;
83
49
  private turnStartInProgress;
84
50
  private authRotationFailedTargets;
85
- private localUsageCache;
86
- private localUsageCacheLoaded;
87
- private localUsageRefresh;
88
- private authQuotaSnapshots;
89
- private authQuotaSnapshotsLoaded;
90
51
  private lastRemoteControlStatus;
91
52
  private pendingThreadRenames;
92
53
  private pendingThreadNewCwds;
@@ -113,6 +74,14 @@ export declare class BridgeSessionCore {
113
74
  private threadListPresentationState;
114
75
  private readonly messaging;
115
76
  constructor(config: AppConfig, store: BridgeStore, logger: Logger, bot: TelegramGateway, app: CodexAppClient, outbound: BridgeMessagingRouter, selfUpdater?: SelfUpdateRuntime | null, coordinator?: CoreCoordinator | null, ownsTelegramRuntime?: boolean);
77
+ attachExecutionHost(host: {
78
+ ownsScope(scopeId: string): boolean;
79
+ hasExecutingTasks(): boolean;
80
+ }): void;
81
+ startControlPlane(): Promise<void>;
82
+ stopControlPlane(): Promise<void>;
83
+ getPendingApprovalCount(): number;
84
+ dispatchBackendCommand(event: TelegramTextEvent): Promise<void>;
116
85
  /** Wire Telegram inbound events. Call before {@link startCodexApp}. */
117
86
  registerTelegramInboundHandlers(): void;
118
87
  /**
@@ -122,12 +91,16 @@ export declare class BridgeSessionCore {
122
91
  dispatchInboundLikeTelegramText(event: TelegramTextEvent): void;
123
92
  hasPendingInteraction(scopeId: string): boolean;
124
93
  /** Start Codex app-server transport and attach RPC listeners. */
125
- startCodexApp(): Promise<void>;
94
+ startCodexApp(options?: {
95
+ recoverExecution?: boolean;
96
+ }): Promise<void>;
126
97
  /** Begin Telegram Bot API long-polling after handlers and Codex are ready. */
127
98
  startTelegramPolling(): Promise<void>;
128
99
  /** Telegram-only default startup (single channel). */
129
100
  start(): Promise<void>;
130
- stop(): Promise<void>;
101
+ stop(options?: {
102
+ keepTransports?: boolean;
103
+ }): Promise<void>;
131
104
  getRuntimeStatus(): RuntimeStatus;
132
105
  private handleText;
133
106
  private handleCommand;
@@ -139,6 +112,7 @@ export declare class BridgeSessionCore {
139
112
  private handleThreadRenameIndexCommand;
140
113
  handleCallback(event: TelegramCallbackEvent): Promise<void>;
141
114
  private handleApprovalTextCommand;
115
+ private trackControlOperation;
142
116
  private handleNotification;
143
117
  private handleServerRequest;
144
118
  private sendApprovalRequestToThreadScopes;