@friendlyrobot/discord-pi-agent 0.19.14 → 0.19.16
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/discord-replies.d.ts +9 -5
- package/dist/index.js +102 -16
- package/dist/session-commands.d.ts +4 -0
- package/dist/session-registry.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { Message } from "discord.js";
|
|
2
|
-
export declare
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
export declare const DEFAULT_WORKING_EMOJI = "\u2699\uFE0F";
|
|
3
|
+
export declare function addWorkingReaction(message: Message, emoji?: string): Promise<void>;
|
|
4
|
+
export declare function removeWorkingReaction(message: Message, emoji?: string): Promise<void>;
|
|
5
|
+
export declare function sendReply(message: Message, text: string): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Sends a command response wrapped in triple backticks.
|
|
8
|
+
* Splits by newlines so each chunk stays within Discord's 2000-char limit.
|
|
9
|
+
*/
|
|
10
|
+
export declare function sendCommandReply(message: Message, text: string): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -727,6 +727,7 @@ async function handleHelpCommand(trimmedInput, context) {
|
|
|
727
727
|
"!compact - compact the persistent session",
|
|
728
728
|
"!reset-session - start a fresh persistent session",
|
|
729
729
|
"!reload - reload resources (AGENTS.md, extensions, skills, etc.)",
|
|
730
|
+
"!reaction - show or set the working reaction emoji",
|
|
730
731
|
extraCommands,
|
|
731
732
|
"Any other text goes to the agent session."
|
|
732
733
|
].filter(Boolean).join(`
|
|
@@ -887,6 +888,32 @@ async function handleResetSessionCommand(trimmedInput, context) {
|
|
|
887
888
|
})
|
|
888
889
|
};
|
|
889
890
|
}
|
|
891
|
+
async function handleReactionCommand(trimmedInput, _context) {
|
|
892
|
+
if (trimmedInput !== "!reaction" && !trimmedInput.startsWith("!reaction ")) {
|
|
893
|
+
return null;
|
|
894
|
+
}
|
|
895
|
+
const parts = trimmedInput.split(" ");
|
|
896
|
+
if (parts.length === 1) {
|
|
897
|
+
return {
|
|
898
|
+
handled: true,
|
|
899
|
+
response: `Current working reaction: ${_context.workingEmoji}
|
|
900
|
+
` + `Usage: !reaction <emoji> to change it.
|
|
901
|
+
` + `Examples: !reaction \uD83D\uDD04 or !reaction ⏳`
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
const emoji = parts.slice(1).join(" ").trim();
|
|
905
|
+
if (!emoji) {
|
|
906
|
+
return {
|
|
907
|
+
handled: true,
|
|
908
|
+
response: "Please provide an emoji. Example: !reaction \uD83D\uDD04"
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
return {
|
|
912
|
+
handled: true,
|
|
913
|
+
workingEmoji: emoji,
|
|
914
|
+
response: `Working reaction emoji set to ${emoji}`
|
|
915
|
+
};
|
|
916
|
+
}
|
|
890
917
|
var commandHandlers = [
|
|
891
918
|
handleHelpCommand,
|
|
892
919
|
handleArchiveCommand,
|
|
@@ -895,7 +922,8 @@ var commandHandlers = [
|
|
|
895
922
|
handleModelCommand,
|
|
896
923
|
handleCompactCommand,
|
|
897
924
|
handleReloadCommand,
|
|
898
|
-
handleResetSessionCommand
|
|
925
|
+
handleResetSessionCommand,
|
|
926
|
+
handleReactionCommand
|
|
899
927
|
];
|
|
900
928
|
async function executeSessionCommand(input, context) {
|
|
901
929
|
const trimmedInput = input.trim();
|
|
@@ -1122,17 +1150,45 @@ function chunkMessage(text, maxChunkSize = SAFE_MESSAGE_LIMIT) {
|
|
|
1122
1150
|
|
|
1123
1151
|
// src/discord-replies.ts
|
|
1124
1152
|
var logger7 = createModuleLogger("discord-replies");
|
|
1125
|
-
var
|
|
1126
|
-
|
|
1153
|
+
var DISCORD_MESSAGE_LIMIT2 = 2000;
|
|
1154
|
+
var FENCE_OVERHEAD = 8;
|
|
1155
|
+
var MAX_CODE_FENCE_CONTENT = DISCORD_MESSAGE_LIMIT2 - FENCE_OVERHEAD;
|
|
1156
|
+
function chunkByLines(text, maxSize) {
|
|
1157
|
+
const lines = text.split(`
|
|
1158
|
+
`);
|
|
1159
|
+
const chunks = [];
|
|
1160
|
+
let current = "";
|
|
1161
|
+
for (const line of lines) {
|
|
1162
|
+
const candidate = current ? current + `
|
|
1163
|
+
` + line : line;
|
|
1164
|
+
if (candidate.length > maxSize) {
|
|
1165
|
+
if (current) {
|
|
1166
|
+
chunks.push(current);
|
|
1167
|
+
current = line;
|
|
1168
|
+
} else {
|
|
1169
|
+
chunks.push(line.slice(0, maxSize));
|
|
1170
|
+
current = line.slice(maxSize);
|
|
1171
|
+
}
|
|
1172
|
+
} else {
|
|
1173
|
+
current = candidate;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
if (current) {
|
|
1177
|
+
chunks.push(current);
|
|
1178
|
+
}
|
|
1179
|
+
return chunks;
|
|
1180
|
+
}
|
|
1181
|
+
var DEFAULT_WORKING_EMOJI = "⚙️";
|
|
1182
|
+
async function addWorkingReaction(message, emoji = DEFAULT_WORKING_EMOJI) {
|
|
1127
1183
|
try {
|
|
1128
|
-
await message.react(
|
|
1184
|
+
await message.react(emoji);
|
|
1129
1185
|
} catch (error) {
|
|
1130
1186
|
logger7.debug({ messageId: message.id, error }, "failed to add working reaction");
|
|
1131
1187
|
}
|
|
1132
1188
|
}
|
|
1133
|
-
async function removeWorkingReaction(message) {
|
|
1189
|
+
async function removeWorkingReaction(message, emoji = DEFAULT_WORKING_EMOJI) {
|
|
1134
1190
|
try {
|
|
1135
|
-
const reaction = message.reactions.cache.get(
|
|
1191
|
+
const reaction = message.reactions.cache.get(emoji);
|
|
1136
1192
|
if (reaction) {
|
|
1137
1193
|
await reaction.users.remove(message.client.user);
|
|
1138
1194
|
}
|
|
@@ -1140,7 +1196,7 @@ async function removeWorkingReaction(message) {
|
|
|
1140
1196
|
logger7.debug({ messageId: message.id, error }, "failed to remove working reaction");
|
|
1141
1197
|
}
|
|
1142
1198
|
}
|
|
1143
|
-
async function sendReply(message, text
|
|
1199
|
+
async function sendReply(message, text) {
|
|
1144
1200
|
const channel = message.channel;
|
|
1145
1201
|
if (!channel.isSendable()) {
|
|
1146
1202
|
logger7.debug({
|
|
@@ -1148,10 +1204,7 @@ async function sendReply(message, text, opts) {
|
|
|
1148
1204
|
}, "reply skipped, channel not sendable");
|
|
1149
1205
|
return;
|
|
1150
1206
|
}
|
|
1151
|
-
const
|
|
1152
|
-
${c}
|
|
1153
|
-
\`\`\`` : (c) => c;
|
|
1154
|
-
const chunks = chunkMessage(text).map(wrap);
|
|
1207
|
+
const chunks = chunkMessage(text);
|
|
1155
1208
|
const [firstChunk, ...remainingChunks] = chunks;
|
|
1156
1209
|
if (!firstChunk) {
|
|
1157
1210
|
return;
|
|
@@ -1168,6 +1221,33 @@ ${c}
|
|
|
1168
1221
|
}, "send reply failed");
|
|
1169
1222
|
}
|
|
1170
1223
|
}
|
|
1224
|
+
async function sendCommandReply(message, text) {
|
|
1225
|
+
const channel = message.channel;
|
|
1226
|
+
if (!channel.isSendable()) {
|
|
1227
|
+
logger7.debug({
|
|
1228
|
+
messageId: message.id
|
|
1229
|
+
}, "command reply skipped, channel not sendable");
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
const chunks = chunkByLines(text, MAX_CODE_FENCE_CONTENT).map((c) => `\`\`\`
|
|
1233
|
+
${c}
|
|
1234
|
+
\`\`\``);
|
|
1235
|
+
const [firstChunk, ...remainingChunks] = chunks;
|
|
1236
|
+
if (!firstChunk) {
|
|
1237
|
+
return;
|
|
1238
|
+
}
|
|
1239
|
+
try {
|
|
1240
|
+
await message.reply(firstChunk);
|
|
1241
|
+
for (const chunk of remainingChunks) {
|
|
1242
|
+
await channel.send(chunk);
|
|
1243
|
+
}
|
|
1244
|
+
} catch (error) {
|
|
1245
|
+
logger7.error({
|
|
1246
|
+
messageId: message.id,
|
|
1247
|
+
error
|
|
1248
|
+
}, "send command reply failed");
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1171
1251
|
|
|
1172
1252
|
// src/media-description.ts
|
|
1173
1253
|
var logger8 = createModuleLogger("media-description");
|
|
@@ -1533,10 +1613,15 @@ ${attachment.content}`;
|
|
|
1533
1613
|
const commandResult = await executeSessionCommand(content, {
|
|
1534
1614
|
agentService,
|
|
1535
1615
|
promptQueue,
|
|
1536
|
-
session
|
|
1616
|
+
session,
|
|
1617
|
+
workingEmoji: entry.workingEmoji
|
|
1537
1618
|
});
|
|
1538
1619
|
if (commandResult.handled) {
|
|
1539
1620
|
stopTypingForChannel(channelKey);
|
|
1621
|
+
if (commandResult.workingEmoji) {
|
|
1622
|
+
entry.workingEmoji = commandResult.workingEmoji;
|
|
1623
|
+
logger11.info({ scope, emoji: commandResult.workingEmoji }, "working emoji updated");
|
|
1624
|
+
}
|
|
1540
1625
|
if (commandResult.archive && scope.startsWith("thread:")) {
|
|
1541
1626
|
logger11.info({ scope }, "archiving thread");
|
|
1542
1627
|
const archiveChannel = message.channel;
|
|
@@ -1561,7 +1646,7 @@ ${commandResult.response ?? "Archiving..."}
|
|
|
1561
1646
|
hasResponse: Boolean(commandResult.response)
|
|
1562
1647
|
}, `command handled: ${content}`);
|
|
1563
1648
|
if (commandResult.response) {
|
|
1564
|
-
await
|
|
1649
|
+
await sendCommandReply(message, commandResult.response);
|
|
1565
1650
|
}
|
|
1566
1651
|
return;
|
|
1567
1652
|
}
|
|
@@ -1570,7 +1655,7 @@ ${commandResult.response ?? "Archiving..."}
|
|
|
1570
1655
|
logger11.debug({ messageId: message.id }, "channel not sendable");
|
|
1571
1656
|
return;
|
|
1572
1657
|
}
|
|
1573
|
-
await addWorkingReaction(message);
|
|
1658
|
+
await addWorkingReaction(message, entry.workingEmoji);
|
|
1574
1659
|
const queuePosition = promptQueue.getSnapshot().pending;
|
|
1575
1660
|
if (queuePosition > 0) {
|
|
1576
1661
|
await sendReply(message, `Queued. ${queuePosition} request(s) ahead of this one.`);
|
|
@@ -1595,7 +1680,7 @@ ${commandResult.response ?? "Archiving..."}
|
|
|
1595
1680
|
});
|
|
1596
1681
|
} finally {
|
|
1597
1682
|
stopTypingForChannel(channelKey);
|
|
1598
|
-
await removeWorkingReaction(message);
|
|
1683
|
+
await removeWorkingReaction(message, entry.workingEmoji);
|
|
1599
1684
|
}
|
|
1600
1685
|
await sendReply(message, response);
|
|
1601
1686
|
}
|
|
@@ -1716,7 +1801,8 @@ class SessionRegistry {
|
|
|
1716
1801
|
const entry = {
|
|
1717
1802
|
session,
|
|
1718
1803
|
promptQueue,
|
|
1719
|
-
createdAt: new Date
|
|
1804
|
+
createdAt: new Date,
|
|
1805
|
+
workingEmoji: DEFAULT_WORKING_EMOJI
|
|
1720
1806
|
};
|
|
1721
1807
|
this.scopes.set(scope, entry);
|
|
1722
1808
|
logger13.debug({
|
|
@@ -6,10 +6,14 @@ export type CommandResult = {
|
|
|
6
6
|
response?: string;
|
|
7
7
|
/** Set to true when the command wants to archive the current thread. */
|
|
8
8
|
archive?: boolean;
|
|
9
|
+
/** When set, update the session's working reaction emoji. */
|
|
10
|
+
workingEmoji?: string;
|
|
9
11
|
};
|
|
10
12
|
export type CommandContext = {
|
|
11
13
|
agentService: AgentService;
|
|
12
14
|
promptQueue: PromptQueue;
|
|
13
15
|
session?: AgentSession;
|
|
16
|
+
/** Current working reaction emoji for this session. */
|
|
17
|
+
workingEmoji: string;
|
|
14
18
|
};
|
|
15
19
|
export declare function executeSessionCommand(input: string, context: CommandContext): Promise<CommandResult>;
|