teleton 0.7.3 → 0.7.5
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/README.md +64 -35
- package/dist/{chunk-RBU6JXD3.js → chunk-2GLHOJ5C.js} +268 -59
- package/dist/chunk-5UVXJMOX.js +292 -0
- package/dist/{chunk-DAMCNMYL.js → chunk-AVDWXYQ7.js} +73 -28
- package/dist/{chunk-RMLQS3X6.js → chunk-CB2Y45HA.js} +106 -1
- package/dist/{chunk-5PLZ3KSO.js → chunk-DMXTIRUW.js} +5 -6
- package/dist/{chunk-A4GCOHCE.js → chunk-G2LLMJXJ.js} +1751 -116
- package/dist/{chunk-FNV5FF35.js → chunk-LCCVZ4D2.js} +32 -16
- package/dist/{chunk-BU453WX4.js → chunk-OGMVWDVU.js} +4172 -3792
- package/dist/chunk-QOQWUUA4.js +158 -0
- package/dist/{chunk-4DU3C27M.js → chunk-R4YSJ4EY.js} +5 -1
- package/dist/{chunk-XBKSS6DM.js → chunk-VFA7QMCZ.js} +5 -3
- package/dist/{chunk-VAUJSSD3.js → chunk-XQUHC3JZ.js} +1 -1
- package/dist/{chunk-RO62LO6Z.js → chunk-YP25WTQK.js} +2 -0
- package/dist/cli/index.js +234 -289
- package/dist/{client-RTNALK7W.js → client-O37XDCJB.js} +4 -5
- package/dist/index.js +12 -13
- package/dist/{memory-5SS3Q5EA.js → memory-KQALFUV3.js} +6 -7
- package/dist/{migrate-M7SJMDOL.js → migrate-UV3WEL5D.js} +6 -7
- package/dist/{server-FOC5P7U6.js → server-BHHJGUDF.js} +324 -16
- package/dist/{setup-server-BVVD2PR6.js → setup-server-G7UG2DI3.js} +26 -118
- package/dist/store-H4XPNGC2.js +34 -0
- package/dist/{task-dependency-resolver-WKZWJLLM.js → task-dependency-resolver-VMEVJRPO.js} +2 -2
- package/dist/{task-executor-PD3H4MLO.js → task-executor-WWSPBJ4V.js} +1 -1
- package/dist/{tool-index-MIVK3D7H.js → tool-index-2KH3OB6X.js} +5 -5
- package/dist/web/assets/index-BrVqauzj.css +1 -0
- package/dist/web/assets/index-Bx8JW3gV.js +72 -0
- package/dist/web/assets/{index.es-7MTSV5SL.js → index.es-Pet5-M13.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +3 -3
- package/dist/chunk-JQDLW7IE.js +0 -107
- package/dist/chunk-UCN6TI25.js +0 -143
- package/dist/web/assets/index-By_fs4Jl.js +0 -72
- package/dist/web/assets/index-CRDIf07k.css +0 -1
- package/scripts/patch-gramjs.sh +0 -46
- package/scripts/postinstall.mjs +0 -16
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getDatabase
|
|
3
|
+
} from "./chunk-2GLHOJ5C.js";
|
|
4
|
+
import {
|
|
5
|
+
createLogger
|
|
6
|
+
} from "./chunk-RCMD3U65.js";
|
|
7
|
+
|
|
8
|
+
// src/session/store.ts
|
|
9
|
+
import { randomUUID } from "crypto";
|
|
10
|
+
var log = createLogger("Session");
|
|
11
|
+
function getDb() {
|
|
12
|
+
return getDatabase().getDb();
|
|
13
|
+
}
|
|
14
|
+
function rowToSession(row) {
|
|
15
|
+
return {
|
|
16
|
+
sessionId: row.id,
|
|
17
|
+
chatId: row.chat_id,
|
|
18
|
+
createdAt: row.started_at,
|
|
19
|
+
updatedAt: row.updated_at,
|
|
20
|
+
messageCount: row.message_count || 0,
|
|
21
|
+
lastMessageId: row.last_message_id ?? void 0,
|
|
22
|
+
lastChannel: row.last_channel ?? void 0,
|
|
23
|
+
lastTo: row.last_to ?? void 0,
|
|
24
|
+
contextTokens: row.context_tokens ?? void 0,
|
|
25
|
+
model: row.model ?? void 0,
|
|
26
|
+
provider: row.provider ?? void 0,
|
|
27
|
+
lastResetDate: row.last_reset_date ?? void 0,
|
|
28
|
+
inputTokens: row.input_tokens ?? void 0,
|
|
29
|
+
outputTokens: row.output_tokens ?? void 0
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function loadSessionStore() {
|
|
33
|
+
try {
|
|
34
|
+
const db = getDb();
|
|
35
|
+
const rows = db.prepare("SELECT * FROM sessions").all();
|
|
36
|
+
const store = {};
|
|
37
|
+
for (const row of rows) {
|
|
38
|
+
const sessionKey = row.chat_id;
|
|
39
|
+
store[sessionKey] = rowToSession(row);
|
|
40
|
+
}
|
|
41
|
+
return store;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
log.warn({ err: error }, "Failed to load sessions from database");
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function saveSessionStore(store) {
|
|
48
|
+
try {
|
|
49
|
+
const db = getDb();
|
|
50
|
+
const insertStmt = db.prepare(`
|
|
51
|
+
INSERT INTO sessions (
|
|
52
|
+
id, chat_id, started_at, updated_at, message_count,
|
|
53
|
+
last_message_id, last_channel, last_to, context_tokens,
|
|
54
|
+
model, provider, last_reset_date, input_tokens, output_tokens
|
|
55
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
56
|
+
`);
|
|
57
|
+
db.transaction(() => {
|
|
58
|
+
db.prepare("DELETE FROM sessions").run();
|
|
59
|
+
for (const [chatId, session] of Object.entries(store)) {
|
|
60
|
+
insertStmt.run(
|
|
61
|
+
session.sessionId,
|
|
62
|
+
chatId,
|
|
63
|
+
session.createdAt,
|
|
64
|
+
session.updatedAt,
|
|
65
|
+
session.messageCount,
|
|
66
|
+
session.lastMessageId,
|
|
67
|
+
session.lastChannel,
|
|
68
|
+
session.lastTo,
|
|
69
|
+
session.contextTokens,
|
|
70
|
+
session.model,
|
|
71
|
+
session.provider,
|
|
72
|
+
session.lastResetDate,
|
|
73
|
+
session.inputTokens ?? 0,
|
|
74
|
+
session.outputTokens ?? 0
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
})();
|
|
78
|
+
} catch (error) {
|
|
79
|
+
log.error({ err: error }, "Failed to save sessions to database");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function getOrCreateSession(chatId) {
|
|
83
|
+
const db = getDb();
|
|
84
|
+
const sessionKey = `telegram:${chatId}`;
|
|
85
|
+
const row = db.prepare("SELECT * FROM sessions WHERE chat_id = ?").get(sessionKey);
|
|
86
|
+
if (row) {
|
|
87
|
+
return rowToSession(row);
|
|
88
|
+
}
|
|
89
|
+
const now = Date.now();
|
|
90
|
+
const newSession = {
|
|
91
|
+
sessionId: randomUUID(),
|
|
92
|
+
chatId,
|
|
93
|
+
createdAt: now,
|
|
94
|
+
updatedAt: now,
|
|
95
|
+
messageCount: 0,
|
|
96
|
+
lastChannel: "telegram",
|
|
97
|
+
lastTo: chatId
|
|
98
|
+
};
|
|
99
|
+
db.prepare(
|
|
100
|
+
`
|
|
101
|
+
INSERT INTO sessions (
|
|
102
|
+
id, chat_id, started_at, updated_at, message_count, last_channel, last_to
|
|
103
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
104
|
+
`
|
|
105
|
+
).run(
|
|
106
|
+
newSession.sessionId,
|
|
107
|
+
sessionKey,
|
|
108
|
+
newSession.createdAt,
|
|
109
|
+
newSession.updatedAt,
|
|
110
|
+
newSession.messageCount,
|
|
111
|
+
newSession.lastChannel,
|
|
112
|
+
newSession.lastTo
|
|
113
|
+
);
|
|
114
|
+
log.info(`New session created: ${newSession.sessionId} for chat ${chatId}`);
|
|
115
|
+
return newSession;
|
|
116
|
+
}
|
|
117
|
+
function updateSession(chatId, update) {
|
|
118
|
+
const db = getDb();
|
|
119
|
+
const sessionKey = `telegram:${chatId}`;
|
|
120
|
+
const existing = db.prepare("SELECT * FROM sessions WHERE chat_id = ?").get(sessionKey);
|
|
121
|
+
if (!existing) {
|
|
122
|
+
return getOrCreateSession(chatId);
|
|
123
|
+
}
|
|
124
|
+
const updates = [];
|
|
125
|
+
const values = [];
|
|
126
|
+
if (update.sessionId !== void 0) {
|
|
127
|
+
updates.push("id = ?");
|
|
128
|
+
values.push(update.sessionId);
|
|
129
|
+
}
|
|
130
|
+
if (update.messageCount !== void 0) {
|
|
131
|
+
updates.push("message_count = ?");
|
|
132
|
+
values.push(update.messageCount);
|
|
133
|
+
}
|
|
134
|
+
if (update.lastMessageId !== void 0) {
|
|
135
|
+
updates.push("last_message_id = ?");
|
|
136
|
+
values.push(update.lastMessageId);
|
|
137
|
+
}
|
|
138
|
+
if (update.lastChannel !== void 0) {
|
|
139
|
+
updates.push("last_channel = ?");
|
|
140
|
+
values.push(update.lastChannel);
|
|
141
|
+
}
|
|
142
|
+
if (update.lastTo !== void 0) {
|
|
143
|
+
updates.push("last_to = ?");
|
|
144
|
+
values.push(update.lastTo);
|
|
145
|
+
}
|
|
146
|
+
if (update.contextTokens !== void 0) {
|
|
147
|
+
updates.push("context_tokens = ?");
|
|
148
|
+
values.push(update.contextTokens);
|
|
149
|
+
}
|
|
150
|
+
if (update.model !== void 0) {
|
|
151
|
+
updates.push("model = ?");
|
|
152
|
+
values.push(update.model);
|
|
153
|
+
}
|
|
154
|
+
if (update.provider !== void 0) {
|
|
155
|
+
updates.push("provider = ?");
|
|
156
|
+
values.push(update.provider);
|
|
157
|
+
}
|
|
158
|
+
if (update.lastResetDate !== void 0) {
|
|
159
|
+
updates.push("last_reset_date = ?");
|
|
160
|
+
values.push(update.lastResetDate);
|
|
161
|
+
}
|
|
162
|
+
if (update.inputTokens !== void 0) {
|
|
163
|
+
updates.push("input_tokens = ?");
|
|
164
|
+
values.push(update.inputTokens);
|
|
165
|
+
}
|
|
166
|
+
if (update.outputTokens !== void 0) {
|
|
167
|
+
updates.push("output_tokens = ?");
|
|
168
|
+
values.push(update.outputTokens);
|
|
169
|
+
}
|
|
170
|
+
updates.push("updated_at = ?");
|
|
171
|
+
values.push(Date.now());
|
|
172
|
+
values.push(sessionKey);
|
|
173
|
+
db.prepare(
|
|
174
|
+
`
|
|
175
|
+
UPDATE sessions
|
|
176
|
+
SET ${updates.join(", ")}
|
|
177
|
+
WHERE chat_id = ?
|
|
178
|
+
`
|
|
179
|
+
).run(...values);
|
|
180
|
+
const updated = db.prepare("SELECT * FROM sessions WHERE chat_id = ?").get(sessionKey);
|
|
181
|
+
return rowToSession(updated);
|
|
182
|
+
}
|
|
183
|
+
function incrementMessageCount(chatId) {
|
|
184
|
+
const db = getDb();
|
|
185
|
+
const sessionKey = `telegram:${chatId}`;
|
|
186
|
+
const result = db.prepare(
|
|
187
|
+
`UPDATE sessions SET message_count = message_count + 1, updated_at = ? WHERE chat_id = ?`
|
|
188
|
+
).run(Date.now(), sessionKey);
|
|
189
|
+
if (result.changes === 0) {
|
|
190
|
+
getOrCreateSession(chatId);
|
|
191
|
+
db.prepare(
|
|
192
|
+
`UPDATE sessions SET message_count = message_count + 1, updated_at = ? WHERE chat_id = ?`
|
|
193
|
+
).run(Date.now(), sessionKey);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function getSession(chatId) {
|
|
197
|
+
const db = getDb();
|
|
198
|
+
const sessionKey = `telegram:${chatId}`;
|
|
199
|
+
const row = db.prepare("SELECT * FROM sessions WHERE chat_id = ?").get(sessionKey);
|
|
200
|
+
return row ? rowToSession(row) : null;
|
|
201
|
+
}
|
|
202
|
+
function resetSession(chatId) {
|
|
203
|
+
const oldSession = getSession(chatId);
|
|
204
|
+
const now = Date.now();
|
|
205
|
+
const newSession = {
|
|
206
|
+
sessionId: randomUUID(),
|
|
207
|
+
chatId,
|
|
208
|
+
createdAt: now,
|
|
209
|
+
updatedAt: now,
|
|
210
|
+
messageCount: 0,
|
|
211
|
+
lastChannel: oldSession?.lastChannel || "telegram",
|
|
212
|
+
lastTo: oldSession?.lastTo || chatId,
|
|
213
|
+
contextTokens: oldSession?.contextTokens,
|
|
214
|
+
model: oldSession?.model,
|
|
215
|
+
provider: oldSession?.provider
|
|
216
|
+
};
|
|
217
|
+
const db = getDb();
|
|
218
|
+
const sessionKey = `telegram:${chatId}`;
|
|
219
|
+
db.prepare(
|
|
220
|
+
`
|
|
221
|
+
UPDATE sessions
|
|
222
|
+
SET id = ?, started_at = ?, updated_at = ?, message_count = 0
|
|
223
|
+
WHERE chat_id = ?
|
|
224
|
+
`
|
|
225
|
+
).run(newSession.sessionId, newSession.createdAt, newSession.updatedAt, sessionKey);
|
|
226
|
+
log.info(`Session reset: ${oldSession?.sessionId} \u2192 ${newSession.sessionId}`);
|
|
227
|
+
return newSession;
|
|
228
|
+
}
|
|
229
|
+
function shouldResetSession(session, policy) {
|
|
230
|
+
const now = Date.now();
|
|
231
|
+
if (policy.daily_reset_enabled) {
|
|
232
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
233
|
+
const lastReset = session.lastResetDate || new Date(session.createdAt).toISOString().split("T")[0];
|
|
234
|
+
if (lastReset !== today) {
|
|
235
|
+
const currentHour = (/* @__PURE__ */ new Date()).getHours();
|
|
236
|
+
const resetHour = policy.daily_reset_hour;
|
|
237
|
+
if (lastReset < today && currentHour >= resetHour) {
|
|
238
|
+
log.info(
|
|
239
|
+
`Daily reset triggered for session ${session.sessionId} (last reset: ${lastReset})`
|
|
240
|
+
);
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (policy.idle_expiry_enabled) {
|
|
246
|
+
const idleMs = now - session.updatedAt;
|
|
247
|
+
const idleMinutes = idleMs / (1e3 * 60);
|
|
248
|
+
const expiryMinutes = policy.idle_expiry_minutes;
|
|
249
|
+
if (idleMinutes >= expiryMinutes) {
|
|
250
|
+
log.info(
|
|
251
|
+
`Idle expiry triggered for session ${session.sessionId} (idle: ${Math.floor(idleMinutes)}m)`
|
|
252
|
+
);
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
function resetSessionWithPolicy(chatId, policy) {
|
|
259
|
+
const newSession = resetSession(chatId);
|
|
260
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
261
|
+
return updateSession(chatId, {
|
|
262
|
+
lastResetDate: today
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
function pruneOldSessions(maxAgeDays = 30) {
|
|
266
|
+
try {
|
|
267
|
+
const db = getDb();
|
|
268
|
+
const cutoffMs = Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3;
|
|
269
|
+
const result = db.prepare(`DELETE FROM sessions WHERE updated_at < ? AND updated_at > 0`).run(cutoffMs);
|
|
270
|
+
const pruned = result.changes;
|
|
271
|
+
if (pruned > 0) {
|
|
272
|
+
log.info(`\u{1F5D1}\uFE0F Pruned ${pruned} session(s) older than ${maxAgeDays} days`);
|
|
273
|
+
}
|
|
274
|
+
return pruned;
|
|
275
|
+
} catch (error) {
|
|
276
|
+
log.warn({ err: error }, "Failed to prune old sessions");
|
|
277
|
+
return 0;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export {
|
|
282
|
+
loadSessionStore,
|
|
283
|
+
saveSessionStore,
|
|
284
|
+
getOrCreateSession,
|
|
285
|
+
updateSession,
|
|
286
|
+
incrementMessageCount,
|
|
287
|
+
getSession,
|
|
288
|
+
resetSession,
|
|
289
|
+
shouldResetSession,
|
|
290
|
+
resetSessionWithPolicy,
|
|
291
|
+
pruneOldSessions
|
|
292
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
COINGECKO_API_URL,
|
|
3
3
|
tonapiFetch
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-VFA7QMCZ.js";
|
|
5
5
|
import {
|
|
6
6
|
TELEGRAM_MAX_MESSAGE_LENGTH
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YP25WTQK.js";
|
|
8
8
|
import {
|
|
9
9
|
fetchWithTimeout
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-XQUHC3JZ.js";
|
|
11
11
|
import {
|
|
12
12
|
TELETON_ROOT,
|
|
13
13
|
WORKSPACE_PATHS,
|
|
@@ -17,20 +17,21 @@ import {
|
|
|
17
17
|
createLogger
|
|
18
18
|
} from "./chunk-RCMD3U65.js";
|
|
19
19
|
|
|
20
|
-
// src/ton/wallet-service.ts
|
|
21
|
-
import { mnemonicNew, mnemonicToPrivateKey, mnemonicValidate } from "@ton/crypto";
|
|
22
|
-
import { WalletContractV5R1, TonClient, fromNano } from "@ton/ton";
|
|
23
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
24
|
-
import { join, dirname } from "path";
|
|
25
|
-
|
|
26
20
|
// src/ton/endpoint.ts
|
|
27
21
|
var ENDPOINT_CACHE_TTL_MS = 6e4;
|
|
28
22
|
var ORBS_HOST = "ton.access.orbs.network";
|
|
29
23
|
var ORBS_TOPOLOGY_URL = `https://${ORBS_HOST}/mngr/nodes?npm_version=2.3.3`;
|
|
30
|
-
var
|
|
24
|
+
var TONCENTER_URL = `https://toncenter.com/api/v2/jsonRPC`;
|
|
31
25
|
var _cache = null;
|
|
26
|
+
var _toncenterApiKey;
|
|
27
|
+
function setToncenterApiKey(key) {
|
|
28
|
+
_toncenterApiKey = key;
|
|
29
|
+
}
|
|
30
|
+
function getToncenterApiKey() {
|
|
31
|
+
return _toncenterApiKey;
|
|
32
|
+
}
|
|
32
33
|
async function discoverOrbsEndpoint() {
|
|
33
|
-
const res = await fetch(ORBS_TOPOLOGY_URL);
|
|
34
|
+
const res = await fetch(ORBS_TOPOLOGY_URL, { signal: AbortSignal.timeout(5e3) });
|
|
34
35
|
const nodes = await res.json();
|
|
35
36
|
const healthy = nodes.filter(
|
|
36
37
|
(n) => n.Healthy === "1" && n.Weight > 0 && n.Mngr?.health?.["v2-mainnet"]
|
|
@@ -53,10 +54,28 @@ async function getCachedHttpEndpoint() {
|
|
|
53
54
|
return _cache.url;
|
|
54
55
|
}
|
|
55
56
|
let url;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
if (_toncenterApiKey) {
|
|
58
|
+
try {
|
|
59
|
+
const testUrl = `https://toncenter.com/api/v2/getAddressInformation?address=EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c`;
|
|
60
|
+
const res = await fetch(testUrl, {
|
|
61
|
+
headers: { "X-API-Key": _toncenterApiKey },
|
|
62
|
+
signal: AbortSignal.timeout(5e3)
|
|
63
|
+
});
|
|
64
|
+
if (!res.ok) throw new Error(`TonCenter ${res.status}`);
|
|
65
|
+
url = TONCENTER_URL;
|
|
66
|
+
} catch {
|
|
67
|
+
try {
|
|
68
|
+
url = await discoverOrbsEndpoint();
|
|
69
|
+
} catch {
|
|
70
|
+
url = TONCENTER_URL;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
try {
|
|
75
|
+
url = await discoverOrbsEndpoint();
|
|
76
|
+
} catch {
|
|
77
|
+
url = TONCENTER_URL;
|
|
78
|
+
}
|
|
60
79
|
}
|
|
61
80
|
_cache = { url, ts: Date.now() };
|
|
62
81
|
return url;
|
|
@@ -66,6 +85,10 @@ function invalidateEndpointCache() {
|
|
|
66
85
|
}
|
|
67
86
|
|
|
68
87
|
// src/ton/wallet-service.ts
|
|
88
|
+
import { mnemonicNew, mnemonicToPrivateKey, mnemonicValidate } from "@ton/crypto";
|
|
89
|
+
import { WalletContractV5R1, TonClient, fromNano } from "@ton/ton";
|
|
90
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
91
|
+
import { join, dirname } from "path";
|
|
69
92
|
var log = createLogger("TON");
|
|
70
93
|
var WALLET_FILE = join(TELETON_ROOT, "wallet.json");
|
|
71
94
|
var _walletCache;
|
|
@@ -147,7 +170,8 @@ async function getCachedTonClient() {
|
|
|
147
170
|
if (_tonClientCache && _tonClientCache.endpoint === endpoint) {
|
|
148
171
|
return _tonClientCache.client;
|
|
149
172
|
}
|
|
150
|
-
const
|
|
173
|
+
const apiKey = getToncenterApiKey();
|
|
174
|
+
const client = new TonClient({ endpoint, ...apiKey && { apiKey } });
|
|
151
175
|
_tonClientCache = { client, endpoint };
|
|
152
176
|
return client;
|
|
153
177
|
}
|
|
@@ -217,8 +241,8 @@ async function getTonPrice() {
|
|
|
217
241
|
|
|
218
242
|
// src/config/schema.ts
|
|
219
243
|
import { z } from "zod";
|
|
220
|
-
var DMPolicy = z.enum(["
|
|
221
|
-
var GroupPolicy = z.enum(["open", "allowlist", "disabled"]);
|
|
244
|
+
var DMPolicy = z.enum(["allowlist", "open", "admin-only", "disabled"]);
|
|
245
|
+
var GroupPolicy = z.enum(["open", "allowlist", "admin-only", "disabled"]);
|
|
222
246
|
var SessionResetPolicySchema = z.object({
|
|
223
247
|
daily_reset_enabled: z.boolean().default(true).describe("Enable daily session reset"),
|
|
224
248
|
daily_reset_hour: z.number().min(0).max(23).default(4).describe("Hour of day (0-23) to reset sessions"),
|
|
@@ -255,7 +279,7 @@ var TelegramConfigSchema = z.object({
|
|
|
255
279
|
phone: z.string(),
|
|
256
280
|
session_name: z.string().default("teleton_session"),
|
|
257
281
|
session_path: z.string().default("~/.teleton"),
|
|
258
|
-
dm_policy: DMPolicy.default("
|
|
282
|
+
dm_policy: DMPolicy.default("allowlist"),
|
|
259
283
|
allow_from: z.array(z.number()).default([]),
|
|
260
284
|
group_policy: GroupPolicy.default("open"),
|
|
261
285
|
group_allow_from: z.array(z.number()).default([]),
|
|
@@ -275,7 +299,6 @@ var TelegramConfigSchema = z.object({
|
|
|
275
299
|
});
|
|
276
300
|
var StorageConfigSchema = z.object({
|
|
277
301
|
sessions_file: z.string().default("~/.teleton/sessions.json"),
|
|
278
|
-
pairing_file: z.string().default("~/.teleton/pairing.json"),
|
|
279
302
|
memory_file: z.string().default("~/.teleton/memory.json"),
|
|
280
303
|
history_limit: z.number().default(100)
|
|
281
304
|
});
|
|
@@ -288,7 +311,7 @@ var MetaConfigSchema = z.object({
|
|
|
288
311
|
var _DealsObject = z.object({
|
|
289
312
|
enabled: z.boolean().default(true),
|
|
290
313
|
expiry_seconds: z.number().default(120),
|
|
291
|
-
buy_max_floor_percent: z.number().default(
|
|
314
|
+
buy_max_floor_percent: z.number().default(95),
|
|
292
315
|
sell_min_floor_percent: z.number().default(105),
|
|
293
316
|
poll_interval_ms: z.number().default(5e3),
|
|
294
317
|
max_verification_retries: z.number().default(12),
|
|
@@ -333,7 +356,7 @@ var _McpObject = z.object({
|
|
|
333
356
|
});
|
|
334
357
|
var McpConfigSchema = _McpObject.default(_McpObject.parse({}));
|
|
335
358
|
var _ToolRagObject = z.object({
|
|
336
|
-
enabled: z.boolean().default(
|
|
359
|
+
enabled: z.boolean().default(true).describe("Enable semantic tool retrieval (Tool RAG)"),
|
|
337
360
|
top_k: z.number().default(25).describe("Max tools to retrieve per LLM call"),
|
|
338
361
|
always_include: z.array(z.string()).default([
|
|
339
362
|
"telegram_send_message",
|
|
@@ -347,6 +370,24 @@ var _ToolRagObject = z.object({
|
|
|
347
370
|
skip_unlimited_providers: z.boolean().default(false).describe("Skip Tool RAG for providers with no tool limit (e.g. Anthropic)")
|
|
348
371
|
});
|
|
349
372
|
var ToolRagConfigSchema = _ToolRagObject.default(_ToolRagObject.parse({}));
|
|
373
|
+
var _ExecLimitsObject = z.object({
|
|
374
|
+
timeout: z.number().min(1).max(3600).default(120).describe("Max seconds per command execution"),
|
|
375
|
+
max_output: z.number().min(1e3).max(5e5).default(5e4).describe("Max chars of stdout/stderr captured per command")
|
|
376
|
+
});
|
|
377
|
+
var _ExecAuditObject = z.object({
|
|
378
|
+
log_commands: z.boolean().default(true).describe("Log every command to SQLite audit table")
|
|
379
|
+
});
|
|
380
|
+
var _ExecObject = z.object({
|
|
381
|
+
mode: z.enum(["off", "yolo"]).default("off").describe("Exec mode: off (disabled) or yolo (full system access)"),
|
|
382
|
+
scope: z.enum(["admin-only", "allowlist", "all"]).default("admin-only").describe("Who can trigger exec tools"),
|
|
383
|
+
allowlist: z.array(z.number()).default([]).describe("Telegram user IDs allowed to use exec (when scope = allowlist)"),
|
|
384
|
+
limits: _ExecLimitsObject.default(_ExecLimitsObject.parse({})),
|
|
385
|
+
audit: _ExecAuditObject.default(_ExecAuditObject.parse({}))
|
|
386
|
+
});
|
|
387
|
+
var _CapabilitiesObject = z.object({
|
|
388
|
+
exec: _ExecObject.default(_ExecObject.parse({}))
|
|
389
|
+
});
|
|
390
|
+
var CapabilitiesConfigSchema = _CapabilitiesObject.default(_CapabilitiesObject.parse({}));
|
|
350
391
|
var ConfigSchema = z.object({
|
|
351
392
|
meta: MetaConfigSchema.default(MetaConfigSchema.parse({})),
|
|
352
393
|
agent: AgentConfigSchema,
|
|
@@ -358,12 +399,14 @@ var ConfigSchema = z.object({
|
|
|
358
399
|
logging: LoggingConfigSchema,
|
|
359
400
|
dev: DevConfigSchema,
|
|
360
401
|
tool_rag: ToolRagConfigSchema,
|
|
402
|
+
capabilities: CapabilitiesConfigSchema,
|
|
361
403
|
mcp: McpConfigSchema,
|
|
362
404
|
plugins: z.record(z.string(), z.unknown()).default({}).describe("Per-plugin config (key = plugin name with underscores)"),
|
|
363
405
|
cocoon: z.object({
|
|
364
406
|
port: z.number().min(1).max(65535).default(1e4).describe("HTTP port of the cocoon-cli proxy")
|
|
365
407
|
}).optional().describe("Cocoon Network \u2014 expects external cocoon-cli running on this port"),
|
|
366
408
|
tonapi_key: z.string().optional().describe("TonAPI key for higher rate limits (from @tonapi_bot)"),
|
|
409
|
+
toncenter_api_key: z.string().optional().describe("TonCenter API key for dedicated RPC endpoint (free at https://toncenter.com)"),
|
|
367
410
|
tavily_api_key: z.string().optional().describe("Tavily API key for web search & extract (free at https://tavily.com)")
|
|
368
411
|
});
|
|
369
412
|
|
|
@@ -382,13 +425,14 @@ function findPackageRoot() {
|
|
|
382
425
|
}
|
|
383
426
|
var TEMPLATES_DIR = join2(findPackageRoot(), "src", "templates");
|
|
384
427
|
async function ensureWorkspace(config) {
|
|
428
|
+
const silent = config?.silent ?? false;
|
|
385
429
|
if (!existsSync2(TELETON_ROOT)) {
|
|
386
430
|
mkdirSync2(TELETON_ROOT, { recursive: true });
|
|
387
|
-
log2.info(`Created Teleton root at ${TELETON_ROOT}`);
|
|
431
|
+
if (!silent) log2.info(`Created Teleton root at ${TELETON_ROOT}`);
|
|
388
432
|
}
|
|
389
433
|
if (!existsSync2(WORKSPACE_ROOT)) {
|
|
390
434
|
mkdirSync2(WORKSPACE_ROOT, { recursive: true });
|
|
391
|
-
log2.info(`Created workspace at ${WORKSPACE_ROOT}`);
|
|
435
|
+
if (!silent) log2.info(`Created workspace at ${WORKSPACE_ROOT}`);
|
|
392
436
|
}
|
|
393
437
|
const directories = [
|
|
394
438
|
WORKSPACE_PATHS.MEMORY_DIR,
|
|
@@ -424,11 +468,11 @@ async function ensureWorkspace(config) {
|
|
|
424
468
|
walletPath: join2(TELETON_ROOT, "wallet.json")
|
|
425
469
|
};
|
|
426
470
|
if (config?.ensureTemplates) {
|
|
427
|
-
await bootstrapTemplates(workspace);
|
|
471
|
+
await bootstrapTemplates(workspace, silent);
|
|
428
472
|
}
|
|
429
473
|
return workspace;
|
|
430
474
|
}
|
|
431
|
-
async function bootstrapTemplates(workspace) {
|
|
475
|
+
async function bootstrapTemplates(workspace, silent = false) {
|
|
432
476
|
const templates = [
|
|
433
477
|
{ name: "SOUL.md", path: workspace.soulPath },
|
|
434
478
|
{ name: "MEMORY.md", path: workspace.memoryPath },
|
|
@@ -442,7 +486,7 @@ async function bootstrapTemplates(workspace) {
|
|
|
442
486
|
const templateSource = join2(TEMPLATES_DIR, template.name);
|
|
443
487
|
if (existsSync2(templateSource)) {
|
|
444
488
|
copyFileSync(templateSource, template.path);
|
|
445
|
-
log2.info(`Created ${template.name}`);
|
|
489
|
+
if (!silent) log2.info(`Created ${template.name}`);
|
|
446
490
|
}
|
|
447
491
|
}
|
|
448
492
|
}
|
|
@@ -464,7 +508,8 @@ export {
|
|
|
464
508
|
ensureWorkspace,
|
|
465
509
|
isNewWorkspace,
|
|
466
510
|
loadTemplate,
|
|
467
|
-
|
|
511
|
+
setToncenterApiKey,
|
|
512
|
+
invalidateEndpointCache,
|
|
468
513
|
generateWallet,
|
|
469
514
|
saveWallet,
|
|
470
515
|
loadWallet,
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createLogger
|
|
3
|
+
} from "./chunk-RCMD3U65.js";
|
|
4
|
+
|
|
1
5
|
// src/config/providers.ts
|
|
2
6
|
var PROVIDER_REGISTRY = {
|
|
3
7
|
anthropic: {
|
|
@@ -154,8 +158,109 @@ function validateApiKeyFormat(provider, key) {
|
|
|
154
158
|
return void 0;
|
|
155
159
|
}
|
|
156
160
|
|
|
161
|
+
// src/providers/claude-code-credentials.ts
|
|
162
|
+
import { readFileSync, existsSync } from "fs";
|
|
163
|
+
import { execSync } from "child_process";
|
|
164
|
+
import { homedir } from "os";
|
|
165
|
+
import { join } from "path";
|
|
166
|
+
var log = createLogger("ClaudeCodeCreds");
|
|
167
|
+
var cachedToken = null;
|
|
168
|
+
var cachedExpiresAt = 0;
|
|
169
|
+
function getClaudeConfigDir() {
|
|
170
|
+
return process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude");
|
|
171
|
+
}
|
|
172
|
+
function getCredentialsFilePath() {
|
|
173
|
+
return join(getClaudeConfigDir(), ".credentials.json");
|
|
174
|
+
}
|
|
175
|
+
function readCredentialsFile() {
|
|
176
|
+
const filePath = getCredentialsFilePath();
|
|
177
|
+
if (!existsSync(filePath)) return null;
|
|
178
|
+
try {
|
|
179
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
180
|
+
return JSON.parse(raw);
|
|
181
|
+
} catch (e) {
|
|
182
|
+
log.warn({ err: e, path: filePath }, "Failed to parse Claude Code credentials file");
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function readKeychainCredentials() {
|
|
187
|
+
const serviceNames = ["Claude Code-credentials", "Claude Code"];
|
|
188
|
+
for (const service of serviceNames) {
|
|
189
|
+
try {
|
|
190
|
+
const raw = execSync(`security find-generic-password -s "${service}" -w`, {
|
|
191
|
+
encoding: "utf-8",
|
|
192
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
193
|
+
}).trim();
|
|
194
|
+
return JSON.parse(raw);
|
|
195
|
+
} catch {
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
function readCredentials() {
|
|
201
|
+
if (process.platform === "darwin") {
|
|
202
|
+
const keychainCreds = readKeychainCredentials();
|
|
203
|
+
if (keychainCreds) return keychainCreds;
|
|
204
|
+
log.debug("Keychain read failed, falling back to credentials file");
|
|
205
|
+
}
|
|
206
|
+
return readCredentialsFile();
|
|
207
|
+
}
|
|
208
|
+
function extractToken(creds) {
|
|
209
|
+
const oauth = creds.claudeAiOauth;
|
|
210
|
+
if (!oauth?.accessToken) {
|
|
211
|
+
log.warn("Claude Code credentials found but missing accessToken");
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
token: oauth.accessToken,
|
|
216
|
+
expiresAt: oauth.expiresAt ?? 0
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function getClaudeCodeApiKey(fallbackKey) {
|
|
220
|
+
if (cachedToken && Date.now() < cachedExpiresAt) {
|
|
221
|
+
return cachedToken;
|
|
222
|
+
}
|
|
223
|
+
const creds = readCredentials();
|
|
224
|
+
if (creds) {
|
|
225
|
+
const extracted = extractToken(creds);
|
|
226
|
+
if (extracted) {
|
|
227
|
+
cachedToken = extracted.token;
|
|
228
|
+
cachedExpiresAt = extracted.expiresAt;
|
|
229
|
+
log.debug("Claude Code credentials loaded successfully");
|
|
230
|
+
return cachedToken;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (fallbackKey && fallbackKey.length > 0) {
|
|
234
|
+
log.warn("Claude Code credentials not found, using fallback api_key from config");
|
|
235
|
+
return fallbackKey;
|
|
236
|
+
}
|
|
237
|
+
throw new Error("No Claude Code credentials found. Run 'claude login' or set api_key in config.");
|
|
238
|
+
}
|
|
239
|
+
function refreshClaudeCodeApiKey() {
|
|
240
|
+
cachedToken = null;
|
|
241
|
+
cachedExpiresAt = 0;
|
|
242
|
+
const creds = readCredentials();
|
|
243
|
+
if (creds) {
|
|
244
|
+
const extracted = extractToken(creds);
|
|
245
|
+
if (extracted) {
|
|
246
|
+
cachedToken = extracted.token;
|
|
247
|
+
cachedExpiresAt = extracted.expiresAt;
|
|
248
|
+
log.info("Claude Code credentials refreshed from disk");
|
|
249
|
+
return cachedToken;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
log.warn("Failed to refresh Claude Code credentials from disk");
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
function isClaudeCodeTokenValid() {
|
|
256
|
+
return cachedToken !== null && Date.now() < cachedExpiresAt;
|
|
257
|
+
}
|
|
258
|
+
|
|
157
259
|
export {
|
|
158
260
|
getProviderMetadata,
|
|
159
261
|
getSupportedProviders,
|
|
160
|
-
validateApiKeyFormat
|
|
262
|
+
validateApiKeyFormat,
|
|
263
|
+
getClaudeCodeApiKey,
|
|
264
|
+
refreshClaudeCodeApiKey,
|
|
265
|
+
isClaudeCodeTokenValid
|
|
161
266
|
};
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getClaudeCodeApiKey,
|
|
3
|
+
getProviderMetadata,
|
|
3
4
|
refreshClaudeCodeApiKey
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import {
|
|
6
|
-
getProviderMetadata
|
|
7
|
-
} from "./chunk-RMLQS3X6.js";
|
|
5
|
+
} from "./chunk-CB2Y45HA.js";
|
|
8
6
|
import {
|
|
9
7
|
appendToTranscript,
|
|
10
8
|
readTranscript
|
|
11
9
|
} from "./chunk-OCLG5GKI.js";
|
|
12
10
|
import {
|
|
13
11
|
fetchWithTimeout
|
|
14
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XQUHC3JZ.js";
|
|
15
13
|
import {
|
|
16
14
|
createLogger
|
|
17
15
|
} from "./chunk-RCMD3U65.js";
|
|
@@ -306,7 +304,8 @@ async function chatWithContext(config, options) {
|
|
|
306
304
|
apiKey: getEffectiveApiKey(provider, config.api_key),
|
|
307
305
|
maxTokens: options.maxTokens ?? config.max_tokens,
|
|
308
306
|
temperature,
|
|
309
|
-
sessionId: options.sessionId
|
|
307
|
+
sessionId: options.sessionId,
|
|
308
|
+
cacheRetention: "long"
|
|
310
309
|
};
|
|
311
310
|
if (isCocoon) {
|
|
312
311
|
const { stripCocoonPayload } = await import("./tool-adapter-Y3TCEQOC.js");
|