agent4discord 0.1.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/README.ko.md +134 -0
- package/README.md +170 -0
- package/dist/bot.d.ts +1 -0
- package/dist/bot.js +114 -0
- package/dist/bot.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +27 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/index.d.ts +9 -0
- package/dist/commands/index.js +44 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.js +152 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/model.d.ts +5 -0
- package/dist/commands/model.js +65 -0
- package/dist/commands/model.js.map +1 -0
- package/dist/commands/resume.d.ts +6 -0
- package/dist/commands/resume.js +113 -0
- package/dist/commands/resume.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.js +49 -0
- package/dist/config.js.map +1 -0
- package/dist/formatters/chunker.d.ts +5 -0
- package/dist/formatters/chunker.js +46 -0
- package/dist/formatters/chunker.js.map +1 -0
- package/dist/formatters/embedBuilder.d.ts +28 -0
- package/dist/formatters/embedBuilder.js +32 -0
- package/dist/formatters/embedBuilder.js.map +1 -0
- package/dist/formatters/toolFormatter.d.ts +4 -0
- package/dist/formatters/toolFormatter.js +90 -0
- package/dist/formatters/toolFormatter.js.map +1 -0
- package/dist/guild.d.ts +22 -0
- package/dist/guild.js +41 -0
- package/dist/guild.js.map +1 -0
- package/dist/interactions/directoryBrowser.d.ts +61 -0
- package/dist/interactions/directoryBrowser.js +611 -0
- package/dist/interactions/directoryBrowser.js.map +1 -0
- package/dist/interactions/index.d.ts +5 -0
- package/dist/interactions/index.js +92 -0
- package/dist/interactions/index.js.map +1 -0
- package/dist/interactions/permissionHandler.d.ts +11 -0
- package/dist/interactions/permissionHandler.js +107 -0
- package/dist/interactions/permissionHandler.js.map +1 -0
- package/dist/interactions/sessionControls.d.ts +9 -0
- package/dist/interactions/sessionControls.js +95 -0
- package/dist/interactions/sessionControls.js.map +1 -0
- package/dist/sessions/eventHandler.d.ts +3 -0
- package/dist/sessions/eventHandler.js +209 -0
- package/dist/sessions/eventHandler.js.map +1 -0
- package/dist/sessions/sessionManager.d.ts +29 -0
- package/dist/sessions/sessionManager.js +203 -0
- package/dist/sessions/sessionManager.js.map +1 -0
- package/dist/sessions/sessionStore.d.ts +4 -0
- package/dist/sessions/sessionStore.js +29 -0
- package/dist/sessions/sessionStore.js.map +1 -0
- package/dist/sessions/streamHandler.d.ts +18 -0
- package/dist/sessions/streamHandler.js +119 -0
- package/dist/sessions/streamHandler.js.map +1 -0
- package/dist/sessions/toolProgress.d.ts +14 -0
- package/dist/sessions/toolProgress.js +65 -0
- package/dist/sessions/toolProgress.js.map +1 -0
- package/dist/sessions/usageTracker.d.ts +12 -0
- package/dist/sessions/usageTracker.js +222 -0
- package/dist/sessions/usageTracker.js.map +1 -0
- package/dist/setup.d.ts +1 -0
- package/dist/setup.js +101 -0
- package/dist/setup.js.map +1 -0
- package/dist/utils/filesystem.d.ts +11 -0
- package/dist/utils/filesystem.js +26 -0
- package/dist/utils/filesystem.js.map +1 -0
- package/dist/utils/logger.d.ts +1 -0
- package/dist/utils/logger.js +3 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/plugins.d.ts +6 -0
- package/dist/utils/plugins.js +66 -0
- package/dist/utils/plugins.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// Session lifecycle -- AGE-016
|
|
2
|
+
import { EventEmitter } from 'node:events';
|
|
3
|
+
import { query, } from '@anthropic-ai/claude-agent-sdk';
|
|
4
|
+
import { resolvePlugins } from '../utils/plugins.js';
|
|
5
|
+
class SessionManager extends EventEmitter {
|
|
6
|
+
sessions = new Map();
|
|
7
|
+
createSession(guildId, userId, channelId, cwd, model, canUseTool) {
|
|
8
|
+
const controller = new AbortController();
|
|
9
|
+
let resolveNext = null;
|
|
10
|
+
async function* messageStream() {
|
|
11
|
+
while (true) {
|
|
12
|
+
const msg = await new Promise((resolve) => {
|
|
13
|
+
resolveNext = resolve;
|
|
14
|
+
});
|
|
15
|
+
yield msg;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const plugins = resolvePlugins();
|
|
19
|
+
const q = query({
|
|
20
|
+
prompt: messageStream(),
|
|
21
|
+
options: {
|
|
22
|
+
cwd,
|
|
23
|
+
model: model || 'opus',
|
|
24
|
+
permissionMode: 'default',
|
|
25
|
+
includePartialMessages: true,
|
|
26
|
+
abortController: controller,
|
|
27
|
+
canUseTool,
|
|
28
|
+
plugins,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
const session = {
|
|
32
|
+
query: q,
|
|
33
|
+
channelId,
|
|
34
|
+
guildId,
|
|
35
|
+
userId,
|
|
36
|
+
sessionId: '',
|
|
37
|
+
cwd,
|
|
38
|
+
state: 'running',
|
|
39
|
+
totalCostUsd: 0,
|
|
40
|
+
createdAt: new Date().toISOString(),
|
|
41
|
+
resolveNext: null,
|
|
42
|
+
abortController: controller,
|
|
43
|
+
};
|
|
44
|
+
// Wire up resolveNext -- the generator captures the outer variable,
|
|
45
|
+
// but ActiveSession needs its own reference so sendMessage can call it.
|
|
46
|
+
// Because the generator closure mutates the local `resolveNext`, we
|
|
47
|
+
// need a proxy that always reads the latest value.
|
|
48
|
+
Object.defineProperty(session, 'resolveNext', {
|
|
49
|
+
get: () => resolveNext,
|
|
50
|
+
set: (v) => {
|
|
51
|
+
resolveNext = v;
|
|
52
|
+
},
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
});
|
|
56
|
+
this.sessions.set(channelId, session);
|
|
57
|
+
void this._processEvents(session);
|
|
58
|
+
return session;
|
|
59
|
+
}
|
|
60
|
+
resumeSession(guildId, userId, channelId, sessionId, cwd, model, canUseTool) {
|
|
61
|
+
const controller = new AbortController();
|
|
62
|
+
let resolveNext = null;
|
|
63
|
+
async function* messageStream() {
|
|
64
|
+
while (true) {
|
|
65
|
+
const msg = await new Promise((resolve) => {
|
|
66
|
+
resolveNext = resolve;
|
|
67
|
+
});
|
|
68
|
+
yield msg;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const plugins = resolvePlugins();
|
|
72
|
+
const q = query({
|
|
73
|
+
prompt: messageStream(),
|
|
74
|
+
options: {
|
|
75
|
+
cwd,
|
|
76
|
+
model: model || 'opus',
|
|
77
|
+
permissionMode: 'default',
|
|
78
|
+
includePartialMessages: true,
|
|
79
|
+
abortController: controller,
|
|
80
|
+
resume: sessionId,
|
|
81
|
+
canUseTool,
|
|
82
|
+
plugins,
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
const session = {
|
|
86
|
+
query: q,
|
|
87
|
+
channelId,
|
|
88
|
+
guildId,
|
|
89
|
+
userId,
|
|
90
|
+
sessionId,
|
|
91
|
+
cwd,
|
|
92
|
+
state: 'running',
|
|
93
|
+
totalCostUsd: 0,
|
|
94
|
+
createdAt: new Date().toISOString(),
|
|
95
|
+
resolveNext: null,
|
|
96
|
+
abortController: controller,
|
|
97
|
+
};
|
|
98
|
+
Object.defineProperty(session, 'resolveNext', {
|
|
99
|
+
get: () => resolveNext,
|
|
100
|
+
set: (v) => {
|
|
101
|
+
resolveNext = v;
|
|
102
|
+
},
|
|
103
|
+
enumerable: true,
|
|
104
|
+
configurable: true,
|
|
105
|
+
});
|
|
106
|
+
this.sessions.set(channelId, session);
|
|
107
|
+
void this._processEvents(session);
|
|
108
|
+
return session;
|
|
109
|
+
}
|
|
110
|
+
sendMessage(channelId, content) {
|
|
111
|
+
const session = this.sessions.get(channelId);
|
|
112
|
+
if (!session) {
|
|
113
|
+
throw new Error(`No session found for channel ${channelId}`);
|
|
114
|
+
}
|
|
115
|
+
if (session.state === 'stopped' || session.state === 'archived') {
|
|
116
|
+
throw new Error(`Session for channel ${channelId} is ${session.state}`);
|
|
117
|
+
}
|
|
118
|
+
session.state = 'running';
|
|
119
|
+
if (session.resolveNext) {
|
|
120
|
+
session.resolveNext({
|
|
121
|
+
type: 'user',
|
|
122
|
+
message: { role: 'user', content },
|
|
123
|
+
parent_tool_use_id: null,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
getSession(channelId) {
|
|
128
|
+
return this.sessions.get(channelId) ?? null;
|
|
129
|
+
}
|
|
130
|
+
stopSession(channelId) {
|
|
131
|
+
const session = this.sessions.get(channelId);
|
|
132
|
+
if (!session)
|
|
133
|
+
return;
|
|
134
|
+
session.query.close();
|
|
135
|
+
session.state = 'stopped';
|
|
136
|
+
}
|
|
137
|
+
removeSession(channelId) {
|
|
138
|
+
const session = this.sessions.get(channelId);
|
|
139
|
+
if (!session)
|
|
140
|
+
return;
|
|
141
|
+
if (session.state !== 'stopped' && session.state !== 'archived') {
|
|
142
|
+
this.stopSession(channelId);
|
|
143
|
+
}
|
|
144
|
+
this.sessions.delete(channelId);
|
|
145
|
+
}
|
|
146
|
+
getAllSessions() {
|
|
147
|
+
return [...this.sessions.values()];
|
|
148
|
+
}
|
|
149
|
+
async _processEvents(session) {
|
|
150
|
+
try {
|
|
151
|
+
for await (const msg of session.query) {
|
|
152
|
+
// Log all non-stream messages for debugging
|
|
153
|
+
if (msg.type !== 'stream_event' && msg.type !== 'tool_progress') {
|
|
154
|
+
console.log(`[sdk:${msg.type}]`, JSON.stringify(msg, null, 2).slice(0, 500));
|
|
155
|
+
}
|
|
156
|
+
switch (msg.type) {
|
|
157
|
+
case 'system': {
|
|
158
|
+
const sysMsg = msg;
|
|
159
|
+
if (sysMsg.subtype === 'init' && sysMsg.session_id) {
|
|
160
|
+
session.sessionId = sysMsg.session_id;
|
|
161
|
+
}
|
|
162
|
+
session.state = 'idle';
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case 'assistant': {
|
|
166
|
+
this.emit('assistant', session.channelId, msg);
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
case 'result': {
|
|
170
|
+
const resultMsg = msg;
|
|
171
|
+
console.log(`[sdk:result] subtype=${resultMsg.subtype}, cost=$${resultMsg.total_cost_usd}`);
|
|
172
|
+
session.totalCostUsd = resultMsg.total_cost_usd ?? session.totalCostUsd;
|
|
173
|
+
session.state = 'idle';
|
|
174
|
+
this.emit('result', session.channelId, resultMsg);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
case 'stream_event':
|
|
178
|
+
this.emit('stream_event', session.channelId, msg);
|
|
179
|
+
break;
|
|
180
|
+
case 'tool_progress':
|
|
181
|
+
this.emit('tool_progress', session.channelId, msg);
|
|
182
|
+
break;
|
|
183
|
+
default: {
|
|
184
|
+
// Handle rate_limit_event
|
|
185
|
+
const anyMsg = msg;
|
|
186
|
+
if (anyMsg.type === 'rate_limit_event' && anyMsg.rate_limit_info) {
|
|
187
|
+
console.log('[sdk:rate_limit]', JSON.stringify(anyMsg.rate_limit_info));
|
|
188
|
+
this.emit('rate_limit', session.guildId, anyMsg.rate_limit_info);
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
console.error(`[session] Event processing error for channel ${session.channelId}:`, err);
|
|
197
|
+
session.state = 'stopped';
|
|
198
|
+
this.emit('error', session.channelId, err);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
export const sessionManager = new SessionManager();
|
|
203
|
+
//# sourceMappingURL=sessionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionManager.js","sourceRoot":"","sources":["../../src/sessions/sessionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type SessionEntry } from '../guild.js';
|
|
2
|
+
export declare function saveSessionToGuild(guildId: string, channelId: string, sessionId: string, cwd: string, userId: string): void;
|
|
3
|
+
export declare function removeSessionFromGuild(guildId: string, channelId: string): void;
|
|
4
|
+
export declare function getSessionsForGuild(guildId: string): Record<string, SessionEntry>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Persist session metadata to guild config -- AGE-016
|
|
2
|
+
import { loadGuildConfig, saveGuildConfig, } from '../guild.js';
|
|
3
|
+
export function saveSessionToGuild(guildId, channelId, sessionId, cwd, userId) {
|
|
4
|
+
const config = loadGuildConfig(guildId);
|
|
5
|
+
if (!config) {
|
|
6
|
+
throw new Error(`Guild config not found for guild ${guildId}`);
|
|
7
|
+
}
|
|
8
|
+
config.activeSessions[channelId] = {
|
|
9
|
+
sessionId,
|
|
10
|
+
cwd,
|
|
11
|
+
createdAt: new Date().toISOString(),
|
|
12
|
+
userId,
|
|
13
|
+
};
|
|
14
|
+
saveGuildConfig(config);
|
|
15
|
+
}
|
|
16
|
+
export function removeSessionFromGuild(guildId, channelId) {
|
|
17
|
+
const config = loadGuildConfig(guildId);
|
|
18
|
+
if (!config)
|
|
19
|
+
return;
|
|
20
|
+
delete config.activeSessions[channelId];
|
|
21
|
+
saveGuildConfig(config);
|
|
22
|
+
}
|
|
23
|
+
export function getSessionsForGuild(guildId) {
|
|
24
|
+
const config = loadGuildConfig(guildId);
|
|
25
|
+
if (!config)
|
|
26
|
+
return {};
|
|
27
|
+
return config.activeSessions;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=sessionStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionStore.js","sourceRoot":"","sources":["../../src/sessions/sessionStore.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,EACL,eAAe,EACf,eAAe,GAEhB,MAAM,aAAa,CAAC;AAErB,MAAM,UAAU,kBAAkB,CAChC,OAAe,EACf,SAAiB,EACjB,SAAiB,EACjB,GAAW,EACX,MAAc;IAEd,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oCAAoC,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG;QACjC,SAAS;QACT,GAAG;QACH,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,MAAM;KACP,CAAC;IAEF,eAAe,CAAC,MAAM,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,OAAe,EACf,SAAiB;IAEjB,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,OAAO,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACxC,eAAe,CAAC,MAAM,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAe;IAEf,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC,cAAc,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type TextChannel } from 'discord.js';
|
|
2
|
+
export declare class StreamHandler {
|
|
3
|
+
private channel;
|
|
4
|
+
private buffer;
|
|
5
|
+
private tokenCount;
|
|
6
|
+
private startTime;
|
|
7
|
+
private messageId;
|
|
8
|
+
private timer;
|
|
9
|
+
private debounceMs;
|
|
10
|
+
private type;
|
|
11
|
+
private finalized;
|
|
12
|
+
constructor(channel: TextChannel, type: 'text' | 'thinking', debounceMs?: number);
|
|
13
|
+
push(text: string): void;
|
|
14
|
+
private flush;
|
|
15
|
+
private sendOrEdit;
|
|
16
|
+
finalize(): Promise<void>;
|
|
17
|
+
getMessageId(): string | null;
|
|
18
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { EmbedBuilder } from 'discord.js';
|
|
2
|
+
import { COLORS } from '../formatters/embedBuilder.js';
|
|
3
|
+
export class StreamHandler {
|
|
4
|
+
channel;
|
|
5
|
+
buffer = '';
|
|
6
|
+
tokenCount = 0;
|
|
7
|
+
startTime = Date.now();
|
|
8
|
+
messageId = null;
|
|
9
|
+
timer = null;
|
|
10
|
+
debounceMs;
|
|
11
|
+
type;
|
|
12
|
+
finalized = false;
|
|
13
|
+
constructor(channel, type, debounceMs) {
|
|
14
|
+
this.channel = channel;
|
|
15
|
+
this.type = type;
|
|
16
|
+
this.debounceMs = debounceMs ?? (type === 'text' ? 1000 : 2000);
|
|
17
|
+
}
|
|
18
|
+
push(text) {
|
|
19
|
+
this.buffer += text;
|
|
20
|
+
this.tokenCount++;
|
|
21
|
+
if (!this.timer) {
|
|
22
|
+
this.timer = setTimeout(() => void this.flush(), this.debounceMs);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async flush() {
|
|
26
|
+
this.timer = null;
|
|
27
|
+
const elapsed = ((Date.now() - this.startTime) / 1000).toFixed(1);
|
|
28
|
+
if (this.type === 'text') {
|
|
29
|
+
// Streaming text: yellow embed with accumulated text
|
|
30
|
+
const description = this.buffer.length > 4090 ? this.buffer.slice(-4090) + '...' : this.buffer;
|
|
31
|
+
const embed = new EmbedBuilder()
|
|
32
|
+
.setTitle('Responding...')
|
|
33
|
+
.setDescription(description)
|
|
34
|
+
.setColor(COLORS.STREAMING)
|
|
35
|
+
.setFooter({ text: `${elapsed}s \u00b7 ${this.tokenCount} tokens` });
|
|
36
|
+
await this.sendOrEdit(embed);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// Thinking: purple embed with only token count and time
|
|
40
|
+
const embed = new EmbedBuilder()
|
|
41
|
+
.setTitle('Thinking...')
|
|
42
|
+
.setColor(COLORS.THINKING)
|
|
43
|
+
.setFooter({ text: `${elapsed}s \u00b7 ${this.tokenCount} tokens` });
|
|
44
|
+
await this.sendOrEdit(embed);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async sendOrEdit(embed) {
|
|
48
|
+
try {
|
|
49
|
+
if (this.messageId) {
|
|
50
|
+
const msg = await this.channel.messages.fetch(this.messageId).catch(() => null);
|
|
51
|
+
if (msg) {
|
|
52
|
+
await msg.edit({ embeds: [embed] });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const msg = await this.channel.send({ embeds: [embed] });
|
|
57
|
+
this.messageId = msg.id;
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.error('[stream] Failed to update embed:', err);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async finalize() {
|
|
64
|
+
if (this.finalized)
|
|
65
|
+
return;
|
|
66
|
+
this.finalized = true;
|
|
67
|
+
// Clear any pending timer
|
|
68
|
+
if (this.timer) {
|
|
69
|
+
clearTimeout(this.timer);
|
|
70
|
+
this.timer = null;
|
|
71
|
+
}
|
|
72
|
+
const elapsed = ((Date.now() - this.startTime) / 1000).toFixed(1);
|
|
73
|
+
if (this.type === 'text') {
|
|
74
|
+
// Replace streaming embed with plain message(s)
|
|
75
|
+
if (this.messageId) {
|
|
76
|
+
try {
|
|
77
|
+
const msg = await this.channel.messages.fetch(this.messageId).catch(() => null);
|
|
78
|
+
if (msg)
|
|
79
|
+
await msg.delete().catch(() => { });
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
/* best-effort */
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Send as plain text, chunked if needed
|
|
86
|
+
if (this.buffer.length > 0) {
|
|
87
|
+
const { chunkMessage } = await import('../formatters/chunker.js');
|
|
88
|
+
const chunks = chunkMessage(this.buffer);
|
|
89
|
+
for (const chunk of chunks) {
|
|
90
|
+
await this.channel.send(chunk);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Thinking: finalize embed with "Thought for Xs"
|
|
96
|
+
const embed = new EmbedBuilder()
|
|
97
|
+
.setTitle(`Thought for ${elapsed}s`)
|
|
98
|
+
.setColor(COLORS.THINKING)
|
|
99
|
+
.setFooter({ text: `${this.tokenCount} tokens` });
|
|
100
|
+
if (this.messageId) {
|
|
101
|
+
try {
|
|
102
|
+
const msg = await this.channel.messages.fetch(this.messageId).catch(() => null);
|
|
103
|
+
if (msg) {
|
|
104
|
+
await msg.edit({ embeds: [embed] });
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
/* best-effort */
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
await this.channel.send({ embeds: [embed] });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
getMessageId() {
|
|
116
|
+
return this.messageId;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=streamHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamHandler.js","sourceRoot":"","sources":["../../src/sessions/streamHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAoB,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAEvD,MAAM,OAAO,aAAa;IAChB,OAAO,CAAc;IACrB,MAAM,GAAG,EAAE,CAAC;IACZ,UAAU,GAAG,CAAC,CAAC;IACf,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,SAAS,GAAkB,IAAI,CAAC;IAChC,KAAK,GAAyC,IAAI,CAAC;IACnD,UAAU,CAAS;IACnB,IAAI,CAAsB;IAC1B,SAAS,GAAG,KAAK,CAAC;IAE1B,YAAY,OAAoB,EAAE,IAAyB,EAAE,UAAmB;QAC9E,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,CAAC,IAAY;QACf,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;QACpB,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,KAAK;QACjB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAElE,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,qDAAqD;YACrD,MAAM,WAAW,GACf,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;YAC7E,MAAM,KAAK,GAAG,IAAI,YAAY,EAAE;iBAC7B,QAAQ,CAAC,eAAe,CAAC;iBACzB,cAAc,CAAC,WAAW,CAAC;iBAC3B,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;iBAC1B,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,OAAO,YAAY,IAAI,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC;YAEvE,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,wDAAwD;YACxD,MAAM,KAAK,GAAG,IAAI,YAAY,EAAE;iBAC7B,QAAQ,CAAC,aAAa,CAAC;iBACvB,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;iBACzB,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,OAAO,YAAY,IAAI,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC;YAEvE,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,KAAmB;QAC1C,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;gBAChF,IAAI,GAAG,EAAE,CAAC;oBACR,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBACpC,OAAO;gBACT,CAAC;YACH,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACzD,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,EAAE,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAEtB,0BAA0B;QAC1B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAElE,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,gDAAgD;YAChD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;oBAChF,IAAI,GAAG;wBAAE,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBAC9C,CAAC;gBAAC,MAAM,CAAC;oBACP,iBAAiB;gBACnB,CAAC;YACH,CAAC;YACD,wCAAwC;YACxC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;gBAClE,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBAC3B,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,iDAAiD;YACjD,MAAM,KAAK,GAAG,IAAI,YAAY,EAAE;iBAC7B,QAAQ,CAAC,eAAe,OAAO,GAAG,CAAC;iBACnC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;iBACzB,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC;YAEpD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;oBAChF,IAAI,GAAG,EAAE,CAAC;wBACR,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;wBACpC,OAAO;oBACT,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,iBAAiB;gBACnB,CAAC;YACH,CAAC;YACD,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type TextChannel } from 'discord.js';
|
|
2
|
+
export declare class ToolProgressHandler {
|
|
3
|
+
private channel;
|
|
4
|
+
private messageId;
|
|
5
|
+
private startTime;
|
|
6
|
+
private timer;
|
|
7
|
+
private toolName;
|
|
8
|
+
constructor(channel: TextChannel, toolName: string);
|
|
9
|
+
update(): void;
|
|
10
|
+
private flush;
|
|
11
|
+
private sendOrEdit;
|
|
12
|
+
finalize(): Promise<void>;
|
|
13
|
+
getMessageId(): string | null;
|
|
14
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { EmbedBuilder } from 'discord.js';
|
|
2
|
+
import { COLORS } from '../formatters/embedBuilder.js';
|
|
3
|
+
export class ToolProgressHandler {
|
|
4
|
+
channel;
|
|
5
|
+
messageId = null;
|
|
6
|
+
startTime = Date.now();
|
|
7
|
+
timer = null;
|
|
8
|
+
toolName;
|
|
9
|
+
constructor(channel, toolName) {
|
|
10
|
+
this.channel = channel;
|
|
11
|
+
this.toolName = toolName;
|
|
12
|
+
}
|
|
13
|
+
update() {
|
|
14
|
+
// Debounce at ~3s
|
|
15
|
+
if (!this.timer) {
|
|
16
|
+
this.timer = setTimeout(() => void this.flush(), 3000);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async flush() {
|
|
20
|
+
this.timer = null;
|
|
21
|
+
const elapsed = ((Date.now() - this.startTime) / 1000).toFixed(1);
|
|
22
|
+
const embed = new EmbedBuilder()
|
|
23
|
+
.setTitle(`Executing: ${this.toolName}`)
|
|
24
|
+
.setColor(COLORS.TOOL_PROGRESS)
|
|
25
|
+
.setFooter({ text: `${elapsed}s` });
|
|
26
|
+
await this.sendOrEdit(embed);
|
|
27
|
+
}
|
|
28
|
+
async sendOrEdit(embed) {
|
|
29
|
+
try {
|
|
30
|
+
if (this.messageId) {
|
|
31
|
+
const msg = await this.channel.messages.fetch(this.messageId).catch(() => null);
|
|
32
|
+
if (msg) {
|
|
33
|
+
await msg.edit({ embeds: [embed] });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const msg = await this.channel.send({ embeds: [embed] });
|
|
38
|
+
this.messageId = msg.id;
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
console.error('[tool-progress] Failed to update embed:', err);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async finalize() {
|
|
45
|
+
if (this.timer) {
|
|
46
|
+
clearTimeout(this.timer);
|
|
47
|
+
this.timer = null;
|
|
48
|
+
}
|
|
49
|
+
// Delete the progress embed (tool result will replace it)
|
|
50
|
+
if (this.messageId) {
|
|
51
|
+
try {
|
|
52
|
+
const msg = await this.channel.messages.fetch(this.messageId).catch(() => null);
|
|
53
|
+
if (msg)
|
|
54
|
+
await msg.delete().catch(() => { });
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
/* best-effort */
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
getMessageId() {
|
|
62
|
+
return this.messageId;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=toolProgress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolProgress.js","sourceRoot":"","sources":["../../src/sessions/toolProgress.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { EmbedBuilder, type Client } from 'discord.js';
|
|
2
|
+
import type { SDKRateLimitInfo } from '@anthropic-ai/claude-agent-sdk';
|
|
3
|
+
interface RateLimitState {
|
|
4
|
+
fiveHour?: SDKRateLimitInfo;
|
|
5
|
+
sevenDayOpus?: SDKRateLimitInfo;
|
|
6
|
+
sevenDaySonnet?: SDKRateLimitInfo;
|
|
7
|
+
sevenDay?: SDKRateLimitInfo;
|
|
8
|
+
lastUpdated: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function buildUsageEmbed(state?: RateLimitState): EmbedBuilder;
|
|
11
|
+
export declare function setupUsageTracker(client: Client): void;
|
|
12
|
+
export {};
|