refactor: Synchronize core and UI package interfaces with async/sync method transformations

- Modify TemplateManager to use synchronous methods instead of async
- Update core service interfaces to remove async/await requirements
- Simplify initialization and method calls across core and UI packages
- Remove unnecessary async/await wrappers in composables and components
- Enhance error handling and logging during service initialization
- Standardize method signatures in template, history, and model managers
This commit is contained in:
linshen committed 2025-02-17 21:19:51 +08:00
1 parent 27f03a40f2
commit 653772ca78
22 files changed
+2537 -637

No files matched your search

+43 -8
View File
@@ -3,25 +3,60 @@
"version": "0.0.1",
"private": true,
"scripts": {
"dev:core": "pnpm -F @prompt-optimizer/core dev",
"dev:ui": "pnpm -F @prompt-optimizer/ui dev",
"dev:web": "pnpm -F @prompt-optimizer/web dev",
"dev:ext": "pnpm -F @prompt-optimizer/extension dev",
"build:core": "pnpm -F @prompt-optimizer/core build",
"build:ui": "pnpm -F @prompt-optimizer/ui build",
"build:web": "pnpm -F @prompt-optimizer/web build",
"build:ext": "pnpm -F @prompt-optimizer/extension build",
"watch:ui": "pnpm -F @prompt-optimizer/ui build --watch",
"dev:web": "pnpm -F @prompt-optimizer/web dev",
"dev:ext": "pnpm -F @prompt-optimizer/extension dev",
"test:core": "pnpm -F @prompt-optimizer/core test",
"test:ui": "pnpm -F @prompt-optimizer/ui test",
"test:web": "pnpm -F @prompt-optimizer/web test",
"test:ext": "pnpm -F @prompt-optimizer/extension test",
"test": "pnpm -r test",
"build": "pnpm -r build"
"build": "pnpm -r build",
"clean:core": "rimraf packages/core/dist",
"clean:ui": "rimraf packages/ui/dist",
"clean:web": "rimraf packages/web/dist",
"clean:ext": "rimraf packages/extension/dist",
"clean:vite:core": "rimraf packages/core/node_modules/.vite",
"clean:vite:ui": "rimraf packages/ui/node_modules/.vite",
"clean:vite:web": "rimraf packages/web/node_modules/.vite",
"clean:vite:ext": "rimraf packages/extension/node_modules/.vite",
"clean:vite": "run-s clean:vite:core clean:vite:ui clean:vite:web clean:vite:ext",
"clean": "run-s clean:core clean:ui clean:web clean:ext clean:vite",
"setup:install": "pnpm install",
"dev:setup": "run-s clean build:core build:ui",
"dev:parallel": "concurrently -k -p \"[{name}]\" -n \"UI,WEB\" \"pnpm run watch:ui\" \"pnpm run dev:web\"",
"dev": "run-s dev:setup dev:parallel",
"dev:fresh": "run-s clean setup:install dev"
},
"devDependencies": {
"concurrently": "^8.2.2",
"cross-env": "^7.0.3",
"npm-run-all": "^4.1.5",
"rimraf": "^4.4.1",
"typescript": "^5.0.0"
},
"dependencies": {
"@ctrl/tinycolor": "^4.1.0",
"@element-plus/icons-vue": "^2.3.1",
"@floating-ui/core": "^1.6.9",
"@floating-ui/dom": "^1.6.13",
"@floating-ui/utils": "^0.2.9",
"@popperjs/core": "^2.11.8",
"@vue/reactivity": "^3.5.13",
"@vue/runtime-core": "^3.5.13",
"@vue/runtime-dom": "^3.5.13",
"@vue/shared": "^3.5.13",
"@vueuse/core": "^12.7.0",
"@vueuse/shared": "^12.7.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.13",
"lodash-es": "^4.17.21",
"lodash-unified": "^1.0.3",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0"
}
}
@@ -13,7 +13,7 @@ export class HistoryManager implements IHistoryManager {
/**
* 初始化历史记录管理器
*/
async init(): Promise<void> {
init(): void {
try {
// 验证存储是否可用
const testKey = '_test_storage_';
+1 -1
View File
@@ -48,7 +48,7 @@ export interface PromptRecordChain {
*/
export interface IHistoryManager {
/** 初始化历史记录管理器 */
init(): Promise<void>;
init(): void;
/** 添加记录 */
addRecord(record: PromptRecord): void;
/** 获取所有记录 */
@@ -63,7 +63,6 @@ export class ModelManager implements IModelManager {
...config,
key
}));
console.log('获取所有模型配置:', returnValue);
return returnValue;
}
+2 -4
View File
@@ -404,15 +404,13 @@ export class PromptService implements IPromptService {
}
// 导出工厂函数
export async function createPromptService(
export function createPromptService(
modelManager: ModelManager = defaultModelManager,
llmService: LLMService = createLLMService(modelManager),
templateManager: TemplateManager = defaultTemplateManager,
historyManager: HistoryManager = defaultHistoryManager
): Promise<PromptService> {
): PromptService {
try {
await templateManager.init();
await historyManager.init();
return new PromptService(modelManager, llmService, templateManager, historyManager);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
@@ -194,7 +194,7 @@ export const DEFAULT_TEMPLATES: Record<string, Template> = {
},
'iterate': {
id: 'iterate',
name: '提示词迭代优化',
name: '通用迭代',
content: `# Role:提示词迭代优化专家
## Background:
@@ -229,16 +229,18 @@ export const DEFAULT_TEMPLATES: Record<string, Template> = {
3. 确保修改符合用户的优化需求
4. 避免过度修改导致提示词效果降低
5. 保持提示词的可读性和结构性
6. 只需要输出优化后的Prompt,使用原有格式,不要输出多余解释或引导词
7. 优化需求是针对原始提示词的
## Workflow:
1. 分析原有提示词,提取核心意图和关键结构
2. 理解用户的优化需求,确定优化方向
3. 在保持核心意图的基础上进行定向优化
3. 在保持核心意图的基础上对原始提示词进行定向优化
4. 检查优化结果是否符合预期
5. 输出优化后的提示词,不要输出多余解释或引导词
## Initialization:
我会给出原始提示词和优化需求,请根据我的优化需求,在保持核心意图的基础上进行定向优化。
我会给出原始提示词和优化需求,请根据我的优化需求,在保持核心意图的基础上对原始提示词进行定向优化。
请避免讨论我发送的内容,只需要输出优化后的Prompt,使用原有格式,不要输出多余解释或引导词。
`,
metadata: {
+33 -31
View File
@@ -18,12 +18,15 @@ export class TemplateManager implements ITemplateManager {
cacheTimeout: 5 * 60 * 1000,
...config
};
// 在构造函数中执行初始化
this.init();
}
/**
* 初始化提示词管理器
* 私有初始化方法
*/
async init(): Promise<void> {
private init(): void {
try {
// 需要先清空已有提示词避免重复加载
this.builtinTemplates.clear();
@@ -42,9 +45,10 @@ export class TemplateManager implements ITemplateManager {
throw new TemplateError('内置提示词加载失败');
}
await this.loadUserTemplates();
this.loadUserTemplates();
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error('模板管理器初始化失败:', errorMessage);
throw new TemplateError(`初始化失败: ${errorMessage}`);
}
}
@@ -52,7 +56,7 @@ export class TemplateManager implements ITemplateManager {
/**
* 获取提示词
*/
async getTemplate(templateId: string): Promise<Template> {
getTemplate(templateId: string): Template {
// 增加空值校验
if (!templateId || typeof templateId !== 'string') {
throw new TemplateError('无效的提示词ID');
@@ -64,7 +68,7 @@ export class TemplateManager implements ITemplateManager {
if (!template) {
// 增加调试信息
console.debug('可用提示词:', [...this.builtinTemplates.keys(), ...this.userTemplates.keys()]);
console.error(`提示词 ${templateId} 不存在, 可用提示词:`, [...this.builtinTemplates.keys(), ...this.userTemplates.keys()]);
throw new TemplateError(`提示词 ${templateId} 不存在`);
}
@@ -75,7 +79,7 @@ export class TemplateManager implements ITemplateManager {
/**
* 保存用户提示词
*/
async saveTemplate(template: Template): Promise<void> {
saveTemplate(template: Template): void {
// 增加类型校验
if (!['optimize', 'iterate'].includes(template.metadata.templateType)) {
throw new TemplateValidationError('无效的提示词类型');
@@ -118,13 +122,13 @@ export class TemplateManager implements ITemplateManager {
// 保存提示词
this.userTemplates.set(template.id, { ...template, isBuiltin: false });
await this.persistUserTemplates();
this.persistUserTemplates();
}
/**
* 删除用户提示词
*/
async deleteTemplate(templateId: string): Promise<void> {
deleteTemplate(templateId: string): void {
if (this.builtinTemplates.has(templateId)) {
throw new TemplateError(`不能删除内置提示词: ${templateId}`);
}
@@ -134,18 +138,17 @@ export class TemplateManager implements ITemplateManager {
}
this.userTemplates.delete(templateId);
await this.persistUserTemplates();
this.persistUserTemplates();
}
/**
* 列出所有提示词
*/
async listTemplates(): Promise<Template[]> {
listTemplates(): Template[] {
const templates = [
...Array.from(this.builtinTemplates.values()),
...Array.from(this.userTemplates.values())
];
return templates.sort((a, b) => {
// 内置提示词排在前面
if (a.isBuiltin !== b.isBuiltin) {
@@ -178,7 +181,7 @@ export class TemplateManager implements ITemplateManager {
/**
* 导入提示词
*/
async importTemplate(templateJson: string): Promise<void> {
importTemplate(templateJson: string): void {
try {
const template = JSON.parse(templateJson) as Template;
const result = templateSchema.safeParse(template);
@@ -186,7 +189,7 @@ export class TemplateManager implements ITemplateManager {
throw new TemplateValidationError(`提示词验证失败: ${result.error.errors.map((e: { message: string }) => e.message).join(', ')}`);
}
this.userTemplates.set(template.id, template);
await this.persistUserTemplates();
this.persistUserTemplates();
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
throw new TemplateError(`导入提示词失败: ${errorMessage}`);
@@ -207,7 +210,7 @@ export class TemplateManager implements ITemplateManager {
/**
* 持久化用户提示词
*/
private async persistUserTemplates(): Promise<void> {
private persistUserTemplates(): void {
try {
const templates = Array.from(this.userTemplates.values());
localStorage.setItem(this.config.storageKey, JSON.stringify(templates));
@@ -220,7 +223,7 @@ export class TemplateManager implements ITemplateManager {
/**
* 加载用户提示词
*/
private async loadUserTemplates(): Promise<void> {
private loadUserTemplates(): void {
try {
const data = localStorage.getItem(this.config.storageKey);
if (data) {
@@ -236,28 +239,27 @@ export class TemplateManager implements ITemplateManager {
}
/**
* 按类型列出提示词
* 根据提示词类型获取提示词列表
* @deprecated 使用 listTemplatesByType 替代
*/
listTemplatesByType(type: 'optimize' | 'iterate'): Template[] {
return [...this.builtinTemplates.values(), ...this.userTemplates.values()].filter(
template => template.metadata.templateType === type
);
getTemplatesByType(type: 'optimize' | 'iterate'): Template[] {
return this.listTemplatesByType(type);
}
/**
* 根据提示词类型获取提示词列表
* @param type 提示词类型 ('optimize' | 'iterate')
* @returns 指定类型的提示词列表
* 按类型列出提示词
*/
async getTemplatesByType(type: 'optimize' | 'iterate'): Promise<Template[]> {
return this.listTemplatesByType(type);
listTemplatesByType(type: 'optimize' | 'iterate'): Template[] {
try {
return this.listTemplates().filter(
template => template.metadata.templateType === type
);
} catch (error) {
console.error(`获取${type}类型模板列表失败:`, error);
return [];
}
}
}
// 导出单例实例
export const templateManager = new TemplateManager();
// 初始化提示词管理器
templateManager.init().catch(error => {
console.error('提示词管理器初始化失败:', error);
});
export const templateManager = new TemplateManager();
+27 -8
View File
@@ -39,16 +39,35 @@ export interface TemplateManagerConfig {
* 提示词管理器接口
*/
export interface ITemplateManager {
init(): Promise<void>;
getTemplate(templateId: string): Promise<Template>;
saveTemplate(template: Template): Promise<void>;
deleteTemplate(templateId: string): Promise<void>;
listTemplates(): Promise<Template[]>;
/** 获取指定ID的模板 */
getTemplate(templateId: string): Template;
/** 保存模板 */
saveTemplate(template: Template): void;
/** 删除模板 */
deleteTemplate(templateId: string): void;
/** 列出所有模板 */
listTemplates(): Template[];
/** 导出模板 */
exportTemplate(templateId: string): string;
importTemplate(templateJson: string): Promise<void>;
/** 导入模板 */
importTemplate(templateJson: string): void;
/** 清除缓存 */
clearCache(templateId?: string): void;
/** 根据类型获取提示词列表 */
getTemplatesByType(type: 'optimize' | 'iterate'): Promise<Template[]>;
/** 按类型列出模板 */
listTemplatesByType(type: 'optimize' | 'iterate'): Template[];
/**
* 根据类型获取模板列表(已废弃)
* @deprecated 使用 listTemplatesByType 替代
*/
getTemplatesByType(type: 'optimize' | 'iterate'): Template[];
}
/**
+14 -26
View File
@@ -3,51 +3,39 @@
"version": "0.0.1",
"private": true,
"type": "module",
"main": "./dist/index.js",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"style": "./dist/style.css",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.umd.cjs"
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
},
"./style.css": "./dist/style.css"
"./style.css": "./dist/style.css",
"./dist/style.css": "./dist/style.css"
},
"files": [
"dist"
],
"scripts": {
"dev": "vite",
"dev": "vite build --watch",
"build": "vite build",
"preview": "vite preview",
"test": "vitest",
"test:coverage": "vitest run --coverage"
"test": "vitest"
},
"dependencies": {
"@prompt-optimizer/core": "workspace:*",
"element-plus": "^2.9.3",
"element-plus": "^2.5.6",
"uuid": "^11.0.5",
"vue": "^3.4.15"
"vue": "^3.3.4"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "^0.5.16",
"@types/node": "^20.11.17",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-vue": "^5.0.3",
"@vue/runtime-core": "^3.4.15",
"@vue/runtime-dom": "3.4.15",
"@vitejs/plugin-vue": "^4.2.3",
"@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.20",
"postcss": "^8.5.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.2.2",
"vite": "^5.0.12",
"vitest": "^1.2.2",
"vue-tsc": "^1.8.27"
},
"peerDependencies": {
"vue": "^3.4.15"
"typescript": "^5.0.0",
"vite": "^4.4.9",
"vitest": "^0.34.3"
}
}
@@ -0,0 +1,127 @@
<template>
<ContentCardUI>
<!-- 输入区域 -->
<div class="flex-none">
<InputPanelUI
v-model="prompt"
v-model:selectedModel="selectedOptimizeModel"
label="原始提示词"
placeholder="请输入需要优化的prompt..."
model-label="优化模型"
template-label="优化提示词"
button-text="开始优化 →"
loading-text="优化中..."
:loading="isOptimizing"
:disabled="isOptimizing"
@submit="handleOptimizePrompt"
@configModel="$emit('showConfig')"
>
<template #model-select>
<ModelSelectUI
ref="optimizeModelSelect"
:modelValue="selectedOptimizeModel"
@update:modelValue="selectedOptimizeModel = $event"
:disabled="isOptimizing"
@config="$emit('showConfig')"
/>
</template>
<template #template-select>
<TemplateSelectUI
v-model="selectedOptimizeTemplate"
type="optimize"
@manage="$emit('openTemplateManager', 'optimize')"
@select="handleTemplateSelect"
/>
</template>
</InputPanelUI>
</div>
<!-- 优化结果区域 -->
<div class="flex-1 min-h-0 overflow-y-auto">
<PromptPanelUI
v-model:optimized-prompt="optimizedPrompt"
:is-iterating="isIterating"
v-model:selected-iterate-template="selectedIterateTemplate"
:versions="currentVersions"
:current-version-id="currentVersionId"
@iterate="handleIteratePrompt"
@openTemplateManager="$emit('openTemplateManager', $event)"
@switchVersion="handleSwitchVersion"
/>
</div>
</ContentCardUI>
</template>
<script setup>
import { ref } from 'vue'
import { usePromptOptimizer } from '../composables/usePromptOptimizer'
import ContentCardUI from './ContentCard.vue'
import InputPanelUI from './InputPanel.vue'
import ModelSelectUI from './ModelSelect.vue'
import TemplateSelectUI from './TemplateSelect.vue'
import PromptPanelUI from './PromptPanel.vue'
const props = defineProps({
modelManager: {
type: Object,
required: true
},
templateManager: {
type: Object,
required: true
},
historyManager: {
type: Object,
required: true
},
promptService: {
type: Object,
required: true
}
})
const emit = defineEmits(['showConfig', 'openTemplateManager'])
const optimizeModelSelect = ref(null)
const {
prompt,
optimizedPrompt,
isOptimizing,
isIterating,
selectedOptimizeTemplate,
selectedIterateTemplate,
selectedOptimizeModel,
currentVersions,
currentVersionId,
currentChainId,
handleOptimizePrompt,
handleIteratePrompt,
handleSwitchVersion,
handleTemplateSelect,
saveTemplateSelection,
initTemplateSelection,
handleModelSelect,
initModelSelection,
loadModels
} = usePromptOptimizer(
props.modelManager,
props.templateManager,
props.historyManager,
props.promptService
)
// 暴露需要的方法和属性给父组件
defineExpose({
prompt,
optimizedPrompt,
currentChainId,
currentVersions,
currentVersionId,
optimizeModelSelect,
initTemplateSelection,
initModelSelection,
loadModels,
saveTemplateSelection
})
</script>
+13 -18
View File
@@ -314,11 +314,9 @@ const selectedTemplate = computed(() => {
})
// 加载提示词列表
const loadTemplates = async () => {
const loadTemplates = () => {
try {
// 确保提示词管理器重新初始化
await templateManager.init()
const allTemplates = await templateManager.listTemplates()
const allTemplates = templateManager.listTemplates()
templates.value = allTemplates
console.log('加载到的提示词:', templates.value)
} catch (error) {
@@ -366,7 +364,7 @@ const cancelEdit = () => {
}
// 提交表单
const handleSubmit = async () => {
const handleSubmit = () => {
try {
const templateData = {
id: editingTemplate.value?.id || `template-${Date.now()}`,
@@ -382,20 +380,17 @@ const handleSubmit = async () => {
}
// 先保存模板
await templateManager.saveTemplate(templateData)
// 确保数据已更新
await templateManager.init()
templateManager.saveTemplate(templateData)
// 重新加载列表
await loadTemplates()
loadTemplates()
// 如果编辑的是当前选中的提示词,只更新其内容
const isCurrentSelected = (currentType.value === 'optimize' && props.selectedOptimizeTemplate?.id === templateData.id) ||
(currentType.value === 'iterate' && props.selectedIterateTemplate?.id === templateData.id)
if (editingTemplate.value && isCurrentSelected) {
const updatedTemplate = await templateManager.getTemplate(templateData.id)
const updatedTemplate = templateManager.getTemplate(templateData.id)
if (updatedTemplate) {
// 通知父组件更新模板内容,但保持选中状态
emit('select', updatedTemplate, currentType.value)
@@ -411,11 +406,11 @@ const handleSubmit = async () => {
}
// 确认删除
const confirmDelete = async (templateId) => {
const confirmDelete = (templateId) => {
if (confirm('确定要删除这个提示词吗?此操作不可恢复。')) {
try {
await templateManager.deleteTemplate(templateId)
await loadTemplates()
templateManager.deleteTemplate(templateId)
loadTemplates()
// 如果删除的是当前选中的提示词,清空选择
if (currentType.value === 'optimize' && props.selectedOptimizeTemplate?.id === templateId) {
@@ -453,16 +448,16 @@ const exportTemplate = (templateId) => {
}
// 导入提示词
const handleFileImport = async (event) => {
const handleFileImport = (event) => {
const file = event.target.files[0]
if (!file) return
try {
const reader = new FileReader()
reader.onload = async (e) => {
reader.onload = (e) => {
try {
await templateManager.importTemplate(e.target.result)
await loadTemplates()
templateManager.importTemplate(e.target.result)
loadTemplates()
toast.success('提示词已导入')
event.target.value = '' // 清空文件输入
} catch (error) {
@@ -121,6 +121,7 @@ const handleResize = () => {
onMounted(() => {
window.addEventListener('resize', handleResize)
refreshTemplates()
})
onBeforeUnmount(() => {
@@ -138,13 +139,10 @@ watch(isOpen, async (newValue) => {
}
})
const typeText = computed(() => {
return props.type === 'iterate' ? '迭代功能提示词' : '优化功能提示词'
})
const templates = computed(() => {
// 使用 refreshTrigger 触发重新计算
refreshTrigger.value
console.log('重新计算templates', templateManager.listTemplatesByType(props.type))
return templateManager.listTemplatesByType(props.type)
})
@@ -153,6 +151,11 @@ const refreshTemplates = () => {
refreshTrigger.value++
}
// 暴露刷新方法给父组件
defineExpose({
refresh: refreshTemplates
})
const selectTemplate = (template) => {
emit('update:modelValue', template)
emit('select', template, props.type)
+81
View File
@@ -0,0 +1,81 @@
<template>
<ContentCardUI>
<!-- 测试输入区域 -->
<div class="flex-none">
<InputPanelUI
v-model="testContent"
v-model:selectedModel="selectedTestModel"
label="测试输入"
placeholder="请输入要测试的内容..."
model-label="模型"
button-text="开始测试 →"
loading-text="测试中..."
:loading="isTesting"
:disabled="isTesting"
@submit="() => handleTest(optimizedPrompt)"
@configModel="$emit('showConfig')"
>
<template #model-select>
<ModelSelectUI
ref="testModelSelect"
:modelValue="selectedTestModel"
@update:modelValue="selectedTestModel = $event"
:disabled="isTesting"
@config="$emit('showConfig')"
/>
</template>
</InputPanelUI>
</div>
<!-- 测试结果区域 -->
<div class="flex-1 min-h-0 overflow-y-auto">
<OutputPanelUI
ref="outputPanelRef"
:loading="isTesting"
:error="testError"
:result="testResult"
/>
</div>
</ContentCardUI>
</template>
<script setup>
import { ref, toRef } from 'vue'
import { usePromptTester } from '../composables/usePromptTester'
import ContentCardUI from './ContentCard.vue'
import InputPanelUI from './InputPanel.vue'
import ModelSelectUI from './ModelSelect.vue'
import OutputPanelUI from './OutputPanel.vue'
const props = defineProps({
promptService: {
type: [Object, null],
required: true
},
optimizedPrompt: {
type: String,
required: true
}
})
const emit = defineEmits(['showConfig'])
const testModelSelect = ref(null)
const outputPanelRef = ref(null)
const selectedTestModel = ref('')
const promptServiceRef = toRef(props, 'promptService')
const {
testContent,
testResult,
testError,
isTesting,
handleTest
} = usePromptTester(promptServiceRef, selectedTestModel)
// 暴露需要的方法和属性给父组件
defineExpose({
testModelSelect,
selectedTestModel
})
</script>
+60
View File
@@ -0,0 +1,60 @@
import { ref } from 'vue'
import { useToast } from './useToast'
export function useModals(
templateManager: any,
optimizeModelSelect: any,
testModelSelect: any,
loadModels: () => Promise<void>,
initTemplateSelection: () => Promise<void>
) {
const toast = useToast()
// 弹窗状态
const showConfig = ref(false)
const showHistory = ref(false)
const showTemplates = ref(false)
const currentType = ref('optimize')
// 打开提示词管理器
const openTemplateManager = (type = 'optimize') => {
currentType.value = type
showTemplates.value = true
}
// 加载提示词模板
const loadTemplates = async () => {
try {
await templateManager.init()
await initTemplateSelection()
toast.success('提示词列表已更新')
} catch (error) {
console.error('加载提示词失败:', error)
toast.error('加载提示词失败')
}
}
// 关闭提示词管理器
const handleTemplateManagerClose = async () => {
await loadTemplates()
showTemplates.value = false
}
// 关闭模型管理器
const handleModelManagerClose = async () => {
await loadModels()
optimizeModelSelect.value?.refresh()
testModelSelect.value?.refresh()
showConfig.value = false
}
return {
showConfig,
showHistory,
showTemplates,
currentType,
openTemplateManager,
handleTemplateManagerClose,
handleModelManagerClose
}
}
@@ -53,9 +53,8 @@ export function usePromptHistory(
}
}
const initHistory = async () => {
const initHistory = () => {
try {
await historyManager.init()
history.value = historyManager.getAllChains()
} catch (error) {
console.error('加载历史记录失败:', error)
@@ -177,20 +177,24 @@ export function usePromptOptimizer(
}
// 初始化提示词选择
const initTemplateSelection = async () => {
const initTemplateSelection = () => {
try {
// 加载优化提示词
const optimizeTemplateId = localStorage.getItem(STORAGE_KEYS.OPTIMIZE_TEMPLATE)
if (optimizeTemplateId) {
const optimizeTemplate = await templateManager.getTemplate(optimizeTemplateId)
if (optimizeTemplate) {
selectedOptimizeTemplate.value = optimizeTemplate
try {
const optimizeTemplate = templateManager.getTemplate(optimizeTemplateId)
if (optimizeTemplate) {
selectedOptimizeTemplate.value = optimizeTemplate
}
} catch (error) {
console.warn('加载已保存的优化提示词失败:', error)
}
}
// 如果没有已保存的提示词或加载失败,使用该类型的第一个提示词
if (!selectedOptimizeTemplate.value) {
const optimizeTemplates = await templateManager.getTemplatesByType('optimize')
const optimizeTemplates = templateManager.listTemplatesByType('optimize')
if (optimizeTemplates.length > 0) {
selectedOptimizeTemplate.value = optimizeTemplates[0]
}
@@ -199,15 +203,19 @@ export function usePromptOptimizer(
// 加载迭代提示词
const iterateTemplateId = localStorage.getItem(STORAGE_KEYS.ITERATE_TEMPLATE)
if (iterateTemplateId) {
const iterateTemplate = await templateManager.getTemplate(iterateTemplateId)
if (iterateTemplate) {
selectedIterateTemplate.value = iterateTemplate
try {
const iterateTemplate = templateManager.getTemplate(iterateTemplateId)
if (iterateTemplate) {
selectedIterateTemplate.value = iterateTemplate
}
} catch (error) {
console.warn('加载已保存的迭代提示词失败:', error)
}
}
// 如果没有已保存的提示词或加载失败,使用该类型的第一个提示词
if (!selectedIterateTemplate.value) {
const iterateTemplates = await templateManager.getTemplatesByType('iterate')
const iterateTemplates = templateManager.listTemplatesByType('iterate')
if (iterateTemplates.length > 0) {
selectedIterateTemplate.value = iterateTemplates[0]
}
@@ -217,7 +225,7 @@ export function usePromptOptimizer(
if (!selectedOptimizeTemplate.value || !selectedIterateTemplate.value) {
throw new Error('无法加载默认提示词')
}
} catch (error: any) {
} catch (error) {
console.error('加载提示词失败:', error)
toast.error('加载提示词失败')
}
@@ -234,7 +242,7 @@ export function usePromptOptimizer(
}
// 初始化模型选择
const initModelSelection = async () => {
const initModelSelection = () => {
try {
const enabledModels = modelManager.getAllModels().filter(m => m.enabled)
const defaultModel = enabledModels[0]?.key
@@ -256,7 +264,7 @@ export function usePromptOptimizer(
saveModelSelection(selectedOptimizeModel.value, 'optimize')
saveModelSelection(selectedTestModel.value, 'test')
}
} catch (error: any) {
} catch (error) {
console.error('初始化模型选择失败:', error)
toast.error('初始化模型选择失败')
}
@@ -312,7 +320,8 @@ export function usePromptOptimizer(
// 在 onMounted 中初始化
onMounted(async () => {
await initModelSelection()
initModelSelection()
initTemplateSelection() // 添加模板初始化
})
return {
+15 -2
View File
@@ -17,12 +17,25 @@ export { default as ApiKeyConfigUI } from './components/ApiKeyConfig.vue'
export { default as MainLayoutUI } from './components/MainLayout.vue'
export { default as ContentCardUI } from './components/ContentCard.vue'
export { default as ActionButtonUI } from './components/ActionButton.vue'
export { default as OptimizePanelUI } from './components/OptimizePanel.vue'
export { default as TestPanelUI } from './components/TestPanel.vue'
// 导出指令
export { clickOutside } from './directives/clickOutside'
// 导出组合式函数
export { useToast } from './composables/useToast'
export { usePromptOptimizer } from './composables/usePromptOptimizer'
export { usePromptTester } from './composables/usePromptTester'
export { usePromptHistory } from './composables/usePromptHistory'
export { useToast } from './composables/useToast'
export { usePromptHistory } from './composables/usePromptHistory'
export { useModals } from './composables/useModals'
// 从core重新导出需要的内容
export {
templateManager,
modelManager,
historyManager,
createLLMService,
createPromptService
} from '@prompt-optimizer/core'
+15 -5
View File
@@ -8,17 +8,27 @@ export default defineConfig({
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'PromptOptimizerUI',
fileName: (format) => `index.${format === 'es' ? 'js' : 'umd.cjs'}`,
formats: ['es']
fileName: (format) => `index.${format === 'es' ? 'js' : 'cjs'}`,
formats: ['es', 'cjs']
},
watch: process.env.NODE_ENV === 'development' ? {} : null,
sourcemap: true,
rollupOptions: {
external: ['vue'],
external: ['vue', '@prompt-optimizer/core', 'element-plus', 'element-plus/dist/index.css', 'uuid'],
output: {
globals: {
vue: 'Vue'
vue: 'Vue',
'@prompt-optimizer/core': 'PromptOptimizerCore',
'element-plus': 'ElementPlus',
'uuid': 'uuid'
},
assetFileNames: (assetInfo) => {
if (assetInfo.name === 'style.css') return 'style.css';
return `assets/${assetInfo.name}`;
}
}
}
},
cssCodeSplit: false
},
assetsInclude: ['**/*.jpg', '**/*.jpeg', '**/*.png', '**/*.svg']
})
-1
View File
@@ -17,7 +17,6 @@
"@langchain/core": "^0.3.33",
"@langchain/google-genai": "^0.1.6",
"@langchain/openai": "^0.3.17",
"@prompt-optimizer/core": "workspace:*",
"@prompt-optimizer/ui": "workspace:*",
"dotenv": "^16.4.7",
"element-plus": "^2.9.3",
+107 -70
View File
@@ -154,16 +154,10 @@
</template>
<script setup>
import '@prompt-optimizer/ui/style.css'
import { ref, onMounted, watch } from 'vue'
import {
createLLMService,
createPromptService,
modelManager,
templateManager,
historyManager
} from '@prompt-optimizer/core'
import '@prompt-optimizer/ui/dist/style.css'
import { ref, onMounted, watch, nextTick } from 'vue'
import {
// UI组件
ToastUI,
ModelManagerUI,
OutputPanelUI,
@@ -176,10 +170,17 @@ import {
MainLayoutUI,
ContentCardUI,
ActionButtonUI,
// composables
usePromptOptimizer,
usePromptTester,
useToast,
usePromptHistory
usePromptHistory,
// 服务
createLLMService,
createPromptService,
modelManager,
templateManager,
historyManager
} from '@prompt-optimizer/ui'
// 初始化服务
@@ -199,6 +200,28 @@ const currentType = ref('optimize') // 默认为优化提示词
const optimizeModelSelect = ref(null)
const testModelSelect = ref(null)
// 初始化基础服务
const initBaseServices = () => {
try {
console.log('开始初始化基础服务...')
// 初始化历史记录管理器(同步操作)
console.log('初始化历史记录管理器...')
historyManager.init()
// 获取并验证模板列表
const templates = templateManager.listTemplates()
console.log('模板列表:', templates)
} catch (error) {
console.error('初始化基础服务失败:', error)
toast.error('初始化失败:' + (error instanceof Error ? error.message : String(error)))
throw error
}
}
// 先初始化基础服务
initBaseServices()
// 初始化组合式函数
const {
prompt,
@@ -244,29 +267,79 @@ const {
currentVersionId
)
// 初始化 promptService
const initServices = async () => {
// 初始化其他服务
const initOtherServices = () => {
try {
promptServiceRef.value = await createPromptService(modelManager, llmService)
console.log('初始化其他服务...')
// 初始化其他数据(同步操作)
console.log('初始化模型选择...')
initModelSelection()
console.log('初始化历史记录...')
initHistory()
console.log('初始化模板选择...')
initTemplateSelection()
// 创建提示词服务
console.log('创建提示词服务...')
promptServiceRef.value = createPromptService(modelManager, llmService, templateManager, historyManager)
console.log('初始化完成', {
optimizeTemplate: selectedOptimizeTemplate.value?.name,
iterateTemplate: selectedIterateTemplate.value?.name
})
} catch (error) {
console.error('服务初始化失败:', error)
toast.error('服务初始化失败')
console.error('初始化其他服务失败:', error)
toast.error('初始化失败:' + (error instanceof Error ? error.message : String(error)))
}
}
// 生命周期钩子
onMounted(() => {
initOtherServices()
})
// 修改提示词选择处理函数
const handleTemplateSelect = async (template, type) => {
// 获取最新的模板数据
const updatedTemplate = template ? await templateManager.getTemplate(template.id) : null
if (type === 'optimize') {
selectedOptimizeTemplate.value = updatedTemplate
} else {
selectedIterateTemplate.value = updatedTemplate
const handleTemplateSelect = (template, type) => {
try {
console.log('选择模板:', {
template: template ? {
id: template.id,
name: template.name,
type: template.metadata?.templateType
} : null,
type
})
// 解构模板ID,避免直接使用Proxy对象
const templateId = String(template.id)
const updatedTemplate = templateManager.getTemplate(templateId)
console.log('获取到更新后的模板:', updatedTemplate ? {
id: updatedTemplate.id,
name: updatedTemplate.name,
type: updatedTemplate.metadata?.templateType
} : null)
if (!updatedTemplate) {
throw new Error(`无法加载模板: ${templateId}`)
}
if (type === 'optimize') {
selectedOptimizeTemplate.value = updatedTemplate
console.log('已更新优化模板:', selectedOptimizeTemplate.value?.name)
} else {
selectedIterateTemplate.value = updatedTemplate
console.log('已更新迭代模板:', selectedIterateTemplate.value?.name)
}
saveTemplateSelection(updatedTemplate, type)
toast.success(`已选择${type === 'optimize' ? '优化' : '迭代'}提示词: ${updatedTemplate.name || '无'}`)
} catch (error) {
console.error('选择提示词失败:', error)
toast.error('选择提示词失败:' + (error instanceof Error ? error.message : String(error)))
}
await saveTemplateSelection(updatedTemplate, type)
toast.success(`已选择${type === 'optimize' ? '优化' : '迭代'}提示词: ${updatedTemplate?.name || '无'}`)
}
// 打开提示词管理器
@@ -275,39 +348,15 @@ const openTemplateManager = (type = 'optimize') => {
showTemplates.value = true
}
const loadTemplates = async () => {
try {
// 确保模板管理器重新初始化
await templateManager.init()
// 重新初始化模板选择
await initTemplateSelection()
// 同步当前选中的模板
if (selectedOptimizeTemplate.value) {
const template = await templateManager.getTemplate(selectedOptimizeTemplate.value.id)
if (template) {
selectedOptimizeTemplate.value = template
}
}
if (selectedIterateTemplate.value) {
const template = await templateManager.getTemplate(selectedIterateTemplate.value.id)
if (template) {
selectedIterateTemplate.value = template
}
}
toast.success('提示词列表已更新')
} catch (error) {
console.error('加载提示词失败:', error)
toast.error('加载提示词失败')
}
}
// 监听模板选择变化
watch([selectedOptimizeTemplate, selectedIterateTemplate], () => {
console.log('模板选择已更新:', {
optimize: selectedOptimizeTemplate.value?.name,
iterate: selectedIterateTemplate.value?.name
})
})
// 修改 handleTemplateManagerClose 方法
const handleTemplateManagerClose = async () => {
// 先更新数据
await loadTemplates()
// 最后关闭界面
const handleTemplateManagerClose = () => {
showTemplates.value = false
}
@@ -326,18 +375,6 @@ const handleModelManagerClose = async () => {
const handleModelsUpdated = (modelKey) => {
// 如果需要,可以在这里处理模型更新后的其他逻辑
}
// 生命周期钩子
onMounted(async () => {
await initServices()
await initModelSelection()
// 初始化历史记录管理器
await initHistory()
// 初始化提示词选择
await initTemplateSelection()
})
</script>
<style>
@@ -2,7 +2,7 @@ import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// https://vite.dev/config/
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
// 加载环境变量
const env = loadEnv(mode, process.cwd())
@@ -11,7 +11,11 @@ export default defineConfig(({ mode }) => {
plugins: [vue()],
server: {
port: 18181,
host: true
host: true,
fs: {
// 允许为工作区依赖提供服务
allow: ['..']
}
},
build: {
rollupOptions: {
@@ -22,12 +26,16 @@ export default defineConfig(({ mode }) => {
},
publicDir: 'public',
resolve: {
preserveSymlinks: true,
alias: {
'@': resolve(__dirname, 'src')
'@': resolve(__dirname, 'src'),
'@prompt-optimizer/ui': resolve(__dirname, '../ui'),
'@prompt-optimizer/ui/dist/style.css': resolve(__dirname, '../ui/dist/style.css')
}
},
optimizeDeps: {
include: ['@prompt-optimizer/core']
// 包含工作区依赖
include: ['@prompt-optimizer/ui', 'element-plus']
},
define: {
'process.env': {
@@ -39,4 +47,4 @@ export default defineConfig(({ mode }) => {
}
}
}
})
})
+1950 -434
View File
File diff suppressed because it is too large. Load diff