Skip to content

Commit 30cc542

Browse files
authored
Merge pull request #1606 from azep-ninja/fix/continue-double-response
fix: Double Responses from Continue Action
2 parents 20090bf + 07e7a54 commit 30cc542

File tree

1 file changed

+61
-32
lines changed

1 file changed

+61
-32
lines changed

packages/plugin-bootstrap/src/actions/continue.ts

+61-32
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,61 @@ export const continueAction: Action = {
9191
options: any,
9292
callback: HandlerCallback
9393
) => {
94-
if (
95-
message.content.text.endsWith("?") ||
96-
message.content.text.endsWith("!")
97-
) {
98-
return;
99-
}
100-
10194
if (!state) {
10295
state = (await runtime.composeState(message)) as State;
10396
}
104-
10597
state = await runtime.updateRecentMessageState(state);
10698

99+
// Get the agent's recent messages
100+
const agentMessages = state.recentMessagesData
101+
.filter((m: { userId: any }) => m.userId === runtime.agentId)
102+
.sort((a: Memory, b: Memory) => {
103+
// Sort by timestamp if available, assuming newer messages have higher timestamps
104+
const aTime = a.createdAt || 0;
105+
const bTime = b.createdAt || 0;
106+
return bTime - aTime;
107+
});
108+
109+
// Check for immediate double response (responding twice in a row to the same message)
110+
const lastAgentMessage = agentMessages[0];
111+
112+
if (lastAgentMessage?.content?.inReplyTo === message.id) {
113+
// If our last message was already a response to this message, only allow continue if:
114+
// 1. The last message had a CONTINUE action
115+
// 2. We haven't hit the maxContinuesInARow limit
116+
const continueCount = agentMessages
117+
.filter((m: Memory) => m.content?.inReplyTo === message.id)
118+
.filter((m: Memory) => m.content?.action === 'CONTINUE')
119+
.length;
120+
121+
if (continueCount >= maxContinuesInARow) {
122+
elizaLogger.log(`[CONTINUE] Max continues (${maxContinuesInARow}) reached for this message chain`);
123+
return;
124+
}
125+
126+
if (lastAgentMessage.content?.action !== 'CONTINUE') {
127+
elizaLogger.log(`[CONTINUE] Last message wasn't a CONTINUE, preventing double response`);
128+
return;
129+
}
130+
}
131+
132+
// Check if our last message or message ended with a question/exclamation and warrants a stop
133+
if ((lastAgentMessage && lastAgentMessage.content.text &&
134+
(lastAgentMessage.content.text.endsWith("?") ||
135+
lastAgentMessage.content.text.endsWith("!"))) || (message.content.text.endsWith("?") || message.content.text.endsWith("!"))) {
136+
elizaLogger.log(`[CONTINUE] Last message had question/exclamation. Not proceeding.`);
137+
return;
138+
}
139+
140+
// Prevent exact duplicate messages
141+
const messageExists = agentMessages
142+
.slice(0, maxContinuesInARow + 1)
143+
.some((m: { content: any }) => m.content.text === message.content.text);
144+
145+
if (messageExists) {
146+
return;
147+
}
148+
107149
async function _shouldContinue(state: State): Promise<boolean> {
108150
// If none of the above conditions are met, use the generateText to decide
109151
const shouldRespondContext = composeContext({
@@ -120,12 +162,14 @@ export const continueAction: Action = {
120162
return response;
121163
}
122164

165+
// Use AI to determine if we should continue
123166
const shouldContinue = await _shouldContinue(state);
124167
if (!shouldContinue) {
125-
elizaLogger.log("Not elaborating, returning");
168+
elizaLogger.log("[CONTINUE] Not elaborating, returning");
126169
return;
127170
}
128171

172+
// Generate and send response
129173
const context = composeContext({
130174
state,
131175
template:
@@ -150,32 +194,17 @@ export const continueAction: Action = {
150194
type: "continue",
151195
});
152196

153-
// prevent repetition
154-
const messageExists = state.recentMessagesData
155-
.filter((m: { userId: any }) => m.userId === runtime.agentId)
156-
.slice(0, maxContinuesInARow + 1)
157-
.some((m: { content: any }) => m.content === message.content);
158-
159-
if (messageExists) {
160-
return;
161-
}
162-
163197
await callback(response);
164198

165-
// if the action is CONTINUE, check if we are over maxContinuesInARow
199+
// Check if we need to clear the CONTINUE action
166200
if (response.action === "CONTINUE") {
167-
const agentMessages = state.recentMessagesData
168-
.filter((m: { userId: any }) => m.userId === runtime.agentId)
169-
.map((m: { content: any }) => (m.content as Content).action);
201+
const continueCount = agentMessages
202+
.slice(0, maxContinuesInARow)
203+
.filter((m: Memory) => m.content?.action === 'CONTINUE')
204+
.length;
170205

171-
const lastMessages = agentMessages.slice(0, maxContinuesInARow);
172-
if (lastMessages.length >= maxContinuesInARow) {
173-
const allContinues = lastMessages.every(
174-
(m: string | undefined) => m === "CONTINUE"
175-
);
176-
if (allContinues) {
177-
response.action = null;
178-
}
206+
if (continueCount >= maxContinuesInARow - 1) { // -1 because we're about to add another
207+
response.action = null;
179208
}
180209
}
181210

@@ -598,4 +627,4 @@ export const continueAction: Action = {
598627
},
599628
],
600629
] as ActionExample[][],
601-
} as Action;
630+
} as Action;

0 commit comments

Comments
 (0)