From 3beb8aada29e92287276830789183d8427d47504 Mon Sep 17 00:00:00 2001 From: jjbrunton Date: Sat, 8 Aug 2026 23:10:52 +0100 Subject: [PATCH] feat: automate bounded image-sharing conversations --- .../conversations/conversation-detail.tsx | 27 +++- .../features/conversations/conversations.css | 38 +++++ packages/api-contracts/src/chats.ts | 6 + .../api-contracts/tests/contracts.test.ts | 3 +- src/ai/openrouter.ts | 29 ++-- src/services/conversation-automation.ts | 148 ++++++++++++++++++ src/services/conversation-state.ts | 62 +++++++- .../reddit-account-runtime-builder.ts | 25 ++- src/services/reddit-account-runtime.ts | 2 + src/web/routes/conversations.ts | 23 +++ tests/conversation-automation.test.ts | 86 ++++++++++ tests/conversation-state.test.ts | 27 ++++ tests/dashboard/conversations.test.tsx | 1 + tests/openrouter-client.test.ts | 1 + tests/web/conversations-route.test.ts | 18 ++- 15 files changed, 477 insertions(+), 19 deletions(-) create mode 100644 src/services/conversation-automation.ts create mode 100644 tests/conversation-automation.test.ts diff --git a/apps/dashboard/src/features/conversations/conversation-detail.tsx b/apps/dashboard/src/features/conversations/conversation-detail.tsx index 6e3808f..d3011eb 100644 --- a/apps/dashboard/src/features/conversations/conversation-detail.tsx +++ b/apps/dashboard/src/features/conversations/conversation-detail.tsx @@ -69,6 +69,7 @@ function ConversationComposer({ conversation, conversationId }: { conversation: const mediaAskMutation = useSuggestMediaAskMutation(conversationId); const sendMutation = useSendReplyMutation(conversationId); const canSend = draft.trim().length > 0 && !sendMutation.isPending; + const automationActive = conversation.automation.status === 'active' && conversation.automation.remainingTurns > 0; const closeConfirmation = useCallback(() => { setIsConfirming(false); @@ -103,10 +104,17 @@ function ConversationComposer({ conversation, conversationId }: { conversation: - +
+ {conversation.automation.remainingTurns} automated {conversation.automation.remainingTurns === 1 ? 'turn' : 'turns'} remaining + {automationStatusMessage(conversation)} +