talon-agent 3.33.0 → 3.33.2
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/package.json +3 -3
- package/src/backend/kilo/factory.ts +39 -119
- package/src/backend/kilo/handler/index.ts +1 -11
- package/src/backend/kilo/handler/message.ts +20 -317
- package/src/backend/kilo/server.ts +55 -272
- package/src/backend/kilo/sessions.ts +5 -83
- package/src/backend/opencode/factory.ts +41 -118
- package/src/backend/opencode/handler/index.ts +1 -11
- package/src/backend/opencode/handler/message.ts +20 -321
- package/src/backend/opencode/server.ts +57 -217
- package/src/backend/opencode/sessions.ts +5 -83
- package/src/backend/remote-server/chat-turn.ts +359 -0
- package/src/backend/remote-server/factory.ts +150 -0
- package/src/backend/remote-server/index.ts +14 -19
- package/src/backend/remote-server/server-bindings.ts +232 -0
- package/src/backend/{kilo/handler → remote-server}/turn.ts +103 -67
- package/src/core/mesh/bridge-links.ts +319 -0
- package/src/core/mesh/common.ts +30 -0
- package/src/core/mesh/device-files.ts +710 -0
- package/src/core/mesh/service.ts +72 -894
- package/src/frontend/discord/handlers/access.ts +7 -56
- package/src/frontend/discord/handlers/state.ts +15 -8
- package/src/frontend/native/server.ts +391 -323
- package/src/frontend/shared/access.ts +152 -0
- package/src/frontend/telegram/handlers/access.ts +8 -25
- package/src/frontend/telegram/handlers/queue.ts +3 -35
- package/src/frontend/telegram/handlers/state.ts +15 -8
- package/src/backend/kilo/events.ts +0 -60
- package/src/backend/kilo/handler/state.ts +0 -9
- package/src/backend/opencode/handler/state.ts +0 -9
- package/src/backend/opencode/handler/turn.ts +0 -314
|
@@ -6,19 +6,13 @@
|
|
|
6
6
|
|
|
7
7
|
import type { Client, Message } from "discord.js";
|
|
8
8
|
import { ChannelType } from "discord.js";
|
|
9
|
-
import {
|
|
10
|
-
import { log, logWarn, logDebug } from "../../../util/log.js";
|
|
9
|
+
import { logWarn } from "../../../util/log.js";
|
|
11
10
|
import { escapeMarkdown } from "../formatting.js";
|
|
12
11
|
import {
|
|
13
12
|
accessState,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
UNAUTHORIZED_COOLDOWN_MS,
|
|
18
|
-
MAX_UNAUTHORIZED_COOLDOWNS,
|
|
19
|
-
userMessageTimestamps,
|
|
20
|
-
RATE_LIMIT_WINDOW_MS,
|
|
21
|
-
RATE_LIMIT_MAX_MESSAGES,
|
|
13
|
+
dmUsers,
|
|
14
|
+
unauthorizedNotices,
|
|
15
|
+
rateLimiter,
|
|
22
16
|
} from "./state.js";
|
|
23
17
|
|
|
24
18
|
export function setAccessControl(cfg: {
|
|
@@ -46,21 +40,7 @@ export function trackDmUser(
|
|
|
46
40
|
senderName: string,
|
|
47
41
|
tag?: string,
|
|
48
42
|
): void {
|
|
49
|
-
|
|
50
|
-
if (knownDmUsers.size >= KNOWN_DM_USERS_CAP) {
|
|
51
|
-
const evictCount = Math.floor(KNOWN_DM_USERS_CAP * 0.1);
|
|
52
|
-
const iter = knownDmUsers.values();
|
|
53
|
-
for (let i = 0; i < evictCount; i++) {
|
|
54
|
-
knownDmUsers.delete(iter.next().value as string);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
knownDmUsers.add(senderId);
|
|
58
|
-
const tagStr = tag ? ` (${tag})` : "";
|
|
59
|
-
log("users", `New DM user: ${senderName}${tagStr} [id:${senderId}]`);
|
|
60
|
-
appendDailyLog(
|
|
61
|
-
"System",
|
|
62
|
-
`New DM user: ${senderName}${tagStr} [id:${senderId}]`,
|
|
63
|
-
);
|
|
43
|
+
dmUsers.track(senderId, senderName, tag);
|
|
64
44
|
}
|
|
65
45
|
|
|
66
46
|
async function notifyUnauthorized(
|
|
@@ -77,13 +57,7 @@ async function notifyUnauthorized(
|
|
|
77
57
|
: type === "guild"
|
|
78
58
|
? `guild:${guildId}`
|
|
79
59
|
: `channel:${channelId}`;
|
|
80
|
-
|
|
81
|
-
const last = unauthorizedCooldown.get(key);
|
|
82
|
-
if (last && now - last < UNAUTHORIZED_COOLDOWN_MS) return;
|
|
83
|
-
if (unauthorizedCooldown.size >= MAX_UNAUTHORIZED_COOLDOWNS) {
|
|
84
|
-
unauthorizedCooldown.clear();
|
|
85
|
-
}
|
|
86
|
-
unauthorizedCooldown.set(key, now);
|
|
60
|
+
if (!unauthorizedNotices.shouldNotify(key)) return;
|
|
87
61
|
|
|
88
62
|
const senderTag = msg.author.username ? ` (@${msg.author.username})` : "";
|
|
89
63
|
const senderName = msg.author.globalName || msg.author.username || "User";
|
|
@@ -216,28 +190,5 @@ export function shouldHandleInGuild(client: Client, msg: Message): boolean {
|
|
|
216
190
|
}
|
|
217
191
|
|
|
218
192
|
export function isUserRateLimited(senderId: string): boolean {
|
|
219
|
-
|
|
220
|
-
let timestamps = userMessageTimestamps.get(senderId);
|
|
221
|
-
if (!timestamps) {
|
|
222
|
-
timestamps = [];
|
|
223
|
-
userMessageTimestamps.set(senderId, timestamps);
|
|
224
|
-
}
|
|
225
|
-
while (timestamps.length > 0 && timestamps[0] < now - RATE_LIMIT_WINDOW_MS) {
|
|
226
|
-
timestamps.shift();
|
|
227
|
-
}
|
|
228
|
-
if (timestamps.length >= RATE_LIMIT_MAX_MESSAGES) {
|
|
229
|
-
logDebug("bot", `Rate-limited user ${senderId}`);
|
|
230
|
-
return true;
|
|
231
|
-
}
|
|
232
|
-
timestamps.push(now);
|
|
233
|
-
if (userMessageTimestamps.size > 5_000) {
|
|
234
|
-
const cutoff = now - 10 * 60_000;
|
|
235
|
-
for (const [userId, ts] of userMessageTimestamps) {
|
|
236
|
-
if (ts.length === 0 || ts[ts.length - 1] < cutoff) {
|
|
237
|
-
userMessageTimestamps.delete(userId);
|
|
238
|
-
}
|
|
239
|
-
if (userMessageTimestamps.size <= 2_500) break;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
return false;
|
|
193
|
+
return rateLimiter.isLimited(senderId);
|
|
243
194
|
}
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
import type { TextBasedChannel } from "discord.js";
|
|
9
9
|
import type { TalonConfig } from "../../../util/config.js";
|
|
10
|
+
import {
|
|
11
|
+
createDmUserTracker,
|
|
12
|
+
createNoticeCooldown,
|
|
13
|
+
createRateLimiter,
|
|
14
|
+
} from "../../shared/access.js";
|
|
10
15
|
|
|
11
16
|
// ── Chat registry: numericChatId → Discord channel info ─────────────────────
|
|
12
17
|
// The gateway/dispatcher uses numeric chatIds. Action handlers need to map
|
|
@@ -49,20 +54,22 @@ export const accessState: { access: AccessConfig } = {
|
|
|
49
54
|
|
|
50
55
|
// ── First-time DM user tracking ──────────────────────────────────────────────
|
|
51
56
|
|
|
52
|
-
export const
|
|
53
|
-
export const KNOWN_DM_USERS_CAP = 10_000;
|
|
57
|
+
export const dmUsers = createDmUserTracker<string>(10_000);
|
|
54
58
|
|
|
55
59
|
// ── Unauthorized notification cooldown (10 min) ──────────────────────────────
|
|
56
60
|
|
|
57
|
-
export const
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
export const unauthorizedNotices = createNoticeCooldown({
|
|
62
|
+
ttlMs: 10 * 60 * 1000,
|
|
63
|
+
cap: 5000,
|
|
64
|
+
});
|
|
60
65
|
|
|
61
66
|
// ── Per-user rate limiting ───────────────────────────────────────────────────
|
|
62
67
|
|
|
63
|
-
|
|
64
|
-
export const
|
|
65
|
-
|
|
68
|
+
/** 15 messages per minute per user. */
|
|
69
|
+
export const rateLimiter = createRateLimiter<string>({
|
|
70
|
+
windowMs: 60_000,
|
|
71
|
+
maxMessages: 15,
|
|
72
|
+
});
|
|
66
73
|
|
|
67
74
|
// ── Message queue (debounce rapid-fire messages per chat) ────────────────────
|
|
68
75
|
|