fix: queue duplicate message

keyboardstaff committed Mar 2, 2026 at 08:36 UTC 75248049c3d468eea528cd49418b5b2269a5a3df
3 files changed +36 -6
plugins/plugin_scan/api/plugin_scan_queue.py
+10 -4
@@ -1,20 +1,26 @@
1 from agent import AgentContext
2 from python.helpers.api import ApiHandler, Input, Output, Request, Response
3 +from python.helpers import message_queue as mq
4
5
6 class PluginScanQueue(ApiHandler):
6 - """Set progress to 'Queued' without starting the agent or logging the prompt."""
7 + """Log the scan prompt into a chat. Optionally set progress to 'Queued'."""
8
9 async def process(self, input: Input, request: Request) -> Output:
10 ctxid: str = input.get("context", "")
11 + text: str = input.get("text", "")
12 + queued: bool = input.get("queued", False)
13
11 - if not ctxid:
12 - return Response("Missing 'context'.", 400)
14 + if not ctxid or not text:
15 + return Response("Missing 'context' or 'text'.", 400)
16
17 context = AgentContext.get(ctxid)
18 if context is None:
19 return Response(f"Context {ctxid} not found.", 404)
20
18 - context.log.set_progress("icon://hourglass_empty Queued - waiting for another scan to finish", 0, True)
21 + mq.log_user_message(context, text, [])
22 +
23 + if queued:
24 + context.log.set_progress("icon://hourglass_empty Queued - waiting for another scan to finish", 0, True)
25
26 return {"ok": True, "context": ctxid}
plugins/plugin_scan/api/plugin_scan_start.py new
+21
@@ -0,0 +1,21 @@
1 +from agent import AgentContext, UserMessage
2 +from python.helpers.api import ApiHandler, Input, Output, Request, Response
3 +
4 +
5 +class PluginScanStart(ApiHandler):
6 + """Start the agent on a context whose user message was already logged by the queue API."""
7 +
8 + async def process(self, input: Input, request: Request) -> Output:
9 + ctxid: str = input.get("context", "")
10 + text: str = input.get("text", "")
11 +
12 + if not ctxid or not text:
13 + return Response("Missing 'context' or 'text'.", 400)
14 +
15 + context = AgentContext.get(ctxid)
16 + if context is None:
17 + return Response(f"Context {ctxid} not found.", 404)
18 +
19 + context.communicate(UserMessage(text, []))
20 +
21 + return {"ok": True, "context": ctxid}
plugins/plugin_scan/webui/plugin-scan-store.js
+5 -2
@@ -165,12 +165,15 @@ export const store = createStore("pluginScan", {
165
166 if (_running) {
167 try {
168 - await api.callJsonApi("/plugins/plugin_scan/plugin_scan_queue", { context: ctxId });
168 + await api.callJsonApi("/plugins/plugin_scan/plugin_scan_queue", { context: ctxId, text: capturedPrompt, queued: true });
169 } catch { /* best-effort */ }
170 _queue.push({ gen, ctxId, prompt: capturedPrompt });
171 this.queued = true;
172 this.scanning = false;
173 } else {
174 + try {
175 + await api.callJsonApi("/plugins/plugin_scan/plugin_scan_queue", { context: ctxId, text: capturedPrompt });
176 + } catch { /* best-effort */ }
177 this.queued = false;
178 this.scanning = true;
179 this._runNext(gen, ctxId, capturedPrompt);
@@ -181,7 +184,7 @@ export const store = createStore("pluginScan", {
184 async _runNext(gen, ctxId, prompt) {
185 _running = { gen, ctxId };
186 try {
184 - await api.callJsonApi("/message_async", { text: prompt, context: ctxId });
187 + await api.callJsonApi("/plugins/plugin_scan/plugin_scan_start", { text: prompt, context: ctxId });
188 await this._pollLoop(gen, ctxId);
189 } catch (/** @type {any} */ e) {
190 if (gen === _pollGen) {