@foxden-app/foxclaw 0.7.3 → 0.11.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.
- package/.env.example +22 -8
- package/CHANGELOG.md +134 -0
- package/README.md +21 -1
- package/README_EN.md +21 -1
- package/dist/antigravity/adapter.d.ts +18 -0
- package/dist/antigravity/adapter.js +394 -0
- package/dist/antigravity/auth.d.ts +126 -0
- package/dist/antigravity/auth.js +933 -0
- package/dist/antigravity/client.d.ts +32 -0
- package/dist/antigravity/client.js +244 -0
- package/dist/antigravity/controller.d.ts +101 -0
- package/dist/antigravity/controller.js +2007 -0
- package/dist/antigravity/conversations.d.ts +29 -0
- package/dist/antigravity/conversations.js +289 -0
- package/dist/antigravity/events.d.ts +102 -0
- package/dist/antigravity/events.js +143 -0
- package/dist/antigravity/runtime.d.ts +49 -0
- package/dist/antigravity/runtime.js +82 -0
- package/dist/antigravity/subagents.d.ts +66 -0
- package/dist/antigravity/subagents.js +459 -0
- package/dist/channels/telegram/telegram_channel_adapter.d.ts +10 -3
- package/dist/channels/telegram/telegram_channel_adapter.js +2 -1
- package/dist/channels/weixin/weixin_channel_adapter.d.ts +5 -1
- package/dist/codex_app/adapter.d.ts +20 -0
- package/dist/codex_app/adapter.js +213 -0
- package/dist/codex_app/client.d.ts +1 -1
- package/dist/codex_app/client.js +12 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.js +65 -16
- package/dist/controller/controller.d.ts +12 -5
- package/dist/controller/controller.js +109 -8
- package/dist/core/attachments.d.ts +11 -0
- package/dist/core/attachments.js +56 -0
- package/dist/core/engine_spi.d.ts +77 -0
- package/dist/core/engine_spi.js +1 -0
- package/dist/core/orchestrator.d.ts +106 -0
- package/dist/core/orchestrator.js +1556 -0
- package/dist/core/stream_preview.d.ts +29 -0
- package/dist/core/stream_preview.js +146 -0
- package/dist/core/turn_queue.d.ts +19 -0
- package/dist/core/turn_queue.js +41 -0
- package/dist/i18n.d.ts +6 -0
- package/dist/i18n.js +49 -0
- package/dist/main.js +375 -446
- package/dist/opencode/adapter.d.ts +11 -0
- package/dist/opencode/adapter.js +169 -0
- package/dist/opencode/controller.js +2 -2
- package/dist/store/database.d.ts +44 -0
- package/dist/store/database.js +275 -43
- package/dist/store/token_usage.d.ts +23 -0
- package/dist/store/token_usage.js +61 -0
- package/dist/telegram/api.d.ts +1 -0
- package/dist/telegram/api.js +80 -3
- package/dist/telegram/bot_home.js +5 -4
- package/dist/telegram/gateway.d.ts +4 -0
- package/dist/telegram/gateway.js +11 -0
- package/dist/types.d.ts +3 -0
- package/dist/update.d.ts +6 -0
- package/dist/update.js +95 -7
- package/dist/voice/tts.js +4 -2
- package/docs/devlogs//346/212/200/346/234/257/351/200/232/350/256/257/02./347/273/237/344/270/200/351/200/232/351/201/223/350/260/203/345/272/246/345/231/250/344/270/216/345/217/257/346/217/222/346/213/224/345/274/225/346/223/216SPI/357/274/232FoxClaw/344/273/216/345/215/225/344/275/223/350/265/260/345/220/221/345/244/232Agent/345/272/225/345/272/247.md +192 -0
- package/docs/devlogs//347/254/254/344/270/200/344/272/272/347/247/260/347/211/210/02./347/257/207/344/272/214_/345/275/223/344/270/200/344/270/252/346/241/245/346/216/245/345/231/250/345/274/200/345/247/213/345/255/246/344/274/232/345/220/254/346/207/202/346/211/200/346/234/211Agent.md +45 -0
- package/package.json +2 -2
package/dist/store/database.js
CHANGED
|
@@ -7,7 +7,7 @@ export class BridgeStore {
|
|
|
7
7
|
constructor(dbPath) {
|
|
8
8
|
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
9
9
|
this.db = new DatabaseSync(dbPath);
|
|
10
|
-
this.db.exec(`
|
|
10
|
+
this.db.exec(`
|
|
11
11
|
CREATE TABLE IF NOT EXISTS telegram_offsets (
|
|
12
12
|
bot_key TEXT PRIMARY KEY,
|
|
13
13
|
update_id INTEGER NOT NULL
|
|
@@ -18,23 +18,32 @@ export class BridgeStore {
|
|
|
18
18
|
chat_id TEXT NOT NULL,
|
|
19
19
|
updated_at INTEGER NOT NULL
|
|
20
20
|
);
|
|
21
|
-
CREATE TABLE IF NOT EXISTS chat_bindings (
|
|
22
|
-
chat_id TEXT PRIMARY KEY,
|
|
23
|
-
thread_id TEXT NOT NULL,
|
|
24
|
-
cwd TEXT,
|
|
25
|
-
updated_at INTEGER NOT NULL
|
|
26
|
-
);
|
|
27
|
-
CREATE TABLE IF NOT EXISTS chat_settings (
|
|
28
|
-
chat_id TEXT PRIMARY KEY,
|
|
29
|
-
model TEXT,
|
|
21
|
+
CREATE TABLE IF NOT EXISTS chat_bindings (
|
|
22
|
+
chat_id TEXT PRIMARY KEY,
|
|
23
|
+
thread_id TEXT NOT NULL,
|
|
24
|
+
cwd TEXT,
|
|
25
|
+
updated_at INTEGER NOT NULL
|
|
26
|
+
);
|
|
27
|
+
CREATE TABLE IF NOT EXISTS chat_settings (
|
|
28
|
+
chat_id TEXT PRIMARY KEY,
|
|
29
|
+
model TEXT,
|
|
30
30
|
reasoning_effort TEXT,
|
|
31
31
|
locale TEXT,
|
|
32
32
|
access_preset TEXT,
|
|
33
33
|
collaboration_mode TEXT,
|
|
34
34
|
service_tier TEXT,
|
|
35
35
|
active_turn_message_mode TEXT,
|
|
36
|
+
active_backend_id TEXT,
|
|
36
37
|
updated_at INTEGER NOT NULL
|
|
37
38
|
);
|
|
39
|
+
CREATE TABLE IF NOT EXISTS scope_backend_bindings (
|
|
40
|
+
scope_id TEXT NOT NULL,
|
|
41
|
+
backend_id TEXT NOT NULL,
|
|
42
|
+
thread_id TEXT NOT NULL,
|
|
43
|
+
cwd TEXT,
|
|
44
|
+
updated_at INTEGER NOT NULL,
|
|
45
|
+
PRIMARY KEY (scope_id, backend_id)
|
|
46
|
+
);
|
|
38
47
|
CREATE TABLE IF NOT EXISTS thread_cache (
|
|
39
48
|
chat_id TEXT NOT NULL,
|
|
40
49
|
idx INTEGER NOT NULL,
|
|
@@ -48,15 +57,15 @@ export class BridgeStore {
|
|
|
48
57
|
updated_at INTEGER NOT NULL,
|
|
49
58
|
PRIMARY KEY (chat_id, idx)
|
|
50
59
|
);
|
|
51
|
-
CREATE TABLE IF NOT EXISTS pending_approvals (
|
|
52
|
-
local_id TEXT PRIMARY KEY,
|
|
53
|
-
server_request_id TEXT NOT NULL,
|
|
54
|
-
kind TEXT NOT NULL,
|
|
55
|
-
chat_id TEXT NOT NULL,
|
|
56
|
-
thread_id TEXT NOT NULL,
|
|
57
|
-
turn_id TEXT NOT NULL,
|
|
58
|
-
item_id TEXT NOT NULL,
|
|
59
|
-
approval_id TEXT,
|
|
60
|
+
CREATE TABLE IF NOT EXISTS pending_approvals (
|
|
61
|
+
local_id TEXT PRIMARY KEY,
|
|
62
|
+
server_request_id TEXT NOT NULL,
|
|
63
|
+
kind TEXT NOT NULL,
|
|
64
|
+
chat_id TEXT NOT NULL,
|
|
65
|
+
thread_id TEXT NOT NULL,
|
|
66
|
+
turn_id TEXT NOT NULL,
|
|
67
|
+
item_id TEXT NOT NULL,
|
|
68
|
+
approval_id TEXT,
|
|
60
69
|
reason TEXT,
|
|
61
70
|
command TEXT,
|
|
62
71
|
cwd TEXT,
|
|
@@ -64,7 +73,7 @@ export class BridgeStore {
|
|
|
64
73
|
message_id INTEGER,
|
|
65
74
|
created_at INTEGER NOT NULL,
|
|
66
75
|
resolved_at INTEGER
|
|
67
|
-
);
|
|
76
|
+
);
|
|
68
77
|
CREATE TABLE IF NOT EXISTS active_turn_previews (
|
|
69
78
|
turn_id TEXT PRIMARY KEY,
|
|
70
79
|
scope_id TEXT NOT NULL,
|
|
@@ -75,6 +84,11 @@ export class BridgeStore {
|
|
|
75
84
|
created_at INTEGER NOT NULL,
|
|
76
85
|
updated_at INTEGER NOT NULL
|
|
77
86
|
);
|
|
87
|
+
CREATE TABLE IF NOT EXISTS watched_threads (
|
|
88
|
+
scope_id TEXT PRIMARY KEY,
|
|
89
|
+
thread_id TEXT NOT NULL,
|
|
90
|
+
updated_at INTEGER NOT NULL
|
|
91
|
+
);
|
|
78
92
|
CREATE TABLE IF NOT EXISTS pending_user_inputs (
|
|
79
93
|
local_id TEXT PRIMARY KEY,
|
|
80
94
|
server_request_id TEXT NOT NULL,
|
|
@@ -160,9 +174,9 @@ export class BridgeStore {
|
|
|
160
174
|
direction TEXT NOT NULL,
|
|
161
175
|
chat_id TEXT NOT NULL,
|
|
162
176
|
event_type TEXT NOT NULL,
|
|
163
|
-
summary TEXT NOT NULL,
|
|
164
|
-
created_at INTEGER NOT NULL
|
|
165
|
-
);
|
|
177
|
+
summary TEXT NOT NULL,
|
|
178
|
+
created_at INTEGER NOT NULL
|
|
179
|
+
);
|
|
166
180
|
CREATE TABLE IF NOT EXISTS weixin_context_tokens (
|
|
167
181
|
scope_id TEXT PRIMARY KEY,
|
|
168
182
|
context_token TEXT NOT NULL,
|
|
@@ -208,6 +222,15 @@ export class BridgeStore {
|
|
|
208
222
|
delete_reason TEXT,
|
|
209
223
|
invalid_delete_count INTEGER NOT NULL DEFAULT 0
|
|
210
224
|
);
|
|
225
|
+
CREATE TABLE IF NOT EXISTS cumulative_token_usage (
|
|
226
|
+
backend_id TEXT PRIMARY KEY,
|
|
227
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
228
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
229
|
+
cached_tokens INTEGER NOT NULL DEFAULT 0,
|
|
230
|
+
total_tokens INTEGER NOT NULL DEFAULT 0,
|
|
231
|
+
turns_count INTEGER NOT NULL DEFAULT 0,
|
|
232
|
+
updated_at INTEGER NOT NULL
|
|
233
|
+
);
|
|
211
234
|
`);
|
|
212
235
|
this.ensureColumn('thread_cache', 'name', 'TEXT');
|
|
213
236
|
this.ensureColumn('thread_cache', 'model_provider', 'TEXT');
|
|
@@ -218,6 +241,7 @@ export class BridgeStore {
|
|
|
218
241
|
this.ensureColumn('chat_settings', 'collaboration_mode', 'TEXT');
|
|
219
242
|
this.ensureColumn('chat_settings', 'service_tier', 'TEXT');
|
|
220
243
|
this.ensureColumn('chat_settings', 'active_turn_message_mode', 'TEXT');
|
|
244
|
+
this.ensureColumn('chat_settings', 'active_backend_id', 'TEXT');
|
|
221
245
|
this.ensureColumn('pending_approvals', 'payload_json', 'TEXT');
|
|
222
246
|
this.ensureColumn('pending_user_inputs', 'status', "TEXT NOT NULL DEFAULT 'pending'");
|
|
223
247
|
this.ensureColumn('pending_user_inputs', 'submitted_at', 'INTEGER');
|
|
@@ -226,12 +250,17 @@ export class BridgeStore {
|
|
|
226
250
|
this.ensureColumn('codex_auth_candidates', 'state', "TEXT NOT NULL DEFAULT 'active'");
|
|
227
251
|
this.ensureColumn('codex_auth_candidate_runtime', 'state', "TEXT NOT NULL DEFAULT 'active'");
|
|
228
252
|
this.ensureColumn('codex_auth_quota_snapshots', 'plan_type', 'TEXT');
|
|
253
|
+
this.ensureColumn('codex_auth_quota_snapshots', 'quota_identity_id', "TEXT NOT NULL DEFAULT ''");
|
|
229
254
|
this.ensureColumn('codex_auth_quota_snapshots', 'primary_window_duration_mins', 'REAL');
|
|
230
255
|
this.ensureColumn('codex_auth_quota_snapshots', 'primary_resets_at', 'INTEGER');
|
|
231
256
|
this.ensureColumn('codex_auth_quota_snapshots', 'secondary_window_duration_mins', 'REAL');
|
|
232
257
|
this.ensureColumn('codex_auth_quota_snapshots', 'secondary_resets_at', 'INTEGER');
|
|
233
|
-
this.ensureColumn('codex_auth_quota_snapshots', 'quota_identity_id', "TEXT NOT NULL DEFAULT ''");
|
|
234
258
|
this.ensureColumn('codex_auth_pool_history', 'invalid_delete_count', 'INTEGER NOT NULL DEFAULT 0');
|
|
259
|
+
this.ensureColumn('scope_backend_bindings', 'model', 'TEXT');
|
|
260
|
+
this.ensureColumn('scope_backend_bindings', 'reasoning_effort', 'TEXT');
|
|
261
|
+
this.ensureColumn('scope_backend_bindings', 'active_turn_message_mode', 'TEXT');
|
|
262
|
+
this.ensureColumn('scope_backend_bindings', 'service_tier', 'TEXT');
|
|
263
|
+
this.ensureColumn('scope_backend_bindings', 'access_preset', 'TEXT');
|
|
235
264
|
this.db.prepare(`
|
|
236
265
|
UPDATE codex_auth_quota_snapshots
|
|
237
266
|
SET quota_identity_id = account_id
|
|
@@ -248,10 +277,10 @@ export class BridgeStore {
|
|
|
248
277
|
return row?.update_id ?? 0;
|
|
249
278
|
}
|
|
250
279
|
setTelegramOffset(botKey, updateId) {
|
|
251
|
-
this.db.prepare(`
|
|
252
|
-
INSERT INTO telegram_offsets (bot_key, update_id)
|
|
253
|
-
VALUES (?, ?)
|
|
254
|
-
ON CONFLICT(bot_key) DO UPDATE SET update_id = excluded.update_id
|
|
280
|
+
this.db.prepare(`
|
|
281
|
+
INSERT INTO telegram_offsets (bot_key, update_id)
|
|
282
|
+
VALUES (?, ?)
|
|
283
|
+
ON CONFLICT(bot_key) DO UPDATE SET update_id = excluded.update_id
|
|
255
284
|
`).run(botKey, updateId);
|
|
256
285
|
}
|
|
257
286
|
rememberTelegramPrivateScope(botId, scopeId, chatId) {
|
|
@@ -269,6 +298,31 @@ export class BridgeStore {
|
|
|
269
298
|
const row = this.db.prepare('SELECT scope_id, chat_id FROM telegram_private_scopes WHERE bot_id = ?').get(botId);
|
|
270
299
|
return row ? { scopeId: String(row.scope_id), chatId: String(row.chat_id) } : null;
|
|
271
300
|
}
|
|
301
|
+
migrateTelegramUnnamespacedScope(botId, chatId) {
|
|
302
|
+
const legacyScope = `telegram:${chatId}::root`;
|
|
303
|
+
const namespacedScope = `telegram:${botId}:${chatId}::root`;
|
|
304
|
+
const existing = this.db.prepare('SELECT chat_id, thread_id, cwd, updated_at FROM chat_bindings WHERE chat_id = ?').get(legacyScope);
|
|
305
|
+
if (existing) {
|
|
306
|
+
const target = this.db.prepare('SELECT chat_id, thread_id, cwd, updated_at FROM chat_bindings WHERE chat_id = ?').get(namespacedScope);
|
|
307
|
+
if (!target) {
|
|
308
|
+
this.db.prepare('INSERT INTO chat_bindings (chat_id, thread_id, cwd, updated_at) VALUES (?, ?, ?, ?)').run(namespacedScope, existing.thread_id, existing.cwd, existing.updated_at);
|
|
309
|
+
}
|
|
310
|
+
else if (Number(existing.updated_at) > Number(target.updated_at)) {
|
|
311
|
+
this.db.prepare('UPDATE chat_bindings SET thread_id = ?, cwd = ?, updated_at = ? WHERE chat_id = ?').run(existing.thread_id, existing.cwd, existing.updated_at, namespacedScope);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
const legacyBackends = this.db.prepare('SELECT * FROM scope_backend_bindings WHERE scope_id = ?').all(legacyScope);
|
|
315
|
+
for (const row of legacyBackends) {
|
|
316
|
+
const backendId = String(row.backend_id);
|
|
317
|
+
const targetRow = this.db.prepare('SELECT updated_at FROM scope_backend_bindings WHERE scope_id = ? AND backend_id = ?').get(namespacedScope, backendId);
|
|
318
|
+
if (!targetRow) {
|
|
319
|
+
this.db.prepare('INSERT INTO scope_backend_bindings (scope_id, backend_id, thread_id, cwd, updated_at, model, reasoning_effort, active_turn_message_mode, service_tier, access_preset) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').run(namespacedScope, backendId, row.thread_id, row.cwd, row.updated_at, row.model, row.reasoning_effort, row.active_turn_message_mode, row.service_tier, row.access_preset);
|
|
320
|
+
}
|
|
321
|
+
else if (Number(row.updated_at) > Number(targetRow.updated_at)) {
|
|
322
|
+
this.db.prepare('UPDATE scope_backend_bindings SET thread_id = ?, cwd = ?, updated_at = ?, model = ?, reasoning_effort = ?, active_turn_message_mode = ?, service_tier = ?, access_preset = ? WHERE scope_id = ? AND backend_id = ?').run(row.thread_id, row.cwd, row.updated_at, row.model, row.reasoning_effort, row.active_turn_message_mode, row.service_tier, row.access_preset, namespacedScope, backendId);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
272
326
|
getBinding(chatId) {
|
|
273
327
|
const row = this.db.prepare('SELECT chat_id, thread_id, cwd, updated_at FROM chat_bindings WHERE chat_id = ?').get(chatId);
|
|
274
328
|
if (!row)
|
|
@@ -299,8 +353,28 @@ export class BridgeStore {
|
|
|
299
353
|
clearBinding(chatId) {
|
|
300
354
|
this.db.prepare('DELETE FROM chat_bindings WHERE chat_id = ?').run(chatId);
|
|
301
355
|
}
|
|
356
|
+
getWatchedThread(chatId) {
|
|
357
|
+
const row = this.db.prepare('SELECT thread_id FROM watched_threads WHERE scope_id = ?').get(chatId);
|
|
358
|
+
return row?.thread_id ? String(row.thread_id) : null;
|
|
359
|
+
}
|
|
360
|
+
setWatchedThread(chatId, threadId) {
|
|
361
|
+
if (threadId) {
|
|
362
|
+
this.db.prepare(`
|
|
363
|
+
INSERT INTO watched_threads (scope_id, thread_id, updated_at)
|
|
364
|
+
VALUES (?, ?, ?)
|
|
365
|
+
ON CONFLICT(scope_id) DO UPDATE SET thread_id = excluded.thread_id, updated_at = excluded.updated_at
|
|
366
|
+
`).run(chatId, threadId, Date.now());
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
this.db.prepare('DELETE FROM watched_threads WHERE scope_id = ?').run(chatId);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
listWatchedThreads() {
|
|
373
|
+
const rows = this.db.prepare('SELECT scope_id, thread_id FROM watched_threads').all();
|
|
374
|
+
return rows.map((r) => ({ scopeId: String(r.scope_id), threadId: String(r.thread_id) }));
|
|
375
|
+
}
|
|
302
376
|
getChatSettings(chatId) {
|
|
303
|
-
const row = this.db.prepare('SELECT chat_id, model, reasoning_effort, locale, access_preset, collaboration_mode, service_tier, active_turn_message_mode, updated_at FROM chat_settings WHERE chat_id = ?').get(chatId);
|
|
377
|
+
const row = this.db.prepare('SELECT chat_id, model, reasoning_effort, locale, access_preset, collaboration_mode, service_tier, active_turn_message_mode, active_backend_id, updated_at FROM chat_settings WHERE chat_id = ?').get(chatId);
|
|
304
378
|
if (!row)
|
|
305
379
|
return null;
|
|
306
380
|
return {
|
|
@@ -312,33 +386,105 @@ export class BridgeStore {
|
|
|
312
386
|
collaborationMode: normalizeCollaborationMode(row.collaboration_mode),
|
|
313
387
|
serviceTier: row.service_tier === null ? null : String(row.service_tier),
|
|
314
388
|
activeTurnMessageMode: normalizeActiveTurnMessageMode(row.active_turn_message_mode),
|
|
389
|
+
activeBackendId: row.active_backend_id === null || row.active_backend_id === undefined ? null : String(row.active_backend_id),
|
|
315
390
|
updatedAt: Number(row.updated_at),
|
|
316
391
|
};
|
|
317
392
|
}
|
|
318
393
|
setChatSettings(chatId, model, reasoningEffort, locale) {
|
|
319
394
|
const current = this.getChatSettings(chatId);
|
|
320
395
|
const nextLocale = locale === undefined ? current?.locale ?? null : locale;
|
|
321
|
-
this.writeChatSettings(chatId, model, reasoningEffort, nextLocale, current?.accessPreset ?? null, current?.collaborationMode ?? null, current?.serviceTier ?? null, current?.activeTurnMessageMode ?? null);
|
|
396
|
+
this.writeChatSettings(chatId, model, reasoningEffort, nextLocale, current?.accessPreset ?? null, current?.collaborationMode ?? null, current?.serviceTier ?? null, current?.activeTurnMessageMode ?? null, current?.activeBackendId ?? null);
|
|
397
|
+
}
|
|
398
|
+
setChatModel(chatId, model) {
|
|
399
|
+
const current = this.getChatSettings(chatId);
|
|
400
|
+
this.setChatSettings(chatId, model, current?.reasoningEffort ?? null);
|
|
401
|
+
}
|
|
402
|
+
setChatEffort(chatId, effort) {
|
|
403
|
+
const current = this.getChatSettings(chatId);
|
|
404
|
+
this.setChatSettings(chatId, current?.model ?? null, effort);
|
|
322
405
|
}
|
|
323
406
|
setChatLocale(chatId, locale) {
|
|
324
407
|
const current = this.getChatSettings(chatId);
|
|
325
|
-
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, locale, current?.accessPreset ?? null, current?.collaborationMode ?? null, current?.serviceTier ?? null, current?.activeTurnMessageMode ?? null);
|
|
408
|
+
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, locale, current?.accessPreset ?? null, current?.collaborationMode ?? null, current?.serviceTier ?? null, current?.activeTurnMessageMode ?? null, current?.activeBackendId ?? null);
|
|
326
409
|
}
|
|
327
410
|
setChatAccessPreset(chatId, accessPreset) {
|
|
328
411
|
const current = this.getChatSettings(chatId);
|
|
329
|
-
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, current?.locale ?? null, accessPreset, current?.collaborationMode ?? null, current?.serviceTier ?? null, current?.activeTurnMessageMode ?? null);
|
|
412
|
+
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, current?.locale ?? null, accessPreset, current?.collaborationMode ?? null, current?.serviceTier ?? null, current?.activeTurnMessageMode ?? null, current?.activeBackendId ?? null);
|
|
330
413
|
}
|
|
331
414
|
setChatCollaborationMode(chatId, collaborationMode) {
|
|
332
415
|
const current = this.getChatSettings(chatId);
|
|
333
|
-
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, current?.locale ?? null, current?.accessPreset ?? null, collaborationMode, current?.serviceTier ?? null, current?.activeTurnMessageMode ?? null);
|
|
416
|
+
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, current?.locale ?? null, current?.accessPreset ?? null, collaborationMode, current?.serviceTier ?? null, current?.activeTurnMessageMode ?? null, current?.activeBackendId ?? null);
|
|
334
417
|
}
|
|
335
418
|
setChatServiceTier(chatId, serviceTier) {
|
|
336
419
|
const current = this.getChatSettings(chatId);
|
|
337
|
-
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, current?.locale ?? null, current?.accessPreset ?? null, current?.collaborationMode ?? null, serviceTier, current?.activeTurnMessageMode ?? null);
|
|
420
|
+
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, current?.locale ?? null, current?.accessPreset ?? null, current?.collaborationMode ?? null, serviceTier, current?.activeTurnMessageMode ?? null, current?.activeBackendId ?? null);
|
|
338
421
|
}
|
|
339
422
|
setChatActiveTurnMessageMode(chatId, activeTurnMessageMode) {
|
|
340
423
|
const current = this.getChatSettings(chatId);
|
|
341
|
-
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, current?.locale ?? null, current?.accessPreset ?? null, current?.collaborationMode ?? null, current?.serviceTier ?? null, activeTurnMessageMode);
|
|
424
|
+
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, current?.locale ?? null, current?.accessPreset ?? null, current?.collaborationMode ?? null, current?.serviceTier ?? null, activeTurnMessageMode, current?.activeBackendId ?? null);
|
|
425
|
+
}
|
|
426
|
+
getActiveBackend(chatId) {
|
|
427
|
+
return this.getChatSettings(chatId)?.activeBackendId ?? null;
|
|
428
|
+
}
|
|
429
|
+
setActiveBackend(chatId, backendId) {
|
|
430
|
+
const current = this.getChatSettings(chatId);
|
|
431
|
+
this.writeChatSettings(chatId, current?.model ?? null, current?.reasoningEffort ?? null, current?.locale ?? null, current?.accessPreset ?? null, current?.collaborationMode ?? null, current?.serviceTier ?? null, current?.activeTurnMessageMode ?? null, backendId);
|
|
432
|
+
}
|
|
433
|
+
getScopeBackendBinding(scopeId, backendId) {
|
|
434
|
+
const row = this.db.prepare(`
|
|
435
|
+
SELECT thread_id, cwd, model, reasoning_effort, active_turn_message_mode, service_tier, access_preset
|
|
436
|
+
FROM scope_backend_bindings
|
|
437
|
+
WHERE scope_id = ? AND backend_id = ?
|
|
438
|
+
`).get(scopeId, backendId);
|
|
439
|
+
if (!row)
|
|
440
|
+
return null;
|
|
441
|
+
return {
|
|
442
|
+
threadId: String(row.thread_id),
|
|
443
|
+
cwd: row.cwd ? String(row.cwd) : null,
|
|
444
|
+
model: row.model === null || row.model === undefined ? null : String(row.model),
|
|
445
|
+
reasoningEffort: row.reasoning_effort === null || row.reasoning_effort === undefined ? null : String(row.reasoning_effort),
|
|
446
|
+
activeTurnMessageMode: row.active_turn_message_mode === null || row.active_turn_message_mode === undefined ? null : String(row.active_turn_message_mode),
|
|
447
|
+
serviceTier: row.service_tier === null || row.service_tier === undefined ? null : String(row.service_tier),
|
|
448
|
+
accessPreset: row.access_preset === null || row.access_preset === undefined ? null : String(row.access_preset),
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
setScopeBackendBinding(scopeId, backendId, threadId, cwd, settings) {
|
|
452
|
+
const current = this.getScopeBackendBinding(scopeId, backendId);
|
|
453
|
+
const model = settings && settings.model !== undefined ? settings.model : current?.model ?? null;
|
|
454
|
+
const reasoningEffort = settings && settings.reasoningEffort !== undefined ? settings.reasoningEffort : current?.reasoningEffort ?? null;
|
|
455
|
+
const activeTurnMessageMode = settings && settings.activeTurnMessageMode !== undefined ? settings.activeTurnMessageMode : current?.activeTurnMessageMode ?? null;
|
|
456
|
+
const serviceTier = settings && settings.serviceTier !== undefined ? settings.serviceTier : current?.serviceTier ?? null;
|
|
457
|
+
const accessPreset = settings && settings.accessPreset !== undefined ? settings.accessPreset : current?.accessPreset ?? null;
|
|
458
|
+
this.db.prepare(`
|
|
459
|
+
INSERT INTO scope_backend_bindings (
|
|
460
|
+
scope_id, backend_id, thread_id, cwd, model, reasoning_effort,
|
|
461
|
+
active_turn_message_mode, service_tier, access_preset, updated_at
|
|
462
|
+
)
|
|
463
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
464
|
+
ON CONFLICT(scope_id, backend_id) DO UPDATE SET
|
|
465
|
+
thread_id = excluded.thread_id,
|
|
466
|
+
cwd = excluded.cwd,
|
|
467
|
+
model = excluded.model,
|
|
468
|
+
reasoning_effort = excluded.reasoning_effort,
|
|
469
|
+
active_turn_message_mode = excluded.active_turn_message_mode,
|
|
470
|
+
service_tier = excluded.service_tier,
|
|
471
|
+
access_preset = excluded.access_preset,
|
|
472
|
+
updated_at = excluded.updated_at
|
|
473
|
+
`).run(scopeId, backendId, threadId, cwd, model, reasoningEffort, activeTurnMessageMode, serviceTier, accessPreset, Date.now());
|
|
474
|
+
}
|
|
475
|
+
listScopeBackendBindings(scopeId) {
|
|
476
|
+
const rows = this.db.prepare(`
|
|
477
|
+
SELECT backend_id, thread_id, cwd, updated_at
|
|
478
|
+
FROM scope_backend_bindings
|
|
479
|
+
WHERE scope_id = ?
|
|
480
|
+
ORDER BY updated_at DESC
|
|
481
|
+
`).all(scopeId);
|
|
482
|
+
return rows.map((r) => ({
|
|
483
|
+
backendId: String(r.backend_id),
|
|
484
|
+
threadId: String(r.thread_id),
|
|
485
|
+
cwd: r.cwd ? String(r.cwd) : null,
|
|
486
|
+
updatedAt: Number(r.updated_at),
|
|
487
|
+
}));
|
|
342
488
|
}
|
|
343
489
|
findChatIdByThreadId(threadId) {
|
|
344
490
|
const row = this.db.prepare('SELECT chat_id FROM chat_bindings WHERE thread_id = ?').get(threadId);
|
|
@@ -365,7 +511,7 @@ export class BridgeStore {
|
|
|
365
511
|
});
|
|
366
512
|
}
|
|
367
513
|
getCachedThread(chatId, index) {
|
|
368
|
-
const row = this.db.prepare(`
|
|
514
|
+
const row = this.db.prepare(`
|
|
369
515
|
SELECT idx, thread_id, name, preview, cwd, model_provider, status, archived, updated_at
|
|
370
516
|
FROM thread_cache
|
|
371
517
|
WHERE chat_id = ? AND idx = ?
|
|
@@ -385,11 +531,11 @@ export class BridgeStore {
|
|
|
385
531
|
};
|
|
386
532
|
}
|
|
387
533
|
listCachedThreads(chatId) {
|
|
388
|
-
const rows = this.db.prepare(`
|
|
534
|
+
const rows = this.db.prepare(`
|
|
389
535
|
SELECT idx, thread_id, name, preview, cwd, model_provider, status, archived, updated_at
|
|
390
536
|
FROM thread_cache
|
|
391
537
|
WHERE chat_id = ?
|
|
392
|
-
ORDER BY idx ASC
|
|
538
|
+
ORDER BY idx ASC
|
|
393
539
|
`).all(chatId);
|
|
394
540
|
return rows.map((row) => ({
|
|
395
541
|
index: Number(row.idx),
|
|
@@ -404,7 +550,7 @@ export class BridgeStore {
|
|
|
404
550
|
}));
|
|
405
551
|
}
|
|
406
552
|
savePendingApproval(record) {
|
|
407
|
-
this.db.prepare(`
|
|
553
|
+
this.db.prepare(`
|
|
408
554
|
INSERT INTO pending_approvals (
|
|
409
555
|
local_id, server_request_id, kind, chat_id, thread_id, turn_id, item_id, approval_id, reason, command, cwd, payload_json, message_id, created_at, resolved_at
|
|
410
556
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
@@ -833,10 +979,10 @@ export class BridgeStore {
|
|
|
833
979
|
resolvedAt: row.resolved_at === null ? null : Number(row.resolved_at),
|
|
834
980
|
};
|
|
835
981
|
}
|
|
836
|
-
writeChatSettings(chatId, model, reasoningEffort, locale, accessPreset, collaborationMode, serviceTier, activeTurnMessageMode) {
|
|
982
|
+
writeChatSettings(chatId, model, reasoningEffort, locale, accessPreset, collaborationMode, serviceTier, activeTurnMessageMode, activeBackendId = null) {
|
|
837
983
|
this.db.prepare(`
|
|
838
|
-
INSERT INTO chat_settings (chat_id, model, reasoning_effort, locale, access_preset, collaboration_mode, service_tier, active_turn_message_mode, updated_at)
|
|
839
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
984
|
+
INSERT INTO chat_settings (chat_id, model, reasoning_effort, locale, access_preset, collaboration_mode, service_tier, active_turn_message_mode, active_backend_id, updated_at)
|
|
985
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
840
986
|
ON CONFLICT(chat_id) DO UPDATE SET
|
|
841
987
|
model = excluded.model,
|
|
842
988
|
reasoning_effort = excluded.reasoning_effort,
|
|
@@ -845,8 +991,9 @@ export class BridgeStore {
|
|
|
845
991
|
collaboration_mode = excluded.collaboration_mode,
|
|
846
992
|
service_tier = excluded.service_tier,
|
|
847
993
|
active_turn_message_mode = excluded.active_turn_message_mode,
|
|
994
|
+
active_backend_id = excluded.active_backend_id,
|
|
848
995
|
updated_at = excluded.updated_at
|
|
849
|
-
`).run(chatId, model, reasoningEffort, locale, accessPreset, collaborationMode, serviceTier, activeTurnMessageMode, Date.now());
|
|
996
|
+
`).run(chatId, model, reasoningEffort, locale, accessPreset, collaborationMode, serviceTier, activeTurnMessageMode, activeBackendId, Date.now());
|
|
850
997
|
}
|
|
851
998
|
getWeixinContextToken(scopeId) {
|
|
852
999
|
const row = this.db.prepare('SELECT context_token FROM weixin_context_tokens WHERE scope_id = ?').get(scopeId);
|
|
@@ -1071,6 +1218,91 @@ export class BridgeStore {
|
|
|
1071
1218
|
updatedAt: Number(row.updated_at),
|
|
1072
1219
|
}));
|
|
1073
1220
|
}
|
|
1221
|
+
recordTokenUsage(delta, backendId = 'default') {
|
|
1222
|
+
const input = Math.max(0, Math.round(delta.inputTokens ?? 0));
|
|
1223
|
+
const output = Math.max(0, Math.round(delta.outputTokens ?? 0));
|
|
1224
|
+
const cached = Math.max(0, Math.round(delta.cachedTokens ?? 0));
|
|
1225
|
+
const total = delta.totalTokens != null ? Math.max(0, Math.round(delta.totalTokens)) : input + output;
|
|
1226
|
+
const now = Date.now();
|
|
1227
|
+
this.db.prepare(`
|
|
1228
|
+
INSERT INTO cumulative_token_usage (backend_id, input_tokens, output_tokens, cached_tokens, total_tokens, turns_count, updated_at)
|
|
1229
|
+
VALUES (?, ?, ?, ?, ?, 1, ?)
|
|
1230
|
+
ON CONFLICT(backend_id) DO UPDATE SET
|
|
1231
|
+
input_tokens = cumulative_token_usage.input_tokens + excluded.input_tokens,
|
|
1232
|
+
output_tokens = cumulative_token_usage.output_tokens + excluded.output_tokens,
|
|
1233
|
+
cached_tokens = cumulative_token_usage.cached_tokens + excluded.cached_tokens,
|
|
1234
|
+
total_tokens = cumulative_token_usage.total_tokens + excluded.total_tokens,
|
|
1235
|
+
turns_count = cumulative_token_usage.turns_count + 1,
|
|
1236
|
+
updated_at = excluded.updated_at
|
|
1237
|
+
`).run(backendId, input, output, cached, total, now);
|
|
1238
|
+
}
|
|
1239
|
+
setBackendCumulativeTokenUsage(usage, backendId) {
|
|
1240
|
+
const input = Math.max(0, Math.round(usage.inputTokens));
|
|
1241
|
+
const output = Math.max(0, Math.round(usage.outputTokens));
|
|
1242
|
+
const cached = Math.max(0, Math.round(usage.cachedTokens ?? 0));
|
|
1243
|
+
const total = usage.totalTokens != null ? Math.max(0, Math.round(usage.totalTokens)) : input + output;
|
|
1244
|
+
const turns = Math.max(0, Math.round(usage.turnsCount ?? 0));
|
|
1245
|
+
const now = Date.now();
|
|
1246
|
+
this.db.prepare(`
|
|
1247
|
+
INSERT INTO cumulative_token_usage (backend_id, input_tokens, output_tokens, cached_tokens, total_tokens, turns_count, updated_at)
|
|
1248
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
1249
|
+
ON CONFLICT(backend_id) DO UPDATE SET
|
|
1250
|
+
input_tokens = excluded.input_tokens,
|
|
1251
|
+
output_tokens = excluded.output_tokens,
|
|
1252
|
+
cached_tokens = excluded.cached_tokens,
|
|
1253
|
+
total_tokens = excluded.total_tokens,
|
|
1254
|
+
turns_count = excluded.turns_count,
|
|
1255
|
+
updated_at = excluded.updated_at
|
|
1256
|
+
`).run(backendId, input, output, cached, total, turns, now);
|
|
1257
|
+
}
|
|
1258
|
+
getCumulativeTokenUsage(backendId) {
|
|
1259
|
+
if (backendId && backendId !== 'all') {
|
|
1260
|
+
const row = this.db.prepare(`
|
|
1261
|
+
SELECT input_tokens, output_tokens, cached_tokens, total_tokens, turns_count
|
|
1262
|
+
FROM cumulative_token_usage
|
|
1263
|
+
WHERE backend_id = ?
|
|
1264
|
+
`).get(backendId);
|
|
1265
|
+
return {
|
|
1266
|
+
inputTokens: Number(row?.input_tokens ?? 0),
|
|
1267
|
+
outputTokens: Number(row?.output_tokens ?? 0),
|
|
1268
|
+
cachedTokens: Number(row?.cached_tokens ?? 0),
|
|
1269
|
+
totalTokens: Number(row?.total_tokens ?? 0),
|
|
1270
|
+
turnsCount: Number(row?.turns_count ?? 0),
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
const row = this.db.prepare(`
|
|
1274
|
+
SELECT
|
|
1275
|
+
COALESCE(SUM(input_tokens), 0) AS input_tokens,
|
|
1276
|
+
COALESCE(SUM(output_tokens), 0) AS output_tokens,
|
|
1277
|
+
COALESCE(SUM(cached_tokens), 0) AS cached_tokens,
|
|
1278
|
+
COALESCE(SUM(total_tokens), 0) AS total_tokens,
|
|
1279
|
+
COALESCE(SUM(turns_count), 0) AS turns_count
|
|
1280
|
+
FROM cumulative_token_usage
|
|
1281
|
+
`).get();
|
|
1282
|
+
return {
|
|
1283
|
+
inputTokens: Number(row?.input_tokens ?? 0),
|
|
1284
|
+
outputTokens: Number(row?.output_tokens ?? 0),
|
|
1285
|
+
cachedTokens: Number(row?.cached_tokens ?? 0),
|
|
1286
|
+
totalTokens: Number(row?.total_tokens ?? 0),
|
|
1287
|
+
turnsCount: Number(row?.turns_count ?? 0),
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1290
|
+
getAllBackendTokenUsages() {
|
|
1291
|
+
const rows = this.db.prepare(`
|
|
1292
|
+
SELECT backend_id, input_tokens, output_tokens, cached_tokens, total_tokens, turns_count, updated_at
|
|
1293
|
+
FROM cumulative_token_usage
|
|
1294
|
+
ORDER BY total_tokens DESC
|
|
1295
|
+
`).all();
|
|
1296
|
+
return rows.map((r) => ({
|
|
1297
|
+
backendId: r.backend_id,
|
|
1298
|
+
inputTokens: Number(r.input_tokens),
|
|
1299
|
+
outputTokens: Number(r.output_tokens),
|
|
1300
|
+
cachedTokens: Number(r.cached_tokens),
|
|
1301
|
+
totalTokens: Number(r.total_tokens),
|
|
1302
|
+
turnsCount: Number(r.turns_count),
|
|
1303
|
+
updatedAt: Number(r.updated_at),
|
|
1304
|
+
}));
|
|
1305
|
+
}
|
|
1074
1306
|
ensureColumn(table, column, definition) {
|
|
1075
1307
|
const columns = this.db.prepare(`PRAGMA table_info(${table})`).all();
|
|
1076
1308
|
if (columns.some(entry => entry.name === column)) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AppLocale } from '../types.js';
|
|
2
|
+
import type { BridgeStore } from './database.js';
|
|
3
|
+
export interface CumulativeTokenTotals {
|
|
4
|
+
inputTokens: number;
|
|
5
|
+
outputTokens: number;
|
|
6
|
+
cachedTokens: number;
|
|
7
|
+
totalTokens: number;
|
|
8
|
+
turnsCount: number;
|
|
9
|
+
}
|
|
10
|
+
export interface CumulativeTokenUsageRecord extends CumulativeTokenTotals {
|
|
11
|
+
backendId: string;
|
|
12
|
+
updatedAt: number;
|
|
13
|
+
}
|
|
14
|
+
export interface TokenUsageDelta {
|
|
15
|
+
inputTokens?: number | undefined;
|
|
16
|
+
outputTokens?: number | undefined;
|
|
17
|
+
cachedTokens?: number | undefined;
|
|
18
|
+
totalTokens?: number | undefined;
|
|
19
|
+
}
|
|
20
|
+
export declare function formatMetricTokenCount(value: number): string;
|
|
21
|
+
export declare function formatTokenUsageSummary(totals: CumulativeTokenTotals, locale?: AppLocale): string;
|
|
22
|
+
export declare function formatBackendTokenUsageBreakdown(usages: CumulativeTokenUsageRecord[]): string;
|
|
23
|
+
export declare function syncCodexLocalUsageToStore(store: BridgeStore, codexHome?: string): Promise<void>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readCodexLocalUsageStats } from '../codex_app/local_usage.js';
|
|
2
|
+
export function formatMetricTokenCount(value) {
|
|
3
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
4
|
+
return '0';
|
|
5
|
+
}
|
|
6
|
+
if (value >= 1_000_000_000) {
|
|
7
|
+
const g = value / 1_000_000_000;
|
|
8
|
+
return `${Number.isInteger(g) ? g : Number(g.toFixed(2))}G`;
|
|
9
|
+
}
|
|
10
|
+
if (value >= 1_000_000) {
|
|
11
|
+
const m = value / 1_000_000;
|
|
12
|
+
return `${Number.isInteger(m) ? m : Number(m.toFixed(2))}M`;
|
|
13
|
+
}
|
|
14
|
+
if (value >= 1_000) {
|
|
15
|
+
const k = value / 1_000;
|
|
16
|
+
return `${Number.isInteger(k) ? k : Number(k.toFixed(1))}K`;
|
|
17
|
+
}
|
|
18
|
+
return String(Math.round(value));
|
|
19
|
+
}
|
|
20
|
+
export function formatTokenUsageSummary(totals, locale = 'zh') {
|
|
21
|
+
const total = formatMetricTokenCount(totals.totalTokens);
|
|
22
|
+
const input = formatMetricTokenCount(totals.inputTokens);
|
|
23
|
+
const output = formatMetricTokenCount(totals.outputTokens);
|
|
24
|
+
const cached = formatMetricTokenCount(totals.cachedTokens);
|
|
25
|
+
if (locale === 'zh') {
|
|
26
|
+
return `• **Token 用量**: 总计 ${total} (输入 ${input}, 输出 ${output}, 缓存 ${cached})`;
|
|
27
|
+
}
|
|
28
|
+
return `• **Token Usage**: Total ${total} (Input ${input}, Output ${output}, Cached ${cached})`;
|
|
29
|
+
}
|
|
30
|
+
export function formatBackendTokenUsageBreakdown(usages) {
|
|
31
|
+
if (usages.length <= 1)
|
|
32
|
+
return '';
|
|
33
|
+
const labels = {
|
|
34
|
+
antigravity: 'AGY',
|
|
35
|
+
codex: 'Codex',
|
|
36
|
+
opencode: 'OpenCode',
|
|
37
|
+
};
|
|
38
|
+
const parts = usages
|
|
39
|
+
.filter((u) => u.totalTokens > 0)
|
|
40
|
+
.map((u) => `${labels[u.backendId] || u.backendId}: ${formatMetricTokenCount(u.totalTokens)}`);
|
|
41
|
+
if (parts.length <= 1)
|
|
42
|
+
return '';
|
|
43
|
+
return `\n └ ${parts.join(' · ')}`;
|
|
44
|
+
}
|
|
45
|
+
export async function syncCodexLocalUsageToStore(store, codexHome) {
|
|
46
|
+
try {
|
|
47
|
+
const stats = await readCodexLocalUsageStats(codexHome);
|
|
48
|
+
if (stats.totals.totalTokens > 0 || stats.turns > 0) {
|
|
49
|
+
store.setBackendCumulativeTokenUsage({
|
|
50
|
+
inputTokens: stats.totals.inputTokens,
|
|
51
|
+
outputTokens: stats.totals.outputTokens,
|
|
52
|
+
cachedTokens: stats.totals.cachedInputTokens,
|
|
53
|
+
totalTokens: stats.totals.totalTokens,
|
|
54
|
+
turnsCount: stats.turns,
|
|
55
|
+
}, 'codex');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Non-fatal if codex home is unavailable
|
|
60
|
+
}
|
|
61
|
+
}
|
package/dist/telegram/api.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface TelegramRemoteFile {
|
|
|
9
9
|
file_size?: number;
|
|
10
10
|
file_path?: string;
|
|
11
11
|
}
|
|
12
|
+
export declare function isTransientNetworkError(err: unknown): boolean;
|
|
12
13
|
export declare function callTelegramApi<T>(botToken: string, method: string, body: Record<string, unknown>): Promise<TelegramApiResult<T>>;
|
|
13
14
|
export declare function callTelegramMultipartApi<T>(botToken: string, method: string, fields: Record<string, string>, files: Array<{
|
|
14
15
|
fieldName: string;
|