feat: automate bounded image-sharing conversations
This commit is contained in:
1 parent
dcf57273e2
commit
3beb8aada2
15 files changed
+477
-19
No files matched your search
@@ -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:
|
||||
<button disabled={suggestionMutation.isPending} onClick={suggestReply} type="button">
|
||||
{suggestionMutation.isPending ? 'Generating…' : 'Suggest reply'}
|
||||
</button>
|
||||
<button disabled={mediaAskMutation.isPending} onClick={suggestMediaAsk} type="button">
|
||||
{mediaAskMutation.isPending ? 'Generating media ask…' : 'Suggest media ask'}
|
||||
<button disabled={mediaAskMutation.isPending || !automationActive} onClick={suggestMediaAsk} type="button">
|
||||
{mediaAskMutation.isPending ? 'Generating media ask…' : 'Suggest media ask'}
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className={`conversation-automation-status is-${conversation.automation.status}`}
|
||||
role="status"
|
||||
>
|
||||
<strong>{conversation.automation.remainingTurns} automated {conversation.automation.remainingTurns === 1 ? 'turn' : 'turns'} remaining</strong>
|
||||
<span>{automationStatusMessage(conversation)}</span>
|
||||
</div>
|
||||
<label className="sr-only" htmlFor="conversation-reply">Reply to {redditUsernameLabel(conversation.username)}</label>
|
||||
<textarea
|
||||
id="conversation-reply"
|
||||
@@ -149,6 +157,21 @@ function ConversationComposer({ conversation, conversationId }: { conversation:
|
||||
);
|
||||
}
|
||||
|
||||
function automationStatusMessage(conversation: ConversationDetailResponse): string {
|
||||
switch (conversation.automation.status) {
|
||||
case 'image-received':
|
||||
return 'Image received. Automation is complete.';
|
||||
case 'human-required':
|
||||
return 'Automated turns are exhausted. A human should take over.';
|
||||
case 'boundary':
|
||||
return 'Automation stopped because the user set a boundary.';
|
||||
case 'user-overridden':
|
||||
return 'A manual reply was sent. AI turns are disabled for this conversation.';
|
||||
default:
|
||||
return 'The next unread reply can be handled automatically.';
|
||||
}
|
||||
}
|
||||
|
||||
export function ConversationDetail({ conversationId, onClose }: ConversationDetailProps) {
|
||||
const detailQuery = useConversationDetailQuery(conversationId);
|
||||
|
||||
|
||||
@@ -85,3 +85,41 @@
|
||||
.start-conversation-form { grid-template-columns: minmax(12rem, .5fr) minmax(18rem, 1fr) auto; align-items: end; }
|
||||
.conversation-workspace { grid-template-columns: minmax(17rem, .75fr) minmax(28rem, 1.5fr); }
|
||||
}
|
||||
.conversation-automation-status {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
padding: 0.75rem 0.875rem;
|
||||
border: 1px solid var(--border-color, #d7dce2);
|
||||
border-radius: 0.625rem;
|
||||
background: rgba(54, 116, 181, 0.08);
|
||||
}
|
||||
|
||||
.conversation-automation-status span {
|
||||
color: var(--muted-color, #606975);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.conversation-automation-status.is-human-required,
|
||||
.conversation-automation-status.is-boundary,
|
||||
.conversation-automation-status.is-user-overridden {
|
||||
border-color: #d8943a;
|
||||
background: rgba(216, 148, 58, 0.12);
|
||||
}
|
||||
|
||||
.conversation-automation-status.is-image-received {
|
||||
border-color: #4d9b68;
|
||||
background: rgba(77, 155, 104, 0.12);
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.conversation-automation-status {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.conversation-automation-status span {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user