diff --git a/packages/ui/src/components/TemplateManager.vue b/packages/ui/src/components/TemplateManager.vue
index fad83d94..c6f4c5a7 100644
--- a/packages/ui/src/components/TemplateManager.vue
+++ b/packages/ui/src/components/TemplateManager.vue
@@ -593,7 +593,16 @@ const props = defineProps<{
selectedSystemOptimizeTemplate?: Template,
selectedUserOptimizeTemplate?: Template,
selectedIterateTemplate?: Template,
- templateType: 'optimize' | 'userOptimize' | 'iterate' | 'text2imageOptimize' | 'image2imageOptimize' | 'imageIterate',
+ templateType:
+ | 'optimize'
+ | 'userOptimize'
+ | 'iterate'
+ | 'text2imageOptimize'
+ | 'image2imageOptimize'
+ | 'imageIterate'
+ | 'contextSystemOptimize'
+ | 'contextUserOptimize'
+ | 'contextIterate',
show: boolean
}>()
@@ -638,10 +647,13 @@ const migrationDialog = ref<{
const selectedTemplate = computed(() => {
switch (props.templateType) {
case 'optimize':
+ case 'contextSystemOptimize':
return props.selectedSystemOptimizeTemplate
case 'userOptimize':
+ case 'contextUserOptimize':
return props.selectedUserOptimizeTemplate
case 'iterate':
+ case 'contextIterate':
return props.selectedIterateTemplate
default:
return null
@@ -663,6 +675,12 @@ function getCategoryFromProps() {
return 'image-image2image-optimize'
case 'imageIterate':
return 'image-iterate'
+ case 'contextSystemOptimize':
+ return 'context-system-optimize'
+ case 'contextUserOptimize':
+ return 'context-user-optimize'
+ case 'contextIterate':
+ return 'context-iterate'
default:
return 'system-optimize'
}
diff --git a/packages/web/src/App.vue b/packages/web/src/App.vue
index ed60c45f..0fe2cbc6 100644
--- a/packages/web/src/App.vue
+++ b/packages/web/src/App.vue
@@ -17,8 +17,8 @@
@@ -125,23 +125,44 @@
/>
-
-
+
+
+
{{ t('template.loading') || '加载中...' }}
@@ -214,11 +235,22 @@
>
-
@@ -335,7 +367,7 @@ hljs.registerLanguage('json', jsonLang)
// UI Components
MainLayoutUI, ThemeToggleUI, ActionButtonUI, ModelManagerUI, TemplateManagerUI, HistoryDrawerUI,
LanguageSwitchDropdown, DataManagerUI, InputPanelUI, PromptPanelUI, OptimizationModeSelectorUI,
- ModelSelectUI, TemplateSelectUI, TestAreaPanel, UpdaterIcon, VariableManagerModal,
+ SelectWithConfig, TestAreaPanel, UpdaterIcon, VariableManagerModal,
ImageWorkspace, FunctionModeSelector,
ConversationManager, OutputDisplay, ContextEditor,
@@ -365,7 +397,7 @@ hljs.registerLanguage('json', jsonLang)
// Quick Template Manager
quickTemplateManager,
} from '@prompt-optimizer/ui'
- import type { IPromptService } from '@prompt-optimizer/core'
+import type { IPromptService, Template, ModelConfig } from '@prompt-optimizer/core'
// 1. 基础 composables
// highlight.js for Naive NCode
@@ -401,7 +433,6 @@ hljs.registerLanguage('json', jsonLang)
const showDataManager = ref(false)
const optimizeModelSelect = ref(null)
const testPanelRef = ref(null)
- const templateSelectRef = ref<{ refresh?: () => void } | null>(null)
const promptPanelRef = ref<{ refreshIterateTemplateSelect?: () => void } | null>(null)
// 高级模式状态
@@ -710,7 +741,156 @@ hljs.registerLanguage('json', jsonLang)
selectedIterateTemplate: toRef(optimizer, 'selectedIterateTemplate')
}
)
-
+
+ const currentSelectedTemplate = computed({
+ get() {
+ return selectedOptimizationMode.value === 'system'
+ ? optimizer.selectedOptimizeTemplate
+ : optimizer.selectedUserOptimizeTemplate
+ },
+ set(newValue) {
+ if (!newValue) return
+ if (selectedOptimizationMode.value === 'system') {
+ optimizer.selectedOptimizeTemplate = newValue
+ } else {
+ optimizer.selectedUserOptimizeTemplate = newValue
+ }
+ }
+ })
+
+ const templateOptions = ref([])
+ const textModelOptions = ref>([])
+
+ const handleOpenOptimizeTemplateManager = () => {
+ const type = templateSelectType.value
+ console.log('[App] Opening template manager for type:', type)
+ openTemplateManager(type as any)
+ }
+
+ const clearCurrentTemplateSelection = () => {
+ if (selectedOptimizationMode.value === 'system') {
+ optimizer.selectedOptimizeTemplate = null
+ } else {
+ optimizer.selectedUserOptimizeTemplate = null
+ }
+ }
+
+ const ensureTemplateSelection = () => {
+ const current = currentSelectedTemplate.value
+ const available = templateOptions.value
+
+ if (current) {
+ const matched = available.find(t => t.id === current.id)
+ if (matched) {
+ if (matched !== current) {
+ currentSelectedTemplate.value = matched
+ }
+ return
+ }
+ }
+
+ if (available.length > 0) {
+ currentSelectedTemplate.value = available[0]
+ } else {
+ clearCurrentTemplateSelection()
+ }
+ }
+
+ const refreshOptimizeTemplates = async () => {
+ if (!services.value?.templateManager) {
+ templateOptions.value = []
+ clearCurrentTemplateSelection()
+ return
+ }
+
+ try {
+ const list = await services.value.templateManager.listTemplatesByType(templateSelectType.value as any)
+ templateOptions.value = list || []
+ } catch (error) {
+ console.warn('[App] Failed to refresh optimize templates:', error)
+ templateOptions.value = []
+ }
+
+ ensureTemplateSelection()
+ }
+
+ const refreshTextModels = async () => {
+ if (!services.value?.modelManager) {
+ textModelOptions.value = []
+ return
+ }
+
+ try {
+ const manager = services.value.modelManager
+ if (typeof (manager as any).ensureInitialized === 'function') {
+ await (manager as any).ensureInitialized()
+ }
+ const enabledModels = await manager.getEnabledModels()
+ textModelOptions.value = enabledModels.map((m: ModelConfig & { key: string }) => {
+ const providerName = (m as any)?.provider ?? (m as any)?.providerId ?? 'Unknown'
+ return {
+ label: `${m.name} (${providerName})`,
+ value: m.key,
+ raw: m
+ }
+ })
+
+ const availableKeys = new Set(textModelOptions.value.map(opt => opt.value))
+ const fallbackValue = textModelOptions.value[0]?.value || ''
+
+ if (fallbackValue) {
+ if (!availableKeys.has(modelManager.selectedOptimizeModel)) {
+ modelManager.selectedOptimizeModel = fallbackValue
+ }
+ if (!availableKeys.has(modelManager.selectedTestModel)) {
+ modelManager.selectedTestModel = fallbackValue
+ }
+ }
+ } catch (error) {
+ console.warn('[App] Failed to refresh text models:', error)
+ textModelOptions.value = []
+ }
+ }
+
+ const selectedTemplateIdForSelect = computed({
+ get() {
+ const current = currentSelectedTemplate.value
+ if (!current) return ''
+ return templateOptions.value.some(t => t.id === current.id) ? current.id : ''
+ },
+ set(id: string) {
+ if (!id) {
+ clearCurrentTemplateSelection()
+ return
+ }
+ const tpl = templateOptions.value.find(t => t.id === id)
+ if (tpl) {
+ currentSelectedTemplate.value = tpl
+ }
+ }
+ })
+
+ watch(() => services.value?.templateManager, async (manager) => {
+ if (manager) {
+ await refreshOptimizeTemplates()
+ } else {
+ templateOptions.value = []
+ clearCurrentTemplateSelection()
+ }
+ }, { immediate: true })
+
+ watch(() => services.value?.modelManager, async (manager) => {
+ if (manager) {
+ await refreshTextModels()
+ } else {
+ textModelOptions.value = []
+ }
+ }, { immediate: true })
+
+ watch(() => templateSelectType.value, async () => {
+ await refreshOptimizeTemplates()
+ })
+
// 7. 监听服务初始化
watch(services, async (newServices) => {
if (!newServices) return
@@ -746,23 +926,6 @@ hljs.registerLanguage('json', jsonLang)
}, 1500)
}
- // 8. 计算属性和方法
- const currentSelectedTemplate = computed({
- get() {
- return selectedOptimizationMode.value === 'system'
- ? optimizer.selectedOptimizeTemplate
- : optimizer.selectedUserOptimizeTemplate
- },
- set(newValue) {
- if (!newValue) return
- if (selectedOptimizationMode.value === 'system') {
- optimizer.selectedOptimizeTemplate = newValue
- } else {
- optimizer.selectedUserOptimizeTemplate = newValue
- }
- }
- })
-
// 处理优化提示词
const handleOptimizePrompt = () => {
// 检查是否需要传递高级上下文
@@ -912,9 +1075,7 @@ hljs.registerLanguage('json', jsonLang)
console.log('[App] 模板语言已切换:', newLanguage)
// 刷新主界面的模板选择组件
- if (templateSelectRef.value?.refresh) {
- templateSelectRef.value.refresh()
- }
+ refreshOptimizeTemplates()
// 刷新迭代页面的模板选择组件
if (promptPanelRef.value?.refreshIterateTemplateSelect) {
@@ -933,10 +1094,11 @@ hljs.registerLanguage('json', jsonLang)
// 模板管理器关闭回调:刷新基础模式选择,同时通知图像模式刷新模板列表
const handleTemplateManagerClosed = () => {
try {
- templateManagerState.handleTemplateManagerClose(() => templateSelectRef.value?.refresh?.())
+ templateManagerState.handleTemplateManagerClose(() => { refreshOptimizeTemplates() })
} catch (e) {
console.warn('[App] Failed to run template manager close handler:', e)
}
+ refreshOptimizeTemplates()
if (typeof window !== 'undefined') {
window.dispatchEvent(new Event('image-workspace-refresh-templates'))
}
@@ -962,6 +1124,7 @@ hljs.registerLanguage('json', jsonLang)
} catch (e) {
console.warn('[App] Failed to refresh text models after manager close:', e)
}
+ await refreshTextModels()
// 图像模式:广播刷新图像模型事件(ImageWorkspace 监听并执行刷新)
if (typeof window !== 'undefined') {
window.dispatchEvent(new Event('image-workspace-refresh-image-models'))