bloby-bot 0.25.0 → 0.25.1
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 +1 -1
- package/supervisor/channels/manager.ts +28 -11
package/package.json
CHANGED
|
@@ -243,6 +243,11 @@ export class ChannelManager {
|
|
|
243
243
|
|
|
244
244
|
// ── Internal ──
|
|
245
245
|
|
|
246
|
+
/** Format a bot reply with the agent's name prefix (for admin & assistant messages, NOT customer) */
|
|
247
|
+
private formatBotReply(text: string, botName: string): string {
|
|
248
|
+
return `🤖 *${botName}:*\n\n${text}`;
|
|
249
|
+
}
|
|
250
|
+
|
|
246
251
|
private handleStatusChange(status: ChannelStatus) {
|
|
247
252
|
for (const listener of this.statusListeners) {
|
|
248
253
|
listener(status);
|
|
@@ -286,9 +291,9 @@ export class ChannelManager {
|
|
|
286
291
|
// Store every message for context (both mine and theirs)
|
|
287
292
|
this.storeAssistantContext(channel, sender, senderName, text, fromMe);
|
|
288
293
|
|
|
289
|
-
// Only continue if it's me AND the message
|
|
294
|
+
// Only continue if it's me AND the message contains the trigger
|
|
290
295
|
const botName = loadConfig().username || 'bloby';
|
|
291
|
-
const triggerPattern = new RegExp(
|
|
296
|
+
const triggerPattern = new RegExp(`(?:^|\\n)\\s*@${botName}[:\\s]`, 'i');
|
|
292
297
|
if (!fromMe || !triggerPattern.test(text)) return;
|
|
293
298
|
// Falls through to debounce → flushDebounce → handleAssistantMessage
|
|
294
299
|
}
|
|
@@ -498,7 +503,7 @@ export class ChannelManager {
|
|
|
498
503
|
|
|
499
504
|
// Agent paused to use a tool — send accumulated text as an intermediate WhatsApp message
|
|
500
505
|
if (type === 'bot:tool' && waChunkBuf.trim()) {
|
|
501
|
-
this.sendMessage(msg.channel, msg.rawSender, waChunkBuf.trim()).catch((err) => {
|
|
506
|
+
this.sendMessage(msg.channel, msg.rawSender, this.formatBotReply(waChunkBuf.trim(), botName)).catch((err) => {
|
|
502
507
|
log.warn(`[channels] Failed to send WhatsApp chunk: ${err.message}`);
|
|
503
508
|
});
|
|
504
509
|
waChunkBuf = '';
|
|
@@ -508,7 +513,7 @@ export class ChannelManager {
|
|
|
508
513
|
// Send remaining text
|
|
509
514
|
const remaining = waChunkBuf.trim();
|
|
510
515
|
if (remaining) {
|
|
511
|
-
this.sendMessage(msg.channel, msg.rawSender, remaining).catch((err) => {
|
|
516
|
+
this.sendMessage(msg.channel, msg.rawSender, this.formatBotReply(remaining, botName)).catch((err) => {
|
|
512
517
|
log.warn(`[channels] Failed to send WhatsApp reply: ${err.message}`);
|
|
513
518
|
});
|
|
514
519
|
waChunkBuf = '';
|
|
@@ -681,17 +686,20 @@ export class ChannelManager {
|
|
|
681
686
|
text: string,
|
|
682
687
|
fromMe: boolean,
|
|
683
688
|
) {
|
|
684
|
-
|
|
689
|
+
// Normalize key to phone number (strip @lid / @s.whatsapp.net) — must match handleAssistantMessage's agentKey
|
|
690
|
+
const phone = sender.replace(/@.*/, '');
|
|
691
|
+
const bufferKey = `${channel}:${phone}`;
|
|
685
692
|
let buffer = this.customerBuffers.get(bufferKey);
|
|
686
693
|
if (!buffer) {
|
|
687
694
|
buffer = [];
|
|
688
695
|
this.customerBuffers.set(bufferKey, buffer);
|
|
689
696
|
}
|
|
690
|
-
const label = fromMe ? 'me' : (senderName ||
|
|
697
|
+
const label = fromMe ? 'me' : (senderName || phone);
|
|
691
698
|
buffer.push({ role: 'user', content: `[${label}]: ${text}` });
|
|
692
699
|
if (buffer.length > MAX_BUFFER_MESSAGES) {
|
|
693
700
|
buffer.splice(0, buffer.length - MAX_BUFFER_MESSAGES);
|
|
694
701
|
}
|
|
702
|
+
log.info(`[channels] Assistant context stored: ${bufferKey} | ${buffer.length} msgs | [${label}]: "${text.slice(0, 60)}"`);
|
|
695
703
|
}
|
|
696
704
|
|
|
697
705
|
/** Handle a triggered assistant message — runs one-shot agent with conversation context */
|
|
@@ -708,11 +716,15 @@ export class ChannelManager {
|
|
|
708
716
|
const { workerApi, getModel } = this.opts;
|
|
709
717
|
const model = getModel();
|
|
710
718
|
|
|
711
|
-
//
|
|
719
|
+
// Extract command after trigger: "Ok.\n\n@bloby: do X" → "do X"
|
|
712
720
|
const config = loadConfig();
|
|
713
721
|
const botName = config.username || 'bloby';
|
|
714
|
-
const triggerRegex = new RegExp(
|
|
715
|
-
const
|
|
722
|
+
const triggerRegex = new RegExp(`@${botName}[:\\s]+`, 'i');
|
|
723
|
+
const triggerMatch = msg.text.match(triggerRegex);
|
|
724
|
+
let cleanText = msg.text;
|
|
725
|
+
if (triggerMatch && triggerMatch.index !== undefined) {
|
|
726
|
+
cleanText = msg.text.slice(triggerMatch.index + triggerMatch[0].length).trim();
|
|
727
|
+
}
|
|
716
728
|
|
|
717
729
|
// Load SCRIPT.md from configured skill
|
|
718
730
|
const scriptPrompt = this.loadActiveScript(channelConfig);
|
|
@@ -732,6 +744,11 @@ export class ChannelManager {
|
|
|
732
744
|
this.customerBuffers.set(agentKey, buffer);
|
|
733
745
|
}
|
|
734
746
|
|
|
747
|
+
log.info(`[channels] Assistant trigger: agentKey=${agentKey} | buffer=${buffer.length} msgs | cleanText="${cleanText.slice(0, 80)}"`);
|
|
748
|
+
if (buffer.length > 0) {
|
|
749
|
+
log.info(`[channels] Assistant context preview: ${buffer.slice(-5).map((m) => `[${m.role}] ${m.content.slice(0, 50)}`).join(' | ')}`);
|
|
750
|
+
}
|
|
751
|
+
|
|
735
752
|
// All buffered messages are context for the agent
|
|
736
753
|
const recentMessages: RecentMessage[] = buffer.map((m) => ({
|
|
737
754
|
role: m.role,
|
|
@@ -789,7 +806,7 @@ export class ChannelManager {
|
|
|
789
806
|
|
|
790
807
|
// Agent paused to use a tool — send accumulated text as intermediate message
|
|
791
808
|
if (type === 'bot:tool' && waChunkBuf.trim()) {
|
|
792
|
-
this.sendMessage(msg.channel, msg.rawSender, waChunkBuf.trim()).catch((err) => {
|
|
809
|
+
this.sendMessage(msg.channel, msg.rawSender, this.formatBotReply(waChunkBuf.trim(), agentBotName)).catch((err) => {
|
|
793
810
|
log.warn(`[channels] Failed to send assistant chunk: ${err.message}`);
|
|
794
811
|
});
|
|
795
812
|
waChunkBuf = '';
|
|
@@ -805,7 +822,7 @@ export class ChannelManager {
|
|
|
805
822
|
// Send remaining text
|
|
806
823
|
const remaining = waChunkBuf.trim();
|
|
807
824
|
if (remaining) {
|
|
808
|
-
this.sendMessage(msg.channel, msg.rawSender, remaining).catch((err) => {
|
|
825
|
+
this.sendMessage(msg.channel, msg.rawSender, this.formatBotReply(remaining, agentBotName)).catch((err) => {
|
|
809
826
|
log.warn(`[channels] Failed to send assistant reply: ${err.message}`);
|
|
810
827
|
});
|
|
811
828
|
waChunkBuf = '';
|