@friendlyrobot/discord-pi-agent 0.22.0 → 0.22.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/dist/agent-turn-runner.js +12 -2
- package/dist/discord-message-handler.js +26 -19
- package/dist/discord-replies.js +29 -1
- package/package.json +1 -1
|
@@ -7,6 +7,7 @@ export async function runAgentTurn(session, prompt, options = {}) {
|
|
|
7
7
|
let eventCount = 0;
|
|
8
8
|
let toolCount = 0;
|
|
9
9
|
const toolInputsByCallId = new Map();
|
|
10
|
+
const pendingToolLifecycleTasks = new Set();
|
|
10
11
|
const model = session.model
|
|
11
12
|
? `${session.model.provider}/${session.model.id}`
|
|
12
13
|
: "none";
|
|
@@ -33,9 +34,13 @@ export async function runAgentTurn(session, prompt, options = {}) {
|
|
|
33
34
|
toolCount += 1;
|
|
34
35
|
const input = event.toolName === "bash" ? event.args.command : event.args;
|
|
35
36
|
toolInputsByCallId.set(event.toolCallId, input);
|
|
36
|
-
|
|
37
|
+
const onToolStartTask = Promise.resolve(options.onToolStart?.({
|
|
37
38
|
toolName: event.toolName,
|
|
38
39
|
toolCallId: event.toolCallId,
|
|
40
|
+
})).then(() => undefined);
|
|
41
|
+
pendingToolLifecycleTasks.add(onToolStartTask);
|
|
42
|
+
void onToolStartTask.finally(() => {
|
|
43
|
+
pendingToolLifecycleTasks.delete(onToolStartTask);
|
|
39
44
|
});
|
|
40
45
|
if (event.toolName === "bash") {
|
|
41
46
|
debugPrint(input, "CMD");
|
|
@@ -56,10 +61,14 @@ export async function runAgentTurn(session, prompt, options = {}) {
|
|
|
56
61
|
if (event.type === "tool_execution_end") {
|
|
57
62
|
const input = toolInputsByCallId.get(event.toolCallId);
|
|
58
63
|
toolInputsByCallId.delete(event.toolCallId);
|
|
59
|
-
|
|
64
|
+
const onToolEndTask = Promise.resolve(options.onToolEnd?.({
|
|
60
65
|
toolName: event.toolName,
|
|
61
66
|
toolCallId: event.toolCallId,
|
|
62
67
|
isError: event.isError,
|
|
68
|
+
})).then(() => undefined);
|
|
69
|
+
pendingToolLifecycleTasks.add(onToolEndTask);
|
|
70
|
+
void onToolEndTask.finally(() => {
|
|
71
|
+
pendingToolLifecycleTasks.delete(onToolEndTask);
|
|
63
72
|
});
|
|
64
73
|
if (event.toolName === "bash") {
|
|
65
74
|
debugPrint(extractToolOutput(event.result), event.isError ? "BASH TOOL ERROR OUTPUT" : "BASH TOOL OUTPUT");
|
|
@@ -97,6 +106,7 @@ export async function runAgentTurn(session, prompt, options = {}) {
|
|
|
97
106
|
});
|
|
98
107
|
try {
|
|
99
108
|
await session.prompt(prompt, { images: options.images });
|
|
109
|
+
await Promise.allSettled(Array.from(pendingToolLifecycleTasks));
|
|
100
110
|
}
|
|
101
111
|
finally {
|
|
102
112
|
unsubscribe();
|
|
@@ -154,33 +154,40 @@ async function processAgentPrompt(message, config, agentService, entry, prepared
|
|
|
154
154
|
await notifyIfPromptQueued(message, entry.promptQueue.getSnapshot().pending);
|
|
155
155
|
const toolEmojiByCallId = new Map();
|
|
156
156
|
const activeToolCountByEmoji = new Map();
|
|
157
|
+
let reactionOperationChain = Promise.resolve();
|
|
157
158
|
try {
|
|
158
159
|
const response = await entry.promptQueue.enqueue(async () => {
|
|
159
160
|
const promptInput = await buildPromptInput(message, config, agentService, entry, preparedMessage);
|
|
160
161
|
return runAgentTurn(entry.session, promptInput.prompt, {
|
|
161
162
|
images: promptInput.images,
|
|
162
163
|
onToolStart: async ({ toolName, toolCallId }) => {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
164
|
+
reactionOperationChain = reactionOperationChain.then(async () => {
|
|
165
|
+
const emoji = resolveToolReactionEmoji(toolName);
|
|
166
|
+
toolEmojiByCallId.set(toolCallId, emoji);
|
|
167
|
+
const activeCount = activeToolCountByEmoji.get(emoji) ?? 0;
|
|
168
|
+
activeToolCountByEmoji.set(emoji, activeCount + 1);
|
|
169
|
+
if (activeCount === 0) {
|
|
170
|
+
await addReaction(message, emoji);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
await reactionOperationChain;
|
|
170
174
|
},
|
|
171
175
|
onToolEnd: async ({ toolCallId }) => {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
176
|
+
reactionOperationChain = reactionOperationChain.then(async () => {
|
|
177
|
+
const emoji = toolEmojiByCallId.get(toolCallId);
|
|
178
|
+
if (!emoji) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
toolEmojiByCallId.delete(toolCallId);
|
|
182
|
+
const activeCount = activeToolCountByEmoji.get(emoji) ?? 0;
|
|
183
|
+
if (activeCount <= 1) {
|
|
184
|
+
activeToolCountByEmoji.delete(emoji);
|
|
185
|
+
await removeReaction(message, emoji);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
activeToolCountByEmoji.set(emoji, activeCount - 1);
|
|
189
|
+
});
|
|
190
|
+
await reactionOperationChain;
|
|
184
191
|
},
|
|
185
192
|
});
|
|
186
193
|
});
|
package/dist/discord-replies.js
CHANGED
|
@@ -35,6 +35,34 @@ function chunkByLines(text, maxSize) {
|
|
|
35
35
|
return chunks;
|
|
36
36
|
}
|
|
37
37
|
export const DEFAULT_WORKING_EMOJI = "⚙️";
|
|
38
|
+
function normalizeEmoji(value) {
|
|
39
|
+
return value.normalize("NFKC").replace(/\uFE0F/g, "");
|
|
40
|
+
}
|
|
41
|
+
function findReactionByEmoji(message, emoji) {
|
|
42
|
+
const directMatch = message.reactions.cache.get(emoji);
|
|
43
|
+
if (directMatch) {
|
|
44
|
+
return directMatch;
|
|
45
|
+
}
|
|
46
|
+
const normalizedEmoji = normalizeEmoji(emoji);
|
|
47
|
+
const normalizedMatch = Array.from(message.reactions.cache.entries()).find(([key, reaction]) => {
|
|
48
|
+
if (normalizeEmoji(String(key)) === normalizedEmoji) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
if (typeof reaction.emoji?.name === "string") {
|
|
52
|
+
return normalizeEmoji(reaction.emoji.name) === normalizedEmoji;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
})?.[1];
|
|
56
|
+
if (!normalizedMatch) {
|
|
57
|
+
logger.debug({
|
|
58
|
+
messageId: message.id,
|
|
59
|
+
emoji,
|
|
60
|
+
normalizedEmoji,
|
|
61
|
+
reactionKeys: Array.from(message.reactions.cache.keys()),
|
|
62
|
+
}, "reaction not found in cache");
|
|
63
|
+
}
|
|
64
|
+
return normalizedMatch;
|
|
65
|
+
}
|
|
38
66
|
export async function addReaction(message, emoji) {
|
|
39
67
|
try {
|
|
40
68
|
await message.react(emoji);
|
|
@@ -45,7 +73,7 @@ export async function addReaction(message, emoji) {
|
|
|
45
73
|
}
|
|
46
74
|
export async function removeReaction(message, emoji) {
|
|
47
75
|
try {
|
|
48
|
-
const reaction = message
|
|
76
|
+
const reaction = findReactionByEmoji(message, emoji);
|
|
49
77
|
if (reaction) {
|
|
50
78
|
await reaction.users.remove(message.client.user);
|
|
51
79
|
}
|