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:
Marvin Zhang
2025-04-18 16:58:42 +08:00
parent 32f0802f8b
commit de680d8ebd
7 changed files with 66 additions and 59 deletions

View File

@@ -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>

View File

@@ -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,
};
};

View File

@@ -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>

View File

@@ -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(':');

View File

@@ -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;
}

View File

@@ -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'],
},
{

View File

@@ -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;
}
}