mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-21 17:21:09 +01:00
refactor: streamline conversation initialization and enhance log handling
- Refactored AssistantConsole to utilize a dedicated initializeConversation function for improved clarity and organization. - Updated DependencyLogsDialog to rename computed property from content to logs for better semantic understanding. - Enhanced LogsView component by wrapping logs in an el-scrollbar for improved user experience. - Adjusted ChatInput to call updateSelectedProviderModel on onBeforeMount for better state management. - Simplified default model handling in ai.ts by introducing a DEFAULT_OPENAI_MODELS constant for consistency.
This commit is contained in:
@@ -6,7 +6,7 @@ import { debounce } from 'lodash';
|
||||
import { useRouter } from 'vue-router';
|
||||
import useAssistantConsole from './useAssistantConsole';
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
}>();
|
||||
|
||||
@@ -35,15 +35,12 @@ const {
|
||||
chatbotConfig,
|
||||
currentConversationTitle,
|
||||
loadConversations,
|
||||
loadConversationMessages,
|
||||
loadCurrentConversation,
|
||||
loadLLMProviders,
|
||||
loadChatbotConfig,
|
||||
saveChatbotConfig,
|
||||
selectConversation,
|
||||
createNewConversation,
|
||||
sendStreamingRequest,
|
||||
extractErrorMessage,
|
||||
initializeConversation,
|
||||
} = useAssistantConsole();
|
||||
|
||||
// Message handling
|
||||
@@ -105,7 +102,9 @@ const cancelMessage = () => {
|
||||
abortController.value = null;
|
||||
isGenerating.value = false;
|
||||
|
||||
const streamingMessageIndex = chatHistory.findIndex((msg: ChatMessage) => msg.isStreaming);
|
||||
const streamingMessageIndex = chatHistory.findIndex(
|
||||
(msg: ChatMessage) => msg.isStreaming
|
||||
);
|
||||
if (streamingMessageIndex >= 0) {
|
||||
chatHistory.splice(streamingMessageIndex, 1);
|
||||
}
|
||||
@@ -156,19 +155,15 @@ watch(isGenerating, () => {
|
||||
});
|
||||
|
||||
// Initialize
|
||||
onBeforeMount(async () => {
|
||||
await loadConversations();
|
||||
loadChatbotConfig();
|
||||
await loadLLMProviders();
|
||||
|
||||
// Load saved conversation ID from localStorage
|
||||
const savedConversationId = localStorage.getItem('currentConversationId');
|
||||
if (savedConversationId) {
|
||||
await loadConversationMessages(savedConversationId);
|
||||
await loadCurrentConversation(savedConversationId);
|
||||
currentConversationId.value = savedConversationId;
|
||||
onBeforeMount(initializeConversation);
|
||||
watch(
|
||||
() => props.visible,
|
||||
async () => {
|
||||
if (props.visible) {
|
||||
await initializeConversation();
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
defineOptions({ name: 'ClAssistantConsole' });
|
||||
</script>
|
||||
|
||||
@@ -418,6 +418,19 @@ const useAssistantConsole = () => {
|
||||
};
|
||||
onMounted(focusInput);
|
||||
|
||||
const initializeConversation = async () => {
|
||||
loadChatbotConfig();
|
||||
await loadLLMProviders();
|
||||
|
||||
// Load saved conversation ID from localStorage
|
||||
const savedConversationId = localStorage.getItem('currentConversationId');
|
||||
if (savedConversationId) {
|
||||
await loadConversationMessages(savedConversationId);
|
||||
await loadCurrentConversation(savedConversationId);
|
||||
currentConversationId.value = savedConversationId;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
// Refs
|
||||
messageListRef,
|
||||
@@ -451,6 +464,7 @@ const useAssistantConsole = () => {
|
||||
createNewConversation,
|
||||
sendStreamingRequest,
|
||||
extractErrorMessage,
|
||||
initializeConversation,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ const visible = computed(() => state.activeDialogKey === 'logs');
|
||||
const activeTargetName = computed(() => state.activeTargetName);
|
||||
const activeTargetStatus = computed(() => state.activeTargetStatus);
|
||||
|
||||
const content = computed(() => {
|
||||
const logs = computed(() => {
|
||||
const data: string[] = [];
|
||||
state.activeTargetLogs?.forEach(l => {
|
||||
l.content
|
||||
@@ -25,7 +25,7 @@ const content = computed(() => {
|
||||
data.push(line.trim());
|
||||
});
|
||||
});
|
||||
return data.join('\n');
|
||||
return data;
|
||||
});
|
||||
|
||||
const logsViewRef = ref<HTMLDivElement>();
|
||||
@@ -86,9 +86,7 @@ defineOptions({ name: 'ClDependencyLogsDialog' });
|
||||
<span>{{ t('common.tabs.logs') }} - {{ activeTargetName }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="logs-view" ref="logsViewRef">
|
||||
<pre>{{ content }}</pre>
|
||||
</div>
|
||||
<cl-logs-view ref="logsViewRef" :logs="logs" />
|
||||
</cl-dialog>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, onMounted, watch, computed, onUnmounted } from 'vue';
|
||||
import { ref, nextTick, onMounted, watch, computed, onUnmounted, onBeforeMount } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { getLLMProviderIcon, getLLMProviderName } from '@/utils/ai';
|
||||
import ClLabelButton from '@/components/ui/button/LabelButton.vue';
|
||||
@@ -38,6 +38,7 @@ watch(
|
||||
() => `${props.selectedProvider}:${props.selectedModel}`,
|
||||
updateSelectedProviderModel
|
||||
);
|
||||
onBeforeMount(updateSelectedProviderModel);
|
||||
|
||||
const onModelChange = (value: string) => {
|
||||
const [provider, model] = value.split(':');
|
||||
|
||||
@@ -31,16 +31,18 @@ defineOptions({ name: 'ClLogsView' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="logs-view" ref="logsViewRef">
|
||||
<pre>{{ content }}</pre>
|
||||
</div>
|
||||
<el-scrollbar max-height="560px">
|
||||
<div class="logs-view" ref="logsViewRef">
|
||||
<pre>{{ content }}</pre>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.logs-view {
|
||||
border: 1px solid rgb(244, 244, 245);
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
min-height: 480px;
|
||||
max-height: 560px;
|
||||
}
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
export const DEFAULT_OPENAI_MODELS = [
|
||||
'gpt-4o',
|
||||
'gpt-4o-mini',
|
||||
'gpt-4.1',
|
||||
'gpt-4.1-mini',
|
||||
'gpt-4.1-nano',
|
||||
'o1-mini',
|
||||
'o1',
|
||||
'o3-mini',
|
||||
'o3',
|
||||
];
|
||||
|
||||
export const getLLMProviderItems = (): LLMProviderItem[] => {
|
||||
return [
|
||||
{
|
||||
key: 'openai',
|
||||
name: 'OpenAI',
|
||||
icon: ['svg', 'openai'],
|
||||
defaultModels: [
|
||||
'gpt-4o',
|
||||
'gpt-4o-mini',
|
||||
'o1-mini',
|
||||
'o1',
|
||||
'o3-mini',
|
||||
'o3',
|
||||
],
|
||||
defaultModels: DEFAULT_OPENAI_MODELS,
|
||||
},
|
||||
{
|
||||
key: 'azure-openai',
|
||||
name: 'Azure OpenAI',
|
||||
icon: ['svg', 'azure'],
|
||||
defaultModels: [
|
||||
'gpt-4o',
|
||||
'gpt-4o-mini',
|
||||
'o1',
|
||||
'o1-mini',
|
||||
'o1-pro',
|
||||
'o3-mini',
|
||||
'gpt-4.5-preview',
|
||||
],
|
||||
defaultModels: DEFAULT_OPENAI_MODELS,
|
||||
defaultApiVersions: ['2025-02-01-preview'],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -233,9 +233,9 @@ defineOptions({ name: 'ClSystemDetailTabAi' });
|
||||
<span class="info">
|
||||
{{
|
||||
op.unset
|
||||
? ' (' + $t('views.system.ai.unset') + ')'
|
||||
? ' (' + t('views.system.ai.unset') + ')'
|
||||
: op.disabled
|
||||
? ' (' + $t('views.system.ai.disabled') + ')'
|
||||
? ' (' + t('views.system.ai.disabled') + ')'
|
||||
: ''
|
||||
}}
|
||||
</span>
|
||||
@@ -247,15 +247,15 @@ defineOptions({ name: 'ClSystemDetailTabAi' });
|
||||
:model="form"
|
||||
:key="activeLLMProviderKey"
|
||||
>
|
||||
<cl-form-item :label="$t('views.system.ai.llmProvider')" :span="4">
|
||||
<cl-form-item :label="t('views.system.ai.llmProvider')" :span="4">
|
||||
<cl-icon :icon="activeLLMProvider?.icon" />
|
||||
{{ activeLLMProvider?.name }}
|
||||
</cl-form-item>
|
||||
<cl-form-item :label="$t('views.system.ai.enabled')" :span="4">
|
||||
<cl-form-item :label="t('views.system.ai.enabled')" :span="4">
|
||||
<cl-switch v-model="form.enabled" @change="saveLLMProvider" />
|
||||
</cl-form-item>
|
||||
<cl-form-item
|
||||
:label="$t('views.system.ai.apiKey')"
|
||||
:label="t('views.system.ai.apiKey')"
|
||||
:span="4"
|
||||
prop="api_key"
|
||||
required
|
||||
@@ -263,14 +263,14 @@ defineOptions({ name: 'ClSystemDetailTabAi' });
|
||||
<cl-edit-input
|
||||
v-model="form.api_key"
|
||||
:display-value="
|
||||
form.api_key ? '*'.repeat(Math.min(form.api_key.length, 10)) : ''
|
||||
form.api_key ? '*'.repeat(Math.min(form.api_key.length, 32)) : ''
|
||||
"
|
||||
@change="saveLLMProvider"
|
||||
/>
|
||||
</cl-form-item>
|
||||
<cl-form-item
|
||||
v-if="showApiBaseUrl"
|
||||
:label="$t('views.system.ai.apiBaseUrl')"
|
||||
:label="t('views.system.ai.apiBaseUrl')"
|
||||
:span="4"
|
||||
prop="api_base_url"
|
||||
required
|
||||
@@ -279,14 +279,14 @@ defineOptions({ name: 'ClSystemDetailTabAi' });
|
||||
</cl-form-item>
|
||||
<cl-form-item
|
||||
v-if="showApiVersion"
|
||||
:label="$t('views.system.ai.apiVersion')"
|
||||
:label="t('views.system.ai.apiVersion')"
|
||||
:span="4"
|
||||
prop="api_version"
|
||||
>
|
||||
<cl-edit-input v-model="form.api_version" @change="saveLLMProvider" />
|
||||
</cl-form-item>
|
||||
<cl-form-item
|
||||
:label="$t('views.system.ai.models')"
|
||||
:label="t('views.system.ai.models')"
|
||||
:span="4"
|
||||
prop="models"
|
||||
>
|
||||
@@ -294,7 +294,7 @@ defineOptions({ name: 'ClSystemDetailTabAi' });
|
||||
<!-- Default models from provider -->
|
||||
<div v-if="defaultModels.length > 0" class="default-models">
|
||||
<div class="section-title">
|
||||
{{ $t('views.system.ai.defaultModels') }}
|
||||
{{ t('views.system.ai.defaultModels') }}
|
||||
</div>
|
||||
<div class="model-list">
|
||||
<el-checkbox
|
||||
@@ -312,14 +312,14 @@ defineOptions({ name: 'ClSystemDetailTabAi' });
|
||||
<!-- Custom models -->
|
||||
<div class="custom-models">
|
||||
<div class="section-title">
|
||||
{{ $t('views.system.ai.customModels') }}
|
||||
{{ t('views.system.ai.customModels') }}
|
||||
</div>
|
||||
|
||||
<!-- Add custom model input -->
|
||||
<div class="add-model">
|
||||
<el-input
|
||||
v-model="customModelInput"
|
||||
:placeholder="$t('views.system.ai.addCustomModel')"
|
||||
:placeholder="t('views.system.ai.addCustomModel')"
|
||||
@keyup.enter.prevent="addCustomModel"
|
||||
>
|
||||
<template #append>
|
||||
@@ -350,7 +350,7 @@ defineOptions({ name: 'ClSystemDetailTabAi' });
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="no-custom-models">
|
||||
{{ $t('views.system.ai.noCustomModels') }}
|
||||
{{ t('views.system.ai.noCustomModels') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -415,7 +415,7 @@ defineOptions({ name: 'ClSystemDetailTabAi' });
|
||||
gap: 8px;
|
||||
|
||||
.model-checkbox {
|
||||
min-width: 200px;
|
||||
min-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user