rdesign/frontend/node_modules/@copilotkitnext/react/dist/components/chat/CopilotChat.mjs

221 lines
8.2 KiB
JavaScript

import { CopilotChatConfigurationProvider, useCopilotChatConfiguration } from "../../providers/CopilotChatConfigurationProvider.mjs";
import { renderSlot } from "../../lib/slots.mjs";
import { useCopilotKit } from "../../providers/CopilotKitProvider.mjs";
import { useAgent } from "../../hooks/use-agent.mjs";
import { useSuggestions } from "../../hooks/use-suggestions.mjs";
import { CopilotChatView } from "./CopilotChatView.mjs";
import { TranscriptionError, transcribeAudio } from "../../lib/transcription-client.mjs";
import { HttpAgent } from "@ag-ui/client";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { DEFAULT_AGENT_ID, TranscriptionErrorCode, randomUUID } from "@copilotkitnext/shared";
import { jsx, jsxs } from "react/jsx-runtime";
import { merge } from "ts-deepmerge";
//#region src/components/chat/CopilotChat.tsx
function CopilotChat({ agentId, threadId, labels, chatView, onError, ...props }) {
const existingConfig = useCopilotChatConfiguration();
const resolvedAgentId = agentId ?? existingConfig?.agentId ?? DEFAULT_AGENT_ID;
const resolvedThreadId = useMemo(() => threadId ?? existingConfig?.threadId ?? randomUUID(), [threadId, existingConfig?.threadId]);
const { agent } = useAgent({ agentId: resolvedAgentId });
const { copilotkit } = useCopilotKit();
const { suggestions: autoSuggestions } = useSuggestions({ agentId: resolvedAgentId });
const onErrorRef = useRef(onError);
useEffect(() => {
onErrorRef.current = onError;
}, [onError]);
useEffect(() => {
if (!onErrorRef.current) return;
const subscription = copilotkit.subscribe({ onError: (event) => {
if (event.context?.agentId === resolvedAgentId || !event.context?.agentId) onErrorRef.current?.({
error: event.error,
code: event.code,
context: event.context
});
} });
return () => {
subscription.unsubscribe();
};
}, [copilotkit, resolvedAgentId]);
const [transcribeMode, setTranscribeMode] = useState("input");
const [inputValue, setInputValue] = useState("");
const [transcriptionError, setTranscriptionError] = useState(null);
const [isTranscribing, setIsTranscribing] = useState(false);
const isTranscriptionEnabled = copilotkit.audioFileTranscriptionEnabled;
const isMediaRecorderSupported = typeof window !== "undefined" && typeof MediaRecorder !== "undefined";
const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
useEffect(() => {
let detached = false;
const connectAbortController = new AbortController();
if (agent instanceof HttpAgent) agent.abortController = connectAbortController;
const connect = async (agent) => {
try {
await copilotkit.connectAgent({ agent });
} catch (error) {
if (detached) return;
console.error("CopilotChat: connectAgent failed", error);
}
};
agent.threadId = resolvedThreadId;
connect(agent);
return () => {
detached = true;
connectAbortController.abort();
agent.detachActiveRun();
};
}, [
resolvedThreadId,
agent,
resolvedAgentId
]);
const onSubmitInput = useCallback(async (value) => {
agent.addMessage({
id: randomUUID(),
role: "user",
content: value
});
setInputValue("");
try {
await copilotkit.runAgent({ agent });
} catch (error) {
console.error("CopilotChat: runAgent failed", error);
}
}, [agent]);
const handleSelectSuggestion = useCallback(async (suggestion) => {
agent.addMessage({
id: randomUUID(),
role: "user",
content: suggestion.message
});
try {
await copilotkit.runAgent({ agent });
} catch (error) {
console.error("CopilotChat: runAgent failed after selecting suggestion", error);
}
}, [agent]);
const stopCurrentRun = useCallback(() => {
try {
copilotkit.stopAgent({ agent });
} catch (error) {
console.error("CopilotChat: stopAgent failed", error);
try {
agent.abortRun();
} catch (abortError) {
console.error("CopilotChat: abortRun fallback failed", abortError);
}
}
}, [agent]);
const handleStartTranscribe = useCallback(() => {
setTranscriptionError(null);
setTranscribeMode("transcribe");
}, []);
const handleCancelTranscribe = useCallback(() => {
setTranscriptionError(null);
setTranscribeMode("input");
}, []);
const handleFinishTranscribe = useCallback(() => {
setTranscribeMode("input");
}, []);
const handleFinishTranscribeWithAudio = useCallback(async (audioBlob) => {
setIsTranscribing(true);
try {
setTranscriptionError(null);
const result = await transcribeAudio(copilotkit, audioBlob);
setInputValue((prev) => {
const trimmedPrev = prev.trim();
if (trimmedPrev) return `${trimmedPrev} ${result.text}`;
return result.text;
});
} catch (error) {
console.error("CopilotChat: Transcription failed", error);
if (error instanceof TranscriptionError) {
const { code, retryable, message } = error.info;
switch (code) {
case TranscriptionErrorCode.RATE_LIMITED:
setTranscriptionError("Too many requests. Please wait a moment.");
break;
case TranscriptionErrorCode.AUTH_FAILED:
setTranscriptionError("Authentication error. Please check your configuration.");
break;
case TranscriptionErrorCode.AUDIO_TOO_LONG:
setTranscriptionError("Recording is too long. Please try a shorter recording.");
break;
case TranscriptionErrorCode.AUDIO_TOO_SHORT:
setTranscriptionError("Recording is too short. Please try again.");
break;
case TranscriptionErrorCode.INVALID_AUDIO_FORMAT:
setTranscriptionError("Audio format not supported.");
break;
case TranscriptionErrorCode.SERVICE_NOT_CONFIGURED:
setTranscriptionError("Transcription service is not available.");
break;
case TranscriptionErrorCode.NETWORK_ERROR:
setTranscriptionError("Network error. Please check your connection.");
break;
default: setTranscriptionError(retryable ? "Transcription failed. Please try again." : message);
}
} else setTranscriptionError("Transcription failed. Please try again.");
} finally {
setIsTranscribing(false);
}
}, []);
useEffect(() => {
if (transcriptionError) {
const timer = setTimeout(() => {
setTranscriptionError(null);
}, 5e3);
return () => clearTimeout(timer);
}
}, [transcriptionError]);
const mergedProps = merge({
isRunning: agent.isRunning,
suggestions: autoSuggestions,
onSelectSuggestion: handleSelectSuggestion,
suggestionView: providedSuggestionView
}, {
...restProps,
...typeof providedMessageView === "string" ? { messageView: { className: providedMessageView } } : providedMessageView !== void 0 ? { messageView: providedMessageView } : {}
});
const hasMessages = agent.messages.length > 0;
const effectiveStopHandler = agent.isRunning && hasMessages ? providedStopHandler ?? stopCurrentRun : providedStopHandler;
const showTranscription = isTranscriptionEnabled && isMediaRecorderSupported;
const effectiveMode = isTranscribing ? "processing" : transcribeMode;
const RenderedChatView = renderSlot(chatView, CopilotChatView, merge(mergedProps, {
messages: useMemo(() => [...agent.messages], [JSON.stringify(agent.messages)]),
onSubmitMessage: onSubmitInput,
onStop: effectiveStopHandler,
inputMode: effectiveMode,
inputValue,
onInputChange: setInputValue,
onStartTranscribe: showTranscription ? handleStartTranscribe : void 0,
onCancelTranscribe: showTranscription ? handleCancelTranscribe : void 0,
onFinishTranscribe: showTranscription ? handleFinishTranscribe : void 0,
onFinishTranscribeWithAudio: showTranscription ? handleFinishTranscribeWithAudio : void 0
}));
return /* @__PURE__ */ jsxs(CopilotChatConfigurationProvider, {
agentId: resolvedAgentId,
threadId: resolvedThreadId,
labels,
children: [transcriptionError && /* @__PURE__ */ jsx("div", {
style: {
position: "absolute",
bottom: "100px",
left: "50%",
transform: "translateX(-50%)",
backgroundColor: "#ef4444",
color: "white",
padding: "8px 16px",
borderRadius: "8px",
fontSize: "14px",
zIndex: 50
},
children: transcriptionError
}), RenderedChatView]
});
}
(function(_CopilotChat) {
_CopilotChat.View = CopilotChatView;
})(CopilotChat || (CopilotChat = {}));
//#endregion
export { CopilotChat };
//# sourceMappingURL=CopilotChat.mjs.map