Commit 4f801bcd35bf

Vincent Demeester <vincent@sbr.pm>
2026-02-17 15:43:11
feat(pi): enhanced message queue with manual queueing and smarter auto-queue
Added /queue <message> syntax to manually add messages to the queue without opening the review UI. Changed auto-queue behavior to only capture messages when queue is already non-empty. First message while agent is busy goes through as normal follow-up, subsequent messages get auto-queued. This prevents aggressive queue capture for single follow-up messages.
1 parent 3a86665
Changed files (1)
dots
pi
agent
dots/pi/agent/extensions/message-queue.ts
@@ -307,7 +307,7 @@ export default function (pi: ExtensionAPI) {
 
 	// --- Events ---
 
-	// Auto-queue messages when agent is busy
+	// Auto-queue messages when agent is busy AND there's already a message waiting
 	pi.on("input", async (event, ctx) => {
 		// Don't intercept messages we're sending from the queue
 		if (sending) {
@@ -323,6 +323,12 @@ export default function (pi: ExtensionAPI) {
 			return { action: "handled" as const };
 		}
 
+		// Only auto-queue if there's already something in the queue
+		// First message goes through as normal follow-up
+		if (queue.length === 0) {
+			return { action: "continue" as const };
+		}
+
 		// Deduplicate: skip if identical to the last queued message
 		const last = queue[queue.length - 1];
 		if (last && last.text === event.text) {
@@ -330,7 +336,7 @@ export default function (pi: ExtensionAPI) {
 			return { action: "handled" as const };
 		}
 
-		// Agent is busy — queue the message
+		// Agent is busy AND queue has messages — queue this one too
 		queue.push({
 			text: event.text,
 			timestamp: Date.now(),
@@ -382,9 +388,28 @@ export default function (pi: ExtensionAPI) {
 	// --- Commands ---
 
 	pi.registerCommand("queue", {
-		description: "Review, reorder, and send queued messages",
-		handler: async (_args, ctx) => {
-			await showQueueUI(ctx);
+		description: "Review, reorder, and send queued messages. Usage: /queue [message to add]",
+		handler: async (args, ctx) => {
+			// If args provided, add to queue directly
+			if (args.trim()) {
+				// Deduplicate: skip if identical to the last queued message
+				const last = queue[queue.length - 1];
+				if (last && last.text === args) {
+					ctx.ui.notify("Duplicate message ignored", "info");
+					return;
+				}
+
+				queue.push({
+					text: args,
+					timestamp: Date.now(),
+				});
+
+				ctx.ui.notify(`Message queued (${queue.length} in queue)`, "info");
+				updateWidget(ctx);
+			} else {
+				// No args, show UI
+				await showQueueUI(ctx);
+			}
 		},
 	});