75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
export type AgentInputSubmitResult = "noop" | "queued" | "submitted" | "failed";
|
|
|
|
export interface AgentInputSubmitActionInput<TAttachment> {
|
|
message: string;
|
|
attachments: TAttachment[];
|
|
hasExternalContent?: boolean;
|
|
allowEmptySubmit?: boolean;
|
|
submitBehavior?: "clear" | "preserve-and-lock";
|
|
forceSend?: boolean;
|
|
isAgentRunning: boolean;
|
|
canSubmit: boolean;
|
|
queueMessage: (input: { message: string; attachments: TAttachment[] }) => void;
|
|
submitMessage: (input: { message: string; attachments: TAttachment[] }) => Promise<void>;
|
|
clearDraft: (lifecycle: "sent" | "abandoned") => void;
|
|
setUserInput: (text: string) => void;
|
|
setAttachments: (attachments: TAttachment[]) => void;
|
|
setSendError: (message: string | null) => void;
|
|
setIsProcessing: (isProcessing: boolean) => void;
|
|
onSubmitError?: (error: unknown) => void;
|
|
}
|
|
|
|
export async function submitAgentInput<TAttachment>(
|
|
input: AgentInputSubmitActionInput<TAttachment>,
|
|
): Promise<AgentInputSubmitResult> {
|
|
const trimmedMessage = input.message.trim();
|
|
const attachments = input.attachments;
|
|
const shouldClearOnSubmit = input.submitBehavior !== "preserve-and-lock";
|
|
|
|
if (
|
|
!trimmedMessage &&
|
|
attachments.length === 0 &&
|
|
!input.hasExternalContent &&
|
|
!input.allowEmptySubmit
|
|
) {
|
|
return "noop";
|
|
}
|
|
|
|
if (!input.canSubmit) {
|
|
return "noop";
|
|
}
|
|
|
|
if (input.isAgentRunning && !input.forceSend) {
|
|
input.queueMessage({ message: trimmedMessage, attachments });
|
|
if (shouldClearOnSubmit) {
|
|
input.setUserInput("");
|
|
input.setAttachments([]);
|
|
}
|
|
return "queued";
|
|
}
|
|
|
|
// Clear immediately so optimistic stream updates and composer state stay in sync.
|
|
if (shouldClearOnSubmit) {
|
|
input.setUserInput("");
|
|
input.setAttachments([]);
|
|
}
|
|
input.setSendError(null);
|
|
input.setIsProcessing(true);
|
|
|
|
try {
|
|
await input.submitMessage({ message: trimmedMessage, attachments });
|
|
input.clearDraft("sent");
|
|
input.setIsProcessing(false);
|
|
return "submitted";
|
|
} catch (error) {
|
|
input.onSubmitError?.(error);
|
|
if (shouldClearOnSubmit) {
|
|
input.setUserInput(trimmedMessage);
|
|
input.setAttachments(attachments);
|
|
}
|
|
input.setSendError(error instanceof Error ? error.message : "Failed to send message");
|
|
input.setIsProcessing(false);
|
|
return "failed";
|
|
}
|
|
}
|